2017-03-13 18:55:02 -04:00
// Copyright 2017 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package collections
import (
"fmt"
2021-04-23 05:05:15 -04:00
"html/template"
2017-03-13 18:55:02 -04:00
"reflect"
2019-11-21 15:59:38 -05:00
"strings"
2017-03-13 18:55:02 -04:00
"testing"
"time"
2019-11-21 15:59:38 -05:00
"github.com/gohugoio/hugo/common/maps"
2022-06-06 03:48:40 -04:00
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/langs"
2019-11-21 15:59:38 -05:00
2017-06-13 12:42:45 -04:00
"github.com/gohugoio/hugo/deps"
2017-03-13 18:55:02 -04:00
)
func TestWhere ( t * testing . T ) {
t . Parallel ( )
2022-06-06 03:48:40 -04:00
ns := New ( & deps . Deps { Language : langs . NewDefaultLanguage ( config . New ( ) ) } )
2017-03-13 18:55:02 -04:00
type Mid struct {
Tst TstX
}
d1 := time . Now ( )
d2 := d1 . Add ( 1 * time . Hour )
d3 := d2 . Add ( 1 * time . Hour )
d4 := d3 . Add ( 1 * time . Hour )
d5 := d4 . Add ( 1 * time . Hour )
d6 := d5 . Add ( 1 * time . Hour )
2019-05-27 16:57:57 -04:00
type testt struct {
2022-03-17 17:03:27 -04:00
seq any
key any
2017-03-13 18:55:02 -04:00
op string
2022-03-17 17:03:27 -04:00
match any
expect any
2019-05-27 16:57:57 -04:00
}
createTestVariants := func ( test testt ) [ ] testt {
testVariants := [ ] testt { test }
if islice := ToTstXIs ( test . seq ) ; islice != nil {
variant := test
variant . seq = islice
expect := ToTstXIs ( test . expect )
if expect != nil {
variant . expect = expect
}
testVariants = append ( testVariants , variant )
}
return testVariants
}
for i , test := range [ ] testt {
2017-03-13 18:55:02 -04:00
{
seq : [ ] map [ int ] string {
{ 1 : "a" , 2 : "m" } , { 1 : "c" , 2 : "d" } , { 1 : "e" , 3 : "m" } ,
} ,
key : 2 , match : "m" ,
expect : [ ] map [ int ] string {
{ 1 : "a" , 2 : "m" } ,
} ,
} ,
{
seq : [ ] map [ string ] int {
{ "a" : 1 , "b" : 2 } , { "a" : 3 , "b" : 4 } , { "a" : 5 , "x" : 4 } ,
} ,
key : "b" , match : 4 ,
expect : [ ] map [ string ] int {
{ "a" : 3 , "b" : 4 } ,
} ,
} ,
2018-11-26 19:40:35 -05:00
{
seq : [ ] map [ string ] float64 {
{ "a" : 1 , "b" : 2 } , { "a" : 3 , "b" : 4 } , { "a" : 5 , "x" : 4 } ,
} ,
key : "b" , match : 4.0 ,
expect : [ ] map [ string ] float64 { { "a" : 3 , "b" : 4 } } ,
} ,
{
seq : [ ] map [ string ] float64 {
{ "a" : 1 , "b" : 2 } , { "a" : 3 , "b" : 4 } , { "a" : 5 , "x" : 4 } ,
} ,
key : "b" , match : 4.0 , op : "!=" ,
expect : [ ] map [ string ] float64 { { "a" : 1 , "b" : 2 } , { "a" : 5 , "x" : 4 } } ,
} ,
{
seq : [ ] map [ string ] float64 {
{ "a" : 1 , "b" : 2 } , { "a" : 3 , "b" : 4 } , { "a" : 5 , "x" : 4 } ,
} ,
key : "b" , match : 4.0 , op : "<" ,
expect : [ ] map [ string ] float64 { { "a" : 1 , "b" : 2 } } ,
} ,
2019-05-30 05:32:58 -04:00
{
seq : [ ] map [ string ] float64 {
{ "a" : 1 , "b" : 2 } , { "a" : 3 , "b" : 4 } , { "a" : 5 , "x" : 4 } ,
} ,
key : "b" , match : 4 , op : "<" ,
expect : [ ] map [ string ] float64 { { "a" : 1 , "b" : 2 } } ,
} ,
{
seq : [ ] map [ string ] int {
{ "a" : 1 , "b" : 2 } , { "a" : 3 , "b" : 4 } , { "a" : 5 , "x" : 4 } ,
} ,
key : "b" , match : 4.0 , op : "<" ,
expect : [ ] map [ string ] int { { "a" : 1 , "b" : 2 } } ,
} ,
{
seq : [ ] map [ string ] int {
{ "a" : 1 , "b" : 2 } , { "a" : 3 , "b" : 4 } , { "a" : 5 , "x" : 4 } ,
} ,
key : "b" , match : 4.2 , op : "<" ,
expect : [ ] map [ string ] int { { "a" : 1 , "b" : 2 } , { "a" : 3 , "b" : 4 } } ,
} ,
2018-11-26 19:40:35 -05:00
{
seq : [ ] map [ string ] float64 {
{ "a" : 1 , "b" : 2 } , { "a" : 3 , "b" : 4 } , { "a" : 5 , "x" : 4 } ,
} ,
key : "b" , match : 4.0 , op : "<=" ,
expect : [ ] map [ string ] float64 { { "a" : 1 , "b" : 2 } , { "a" : 3 , "b" : 4 } } ,
} ,
{
seq : [ ] map [ string ] float64 {
{ "a" : 1 , "b" : 2 } , { "a" : 3 , "b" : 3 } , { "a" : 5 , "x" : 4 } ,
} ,
key : "b" , match : 2.0 , op : ">" ,
expect : [ ] map [ string ] float64 { { "a" : 3 , "b" : 3 } } ,
} ,
{
seq : [ ] map [ string ] float64 {
{ "a" : 1 , "b" : 2 } , { "a" : 3 , "b" : 3 } , { "a" : 5 , "x" : 4 } ,
} ,
key : "b" , match : 2.0 , op : ">=" ,
expect : [ ] map [ string ] float64 { { "a" : 1 , "b" : 2 } , { "a" : 3 , "b" : 3 } } ,
} ,
2021-04-23 05:05:15 -04:00
// Issue #8353
// String type mismatch.
{
2022-03-17 17:03:27 -04:00
seq : [ ] map [ string ] any {
2021-04-23 05:05:15 -04:00
{ "a" : "1" , "b" : "2" } , { "a" : "3" , "b" : template . HTML ( "4" ) } , { "a" : "5" , "x" : "4" } ,
} ,
key : "b" , match : "4" ,
2022-03-17 17:03:27 -04:00
expect : [ ] map [ string ] any {
2021-04-23 05:05:15 -04:00
{ "a" : "3" , "b" : template . HTML ( "4" ) } ,
} ,
} ,
2017-03-13 18:55:02 -04:00
{
seq : [ ] TstX {
{ A : "a" , B : "b" } , { A : "c" , B : "d" } , { A : "e" , B : "f" } ,
} ,
key : "B" , match : "f" ,
expect : [ ] TstX {
{ A : "e" , B : "f" } ,
} ,
} ,
{
seq : [ ] * map [ int ] string {
{ 1 : "a" , 2 : "m" } , { 1 : "c" , 2 : "d" } , { 1 : "e" , 3 : "m" } ,
} ,
key : 2 , match : "m" ,
expect : [ ] * map [ int ] string {
{ 1 : "a" , 2 : "m" } ,
} ,
} ,
2021-04-21 03:08:42 -04:00
// Case insensitive maps.Params
// Slice of structs
{
seq : [ ] TstParams { { params : maps . Params { "i" : 0 , "color" : "indigo" } } , { params : maps . Params { "i" : 1 , "color" : "blue" } } , { params : maps . Params { "i" : 2 , "color" : "green" } } , { params : maps . Params { "i" : 3 , "color" : "blue" } } } ,
key : ".Params.COLOR" , match : "blue" ,
expect : [ ] TstParams { { params : maps . Params { "i" : 1 , "color" : "blue" } } , { params : maps . Params { "i" : 3 , "color" : "blue" } } } ,
} ,
{
2022-03-17 17:03:27 -04:00
seq : [ ] TstParams { { params : maps . Params { "nested" : map [ string ] any { "color" : "indigo" } } } , { params : maps . Params { "nested" : map [ string ] any { "color" : "blue" } } } } ,
2021-04-21 03:08:42 -04:00
key : ".Params.NEsTED.COLOR" , match : "blue" ,
2022-03-17 17:03:27 -04:00
expect : [ ] TstParams { { params : maps . Params { "nested" : map [ string ] any { "color" : "blue" } } } } ,
2021-04-21 03:08:42 -04:00
} ,
{
seq : [ ] TstParams { { params : maps . Params { "i" : 0 , "color" : "indigo" } } , { params : maps . Params { "i" : 1 , "color" : "blue" } } , { params : maps . Params { "i" : 2 , "color" : "green" } } , { params : maps . Params { "i" : 3 , "color" : "blue" } } } ,
key : ".Params" , match : "blue" ,
expect : [ ] TstParams { } ,
} ,
// Slice of maps
2019-11-21 15:59:38 -05:00
{
seq : [ ] maps . Params {
{ "a" : "a1" , "b" : "b1" } , { "a" : "a2" , "b" : "b2" } ,
} ,
key : "B" , match : "b2" ,
expect : [ ] maps . Params {
2020-12-02 07:23:25 -05:00
{ "a" : "a2" , "b" : "b2" } ,
2019-11-21 15:59:38 -05:00
} ,
} ,
{
seq : [ ] maps . Params {
2020-12-02 07:23:25 -05:00
{
2022-03-17 17:03:27 -04:00
"a" : map [ string ] any {
2019-11-21 15:59:38 -05:00
"b" : "b1" ,
} ,
} ,
2020-12-02 07:23:25 -05:00
{
2022-03-17 17:03:27 -04:00
"a" : map [ string ] any {
2019-11-21 15:59:38 -05:00
"b" : "b2" ,
} ,
} ,
} ,
key : "A.B" , match : "b2" ,
expect : [ ] maps . Params {
2020-12-02 07:23:25 -05:00
{
2022-03-17 17:03:27 -04:00
"a" : map [ string ] any {
2019-11-21 15:59:38 -05:00
"b" : "b2" ,
} ,
} ,
} ,
} ,
2017-03-13 18:55:02 -04:00
{
seq : [ ] * TstX {
{ A : "a" , B : "b" } , { A : "c" , B : "d" } , { A : "e" , B : "f" } ,
} ,
key : "B" , match : "f" ,
expect : [ ] * TstX {
{ A : "e" , B : "f" } ,
} ,
} ,
{
seq : [ ] * TstX {
{ A : "a" , B : "b" } , { A : "c" , B : "d" } , { A : "e" , B : "c" } ,
} ,
key : "TstRp" , match : "rc" ,
expect : [ ] * TstX {
{ A : "c" , B : "d" } ,
} ,
} ,
{
seq : [ ] TstX {
{ A : "a" , B : "b" } , { A : "c" , B : "d" } , { A : "e" , B : "c" } ,
} ,
key : "TstRv" , match : "rc" ,
expect : [ ] TstX {
{ A : "e" , B : "c" } ,
} ,
} ,
{
seq : [ ] map [ string ] TstX {
{ "foo" : TstX { A : "a" , B : "b" } } , { "foo" : TstX { A : "c" , B : "d" } } , { "foo" : TstX { A : "e" , B : "f" } } ,
} ,
key : "foo.B" , match : "d" ,
expect : [ ] map [ string ] TstX {
{ "foo" : TstX { A : "c" , B : "d" } } ,
} ,
} ,
2019-02-03 06:03:44 -05:00
{
seq : [ ] map [ string ] TstX {
{ "baz" : TstX { A : "a" , B : "b" } } , { "foo" : TstX { A : "a" , B : "b" } } , { "foo" : TstX { A : "c" , B : "d" } } , { "foo" : TstX { A : "e" , B : "f" } } ,
} ,
key : "foo.B" , match : "d" ,
expect : [ ] map [ string ] TstX {
{ "foo" : TstX { A : "c" , B : "d" } } ,
} ,
} ,
2017-03-13 18:55:02 -04:00
{
seq : [ ] map [ string ] TstX {
{ "foo" : TstX { A : "a" , B : "b" } } , { "foo" : TstX { A : "c" , B : "d" } } , { "foo" : TstX { A : "e" , B : "f" } } ,
} ,
key : ".foo.B" , match : "d" ,
expect : [ ] map [ string ] TstX {
{ "foo" : TstX { A : "c" , B : "d" } } ,
} ,
} ,
{
seq : [ ] map [ string ] TstX {
{ "foo" : TstX { A : "a" , B : "b" } } , { "foo" : TstX { A : "c" , B : "d" } } , { "foo" : TstX { A : "e" , B : "f" } } ,
} ,
key : "foo.TstRv" , match : "rd" ,
expect : [ ] map [ string ] TstX {
{ "foo" : TstX { A : "c" , B : "d" } } ,
} ,
} ,
{
seq : [ ] map [ string ] * TstX {
{ "foo" : & TstX { A : "a" , B : "b" } } , { "foo" : & TstX { A : "c" , B : "d" } } , { "foo" : & TstX { A : "e" , B : "f" } } ,
} ,
key : "foo.TstRp" , match : "rc" ,
expect : [ ] map [ string ] * TstX {
{ "foo" : & TstX { A : "c" , B : "d" } } ,
} ,
} ,
2019-05-27 16:57:57 -04:00
{
seq : [ ] TstXIHolder {
{ & TstX { A : "a" , B : "b" } } , { & TstX { A : "c" , B : "d" } } , { & TstX { A : "e" , B : "f" } } ,
} ,
key : "XI.TstRp" , match : "rc" ,
expect : [ ] TstXIHolder {
{ & TstX { A : "c" , B : "d" } } ,
} ,
} ,
{
seq : [ ] TstXIHolder {
{ & TstX { A : "a" , B : "b" } } , { & TstX { A : "c" , B : "d" } } , { & TstX { A : "e" , B : "f" } } ,
} ,
key : "XI.A" , match : "e" ,
expect : [ ] TstXIHolder {
{ & TstX { A : "e" , B : "f" } } ,
} ,
} ,
2017-03-13 18:55:02 -04:00
{
seq : [ ] map [ string ] Mid {
{ "foo" : Mid { Tst : TstX { A : "a" , B : "b" } } } , { "foo" : Mid { Tst : TstX { A : "c" , B : "d" } } } , { "foo" : Mid { Tst : TstX { A : "e" , B : "f" } } } ,
} ,
key : "foo.Tst.B" , match : "d" ,
expect : [ ] map [ string ] Mid {
{ "foo" : Mid { Tst : TstX { A : "c" , B : "d" } } } ,
} ,
} ,
{
seq : [ ] map [ string ] Mid {
{ "foo" : Mid { Tst : TstX { A : "a" , B : "b" } } } , { "foo" : Mid { Tst : TstX { A : "c" , B : "d" } } } , { "foo" : Mid { Tst : TstX { A : "e" , B : "f" } } } ,
} ,
key : "foo.Tst.TstRv" , match : "rd" ,
expect : [ ] map [ string ] Mid {
{ "foo" : Mid { Tst : TstX { A : "c" , B : "d" } } } ,
} ,
} ,
{
seq : [ ] map [ string ] * Mid {
{ "foo" : & Mid { Tst : TstX { A : "a" , B : "b" } } } , { "foo" : & Mid { Tst : TstX { A : "c" , B : "d" } } } , { "foo" : & Mid { Tst : TstX { A : "e" , B : "f" } } } ,
} ,
key : "foo.Tst.TstRp" , match : "rc" ,
expect : [ ] map [ string ] * Mid {
{ "foo" : & Mid { Tst : TstX { A : "c" , B : "d" } } } ,
} ,
} ,
{
seq : [ ] map [ string ] int {
{ "a" : 1 , "b" : 2 } , { "a" : 3 , "b" : 4 } , { "a" : 5 , "b" : 6 } ,
} ,
key : "b" , op : ">" , match : 3 ,
expect : [ ] map [ string ] int {
{ "a" : 3 , "b" : 4 } , { "a" : 5 , "b" : 6 } ,
} ,
} ,
2018-11-26 19:40:35 -05:00
{
seq : [ ] map [ string ] float64 {
{ "a" : 1 , "b" : 2 } , { "a" : 3 , "b" : 4 } , { "a" : 5 , "b" : 6 } ,
} ,
key : "b" , op : ">" , match : 3.0 ,
expect : [ ] map [ string ] float64 {
{ "a" : 3 , "b" : 4 } , { "a" : 5 , "b" : 6 } ,
} ,
} ,
2017-03-13 18:55:02 -04:00
{
seq : [ ] TstX {
{ A : "a" , B : "b" } , { A : "c" , B : "d" } , { A : "e" , B : "f" } ,
} ,
key : "B" , op : "!=" , match : "f" ,
expect : [ ] TstX {
{ A : "a" , B : "b" } , { A : "c" , B : "d" } ,
} ,
} ,
{
seq : [ ] map [ string ] int {
{ "a" : 1 , "b" : 2 } , { "a" : 3 , "b" : 4 } , { "a" : 5 , "b" : 6 } ,
} ,
key : "b" , op : "in" , match : [ ] int { 3 , 4 , 5 } ,
expect : [ ] map [ string ] int {
{ "a" : 3 , "b" : 4 } ,
} ,
} ,
2018-11-26 19:40:35 -05:00
{
seq : [ ] map [ string ] float64 {
{ "a" : 1 , "b" : 2 } , { "a" : 3 , "b" : 4 } , { "a" : 5 , "b" : 6 } ,
} ,
key : "b" , op : "in" , match : [ ] float64 { 3 , 4 , 5 } ,
expect : [ ] map [ string ] float64 {
{ "a" : 3 , "b" : 4 } ,
} ,
} ,
2017-03-13 18:55:02 -04:00
{
seq : [ ] map [ string ] [ ] string {
{ "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" } } ,
} ,
key : "b" , op : "intersect" , match : [ ] string { "D" , "P" , "Q" } ,
expect : [ ] map [ string ] [ ] string {
{ "a" : [ ] string { "A" , "B" , "C" } , "b" : [ ] string { "D" , "E" , "F" } } , { "a" : [ ] string { "M" , "N" , "O" } , "b" : [ ] string { "P" , "Q" , "R" } } ,
} ,
} ,
{
seq : [ ] map [ string ] [ ] int {
{ "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 } } ,
} ,
key : "b" , op : "intersect" , match : [ ] int { 4 , 10 , 12 } ,
expect : [ ] map [ string ] [ ] int {
{ "a" : [ ] int { 1 , 2 , 3 } , "b" : [ ] int { 4 , 5 , 6 } } , { "a" : [ ] int { 7 , 8 , 9 } , "b" : [ ] int { 10 , 11 , 12 } } ,
} ,
} ,
{
seq : [ ] map [ string ] [ ] int8 {
{ "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 } } ,
} ,
key : "b" , op : "intersect" , match : [ ] int8 { 4 , 10 , 12 } ,
expect : [ ] map [ string ] [ ] int8 {
{ "a" : [ ] int8 { 1 , 2 , 3 } , "b" : [ ] int8 { 4 , 5 , 6 } } , { "a" : [ ] int8 { 7 , 8 , 9 } , "b" : [ ] int8 { 10 , 11 , 12 } } ,
} ,
} ,
{
seq : [ ] map [ string ] [ ] int16 {
{ "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 } } ,
} ,
key : "b" , op : "intersect" , match : [ ] int16 { 4 , 10 , 12 } ,
expect : [ ] map [ string ] [ ] int16 {
{ "a" : [ ] int16 { 1 , 2 , 3 } , "b" : [ ] int16 { 4 , 5 , 6 } } , { "a" : [ ] int16 { 7 , 8 , 9 } , "b" : [ ] int16 { 10 , 11 , 12 } } ,
} ,
} ,
{
seq : [ ] map [ string ] [ ] int32 {
{ "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 } } ,
} ,
key : "b" , op : "intersect" , match : [ ] int32 { 4 , 10 , 12 } ,
expect : [ ] map [ string ] [ ] int32 {
{ "a" : [ ] int32 { 1 , 2 , 3 } , "b" : [ ] int32 { 4 , 5 , 6 } } , { "a" : [ ] int32 { 7 , 8 , 9 } , "b" : [ ] int32 { 10 , 11 , 12 } } ,
} ,
} ,
{
seq : [ ] map [ string ] [ ] int64 {
{ "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 } } ,
} ,
key : "b" , op : "intersect" , match : [ ] int64 { 4 , 10 , 12 } ,
expect : [ ] map [ string ] [ ] int64 {
{ "a" : [ ] int64 { 1 , 2 , 3 } , "b" : [ ] int64 { 4 , 5 , 6 } } , { "a" : [ ] int64 { 7 , 8 , 9 } , "b" : [ ] int64 { 10 , 11 , 12 } } ,
} ,
} ,
{
seq : [ ] map [ string ] [ ] float32 {
{ "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 } } ,
} ,
key : "b" , op : "intersect" , match : [ ] float32 { 4 , 10 , 12 } ,
expect : [ ] map [ string ] [ ] float32 {
{ "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 } } ,
} ,
} ,
{
seq : [ ] map [ string ] [ ] float64 {
{ "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 } } ,
} ,
key : "b" , op : "intersect" , match : [ ] float64 { 4 , 10 , 12 } ,
expect : [ ] map [ string ] [ ] float64 {
{ "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 } } ,
} ,
} ,
{
seq : [ ] map [ string ] int {
{ "a" : 1 , "b" : 2 } , { "a" : 3 , "b" : 4 } , { "a" : 5 , "b" : 6 } ,
} ,
key : "b" , op : "in" , match : ns . Slice ( 3 , 4 , 5 ) ,
expect : [ ] map [ string ] int {
{ "a" : 3 , "b" : 4 } ,
} ,
} ,
2018-11-26 19:40:35 -05:00
{
seq : [ ] map [ string ] float64 {
{ "a" : 1 , "b" : 2 } , { "a" : 3 , "b" : 4 } , { "a" : 5 , "b" : 6 } ,
} ,
key : "b" , op : "in" , match : ns . Slice ( 3.0 , 4.0 , 5.0 ) ,
expect : [ ] map [ string ] float64 {
{ "a" : 3 , "b" : 4 } ,
} ,
} ,
2017-03-13 18:55:02 -04:00
{
seq : [ ] map [ string ] time . Time {
{ "a" : d1 , "b" : d2 } , { "a" : d3 , "b" : d4 } , { "a" : d5 , "b" : d6 } ,
} ,
key : "b" , op : "in" , match : ns . Slice ( d3 , d4 , d5 ) ,
expect : [ ] map [ string ] time . Time {
{ "a" : d3 , "b" : d4 } ,
} ,
} ,
{
seq : [ ] TstX {
{ A : "a" , B : "b" } , { A : "c" , B : "d" } , { A : "e" , B : "f" } ,
} ,
key : "B" , op : "not in" , match : [ ] string { "c" , "d" , "e" } ,
expect : [ ] TstX {
{ A : "a" , B : "b" } , { A : "e" , B : "f" } ,
} ,
} ,
{
seq : [ ] TstX {
{ A : "a" , B : "b" } , { A : "c" , B : "d" } , { A : "e" , B : "f" } ,
} ,
key : "B" , op : "not in" , match : ns . Slice ( "c" , t , "d" , "e" ) ,
expect : [ ] TstX {
{ A : "a" , B : "b" } , { A : "e" , B : "f" } ,
} ,
} ,
{
seq : [ ] map [ string ] int {
{ "a" : 1 , "b" : 2 } , { "a" : 3 } , { "a" : 5 , "b" : 6 } ,
} ,
key : "b" , op : "" , match : nil ,
expect : [ ] map [ string ] int {
{ "a" : 3 } ,
} ,
} ,
{
seq : [ ] map [ string ] int {
{ "a" : 1 , "b" : 2 } , { "a" : 3 } , { "a" : 5 , "b" : 6 } ,
} ,
key : "b" , op : "!=" , match : nil ,
expect : [ ] map [ string ] int {
{ "a" : 1 , "b" : 2 } , { "a" : 5 , "b" : 6 } ,
} ,
} ,
{
seq : [ ] map [ string ] int {
{ "a" : 1 , "b" : 2 } , { "a" : 3 } , { "a" : 5 , "b" : 6 } ,
} ,
key : "b" , op : ">" , match : nil ,
expect : [ ] map [ string ] int { } ,
} ,
2018-11-26 19:40:35 -05:00
{
seq : [ ] map [ string ] float64 {
{ "a" : 1 , "b" : 2 } , { "a" : 3 } , { "a" : 5 , "b" : 6 } ,
} ,
key : "b" , op : "" , match : nil ,
expect : [ ] map [ string ] float64 {
{ "a" : 3 } ,
} ,
} ,
{
seq : [ ] map [ string ] float64 {
{ "a" : 1 , "b" : 2 } , { "a" : 3 } , { "a" : 5 , "b" : 6 } ,
} ,
key : "b" , op : "!=" , match : nil ,
expect : [ ] map [ string ] float64 {
{ "a" : 1 , "b" : 2 } , { "a" : 5 , "b" : 6 } ,
} ,
} ,
{
seq : [ ] map [ string ] float64 {
{ "a" : 1 , "b" : 2 } , { "a" : 3 } , { "a" : 5 , "b" : 6 } ,
} ,
key : "b" , op : ">" , match : nil ,
expect : [ ] map [ string ] float64 { } ,
} ,
2017-03-13 18:55:02 -04:00
{
seq : [ ] map [ string ] bool {
{ "a" : true , "b" : false } , { "c" : true , "b" : true } , { "d" : true , "b" : false } ,
} ,
key : "b" , op : "" , match : true ,
expect : [ ] map [ string ] bool {
{ "c" : true , "b" : true } ,
} ,
} ,
{
seq : [ ] map [ string ] bool {
{ "a" : true , "b" : false } , { "c" : true , "b" : true } , { "d" : true , "b" : false } ,
} ,
key : "b" , op : "!=" , match : true ,
expect : [ ] map [ string ] bool {
{ "a" : true , "b" : false } , { "d" : true , "b" : false } ,
} ,
} ,
{
seq : [ ] map [ string ] bool {
{ "a" : true , "b" : false } , { "c" : true , "b" : true } , { "d" : true , "b" : false } ,
} ,
key : "b" , op : ">" , match : false ,
expect : [ ] map [ string ] bool { } ,
} ,
2019-02-03 06:03:44 -05:00
{
seq : [ ] map [ string ] bool {
{ "a" : true , "b" : false } , { "c" : true , "b" : true } , { "d" : true , "b" : false } ,
} ,
key : "b.z" , match : false ,
expect : [ ] map [ string ] bool { } ,
} ,
2017-03-13 18:55:02 -04:00
{ seq : ( * [ ] TstX ) ( nil ) , key : "A" , match : "a" , expect : false } ,
{ seq : TstX { A : "a" , B : "b" } , key : "A" , match : "a" , expect : false } ,
2019-02-03 06:03:44 -05:00
{ seq : [ ] map [ string ] * TstX { { "foo" : nil } } , key : "foo.B" , match : "d" , expect : [ ] map [ string ] * TstX { } } ,
{ seq : [ ] map [ string ] * TstX { { "foo" : nil } } , key : "foo.B.Z" , match : "d" , expect : [ ] map [ string ] * TstX { } } ,
2017-03-13 18:55:02 -04:00
{
seq : [ ] TstX {
{ A : "a" , B : "b" } , { A : "c" , B : "d" } , { A : "e" , B : "f" } ,
} ,
key : "B" , op : "op" , match : "f" ,
expect : false ,
} ,
{
2022-03-17 17:03:27 -04:00
seq : map [ string ] any {
"foo" : [ ] any { map [ any ] any { "a" : 1 , "b" : 2 } } ,
"bar" : [ ] any { map [ any ] any { "a" : 3 , "b" : 4 } } ,
"zap" : [ ] any { map [ any ] any { "a" : 5 , "b" : 6 } } ,
2017-03-13 18:55:02 -04:00
} ,
key : "b" , op : "in" , match : ns . Slice ( 3 , 4 , 5 ) ,
2022-03-17 17:03:27 -04:00
expect : map [ string ] any {
"bar" : [ ] any { map [ any ] any { "a" : 3 , "b" : 4 } } ,
2017-03-13 18:55:02 -04:00
} ,
} ,
{
2022-03-17 17:03:27 -04:00
seq : map [ string ] any {
"foo" : [ ] any { map [ any ] any { "a" : 1 , "b" : 2 } } ,
"bar" : [ ] any { map [ any ] any { "a" : 3 , "b" : 4 } } ,
"zap" : [ ] any { map [ any ] any { "a" : 5 , "b" : 6 } } ,
2017-03-13 18:55:02 -04:00
} ,
key : "b" , op : ">" , match : 3 ,
2022-03-17 17:03:27 -04:00
expect : map [ string ] any {
"bar" : [ ] any { map [ any ] any { "a" : 3 , "b" : 4 } } ,
"zap" : [ ] any { map [ any ] any { "a" : 5 , "b" : 6 } } ,
2017-03-13 18:55:02 -04:00
} ,
} ,
2019-11-21 15:59:38 -05:00
{
2022-03-17 17:03:27 -04:00
seq : map [ string ] any {
"foo" : [ ] any { maps . Params { "a" : 1 , "b" : 2 } } ,
"bar" : [ ] any { maps . Params { "a" : 3 , "b" : 4 } } ,
"zap" : [ ] any { maps . Params { "a" : 5 , "b" : 6 } } ,
2019-11-21 15:59:38 -05:00
} ,
key : "B" , op : ">" , match : 3 ,
2022-03-17 17:03:27 -04:00
expect : map [ string ] any {
"bar" : [ ] any { maps . Params { "a" : 3 , "b" : 4 } } ,
"zap" : [ ] any { maps . Params { "a" : 5 , "b" : 6 } } ,
2019-11-21 15:59:38 -05:00
} ,
} ,
2017-03-13 18:55:02 -04:00
} {
2019-05-27 16:57:57 -04:00
testVariants := createTestVariants ( test )
for j , test := range testVariants {
2019-11-21 15:59:38 -05:00
name := fmt . Sprintf ( "%d/%d %T %s %s" , i , j , test . seq , test . op , test . key )
name = strings . ReplaceAll ( name , "[]" , "slice-of-" )
2019-05-27 16:57:57 -04:00
t . Run ( name , func ( t * testing . T ) {
2022-03-17 17:03:27 -04:00
var results any
2019-05-27 16:57:57 -04:00
var err error
if len ( test . op ) > 0 {
results , err = ns . Where ( test . seq , test . key , test . op , test . match )
} else {
results , err = ns . Where ( test . seq , test . key , test . match )
2019-02-03 06:03:44 -05:00
}
2019-05-27 16:57:57 -04:00
if b , ok := test . expect . ( bool ) ; ok && ! b {
if err == nil {
t . Fatalf ( "[%d] Where didn't return an expected error" , i )
}
} else {
if err != nil {
t . Fatalf ( "[%d] failed: %s" , i , err )
}
if ! reflect . DeepEqual ( results , test . expect ) {
t . Fatalf ( "Where clause matching %v with %v in seq %v (%T),\ngot\n%v (%T) but expected\n%v (%T)" , test . key , test . match , test . seq , test . seq , results , results , test . expect , test . expect )
}
2019-02-03 06:03:44 -05:00
}
2019-05-27 16:57:57 -04:00
} )
}
2017-03-13 18:55:02 -04:00
}
var err error
_ , err = ns . Where ( map [ string ] int { "a" : 1 , "b" : 2 } , "a" , [ ] byte ( "=" ) , 1 )
if err == nil {
t . Errorf ( "Where called with none string op value didn't return an expected error" )
}
_ , err = ns . Where ( map [ string ] int { "a" : 1 , "b" : 2 } , "a" , [ ] byte ( "=" ) , 1 , 2 )
if err == nil {
t . Errorf ( "Where called with more than two variable arguments didn't return an expected error" )
}
_ , err = ns . Where ( map [ string ] int { "a" : 1 , "b" : 2 } , "a" )
if err == nil {
t . Errorf ( "Where called with no variable arguments didn't return an expected error" )
}
}
func TestCheckCondition ( t * testing . T ) {
t . Parallel ( )
2022-06-06 03:48:40 -04:00
ns := New ( & deps . Deps { Language : langs . NewDefaultLanguage ( config . New ( ) ) } )
2017-03-13 18:55:02 -04:00
type expect struct {
result bool
isError bool
}
for i , test := range [ ] struct {
value reflect . Value
match reflect . Value
op string
expect
} {
{ reflect . ValueOf ( 123 ) , reflect . ValueOf ( 123 ) , "" , expect { true , false } } ,
{ reflect . ValueOf ( "foo" ) , reflect . ValueOf ( "foo" ) , "" , expect { true , false } } ,
{
reflect . ValueOf ( time . Date ( 2015 , time . May , 26 , 19 , 18 , 56 , 12345 , time . UTC ) ) ,
reflect . ValueOf ( time . Date ( 2015 , time . May , 26 , 19 , 18 , 56 , 12345 , time . UTC ) ) ,
"" ,
expect { true , false } ,
} ,
{ reflect . ValueOf ( true ) , reflect . ValueOf ( true ) , "" , expect { true , false } } ,
{ reflect . ValueOf ( nil ) , reflect . ValueOf ( nil ) , "" , expect { true , false } } ,
{ reflect . ValueOf ( 123 ) , reflect . ValueOf ( 456 ) , "!=" , expect { true , false } } ,
{ reflect . ValueOf ( "foo" ) , reflect . ValueOf ( "bar" ) , "!=" , expect { true , false } } ,
{
reflect . ValueOf ( time . Date ( 2015 , time . May , 26 , 19 , 18 , 56 , 12345 , time . UTC ) ) ,
reflect . ValueOf ( time . Date ( 2015 , time . April , 26 , 19 , 18 , 56 , 12345 , time . UTC ) ) ,
"!=" ,
expect { true , false } ,
} ,
{ reflect . ValueOf ( true ) , reflect . ValueOf ( false ) , "!=" , expect { true , false } } ,
{ reflect . ValueOf ( 123 ) , reflect . ValueOf ( nil ) , "!=" , expect { true , false } } ,
{ reflect . ValueOf ( 456 ) , reflect . ValueOf ( 123 ) , ">=" , expect { true , false } } ,
{ reflect . ValueOf ( "foo" ) , reflect . ValueOf ( "bar" ) , ">=" , expect { true , false } } ,
{
reflect . ValueOf ( time . Date ( 2015 , time . May , 26 , 19 , 18 , 56 , 12345 , time . UTC ) ) ,
reflect . ValueOf ( time . Date ( 2015 , time . April , 26 , 19 , 18 , 56 , 12345 , time . UTC ) ) ,
">=" ,
expect { true , false } ,
} ,
{ reflect . ValueOf ( 456 ) , reflect . ValueOf ( 123 ) , ">" , expect { true , false } } ,
{ reflect . ValueOf ( "foo" ) , reflect . ValueOf ( "bar" ) , ">" , expect { true , false } } ,
{
reflect . ValueOf ( time . Date ( 2015 , time . May , 26 , 19 , 18 , 56 , 12345 , time . UTC ) ) ,
reflect . ValueOf ( time . Date ( 2015 , time . April , 26 , 19 , 18 , 56 , 12345 , time . UTC ) ) ,
">" ,
expect { true , false } ,
} ,
{ reflect . ValueOf ( 123 ) , reflect . ValueOf ( 456 ) , "<=" , expect { true , false } } ,
{ reflect . ValueOf ( "bar" ) , reflect . ValueOf ( "foo" ) , "<=" , expect { true , false } } ,
{
reflect . ValueOf ( time . Date ( 2015 , time . April , 26 , 19 , 18 , 56 , 12345 , time . UTC ) ) ,
reflect . ValueOf ( time . Date ( 2015 , time . May , 26 , 19 , 18 , 56 , 12345 , time . UTC ) ) ,
"<=" ,
expect { true , false } ,
} ,
{ reflect . ValueOf ( 123 ) , reflect . ValueOf ( 456 ) , "<" , expect { true , false } } ,
{ reflect . ValueOf ( "bar" ) , reflect . ValueOf ( "foo" ) , "<" , expect { true , false } } ,
{
reflect . ValueOf ( time . Date ( 2015 , time . April , 26 , 19 , 18 , 56 , 12345 , time . UTC ) ) ,
reflect . ValueOf ( time . Date ( 2015 , time . May , 26 , 19 , 18 , 56 , 12345 , time . UTC ) ) ,
"<" ,
expect { true , false } ,
} ,
{ reflect . ValueOf ( 123 ) , reflect . ValueOf ( [ ] int { 123 , 45 , 678 } ) , "in" , expect { true , false } } ,
{ reflect . ValueOf ( "foo" ) , reflect . ValueOf ( [ ] string { "foo" , "bar" , "baz" } ) , "in" , expect { true , false } } ,
{
reflect . ValueOf ( time . Date ( 2015 , time . May , 26 , 19 , 18 , 56 , 12345 , time . UTC ) ) ,
reflect . ValueOf ( [ ] time . Time {
time . Date ( 2015 , time . April , 26 , 19 , 18 , 56 , 12345 , time . UTC ) ,
time . Date ( 2015 , time . May , 26 , 19 , 18 , 56 , 12345 , time . UTC ) ,
time . Date ( 2015 , time . June , 26 , 19 , 18 , 56 , 12345 , time . UTC ) ,
} ) ,
"in" ,
expect { true , false } ,
} ,
{ reflect . ValueOf ( 123 ) , reflect . ValueOf ( [ ] int { 45 , 678 } ) , "not in" , expect { true , false } } ,
{ reflect . ValueOf ( "foo" ) , reflect . ValueOf ( [ ] string { "bar" , "baz" } ) , "not in" , expect { true , false } } ,
{
reflect . ValueOf ( time . Date ( 2015 , time . May , 26 , 19 , 18 , 56 , 12345 , time . UTC ) ) ,
reflect . ValueOf ( [ ] time . Time {
time . Date ( 2015 , time . February , 26 , 19 , 18 , 56 , 12345 , time . UTC ) ,
time . Date ( 2015 , time . March , 26 , 19 , 18 , 56 , 12345 , time . UTC ) ,
time . Date ( 2015 , time . April , 26 , 19 , 18 , 56 , 12345 , time . UTC ) ,
} ) ,
"not in" ,
expect { true , false } ,
} ,
{ reflect . ValueOf ( "foo" ) , reflect . ValueOf ( "bar-foo-baz" ) , "in" , expect { true , false } } ,
{ reflect . ValueOf ( "foo" ) , reflect . ValueOf ( "bar--baz" ) , "not in" , expect { true , false } } ,
{ reflect . Value { } , reflect . ValueOf ( "foo" ) , "" , expect { false , false } } ,
{ reflect . ValueOf ( "foo" ) , reflect . Value { } , "" , expect { false , false } } ,
{ reflect . ValueOf ( ( * TstX ) ( nil ) ) , reflect . ValueOf ( "foo" ) , "" , expect { false , false } } ,
{ reflect . ValueOf ( "foo" ) , reflect . ValueOf ( ( * TstX ) ( nil ) ) , "" , expect { false , false } } ,
{ reflect . ValueOf ( true ) , reflect . ValueOf ( "foo" ) , "" , expect { false , false } } ,
{ reflect . ValueOf ( "foo" ) , reflect . ValueOf ( true ) , "" , expect { false , false } } ,
{ reflect . ValueOf ( "foo" ) , reflect . ValueOf ( map [ int ] string { } ) , "" , expect { false , false } } ,
{ reflect . ValueOf ( "foo" ) , reflect . ValueOf ( [ ] int { 1 , 2 } ) , "" , expect { false , false } } ,
{ reflect . ValueOf ( ( * TstX ) ( nil ) ) , reflect . ValueOf ( ( * TstX ) ( nil ) ) , ">" , expect { false , false } } ,
{ reflect . ValueOf ( true ) , reflect . ValueOf ( false ) , ">" , expect { false , false } } ,
{ reflect . ValueOf ( 123 ) , reflect . ValueOf ( [ ] int { } ) , "in" , expect { false , false } } ,
{ reflect . ValueOf ( 123 ) , reflect . ValueOf ( 123 ) , "op" , expect { false , true } } ,
2017-07-27 18:23:49 -04:00
// Issue #3718
2022-03-17 17:03:27 -04:00
{ reflect . ValueOf ( [ ] any { "a" } ) , reflect . ValueOf ( [ ] string { "a" , "b" } ) , "intersect" , expect { true , false } } ,
{ reflect . ValueOf ( [ ] string { "a" } ) , reflect . ValueOf ( [ ] any { "a" , "b" } ) , "intersect" , expect { true , false } } ,
{ reflect . ValueOf ( [ ] any { 1 , 2 } ) , reflect . ValueOf ( [ ] int { 1 } ) , "intersect" , expect { true , false } } ,
{ reflect . ValueOf ( [ ] int { 1 } ) , reflect . ValueOf ( [ ] any { 1 , 2 } ) , "intersect" , expect { true , false } } ,
2017-03-13 18:55:02 -04:00
} {
result , err := ns . checkCondition ( test . value , test . match , test . op )
if test . expect . isError {
if err == nil {
t . Errorf ( "[%d] checkCondition didn't return an expected error" , i )
}
} else {
if err != nil {
t . Errorf ( "[%d] failed: %s" , i , err )
continue
}
if result != test . expect . result {
t . Errorf ( "[%d] check condition %v %s %v, got %v but expected %v" , i , test . value , test . op , test . match , result , test . expect . result )
}
}
}
}
func TestEvaluateSubElem ( t * testing . T ) {
t . Parallel ( )
tstx := TstX { A : "foo" , B : "bar" }
var inner struct {
S fmt . Stringer
}
inner . S = tstx
interfaceValue := reflect . ValueOf ( & inner ) . Elem ( ) . Field ( 0 )
for i , test := range [ ] struct {
value reflect . Value
key string
2022-03-17 17:03:27 -04:00
expect any
2017-03-13 18:55:02 -04:00
} {
{ reflect . ValueOf ( tstx ) , "A" , "foo" } ,
{ reflect . ValueOf ( & tstx ) , "TstRp" , "rfoo" } ,
{ reflect . ValueOf ( tstx ) , "TstRv" , "rbar" } ,
//{reflect.ValueOf(map[int]string{1: "foo", 2: "bar"}), 1, "foo"},
{ reflect . ValueOf ( map [ string ] string { "key1" : "foo" , "key2" : "bar" } ) , "key1" , "foo" } ,
{ interfaceValue , "String" , "A: foo, B: bar" } ,
{ reflect . Value { } , "foo" , false } ,
//{reflect.ValueOf(map[int]string{1: "foo", 2: "bar"}), 1.2, false},
{ reflect . ValueOf ( tstx ) , "unexported" , false } ,
{ reflect . ValueOf ( tstx ) , "unexportedMethod" , false } ,
{ reflect . ValueOf ( tstx ) , "MethodWithArg" , false } ,
{ reflect . ValueOf ( tstx ) , "MethodReturnNothing" , false } ,
{ reflect . ValueOf ( tstx ) , "MethodReturnErrorOnly" , false } ,
{ reflect . ValueOf ( tstx ) , "MethodReturnTwoValues" , false } ,
{ reflect . ValueOf ( tstx ) , "MethodReturnValueWithError" , false } ,
{ reflect . ValueOf ( ( * TstX ) ( nil ) ) , "A" , false } ,
{ reflect . ValueOf ( tstx ) , "C" , false } ,
{ reflect . ValueOf ( map [ int ] string { 1 : "foo" , 2 : "bar" } ) , "1" , false } ,
{ reflect . ValueOf ( [ ] string { "foo" , "bar" } ) , "1" , false } ,
} {
result , err := evaluateSubElem ( test . value , test . key )
if b , ok := test . expect . ( bool ) ; ok && ! b {
if err == nil {
t . Errorf ( "[%d] evaluateSubElem didn't return an expected error" , i )
}
} else {
if err != nil {
t . Errorf ( "[%d] failed: %s" , i , err )
continue
}
if result . Kind ( ) != reflect . String || result . String ( ) != test . expect {
t . Errorf ( "[%d] evaluateSubElem with %v got %v but expected %v" , i , test . key , result , test . expect )
}
}
}
}