Skip to content

Commit a716a21

Browse files
alisdairbbasata
authored andcommitted
set: Add SameRules method to set.Rules
Previously, we checked if two sets had the same rules using a simple equality check. This panics if the sets contain object types, as they cannot be compared using `==`. Adding a SameRules method to the Rules interface allows us to delegate to the Type.Equals method where necessary, fixing this problem.
1 parent 6834be6 commit a716a21

File tree

7 files changed

+86
-2
lines changed

7 files changed

+86
-2
lines changed

cty/gocty/in_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,10 @@ func (r testSetRules) Equivalent(v1 interface{}, v2 interface{}) bool {
480480
return v1 == v2
481481
}
482482

483+
func (r testSetRules) SameRules(other set.Rules) bool {
484+
return r == other
485+
}
486+
483487
type capsuleType1Native struct {
484488
name string
485489
}

cty/path_set.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,3 +196,9 @@ func (r pathSetRules) Equivalent(a, b interface{}) bool {
196196

197197
return true
198198
}
199+
200+
// SameRules is true if both Rules instances are pathSetRules structs.
201+
func (r pathSetRules) SameRules(other set.Rules) bool {
202+
_, ok := other.(pathSetRules)
203+
return ok
204+
}

cty/set/rules.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ type Rules interface {
2222
// though it is *not* required that two values with the same hash value
2323
// be equivalent.
2424
Equivalent(interface{}, interface{}) bool
25+
26+
// SameRules returns true if the instance is equivalent to another Rules
27+
// instance.
28+
SameRules(Rules) bool
2529
}
2630

2731
// OrderedRules is an extension of Rules that can apply a partial order to

cty/set/rules_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,7 @@ func (r testRules) Hash(val interface{}) int {
1313
func (r testRules) Equivalent(val1 interface{}, val2 interface{}) bool {
1414
return val1 == val2
1515
}
16+
17+
func (r testRules) SameRules(other Rules) bool {
18+
return r == other // true if "other" is also a testRules
19+
}

cty/set/set.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func NewSetFromSlice(rules Rules, vals []interface{}) Set {
4141
}
4242

4343
func sameRules(s1 Set, s2 Set) bool {
44-
return s1.rules == s2.rules
44+
return s1.rules.SameRules(s2.rules)
4545
}
4646

4747
func mustHaveSameRules(s1 Set, s2 Set) {
@@ -53,7 +53,7 @@ func mustHaveSameRules(s1 Set, s2 Set) {
5353
// HasRules returns true if and only if the receiving set has the given rules
5454
// instance as its rules.
5555
func (s Set) HasRules(rules Rules) bool {
56-
return s.rules == rules
56+
return s.rules.SameRules(rules)
5757
}
5858

5959
// Rules returns the receiving set's rules instance.

cty/set_internals.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,17 @@ func (r setRules) Equivalent(v1 interface{}, v2 interface{}) bool {
6565
return eqv.v == true
6666
}
6767

68+
// SameRules is only true if the other Rules instance is also a setRules struct,
69+
// and the types are considered equal.
70+
func (r setRules) SameRules(other set.Rules) bool {
71+
rules, ok := other.(setRules)
72+
if !ok {
73+
return false
74+
}
75+
76+
return r.Type.Equals(rules.Type)
77+
}
78+
6879
// Less is an implementation of set.OrderedRules so that we can iterate over
6980
// set elements in a consistent order, where such an order is possible.
7081
func (r setRules) Less(v1, v2 interface{}) bool {

cty/set_internals_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"fmt"
55
"math/big"
66
"testing"
7+
8+
"github.com/zclconf/go-cty/cty/set"
79
)
810

911
func TestSetHashBytes(t *testing.T) {
@@ -313,3 +315,56 @@ func TestSetOrder(t *testing.T) {
313315
})
314316
}
315317
}
318+
319+
func TestSetRulesSameRules(t *testing.T) {
320+
tests := []struct {
321+
a set.Rules
322+
b set.Rules
323+
want bool
324+
}{
325+
{
326+
setRules{EmptyObject},
327+
setRules{DynamicPseudoType},
328+
false,
329+
},
330+
{
331+
setRules{EmptyObject},
332+
setRules{EmptyObject},
333+
true,
334+
},
335+
{
336+
setRules{String},
337+
setRules{String},
338+
true,
339+
},
340+
{
341+
setRules{Object(map[string]Type{"a": String})},
342+
setRules{Object(map[string]Type{"a": String})},
343+
true,
344+
},
345+
{
346+
setRules{Object(map[string]Type{"a": String})},
347+
setRules{Object(map[string]Type{"a": Bool})},
348+
false,
349+
},
350+
{
351+
pathSetRules{},
352+
pathSetRules{},
353+
true,
354+
},
355+
{
356+
setRules{DynamicPseudoType},
357+
pathSetRules{},
358+
false,
359+
},
360+
}
361+
362+
for _, test := range tests {
363+
t.Run(fmt.Sprintf("%#v.SameRules(%#v)", test.a, test.b), func(t *testing.T) {
364+
got := test.a.SameRules(test.b)
365+
if got != test.want {
366+
t.Errorf("wrong result\na: %#v\nb: %#v\ngot %#v, want %#v", test.a, test.b, got, test.want)
367+
}
368+
})
369+
}
370+
}

0 commit comments

Comments
 (0)