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