github.com/aavshr/aws-sdk-go@v1.41.3/service/dynamodb/expression/condition_test.go (about)

     1  //go:build go1.7
     2  // +build go1.7
     3  
     4  package expression
     5  
     6  import (
     7  	"reflect"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/aavshr/aws-sdk-go/aws"
    12  	"github.com/aavshr/aws-sdk-go/service/dynamodb"
    13  )
    14  
    15  // condErrorMode will help with error cases and checking error types
    16  type condErrorMode string
    17  
    18  const (
    19  	noConditionError condErrorMode = ""
    20  	// unsetCondition error will occur when BuildExpression is called on an empty
    21  	// ConditionBuilder
    22  	unsetCondition = "unset parameter: ConditionBuilder"
    23  	// invalidOperand error will occur when an invalid OperandBuilder is used as
    24  	// an argument
    25  	invalidConditionOperand = "BuildOperand error"
    26  )
    27  
    28  //Compare
    29  func TestCompare(t *testing.T) {
    30  	cases := []struct {
    31  		name         string
    32  		input        ConditionBuilder
    33  		expectedNode exprNode
    34  		err          condErrorMode
    35  	}{
    36  		{
    37  			name:  "name equal name",
    38  			input: Name("foo").Equal(Name("bar")),
    39  			expectedNode: exprNode{
    40  				children: []exprNode{
    41  					{
    42  						names:   []string{"foo"},
    43  						fmtExpr: "$n",
    44  					},
    45  					{
    46  						names:   []string{"bar"},
    47  						fmtExpr: "$n",
    48  					},
    49  				},
    50  				fmtExpr: "$c = $c",
    51  			},
    52  		},
    53  		{
    54  			name:  "value equal value",
    55  			input: Value(5).Equal(Value("bar")),
    56  			expectedNode: exprNode{
    57  				children: []exprNode{
    58  					{
    59  						values: []dynamodb.AttributeValue{
    60  							{
    61  								N: aws.String("5"),
    62  							},
    63  						},
    64  						fmtExpr: "$v",
    65  					},
    66  					{
    67  						values: []dynamodb.AttributeValue{
    68  							{
    69  								S: aws.String("bar"),
    70  							},
    71  						},
    72  						fmtExpr: "$v",
    73  					},
    74  				},
    75  				fmtExpr: "$c = $c",
    76  			},
    77  		},
    78  		{
    79  			name:  "name size equal name size",
    80  			input: Name("foo[1]").Size().Equal(Name("bar").Size()),
    81  			expectedNode: exprNode{
    82  				children: []exprNode{
    83  					{
    84  						names:   []string{"foo"},
    85  						fmtExpr: "size ($n[1])",
    86  					},
    87  					{
    88  						names:   []string{"bar"},
    89  						fmtExpr: "size ($n)",
    90  					},
    91  				},
    92  				fmtExpr: "$c = $c",
    93  			},
    94  		},
    95  		{
    96  			name:  "name not equal name",
    97  			input: Name("foo").NotEqual(Name("bar")),
    98  			expectedNode: exprNode{
    99  				children: []exprNode{
   100  					{
   101  						names:   []string{"foo"},
   102  						fmtExpr: "$n",
   103  					},
   104  					{
   105  						names:   []string{"bar"},
   106  						fmtExpr: "$n",
   107  					},
   108  				},
   109  				fmtExpr: "$c <> $c",
   110  			},
   111  		},
   112  		{
   113  			name:  "value not equal value",
   114  			input: Value(5).NotEqual(Value("bar")),
   115  			expectedNode: exprNode{
   116  				children: []exprNode{
   117  					{
   118  						values: []dynamodb.AttributeValue{
   119  							{
   120  								N: aws.String("5"),
   121  							},
   122  						},
   123  						fmtExpr: "$v",
   124  					},
   125  					{
   126  						values: []dynamodb.AttributeValue{
   127  							{
   128  								S: aws.String("bar"),
   129  							},
   130  						},
   131  						fmtExpr: "$v",
   132  					},
   133  				},
   134  				fmtExpr: "$c <> $c",
   135  			},
   136  		},
   137  		{
   138  			name:  "name size not equal name size",
   139  			input: Name("foo[1]").Size().NotEqual(Name("bar").Size()),
   140  			expectedNode: exprNode{
   141  				children: []exprNode{
   142  					{
   143  						names:   []string{"foo"},
   144  						fmtExpr: "size ($n[1])",
   145  					},
   146  					{
   147  						names:   []string{"bar"},
   148  						fmtExpr: "size ($n)",
   149  					},
   150  				},
   151  				fmtExpr: "$c <> $c",
   152  			},
   153  		},
   154  		{
   155  			name:  "name less than name",
   156  			input: Name("foo").LessThan(Name("bar")),
   157  			expectedNode: exprNode{
   158  				children: []exprNode{
   159  					{
   160  						names:   []string{"foo"},
   161  						fmtExpr: "$n",
   162  					},
   163  					{
   164  						names:   []string{"bar"},
   165  						fmtExpr: "$n",
   166  					},
   167  				},
   168  				fmtExpr: "$c < $c",
   169  			},
   170  		},
   171  		{
   172  			name:  "value less than value",
   173  			input: Value(5).LessThan(Value("bar")),
   174  			expectedNode: exprNode{
   175  				children: []exprNode{
   176  					{
   177  						values: []dynamodb.AttributeValue{
   178  							{
   179  								N: aws.String("5"),
   180  							},
   181  						},
   182  						fmtExpr: "$v",
   183  					},
   184  					{
   185  						values: []dynamodb.AttributeValue{
   186  							{
   187  								S: aws.String("bar"),
   188  							},
   189  						},
   190  						fmtExpr: "$v",
   191  					},
   192  				},
   193  				fmtExpr: "$c < $c",
   194  			},
   195  		},
   196  		{
   197  			name:  "name size less than name size",
   198  			input: Name("foo[1]").Size().LessThan(Name("bar").Size()),
   199  			expectedNode: exprNode{
   200  				children: []exprNode{
   201  					{
   202  						names:   []string{"foo"},
   203  						fmtExpr: "size ($n[1])",
   204  					},
   205  					{
   206  						names:   []string{"bar"},
   207  						fmtExpr: "size ($n)",
   208  					},
   209  				},
   210  				fmtExpr: "$c < $c",
   211  			},
   212  		},
   213  		{
   214  			name:  "name less than equal name",
   215  			input: Name("foo").LessThanEqual(Name("bar")),
   216  			expectedNode: exprNode{
   217  				children: []exprNode{
   218  					{
   219  						names:   []string{"foo"},
   220  						fmtExpr: "$n",
   221  					},
   222  					{
   223  						names:   []string{"bar"},
   224  						fmtExpr: "$n",
   225  					},
   226  				},
   227  				fmtExpr: "$c <= $c",
   228  			},
   229  		},
   230  		{
   231  			name:  "value less than equal value",
   232  			input: Value(5).LessThanEqual(Value("bar")),
   233  			expectedNode: exprNode{
   234  				children: []exprNode{
   235  					{
   236  						values: []dynamodb.AttributeValue{
   237  							{
   238  								N: aws.String("5"),
   239  							},
   240  						},
   241  						fmtExpr: "$v",
   242  					},
   243  					{
   244  						values: []dynamodb.AttributeValue{
   245  							{
   246  								S: aws.String("bar"),
   247  							},
   248  						},
   249  						fmtExpr: "$v",
   250  					},
   251  				},
   252  				fmtExpr: "$c <= $c",
   253  			},
   254  		},
   255  		{
   256  			name:  "name size less than equal name size",
   257  			input: Name("foo[1]").Size().LessThanEqual(Name("bar").Size()),
   258  			expectedNode: exprNode{
   259  				children: []exprNode{
   260  					{
   261  						names:   []string{"foo"},
   262  						fmtExpr: "size ($n[1])",
   263  					},
   264  					{
   265  						names:   []string{"bar"},
   266  						fmtExpr: "size ($n)",
   267  					},
   268  				},
   269  				fmtExpr: "$c <= $c",
   270  			},
   271  		},
   272  		{
   273  			name:  "name greater than name",
   274  			input: Name("foo").GreaterThan(Name("bar")),
   275  			expectedNode: exprNode{
   276  				children: []exprNode{
   277  					{
   278  						names:   []string{"foo"},
   279  						fmtExpr: "$n",
   280  					},
   281  					{
   282  						names:   []string{"bar"},
   283  						fmtExpr: "$n",
   284  					},
   285  				},
   286  				fmtExpr: "$c > $c",
   287  			},
   288  		},
   289  		{
   290  			name:  "value greater than value",
   291  			input: Value(5).GreaterThan(Value("bar")),
   292  			expectedNode: exprNode{
   293  				children: []exprNode{
   294  					{
   295  						values: []dynamodb.AttributeValue{
   296  							{
   297  								N: aws.String("5"),
   298  							},
   299  						},
   300  						fmtExpr: "$v",
   301  					},
   302  					{
   303  						values: []dynamodb.AttributeValue{
   304  							{
   305  								S: aws.String("bar"),
   306  							},
   307  						},
   308  						fmtExpr: "$v",
   309  					},
   310  				},
   311  				fmtExpr: "$c > $c",
   312  			},
   313  		},
   314  		{
   315  			name:  "name size greater than name size",
   316  			input: Name("foo[1]").Size().GreaterThan(Name("bar").Size()),
   317  			expectedNode: exprNode{
   318  				children: []exprNode{
   319  					{
   320  						names:   []string{"foo"},
   321  						fmtExpr: "size ($n[1])",
   322  					},
   323  					{
   324  						names:   []string{"bar"},
   325  						fmtExpr: "size ($n)",
   326  					},
   327  				},
   328  				fmtExpr: "$c > $c",
   329  			},
   330  		},
   331  		{
   332  			name:  "name greater than equal name",
   333  			input: Name("foo").GreaterThanEqual(Name("bar")),
   334  			expectedNode: exprNode{
   335  				children: []exprNode{
   336  					{
   337  						names:   []string{"foo"},
   338  						fmtExpr: "$n",
   339  					},
   340  					{
   341  						names:   []string{"bar"},
   342  						fmtExpr: "$n",
   343  					},
   344  				},
   345  				fmtExpr: "$c >= $c",
   346  			},
   347  		},
   348  		{
   349  			name:  "value greater than equal value",
   350  			input: Value(5).GreaterThanEqual(Value("bar")),
   351  			expectedNode: exprNode{
   352  				children: []exprNode{
   353  					{
   354  						values: []dynamodb.AttributeValue{
   355  							{
   356  								N: aws.String("5"),
   357  							},
   358  						},
   359  						fmtExpr: "$v",
   360  					},
   361  					{
   362  						values: []dynamodb.AttributeValue{
   363  							{
   364  								S: aws.String("bar"),
   365  							},
   366  						},
   367  						fmtExpr: "$v",
   368  					},
   369  				},
   370  				fmtExpr: "$c >= $c",
   371  			},
   372  		},
   373  		{
   374  			name:  "name size greater than equal name size",
   375  			input: Name("foo[1]").Size().GreaterThanEqual(Name("bar").Size()),
   376  			expectedNode: exprNode{
   377  				children: []exprNode{
   378  					{
   379  						names:   []string{"foo"},
   380  						fmtExpr: "size ($n[1])",
   381  					},
   382  					{
   383  						names:   []string{"bar"},
   384  						fmtExpr: "size ($n)",
   385  					},
   386  				},
   387  				fmtExpr: "$c >= $c",
   388  			},
   389  		},
   390  		{
   391  			name:  "invalid operand error Equal",
   392  			input: Name("").Size().Equal(Value(5)),
   393  			err:   invalidConditionOperand,
   394  		},
   395  		{
   396  			name:  "invalid operand error NotEqual",
   397  			input: Name("").Size().NotEqual(Value(5)),
   398  			err:   invalidConditionOperand,
   399  		},
   400  		{
   401  			name:  "invalid operand error LessThan",
   402  			input: Name("").Size().LessThan(Value(5)),
   403  			err:   invalidConditionOperand,
   404  		},
   405  		{
   406  			name:  "invalid operand error LessThanEqual",
   407  			input: Name("").Size().LessThanEqual(Value(5)),
   408  			err:   invalidConditionOperand,
   409  		},
   410  		{
   411  			name:  "invalid operand error GreaterThan",
   412  			input: Name("").Size().GreaterThan(Value(5)),
   413  			err:   invalidConditionOperand,
   414  		},
   415  		{
   416  			name:  "invalid operand error GreaterThanEqual",
   417  			input: Name("").Size().GreaterThanEqual(Value(5)),
   418  			err:   invalidConditionOperand,
   419  		},
   420  	}
   421  	for _, c := range cases {
   422  		t.Run(c.name, func(t *testing.T) {
   423  			actual, err := c.input.buildTree()
   424  			if c.err != noConditionError {
   425  				if err == nil {
   426  					t.Errorf("expect error %q, got no error", c.err)
   427  				} else {
   428  					if e, a := string(c.err), err.Error(); !strings.Contains(a, e) {
   429  						t.Errorf("expect %q error message to be in %q", e, a)
   430  					}
   431  				}
   432  			} else {
   433  				if err != nil {
   434  					t.Errorf("expect no error, got unexpected Error %q", err)
   435  				}
   436  
   437  				if e, a := c.expectedNode, actual; !reflect.DeepEqual(a, e) {
   438  					t.Errorf("expect %v, got %v", e, a)
   439  				}
   440  			}
   441  		})
   442  	}
   443  }
   444  
   445  func TestBuildCondition(t *testing.T) {
   446  	cases := []struct {
   447  		name     string
   448  		input    ConditionBuilder
   449  		expected exprNode
   450  		err      condErrorMode
   451  	}{
   452  		{
   453  			name:  "no match error",
   454  			input: ConditionBuilder{},
   455  			err:   unsetCondition,
   456  		},
   457  	}
   458  
   459  	for _, c := range cases {
   460  		t.Run(c.name, func(t *testing.T) {
   461  			actual, err := c.input.buildTree()
   462  			if c.err != noConditionError {
   463  				if err == nil {
   464  					t.Errorf("expect error %q, got no error", c.err)
   465  				} else {
   466  					if e, a := string(c.err), err.Error(); !strings.Contains(a, e) {
   467  						t.Errorf("expect %q error message to be in %q", e, a)
   468  					}
   469  				}
   470  			} else {
   471  				if err != nil {
   472  					t.Errorf("expect no error, got unexpected Error %q", err)
   473  				}
   474  				if e, a := c.expected, actual; !reflect.DeepEqual(a, e) {
   475  					t.Errorf("expect %v, got %v", e, a)
   476  				}
   477  			}
   478  		})
   479  	}
   480  }
   481  
   482  func TestBoolCondition(t *testing.T) {
   483  	cases := []struct {
   484  		name         string
   485  		input        ConditionBuilder
   486  		expectedNode exprNode
   487  		err          condErrorMode
   488  	}{
   489  		{
   490  			name:  "basic method and",
   491  			input: Name("foo").Equal(Value(5)).And(Name("bar").Equal(Value("baz"))),
   492  			expectedNode: exprNode{
   493  				children: []exprNode{
   494  					{
   495  						children: []exprNode{
   496  							{
   497  								names:   []string{"foo"},
   498  								fmtExpr: "$n",
   499  							},
   500  							{
   501  								values: []dynamodb.AttributeValue{
   502  									{
   503  										N: aws.String("5"),
   504  									},
   505  								},
   506  								fmtExpr: "$v",
   507  							},
   508  						},
   509  						fmtExpr: "$c = $c",
   510  					},
   511  					{
   512  						children: []exprNode{
   513  							{
   514  								names:   []string{"bar"},
   515  								fmtExpr: "$n",
   516  							},
   517  							{
   518  								values: []dynamodb.AttributeValue{
   519  									{
   520  										S: aws.String("baz"),
   521  									},
   522  								},
   523  								fmtExpr: "$v",
   524  							},
   525  						},
   526  						fmtExpr: "$c = $c",
   527  					},
   528  				},
   529  				fmtExpr: "($c) AND ($c)",
   530  			},
   531  		},
   532  		{
   533  			name:  "basic method or",
   534  			input: Name("foo").Equal(Value(5)).Or(Name("bar").Equal(Value("baz"))),
   535  			expectedNode: exprNode{
   536  				children: []exprNode{
   537  					{
   538  						children: []exprNode{
   539  							{
   540  								names:   []string{"foo"},
   541  								fmtExpr: "$n",
   542  							},
   543  							{
   544  								values: []dynamodb.AttributeValue{
   545  									{
   546  										N: aws.String("5"),
   547  									},
   548  								},
   549  								fmtExpr: "$v",
   550  							},
   551  						},
   552  						fmtExpr: "$c = $c",
   553  					},
   554  					{
   555  						children: []exprNode{
   556  							{
   557  								names:   []string{"bar"},
   558  								fmtExpr: "$n",
   559  							},
   560  							{
   561  								values: []dynamodb.AttributeValue{
   562  									{
   563  										S: aws.String("baz"),
   564  									},
   565  								},
   566  								fmtExpr: "$v",
   567  							},
   568  						},
   569  						fmtExpr: "$c = $c",
   570  					},
   571  				},
   572  				fmtExpr: "($c) OR ($c)",
   573  			},
   574  		},
   575  		{
   576  			name:  "variadic function and",
   577  			input: And(Name("foo").Equal(Value(5)), Name("bar").Equal(Value("baz")), Name("qux").Equal(Value(true))),
   578  			expectedNode: exprNode{
   579  				children: []exprNode{
   580  					{
   581  						children: []exprNode{
   582  							{
   583  								names:   []string{"foo"},
   584  								fmtExpr: "$n",
   585  							},
   586  							{
   587  								values: []dynamodb.AttributeValue{
   588  									{
   589  										N: aws.String("5"),
   590  									},
   591  								},
   592  								fmtExpr: "$v",
   593  							},
   594  						},
   595  						fmtExpr: "$c = $c",
   596  					},
   597  					{
   598  						children: []exprNode{
   599  							{
   600  								names:   []string{"bar"},
   601  								fmtExpr: "$n",
   602  							},
   603  							{
   604  								values: []dynamodb.AttributeValue{
   605  									{
   606  										S: aws.String("baz"),
   607  									},
   608  								},
   609  								fmtExpr: "$v",
   610  							},
   611  						},
   612  						fmtExpr: "$c = $c",
   613  					},
   614  					{
   615  						children: []exprNode{
   616  							{
   617  								names:   []string{"qux"},
   618  								fmtExpr: "$n",
   619  							},
   620  							{
   621  								values: []dynamodb.AttributeValue{
   622  									{
   623  										BOOL: aws.Bool(true),
   624  									},
   625  								},
   626  								fmtExpr: "$v",
   627  							},
   628  						},
   629  						fmtExpr: "$c = $c",
   630  					},
   631  				},
   632  				fmtExpr: "($c) AND ($c) AND ($c)",
   633  			},
   634  		},
   635  		{
   636  			name:  "variadic function or",
   637  			input: Or(Name("foo").Equal(Value(5)), Name("bar").Equal(Value("baz")), Name("qux").Equal(Value(true))),
   638  			expectedNode: exprNode{
   639  				children: []exprNode{
   640  					{
   641  						children: []exprNode{
   642  							{
   643  								names:   []string{"foo"},
   644  								fmtExpr: "$n",
   645  							},
   646  							{
   647  								values: []dynamodb.AttributeValue{
   648  									{
   649  										N: aws.String("5"),
   650  									},
   651  								},
   652  								fmtExpr: "$v",
   653  							},
   654  						},
   655  						fmtExpr: "$c = $c",
   656  					},
   657  					{
   658  						children: []exprNode{
   659  							{
   660  								names:   []string{"bar"},
   661  								fmtExpr: "$n",
   662  							},
   663  							{
   664  								values: []dynamodb.AttributeValue{
   665  									{
   666  										S: aws.String("baz"),
   667  									},
   668  								},
   669  								fmtExpr: "$v",
   670  							},
   671  						},
   672  						fmtExpr: "$c = $c",
   673  					},
   674  					{
   675  						children: []exprNode{
   676  							{
   677  								names:   []string{"qux"},
   678  								fmtExpr: "$n",
   679  							},
   680  							{
   681  								values: []dynamodb.AttributeValue{
   682  									{
   683  										BOOL: aws.Bool(true),
   684  									},
   685  								},
   686  								fmtExpr: "$v",
   687  							},
   688  						},
   689  						fmtExpr: "$c = $c",
   690  					},
   691  				},
   692  				fmtExpr: "($c) OR ($c) OR ($c)",
   693  			},
   694  		},
   695  		{
   696  			name:  "invalid operand error And",
   697  			input: Name("").Size().GreaterThanEqual(Value(5)).And(Name("[5]").Between(Value(3), Value(9))),
   698  			err:   invalidConditionOperand,
   699  		},
   700  		{
   701  			name:  "invalid operand error Or",
   702  			input: Name("").Size().GreaterThanEqual(Value(5)).Or(Name("[5]").Between(Value(3), Value(9))),
   703  			err:   invalidConditionOperand,
   704  		},
   705  	}
   706  
   707  	for _, c := range cases {
   708  		t.Run(c.name, func(t *testing.T) {
   709  			actual, err := c.input.buildTree()
   710  			if c.err != noConditionError {
   711  				if err == nil {
   712  					t.Errorf("expect error %q, got no error", c.err)
   713  				} else {
   714  					if e, a := string(c.err), err.Error(); !strings.Contains(a, e) {
   715  						t.Errorf("expect %q error message to be in %q", e, a)
   716  					}
   717  				}
   718  			} else {
   719  				if err != nil {
   720  					t.Errorf("expect no error, got unexpected Error %q", err)
   721  				}
   722  				if e, a := c.expectedNode, actual; !reflect.DeepEqual(a, e) {
   723  					t.Errorf("expect %v, got %v", e, a)
   724  				}
   725  			}
   726  		})
   727  	}
   728  }
   729  
   730  func TestNotCondition(t *testing.T) {
   731  	cases := []struct {
   732  		name         string
   733  		input        ConditionBuilder
   734  		expectedNode exprNode
   735  		err          condErrorMode
   736  	}{
   737  		{
   738  			name:  "basic method not",
   739  			input: Name("foo").Equal(Value(5)).Not(),
   740  			expectedNode: exprNode{
   741  				children: []exprNode{
   742  					{
   743  						children: []exprNode{
   744  							{
   745  								names:   []string{"foo"},
   746  								fmtExpr: "$n",
   747  							},
   748  							{
   749  								values: []dynamodb.AttributeValue{
   750  									{
   751  										N: aws.String("5"),
   752  									},
   753  								},
   754  								fmtExpr: "$v",
   755  							},
   756  						},
   757  						fmtExpr: "$c = $c",
   758  					},
   759  				},
   760  				fmtExpr: "NOT ($c)",
   761  			},
   762  		},
   763  		{
   764  			name:  "basic function not",
   765  			input: Not(Name("foo").Equal(Value(5))),
   766  			expectedNode: exprNode{
   767  				children: []exprNode{
   768  					{
   769  						children: []exprNode{
   770  							{
   771  								names:   []string{"foo"},
   772  								fmtExpr: "$n",
   773  							},
   774  							{
   775  								values: []dynamodb.AttributeValue{
   776  									{
   777  										N: aws.String("5"),
   778  									},
   779  								},
   780  								fmtExpr: "$v",
   781  							},
   782  						},
   783  						fmtExpr: "$c = $c",
   784  					},
   785  				},
   786  				fmtExpr: "NOT ($c)",
   787  			},
   788  		},
   789  		{
   790  			name:  "invalid operand error not",
   791  			input: Name("").Size().GreaterThanEqual(Value(5)).Or(Name("[5]").Between(Value(3), Value(9))).Not(),
   792  			err:   invalidConditionOperand,
   793  		},
   794  	}
   795  
   796  	for _, c := range cases {
   797  		t.Run(c.name, func(t *testing.T) {
   798  			actual, err := c.input.buildTree()
   799  			if c.err != noConditionError {
   800  				if err == nil {
   801  					t.Errorf("expect error %q, got no error", c.err)
   802  				} else {
   803  					if e, a := string(c.err), err.Error(); !strings.Contains(a, e) {
   804  						t.Errorf("expect %q error message to be in %q", e, a)
   805  					}
   806  				}
   807  			} else {
   808  				if err != nil {
   809  					t.Errorf("expect no error, got unexpected Error %q", err)
   810  				}
   811  				if e, a := c.expectedNode, actual; !reflect.DeepEqual(a, e) {
   812  					t.Errorf("expect %v, got %v", e, a)
   813  				}
   814  			}
   815  		})
   816  	}
   817  }
   818  
   819  func TestBetweenCondition(t *testing.T) {
   820  	cases := []struct {
   821  		name         string
   822  		input        ConditionBuilder
   823  		expectedNode exprNode
   824  		err          condErrorMode
   825  	}{
   826  		{
   827  			name:  "basic method between for name",
   828  			input: Name("foo").Between(Value(5), Value(7)),
   829  			expectedNode: exprNode{
   830  				children: []exprNode{
   831  					{
   832  						names:   []string{"foo"},
   833  						fmtExpr: "$n",
   834  					},
   835  					{
   836  						values: []dynamodb.AttributeValue{
   837  							{
   838  								N: aws.String("5"),
   839  							},
   840  						},
   841  						fmtExpr: "$v",
   842  					},
   843  					{
   844  						values: []dynamodb.AttributeValue{
   845  							{
   846  								N: aws.String("7"),
   847  							},
   848  						},
   849  						fmtExpr: "$v",
   850  					},
   851  				},
   852  				fmtExpr: "$c BETWEEN $c AND $c",
   853  			},
   854  		},
   855  		{
   856  			name:  "basic method between for value",
   857  			input: Value(6).Between(Value(5), Value(7)),
   858  			expectedNode: exprNode{
   859  				children: []exprNode{
   860  					{
   861  						values: []dynamodb.AttributeValue{
   862  							{
   863  								N: aws.String("6"),
   864  							},
   865  						},
   866  						fmtExpr: "$v",
   867  					},
   868  					{
   869  						values: []dynamodb.AttributeValue{
   870  							{
   871  								N: aws.String("5"),
   872  							},
   873  						},
   874  						fmtExpr: "$v",
   875  					},
   876  					{
   877  						values: []dynamodb.AttributeValue{
   878  							{
   879  								N: aws.String("7"),
   880  							},
   881  						},
   882  						fmtExpr: "$v",
   883  					},
   884  				},
   885  				fmtExpr: "$c BETWEEN $c AND $c",
   886  			},
   887  		},
   888  		{
   889  			name:  "basic method between for size",
   890  			input: Name("foo").Size().Between(Value(5), Value(7)),
   891  			expectedNode: exprNode{
   892  				children: []exprNode{
   893  					{
   894  						names:   []string{"foo"},
   895  						fmtExpr: "size ($n)",
   896  					},
   897  					{
   898  						values: []dynamodb.AttributeValue{
   899  							{
   900  								N: aws.String("5"),
   901  							},
   902  						},
   903  						fmtExpr: "$v",
   904  					},
   905  					{
   906  						values: []dynamodb.AttributeValue{
   907  							{
   908  								N: aws.String("7"),
   909  							},
   910  						},
   911  						fmtExpr: "$v",
   912  					},
   913  				},
   914  				fmtExpr: "$c BETWEEN $c AND $c",
   915  			},
   916  		},
   917  		{
   918  			name:  "invalid operand error between",
   919  			input: Name("[5]").Between(Value(3), Name("foo..bar")),
   920  			err:   invalidConditionOperand,
   921  		},
   922  	}
   923  
   924  	for _, c := range cases {
   925  		t.Run(c.name, func(t *testing.T) {
   926  			actual, err := c.input.buildTree()
   927  			if c.err != noConditionError {
   928  				if err == nil {
   929  					t.Errorf("expect error %q, got no error", c.err)
   930  				} else {
   931  					if e, a := string(c.err), err.Error(); !strings.Contains(a, e) {
   932  						t.Errorf("expect %q error message to be in %q", e, a)
   933  					}
   934  				}
   935  			} else {
   936  				if err != nil {
   937  					t.Errorf("expect no error, got unexpected Error %q", err)
   938  				}
   939  				if e, a := c.expectedNode, actual; !reflect.DeepEqual(a, e) {
   940  					t.Errorf("expect %v, got %v", e, a)
   941  				}
   942  			}
   943  		})
   944  	}
   945  }
   946  
   947  func TestInCondition(t *testing.T) {
   948  	cases := []struct {
   949  		name         string
   950  		input        ConditionBuilder
   951  		expectedNode exprNode
   952  		err          condErrorMode
   953  	}{
   954  		{
   955  			name:  "basic method in for name",
   956  			input: Name("foo").In(Value(5), Value(7)),
   957  			expectedNode: exprNode{
   958  				children: []exprNode{
   959  					{
   960  						names:   []string{"foo"},
   961  						fmtExpr: "$n",
   962  					},
   963  					{
   964  						values: []dynamodb.AttributeValue{
   965  							{
   966  								N: aws.String("5"),
   967  							},
   968  						},
   969  						fmtExpr: "$v",
   970  					},
   971  					{
   972  						values: []dynamodb.AttributeValue{
   973  							{
   974  								N: aws.String("7"),
   975  							},
   976  						},
   977  						fmtExpr: "$v",
   978  					},
   979  				},
   980  				fmtExpr: "$c IN ($c, $c)",
   981  			},
   982  		},
   983  		{
   984  			name:  "basic method in for value",
   985  			input: Value(6).In(Value(5), Value(7)),
   986  			expectedNode: exprNode{
   987  				children: []exprNode{
   988  					{
   989  						values: []dynamodb.AttributeValue{
   990  							{
   991  								N: aws.String("6"),
   992  							},
   993  						},
   994  						fmtExpr: "$v",
   995  					},
   996  					{
   997  						values: []dynamodb.AttributeValue{
   998  							{
   999  								N: aws.String("5"),
  1000  							},
  1001  						},
  1002  						fmtExpr: "$v",
  1003  					},
  1004  					{
  1005  						values: []dynamodb.AttributeValue{
  1006  							{
  1007  								N: aws.String("7"),
  1008  							},
  1009  						},
  1010  						fmtExpr: "$v",
  1011  					},
  1012  				},
  1013  				fmtExpr: "$c IN ($c, $c)",
  1014  			},
  1015  		},
  1016  		{
  1017  			name:  "basic method in for size",
  1018  			input: Name("foo").Size().In(Value(5), Value(7)),
  1019  			expectedNode: exprNode{
  1020  				children: []exprNode{
  1021  					{
  1022  						names:   []string{"foo"},
  1023  						fmtExpr: "size ($n)",
  1024  					},
  1025  					{
  1026  						values: []dynamodb.AttributeValue{
  1027  							{
  1028  								N: aws.String("5"),
  1029  							},
  1030  						},
  1031  						fmtExpr: "$v",
  1032  					},
  1033  					{
  1034  						values: []dynamodb.AttributeValue{
  1035  							{
  1036  								N: aws.String("7"),
  1037  							},
  1038  						},
  1039  						fmtExpr: "$v",
  1040  					},
  1041  				},
  1042  				fmtExpr: "$c IN ($c, $c)",
  1043  			},
  1044  		},
  1045  		{
  1046  			name:  "invalid operand error in",
  1047  			input: Name("[5]").In(Value(3), Name("foo..bar")),
  1048  			err:   invalidConditionOperand,
  1049  		},
  1050  	}
  1051  
  1052  	for _, c := range cases {
  1053  		t.Run(c.name, func(t *testing.T) {
  1054  			actual, err := c.input.buildTree()
  1055  			if c.err != noConditionError {
  1056  				if err == nil {
  1057  					t.Errorf("expect error %q, got no error", c.err)
  1058  				} else {
  1059  					if e, a := string(c.err), err.Error(); !strings.Contains(a, e) {
  1060  						t.Errorf("expect %q error message to be in %q", e, a)
  1061  					}
  1062  				}
  1063  			} else {
  1064  				if err != nil {
  1065  					t.Errorf("expect no error, got unexpected Error %q", err)
  1066  				}
  1067  				if e, a := c.expectedNode, actual; !reflect.DeepEqual(a, e) {
  1068  					t.Errorf("expect %v, got %v", e, a)
  1069  				}
  1070  			}
  1071  		})
  1072  	}
  1073  }
  1074  
  1075  func TestAttrExistsCondition(t *testing.T) {
  1076  	cases := []struct {
  1077  		name         string
  1078  		input        ConditionBuilder
  1079  		expectedNode exprNode
  1080  		err          condErrorMode
  1081  	}{
  1082  		{
  1083  			name:  "basic attr exists",
  1084  			input: Name("foo").AttributeExists(),
  1085  			expectedNode: exprNode{
  1086  				children: []exprNode{
  1087  					{
  1088  						names:   []string{"foo"},
  1089  						fmtExpr: "$n",
  1090  					},
  1091  				},
  1092  				fmtExpr: "attribute_exists ($c)",
  1093  			},
  1094  		},
  1095  		{
  1096  			name:  "basic attr not exists",
  1097  			input: Name("foo").AttributeNotExists(),
  1098  			expectedNode: exprNode{
  1099  				children: []exprNode{
  1100  					{
  1101  						names:   []string{"foo"},
  1102  						fmtExpr: "$n",
  1103  					},
  1104  				},
  1105  				fmtExpr: "attribute_not_exists ($c)",
  1106  			},
  1107  		},
  1108  		{
  1109  			name:  "invalid operand error attr exists",
  1110  			input: AttributeExists(Name("")),
  1111  			err:   invalidConditionOperand,
  1112  		},
  1113  		{
  1114  			name:  "invalid operand error attr not exists",
  1115  			input: AttributeNotExists(Name("foo..bar")),
  1116  			err:   invalidConditionOperand,
  1117  		},
  1118  	}
  1119  
  1120  	for _, c := range cases {
  1121  		t.Run(c.name, func(t *testing.T) {
  1122  			actual, err := c.input.buildTree()
  1123  			if c.err != noConditionError {
  1124  				if err == nil {
  1125  					t.Errorf("expect error %q, got no error", c.err)
  1126  				} else {
  1127  					if e, a := string(c.err), err.Error(); !strings.Contains(a, e) {
  1128  						t.Errorf("expect %q error message to be in %q", e, a)
  1129  					}
  1130  				}
  1131  			} else {
  1132  				if err != nil {
  1133  					t.Errorf("expect no error, got unexpected Error %q", err)
  1134  				}
  1135  				if e, a := c.expectedNode, actual; !reflect.DeepEqual(a, e) {
  1136  					t.Errorf("expect %v, got %v", e, a)
  1137  				}
  1138  			}
  1139  		})
  1140  	}
  1141  }
  1142  
  1143  func TestAttrTypeCondition(t *testing.T) {
  1144  	cases := []struct {
  1145  		name         string
  1146  		input        ConditionBuilder
  1147  		expectedNode exprNode
  1148  		err          condErrorMode
  1149  	}{
  1150  		{
  1151  			name:  "attr type String",
  1152  			input: Name("foo").AttributeType(String),
  1153  			expectedNode: exprNode{
  1154  				children: []exprNode{
  1155  					{
  1156  						names:   []string{"foo"},
  1157  						fmtExpr: "$n",
  1158  					},
  1159  					{
  1160  						values: []dynamodb.AttributeValue{
  1161  							{
  1162  								S: aws.String("S"),
  1163  							},
  1164  						},
  1165  						fmtExpr: "$v",
  1166  					},
  1167  				},
  1168  				fmtExpr: "attribute_type ($c, $c)",
  1169  			},
  1170  		},
  1171  		{
  1172  			name:  "attr type String",
  1173  			input: Name("foo").AttributeType(String),
  1174  			expectedNode: exprNode{
  1175  				children: []exprNode{
  1176  					{
  1177  						names:   []string{"foo"},
  1178  						fmtExpr: "$n",
  1179  					},
  1180  					{
  1181  						values: []dynamodb.AttributeValue{
  1182  							{
  1183  								S: aws.String("S"),
  1184  							},
  1185  						},
  1186  						fmtExpr: "$v",
  1187  					},
  1188  				},
  1189  				fmtExpr: "attribute_type ($c, $c)",
  1190  			},
  1191  		},
  1192  		{
  1193  			name:  "attr type StringSet",
  1194  			input: Name("foo").AttributeType(StringSet),
  1195  			expectedNode: exprNode{
  1196  				children: []exprNode{
  1197  					{
  1198  						names:   []string{"foo"},
  1199  						fmtExpr: "$n",
  1200  					},
  1201  					{
  1202  						values: []dynamodb.AttributeValue{
  1203  							{
  1204  								S: aws.String("SS"),
  1205  							},
  1206  						},
  1207  						fmtExpr: "$v",
  1208  					},
  1209  				},
  1210  				fmtExpr: "attribute_type ($c, $c)",
  1211  			},
  1212  		},
  1213  		{
  1214  			name:  "attr type Number",
  1215  			input: Name("foo").AttributeType(Number),
  1216  			expectedNode: exprNode{
  1217  				children: []exprNode{
  1218  					{
  1219  						names:   []string{"foo"},
  1220  						fmtExpr: "$n",
  1221  					},
  1222  					{
  1223  						values: []dynamodb.AttributeValue{
  1224  							{
  1225  								S: aws.String("N"),
  1226  							},
  1227  						},
  1228  						fmtExpr: "$v",
  1229  					},
  1230  				},
  1231  				fmtExpr: "attribute_type ($c, $c)",
  1232  			},
  1233  		},
  1234  		{
  1235  			name:  "attr type NumberSet",
  1236  			input: Name("foo").AttributeType(NumberSet),
  1237  			expectedNode: exprNode{
  1238  				children: []exprNode{
  1239  					{
  1240  						names:   []string{"foo"},
  1241  						fmtExpr: "$n",
  1242  					},
  1243  					{
  1244  						values: []dynamodb.AttributeValue{
  1245  							{
  1246  								S: aws.String("NS"),
  1247  							},
  1248  						},
  1249  						fmtExpr: "$v",
  1250  					},
  1251  				},
  1252  				fmtExpr: "attribute_type ($c, $c)",
  1253  			},
  1254  		},
  1255  		{
  1256  			name:  "attr type Binary",
  1257  			input: Name("foo").AttributeType(Binary),
  1258  			expectedNode: exprNode{
  1259  				children: []exprNode{
  1260  					{
  1261  						names:   []string{"foo"},
  1262  						fmtExpr: "$n",
  1263  					},
  1264  					{
  1265  						values: []dynamodb.AttributeValue{
  1266  							{
  1267  								S: aws.String("B"),
  1268  							},
  1269  						},
  1270  						fmtExpr: "$v",
  1271  					},
  1272  				},
  1273  				fmtExpr: "attribute_type ($c, $c)",
  1274  			},
  1275  		},
  1276  		{
  1277  			name:  "attr type BinarySet",
  1278  			input: Name("foo").AttributeType(BinarySet),
  1279  			expectedNode: exprNode{
  1280  				children: []exprNode{
  1281  					{
  1282  						names:   []string{"foo"},
  1283  						fmtExpr: "$n",
  1284  					},
  1285  					{
  1286  						values: []dynamodb.AttributeValue{
  1287  							{
  1288  								S: aws.String("BS"),
  1289  							},
  1290  						},
  1291  						fmtExpr: "$v",
  1292  					},
  1293  				},
  1294  				fmtExpr: "attribute_type ($c, $c)",
  1295  			},
  1296  		},
  1297  		{
  1298  			name:  "attr type Boolean",
  1299  			input: Name("foo").AttributeType(Boolean),
  1300  			expectedNode: exprNode{
  1301  				children: []exprNode{
  1302  					{
  1303  						names:   []string{"foo"},
  1304  						fmtExpr: "$n",
  1305  					},
  1306  					{
  1307  						values: []dynamodb.AttributeValue{
  1308  							{
  1309  								S: aws.String("BOOL"),
  1310  							},
  1311  						},
  1312  						fmtExpr: "$v",
  1313  					},
  1314  				},
  1315  				fmtExpr: "attribute_type ($c, $c)",
  1316  			},
  1317  		},
  1318  		{
  1319  			name:  "attr type Null",
  1320  			input: Name("foo").AttributeType(Null),
  1321  			expectedNode: exprNode{
  1322  				children: []exprNode{
  1323  					{
  1324  						names:   []string{"foo"},
  1325  						fmtExpr: "$n",
  1326  					},
  1327  					{
  1328  						values: []dynamodb.AttributeValue{
  1329  							{
  1330  								S: aws.String("NULL"),
  1331  							},
  1332  						},
  1333  						fmtExpr: "$v",
  1334  					},
  1335  				},
  1336  				fmtExpr: "attribute_type ($c, $c)",
  1337  			},
  1338  		},
  1339  		{
  1340  			name:  "attr type List",
  1341  			input: Name("foo").AttributeType(List),
  1342  			expectedNode: exprNode{
  1343  				children: []exprNode{
  1344  					{
  1345  						names:   []string{"foo"},
  1346  						fmtExpr: "$n",
  1347  					},
  1348  					{
  1349  						values: []dynamodb.AttributeValue{
  1350  							{
  1351  								S: aws.String("L"),
  1352  							},
  1353  						},
  1354  						fmtExpr: "$v",
  1355  					},
  1356  				},
  1357  				fmtExpr: "attribute_type ($c, $c)",
  1358  			},
  1359  		},
  1360  		{
  1361  			name:  "attr type Map",
  1362  			input: Name("foo").AttributeType(Map),
  1363  			expectedNode: exprNode{
  1364  				children: []exprNode{
  1365  					{
  1366  						names:   []string{"foo"},
  1367  						fmtExpr: "$n",
  1368  					},
  1369  					{
  1370  						values: []dynamodb.AttributeValue{
  1371  							{
  1372  								S: aws.String("M"),
  1373  							},
  1374  						},
  1375  						fmtExpr: "$v",
  1376  					},
  1377  				},
  1378  				fmtExpr: "attribute_type ($c, $c)",
  1379  			},
  1380  		},
  1381  		{
  1382  			name:  "attr type invalid operand",
  1383  			input: Name("").AttributeType(Map),
  1384  			err:   invalidConditionOperand,
  1385  		},
  1386  	}
  1387  
  1388  	for _, c := range cases {
  1389  		t.Run(c.name, func(t *testing.T) {
  1390  			actual, err := c.input.buildTree()
  1391  			if c.err != noConditionError {
  1392  				if err == nil {
  1393  					t.Errorf("expect error %q, got no error", c.err)
  1394  				} else {
  1395  					if e, a := string(c.err), err.Error(); !strings.Contains(a, e) {
  1396  						t.Errorf("expect %q error message to be in %q", e, a)
  1397  					}
  1398  				}
  1399  			} else {
  1400  				if err != nil {
  1401  					t.Errorf("expect no error, got unexpected Error %q", err)
  1402  				}
  1403  				if e, a := c.expectedNode, actual; !reflect.DeepEqual(a, e) {
  1404  					t.Errorf("expect %v, got %v", e, a)
  1405  				}
  1406  			}
  1407  		})
  1408  	}
  1409  }
  1410  
  1411  func TestBeginsWithCondition(t *testing.T) {
  1412  	cases := []struct {
  1413  		name         string
  1414  		input        ConditionBuilder
  1415  		expectedNode exprNode
  1416  		err          condErrorMode
  1417  	}{
  1418  		{
  1419  			name:  "basic begins with",
  1420  			input: Name("foo").BeginsWith("bar"),
  1421  			expectedNode: exprNode{
  1422  				children: []exprNode{
  1423  					{
  1424  						names:   []string{"foo"},
  1425  						fmtExpr: "$n",
  1426  					},
  1427  					{
  1428  						values: []dynamodb.AttributeValue{
  1429  							{
  1430  								S: aws.String("bar"),
  1431  							},
  1432  						},
  1433  						fmtExpr: "$v",
  1434  					},
  1435  				},
  1436  				fmtExpr: "begins_with ($c, $c)",
  1437  			},
  1438  		},
  1439  		{
  1440  			name:  "begins with invalid operand",
  1441  			input: Name("").BeginsWith("bar"),
  1442  			err:   invalidConditionOperand,
  1443  		},
  1444  	}
  1445  
  1446  	for _, c := range cases {
  1447  		t.Run(c.name, func(t *testing.T) {
  1448  			actual, err := c.input.buildTree()
  1449  			if c.err != noConditionError {
  1450  				if err == nil {
  1451  					t.Errorf("expect error %q, got no error", c.err)
  1452  				} else {
  1453  					if e, a := string(c.err), err.Error(); !strings.Contains(a, e) {
  1454  						t.Errorf("expect %q error message to be in %q", e, a)
  1455  					}
  1456  				}
  1457  			} else {
  1458  				if err != nil {
  1459  					t.Errorf("expect no error, got unexpected Error %q", err)
  1460  				}
  1461  				if e, a := c.expectedNode, actual; !reflect.DeepEqual(a, e) {
  1462  					t.Errorf("expect %v, got %v", e, a)
  1463  				}
  1464  			}
  1465  		})
  1466  	}
  1467  }
  1468  
  1469  func TestContainsCondition(t *testing.T) {
  1470  	cases := []struct {
  1471  		name         string
  1472  		input        ConditionBuilder
  1473  		expectedNode exprNode
  1474  		err          condErrorMode
  1475  	}{
  1476  		{
  1477  			name:  "basic contains",
  1478  			input: Name("foo").Contains("bar"),
  1479  			expectedNode: exprNode{
  1480  				children: []exprNode{
  1481  					{
  1482  						names:   []string{"foo"},
  1483  						fmtExpr: "$n",
  1484  					},
  1485  					{
  1486  						values: []dynamodb.AttributeValue{
  1487  							{
  1488  								S: aws.String("bar"),
  1489  							},
  1490  						},
  1491  						fmtExpr: "$v",
  1492  					},
  1493  				},
  1494  				fmtExpr: "contains ($c, $c)",
  1495  			},
  1496  		},
  1497  		{
  1498  			name:  "contains invalid operand",
  1499  			input: Name("").Contains("bar"),
  1500  			err:   invalidConditionOperand,
  1501  		},
  1502  	}
  1503  
  1504  	for _, c := range cases {
  1505  		t.Run(c.name, func(t *testing.T) {
  1506  			actual, err := c.input.buildTree()
  1507  			if c.err != noConditionError {
  1508  				if err == nil {
  1509  					t.Errorf("expect error %q, got no error", c.err)
  1510  				} else {
  1511  					if e, a := string(c.err), err.Error(); !strings.Contains(a, e) {
  1512  						t.Errorf("expect %q error message to be in %q", e, a)
  1513  					}
  1514  				}
  1515  			} else {
  1516  				if err != nil {
  1517  					t.Errorf("expect no error, got unexpected Error %q", err)
  1518  				}
  1519  				if e, a := c.expectedNode, actual; !reflect.DeepEqual(a, e) {
  1520  					t.Errorf("expect %v, got %v", e, a)
  1521  				}
  1522  			}
  1523  		})
  1524  	}
  1525  }
  1526  
  1527  func TestCompoundBuildCondition(t *testing.T) {
  1528  	cases := []struct {
  1529  		name      string
  1530  		inputCond ConditionBuilder
  1531  		expected  string
  1532  	}{
  1533  		{
  1534  			name: "and",
  1535  			inputCond: ConditionBuilder{
  1536  				conditionList: []ConditionBuilder{
  1537  					{},
  1538  					{},
  1539  					{},
  1540  					{},
  1541  				},
  1542  				mode: andCond,
  1543  			},
  1544  			expected: "($c) AND ($c) AND ($c) AND ($c)",
  1545  		},
  1546  		{
  1547  			name: "or",
  1548  			inputCond: ConditionBuilder{
  1549  				conditionList: []ConditionBuilder{
  1550  					{},
  1551  					{},
  1552  					{},
  1553  					{},
  1554  					{},
  1555  					{},
  1556  					{},
  1557  				},
  1558  				mode: orCond,
  1559  			},
  1560  			expected: "($c) OR ($c) OR ($c) OR ($c) OR ($c) OR ($c) OR ($c)",
  1561  		},
  1562  	}
  1563  
  1564  	for _, c := range cases {
  1565  		t.Run(c.name, func(t *testing.T) {
  1566  			en, err := compoundBuildCondition(c.inputCond, exprNode{})
  1567  			if err != nil {
  1568  				t.Errorf("expect no error, got unexpected Error %q", err)
  1569  			}
  1570  
  1571  			if e, a := c.expected, en.fmtExpr; !reflect.DeepEqual(a, e) {
  1572  				t.Errorf("expect %v, got %v", e, a)
  1573  			}
  1574  		})
  1575  	}
  1576  }
  1577  
  1578  func TestInBuildCondition(t *testing.T) {
  1579  	cases := []struct {
  1580  		name      string
  1581  		inputCond ConditionBuilder
  1582  		expected  string
  1583  	}{
  1584  		{
  1585  			name: "in",
  1586  			inputCond: ConditionBuilder{
  1587  				operandList: []OperandBuilder{
  1588  					NameBuilder{},
  1589  					NameBuilder{},
  1590  					NameBuilder{},
  1591  					NameBuilder{},
  1592  					NameBuilder{},
  1593  					NameBuilder{},
  1594  					NameBuilder{},
  1595  				},
  1596  				mode: andCond,
  1597  			},
  1598  			expected: "$c IN ($c, $c, $c, $c, $c, $c)",
  1599  		},
  1600  	}
  1601  
  1602  	for _, c := range cases {
  1603  		t.Run(c.name, func(t *testing.T) {
  1604  			en, err := inBuildCondition(c.inputCond, exprNode{})
  1605  			if err != nil {
  1606  				t.Errorf("expect no error, got unexpected Error %q", err)
  1607  			}
  1608  
  1609  			if e, a := c.expected, en.fmtExpr; !reflect.DeepEqual(a, e) {
  1610  				t.Errorf("expect %v, got %v", e, a)
  1611  			}
  1612  		})
  1613  	}
  1614  }
  1615  
  1616  // If there is time implement mapEquals