github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/plans/objchange/lcs_test.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package objchange 5 6 import ( 7 "fmt" 8 "testing" 9 10 "github.com/terramate-io/tf/lang/marks" 11 "github.com/zclconf/go-cty/cty" 12 ) 13 14 func TestLongestCommonSubsequence(t *testing.T) { 15 tests := []struct { 16 xs []cty.Value 17 ys []cty.Value 18 want []cty.Value 19 }{ 20 { 21 []cty.Value{}, 22 []cty.Value{}, 23 []cty.Value{}, 24 }, 25 { 26 []cty.Value{cty.NumberIntVal(1), cty.NumberIntVal(2)}, 27 []cty.Value{cty.NumberIntVal(1), cty.NumberIntVal(2)}, 28 []cty.Value{cty.NumberIntVal(1), cty.NumberIntVal(2)}, 29 }, 30 { 31 []cty.Value{cty.NumberIntVal(1), cty.NumberIntVal(2)}, 32 []cty.Value{cty.NumberIntVal(3), cty.NumberIntVal(4)}, 33 []cty.Value{}, 34 }, 35 { 36 []cty.Value{cty.NumberIntVal(2)}, 37 []cty.Value{cty.NumberIntVal(1), cty.NumberIntVal(2)}, 38 []cty.Value{cty.NumberIntVal(2)}, 39 }, 40 { 41 []cty.Value{cty.NumberIntVal(1)}, 42 []cty.Value{cty.NumberIntVal(1), cty.NumberIntVal(2)}, 43 []cty.Value{cty.NumberIntVal(1)}, 44 }, 45 { 46 []cty.Value{cty.NumberIntVal(2), cty.NumberIntVal(1)}, 47 []cty.Value{cty.NumberIntVal(1), cty.NumberIntVal(2)}, 48 []cty.Value{cty.NumberIntVal(1)}, // arbitrarily selected 1; 2 would also be valid 49 }, 50 { 51 []cty.Value{cty.NumberIntVal(1), cty.NumberIntVal(2), cty.NumberIntVal(3), cty.NumberIntVal(4)}, 52 []cty.Value{cty.NumberIntVal(2), cty.NumberIntVal(4), cty.NumberIntVal(5)}, 53 []cty.Value{cty.NumberIntVal(2), cty.NumberIntVal(4)}, 54 }, 55 { 56 []cty.Value{cty.NumberIntVal(1), cty.NumberIntVal(2), cty.NumberIntVal(3), cty.NumberIntVal(4)}, 57 []cty.Value{cty.NumberIntVal(4), cty.NumberIntVal(2), cty.NumberIntVal(5)}, 58 []cty.Value{cty.NumberIntVal(4)}, // 2 would also be valid 59 }, 60 { 61 []cty.Value{cty.NumberIntVal(1), cty.NumberIntVal(2), cty.NumberIntVal(3), cty.NumberIntVal(5)}, 62 []cty.Value{cty.NumberIntVal(2), cty.NumberIntVal(4), cty.NumberIntVal(5)}, 63 []cty.Value{cty.NumberIntVal(2), cty.NumberIntVal(5)}, 64 }, 65 66 // unknowns never compare as equal 67 { 68 []cty.Value{cty.NumberIntVal(1), cty.UnknownVal(cty.Number), cty.NumberIntVal(3)}, 69 []cty.Value{cty.NumberIntVal(1), cty.UnknownVal(cty.Number), cty.NumberIntVal(3)}, 70 []cty.Value{cty.NumberIntVal(1), cty.NumberIntVal(3)}, 71 }, 72 { 73 []cty.Value{cty.UnknownVal(cty.Number)}, 74 []cty.Value{cty.UnknownVal(cty.Number)}, 75 []cty.Value{}, 76 }, 77 78 // marked values 79 { 80 []cty.Value{cty.NumberIntVal(1).Mark("foo"), cty.NumberIntVal(2).Mark("foo"), cty.NumberIntVal(3)}, 81 []cty.Value{cty.NumberIntVal(1).Mark("foo"), cty.NumberIntVal(2).Mark("foo")}, 82 []cty.Value{cty.NumberIntVal(1).Mark("foo"), cty.NumberIntVal(2).Mark("foo")}, 83 }, 84 { 85 []cty.Value{cty.NumberIntVal(1), cty.NumberIntVal(2).Mark("foo"), cty.NumberIntVal(3)}, 86 []cty.Value{cty.NumberIntVal(2), cty.NumberIntVal(3)}, 87 []cty.Value{cty.NumberIntVal(3)}, 88 }, 89 { 90 []cty.Value{cty.NumberIntVal(1), cty.NumberIntVal(2).Mark("foo")}, 91 []cty.Value{cty.NumberIntVal(2)}, 92 []cty.Value{}, 93 }, 94 { 95 []cty.Value{ 96 cty.MapVal(map[string]cty.Value{"a": cty.StringVal("x").Mark(marks.Sensitive)}), 97 cty.MapVal(map[string]cty.Value{"b": cty.StringVal("y")}), 98 }, 99 []cty.Value{ 100 cty.MapVal(map[string]cty.Value{"a": cty.StringVal("x").Mark(marks.Sensitive)}), 101 cty.MapVal(map[string]cty.Value{"b": cty.StringVal("y")}), 102 cty.MapVal(map[string]cty.Value{"c": cty.StringVal("z")}), 103 }, 104 []cty.Value{ 105 cty.MapVal(map[string]cty.Value{"a": cty.StringVal("x").Mark(marks.Sensitive)}), 106 cty.MapVal(map[string]cty.Value{"b": cty.StringVal("y")}), 107 }, 108 }, 109 } 110 111 for _, test := range tests { 112 t.Run(fmt.Sprintf("%#v,%#v", test.xs, test.ys), func(t *testing.T) { 113 got := LongestCommonSubsequence(test.xs, test.ys, ValueEqual) 114 115 wrong := func() { 116 t.Fatalf( 117 "wrong result\nX: %#v\nY: %#v\ngot: %#v\nwant: %#v", 118 test.xs, test.ys, got, test.want, 119 ) 120 } 121 122 if len(got) != len(test.want) { 123 wrong() 124 } 125 126 for i := range got { 127 if got[i] == cty.NilVal { 128 wrong() 129 } 130 if !got[i].RawEquals(test.want[i]) { 131 wrong() 132 } 133 } 134 }) 135 } 136 }