@@ -17,46 +17,189 @@ limitations under the License.
17
17
package provider
18
18
19
19
import (
20
+ "fmt"
20
21
"testing"
21
22
22
23
"github.com/stretchr/testify/assert"
23
24
)
24
25
26
+ var basicZoneTags = []struct {
27
+ name string
28
+ tagsFilter []string
29
+ zoneTags map [string ]string
30
+ matches bool
31
+ }{
32
+ {
33
+ "single tag no match" , []string {"tag1=value1" }, map [string ]string {"tag0" : "value0" }, false ,
34
+ },
35
+ {
36
+ "single tag matches" , []string {"tag1=value1" }, map [string ]string {"tag1" : "value1" }, true ,
37
+ },
38
+ {
39
+ "multiple tags no value match" , []string {"tag1=value1" }, map [string ]string {"tag0" : "value0" , "tag1" : "value2" }, false ,
40
+ },
41
+ {
42
+ "multiple tags matches" , []string {"tag1=value1" }, map [string ]string {"tag0" : "value0" , "tag1" : "value1" }, true ,
43
+ },
44
+ {
45
+ "tag name no match" , []string {"tag1" }, map [string ]string {"tag0" : "value0" }, false ,
46
+ },
47
+ {
48
+ "tag name matches" , []string {"tag1" }, map [string ]string {"tag1" : "value1" }, true ,
49
+ },
50
+ {
51
+ "multiple filter no match" , []string {"tag1=value1" , "tag2=value2" }, map [string ]string {"tag1" : "value1" }, false ,
52
+ },
53
+ {
54
+ "multiple filter matches" , []string {"tag1=value1" , "tag2=value2" }, map [string ]string {"tag2" : "value2" , "tag1" : "value1" , "tag3" : "value3" }, true ,
55
+ },
56
+ {
57
+ "empty tag filter matches all" , []string {"" }, map [string ]string {"tag0" : "value0" }, true ,
58
+ },
59
+ {
60
+ "tag filter without key and equal sign" , []string {"tag1=value1" , "=haha" }, map [string ]string {"tag1" : "value1" }, false ,
61
+ },
62
+ }
63
+
25
64
func TestZoneTagFilterMatch (t * testing.T ) {
26
- for _ , tc := range []struct {
27
- name string
28
- zoneTagFilter []string
29
- zoneTags map [string ]string
30
- matches bool
31
- }{
32
- {
33
- "single tag no match" , []string {"tag1=value1" }, map [string ]string {"tag0" : "value0" }, false ,
34
- },
35
- {
36
- "single tag matches" , []string {"tag1=value1" }, map [string ]string {"tag1" : "value1" }, true ,
37
- },
38
- {
39
- "multiple tags no value match" , []string {"tag1=value1" }, map [string ]string {"tag0" : "value0" , "tag1" : "value2" }, false ,
40
- },
41
- {
42
- "multiple tags matches" , []string {"tag1=value1" }, map [string ]string {"tag0" : "value0" , "tag1" : "value1" }, true ,
43
- },
44
- {
45
- "tag name no match" , []string {"tag1" }, map [string ]string {"tag0" : "value0" }, false ,
46
- },
47
- {
48
- "tag name matches" , []string {"tag1" }, map [string ]string {"tag1" : "value1" }, true ,
49
- },
50
- {
51
- "multiple filter no match" , []string {"tag1=value1" , "tag2=value2" }, map [string ]string {"tag1" : "value1" }, false ,
52
- },
53
- {
54
- "multiple filter matches" , []string {"tag1=value1" , "tag2=value2" }, map [string ]string {"tag2" : "value2" , "tag1" : "value1" , "tag3" : "value3" }, true ,
55
- },
56
- } {
57
- zoneTagFilter := NewZoneTagFilter (tc .zoneTagFilter )
65
+ for _ , tc := range basicZoneTags {
66
+ zoneTagFilter := NewZoneTagFilter (tc .tagsFilter )
58
67
t .Run (tc .name , func (t * testing.T ) {
59
68
assert .Equal (t , tc .matches , zoneTagFilter .Match (tc .zoneTags ))
60
69
})
61
70
}
62
71
}
72
+
73
+ func TestZoneTagFilterNotSupportedFormat (t * testing.T ) {
74
+ tests := []struct {
75
+ desc string
76
+ tags []string
77
+ want []string
78
+ }{
79
+ {desc : "multiple or separate values with commas" , tags : []string {"key1=val1,key2=val2" }, want : []string {"key1=val1,key2=val2" }},
80
+ {desc : "exclude tag" , tags : []string {"!key1" }, want : []string {"!key1" }},
81
+ {desc : "exclude tags" , tags : []string {"!key1=val" }, want : []string {"!key1=val" }},
82
+ }
83
+ for _ , tc := range tests {
84
+ t .Run (fmt .Sprintf ("%s" , tc .desc ), func (t * testing.T ) {
85
+ got := NewZoneTagFilter (tc .tags )
86
+ assert .Equal (t , tc .want , got .zoneTags )
87
+ })
88
+ }
89
+ }
90
+
91
+ func TestZoneTagFilterMatchGeneratedValues (t * testing.T ) {
92
+ tests := []struct {
93
+ filters int
94
+ zones int
95
+ source filterZoneTags
96
+ }{
97
+ {10 , 30 , generateTagFilterAndZoneTagsForMatch (10 , 30 )},
98
+ {5 , 40 , generateTagFilterAndZoneTagsForMatch (5 , 40 )},
99
+ {30 , 50 , generateTagFilterAndZoneTagsForMatch (30 , 50 )},
100
+ }
101
+ for _ , tc := range tests {
102
+ t .Run (fmt .Sprintf ("filters:%d zones:%d" , tc .filters , tc .zones ), func (t * testing.T ) {
103
+ assert .True (t , tc .source .ZoneTagFilter .Match (tc .source .inputTags ))
104
+ })
105
+ }
106
+ }
107
+
108
+ func TestZoneTagFilterNotMatchGeneratedValues (t * testing.T ) {
109
+ tests := []struct {
110
+ filters int
111
+ zones int
112
+ source filterZoneTags
113
+ }{
114
+ {10 , 30 , generateTagFilterAndZoneTagsForNotMatch (10 , 30 )},
115
+ {5 , 40 , generateTagFilterAndZoneTagsForNotMatch (5 , 40 )},
116
+ {30 , 50 , generateTagFilterAndZoneTagsForNotMatch (30 , 50 )},
117
+ }
118
+ for _ , tc := range tests {
119
+ t .Run (fmt .Sprintf ("filters:%d zones:%d" , tc .filters , tc .zones ), func (t * testing.T ) {
120
+ assert .False (t , tc .source .ZoneTagFilter .Match (tc .source .inputTags ))
121
+ })
122
+ }
123
+ }
124
+
125
+ // benchmarks
126
+ func BenchmarkZoneTagFilterMatchBasic (b * testing.B ) {
127
+ for _ , tc := range basicZoneTags {
128
+ zoneTagFilter := NewZoneTagFilter (tc .tagsFilter )
129
+ for range b .N {
130
+ zoneTagFilter .Match (tc .zoneTags )
131
+ }
132
+ }
133
+ }
134
+
135
+ var benchFixtures = []struct {
136
+ source filterZoneTags
137
+ }{
138
+ // match
139
+ {generateTagFilterAndZoneTagsForMatch (10 , 30 )},
140
+ {generateTagFilterAndZoneTagsForMatch (5 , 40 )},
141
+ {generateTagFilterAndZoneTagsForMatch (30 , 50 )},
142
+ // no match
143
+ {generateTagFilterAndZoneTagsForNotMatch (10 , 30 )},
144
+ {generateTagFilterAndZoneTagsForNotMatch (5 , 40 )},
145
+ {generateTagFilterAndZoneTagsForNotMatch (30 , 50 )},
146
+ }
147
+
148
+ func BenchmarkZoneTagFilterComplex (b * testing.B ) {
149
+ for _ , tc := range benchFixtures {
150
+ for range b .N {
151
+ tc .source .ZoneTagFilter .Match (tc .source .inputTags )
152
+ }
153
+ }
154
+ }
155
+
156
+ // test doubles
157
+ type filterZoneTags struct {
158
+ ZoneTagFilter
159
+ inputTags map [string ]string
160
+ }
161
+
162
+ // generateTagFilterAndZoneTagsForMatch generates filter tags and zone tags that do match.
163
+ func generateTagFilterAndZoneTagsForMatch (filter , zone int ) filterZoneTags {
164
+ return generateTagFilterAndZoneTags (filter , zone , true )
165
+ }
166
+
167
+ // generateTagFilterAndZoneTagsForNotMatch generates filter tags and zone tags that do not match.
168
+ func generateTagFilterAndZoneTagsForNotMatch (filter , zone int ) filterZoneTags {
169
+ return generateTagFilterAndZoneTags (filter , zone , false )
170
+ }
171
+
172
+ // generateTagFilterAndZoneTags generates filter tags and zone tags based on the match parameter.
173
+ func generateTagFilterAndZoneTags (filter , zone int , match bool ) filterZoneTags {
174
+ validate (filter , zone )
175
+ toFilterTags := make ([]string , 0 , filter )
176
+ inputTags := make (map [string ]string , zone )
177
+
178
+ for i := 0 ; i < filter ; i ++ {
179
+ tagIndex := i
180
+ if ! match {
181
+ tagIndex += 50
182
+ }
183
+ toFilterTags = append (toFilterTags , fmt .Sprintf ("tag-%d=value-%d" , tagIndex , i ))
184
+ }
185
+
186
+ for i := 0 ; i < zone ; i ++ {
187
+ tagIndex := i
188
+ if ! match {
189
+ // Make sure the input tags are different from the filter tags
190
+ tagIndex += 2
191
+ }
192
+ inputTags [fmt .Sprintf ("tag-%d" , i )] = fmt .Sprintf ("value-%d" , tagIndex )
193
+ }
194
+
195
+ return filterZoneTags {NewZoneTagFilter (toFilterTags ), inputTags }
196
+ }
197
+
198
+ func validate (filter int , zone int ) {
199
+ if zone > 50 {
200
+ panic ("zone number is too high" )
201
+ }
202
+ if filter > zone {
203
+ panic ("filter number is too high" )
204
+ }
205
+ }
0 commit comments