github.com/GuanceCloud/cliutils@v1.1.21/filter/parse_test.go (about) 1 // Unless explicitly stated otherwise all files in this repository are licensed 2 // under the MIT License. 3 // This product includes software developed at Guance Cloud (https://www.guance.com/). 4 // Copyright 2021-present Guance, Inc. 5 6 package filter 7 8 import ( 9 "reflect" 10 "testing" 11 12 "github.com/stretchr/testify/assert" 13 ) 14 15 func TestParse(t *testing.T) { 16 cases := []struct { 17 in string 18 expected interface{} 19 fail bool 20 }{ 21 { 22 in: "{ t1 match ['g(-z]+ng wrong regex']} # invalid regex", 23 expected: WhereConditions{ 24 &WhereCondition{ 25 conditions: []Node{ 26 &BinaryExpr{ 27 Op: MATCH, 28 LHS: &Identifier{Name: "t1"}, 29 RHS: NodeList{}, 30 }, 31 }, 32 }, 33 }, 34 }, 35 36 { 37 in: "{ t1 in ['abc']}", 38 expected: WhereConditions{ 39 &WhereCondition{ 40 conditions: []Node{ 41 &BinaryExpr{ 42 Op: IN, 43 LHS: &Identifier{Name: "t1"}, 44 RHS: NodeList{ 45 &StringLiteral{Val: "abc"}, 46 }, 47 }, 48 }, 49 }, 50 }, 51 }, 52 53 { 54 in: `{ service = re(".*") AND ( 55 f1 in ["1", "2", "3"] OR 56 t1 match [ 'def.*' ] OR 57 t2 notmatch [ 'def.*' ] 58 )}`, 59 expected: WhereConditions{ 60 &WhereCondition{ 61 conditions: []Node{ 62 &BinaryExpr{ 63 Op: AND, 64 RHS: &ParenExpr{ 65 Param: &BinaryExpr{ 66 Op: OR, 67 LHS: &BinaryExpr{ 68 Op: OR, 69 70 LHS: &BinaryExpr{ 71 Op: IN, 72 LHS: &Identifier{Name: "f1"}, 73 RHS: NodeList{ 74 &StringLiteral{Val: "1"}, 75 &StringLiteral{Val: "2"}, 76 &StringLiteral{Val: "3"}, 77 }, 78 }, 79 80 RHS: &BinaryExpr{ 81 Op: MATCH, 82 LHS: &Identifier{Name: "t1"}, 83 RHS: NodeList{ 84 &Regex{Regex: "def.*"}, 85 }, 86 }, 87 }, 88 89 RHS: &BinaryExpr{ 90 Op: NOT_MATCH, 91 LHS: &Identifier{Name: "t2"}, 92 RHS: NodeList{ 93 &Regex{Regex: "def.*"}, 94 }, 95 }, 96 }, 97 }, 98 LHS: &BinaryExpr{ 99 Op: EQ, 100 LHS: &Identifier{Name: "service"}, 101 RHS: &Regex{Regex: ".*"}, 102 }, 103 }, 104 }, 105 }, 106 }, 107 }, 108 109 { 110 in: `{ service = re(".*")}`, 111 expected: WhereConditions{ 112 &WhereCondition{ 113 conditions: []Node{ 114 &BinaryExpr{ 115 Op: EQ, 116 LHS: &Identifier{Name: "service"}, 117 RHS: &Regex{Regex: ".*"}, 118 }, 119 }, 120 }, 121 }, 122 }, 123 { 124 in: `{abc notin [1.1,1.2,1.3] and (a > 1 || c< 0)}`, 125 expected: WhereConditions{ 126 &WhereCondition{ 127 conditions: []Node{ 128 &BinaryExpr{ 129 Op: AND, 130 RHS: &ParenExpr{ 131 Param: &BinaryExpr{ 132 Op: OR, 133 LHS: &BinaryExpr{ 134 Op: GT, 135 LHS: &Identifier{Name: "a"}, 136 RHS: &NumberLiteral{IsInt: true, Int: 1}, 137 }, 138 RHS: &BinaryExpr{ 139 Op: LT, 140 LHS: &Identifier{Name: "c"}, 141 RHS: &NumberLiteral{IsInt: true, Int: 0}, 142 }, 143 }, 144 }, 145 LHS: &BinaryExpr{ 146 Op: NOT_IN, 147 LHS: &Identifier{Name: "abc"}, 148 RHS: NodeList{ 149 &NumberLiteral{Float: 1.1}, 150 &NumberLiteral{Float: 1.2}, 151 &NumberLiteral{Float: 1.3}, 152 }, 153 }, 154 }, 155 }, 156 }, 157 }, 158 }, 159 160 { 161 in: `{abc notin [1.1,1.2,1.3]}`, 162 expected: WhereConditions{ 163 &WhereCondition{ 164 conditions: []Node{ 165 &BinaryExpr{ 166 Op: NOT_IN, 167 LHS: &Identifier{Name: "abc"}, 168 RHS: NodeList{ 169 &NumberLiteral{Float: 1.1}, 170 &NumberLiteral{Float: 1.2}, 171 &NumberLiteral{Float: 1.3}, 172 }, 173 }, 174 }, 175 }, 176 }, 177 }, 178 179 { 180 in: `{};{};{}`, 181 expected: WhereConditions{&WhereCondition{}, &WhereCondition{}, &WhereCondition{}}, 182 }, 183 184 { 185 in: `;;;;;{a>1};;;; {b>1};;;;`, // multiple conditions 186 expected: WhereConditions{ 187 &WhereCondition{ 188 conditions: []Node{ 189 &BinaryExpr{ 190 Op: GT, 191 LHS: &Identifier{Name: "a"}, 192 RHS: &NumberLiteral{IsInt: true, Int: 1}, 193 }, 194 }, 195 }, 196 &WhereCondition{ 197 conditions: []Node{ 198 &BinaryExpr{ 199 Op: GT, 200 LHS: &Identifier{Name: "b"}, 201 RHS: &NumberLiteral{IsInt: true, Int: 1}, 202 }, 203 }, 204 }, 205 }, 206 }, 207 208 { 209 in: `{source = 'http_dial_testing' and ( aaaa in ['aaaa44', 'gaga'] and city in ['北京'] )}`, 210 expected: WhereConditions{ 211 &WhereCondition{ 212 conditions: []Node{ 213 &BinaryExpr{ 214 Op: AND, 215 216 LHS: &BinaryExpr{ 217 Op: EQ, 218 LHS: &Identifier{Name: "source"}, 219 RHS: &StringLiteral{Val: "http_dial_testing"}, 220 }, 221 222 RHS: &ParenExpr{ 223 Param: &BinaryExpr{ 224 Op: AND, 225 226 LHS: &BinaryExpr{ 227 Op: IN, 228 LHS: &Identifier{Name: "aaaa"}, 229 RHS: &NodeList{ 230 &StringLiteral{Val: "aaaa44"}, 231 &StringLiteral{Val: "gaga"}, 232 }, 233 }, 234 RHS: &BinaryExpr{ 235 Op: IN, 236 LHS: &Identifier{Name: "city"}, 237 RHS: &NodeList{ 238 &StringLiteral{Val: "北京"}, 239 }, 240 }, 241 }, 242 }, 243 }, 244 }, 245 }, 246 }, 247 }, 248 249 { 250 in: `{source = 'http_dial_testing' and aaaa in ['aaaa44', 'gaga'] and city in ['北京'] }`, 251 expected: WhereConditions{ 252 &WhereCondition{ 253 conditions: []Node{ 254 &BinaryExpr{ 255 Op: AND, 256 LHS: &BinaryExpr{ 257 Op: AND, 258 LHS: &BinaryExpr{ 259 Op: EQ, 260 LHS: &Identifier{Name: "source"}, 261 RHS: &StringLiteral{Val: "http_dial_testing"}, 262 }, 263 RHS: &BinaryExpr{ 264 Op: IN, 265 LHS: &Identifier{Name: "aaaa"}, 266 RHS: &NodeList{ 267 &StringLiteral{Val: "aaaa44"}, 268 &StringLiteral{Val: "gaga"}, 269 }, 270 }, 271 }, 272 RHS: &BinaryExpr{ 273 Op: IN, 274 LHS: &Identifier{Name: "city"}, 275 RHS: &NodeList{ 276 &StringLiteral{Val: "北京"}, 277 }, 278 }, 279 }, 280 }, 281 }, 282 }, 283 }, 284 } 285 286 for _, tc := range cases { 287 t.Run(tc.in, func(t *testing.T) { 288 var err error 289 p := newParser(tc.in) 290 defer parserPool.Put(p) 291 defer p.recover(&err) 292 293 p.doParse() 294 295 if len(p.warns) > 0 { 296 for _, w := range p.warns { 297 t.Logf("Warn: %s", w.Error()) 298 } 299 } else { 300 t.Logf("no warnning") 301 } 302 303 if len(p.errs) > 0 { 304 for _, e := range p.errs { 305 t.Logf("Err: %s", e.Error()) 306 } 307 } 308 309 if tc.fail { 310 assert.True(t, len(p.errs) > 0) 311 return 312 } 313 314 if len(p.errs) > 0 { 315 assert.Nil(t, p.errs[0]) 316 return 317 } 318 319 switch v := p.parseResult.(type) { 320 case WhereConditions: 321 322 exp, ok := tc.expected.(WhereConditions) 323 if !ok { 324 t.Fatal("not WhereConditions") 325 } 326 327 x := exp.String() 328 y := v.String() 329 330 assert.Equal(t, x, y) 331 t.Logf("[ok] in: %s, exp: %s", x, y) 332 default: 333 t.Fatalf("should not been here: %s", reflect.TypeOf(p.parseResult).String()) 334 } 335 }) 336 } 337 } 338 339 func TestNewRegex(t *testing.T) { 340 _, err := doNewRegex("g(-z]+ng wrong regex") 341 if err != nil { 342 t.Log(err) 343 } 344 }