Skip to content

Commit 814d4ff

Browse files
authored
Merge pull request #5060 from gofogo/chore-tags-filter-tests
test(provider): tags filter coverage and benchmark
2 parents b90e013 + 76c8241 commit 814d4ff

File tree

1 file changed

+175
-32
lines changed

1 file changed

+175
-32
lines changed

provider/zone_tag_filter_test.go

+175-32
Original file line numberDiff line numberDiff line change
@@ -17,46 +17,189 @@ limitations under the License.
1717
package provider
1818

1919
import (
20+
"fmt"
2021
"testing"
2122

2223
"github.com/stretchr/testify/assert"
2324
)
2425

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+
2564
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)
5867
t.Run(tc.name, func(t *testing.T) {
5968
assert.Equal(t, tc.matches, zoneTagFilter.Match(tc.zoneTags))
6069
})
6170
}
6271
}
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

Comments
 (0)