github.com/whatlly/hugo@v0.47.1/tpl/collections/where_test.go (about)

     1  // Copyright 2017 The Hugo Authors. 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  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package collections
    15  
    16  import (
    17  	"fmt"
    18  	"reflect"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/gohugoio/hugo/deps"
    23  )
    24  
    25  func TestWhere(t *testing.T) {
    26  	t.Parallel()
    27  
    28  	ns := New(&deps.Deps{})
    29  
    30  	type Mid struct {
    31  		Tst TstX
    32  	}
    33  
    34  	d1 := time.Now()
    35  	d2 := d1.Add(1 * time.Hour)
    36  	d3 := d2.Add(1 * time.Hour)
    37  	d4 := d3.Add(1 * time.Hour)
    38  	d5 := d4.Add(1 * time.Hour)
    39  	d6 := d5.Add(1 * time.Hour)
    40  
    41  	for i, test := range []struct {
    42  		seq    interface{}
    43  		key    interface{}
    44  		op     string
    45  		match  interface{}
    46  		expect interface{}
    47  	}{
    48  		{
    49  			seq: []map[int]string{
    50  				{1: "a", 2: "m"}, {1: "c", 2: "d"}, {1: "e", 3: "m"},
    51  			},
    52  			key: 2, match: "m",
    53  			expect: []map[int]string{
    54  				{1: "a", 2: "m"},
    55  			},
    56  		},
    57  		{
    58  			seq: []map[string]int{
    59  				{"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "x": 4},
    60  			},
    61  			key: "b", match: 4,
    62  			expect: []map[string]int{
    63  				{"a": 3, "b": 4},
    64  			},
    65  		},
    66  		{
    67  			seq: []TstX{
    68  				{A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"},
    69  			},
    70  			key: "B", match: "f",
    71  			expect: []TstX{
    72  				{A: "e", B: "f"},
    73  			},
    74  		},
    75  		{
    76  			seq: []*map[int]string{
    77  				{1: "a", 2: "m"}, {1: "c", 2: "d"}, {1: "e", 3: "m"},
    78  			},
    79  			key: 2, match: "m",
    80  			expect: []*map[int]string{
    81  				{1: "a", 2: "m"},
    82  			},
    83  		},
    84  		{
    85  			seq: []*TstX{
    86  				{A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"},
    87  			},
    88  			key: "B", match: "f",
    89  			expect: []*TstX{
    90  				{A: "e", B: "f"},
    91  			},
    92  		},
    93  		{
    94  			seq: []*TstX{
    95  				{A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "c"},
    96  			},
    97  			key: "TstRp", match: "rc",
    98  			expect: []*TstX{
    99  				{A: "c", B: "d"},
   100  			},
   101  		},
   102  		{
   103  			seq: []TstX{
   104  				{A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "c"},
   105  			},
   106  			key: "TstRv", match: "rc",
   107  			expect: []TstX{
   108  				{A: "e", B: "c"},
   109  			},
   110  		},
   111  		{
   112  			seq: []map[string]TstX{
   113  				{"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}, {"foo": TstX{A: "e", B: "f"}},
   114  			},
   115  			key: "foo.B", match: "d",
   116  			expect: []map[string]TstX{
   117  				{"foo": TstX{A: "c", B: "d"}},
   118  			},
   119  		},
   120  		{
   121  			seq: []map[string]TstX{
   122  				{"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}, {"foo": TstX{A: "e", B: "f"}},
   123  			},
   124  			key: ".foo.B", match: "d",
   125  			expect: []map[string]TstX{
   126  				{"foo": TstX{A: "c", B: "d"}},
   127  			},
   128  		},
   129  		{
   130  			seq: []map[string]TstX{
   131  				{"foo": TstX{A: "a", B: "b"}}, {"foo": TstX{A: "c", B: "d"}}, {"foo": TstX{A: "e", B: "f"}},
   132  			},
   133  			key: "foo.TstRv", match: "rd",
   134  			expect: []map[string]TstX{
   135  				{"foo": TstX{A: "c", B: "d"}},
   136  			},
   137  		},
   138  		{
   139  			seq: []map[string]*TstX{
   140  				{"foo": &TstX{A: "a", B: "b"}}, {"foo": &TstX{A: "c", B: "d"}}, {"foo": &TstX{A: "e", B: "f"}},
   141  			},
   142  			key: "foo.TstRp", match: "rc",
   143  			expect: []map[string]*TstX{
   144  				{"foo": &TstX{A: "c", B: "d"}},
   145  			},
   146  		},
   147  		{
   148  			seq: []map[string]Mid{
   149  				{"foo": Mid{Tst: TstX{A: "a", B: "b"}}}, {"foo": Mid{Tst: TstX{A: "c", B: "d"}}}, {"foo": Mid{Tst: TstX{A: "e", B: "f"}}},
   150  			},
   151  			key: "foo.Tst.B", match: "d",
   152  			expect: []map[string]Mid{
   153  				{"foo": Mid{Tst: TstX{A: "c", B: "d"}}},
   154  			},
   155  		},
   156  		{
   157  			seq: []map[string]Mid{
   158  				{"foo": Mid{Tst: TstX{A: "a", B: "b"}}}, {"foo": Mid{Tst: TstX{A: "c", B: "d"}}}, {"foo": Mid{Tst: TstX{A: "e", B: "f"}}},
   159  			},
   160  			key: "foo.Tst.TstRv", match: "rd",
   161  			expect: []map[string]Mid{
   162  				{"foo": Mid{Tst: TstX{A: "c", B: "d"}}},
   163  			},
   164  		},
   165  		{
   166  			seq: []map[string]*Mid{
   167  				{"foo": &Mid{Tst: TstX{A: "a", B: "b"}}}, {"foo": &Mid{Tst: TstX{A: "c", B: "d"}}}, {"foo": &Mid{Tst: TstX{A: "e", B: "f"}}},
   168  			},
   169  			key: "foo.Tst.TstRp", match: "rc",
   170  			expect: []map[string]*Mid{
   171  				{"foo": &Mid{Tst: TstX{A: "c", B: "d"}}},
   172  			},
   173  		},
   174  		{
   175  			seq: []map[string]int{
   176  				{"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "b": 6},
   177  			},
   178  			key: "b", op: ">", match: 3,
   179  			expect: []map[string]int{
   180  				{"a": 3, "b": 4}, {"a": 5, "b": 6},
   181  			},
   182  		},
   183  		{
   184  			seq: []TstX{
   185  				{A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"},
   186  			},
   187  			key: "B", op: "!=", match: "f",
   188  			expect: []TstX{
   189  				{A: "a", B: "b"}, {A: "c", B: "d"},
   190  			},
   191  		},
   192  		{
   193  			seq: []map[string]int{
   194  				{"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "b": 6},
   195  			},
   196  			key: "b", op: "in", match: []int{3, 4, 5},
   197  			expect: []map[string]int{
   198  				{"a": 3, "b": 4},
   199  			},
   200  		},
   201  		{
   202  			seq: []map[string][]string{
   203  				{"a": []string{"A", "B", "C"}, "b": []string{"D", "E", "F"}}, {"a": []string{"G", "H", "I"}, "b": []string{"J", "K", "L"}}, {"a": []string{"M", "N", "O"}, "b": []string{"P", "Q", "R"}},
   204  			},
   205  			key: "b", op: "intersect", match: []string{"D", "P", "Q"},
   206  			expect: []map[string][]string{
   207  				{"a": []string{"A", "B", "C"}, "b": []string{"D", "E", "F"}}, {"a": []string{"M", "N", "O"}, "b": []string{"P", "Q", "R"}},
   208  			},
   209  		},
   210  		{
   211  			seq: []map[string][]int{
   212  				{"a": []int{1, 2, 3}, "b": []int{4, 5, 6}}, {"a": []int{7, 8, 9}, "b": []int{10, 11, 12}}, {"a": []int{13, 14, 15}, "b": []int{16, 17, 18}},
   213  			},
   214  			key: "b", op: "intersect", match: []int{4, 10, 12},
   215  			expect: []map[string][]int{
   216  				{"a": []int{1, 2, 3}, "b": []int{4, 5, 6}}, {"a": []int{7, 8, 9}, "b": []int{10, 11, 12}},
   217  			},
   218  		},
   219  		{
   220  			seq: []map[string][]int8{
   221  				{"a": []int8{1, 2, 3}, "b": []int8{4, 5, 6}}, {"a": []int8{7, 8, 9}, "b": []int8{10, 11, 12}}, {"a": []int8{13, 14, 15}, "b": []int8{16, 17, 18}},
   222  			},
   223  			key: "b", op: "intersect", match: []int8{4, 10, 12},
   224  			expect: []map[string][]int8{
   225  				{"a": []int8{1, 2, 3}, "b": []int8{4, 5, 6}}, {"a": []int8{7, 8, 9}, "b": []int8{10, 11, 12}},
   226  			},
   227  		},
   228  		{
   229  			seq: []map[string][]int16{
   230  				{"a": []int16{1, 2, 3}, "b": []int16{4, 5, 6}}, {"a": []int16{7, 8, 9}, "b": []int16{10, 11, 12}}, {"a": []int16{13, 14, 15}, "b": []int16{16, 17, 18}},
   231  			},
   232  			key: "b", op: "intersect", match: []int16{4, 10, 12},
   233  			expect: []map[string][]int16{
   234  				{"a": []int16{1, 2, 3}, "b": []int16{4, 5, 6}}, {"a": []int16{7, 8, 9}, "b": []int16{10, 11, 12}},
   235  			},
   236  		},
   237  		{
   238  			seq: []map[string][]int32{
   239  				{"a": []int32{1, 2, 3}, "b": []int32{4, 5, 6}}, {"a": []int32{7, 8, 9}, "b": []int32{10, 11, 12}}, {"a": []int32{13, 14, 15}, "b": []int32{16, 17, 18}},
   240  			},
   241  			key: "b", op: "intersect", match: []int32{4, 10, 12},
   242  			expect: []map[string][]int32{
   243  				{"a": []int32{1, 2, 3}, "b": []int32{4, 5, 6}}, {"a": []int32{7, 8, 9}, "b": []int32{10, 11, 12}},
   244  			},
   245  		},
   246  		{
   247  			seq: []map[string][]int64{
   248  				{"a": []int64{1, 2, 3}, "b": []int64{4, 5, 6}}, {"a": []int64{7, 8, 9}, "b": []int64{10, 11, 12}}, {"a": []int64{13, 14, 15}, "b": []int64{16, 17, 18}},
   249  			},
   250  			key: "b", op: "intersect", match: []int64{4, 10, 12},
   251  			expect: []map[string][]int64{
   252  				{"a": []int64{1, 2, 3}, "b": []int64{4, 5, 6}}, {"a": []int64{7, 8, 9}, "b": []int64{10, 11, 12}},
   253  			},
   254  		},
   255  		{
   256  			seq: []map[string][]float32{
   257  				{"a": []float32{1.0, 2.0, 3.0}, "b": []float32{4.0, 5.0, 6.0}}, {"a": []float32{7.0, 8.0, 9.0}, "b": []float32{10.0, 11.0, 12.0}}, {"a": []float32{13.0, 14.0, 15.0}, "b": []float32{16.0, 17.0, 18.0}},
   258  			},
   259  			key: "b", op: "intersect", match: []float32{4, 10, 12},
   260  			expect: []map[string][]float32{
   261  				{"a": []float32{1.0, 2.0, 3.0}, "b": []float32{4.0, 5.0, 6.0}}, {"a": []float32{7.0, 8.0, 9.0}, "b": []float32{10.0, 11.0, 12.0}},
   262  			},
   263  		},
   264  		{
   265  			seq: []map[string][]float64{
   266  				{"a": []float64{1.0, 2.0, 3.0}, "b": []float64{4.0, 5.0, 6.0}}, {"a": []float64{7.0, 8.0, 9.0}, "b": []float64{10.0, 11.0, 12.0}}, {"a": []float64{13.0, 14.0, 15.0}, "b": []float64{16.0, 17.0, 18.0}},
   267  			},
   268  			key: "b", op: "intersect", match: []float64{4, 10, 12},
   269  			expect: []map[string][]float64{
   270  				{"a": []float64{1.0, 2.0, 3.0}, "b": []float64{4.0, 5.0, 6.0}}, {"a": []float64{7.0, 8.0, 9.0}, "b": []float64{10.0, 11.0, 12.0}},
   271  			},
   272  		},
   273  		{
   274  			seq: []map[string]int{
   275  				{"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "b": 6},
   276  			},
   277  			key: "b", op: "in", match: ns.Slice(3, 4, 5),
   278  			expect: []map[string]int{
   279  				{"a": 3, "b": 4},
   280  			},
   281  		},
   282  		{
   283  			seq: []map[string]time.Time{
   284  				{"a": d1, "b": d2}, {"a": d3, "b": d4}, {"a": d5, "b": d6},
   285  			},
   286  			key: "b", op: "in", match: ns.Slice(d3, d4, d5),
   287  			expect: []map[string]time.Time{
   288  				{"a": d3, "b": d4},
   289  			},
   290  		},
   291  		{
   292  			seq: []TstX{
   293  				{A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"},
   294  			},
   295  			key: "B", op: "not in", match: []string{"c", "d", "e"},
   296  			expect: []TstX{
   297  				{A: "a", B: "b"}, {A: "e", B: "f"},
   298  			},
   299  		},
   300  		{
   301  			seq: []TstX{
   302  				{A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"},
   303  			},
   304  			key: "B", op: "not in", match: ns.Slice("c", t, "d", "e"),
   305  			expect: []TstX{
   306  				{A: "a", B: "b"}, {A: "e", B: "f"},
   307  			},
   308  		},
   309  		{
   310  			seq: []map[string]int{
   311  				{"a": 1, "b": 2}, {"a": 3}, {"a": 5, "b": 6},
   312  			},
   313  			key: "b", op: "", match: nil,
   314  			expect: []map[string]int{
   315  				{"a": 3},
   316  			},
   317  		},
   318  		{
   319  			seq: []map[string]int{
   320  				{"a": 1, "b": 2}, {"a": 3}, {"a": 5, "b": 6},
   321  			},
   322  			key: "b", op: "!=", match: nil,
   323  			expect: []map[string]int{
   324  				{"a": 1, "b": 2}, {"a": 5, "b": 6},
   325  			},
   326  		},
   327  		{
   328  			seq: []map[string]int{
   329  				{"a": 1, "b": 2}, {"a": 3}, {"a": 5, "b": 6},
   330  			},
   331  			key: "b", op: ">", match: nil,
   332  			expect: []map[string]int{},
   333  		},
   334  		{
   335  			seq: []map[string]bool{
   336  				{"a": true, "b": false}, {"c": true, "b": true}, {"d": true, "b": false},
   337  			},
   338  			key: "b", op: "", match: true,
   339  			expect: []map[string]bool{
   340  				{"c": true, "b": true},
   341  			},
   342  		},
   343  		{
   344  			seq: []map[string]bool{
   345  				{"a": true, "b": false}, {"c": true, "b": true}, {"d": true, "b": false},
   346  			},
   347  			key: "b", op: "!=", match: true,
   348  			expect: []map[string]bool{
   349  				{"a": true, "b": false}, {"d": true, "b": false},
   350  			},
   351  		},
   352  		{
   353  			seq: []map[string]bool{
   354  				{"a": true, "b": false}, {"c": true, "b": true}, {"d": true, "b": false},
   355  			},
   356  			key: "b", op: ">", match: false,
   357  			expect: []map[string]bool{},
   358  		},
   359  		{seq: (*[]TstX)(nil), key: "A", match: "a", expect: false},
   360  		{seq: TstX{A: "a", B: "b"}, key: "A", match: "a", expect: false},
   361  		{seq: []map[string]*TstX{{"foo": nil}}, key: "foo.B", match: "d", expect: false},
   362  		{
   363  			seq: []TstX{
   364  				{A: "a", B: "b"}, {A: "c", B: "d"}, {A: "e", B: "f"},
   365  			},
   366  			key: "B", op: "op", match: "f",
   367  			expect: false,
   368  		},
   369  		{
   370  			seq: map[string]interface{}{
   371  				"foo": []interface{}{map[interface{}]interface{}{"a": 1, "b": 2}},
   372  				"bar": []interface{}{map[interface{}]interface{}{"a": 3, "b": 4}},
   373  				"zap": []interface{}{map[interface{}]interface{}{"a": 5, "b": 6}},
   374  			},
   375  			key: "b", op: "in", match: ns.Slice(3, 4, 5),
   376  			expect: map[string]interface{}{
   377  				"bar": []interface{}{map[interface{}]interface{}{"a": 3, "b": 4}},
   378  			},
   379  		},
   380  		{
   381  			seq: map[string]interface{}{
   382  				"foo": []interface{}{map[interface{}]interface{}{"a": 1, "b": 2}},
   383  				"bar": []interface{}{map[interface{}]interface{}{"a": 3, "b": 4}},
   384  				"zap": []interface{}{map[interface{}]interface{}{"a": 5, "b": 6}},
   385  			},
   386  			key: "b", op: ">", match: 3,
   387  			expect: map[string]interface{}{
   388  				"bar": []interface{}{map[interface{}]interface{}{"a": 3, "b": 4}},
   389  				"zap": []interface{}{map[interface{}]interface{}{"a": 5, "b": 6}},
   390  			},
   391  		},
   392  	} {
   393  		var results interface{}
   394  		var err error
   395  
   396  		if len(test.op) > 0 {
   397  			results, err = ns.Where(test.seq, test.key, test.op, test.match)
   398  		} else {
   399  			results, err = ns.Where(test.seq, test.key, test.match)
   400  		}
   401  		if b, ok := test.expect.(bool); ok && !b {
   402  			if err == nil {
   403  				t.Errorf("[%d] Where didn't return an expected error", i)
   404  			}
   405  		} else {
   406  			if err != nil {
   407  				t.Errorf("[%d] failed: %s", i, err)
   408  				continue
   409  			}
   410  			if !reflect.DeepEqual(results, test.expect) {
   411  				t.Errorf("[%d] Where clause matching %v with %v, got %v but expected %v", i, test.key, test.match, results, test.expect)
   412  			}
   413  		}
   414  	}
   415  
   416  	var err error
   417  	_, err = ns.Where(map[string]int{"a": 1, "b": 2}, "a", []byte("="), 1)
   418  	if err == nil {
   419  		t.Errorf("Where called with none string op value didn't return an expected error")
   420  	}
   421  
   422  	_, err = ns.Where(map[string]int{"a": 1, "b": 2}, "a", []byte("="), 1, 2)
   423  	if err == nil {
   424  		t.Errorf("Where called with more than two variable arguments didn't return an expected error")
   425  	}
   426  
   427  	_, err = ns.Where(map[string]int{"a": 1, "b": 2}, "a")
   428  	if err == nil {
   429  		t.Errorf("Where called with no variable arguments didn't return an expected error")
   430  	}
   431  }
   432  
   433  func TestCheckCondition(t *testing.T) {
   434  	t.Parallel()
   435  
   436  	ns := New(&deps.Deps{})
   437  
   438  	type expect struct {
   439  		result  bool
   440  		isError bool
   441  	}
   442  
   443  	for i, test := range []struct {
   444  		value reflect.Value
   445  		match reflect.Value
   446  		op    string
   447  		expect
   448  	}{
   449  		{reflect.ValueOf(123), reflect.ValueOf(123), "", expect{true, false}},
   450  		{reflect.ValueOf("foo"), reflect.ValueOf("foo"), "", expect{true, false}},
   451  		{
   452  			reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)),
   453  			reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)),
   454  			"",
   455  			expect{true, false},
   456  		},
   457  		{reflect.ValueOf(true), reflect.ValueOf(true), "", expect{true, false}},
   458  		{reflect.ValueOf(nil), reflect.ValueOf(nil), "", expect{true, false}},
   459  		{reflect.ValueOf(123), reflect.ValueOf(456), "!=", expect{true, false}},
   460  		{reflect.ValueOf("foo"), reflect.ValueOf("bar"), "!=", expect{true, false}},
   461  		{
   462  			reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)),
   463  			reflect.ValueOf(time.Date(2015, time.April, 26, 19, 18, 56, 12345, time.UTC)),
   464  			"!=",
   465  			expect{true, false},
   466  		},
   467  		{reflect.ValueOf(true), reflect.ValueOf(false), "!=", expect{true, false}},
   468  		{reflect.ValueOf(123), reflect.ValueOf(nil), "!=", expect{true, false}},
   469  		{reflect.ValueOf(456), reflect.ValueOf(123), ">=", expect{true, false}},
   470  		{reflect.ValueOf("foo"), reflect.ValueOf("bar"), ">=", expect{true, false}},
   471  		{
   472  			reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)),
   473  			reflect.ValueOf(time.Date(2015, time.April, 26, 19, 18, 56, 12345, time.UTC)),
   474  			">=",
   475  			expect{true, false},
   476  		},
   477  		{reflect.ValueOf(456), reflect.ValueOf(123), ">", expect{true, false}},
   478  		{reflect.ValueOf("foo"), reflect.ValueOf("bar"), ">", expect{true, false}},
   479  		{
   480  			reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)),
   481  			reflect.ValueOf(time.Date(2015, time.April, 26, 19, 18, 56, 12345, time.UTC)),
   482  			">",
   483  			expect{true, false},
   484  		},
   485  		{reflect.ValueOf(123), reflect.ValueOf(456), "<=", expect{true, false}},
   486  		{reflect.ValueOf("bar"), reflect.ValueOf("foo"), "<=", expect{true, false}},
   487  		{
   488  			reflect.ValueOf(time.Date(2015, time.April, 26, 19, 18, 56, 12345, time.UTC)),
   489  			reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)),
   490  			"<=",
   491  			expect{true, false},
   492  		},
   493  		{reflect.ValueOf(123), reflect.ValueOf(456), "<", expect{true, false}},
   494  		{reflect.ValueOf("bar"), reflect.ValueOf("foo"), "<", expect{true, false}},
   495  		{
   496  			reflect.ValueOf(time.Date(2015, time.April, 26, 19, 18, 56, 12345, time.UTC)),
   497  			reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)),
   498  			"<",
   499  			expect{true, false},
   500  		},
   501  		{reflect.ValueOf(123), reflect.ValueOf([]int{123, 45, 678}), "in", expect{true, false}},
   502  		{reflect.ValueOf("foo"), reflect.ValueOf([]string{"foo", "bar", "baz"}), "in", expect{true, false}},
   503  		{
   504  			reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)),
   505  			reflect.ValueOf([]time.Time{
   506  				time.Date(2015, time.April, 26, 19, 18, 56, 12345, time.UTC),
   507  				time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC),
   508  				time.Date(2015, time.June, 26, 19, 18, 56, 12345, time.UTC),
   509  			}),
   510  			"in",
   511  			expect{true, false},
   512  		},
   513  		{reflect.ValueOf(123), reflect.ValueOf([]int{45, 678}), "not in", expect{true, false}},
   514  		{reflect.ValueOf("foo"), reflect.ValueOf([]string{"bar", "baz"}), "not in", expect{true, false}},
   515  		{
   516  			reflect.ValueOf(time.Date(2015, time.May, 26, 19, 18, 56, 12345, time.UTC)),
   517  			reflect.ValueOf([]time.Time{
   518  				time.Date(2015, time.February, 26, 19, 18, 56, 12345, time.UTC),
   519  				time.Date(2015, time.March, 26, 19, 18, 56, 12345, time.UTC),
   520  				time.Date(2015, time.April, 26, 19, 18, 56, 12345, time.UTC),
   521  			}),
   522  			"not in",
   523  			expect{true, false},
   524  		},
   525  		{reflect.ValueOf("foo"), reflect.ValueOf("bar-foo-baz"), "in", expect{true, false}},
   526  		{reflect.ValueOf("foo"), reflect.ValueOf("bar--baz"), "not in", expect{true, false}},
   527  		{reflect.Value{}, reflect.ValueOf("foo"), "", expect{false, false}},
   528  		{reflect.ValueOf("foo"), reflect.Value{}, "", expect{false, false}},
   529  		{reflect.ValueOf((*TstX)(nil)), reflect.ValueOf("foo"), "", expect{false, false}},
   530  		{reflect.ValueOf("foo"), reflect.ValueOf((*TstX)(nil)), "", expect{false, false}},
   531  		{reflect.ValueOf(true), reflect.ValueOf("foo"), "", expect{false, false}},
   532  		{reflect.ValueOf("foo"), reflect.ValueOf(true), "", expect{false, false}},
   533  		{reflect.ValueOf("foo"), reflect.ValueOf(map[int]string{}), "", expect{false, false}},
   534  		{reflect.ValueOf("foo"), reflect.ValueOf([]int{1, 2}), "", expect{false, false}},
   535  		{reflect.ValueOf((*TstX)(nil)), reflect.ValueOf((*TstX)(nil)), ">", expect{false, false}},
   536  		{reflect.ValueOf(true), reflect.ValueOf(false), ">", expect{false, false}},
   537  		{reflect.ValueOf(123), reflect.ValueOf([]int{}), "in", expect{false, false}},
   538  		{reflect.ValueOf(123), reflect.ValueOf(123), "op", expect{false, true}},
   539  
   540  		// Issue #3718
   541  		{reflect.ValueOf([]interface{}{"a"}), reflect.ValueOf([]string{"a", "b"}), "intersect", expect{true, false}},
   542  		{reflect.ValueOf([]string{"a"}), reflect.ValueOf([]interface{}{"a", "b"}), "intersect", expect{true, false}},
   543  		{reflect.ValueOf([]interface{}{1, 2}), reflect.ValueOf([]int{1}), "intersect", expect{true, false}},
   544  		{reflect.ValueOf([]int{1}), reflect.ValueOf([]interface{}{1, 2}), "intersect", expect{true, false}},
   545  	} {
   546  		result, err := ns.checkCondition(test.value, test.match, test.op)
   547  		if test.expect.isError {
   548  			if err == nil {
   549  				t.Errorf("[%d] checkCondition didn't return an expected error", i)
   550  			}
   551  		} else {
   552  			if err != nil {
   553  				t.Errorf("[%d] failed: %s", i, err)
   554  				continue
   555  			}
   556  			if result != test.expect.result {
   557  				t.Errorf("[%d] check condition %v %s %v, got %v but expected %v", i, test.value, test.op, test.match, result, test.expect.result)
   558  			}
   559  		}
   560  	}
   561  }
   562  
   563  func TestEvaluateSubElem(t *testing.T) {
   564  	t.Parallel()
   565  	tstx := TstX{A: "foo", B: "bar"}
   566  	var inner struct {
   567  		S fmt.Stringer
   568  	}
   569  	inner.S = tstx
   570  	interfaceValue := reflect.ValueOf(&inner).Elem().Field(0)
   571  
   572  	for i, test := range []struct {
   573  		value  reflect.Value
   574  		key    string
   575  		expect interface{}
   576  	}{
   577  		{reflect.ValueOf(tstx), "A", "foo"},
   578  		{reflect.ValueOf(&tstx), "TstRp", "rfoo"},
   579  		{reflect.ValueOf(tstx), "TstRv", "rbar"},
   580  		//{reflect.ValueOf(map[int]string{1: "foo", 2: "bar"}), 1, "foo"},
   581  		{reflect.ValueOf(map[string]string{"key1": "foo", "key2": "bar"}), "key1", "foo"},
   582  		{interfaceValue, "String", "A: foo, B: bar"},
   583  		{reflect.Value{}, "foo", false},
   584  		//{reflect.ValueOf(map[int]string{1: "foo", 2: "bar"}), 1.2, false},
   585  		{reflect.ValueOf(tstx), "unexported", false},
   586  		{reflect.ValueOf(tstx), "unexportedMethod", false},
   587  		{reflect.ValueOf(tstx), "MethodWithArg", false},
   588  		{reflect.ValueOf(tstx), "MethodReturnNothing", false},
   589  		{reflect.ValueOf(tstx), "MethodReturnErrorOnly", false},
   590  		{reflect.ValueOf(tstx), "MethodReturnTwoValues", false},
   591  		{reflect.ValueOf(tstx), "MethodReturnValueWithError", false},
   592  		{reflect.ValueOf((*TstX)(nil)), "A", false},
   593  		{reflect.ValueOf(tstx), "C", false},
   594  		{reflect.ValueOf(map[int]string{1: "foo", 2: "bar"}), "1", false},
   595  		{reflect.ValueOf([]string{"foo", "bar"}), "1", false},
   596  	} {
   597  		result, err := evaluateSubElem(test.value, test.key)
   598  		if b, ok := test.expect.(bool); ok && !b {
   599  			if err == nil {
   600  				t.Errorf("[%d] evaluateSubElem didn't return an expected error", i)
   601  			}
   602  		} else {
   603  			if err != nil {
   604  				t.Errorf("[%d] failed: %s", i, err)
   605  				continue
   606  			}
   607  			if result.Kind() != reflect.String || result.String() != test.expect {
   608  				t.Errorf("[%d] evaluateSubElem with %v got %v but expected %v", i, test.key, result, test.expect)
   609  			}
   610  		}
   611  	}
   612  }