github.com/bytedance/go-tagexpr/v2@v2.9.8/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  	"context"
    19  	"fmt"
    20  	"reflect"
    21  	"testing"
    22  )
    23  
    24  func TestReadPairedSymbol(t *testing.T) {
    25  	var cases = []struct {
    26  		left, right             rune
    27  		expr, val, lastExprNode string
    28  	}{
    29  		{left: '\'', right: '\'', expr: "'true '+'a'", val: "true ", lastExprNode: "+'a'"},
    30  		{left: '(', right: ')', expr: "((0+1)/(2-1)*9)%2", val: "(0+1)/(2-1)*9", lastExprNode: "%2"},
    31  		{left: '(', right: ')', expr: `(\)\(\))`, val: `)()`},
    32  		{left: '\'', right: '\'', expr: `'\\'`, val: `\\`},
    33  		{left: '\'', right: '\'', expr: `'\'\''`, val: `''`},
    34  	}
    35  	for _, c := range cases {
    36  		t.Log(c.expr)
    37  		expr := c.expr
    38  		got := readPairedSymbol(&expr, c.left, c.right)
    39  		if got == nil {
    40  			t.Fatalf("expr: %q, got: %v, %q, want: %q, %q", c.expr, got, expr, c.val, c.lastExprNode)
    41  		} else if *got != c.val || expr != c.lastExprNode {
    42  			t.Fatalf("expr: %q, got: %q, %q, want: %q, %q", c.expr, *got, expr, c.val, c.lastExprNode)
    43  		}
    44  	}
    45  }
    46  
    47  func TestReadBoolExprNode(t *testing.T) {
    48  	var cases = []struct {
    49  		expr         string
    50  		val          bool
    51  		lastExprNode string
    52  	}{
    53  		{expr: "false", val: false, lastExprNode: ""},
    54  		{expr: "true", val: true, lastExprNode: ""},
    55  		{expr: "true ", val: true, lastExprNode: " "},
    56  		{expr: "!true&", val: false, lastExprNode: "&"},
    57  		{expr: "!false|", val: true, lastExprNode: "|"},
    58  		{expr: "!!!!false =", val: !!!!false, lastExprNode: " ="},
    59  	}
    60  	for _, c := range cases {
    61  		t.Log(c.expr)
    62  		expr := c.expr
    63  		e := readBoolExprNode(&expr)
    64  		got := e.Run(context.TODO(), "", nil).(bool)
    65  		if got != c.val || expr != c.lastExprNode {
    66  			t.Fatalf("expr: %s, got: %v, %s, want: %v, %s", c.expr, got, expr, c.val, c.lastExprNode)
    67  		}
    68  	}
    69  }
    70  
    71  func TestReadDigitalExprNode(t *testing.T) {
    72  	var cases = []struct {
    73  		expr         string
    74  		val          float64
    75  		lastExprNode string
    76  	}{
    77  		{expr: "0.1 +1", val: 0.1, lastExprNode: " +1"},
    78  		{expr: "-1\\1", val: -1, lastExprNode: "\\1"},
    79  		{expr: "1a", val: 0, lastExprNode: ""},
    80  		{expr: "1", val: 1, lastExprNode: ""},
    81  		{expr: "1.1", val: 1.1, lastExprNode: ""},
    82  		{expr: "1.1/", val: 1.1, lastExprNode: "/"},
    83  	}
    84  	for _, c := range cases {
    85  		expr := c.expr
    86  		e := readDigitalExprNode(&expr)
    87  		if c.expr == "1a" {
    88  			if e != nil {
    89  				t.Fatalf("expr: %s, got:%v, want:%v", c.expr, e.Run(context.TODO(), "", nil), nil)
    90  			}
    91  			continue
    92  		}
    93  		got := e.Run(context.TODO(), "", nil).(float64)
    94  		if got != c.val || expr != c.lastExprNode {
    95  			t.Fatalf("expr: %s, got: %f, %s, want: %f, %s", c.expr, got, expr, c.val, c.lastExprNode)
    96  		}
    97  	}
    98  }
    99  
   100  func TestFindSelector(t *testing.T) {
   101  	var cases = []struct {
   102  		expr         string
   103  		field        string
   104  		name         string
   105  		subSelector  []string
   106  		boolOpposite bool
   107  		signOpposite bool
   108  		found        bool
   109  		last         string
   110  	}{
   111  		{expr: "$", name: "$", found: true},
   112  		{expr: "!!$", name: "$", found: true},
   113  		{expr: "!$", name: "$", boolOpposite: true, found: true},
   114  		{expr: "+$", name: "$", found: true},
   115  		{expr: "--$", name: "$", found: true},
   116  		{expr: "-$", name: "$", signOpposite: true, found: true},
   117  		{expr: "---$", name: "$", signOpposite: true, found: true},
   118  		{expr: "()$", last: "()$"},
   119  		{expr: "(0)$", last: "(0)$"},
   120  		{expr: "(A)$", field: "A", name: "$", found: true},
   121  		{expr: "+(A)$", field: "A", name: "$", found: true},
   122  		{expr: "++(A)$", field: "A", name: "$", found: true},
   123  		{expr: "!(A)$", field: "A", name: "$", boolOpposite: true, found: true},
   124  		{expr: "-(A)$", field: "A", name: "$", signOpposite: true, found: true},
   125  		{expr: "(A0)$", field: "A0", name: "$", found: true},
   126  		{expr: "!!(A0)$", field: "A0", name: "$", found: true},
   127  		{expr: "--(A0)$", field: "A0", name: "$", found: true},
   128  		{expr: "(A0)$(A1)$", last: "(A0)$(A1)$"},
   129  		{expr: "(A0)$ $(A1)$", field: "A0", name: "$", found: true, last: " $(A1)$"},
   130  		{expr: "$a", last: "$a"},
   131  		{expr: "$[1]['a']", name: "$", subSelector: []string{"1", "'a'"}, found: true},
   132  		{expr: "$[1][]", last: "$[1][]"},
   133  		{expr: "$[[]]", last: "$[[]]"},
   134  		{expr: "$[[[]]]", last: "$[[[]]]"},
   135  		{expr: "$[(A)$[1]]", name: "$", subSelector: []string{"(A)$[1]"}, found: true},
   136  		{expr: "$>0&&$<10", name: "$", found: true, last: ">0&&$<10"},
   137  	}
   138  	for _, c := range cases {
   139  		last := c.expr
   140  		field, name, subSelector, boolOpposite, signOpposite, found := findSelector(&last)
   141  		if found != c.found {
   142  			t.Fatalf("%q found: got: %v, want: %v", c.expr, found, c.found)
   143  		}
   144  		if c.boolOpposite && (boolOpposite == nil || !*boolOpposite) {
   145  			t.Fatalf("%q boolOpposite: got: %v, want: %v", c.expr, boolOpposite, c.boolOpposite)
   146  		}
   147  		if c.signOpposite && (signOpposite == nil || !*signOpposite) {
   148  			t.Fatalf("%q signOpposite: got: %v, want: %v", c.expr, signOpposite, c.signOpposite)
   149  		}
   150  		if field != c.field {
   151  			t.Fatalf("%q field: got: %q, want: %q", c.expr, field, c.field)
   152  		}
   153  		if name != c.name {
   154  			t.Fatalf("%q name: got: %q, want: %q", c.expr, name, c.name)
   155  		}
   156  		if !reflect.DeepEqual(subSelector, c.subSelector) {
   157  			t.Fatalf("%q subSelector: got: %v, want: %v", c.expr, subSelector, c.subSelector)
   158  		}
   159  		if last != c.last {
   160  			t.Fatalf("%q last: got: %q, want: %q", c.expr, last, c.last)
   161  		}
   162  	}
   163  }
   164  func printBoolPtr(b *bool) string {
   165  	var v interface{} = b
   166  	if b != nil {
   167  		v = *b
   168  	}
   169  	return fmt.Sprint(v)
   170  }