github.com/aavshr/aws-sdk-go@v1.41.3/service/dynamodb/expression/key_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  // keyCondErrorMode will help with error cases and checking error types
    16  type keyCondErrorMode string
    17  
    18  const (
    19  	noKeyConditionError keyCondErrorMode = ""
    20  	// unsetKeyCondition error will occur when buildTree() is called on an empty
    21  	// KeyConditionBuilder
    22  	unsetKeyCondition = "unset parameter: KeyConditionBuilder"
    23  	// invalidKeyConditionOperand error will occur when an invalid OperandBuilder is used as
    24  	// an argument
    25  	invalidKeyConditionOperand = "BuildOperand error"
    26  	// invalidKeyConditionFormat error will occur when the first key condition is not an equal
    27  	// clause or if more then one And condition is provided
    28  	invalidKeyConditionFormat = "buildKeyCondition error: invalid key condition constructed"
    29  )
    30  
    31  func TestKeyCompare(t *testing.T) {
    32  	cases := []struct {
    33  		name         string
    34  		input        KeyConditionBuilder
    35  		expectedNode exprNode
    36  		err          keyCondErrorMode
    37  	}{
    38  		{
    39  			name:  "key equal",
    40  			input: Key("foo").Equal(Value(5)),
    41  			expectedNode: exprNode{
    42  				children: []exprNode{
    43  					{
    44  						names:   []string{"foo"},
    45  						fmtExpr: "$n",
    46  					},
    47  					{
    48  						values: []dynamodb.AttributeValue{
    49  							{
    50  								N: aws.String("5"),
    51  							},
    52  						},
    53  						fmtExpr: "$v",
    54  					},
    55  				},
    56  				fmtExpr: "$c = $c",
    57  			},
    58  		},
    59  		{
    60  			name:  "key less than",
    61  			input: Key("foo").LessThan(Value(5)),
    62  			expectedNode: exprNode{
    63  				children: []exprNode{
    64  					{
    65  						names:   []string{"foo"},
    66  						fmtExpr: "$n",
    67  					},
    68  					{
    69  						values: []dynamodb.AttributeValue{
    70  							{
    71  								N: aws.String("5"),
    72  							},
    73  						},
    74  						fmtExpr: "$v",
    75  					},
    76  				},
    77  				fmtExpr: "$c < $c",
    78  			},
    79  		},
    80  		{
    81  			name:  "key less than equal",
    82  			input: Key("foo").LessThanEqual(Value(5)),
    83  			expectedNode: exprNode{
    84  				children: []exprNode{
    85  					{
    86  						names:   []string{"foo"},
    87  						fmtExpr: "$n",
    88  					},
    89  					{
    90  						values: []dynamodb.AttributeValue{
    91  							{
    92  								N: aws.String("5"),
    93  							},
    94  						},
    95  						fmtExpr: "$v",
    96  					},
    97  				},
    98  				fmtExpr: "$c <= $c",
    99  			},
   100  		},
   101  		{
   102  			name:  "key greater than",
   103  			input: Key("foo").GreaterThan(Value(5)),
   104  			expectedNode: exprNode{
   105  				children: []exprNode{
   106  					{
   107  						names:   []string{"foo"},
   108  						fmtExpr: "$n",
   109  					},
   110  					{
   111  						values: []dynamodb.AttributeValue{
   112  							{
   113  								N: aws.String("5"),
   114  							},
   115  						},
   116  						fmtExpr: "$v",
   117  					},
   118  				},
   119  				fmtExpr: "$c > $c",
   120  			},
   121  		},
   122  		{
   123  			name:  "key greater than equal",
   124  			input: Key("foo").GreaterThanEqual(Value(5)),
   125  			expectedNode: exprNode{
   126  				children: []exprNode{
   127  					{
   128  						names:   []string{"foo"},
   129  						fmtExpr: "$n",
   130  					},
   131  					{
   132  						values: []dynamodb.AttributeValue{
   133  							{
   134  								N: aws.String("5"),
   135  							},
   136  						},
   137  						fmtExpr: "$v",
   138  					},
   139  				},
   140  				fmtExpr: "$c >= $c",
   141  			},
   142  		},
   143  		{
   144  			name:  "unset KeyConditionBuilder",
   145  			input: KeyConditionBuilder{},
   146  			err:   unsetKeyCondition,
   147  		},
   148  	}
   149  	for _, c := range cases {
   150  		t.Run(c.name, func(t *testing.T) {
   151  			actual, err := c.input.buildTree()
   152  			if c.err != noKeyConditionError {
   153  				if err == nil {
   154  					t.Errorf("expect error %q, got no error", c.err)
   155  				} else {
   156  					if e, a := string(c.err), err.Error(); !strings.Contains(a, e) {
   157  						t.Errorf("expect %q error message to be in %q", e, a)
   158  					}
   159  				}
   160  			} else {
   161  				if err != nil {
   162  					t.Errorf("expect no error, got unexpected Error %q", err)
   163  				}
   164  
   165  				if e, a := c.expectedNode, actual; !reflect.DeepEqual(a, e) {
   166  					t.Errorf("expect %v, got %v", e, a)
   167  				}
   168  			}
   169  		})
   170  	}
   171  }
   172  
   173  func TestKeyBetween(t *testing.T) {
   174  	cases := []struct {
   175  		name         string
   176  		input        KeyConditionBuilder
   177  		expectedNode exprNode
   178  		err          keyCondErrorMode
   179  	}{
   180  		{
   181  			name:  "key between",
   182  			input: Key("foo").Between(Value(5), Value(10)),
   183  			expectedNode: exprNode{
   184  				children: []exprNode{
   185  					{
   186  						names:   []string{"foo"},
   187  						fmtExpr: "$n",
   188  					},
   189  					{
   190  						values: []dynamodb.AttributeValue{
   191  							{
   192  								N: aws.String("5"),
   193  							},
   194  						},
   195  						fmtExpr: "$v",
   196  					},
   197  					{
   198  						values: []dynamodb.AttributeValue{
   199  							{
   200  								N: aws.String("10"),
   201  							},
   202  						},
   203  						fmtExpr: "$v",
   204  					},
   205  				},
   206  				fmtExpr: "$c BETWEEN $c AND $c",
   207  			},
   208  		},
   209  	}
   210  	for _, c := range cases {
   211  		t.Run(c.name, func(t *testing.T) {
   212  			actual, err := c.input.buildTree()
   213  			if c.err != noKeyConditionError {
   214  				if err == nil {
   215  					t.Errorf("expect error %q, got no error", c.err)
   216  				} else {
   217  					if e, a := string(c.err), err.Error(); !strings.Contains(a, e) {
   218  						t.Errorf("expect %q error message to be in %q", e, a)
   219  					}
   220  				}
   221  			} else {
   222  				if err != nil {
   223  					t.Errorf("expect no error, got unexpected Error %q", err)
   224  				}
   225  
   226  				if e, a := c.expectedNode, actual; !reflect.DeepEqual(a, e) {
   227  					t.Errorf("expect %v, got %v", e, a)
   228  				}
   229  			}
   230  		})
   231  	}
   232  }
   233  
   234  func TestKeyBeginsWith(t *testing.T) {
   235  	cases := []struct {
   236  		name         string
   237  		input        KeyConditionBuilder
   238  		expectedNode exprNode
   239  		err          keyCondErrorMode
   240  	}{
   241  		{
   242  			name:  "key begins with",
   243  			input: Key("foo").BeginsWith("bar"),
   244  			expectedNode: exprNode{
   245  				children: []exprNode{
   246  					{
   247  						names:   []string{"foo"},
   248  						fmtExpr: "$n",
   249  					},
   250  					{
   251  						values: []dynamodb.AttributeValue{
   252  							{
   253  								S: aws.String("bar"),
   254  							},
   255  						},
   256  						fmtExpr: "$v",
   257  					},
   258  				},
   259  				fmtExpr: "begins_with ($c, $c)",
   260  			},
   261  		},
   262  	}
   263  	for _, c := range cases {
   264  		t.Run(c.name, func(t *testing.T) {
   265  			actual, err := c.input.buildTree()
   266  			if c.err != noKeyConditionError {
   267  				if err == nil {
   268  					t.Errorf("expect error %q, got no error", c.err)
   269  				} else {
   270  					if e, a := string(c.err), err.Error(); !strings.Contains(a, e) {
   271  						t.Errorf("expect %q error message to be in %q", e, a)
   272  					}
   273  				}
   274  			} else {
   275  				if err != nil {
   276  					t.Errorf("expect no error, got unexpected Error %q", err)
   277  				}
   278  
   279  				if e, a := c.expectedNode, actual; !reflect.DeepEqual(a, e) {
   280  					t.Errorf("expect %v, got %v", e, a)
   281  				}
   282  			}
   283  		})
   284  	}
   285  }
   286  
   287  func TestKeyAnd(t *testing.T) {
   288  	cases := []struct {
   289  		name         string
   290  		input        KeyConditionBuilder
   291  		expectedNode exprNode
   292  		err          keyCondErrorMode
   293  	}{
   294  		{
   295  			name:  "key and",
   296  			input: Key("foo").Equal(Value(5)).And(Key("bar").BeginsWith("baz")),
   297  			expectedNode: exprNode{
   298  				children: []exprNode{
   299  					{
   300  						children: []exprNode{
   301  							{
   302  								names:   []string{"foo"},
   303  								fmtExpr: "$n",
   304  							},
   305  							{
   306  								values: []dynamodb.AttributeValue{
   307  									{
   308  										N: aws.String("5"),
   309  									},
   310  								},
   311  								fmtExpr: "$v",
   312  							},
   313  						},
   314  						fmtExpr: "$c = $c",
   315  					},
   316  					{
   317  						children: []exprNode{
   318  							{
   319  								names:   []string{"bar"},
   320  								fmtExpr: "$n",
   321  							},
   322  							{
   323  								values: []dynamodb.AttributeValue{
   324  									{
   325  										S: aws.String("baz"),
   326  									},
   327  								},
   328  								fmtExpr: "$v",
   329  							},
   330  						},
   331  						fmtExpr: "begins_with ($c, $c)",
   332  					},
   333  				},
   334  				fmtExpr: "($c) AND ($c)",
   335  			},
   336  		},
   337  		{
   338  			name:  "first condition is not equal",
   339  			input: Key("foo").LessThan(Value(5)).And(Key("bar").BeginsWith("baz")),
   340  			err:   invalidKeyConditionFormat,
   341  		},
   342  		{
   343  			name:  "more then one condition on key",
   344  			input: Key("foo").Equal(Value(5)).And(Key("bar").Equal(Value(1)).And(Key("baz").BeginsWith("yar"))),
   345  			err:   invalidKeyConditionFormat,
   346  		},
   347  		{
   348  			name:  "operand error",
   349  			input: Key("").Equal(Value("yikes")),
   350  			err:   invalidKeyConditionOperand,
   351  		},
   352  	}
   353  	for _, c := range cases {
   354  		t.Run(c.name, func(t *testing.T) {
   355  			actual, err := c.input.buildTree()
   356  			if c.err != noKeyConditionError {
   357  				if err == nil {
   358  					t.Errorf("expect error %q, got no error", c.err)
   359  				} else {
   360  					if e, a := string(c.err), err.Error(); !strings.Contains(a, e) {
   361  						t.Errorf("expect %q error message to be in %q", e, a)
   362  					}
   363  				}
   364  			} else {
   365  				if err != nil {
   366  					t.Errorf("expect no error, got unexpected Error %q", err)
   367  				}
   368  
   369  				if e, a := c.expectedNode, actual; !reflect.DeepEqual(a, e) {
   370  					t.Errorf("expect %v, got %v", e, a)
   371  				}
   372  			}
   373  		})
   374  	}
   375  }
   376  
   377  func TestKeyConditionBuildChildNodes(t *testing.T) {
   378  	cases := []struct {
   379  		name     string
   380  		input    KeyConditionBuilder
   381  		expected []exprNode
   382  		err      keyCondErrorMode
   383  	}{
   384  		{
   385  			name:  "build child nodes",
   386  			input: Key("foo").Equal(Value("bar")).And(Key("baz").LessThan(Value(10))),
   387  			expected: []exprNode{
   388  				{
   389  					children: []exprNode{
   390  						{
   391  							names:   []string{"foo"},
   392  							fmtExpr: "$n",
   393  						},
   394  						{
   395  							values: []dynamodb.AttributeValue{
   396  								{
   397  									S: aws.String("bar"),
   398  								},
   399  							},
   400  							fmtExpr: "$v",
   401  						},
   402  					},
   403  					fmtExpr: "$c = $c",
   404  				},
   405  				{
   406  					children: []exprNode{
   407  						{
   408  							names:   []string{"baz"},
   409  							fmtExpr: "$n",
   410  						},
   411  						{
   412  							values: []dynamodb.AttributeValue{
   413  								{
   414  									N: aws.String("10"),
   415  								},
   416  							},
   417  							fmtExpr: "$v",
   418  						},
   419  					},
   420  					fmtExpr: "$c < $c",
   421  				},
   422  			},
   423  		},
   424  	}
   425  	for _, c := range cases {
   426  		t.Run(c.name, func(t *testing.T) {
   427  			actual, err := c.input.buildChildNodes()
   428  			if c.err != noKeyConditionError {
   429  				if err == nil {
   430  					t.Errorf("expect error %q, got no error", c.err)
   431  				} else {
   432  					if e, a := string(c.err), err.Error(); !strings.Contains(a, e) {
   433  						t.Errorf("expect %q error message to be in %q", e, a)
   434  					}
   435  				}
   436  			} else {
   437  				if err != nil {
   438  					t.Errorf("expect no error, got unexpected Error %q", err)
   439  				}
   440  
   441  				if e, a := c.expected, actual; !reflect.DeepEqual(a, e) {
   442  					t.Errorf("expect %#v, got %#v", e, a)
   443  				}
   444  			}
   445  		})
   446  	}
   447  }