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  }