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  }