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 }