mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-01 07:47:56 +00:00
add unit test
This commit is contained in:
parent
a3584f2c34
commit
9a8ef00888
@ -46,15 +46,37 @@ type StrategicMergePatchTestCase struct {
|
||||
StrategicMergePatchTestCaseData
|
||||
}
|
||||
|
||||
type StrategicMergePatchRawTestCase struct {
|
||||
Description string
|
||||
StrategicMergePatchRawTestCaseData
|
||||
}
|
||||
|
||||
type StrategicMergePatchTestCaseData struct {
|
||||
// Original is the original object (last-applied config in annotation)
|
||||
Original map[string]interface{}
|
||||
TwoWay map[string]interface{}
|
||||
// Modified is the modified object (new config we want)
|
||||
Modified map[string]interface{}
|
||||
// Current is the current object (live config in the server)
|
||||
Current map[string]interface{}
|
||||
// TwoWay is the expected two-way merge patch diff between original and modified
|
||||
TwoWay map[string]interface{}
|
||||
// ThreeWay is the expected three-way merge patch
|
||||
ThreeWay map[string]interface{}
|
||||
// Result is the expected object after applying the three-way patch on current object.
|
||||
Result map[string]interface{}
|
||||
}
|
||||
|
||||
// The meaning of each field is the same as StrategicMergePatchTestCaseData's.
|
||||
// The difference is that all the fields in StrategicMergePatchRawTestCaseData are json-encoded data.
|
||||
type StrategicMergePatchRawTestCaseData struct {
|
||||
Original []byte
|
||||
Modified []byte
|
||||
Current []byte
|
||||
TwoWay []byte
|
||||
ThreeWay []byte
|
||||
Result []byte
|
||||
}
|
||||
|
||||
type MergeItem struct {
|
||||
Name string
|
||||
Value string
|
||||
@ -1797,6 +1819,125 @@ testCases:
|
||||
other: b
|
||||
`)
|
||||
|
||||
var strategicMergePatchRawTestCases = []StrategicMergePatchRawTestCase{
|
||||
{
|
||||
Description: "delete items in lists of scalars",
|
||||
StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
|
||||
Original: []byte(`
|
||||
mergingIntList:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
`),
|
||||
TwoWay: []byte(`
|
||||
$deleteFromPrimitiveList/mergingIntList:
|
||||
- 3
|
||||
`),
|
||||
Modified: []byte(`
|
||||
mergingIntList:
|
||||
- 1
|
||||
- 2
|
||||
`),
|
||||
Current: []byte(`
|
||||
mergingIntList:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
`),
|
||||
ThreeWay: []byte(`
|
||||
$deleteFromPrimitiveList/mergingIntList:
|
||||
- 3
|
||||
`),
|
||||
Result: []byte(`
|
||||
mergingIntList:
|
||||
- 1
|
||||
- 2
|
||||
- 4
|
||||
`),
|
||||
},
|
||||
},
|
||||
{
|
||||
Description: "delete all duplicate items in lists of scalars",
|
||||
StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
|
||||
Original: []byte(`
|
||||
mergingIntList:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 3
|
||||
`),
|
||||
TwoWay: []byte(`
|
||||
$deleteFromPrimitiveList/mergingIntList:
|
||||
- 3
|
||||
`),
|
||||
Modified: []byte(`
|
||||
mergingIntList:
|
||||
- 1
|
||||
- 2
|
||||
`),
|
||||
Current: []byte(`
|
||||
mergingIntList:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 3
|
||||
- 4
|
||||
`),
|
||||
ThreeWay: []byte(`
|
||||
$deleteFromPrimitiveList/mergingIntList:
|
||||
- 3
|
||||
`),
|
||||
Result: []byte(`
|
||||
mergingIntList:
|
||||
- 1
|
||||
- 2
|
||||
- 4
|
||||
`),
|
||||
},
|
||||
},
|
||||
{
|
||||
Description: "add and delete items in lists of scalars",
|
||||
StrategicMergePatchRawTestCaseData: StrategicMergePatchRawTestCaseData{
|
||||
Original: []byte(`
|
||||
mergingIntList:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
`),
|
||||
TwoWay: []byte(`
|
||||
$deleteFromPrimitiveList/mergingIntList:
|
||||
- 3
|
||||
mergingIntList:
|
||||
- 4
|
||||
`),
|
||||
Modified: []byte(`
|
||||
mergingIntList:
|
||||
- 1
|
||||
- 2
|
||||
- 4
|
||||
`),
|
||||
Current: []byte(`
|
||||
mergingIntList:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
`),
|
||||
ThreeWay: []byte(`
|
||||
$deleteFromPrimitiveList/mergingIntList:
|
||||
- 3
|
||||
`),
|
||||
Result: []byte(`
|
||||
mergingIntList:
|
||||
- 1
|
||||
- 2
|
||||
- 4
|
||||
`),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestStrategicMergePatch(t *testing.T) {
|
||||
testStrategicMergePatchWithCustomArguments(t, "bad original",
|
||||
"<THIS IS NOT JSON>", "{}", mergeItem, errBadJSONDoc)
|
||||
@ -1818,6 +1959,11 @@ func TestStrategicMergePatch(t *testing.T) {
|
||||
testTwoWayPatch(t, c)
|
||||
testThreeWayPatch(t, c)
|
||||
}
|
||||
|
||||
for _, c := range strategicMergePatchRawTestCases {
|
||||
testTwoWayPatchForRawTestCase(t, c)
|
||||
testThreeWayPatchForRawTestCase(t, c)
|
||||
}
|
||||
}
|
||||
|
||||
func testStrategicMergePatchWithCustomArguments(t *testing.T, description, original, patch string, dataStruct interface{}, err error) {
|
||||
@ -1849,12 +1995,32 @@ func testTwoWayPatch(t *testing.T, c StrategicMergePatchTestCase) {
|
||||
testPatchApplication(t, original, actual, modified, c.Description)
|
||||
}
|
||||
|
||||
func testTwoWayPatchForRawTestCase(t *testing.T, c StrategicMergePatchRawTestCase) {
|
||||
original, expected, modified := twoWayRawTestCaseToJSONOrFail(t, c)
|
||||
|
||||
actual, err := CreateTwoWayMergePatch(original, modified, mergeItem)
|
||||
if err != nil {
|
||||
t.Errorf("error: %s\nin test case: %s\ncannot create two way patch:\noriginal:%s\ntwoWay:%s\nmodified:%s\ncurrent:%s\nthreeWay:%s\nresult:%s\n",
|
||||
err, c.Description, c.Original, c.TwoWay, c.Modified, c.Current, c.ThreeWay, c.Result)
|
||||
return
|
||||
}
|
||||
|
||||
testPatchCreation(t, expected, actual, c.Description)
|
||||
testPatchApplication(t, original, actual, modified, c.Description)
|
||||
}
|
||||
|
||||
func twoWayTestCaseToJSONOrFail(t *testing.T, c StrategicMergePatchTestCase) ([]byte, []byte, []byte) {
|
||||
return testObjectToJSONOrFail(t, c.Original, c.Description),
|
||||
testObjectToJSONOrFail(t, c.TwoWay, c.Description),
|
||||
testObjectToJSONOrFail(t, c.Modified, c.Description)
|
||||
}
|
||||
|
||||
func twoWayRawTestCaseToJSONOrFail(t *testing.T, c StrategicMergePatchRawTestCase) ([]byte, []byte, []byte) {
|
||||
return yamlToJSONOrError(t, c.Original),
|
||||
yamlToJSONOrError(t, c.TwoWay),
|
||||
yamlToJSONOrError(t, c.Modified)
|
||||
}
|
||||
|
||||
func testThreeWayPatch(t *testing.T, c StrategicMergePatchTestCase) {
|
||||
original, modified, current, expected, result := threeWayTestCaseToJSONOrFail(t, c)
|
||||
actual, err := CreateThreeWayMergePatch(original, modified, current, mergeItem, false)
|
||||
@ -1896,6 +2062,47 @@ func testThreeWayPatch(t *testing.T, c StrategicMergePatchTestCase) {
|
||||
testPatchApplication(t, current, actual, result, c.Description)
|
||||
}
|
||||
|
||||
func testThreeWayPatchForRawTestCase(t *testing.T, c StrategicMergePatchRawTestCase) {
|
||||
original, modified, current, expected, result := threeWayRawTestCaseToJSONOrFail(t, c)
|
||||
actual, err := CreateThreeWayMergePatch(original, modified, current, mergeItem, false)
|
||||
if err != nil {
|
||||
if !IsConflict(err) {
|
||||
t.Errorf("error: %s\nin test case: %s\ncannot create three way patch:\noriginal:%s\ntwoWay:%s\nmodified:%s\ncurrent:%s\nthreeWay:%s\nresult:%s\n",
|
||||
err, c.Description, c.Original, c.TwoWay, c.Modified, c.Current, c.ThreeWay, c.Result)
|
||||
return
|
||||
}
|
||||
|
||||
if !strings.Contains(c.Description, "conflict") {
|
||||
t.Errorf("unexpected conflict: %s\nin test case: %s\ncannot create three way patch:\noriginal:%s\ntwoWay:%s\nmodified:%s\ncurrent:%s\nthreeWay:%s\nresult:%s\n",
|
||||
err, c.Description, c.Original, c.TwoWay, c.Modified, c.Current, c.ThreeWay, c.Result)
|
||||
return
|
||||
}
|
||||
|
||||
if len(c.Result) > 0 {
|
||||
actual, err := CreateThreeWayMergePatch(original, modified, current, mergeItem, true)
|
||||
if err != nil {
|
||||
t.Errorf("error: %s\nin test case: %s\ncannot force three way patch application:\noriginal:%s\ntwoWay:%s\nmodified:%s\ncurrent:%s\nthreeWay:%s\nresult:%s\n",
|
||||
err, c.Description, c.Original, c.TwoWay, c.Modified, c.Current, c.ThreeWay, c.Result)
|
||||
return
|
||||
}
|
||||
|
||||
testPatchCreation(t, expected, actual, c.Description)
|
||||
testPatchApplication(t, current, actual, result, c.Description)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if strings.Contains(c.Description, "conflict") || len(c.Result) < 1 {
|
||||
t.Errorf("error: %s\nin test case: %s\nexpected conflict did not occur:\noriginal:%s\ntwoWay:%s\nmodified:%s\ncurrent:%s\nthreeWay:%s\nresult:%s\n",
|
||||
err, c.Description, c.Original, c.TwoWay, c.Modified, c.Current, c.ThreeWay, c.Result)
|
||||
return
|
||||
}
|
||||
|
||||
testPatchCreation(t, expected, actual, c.Description)
|
||||
testPatchApplication(t, current, actual, result, c.Description)
|
||||
}
|
||||
|
||||
func threeWayTestCaseToJSONOrFail(t *testing.T, c StrategicMergePatchTestCase) ([]byte, []byte, []byte, []byte, []byte) {
|
||||
return testObjectToJSONOrFail(t, c.Original, c.Description),
|
||||
testObjectToJSONOrFail(t, c.Modified, c.Description),
|
||||
@ -1904,6 +2111,14 @@ func threeWayTestCaseToJSONOrFail(t *testing.T, c StrategicMergePatchTestCase) (
|
||||
testObjectToJSONOrFail(t, c.Result, c.Description)
|
||||
}
|
||||
|
||||
func threeWayRawTestCaseToJSONOrFail(t *testing.T, c StrategicMergePatchRawTestCase) ([]byte, []byte, []byte, []byte, []byte) {
|
||||
return yamlToJSONOrError(t, c.Original),
|
||||
yamlToJSONOrError(t, c.Modified),
|
||||
yamlToJSONOrError(t, c.Current),
|
||||
yamlToJSONOrError(t, c.ThreeWay),
|
||||
yamlToJSONOrError(t, c.Result)
|
||||
}
|
||||
|
||||
func testPatchCreation(t *testing.T, expected, actual []byte, description string) {
|
||||
sorted, err := sortMergeListsByName(actual, mergeItem)
|
||||
if err != nil {
|
||||
@ -1989,6 +2204,24 @@ func jsonToYAML(j []byte) ([]byte, error) {
|
||||
return y, nil
|
||||
}
|
||||
|
||||
func yamlToJSON(y []byte) ([]byte, error) {
|
||||
j, err := yaml.YAMLToJSON(y)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("yaml to json failed: %v\n%v\n", err, y)
|
||||
}
|
||||
|
||||
return j, nil
|
||||
}
|
||||
|
||||
func yamlToJSONOrError(t *testing.T, y []byte) []byte {
|
||||
j, err := yamlToJSON(y)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
|
||||
return j
|
||||
}
|
||||
|
||||
func TestHasConflicts(t *testing.T) {
|
||||
testCases := []struct {
|
||||
A interface{}
|
||||
|
Loading…
Reference in New Issue
Block a user