github.com/bytedance/go-tagexpr@v2.7.5-0.20210114074101-de5b8743ad85+incompatible/spec_test.go (about)

     1  // Copyright 2019 Bytedance Inc. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package tagexpr
    16  
    17  import (
    18  	"fmt"
    19  	"reflect"
    20  	"testing"
    21  )
    22  
    23  func TestReadPairedSymbol(t *testing.T) {
    24  	var cases = []struct {
    25  		left, right             rune
    26  		expr, val, lastExprNode string
    27  	}{
    28  		{left: '\'', right: '\'', expr: "'true '+'a'", val: "true ", lastExprNode: "+'a'"},
    29  		{left: '(', right: ')', expr: "((0+1)/(2-1)*9)%2", val: "(0+1)/(2-1)*9", lastExprNode: "%2"},
    30  		{left: '(', right: ')', expr: `(\)\(\))`, val: `)()`},
    31  		{left: '\'', right: '\'', expr: `'\\'`, val: `\\`},
    32  		{left: '\'', right: '\'', expr: `'\'\''`, val: `''`},
    33  	}
    34  	for _, c := range cases {
    35  		t.Log(c.expr)
    36  		expr := c.expr
    37  		got := readPairedSymbol(&expr, c.left, c.right)
    38  		if got == nil {
    39  			t.Fatalf("expr: %q, got: %v, %q, want: %q, %q", c.expr, got, expr, c.val, c.lastExprNode)
    40  		} else if *got != c.val || expr != c.lastExprNode {
    41  			t.Fatalf("expr: %q, got: %q, %q, want: %q, %q", c.expr, *got, expr, c.val, c.lastExprNode)
    42  		}
    43  	}
    44  }
    45  
    46  func TestReadBoolExprNode(t *testing.T) {
    47  	var cases = []struct {
    48  		expr         string
    49  		val          bool
    50  		lastExprNode string
    51  	}{
    52  		{expr: "false", val: false, lastExprNode: ""},
    53  		{expr: "true", val: true, lastExprNode: ""},
    54  		{expr: "true ", val: true, lastExprNode: " "},
    55  		{expr: "!true&", val: false, lastExprNode: "&"},
    56  		{expr: "!false|", val: true, lastExprNode: "|"},
    57  		{expr: "!!!!false =", val: !!!!false, lastExprNode: " ="},
    58  	}
    59  	for _, c := range cases {
    60  		t.Log(c.expr)
    61  		expr := c.expr
    62  		e := readBoolExprNode(&expr)
    63  		got := e.Run("", nil).(bool)
    64  		if got != c.val || expr != c.lastExprNode {
    65  			t.Fatalf("expr: %s, got: %v, %s, want: %v, %s", c.expr, got, expr, c.val, c.lastExprNode)
    66  		}
    67  	}
    68  }
    69  
    70  func TestReadDigitalExprNode(t *testing.T) {
    71  	var cases = []struct {
    72  		expr         string
    73  		val          float64
    74  		lastExprNode string
    75  	}{
    76  		{expr: "0.1 +1", val: 0.1, lastExprNode: " +1"},
    77  		{expr: "-1\\1", val: -1, lastExprNode: "\\1"},
    78  		{expr: "1a", val: 0, lastExprNode: ""},
    79  		{expr: "1", val: 1, lastExprNode: ""},
    80  		{expr: "1.1", val: 1.1, lastExprNode: ""},
    81  		{expr: "1.1/", val: 1.1, lastExprNode: "/"},
    82  	}
    83  	for _, c := range cases {
    84  		expr := c.expr
    85  		e := readDigitalExprNode(&expr)
    86  		if c.expr == "1a" {
    87  			if e != nil {
    88  				t.Fatalf("expr: %s, got:%v, want:%v", c.expr, e.Run("", nil), nil)
    89  			}
    90  			continue
    91  		}
    92  		got := e.Run("", nil).(float64)
    93  		if got != c.val || expr != c.lastExprNode {
    94  			t.Fatalf("expr: %s, got: %f, %s, want: %f, %s", c.expr, got, expr, c.val, c.lastExprNode)
    95  		}
    96  	}
    97  }
    98  
    99  func TestFindSelector(t *testing.T) {
   100  	var cases = []struct {
   101  		expr          string
   102  		field         string
   103  		name          string
   104  		subSelector   []string
   105  		boolOpposite  bool
   106  		floatOpposite bool
   107  		found         bool
   108  		last          string
   109  	}{
   110  		{expr: "$", name: "$", found: true},
   111  		{expr: "!!$", name: "$", found: true},
   112  		{expr: "!$", name: "$", boolOpposite: true, found: true},
   113  		{expr: "+$", name: "$", found: true},
   114  		{expr: "--$", name: "$", found: true},
   115  		{expr: "-$", name: "$", floatOpposite: true, found: true},
   116  		{expr: "---$", name: "$", floatOpposite: true, found: true},
   117  		{expr: "()$", last: "()$"},
   118  		{expr: "(0)$", last: "(0)$"},
   119  		{expr: "(A)$", field: "A", name: "$", found: true},
   120  		{expr: "+(A)$", field: "A", name: "$", found: true},
   121  		{expr: "++(A)$", field: "A", name: "$", found: true},
   122  		{expr: "!(A)$", field: "A", name: "$", boolOpposite: true, found: true},
   123  		{expr: "-(A)$", field: "A", name: "$", floatOpposite: true, found: true},
   124  		{expr: "(A0)$", field: "A0", name: "$", found: true},
   125  		{expr: "!!(A0)$", field: "A0", name: "$", found: true},
   126  		{expr: "--(A0)$", field: "A0", name: "$", found: true},
   127  		{expr: "(A0)$(A1)$", last: "(A0)$(A1)$"},
   128  		{expr: "(A0)$ $(A1)$", field: "A0", name: "$", found: true, last: " $(A1)$"},
   129  		{expr: "$a", last: "$a"},
   130  		{expr: "$[1]['a']", name: "$", subSelector: []string{"1", "'a'"}, found: true},
   131  		{expr: "$[1][]", last: "$[1][]"},
   132  		{expr: "$[[]]", last: "$[[]]"},
   133  		{expr: "$[[[]]]", last: "$[[[]]]"},
   134  		{expr: "$[(A)$[1]]", name: "$", subSelector: []string{"(A)$[1]"}, found: true},
   135  		{expr: "$>0&&$<10", name: "$", found: true, last: ">0&&$<10"},
   136  	}
   137  	for _, c := range cases {
   138  		last := c.expr
   139  		field, name, subSelector, boolOpposite, floatOpposite, found := findSelector(&last)
   140  		if found != c.found {
   141  			t.Fatalf("%q found: got: %v, want: %v", c.expr, found, c.found)
   142  		}
   143  		if c.boolOpposite && (boolOpposite == nil || !*boolOpposite) {
   144  			t.Fatalf("%q boolOpposite: got: %v, want: %v", c.expr, boolOpposite, c.boolOpposite)
   145  		}
   146  		if floatOpposite != c.floatOpposite {
   147  			t.Fatalf("%q floatOpposite: got: %v, want: %v", c.expr, floatOpposite, c.floatOpposite)
   148  		}
   149  		if field != c.field {
   150  			t.Fatalf("%q field: got: %q, want: %q", c.expr, field, c.field)
   151  		}
   152  		if name != c.name {
   153  			t.Fatalf("%q name: got: %q, want: %q", c.expr, name, c.name)
   154  		}
   155  		if !reflect.DeepEqual(subSelector, c.subSelector) {
   156  			t.Fatalf("%q subSelector: got: %v, want: %v", c.expr, subSelector, c.subSelector)
   157  		}
   158  		if last != c.last {
   159  			t.Fatalf("%q last: got: %q, want: %q", c.expr, last, c.last)
   160  		}
   161  	}
   162  }
   163  func printBoolPtr(b *bool) string {
   164  	var v interface{} = b
   165  	if b != nil {
   166  		v = *b
   167  	}
   168  	return fmt.Sprint(v)
   169  }