diff --git a/pkg/schema/walk/fn.go b/pkg/schema/walk/fn.go index c3eaf35c569c18ba8ead7c7ff48c08d03f2a9d90..9b1d4f22316cf37cae1af824d98f611b7dc0bcf7 100644 --- a/pkg/schema/walk/fn.go +++ b/pkg/schema/walk/fn.go @@ -1,10 +1,15 @@ package walk +import "reflect" + func GenericMerge(c *WalkContext) (err error) { return } func KeepSrc(c *WalkContext) (err error) { + if reflect.DeepEqual(c.Src, c.Dst) { + return + } c.Dst = c.Src c.Changed = true return diff --git a/pkg/schema/walk/walk_test.go b/pkg/schema/walk/walk_test.go index e20adb462735e83c92c8b04f5c159e336e49f2b0..3fd01bd577c3fe16abb1cae7b2e9785e0edc659c 100644 --- a/pkg/schema/walk/walk_test.go +++ b/pkg/schema/walk/walk_test.go @@ -46,6 +46,54 @@ func TestWalker_DataWalk(t *testing.T) { wantErr bool }{ {"generic", + &WalkConfig{ + Fields: map[string]FieldConfig{}, + }, + map[string]interface{}{ + "a": "src_a", + "b": "src_b", + "obj1": map[string]interface{}{ + "a": "src_obj1_a", + "b": "src_obj1_b", + "obj2": map[string]interface{}{ + "a": "dst_obj1_obj2_a", + }, + "obj3": map[string]interface{}{ + "e": "dst_obj1_obj3_e", + }, + }, + "inline_str_1": "src_inline_1", + "inline_str_2": "src_inline_2", + "slice": []interface{}{"src_s1", "src_s2"}, + }, + map[string]interface{}{ + "a": "dst_a", + "field_not_extists": "remove", + "obj1": map[string]interface{}{ + "a": "dst_obj1_a", + "obj2": map[string]interface{}{ + "a": "dst_obj1_obj2_a", + }, + }, + "inline_str_1": "dst_inline_1", + "inline_str_2": "dst_inline_2", + "slice": []interface{}{"dst_s1", "dst_s2", "dst_s3"}, + }, + map[string]interface{}{ + "a": "dst_a", + "obj1": map[string]interface{}{ + "a": "dst_obj1_a", + "obj2": map[string]interface{}{ + "a": "dst_obj1_obj2_a", + }, + }, + "inline_str_1": "dst_inline_1", + "inline_str_2": "dst_inline_2", + "slice": []interface{}{"dst_s1", "dst_s2", "dst_s3"}, + }, + false, false, + }, + {"keep src changed", &WalkConfig{ Fields: map[string]FieldConfig{ "obj1.a": {Fn: KeepSrc}, @@ -96,6 +144,68 @@ func TestWalker_DataWalk(t *testing.T) { "inline_str_2": "src_inline_2", "slice": []interface{}{"dst_s1", "src_s2", "dst_s3"}, }, + true, false, + }, + {"keep src not changed", + &WalkConfig{ + Fields: map[string]FieldConfig{ + "obj1.a": {Fn: KeepSrc}, + "slice.1": {Fn: KeepSrc}, + "inline_str_1": {Fn: KeepSrc}, + "inline_str_2": {Fn: KeepSrc}, + }, + }, + map[string]interface{}{ + "a": "src_a", + "b": "src_b", + "obj1": map[string]interface{}{ + "a": "src_obj1_a", + "b": "src_obj1_b", + "obj2": map[string]interface{}{ + "a": "dst_obj1_obj2_a", + }, + "obj3": map[string]interface{}{ + "e": "dst_obj1_obj3_e", + }, + }, + "inline_str_1": "src_inline_1", + "inline_str_2": "src_inline_2", + "slice": []interface{}{"src_s1", "src_s2"}, + }, + map[string]interface{}{ + "a": "src_a", + "b": "src_b", + "obj1": map[string]interface{}{ + "a": "src_obj1_a", + "b": "src_obj1_b", + "obj2": map[string]interface{}{ + "a": "dst_obj1_obj2_a", + }, + "obj3": map[string]interface{}{ + "e": "dst_obj1_obj3_e", + }, + }, + "inline_str_1": "src_inline_1", + "inline_str_2": "src_inline_2", + "slice": []interface{}{"src_s1", "src_s2"}, + }, + map[string]interface{}{ + "a": "src_a", + "b": "src_b", + "obj1": map[string]interface{}{ + "a": "src_obj1_a", + "b": "src_obj1_b", + "obj2": map[string]interface{}{ + "a": "dst_obj1_obj2_a", + }, + "obj3": map[string]interface{}{ + "e": "dst_obj1_obj3_e", + }, + }, + "inline_str_1": "src_inline_1", + "inline_str_2": "src_inline_2", + "slice": []interface{}{"src_s1", "src_s2"}, + }, false, false, }, } @@ -103,11 +213,12 @@ func TestWalker_DataWalk(t *testing.T) { t.Run(tt.name, func(t *testing.T) { m := NewWalker(s, tt.config) dst := tt.dst - res, _, err := m.DataWalk(context.Background(), dst, tt.src) - assert.Equal(t, tt.res, res) + res, chg, err := m.DataWalk(context.Background(), dst, tt.src) if tt.wantErr { require.Error(t, err) } else { + assert.Equal(t, tt.res, res) + assert.Equal(t, tt.wantChanged, chg) require.NoError(t, err) } })