diff --git a/equinix/provider.go b/equinix/provider.go index 46275dc5d..b300753c3 100644 --- a/equinix/provider.go +++ b/equinix/provider.go @@ -193,6 +193,10 @@ func configureProvider(ctx context.Context, d *schema.ResourceData, p *schema.Pr return &config, nil } +// stringsFound returns true if all strings in source are found in target +// Deprecated: stringsFound is shared between provider, tests, and resources +// and is being relocated for package refactoring. +// Use github.com/equinix/terraform-provider-equinix/internal/comparisons.Subsets func stringsFound(source []string, target []string) bool { for i := range source { if !slices.Contains(target, source[i]) { @@ -202,6 +206,10 @@ func stringsFound(source []string, target []string) bool { return true } +// isEmpty returns true if the value is nil or zero +// Deprecated: isEmpty is shared between provider, tests, and resources +// and is being relocated for package refactoring. +// Use github.com/equinix/terraform-provider-equinix/internal/comparisons.IsEmpty func isEmpty(v interface{}) bool { switch v := v.(type) { case int: @@ -219,6 +227,10 @@ func isEmpty(v interface{}) bool { } } +// slicesMatch returns true if all strings in s1 are found in s2 +// Deprecated: slicesMatch is shared between provider, tests, and resources +// and is being relocated for package refactoring. +// Use github.com/equinix/terraform-provider-equinix/internal/comparisons.SlicesMatch func slicesMatch(s1, s2 []string) bool { if len(s1) != len(s2) { return false diff --git a/internal/comparisons/comparisons.go b/internal/comparisons/comparisons.go new file mode 100644 index 000000000..351c173c2 --- /dev/null +++ b/internal/comparisons/comparisons.go @@ -0,0 +1,67 @@ +package comparisons + +import ( + "cmp" + "slices" + "strings" +) + +// isEmpty returns true if the given value is empty +func isEmpty(v interface{}) bool { + switch v := v.(type) { + case int: + return v == 0 + case *int: + return v == nil || *v == 0 + case string: + return v == "" + case *string: + return v == nil || *v == "" + case nil: + return true + default: + return false + } +} + +// Subsets returns true if the first slice is a subset of the second slice +func Subsets[T cmp.Ordered](s1, s2 []T) bool { + // Iterate over the first slice + for _, e := range s1 { + // If the element is not in the second slice, return false + if !slices.Contains(s2, e) { + return false + } + } + + return true +} + +// comparisons.SlicesMatch returns true if the two slices contain the same elements, regardless of order +func SlicesMatch[T cmp.Ordered](s1, s2 []T) bool { + if len(s1) != len(s2) { + return false + } + + // Create copies of the slices to avoid mutating the input slices + s1Copy := append([]T(nil), s1...) + s2Copy := append([]T(nil), s2...) + + // Sort the slices + slices.Sort(s1Copy) + slices.Sort(s2Copy) + + return slices.Equal(s1Copy, s2Copy) +} + +// caseInsensitiveLess is a comparison function for sorting strings case-insensitively +func caseInsensitiveLess(s1, s2 string) int { + switch { + case strings.ToLower(s1) == strings.ToLower(s2): + return 0 + case strings.ToLower(s1) < strings.ToLower(s2): + return -1 + default: + return 1 + } +} diff --git a/internal/comparisons/comparisons_test.go b/internal/comparisons/comparisons_test.go new file mode 100644 index 000000000..f0a552f54 --- /dev/null +++ b/internal/comparisons/comparisons_test.go @@ -0,0 +1,89 @@ +package comparisons_test + +import ( + "testing" + + "github.com/equinix/terraform-provider-equinix/internal/comparisons" + "github.com/stretchr/testify/assert" +) + +func TestSubsets(t *testing.T) { + // given + needles := []string{"key1", "key5"} + hay := []string{"key1", "key2", "Key3", "key4", "key5"} + // when + result := comparisons.Subsets(needles, hay) + // then + assert.True(t, result, "Given strings were found") +} + +func TestSubsets_negative(t *testing.T) { + // given + needles := []string{"key1", "key6"} + hay := []string{"key1", "key2", "Key3", "key4", "key5"} + // when + result := comparisons.Subsets(hay, needles) + // then + assert.False(t, result, "Given strings were found") +} + +func TestIsEmpty(t *testing.T) { + // given + input := []interface{}{ + "test", + "", + nil, + 123, + 0, + 43.43, + } + expected := []bool{ + false, + true, + true, + false, + true, + false, + true, + } + // when then + for i := range input { + assert.Equal(t, expected[i], comparisons.IsEmpty(input[i]), "Input %v produces expected result %v", input[i], expected[i]) + } +} + +func TestSlicesMatch(t *testing.T) { + // given + input := [][][]string{ + { + {"DC", "SV", "FR"}, + {"FR", "SV", "DC"}, + }, + { + {"SV"}, + {}, + }, + { + {"DC", "DC", "DC"}, + {"DC", "SV", "DC"}, + }, + { + {}, {}, + }, + } + expected := []bool{ + true, + false, + false, + true, + } + // when + results := make([]bool, len(expected)) + for i := range input { + results[i] = comparisons.SlicesMatch(input[i][0], input[i][1]) + } + // then + for i := range expected { + assert.Equal(t, expected[i], results[i]) + } +}