Skip to content

Commit d87ac10

Browse files
committed
Avoid potential nil pointers in compare.go
Signed-off-by: Xie Zheng <[email protected]>
1 parent 20379c1 commit d87ac10

File tree

2 files changed

+79
-43
lines changed

2 files changed

+79
-43
lines changed

pkg/nsx/services/common/compare.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package common
22

33
import (
4+
"reflect"
5+
46
"github.com/vmware/vsphere-automation-sdk-go/runtime/data"
57
"github.com/vmware/vsphere-automation-sdk-go/runtime/data/serializers/cleanjson"
68

@@ -15,6 +17,10 @@ type Comparable interface {
1517
}
1618

1719
func CompareResource(existing Comparable, expected Comparable) (isChanged bool) {
20+
// avoid nil pointer
21+
if reflect.ValueOf(existing).IsNil() || reflect.ValueOf(expected).IsNil() {
22+
return true
23+
}
1824
var dataValueToJSONEncoder = cleanjson.NewDataValueToJsonEncoder()
1925
s1, _ := dataValueToJSONEncoder.Encode(existing.Value())
2026
s2, _ := dataValueToJSONEncoder.Encode(expected.Value())
@@ -25,6 +31,20 @@ func CompareResource(existing Comparable, expected Comparable) (isChanged bool)
2531
}
2632

2733
func CompareResources(existing []Comparable, expected []Comparable) (changed []Comparable, stale []Comparable) {
34+
// remove nil item in existing and expected
35+
for i := 0; i < len(existing); i++ {
36+
if reflect.ValueOf(existing[i]).IsNil() {
37+
existing = append(existing[:i], existing[i+1:]...)
38+
i--
39+
}
40+
}
41+
for i := 0; i < len(expected); i++ {
42+
if reflect.ValueOf(expected[i]).IsNil() {
43+
expected = append(expected[:i], expected[i+1:]...)
44+
i--
45+
}
46+
}
47+
2848
stale = make([]Comparable, 0)
2949
changed = make([]Comparable, 0)
3050

pkg/nsx/services/common/compare_test.go

Lines changed: 59 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -12,87 +12,103 @@ type mockComparable struct {
1212
value data.DataValue
1313
}
1414

15-
func (m mockComparable) Key() string {
15+
func (m *mockComparable) Key() string {
1616
return m.key
1717
}
1818

19-
func (m mockComparable) Value() data.DataValue {
19+
func (m *mockComparable) Value() data.DataValue {
2020
return m.value
2121
}
2222

23+
func mockComparableToComparable(mc []*mockComparable) []Comparable {
24+
res := make([]Comparable, 0, len(mc))
25+
for i := range mc {
26+
res = append(res, (*mockComparable)(mc[i]))
27+
}
28+
return res
29+
}
30+
31+
func comparableToMockComparable(c []Comparable) []*mockComparable {
32+
res := make([]*mockComparable, 0, len(c))
33+
for i := range c {
34+
res = append(res, c[i].(*mockComparable))
35+
}
36+
return res
37+
}
38+
2339
func TestCompareResources(t *testing.T) {
2440
tests := []struct {
2541
name string
26-
existing []Comparable
27-
expected []Comparable
28-
wantChanged []Comparable
29-
wantStale []Comparable
42+
existing []*mockComparable
43+
expected []*mockComparable
44+
wantChanged []*mockComparable
45+
wantStale []*mockComparable
3046
}{
3147
{
3248
name: "No changes",
33-
existing: []Comparable{
34-
mockComparable{key: "key1", value: data.NewStringValue("value1")},
35-
mockComparable{key: "key2", value: data.NewStringValue("value2")},
49+
existing: []*mockComparable{
50+
{key: "key1", value: data.NewStringValue("value1")},
51+
{key: "key2", value: data.NewStringValue("value2")},
3652
},
37-
expected: []Comparable{
38-
mockComparable{key: "key1", value: data.NewStringValue("value1")},
39-
mockComparable{key: "key2", value: data.NewStringValue("value2")},
53+
expected: []*mockComparable{
54+
{key: "key1", value: data.NewStringValue("value1")},
55+
{key: "key2", value: data.NewStringValue("value2")},
4056
},
41-
wantChanged: []Comparable{},
42-
wantStale: []Comparable{},
57+
wantChanged: []*mockComparable{},
58+
wantStale: []*mockComparable{},
4359
},
4460
{
4561
name: "Changed resources",
46-
existing: []Comparable{
47-
mockComparable{key: "key1", value: data.NewStringValue("value1")},
48-
mockComparable{key: "key2", value: data.NewStringValue("value2")},
62+
existing: []*mockComparable{
63+
{key: "key1", value: data.NewStringValue("value1")},
64+
{key: "key2", value: data.NewStringValue("value2")},
4965
},
50-
expected: []Comparable{
51-
mockComparable{key: "key1", value: data.NewStringValue("value1")},
52-
mockComparable{key: "key2", value: data.NewStringValue("value2_changed")},
66+
expected: []*mockComparable{
67+
{key: "key1", value: data.NewStringValue("value1")},
68+
{key: "key2", value: data.NewStringValue("value2_changed")},
5369
},
54-
wantChanged: []Comparable{
55-
mockComparable{key: "key2", value: data.NewStringValue("value2_changed")},
70+
wantChanged: []*mockComparable{
71+
{key: "key2", value: data.NewStringValue("value2_changed")},
5672
},
57-
wantStale: []Comparable{},
73+
wantStale: []*mockComparable{},
5874
},
5975
{
6076
name: "Stale resources",
61-
existing: []Comparable{
62-
mockComparable{key: "key1", value: data.NewStringValue("value1")},
63-
mockComparable{key: "key2", value: data.NewStringValue("value2")},
77+
existing: []*mockComparable{
78+
{key: "key1", value: data.NewStringValue("value1")},
79+
{key: "key2", value: data.NewStringValue("value2")},
6480
},
65-
expected: []Comparable{
66-
mockComparable{key: "key1", value: data.NewStringValue("value1")},
81+
expected: []*mockComparable{
82+
{key: "key1", value: data.NewStringValue("value1")},
6783
},
68-
wantChanged: []Comparable{},
69-
wantStale: []Comparable{
70-
mockComparable{key: "key2", value: data.NewStringValue("value2")},
84+
wantChanged: []*mockComparable{},
85+
wantStale: []*mockComparable{
86+
{key: "key2", value: data.NewStringValue("value2")},
7187
},
7288
},
7389
{
7490
name: "Changed and stale resources",
75-
existing: []Comparable{
76-
mockComparable{key: "key1", value: data.NewStringValue("value1")},
77-
mockComparable{key: "key2", value: data.NewStringValue("value2")},
91+
existing: []*mockComparable{
92+
{key: "key1", value: data.NewStringValue("value1")},
93+
{key: "key2", value: data.NewStringValue("value2")},
7894
},
79-
expected: []Comparable{
80-
mockComparable{key: "key1", value: data.NewStringValue("value1_changed")},
95+
expected: []*mockComparable{
96+
{key: "key1", value: data.NewStringValue("value1_changed")},
8197
},
82-
wantChanged: []Comparable{
83-
mockComparable{key: "key1", value: data.NewStringValue("value1_changed")},
98+
wantChanged: []*mockComparable{
99+
{key: "key1", value: data.NewStringValue("value1_changed")},
84100
},
85-
wantStale: []Comparable{
86-
mockComparable{key: "key2", value: data.NewStringValue("value2")},
101+
wantStale: []*mockComparable{
102+
{key: "key2", value: data.NewStringValue("value2")},
87103
},
88104
},
89105
}
90106

91107
for _, tt := range tests {
92108
t.Run(tt.name, func(t *testing.T) {
93-
gotChanged, gotStale := CompareResources(tt.existing, tt.expected)
94-
assert.Equal(t, tt.wantChanged, gotChanged)
95-
assert.Equal(t, tt.wantStale, gotStale)
109+
gotChanged, gotStale := CompareResources(mockComparableToComparable(tt.existing), mockComparableToComparable(tt.expected))
110+
assert.Equal(t, tt.wantChanged, comparableToMockComparable(gotChanged))
111+
assert.Equal(t, tt.wantStale, comparableToMockComparable(gotStale))
96112
})
97113
}
98114
}

0 commit comments

Comments
 (0)