Skip to content

Commit 3f0a19a

Browse files
committed
Add test to show that typename and version don't always match
The test is flaky since the behavior depends on the order of which the versions are processed, and the current code that prevents that from happening depends on an invalid name for the version.
1 parent 26781d0 commit 3f0a19a

File tree

1 file changed

+155
-0
lines changed

1 file changed

+155
-0
lines changed

merge/multiple_appliers_test.go

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1945,3 +1945,158 @@ func TestMultipleAppliersReliantFieldsConversions(t *testing.T) {
19451945
})
19461946
}
19471947
}
1948+
1949+
var versionDoesntMatchTypeName = func() Parser {
1950+
parser, err := typed.NewParser(`types:
1951+
- name: TypeV1
1952+
map:
1953+
fields:
1954+
- name: field_foo_rely_on_bar
1955+
type:
1956+
scalar: string
1957+
- name: common_field
1958+
type:
1959+
scalar: string
1960+
- name: TypeV2
1961+
map:
1962+
fields:
1963+
- name: required_field_bar
1964+
type:
1965+
scalar: string
1966+
- name: common_field
1967+
type:
1968+
scalar: string
1969+
`)
1970+
if err != nil {
1971+
panic(err)
1972+
}
1973+
return parser
1974+
}()
1975+
1976+
type versionDoesntMatchTypenameConverter struct{}
1977+
1978+
var _ merge.Converter = versionDoesntMatchTypenameConverter{}
1979+
1980+
func (r versionDoesntMatchTypenameConverter) Convert(v *typed.TypedValue, version fieldpath.APIVersion) (*typed.TypedValue, error) {
1981+
inVersion := fieldpath.APIVersion("")
1982+
switch fieldpath.APIVersion(*v.TypeRef().NamedType) {
1983+
case "TypeV1":
1984+
inVersion = "v1"
1985+
case "TypeV2":
1986+
inVersion = "v2"
1987+
default:
1988+
return nil, fmt.Errorf(`Invalid typename: %q, should be one of ["TypeV1", "TypeV2"]`, version)
1989+
}
1990+
if inVersion == version {
1991+
return v, nil
1992+
}
1993+
if inVersion == version {
1994+
return v, nil
1995+
}
1996+
y, err := yaml.Marshal(v.AsValue().Unstructured())
1997+
if err != nil {
1998+
return nil, err
1999+
}
2000+
inStr := string(y)
2001+
var outStr string
2002+
var outType string
2003+
switch version {
2004+
case "v1":
2005+
if !strings.Contains(inStr, "required_field_bar") {
2006+
return v, fmt.Errorf("missing requried field bar")
2007+
}
2008+
outType = "TypeV1"
2009+
outStr = strings.Replace(inStr, "required_field_bar", "field_foo_rely_on_bar", -1)
2010+
case "v2":
2011+
outType = "TypeV2"
2012+
outStr = strings.Replace(inStr, "field_foo_rely_on_bar", "required_field_bar", -1)
2013+
default:
2014+
return nil, missingVersionError
2015+
}
2016+
return versionDoesntMatchTypeName.Type(string(outType)).FromYAML(typed.YAMLObject(outStr))
2017+
}
2018+
2019+
func (r versionDoesntMatchTypenameConverter) IsMissingVersionError(err error) bool {
2020+
return err == missingVersionError
2021+
}
2022+
2023+
// This is the same test as TestMultipleAppliersReliantFieldsConversions
2024+
// but written without the internal test framework that assumes that
2025+
// typenames and versions match. The goal of this test is to make sure
2026+
// that no such assumptions are used in the tested code.
2027+
func TestVersionDoesntMatchTypename(t *testing.T) {
2028+
converter := versionDoesntMatchTypenameConverter{}
2029+
updater := &merge.Updater{Converter: converter}
2030+
2031+
// Apply in one version, apply in another, apply in a third.
2032+
live, err := versionDoesntMatchTypeName.Type("TypeV2").FromYAML(`{}`)
2033+
if err != nil {
2034+
t.Fatalf("Failed to parse empty object: %v", err)
2035+
}
2036+
managers := fieldpath.ManagedFields{}
2037+
config, err := versionDoesntMatchTypeName.Type("TypeV2").FromYAML(`{"required_field_bar": "a"}`)
2038+
if err != nil {
2039+
t.Fatalf("Failed to parse object: %v", err)
2040+
}
2041+
live, managers, err = updater.Apply(live, config, "v2", managers, "v2_applier", false)
2042+
if err != nil {
2043+
t.Fatalf("Failed to apply: %v", err)
2044+
}
2045+
2046+
live, err = converter.Convert(live, "v1")
2047+
if err != nil {
2048+
t.Fatalf("Failed to convert object to v1: %v", err)
2049+
}
2050+
config, err = versionDoesntMatchTypeName.Type("TypeV1").FromYAML(`{"common_field": "b"}`)
2051+
if err != nil {
2052+
t.Fatalf("Failed to parse object: %v", err)
2053+
}
2054+
2055+
live, managers, err = updater.Apply(live, config, "v1", managers, "v1_applier", false)
2056+
if err != nil {
2057+
t.Fatalf("Failed to apply: %v", err)
2058+
}
2059+
2060+
live, err = converter.Convert(live, "v2")
2061+
if err != nil {
2062+
t.Fatalf("Failed to convert object to v1: %v", err)
2063+
}
2064+
config, err = versionDoesntMatchTypeName.Type("TypeV2").FromYAML(`{"required_field_bar": "b"}`)
2065+
if err != nil {
2066+
t.Fatalf("Failed to parse object: %v", err)
2067+
}
2068+
live, managers, err = updater.Apply(live, config, "v2", managers, "v2_applier", false)
2069+
if err != nil {
2070+
t.Fatalf("Failed to apply: %v", err)
2071+
}
2072+
2073+
expectedObject, err := versionDoesntMatchTypeName.Type("TypeV2").FromYAML(`{"required_field_bar": "b", "common_field": "b"}`)
2074+
if err != nil {
2075+
t.Fatalf("Failed to parse object: %v", err)
2076+
}
2077+
if comparison, err := live.Compare(expectedObject); err != nil {
2078+
t.Fatalf("Failed to compare live with expected: %v", err)
2079+
} else if !comparison.IsSame() {
2080+
t.Fatalf("Live is different from expected:\n%v", comparison)
2081+
}
2082+
2083+
expectedManagers := fieldpath.ManagedFields{
2084+
"v2_applier": fieldpath.NewVersionedSet(
2085+
_NS(
2086+
_P("required_field_bar"),
2087+
),
2088+
"v2",
2089+
true,
2090+
),
2091+
"v1_applier": fieldpath.NewVersionedSet(
2092+
_NS(
2093+
_P("common_field"),
2094+
),
2095+
"v1",
2096+
true,
2097+
),
2098+
}
2099+
if !expectedManagers.Equals(managers) {
2100+
t.Fatalf("ManagedFields not as expected:\n%v", managers)
2101+
}
2102+
}

0 commit comments

Comments
 (0)