blob: d08811d4e5f84e5e11140ceac9e2a9c76695da4f [file] [log] [blame]
Scott Baker2b0ad652019-08-21 14:57:07 -07001/*
2 * Copyright 2019-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Zack Williamse940c7a2019-08-21 14:25:39 -070017package filter
18
19import (
Scott Baker9a2d9a42020-06-09 18:11:26 -070020 "github.com/stretchr/testify/assert"
Zack Williamse940c7a2019-08-21 14:25:39 -070021 "testing"
22)
23
Scott Baker9a2d9a42020-06-09 18:11:26 -070024type TestFilterIncludedStruct struct {
25 Six string
26}
27
Zack Williamse940c7a2019-08-21 14:25:39 -070028type TestFilterStruct struct {
29 One string
30 Two string
31 Three string
Scott Baker9a2d9a42020-06-09 18:11:26 -070032 Five TestFilterIncludedStruct
Scott Bakerd466f402020-06-12 15:40:42 -070033 Seven *TestFilterIncludedStruct
Zack Williamse940c7a2019-08-21 14:25:39 -070034}
35
36func TestFilterList(t *testing.T) {
Scott Bakerd466f402020-06-12 15:40:42 -070037 f, err := Parse("One=a,Two=b,Five.Six=d,Seven.Six=e")
Zack Williamse940c7a2019-08-21 14:25:39 -070038 if err != nil {
39 t.Errorf("Unable to parse filter: %s", err.Error())
40 }
41
42 data := []interface{}{
43 TestFilterStruct{
44 One: "a",
45 Two: "b",
46 Three: "c",
Scott Baker9a2d9a42020-06-09 18:11:26 -070047 Five: TestFilterIncludedStruct{Six: "d"},
Scott Bakerd466f402020-06-12 15:40:42 -070048 Seven: &TestFilterIncludedStruct{Six: "e"},
Zack Williamse940c7a2019-08-21 14:25:39 -070049 },
50 TestFilterStruct{
51 One: "1",
52 Two: "2",
53 Three: "3",
Scott Baker9a2d9a42020-06-09 18:11:26 -070054 Five: TestFilterIncludedStruct{Six: "4"},
Scott Bakerd466f402020-06-12 15:40:42 -070055 Seven: &TestFilterIncludedStruct{Six: "5"},
Zack Williamse940c7a2019-08-21 14:25:39 -070056 },
57 TestFilterStruct{
58 One: "a",
59 Two: "b",
60 Three: "z",
Scott Baker9a2d9a42020-06-09 18:11:26 -070061 Five: TestFilterIncludedStruct{Six: "d"},
Scott Bakerd466f402020-06-12 15:40:42 -070062 Seven: &TestFilterIncludedStruct{Six: "e"},
Zack Williamse940c7a2019-08-21 14:25:39 -070063 },
64 }
65
66 r, _ := f.Process(data)
67
68 if _, ok := r.([]interface{}); !ok {
69 t.Errorf("Expected list, but didn't get one")
70 }
71
72 if len(r.([]interface{})) != 2 {
73 t.Errorf("Expected %d got %d", 2, len(r.([]interface{})))
74 }
75
76 if r.([]interface{})[0] != data[0] {
77 t.Errorf("Filtered list did not match, item %d", 0)
78 }
79 if r.([]interface{})[1] != data[2] {
80 t.Errorf("Filtered list did not match, item %d", 1)
81 }
82}
83
84func TestFilterItem(t *testing.T) {
85 f, err := Parse("One=a,Two=b")
86 if err != nil {
87 t.Errorf("Unable to parse filter: %s", err.Error())
88 }
89
90 data := TestFilterStruct{
91 One: "a",
92 Two: "b",
93 Three: "c",
94 }
95
96 r, _ := f.Process(data)
97
98 if r == nil {
99 t.Errorf("Expected item, got nil")
100 }
101
102 if _, ok := r.([]interface{}); ok {
103 t.Errorf("Expected item, but got list")
104 }
105}
106
107func TestGoodFilters(t *testing.T) {
108 var f Filter
109 var err error
110 f, err = Parse("One=a,Two=b")
111 if err != nil {
112 t.Errorf("1. Unable to parse filter: %s", err.Error())
113 }
114 if len(f) != 2 ||
115 f["One"].Value != "a" ||
116 f["One"].Op != EQ ||
117 f["Two"].Value != "b" ||
118 f["Two"].Op != EQ {
119 t.Errorf("1. Filter did not parse correctly")
120 }
121
122 f, err = Parse("One=a")
123 if err != nil {
124 t.Errorf("2. Unable to parse filter: %s", err.Error())
125 }
126 if len(f) != 1 ||
127 f["One"].Value != "a" ||
128 f["One"].Op != EQ {
129 t.Errorf("2. Filter did not parse correctly")
130 }
131
132 f, err = Parse("One<a")
133 if err != nil {
134 t.Errorf("3. Unable to parse filter: %s", err.Error())
135 }
136 if len(f) != 1 ||
137 f["One"].Value != "a" ||
138 f["One"].Op != LT {
139 t.Errorf("3. Filter did not parse correctly")
140 }
141
142 f, err = Parse("One!=a")
143 if err != nil {
144 t.Errorf("4. Unable to parse filter: %s", err.Error())
145 }
146 if len(f) != 1 ||
147 f["One"].Value != "a" ||
148 f["One"].Op != NE {
149 t.Errorf("4. Filter did not parse correctly")
150 }
151}
152
153func TestBadFilters(t *testing.T) {
154 _, err := Parse("One%a")
155 if err == nil {
156 t.Errorf("Parsed filter when it shouldn't have")
157 }
158}
159
160func TestSingleRecord(t *testing.T) {
161 f, err := Parse("One=d")
162 if err != nil {
163 t.Errorf("Unable to parse filter: %s", err.Error())
164 }
165
166 data := TestFilterStruct{
167 One: "a",
168 Two: "b",
169 Three: "c",
170 }
171
172 r, err := f.Process(data)
173 if err != nil {
174 t.Errorf("Error processing data")
175 }
176
177 if r != nil {
178 t.Errorf("expected no results, got some")
179 }
180}
181
Scott Baker9a2d9a42020-06-09 18:11:26 -0700182// Invalid fields will throw an exception.
Zack Williamse940c7a2019-08-21 14:25:39 -0700183func TestInvalidField(t *testing.T) {
184 f, err := Parse("Four=a")
185 if err != nil {
186 t.Errorf("Unable to parse filter: %s", err.Error())
187 }
188
189 data := TestFilterStruct{
190 One: "a",
191 Two: "b",
192 Three: "c",
193 }
194
195 r, err := f.Process(data)
Scott Baker9a2d9a42020-06-09 18:11:26 -0700196 assert.EqualError(t, err, "Failed to find field Four while filtering")
197
198 if r != nil {
199 t.Errorf("expected no results, got some")
Zack Williamse940c7a2019-08-21 14:25:39 -0700200 }
Scott Baker9a2d9a42020-06-09 18:11:26 -0700201}
202
203func TestInvalidDotted(t *testing.T) {
204 f, err := Parse("Five.NonExistent=a")
205 if err != nil {
206 t.Errorf("Unable to parse filter: %s", err.Error())
207 }
208
209 data := TestFilterStruct{
210 One: "a",
211 Two: "b",
212 Three: "c",
213 Five: TestFilterIncludedStruct{Six: "w"},
214 }
215
216 r, err := f.Process(data)
217 assert.EqualError(t, err, "Failed to find field NonExistent while filtering")
218
219 if r != nil {
220 t.Errorf("expected no results, got some")
221 }
222}
223
224func TestTrailingDot(t *testing.T) {
225 f, err := Parse("Five.Six.=a")
226 if err != nil {
227 t.Errorf("Unable to parse filter: %s", err.Error())
228 }
229
230 data := TestFilterStruct{
231 One: "a",
232 Two: "b",
233 Three: "c",
234 Five: TestFilterIncludedStruct{Six: "w"},
235 }
236
237 r, err := f.Process(data)
Scott Bakerd466f402020-06-12 15:40:42 -0700238 assert.EqualError(t, err, "Field name specified in filter did not resolve to a valid field")
Scott Baker9a2d9a42020-06-09 18:11:26 -0700239
240 if r != nil {
241 t.Errorf("expected no results, got some")
242 }
243}
244
245func TestDottedOnString(t *testing.T) {
246 f, err := Parse("One.IsNotAStruct=a")
247 if err != nil {
248 t.Errorf("Unable to parse filter: %s", err.Error())
249 }
250
251 data := TestFilterStruct{
252 One: "a",
253 Two: "b",
254 Three: "c",
255 Five: TestFilterIncludedStruct{Six: "w"},
256 }
257
258 r, err := f.Process(data)
Scott Bakerd466f402020-06-12 15:40:42 -0700259 assert.EqualError(t, err, "Field name specified in filter did not resolve to a valid field")
260
261 if r != nil {
262 t.Errorf("expected no results, got some")
263 }
264}
265
266func TestFilterOnStruct(t *testing.T) {
267 f, err := Parse("Five=a")
268 if err != nil {
269 t.Errorf("Unable to parse filter: %s", err.Error())
270 }
271
272 data := TestFilterStruct{
273 One: "a",
274 Two: "b",
275 Three: "c",
276 Five: TestFilterIncludedStruct{Six: "w"},
277 }
278
279 r, err := f.Process(data)
280 assert.EqualError(t, err, "Cannot filter on a field that is a struct")
281
282 if r != nil {
283 t.Errorf("expected no results, got some")
284 }
285}
286
287func TestFilterOnPointerStruct(t *testing.T) {
288 f, err := Parse("Seven=a")
289 if err != nil {
290 t.Errorf("Unable to parse filter: %s", err.Error())
291 }
292
293 data := TestFilterStruct{
294 One: "a",
295 Two: "b",
296 Three: "c",
297 Seven: &TestFilterIncludedStruct{Six: "w"},
298 }
299
300 r, err := f.Process(data)
301 assert.EqualError(t, err, "Cannot filter on a field that is a struct")
Zack Williamse940c7a2019-08-21 14:25:39 -0700302
303 if r != nil {
304 t.Errorf("expected no results, got some")
305 }
306}
307
308func TestREFilter(t *testing.T) {
309 var f Filter
310 var err error
311 f, err = Parse("One~a")
312 if err != nil {
313 t.Errorf("Unable to parse RE expression")
314 }
315 if len(f) != 1 {
316 t.Errorf("filter parsed incorrectly")
317 }
318
319 data := []interface{}{
320 TestFilterStruct{
321 One: "a",
322 Two: "b",
323 Three: "c",
324 },
325 TestFilterStruct{
326 One: "1",
327 Two: "2",
328 Three: "3",
329 },
330 TestFilterStruct{
331 One: "a",
332 Two: "b",
333 Three: "z",
334 },
335 }
336
David Bainbridge12f036f2019-10-15 22:09:04 +0000337 if _, err = f.Process(data); err != nil {
338 t.Errorf("Error processing data")
339 }
Zack Williamse940c7a2019-08-21 14:25:39 -0700340}
341
342func TestBadRE(t *testing.T) {
343 _, err := Parse("One~(qs*")
344 if err == nil {
345 t.Errorf("Expected RE parse error, got none")
346 }
347}