master
go 207 lines 5.58 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package pipeline
4
5 import (
6 "fmt"
7 "regexp"
8 "testing"
9
10 "github.com/netdata/netdata/go/plugins/plugin/agent/discovery/sd/model"
11
12 "github.com/stretchr/testify/assert"
13 )
14
15 var reSrString = regexp.MustCompile(`^{[^{}]+}$`)
16
17 func TestSelector_String(t *testing.T) {
18 tests := map[string]struct {
19 sr selector
20 want string
21 wantRegexForm bool
22 }{
23 "true selector": {
24 sr: trueSelector{},
25 want: "{*}",
26 },
27 "exact selector": {
28 sr: exactSelector("selector"),
29 wantRegexForm: true,
30 },
31 "neg selector from exact": {
32 sr: negSelector{exactSelector("selector")},
33 wantRegexForm: true,
34 },
35 "neg selector from neg": {
36 sr: negSelector{negSelector{exactSelector("selector")}},
37 wantRegexForm: true,
38 },
39 "neg selector from or": {
40 sr: negSelector{orSelector{
41 lhs: exactSelector("selector"),
42 rhs: exactSelector("selector"),
43 }},
44 wantRegexForm: true,
45 },
46 "neg selector from nested or": {
47 sr: negSelector{orSelector{
48 lhs: orSelector{lhs: exactSelector("selector"), rhs: negSelector{exactSelector("selector")}},
49 rhs: orSelector{lhs: exactSelector("selector"), rhs: negSelector{exactSelector("selector")}},
50 }},
51 wantRegexForm: true,
52 },
53 "neg selector from nested and": {
54 sr: negSelector{andSelector{
55 lhs: andSelector{lhs: exactSelector("selector"), rhs: negSelector{exactSelector("selector")}},
56 rhs: andSelector{lhs: exactSelector("selector"), rhs: negSelector{exactSelector("selector")}},
57 }},
58 wantRegexForm: true,
59 },
60 "or selector": {
61 sr: orSelector{
62 lhs: orSelector{lhs: exactSelector("selector"), rhs: negSelector{exactSelector("selector")}},
63 rhs: orSelector{lhs: exactSelector("selector"), rhs: negSelector{exactSelector("selector")}},
64 },
65 wantRegexForm: true,
66 },
67 "and selector": {
68 sr: andSelector{
69 lhs: andSelector{lhs: exactSelector("selector"), rhs: negSelector{exactSelector("selector")}},
70 rhs: andSelector{lhs: exactSelector("selector"), rhs: negSelector{exactSelector("selector")}},
71 },
72 wantRegexForm: true,
73 },
74 }
75
76 for name, tc := range tests {
77 t.Run(name, func(t *testing.T) {
78 got := fmt.Sprintf("%s", tc.sr)
79 if tc.wantRegexForm {
80 assert.True(t, reSrString.MatchString(got))
81 return
82 }
83 assert.Equal(t, tc.want, got)
84 })
85 }
86 }
87
88 func TestSelector_Matches(t *testing.T) {
89 tests := map[string]struct {
90 sr selector
91 tags model.Tags
92 want bool
93 }{
94 "exact selector matches": {
95 sr: exactSelector("a"),
96 tags: model.Tags{"a": {}, "b": {}},
97 want: true,
98 },
99 "exact selector does not match": {
100 sr: exactSelector("c"),
101 tags: model.Tags{"a": {}, "b": {}},
102 want: false,
103 },
104 "neg selector matches": {
105 sr: negSelector{exactSelector("c")},
106 tags: model.Tags{"a": {}, "b": {}},
107 want: true,
108 },
109 "neg selector does not match": {
110 sr: negSelector{exactSelector("a")},
111 tags: model.Tags{"a": {}, "b": {}},
112 want: false,
113 },
114 "or selector matches": {
115 sr: orSelector{
116 lhs: orSelector{lhs: exactSelector("c"), rhs: exactSelector("d")},
117 rhs: orSelector{lhs: exactSelector("e"), rhs: exactSelector("b")},
118 },
119 tags: model.Tags{"a": {}, "b": {}},
120 want: true,
121 },
122 "or selector does not match": {
123 sr: orSelector{
124 lhs: orSelector{lhs: exactSelector("c"), rhs: exactSelector("d")},
125 rhs: orSelector{lhs: exactSelector("e"), rhs: exactSelector("f")},
126 },
127 tags: model.Tags{"a": {}, "b": {}},
128 want: false,
129 },
130 "and selector matches": {
131 sr: andSelector{
132 lhs: andSelector{lhs: exactSelector("a"), rhs: exactSelector("b")},
133 rhs: andSelector{lhs: exactSelector("c"), rhs: exactSelector("d")},
134 },
135 tags: model.Tags{"a": {}, "b": {}, "c": {}, "d": {}},
136 want: true,
137 },
138 "and selector does not match": {
139 sr: andSelector{
140 lhs: andSelector{lhs: exactSelector("a"), rhs: exactSelector("b")},
141 rhs: andSelector{lhs: exactSelector("c"), rhs: exactSelector("z")},
142 },
143 tags: model.Tags{"a": {}, "b": {}, "c": {}, "d": {}},
144 want: false,
145 },
146 }
147
148 for name, tc := range tests {
149 t.Run(name, func(t *testing.T) {
150 assert.Equal(t, tc.want, tc.sr.matches(tc.tags))
151 })
152 }
153 }
154
155 func TestParseSelector(t *testing.T) {
156 tests := map[string]struct {
157 wantSelector selector
158 wantErr bool
159 }{
160 "": {wantSelector: trueSelector{}},
161 "a": {wantSelector: exactSelector("a")},
162 "Z": {wantSelector: exactSelector("Z")},
163 "a_b": {wantSelector: exactSelector("a_b")},
164 "a=b": {wantSelector: exactSelector("a=b")},
165 "!a": {wantSelector: negSelector{exactSelector("a")}},
166 "a b": {wantSelector: andSelector{lhs: exactSelector("a"), rhs: exactSelector("b")}},
167 "a|b": {wantSelector: orSelector{lhs: exactSelector("a"), rhs: exactSelector("b")}},
168 "*": {wantSelector: trueSelector{}},
169 "!*": {wantSelector: negSelector{trueSelector{}}},
170 "a b !c d|e f": {
171 wantSelector: andSelector{
172 lhs: andSelector{
173 lhs: andSelector{
174 lhs: andSelector{lhs: exactSelector("a"), rhs: exactSelector("b")},
175 rhs: negSelector{exactSelector("c")},
176 },
177 rhs: orSelector{
178 lhs: exactSelector("d"),
179 rhs: exactSelector("e"),
180 },
181 },
182 rhs: exactSelector("f"),
183 },
184 },
185 "!": {wantErr: true},
186 "a !": {wantErr: true},
187 "a!b": {wantErr: true},
188 "0a": {wantErr: true},
189 "a b c*": {wantErr: true},
190 "__": {wantErr: true},
191 "a|b|c*": {wantErr: true},
192 }
193
194 for name, test := range tests {
195 t.Run(name, func(t *testing.T) {
196 sr, err := parseSelector(name)
197
198 if test.wantErr {
199 assert.Nil(t, sr)
200 assert.Error(t, err)
201 } else {
202 assert.NoError(t, err)
203 assert.Equal(t, test.wantSelector, sr)
204 }
205 })
206 }
207 }