github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/message/error_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 "fmt" 21 "net" 22 "testing" 23 24 "github.com/stretchr/testify/assert" 25 26 "github.com/datastax/go-cassandra-native-protocol/primitive" 27 ) 28 29 func TestServerError_DeepCopy(t *testing.T) { 30 msg := &ServerError{ 31 ErrorMessage: "msg", 32 } 33 cloned := msg.DeepCopy() 34 assert.Equal(t, msg, cloned) 35 cloned.ErrorMessage = "alt msg" 36 assert.NotEqual(t, msg, cloned) 37 assert.Equal(t, "msg", msg.ErrorMessage) 38 assert.Equal(t, "alt msg", cloned.ErrorMessage) 39 } 40 41 func TestProtocolError_DeepCopy(t *testing.T) { 42 msg := &ProtocolError{ 43 ErrorMessage: "msg", 44 } 45 cloned := msg.DeepCopy() 46 assert.Equal(t, msg, cloned) 47 cloned.ErrorMessage = "alt msg" 48 assert.NotEqual(t, msg, cloned) 49 assert.Equal(t, "msg", msg.ErrorMessage) 50 assert.Equal(t, "alt msg", cloned.ErrorMessage) 51 } 52 53 func TestAuthenticationError_DeepCopy(t *testing.T) { 54 msg := &AuthenticationError{ 55 ErrorMessage: "msg", 56 } 57 cloned := msg.DeepCopy() 58 assert.Equal(t, msg, cloned) 59 cloned.ErrorMessage = "alt msg" 60 assert.NotEqual(t, msg, cloned) 61 assert.Equal(t, "msg", msg.ErrorMessage) 62 assert.Equal(t, "alt msg", cloned.ErrorMessage) 63 } 64 65 func TestOverloaded_DeepCopy(t *testing.T) { 66 msg := &Overloaded{ 67 ErrorMessage: "msg", 68 } 69 cloned := msg.DeepCopy() 70 assert.Equal(t, msg, cloned) 71 cloned.ErrorMessage = "alt msg" 72 assert.NotEqual(t, msg, cloned) 73 assert.Equal(t, "msg", msg.ErrorMessage) 74 assert.Equal(t, "alt msg", cloned.ErrorMessage) 75 } 76 77 func TestIsBootstrapping_DeepCopy(t *testing.T) { 78 msg := &IsBootstrapping{ 79 ErrorMessage: "msg", 80 } 81 cloned := msg.DeepCopy() 82 assert.Equal(t, msg, cloned) 83 cloned.ErrorMessage = "alt msg" 84 assert.NotEqual(t, msg, cloned) 85 assert.Equal(t, "msg", msg.ErrorMessage) 86 assert.Equal(t, "alt msg", cloned.ErrorMessage) 87 } 88 89 func TestTruncateError_DeepCopy(t *testing.T) { 90 msg := &TruncateError{ 91 ErrorMessage: "msg", 92 } 93 cloned := msg.DeepCopy() 94 assert.Equal(t, msg, cloned) 95 cloned.ErrorMessage = "alt msg" 96 assert.NotEqual(t, msg, cloned) 97 assert.Equal(t, "msg", msg.ErrorMessage) 98 assert.Equal(t, "alt msg", cloned.ErrorMessage) 99 } 100 101 func TestSyntaxError_DeepCopy(t *testing.T) { 102 msg := &SyntaxError{ 103 ErrorMessage: "msg", 104 } 105 cloned := msg.DeepCopy() 106 assert.Equal(t, msg, cloned) 107 cloned.ErrorMessage = "alt msg" 108 assert.NotEqual(t, msg, cloned) 109 assert.Equal(t, "msg", msg.ErrorMessage) 110 assert.Equal(t, "alt msg", cloned.ErrorMessage) 111 } 112 113 func TestUnauthorized_DeepCopy(t *testing.T) { 114 msg := &Unauthorized{ 115 ErrorMessage: "msg", 116 } 117 cloned := msg.DeepCopy() 118 assert.Equal(t, msg, cloned) 119 cloned.ErrorMessage = "alt msg" 120 assert.NotEqual(t, msg, cloned) 121 assert.Equal(t, "msg", msg.ErrorMessage) 122 assert.Equal(t, "alt msg", cloned.ErrorMessage) 123 } 124 125 func TestInvalid_DeepCopy(t *testing.T) { 126 msg := &Invalid{ 127 ErrorMessage: "msg", 128 } 129 cloned := msg.DeepCopy() 130 assert.Equal(t, msg, cloned) 131 cloned.ErrorMessage = "alt msg" 132 assert.NotEqual(t, msg, cloned) 133 assert.Equal(t, "msg", msg.ErrorMessage) 134 assert.Equal(t, "alt msg", cloned.ErrorMessage) 135 } 136 137 func TestConfigError_DeepCopy(t *testing.T) { 138 msg := &ConfigError{ 139 ErrorMessage: "msg", 140 } 141 cloned := msg.DeepCopy() 142 assert.Equal(t, msg, cloned) 143 cloned.ErrorMessage = "alt msg" 144 assert.NotEqual(t, msg, cloned) 145 assert.Equal(t, "msg", msg.ErrorMessage) 146 assert.Equal(t, "alt msg", cloned.ErrorMessage) 147 } 148 149 func TestUnavailable_DeepCopy(t *testing.T) { 150 msg := &Unavailable{ 151 ErrorMessage: "msg", 152 Consistency: primitive.ConsistencyLevelAll, 153 Required: 2, 154 Alive: 1, 155 } 156 cloned := msg.DeepCopy() 157 assert.Equal(t, msg, cloned) 158 cloned.ErrorMessage = "alt msg" 159 cloned.Consistency = primitive.ConsistencyLevelEachQuorum 160 cloned.Required = 3 161 cloned.Alive = 2 162 assert.NotEqual(t, msg, cloned) 163 assert.Equal(t, "msg", msg.ErrorMessage) 164 assert.Equal(t, primitive.ConsistencyLevelAll, msg.Consistency) 165 assert.EqualValues(t, 2, msg.Required) 166 assert.EqualValues(t, 1, msg.Alive) 167 assert.Equal(t, "alt msg", cloned.ErrorMessage) 168 assert.Equal(t, primitive.ConsistencyLevelEachQuorum, cloned.Consistency) 169 assert.EqualValues(t, 3, cloned.Required) 170 assert.EqualValues(t, 2, cloned.Alive) 171 } 172 173 func TestReadTimeout_DeepCopy(t *testing.T) { 174 msg := &ReadTimeout{ 175 ErrorMessage: "msg", 176 Consistency: primitive.ConsistencyLevelAll, 177 Received: 3, 178 BlockFor: 4, 179 DataPresent: false, 180 } 181 cloned := msg.DeepCopy() 182 assert.Equal(t, msg, cloned) 183 cloned.ErrorMessage = "alt msg" 184 cloned.Consistency = primitive.ConsistencyLevelEachQuorum 185 cloned.Received = 2 186 cloned.BlockFor = 3 187 cloned.DataPresent = true 188 assert.NotEqual(t, msg, cloned) 189 assert.Equal(t, "msg", msg.ErrorMessage) 190 assert.Equal(t, primitive.ConsistencyLevelAll, msg.Consistency) 191 assert.EqualValues(t, 3, msg.Received) 192 assert.EqualValues(t, 4, msg.BlockFor) 193 assert.False(t, msg.DataPresent) 194 assert.Equal(t, "alt msg", cloned.ErrorMessage) 195 assert.Equal(t, primitive.ConsistencyLevelEachQuorum, cloned.Consistency) 196 assert.EqualValues(t, 2, cloned.Received) 197 assert.EqualValues(t, 3, cloned.BlockFor) 198 assert.True(t, cloned.DataPresent) 199 } 200 201 func TestWriteTimeout_DeepCopy(t *testing.T) { 202 msg := &WriteTimeout{ 203 ErrorMessage: "msg", 204 Consistency: primitive.ConsistencyLevelAll, 205 Received: 5, 206 BlockFor: 6, 207 WriteType: primitive.WriteTypeBatch, 208 } 209 cloned := msg.DeepCopy() 210 assert.Equal(t, msg, cloned) 211 cloned.ErrorMessage = "alt msg" 212 cloned.Consistency = primitive.ConsistencyLevelEachQuorum 213 cloned.Received = 2 214 cloned.BlockFor = 3 215 cloned.WriteType = primitive.WriteTypeBatchLog 216 assert.NotEqual(t, msg, cloned) 217 assert.Equal(t, "msg", msg.ErrorMessage) 218 assert.Equal(t, primitive.ConsistencyLevelAll, msg.Consistency) 219 assert.EqualValues(t, 5, msg.Received) 220 assert.EqualValues(t, 6, msg.BlockFor) 221 assert.Equal(t, primitive.WriteTypeBatch, msg.WriteType) 222 assert.Equal(t, "alt msg", cloned.ErrorMessage) 223 assert.Equal(t, primitive.ConsistencyLevelEachQuorum, cloned.Consistency) 224 assert.EqualValues(t, 2, cloned.Received) 225 assert.EqualValues(t, 3, cloned.BlockFor) 226 assert.Equal(t, primitive.WriteTypeBatchLog, cloned.WriteType) 227 } 228 229 func TestReadFailure_DeepCopy(t *testing.T) { 230 msg := &ReadFailure{ 231 ErrorMessage: "msg", 232 Consistency: primitive.ConsistencyLevelAll, 233 Received: 1, 234 BlockFor: 2, 235 NumFailures: 1, 236 FailureReasons: []*primitive.FailureReason{ 237 { 238 Endpoint: net.IP{0x01}, 239 Code: primitive.FailureCodeCdcSpaceFull, 240 }, 241 { 242 Endpoint: net.IP{0x02}, 243 Code: primitive.FailureCodeCounterWrite, 244 }, 245 }, 246 DataPresent: false, 247 } 248 cloned := msg.DeepCopy() 249 assert.Equal(t, msg, cloned) 250 cloned.ErrorMessage = "alt msg" 251 cloned.Consistency = primitive.ConsistencyLevelEachQuorum 252 cloned.Received = 2 253 cloned.BlockFor = 3 254 cloned.NumFailures = 2 255 cloned.FailureReasons = []*primitive.FailureReason{ 256 { 257 Endpoint: net.IP{0x05}, 258 Code: primitive.FailureCodeIndexNotAvailable, 259 }, 260 { 261 Endpoint: net.IP{0x06}, 262 Code: primitive.FailureCodeKeyspaceNotFound, 263 }, 264 } 265 cloned.DataPresent = true 266 assert.NotEqual(t, msg, cloned) 267 assert.Equal(t, "msg", msg.ErrorMessage) 268 assert.Equal(t, primitive.ConsistencyLevelAll, msg.Consistency) 269 assert.EqualValues(t, 1, msg.Received) 270 assert.EqualValues(t, 2, msg.BlockFor) 271 assert.EqualValues(t, 1, msg.NumFailures) 272 assert.Equal(t, net.IP{0x01}, msg.FailureReasons[0].Endpoint) 273 assert.Equal(t, primitive.FailureCodeCdcSpaceFull, msg.FailureReasons[0].Code) 274 assert.Equal(t, net.IP{0x02}, msg.FailureReasons[1].Endpoint) 275 assert.Equal(t, primitive.FailureCodeCounterWrite, msg.FailureReasons[1].Code) 276 assert.False(t, msg.DataPresent) 277 assert.Equal(t, "alt msg", cloned.ErrorMessage) 278 assert.Equal(t, primitive.ConsistencyLevelEachQuorum, cloned.Consistency) 279 assert.EqualValues(t, 2, cloned.Received) 280 assert.EqualValues(t, 3, cloned.BlockFor) 281 assert.EqualValues(t, 2, cloned.NumFailures) 282 assert.Equal(t, net.IP{0x05}, cloned.FailureReasons[0].Endpoint) 283 assert.Equal(t, primitive.FailureCodeIndexNotAvailable, cloned.FailureReasons[0].Code) 284 assert.Equal(t, net.IP{0x06}, cloned.FailureReasons[1].Endpoint) 285 assert.Equal(t, primitive.FailureCodeKeyspaceNotFound, cloned.FailureReasons[1].Code) 286 assert.True(t, cloned.DataPresent) 287 } 288 289 func TestWriteFailure_DeepCopy(t *testing.T) { 290 msg := &WriteFailure{ 291 ErrorMessage: "msg", 292 Consistency: primitive.ConsistencyLevelAll, 293 Received: 1, 294 BlockFor: 2, 295 NumFailures: 1, 296 FailureReasons: []*primitive.FailureReason{ 297 { 298 Endpoint: net.IP{0x01}, 299 Code: primitive.FailureCodeCdcSpaceFull, 300 }, 301 { 302 Endpoint: net.IP{0x02}, 303 Code: primitive.FailureCodeCounterWrite, 304 }, 305 }, 306 WriteType: primitive.WriteTypeBatchLog, 307 } 308 cloned := msg.DeepCopy() 309 assert.Equal(t, msg, cloned) 310 cloned.ErrorMessage = "alt msg" 311 cloned.Consistency = primitive.ConsistencyLevelEachQuorum 312 cloned.Received = 2 313 cloned.BlockFor = 3 314 cloned.NumFailures = 2 315 cloned.FailureReasons = []*primitive.FailureReason{ 316 { 317 Endpoint: net.IP{0x05}, 318 Code: primitive.FailureCodeIndexNotAvailable, 319 }, 320 { 321 Endpoint: net.IP{0x06}, 322 Code: primitive.FailureCodeKeyspaceNotFound, 323 }, 324 } 325 cloned.WriteType = primitive.WriteTypeCdc 326 assert.NotEqual(t, msg, cloned) 327 assert.Equal(t, "msg", msg.ErrorMessage) 328 assert.Equal(t, primitive.ConsistencyLevelAll, msg.Consistency) 329 assert.EqualValues(t, 1, msg.Received) 330 assert.EqualValues(t, 2, msg.BlockFor) 331 assert.EqualValues(t, 1, msg.NumFailures) 332 assert.Equal(t, net.IP{0x01}, msg.FailureReasons[0].Endpoint) 333 assert.Equal(t, primitive.FailureCodeCdcSpaceFull, msg.FailureReasons[0].Code) 334 assert.Equal(t, net.IP{0x02}, msg.FailureReasons[1].Endpoint) 335 assert.Equal(t, primitive.FailureCodeCounterWrite, msg.FailureReasons[1].Code) 336 assert.Equal(t, primitive.WriteTypeBatchLog, msg.WriteType) 337 assert.Equal(t, "alt msg", cloned.ErrorMessage) 338 assert.Equal(t, primitive.ConsistencyLevelEachQuorum, cloned.Consistency) 339 assert.EqualValues(t, 2, cloned.Received) 340 assert.EqualValues(t, 3, cloned.BlockFor) 341 assert.EqualValues(t, 2, cloned.NumFailures) 342 assert.Equal(t, net.IP{0x05}, cloned.FailureReasons[0].Endpoint) 343 assert.Equal(t, primitive.FailureCodeIndexNotAvailable, cloned.FailureReasons[0].Code) 344 assert.Equal(t, net.IP{0x06}, cloned.FailureReasons[1].Endpoint) 345 assert.Equal(t, primitive.FailureCodeKeyspaceNotFound, cloned.FailureReasons[1].Code) 346 assert.Equal(t, primitive.WriteTypeCdc, cloned.WriteType) 347 } 348 349 func TestFunctionFailure_DeepCopy(t *testing.T) { 350 msg := &FunctionFailure{ 351 ErrorMessage: "msg", 352 Keyspace: "ks1", 353 Function: "f1", 354 Arguments: []string{"arg1", "arg2"}, 355 } 356 cloned := msg.DeepCopy() 357 assert.Equal(t, msg, cloned) 358 cloned.ErrorMessage = "alt msg" 359 cloned.Keyspace = "ks2" 360 cloned.Function = "f2" 361 cloned.Arguments = []string{"arg3"} 362 assert.NotEqual(t, msg, cloned) 363 assert.Equal(t, "msg", msg.ErrorMessage) 364 assert.Equal(t, "ks1", msg.Keyspace) 365 assert.Equal(t, "f1", msg.Function) 366 assert.Equal(t, []string{"arg1", "arg2"}, msg.Arguments) 367 assert.Equal(t, "alt msg", cloned.ErrorMessage) 368 assert.Equal(t, "ks2", cloned.Keyspace) 369 assert.Equal(t, "f2", cloned.Function) 370 assert.Equal(t, []string{"arg3"}, cloned.Arguments) 371 } 372 373 func TestUnprepared_DeepCopy(t *testing.T) { 374 msg := &Unprepared{ 375 ErrorMessage: "msg", 376 Id: []byte{0x01}, 377 } 378 cloned := msg.DeepCopy() 379 assert.Equal(t, msg, cloned) 380 cloned.ErrorMessage = "alt msg" 381 cloned.Id = []byte{0x02, 0x03} 382 assert.NotEqual(t, msg, cloned) 383 assert.Equal(t, "msg", msg.ErrorMessage) 384 assert.Equal(t, []byte{0x01}, msg.Id) 385 assert.Equal(t, "alt msg", cloned.ErrorMessage) 386 assert.Equal(t, []byte{0x02, 0x03}, cloned.Id) 387 } 388 389 func TestAlreadyExists_DeepCopy(t *testing.T) { 390 msg := &AlreadyExists{ 391 ErrorMessage: "msg", 392 Keyspace: "ks1", 393 Table: "table1", 394 } 395 cloned := msg.DeepCopy() 396 assert.Equal(t, msg, cloned) 397 cloned.ErrorMessage = "alt msg" 398 cloned.Keyspace = "ks2" 399 cloned.Table = "table2" 400 assert.NotEqual(t, msg, cloned) 401 assert.Equal(t, "msg", msg.ErrorMessage) 402 assert.Equal(t, "ks1", msg.Keyspace) 403 assert.Equal(t, "table1", msg.Table) 404 assert.Equal(t, "alt msg", cloned.ErrorMessage) 405 assert.Equal(t, "ks2", cloned.Keyspace) 406 assert.Equal(t, "table2", cloned.Table) 407 } 408 409 func TestErrorCodec_Encode(test *testing.T) { 410 codec := &errorCodec{} 411 // errors encoded the same in all versions 412 for _, version := range primitive.SupportedProtocolVersions() { 413 test.Run(version.String(), func(test *testing.T) { 414 tests := []encodeTestCase{ 415 { 416 "server error", 417 &ServerError{"BOOM"}, 418 []byte{ 419 0, 0, 0, 0, // error code 420 0, 4, B, O, O, M, 421 }, 422 nil, 423 }, 424 { 425 "protocol error", 426 &ProtocolError{"BOOM"}, 427 []byte{ 428 0, 0, 0, 10, // error code 429 0, 4, B, O, O, M, 430 }, 431 nil, 432 }, 433 { 434 "authentication error", 435 &AuthenticationError{"BOOM"}, 436 []byte{ 437 0, 0, 1, 0, // error code 438 0, 4, B, O, O, M, 439 }, 440 nil, 441 }, 442 { 443 "overloaded error", 444 &Overloaded{"BOOM"}, 445 []byte{ 446 0, 0, 0b_0001_0000, 0b_0000_0001, 447 0, 4, B, O, O, M, 448 }, 449 nil, 450 }, 451 { 452 "is bootstrapping error", 453 &IsBootstrapping{"BOOM"}, 454 []byte{ 455 0, 0, 0b_0001_0000, 0b_0000_0010, 456 0, 4, B, O, O, M, 457 }, 458 nil, 459 }, 460 { 461 "truncate error", 462 &TruncateError{"BOOM"}, 463 []byte{ 464 0, 0, 0b_0001_0000, 0b_0000_0011, 465 0, 4, B, O, O, M, 466 }, 467 nil, 468 }, 469 { 470 "syntax error", 471 &SyntaxError{"BOOM"}, 472 []byte{ 473 0, 0, 0b_0010_0000, 0b_0000_0000, 474 0, 4, B, O, O, M, 475 }, 476 nil, 477 }, 478 { 479 "unauthorized error", 480 &Unauthorized{"BOOM"}, 481 []byte{ 482 0, 0, 0b_0010_0001, 0b_0000_0000, 483 0, 4, B, O, O, M, 484 }, 485 nil, 486 }, 487 { 488 "invalid error", 489 &Invalid{"BOOM"}, 490 []byte{ 491 0, 0, 0b_0010_0010, 0b_0000_0000, 492 0, 4, B, O, O, M, 493 }, 494 nil, 495 }, 496 { 497 "config error", 498 &ConfigError{"BOOM"}, 499 []byte{ 500 0, 0, 0b_0010_0011, 0b_0000_0000, 501 0, 4, B, O, O, M, 502 }, 503 nil, 504 }, 505 { 506 "unavailable", 507 &Unavailable{"BOOM", primitive.ConsistencyLevelLocalQuorum, 3, 2}, 508 []byte{ 509 0, 0, 0b_0001_0000, 0b_0000_0000, 510 0, 4, B, O, O, M, 511 0, 6, // consistency 512 0, 0, 0, 3, 513 0, 0, 0, 2, 514 }, 515 nil, 516 }, 517 { 518 "read timeout", 519 &ReadTimeout{"BOOM", primitive.ConsistencyLevelLocalQuorum, 1, 2, true}, 520 []byte{ 521 0, 0, 0b_0001_0010, 0b_0000_0000, 522 0, 4, B, O, O, M, 523 0, 6, // consistency 524 0, 0, 0, 1, 525 0, 0, 0, 2, 526 1, // data present 527 }, 528 nil, 529 }, 530 { 531 "write timeout", 532 &WriteTimeout{"BOOM", primitive.ConsistencyLevelLocalQuorum, 1, 2, primitive.WriteTypeBatchLog, 0}, 533 []byte{ 534 0, 0, 0b_0001_0001, 0b_0000_0000, 535 0, 4, B, O, O, M, 536 0, 6, // consistency 537 0, 0, 0, 1, 538 0, 0, 0, 2, 539 0, 9, B, A, T, C, H, __, L, O, G, 540 }, 541 nil, 542 }, 543 { 544 "function failure", 545 &FunctionFailure{"BOOM", "ks1", "func1", []string{"int", "varchar"}}, 546 []byte{ 547 0, 0, 0b_0001_0100, 0b_0000_0000, 548 0, 4, B, O, O, M, 549 0, 3, k, s, _1, 550 0, 5, f, u, n, c, _1, 551 0, 2, 552 0, 3, i, n, t, 553 0, 7, v, a, r, c, h, a, r, 554 }, 555 nil, 556 }, 557 { 558 "already exists", 559 &AlreadyExists{"BOOM", "ks1", "table1"}, 560 []byte{ 561 0, 0, 0b_0010_0100, 0b_0000_0000, 562 0, 4, B, O, O, M, 563 0, 3, k, s, _1, 564 0, 6, t, a, b, l, e, _1, 565 }, 566 nil, 567 }, 568 { 569 "unprepared", 570 &Unprepared{"BOOM", []byte{1, 2, 3, 4}}, 571 []byte{ 572 0, 0, 0b_0010_0101, 0b_0000_0000, 573 0, 4, B, O, O, M, 574 0, 4, 1, 2, 3, 4, 575 }, 576 nil, 577 }, 578 } 579 for _, tt := range tests { 580 test.Run(tt.name, func(t *testing.T) { 581 dest := &bytes.Buffer{} 582 err := codec.Encode(tt.input, dest, version) 583 assert.Equal(t, tt.expected, dest.Bytes()) 584 assert.Equal(t, tt.err, err) 585 }) 586 } 587 }) 588 } 589 // num failures v2, v3, v4 590 for _, version := range primitive.SupportedProtocolVersionsLesserThanOrEqualTo(primitive.ProtocolVersion4) { 591 test.Run(fmt.Sprintf("read/write failure version %v", version), func(test *testing.T) { 592 tests := []encodeTestCase{ 593 { 594 "read failure", 595 &ReadFailure{ 596 "BOOM", 597 primitive.ConsistencyLevelLocalQuorum, 598 0, 599 2, 600 1, 601 nil, 602 false, 603 }, 604 []byte{ 605 0, 0, 0b_0001_0011, 0b_0000_0000, 606 0, 4, B, O, O, M, 607 0, 6, // consistency 608 0, 0, 0, 0, 609 0, 0, 0, 2, 610 0, 0, 0, 1, 611 0, // data present 612 }, 613 nil, 614 }, 615 { 616 "write failure", 617 &WriteFailure{ 618 "BOOM", 619 primitive.ConsistencyLevelLocalQuorum, 620 0, 621 2, 622 1, 623 nil, 624 primitive.WriteTypeBatchLog, 625 }, 626 []byte{ 627 0, 0, 0b_0001_0101, 0b_0000_0000, 628 0, 4, B, O, O, M, 629 0, 6, // consistency 630 0, 0, 0, 0, 631 0, 0, 0, 2, 632 0, 0, 0, 1, 633 0, 9, B, A, T, C, H, __, L, O, G, 634 }, 635 nil, 636 }, 637 } 638 for _, tt := range tests { 639 test.Run(tt.name, func(t *testing.T) { 640 dest := &bytes.Buffer{} 641 err := codec.Encode(tt.input, dest, version) 642 assert.Equal(t, tt.expected, dest.Bytes()) 643 assert.Equal(t, tt.err, err) 644 }) 645 } 646 }) 647 } 648 // reason map in v5, DSE v1, DSE v2 649 for _, version := range primitive.SupportedProtocolVersionsGreaterThanOrEqualTo(primitive.ProtocolVersion5) { 650 test.Run(fmt.Sprintf("read/write failure version %v", version), func(test *testing.T) { 651 tests := []encodeTestCase{ 652 { 653 "read failure", 654 &ReadFailure{ 655 "BOOM", 656 primitive.ConsistencyLevelLocalQuorum, 657 0, 658 2, 659 0, 660 []*primitive.FailureReason{{net.IPv4(192, 168, 1, 1), primitive.FailureCodeTooManyTombstonesRead}}, 661 false, 662 }, 663 []byte{ 664 0, 0, 0b_0001_0011, 0b_0000_0000, 665 0, 4, B, O, O, M, 666 0, 6, // consistency 667 0, 0, 0, 0, 668 0, 0, 0, 2, 669 0, 0, 0, 1, // map length 670 4, 192, 168, 1, 1, // map key 671 0, 1, // map value (reason code) 672 0, // data present 673 }, 674 nil, 675 }, 676 { 677 "write failure", 678 &WriteFailure{ 679 "BOOM", 680 primitive.ConsistencyLevelLocalQuorum, 681 0, 682 2, 683 0, 684 []*primitive.FailureReason{{net.IPv4(192, 168, 1, 1), primitive.FailureCodeTooManyTombstonesRead}}, 685 primitive.WriteTypeBatchLog, 686 }, 687 []byte{ 688 0, 0, 0b_0001_0101, 0b_0000_0000, 689 0, 4, B, O, O, M, 690 0, 6, // consistency 691 0, 0, 0, 0, 692 0, 0, 0, 2, 693 0, 0, 0, 1, // map length 694 4, 192, 168, 1, 1, // map key 695 0, 1, // map value (reason code) 696 0, 9, B, A, T, C, H, __, L, O, G, 697 }, 698 nil, 699 }, 700 } 701 for _, tt := range tests { 702 test.Run(tt.name, func(t *testing.T) { 703 dest := &bytes.Buffer{} 704 err := codec.Encode(tt.input, dest, version) 705 assert.Equal(t, tt.expected, dest.Bytes()) 706 assert.Equal(t, tt.err, err) 707 }) 708 } 709 }) 710 } 711 // write timeout with contentions in v5 712 test.Run(fmt.Sprintf("write timeout with contentions version %v", primitive.ProtocolVersion5), func(test *testing.T) { 713 tests := []encodeTestCase{ 714 { 715 "write timeout CAS with contentions", 716 &WriteTimeout{"BOOM", primitive.ConsistencyLevelLocalQuorum, 1, 2, primitive.WriteTypeCas, 5}, 717 []byte{ 718 0, 0, 0b_0001_0001, 0b_0000_0000, 719 0, 4, B, O, O, M, 720 0, 6, // consistency 721 0, 0, 0, 1, 722 0, 0, 0, 2, 723 0, 3, C, A, S, 724 0, 5, 725 }, 726 nil, 727 }, 728 { 729 "write timeout not CAS", 730 &WriteTimeout{"BOOM", primitive.ConsistencyLevelLocalQuorum, 1, 2, primitive.WriteTypeBatchLog, 5}, 731 []byte{ 732 0, 0, 0b_0001_0001, 0b_0000_0000, 733 0, 4, B, O, O, M, 734 0, 6, // consistency 735 0, 0, 0, 1, 736 0, 0, 0, 2, 737 0, 9, B, A, T, C, H, __, L, O, G, 738 }, 739 nil, 740 }, 741 } 742 for _, tt := range tests { 743 test.Run(tt.name, func(t *testing.T) { 744 dest := &bytes.Buffer{} 745 err := codec.Encode(tt.input, dest, primitive.ProtocolVersion5) 746 assert.Equal(t, tt.expected, dest.Bytes()) 747 assert.Equal(t, tt.err, err) 748 }) 749 } 750 }) 751 } 752 753 func TestErrorCodec_EncodedLength(test *testing.T) { 754 codec := &errorCodec{} 755 // errors encoded the same in all versions 756 for _, version := range primitive.SupportedProtocolVersions() { 757 test.Run(version.String(), func(test *testing.T) { 758 tests := []encodedLengthTestCase{ 759 { 760 "server error", 761 &ServerError{"BOOM"}, 762 primitive.LengthOfInt + primitive.LengthOfString("BOOM"), 763 nil, 764 }, 765 { 766 "protocol error", 767 &ProtocolError{"BOOM"}, 768 primitive.LengthOfInt + primitive.LengthOfString("BOOM"), 769 nil, 770 }, 771 { 772 "authentication error", 773 &AuthenticationError{"BOOM"}, 774 primitive.LengthOfInt + primitive.LengthOfString("BOOM"), 775 nil, 776 }, 777 { 778 "overloaded error", 779 &Overloaded{"BOOM"}, 780 primitive.LengthOfInt + primitive.LengthOfString("BOOM"), 781 nil, 782 }, 783 { 784 "is bootstrapping error", 785 &IsBootstrapping{"BOOM"}, 786 primitive.LengthOfInt + primitive.LengthOfString("BOOM"), 787 nil, 788 }, 789 { 790 "truncate error", 791 &TruncateError{"BOOM"}, 792 primitive.LengthOfInt + primitive.LengthOfString("BOOM"), 793 nil, 794 }, 795 { 796 "syntax error", 797 &SyntaxError{"BOOM"}, 798 primitive.LengthOfInt + primitive.LengthOfString("BOOM"), 799 nil, 800 }, 801 { 802 "unauthorized error", 803 &Unauthorized{"BOOM"}, 804 primitive.LengthOfInt + primitive.LengthOfString("BOOM"), 805 nil, 806 }, 807 { 808 "invalid error", 809 &Invalid{"BOOM"}, 810 primitive.LengthOfInt + primitive.LengthOfString("BOOM"), 811 nil, 812 }, 813 { 814 "config error", 815 &ConfigError{"BOOM"}, 816 primitive.LengthOfInt + primitive.LengthOfString("BOOM"), 817 nil, 818 }, 819 { 820 "unavailable", 821 &Unavailable{"BOOM", primitive.ConsistencyLevelLocalQuorum, 3, 2}, 822 primitive.LengthOfInt + 823 primitive.LengthOfString("BOOM") + 824 primitive.LengthOfShort + // consistency 825 primitive.LengthOfInt + // required 826 primitive.LengthOfInt, // alive 827 nil, 828 }, 829 { 830 "read timeout", 831 &ReadTimeout{"BOOM", primitive.ConsistencyLevelLocalQuorum, 1, 2, true}, 832 primitive.LengthOfInt + 833 primitive.LengthOfString("BOOM") + 834 primitive.LengthOfShort + // consistency 835 primitive.LengthOfInt + // received 836 primitive.LengthOfInt + // block for 837 primitive.LengthOfByte, // data present 838 nil, 839 }, 840 { 841 "write timeout", 842 &WriteTimeout{"BOOM", primitive.ConsistencyLevelLocalQuorum, 1, 2, primitive.WriteTypeBatchLog, 0}, 843 primitive.LengthOfInt + 844 primitive.LengthOfString("BOOM") + 845 primitive.LengthOfShort + // consistency 846 primitive.LengthOfInt + // received 847 primitive.LengthOfInt + // block for 848 primitive.LengthOfString(string(primitive.WriteTypeBatchLog)), // write type 849 nil, 850 }, 851 { 852 "function failure", 853 &FunctionFailure{"BOOM", "ks1", "func1", []string{"int", "varchar"}}, 854 primitive.LengthOfInt + 855 primitive.LengthOfString("BOOM") + 856 primitive.LengthOfString("ks1") + // keyspace 857 primitive.LengthOfString("func1") + // function 858 primitive.LengthOfStringList([]string{"int", "varchar"}), // arguments 859 nil, 860 }, 861 { 862 "already exists", 863 &AlreadyExists{"BOOM", "ks1", "table1"}, 864 primitive.LengthOfInt + 865 primitive.LengthOfString("BOOM") + 866 primitive.LengthOfString("ks1") + // keyspace 867 primitive.LengthOfString("table1"), // table 868 nil, 869 }, 870 { 871 "unprepared", 872 &Unprepared{"BOOM", []byte{1, 2, 3, 4}}, 873 primitive.LengthOfInt + 874 primitive.LengthOfString("BOOM") + 875 primitive.LengthOfShortBytes([]byte{1, 2, 3, 4}), 876 nil, 877 }, 878 } 879 for _, tt := range tests { 880 test.Run(tt.name, func(t *testing.T) { 881 actual, err := codec.EncodedLength(tt.input, version) 882 assert.Equal(t, tt.expected, actual) 883 assert.Equal(t, tt.err, err) 884 }) 885 } 886 }) 887 } 888 // num failures in v2, v3, v4 889 for _, version := range primitive.SupportedProtocolVersionsLesserThanOrEqualTo(primitive.ProtocolVersion4) { 890 test.Run(fmt.Sprintf("read/write failure version %v", version), func(test *testing.T) { 891 tests := []encodedLengthTestCase{ 892 { 893 "read failure", 894 &ReadFailure{ 895 "BOOM", 896 primitive.ConsistencyLevelLocalQuorum, 897 0, 898 2, 899 1, 900 nil, 901 false, 902 }, 903 primitive.LengthOfInt + 904 primitive.LengthOfString("BOOM") + 905 primitive.LengthOfShort + // consistency 906 primitive.LengthOfInt + // received 907 primitive.LengthOfInt + // block for 908 primitive.LengthOfInt + // num failures 909 primitive.LengthOfByte, // data present 910 nil, 911 }, 912 { 913 "write failure", 914 &WriteFailure{ 915 "BOOM", 916 primitive.ConsistencyLevelLocalQuorum, 917 0, 918 2, 919 1, 920 nil, 921 primitive.WriteTypeBatchLog, 922 }, 923 primitive.LengthOfInt + 924 primitive.LengthOfString("BOOM") + 925 primitive.LengthOfShort + // consistency 926 primitive.LengthOfInt + // received 927 primitive.LengthOfInt + // block for 928 primitive.LengthOfInt + // num failures 929 primitive.LengthOfString(string(primitive.WriteTypeBatchLog)), // write type 930 nil, 931 }, 932 } 933 for _, tt := range tests { 934 test.Run(tt.name, func(t *testing.T) { 935 actual, err := codec.EncodedLength(tt.input, version) 936 assert.Equal(t, tt.expected, actual) 937 assert.Equal(t, tt.err, err) 938 }) 939 } 940 }) 941 } 942 // reason map in v5, DSE v1, DSE v2 943 for _, version := range primitive.SupportedProtocolVersionsGreaterThanOrEqualTo(primitive.ProtocolVersion5) { 944 test.Run(fmt.Sprintf("read/write failure version %v", version), func(test *testing.T) { 945 tests := []encodedLengthTestCase{ 946 { 947 "read failure", 948 &ReadFailure{ 949 "BOOM", 950 primitive.ConsistencyLevelLocalQuorum, 951 0, 952 2, 953 0, 954 []*primitive.FailureReason{{net.IPv4(192, 168, 1, 1), primitive.FailureCodeTooManyTombstonesRead}}, 955 false, 956 }, 957 primitive.LengthOfInt + 958 primitive.LengthOfString("BOOM") + 959 primitive.LengthOfShort + // consistency 960 primitive.LengthOfInt + // received 961 primitive.LengthOfInt + // block for 962 primitive.LengthOfInt + // map length 963 primitive.LengthOfByte + net.IPv4len + // map key length 964 primitive.LengthOfShort + // map value length (reason code) 965 primitive.LengthOfByte, // data present 966 nil, 967 }, 968 { 969 "write failure", 970 &WriteFailure{ 971 "BOOM", 972 primitive.ConsistencyLevelLocalQuorum, 973 0, 974 2, 975 0, 976 []*primitive.FailureReason{{net.IPv4(192, 168, 1, 1), primitive.FailureCodeTooManyTombstonesRead}}, 977 primitive.WriteTypeBatchLog, 978 }, 979 primitive.LengthOfInt + 980 primitive.LengthOfString("BOOM") + 981 primitive.LengthOfShort + // consistency 982 primitive.LengthOfInt + // received 983 primitive.LengthOfInt + // block for 984 primitive.LengthOfInt + // map length 985 primitive.LengthOfByte + net.IPv4len + // map key length 986 primitive.LengthOfShort + // map value length (reason code) 987 primitive.LengthOfString(string(primitive.WriteTypeBatchLog)), // write type 988 nil, 989 }, 990 } 991 for _, tt := range tests { 992 test.Run(tt.name, func(t *testing.T) { 993 actual, err := codec.EncodedLength(tt.input, version) 994 assert.Equal(t, tt.expected, actual) 995 assert.Equal(t, tt.err, err) 996 }) 997 } 998 }) 999 } 1000 // write timeout with contentions in v5 1001 test.Run(fmt.Sprintf("write timeout with contentions version %v", primitive.ProtocolVersion5), func(test *testing.T) { 1002 tests := []encodedLengthTestCase{ 1003 { 1004 "write timeout CAS with contentions", 1005 &WriteTimeout{"BOOM", primitive.ConsistencyLevelLocalQuorum, 1, 2, primitive.WriteTypeCas, 5}, 1006 primitive.LengthOfInt + 1007 primitive.LengthOfString("BOOM") + 1008 primitive.LengthOfShort + // consistency 1009 primitive.LengthOfInt + // received 1010 primitive.LengthOfInt + // block for 1011 primitive.LengthOfString(string(primitive.WriteTypeCas)) + // write type 1012 primitive.LengthOfShort, // contentions 1013 nil, 1014 }, 1015 } 1016 for _, tt := range tests { 1017 test.Run(tt.name, func(t *testing.T) { 1018 actual, err := codec.EncodedLength(tt.input, primitive.ProtocolVersion5) 1019 assert.Equal(t, tt.expected, actual) 1020 assert.Equal(t, tt.err, err) 1021 }) 1022 } 1023 }) 1024 } 1025 1026 func TestErrorCodec_Decode(test *testing.T) { 1027 codec := &errorCodec{} 1028 // errors encoded the same in all versions 1029 for _, version := range primitive.SupportedProtocolVersions() { 1030 test.Run(version.String(), func(test *testing.T) { 1031 tests := []decodeTestCase{ 1032 { 1033 "server error", 1034 []byte{ 1035 0, 0, 0, 0, // error code 1036 0, 4, B, O, O, M, 1037 }, 1038 &ServerError{"BOOM"}, 1039 nil, 1040 }, 1041 { 1042 "protocol error", 1043 []byte{ 1044 0, 0, 0, 10, // error code 1045 0, 4, B, O, O, M, 1046 }, 1047 &ProtocolError{"BOOM"}, 1048 nil, 1049 }, 1050 { 1051 "authentication error", 1052 []byte{ 1053 0, 0, 1, 0, // error code 1054 0, 4, B, O, O, M, 1055 }, 1056 &AuthenticationError{"BOOM"}, 1057 nil, 1058 }, 1059 { 1060 "overloaded error", 1061 []byte{ 1062 0, 0, 0b_0001_0000, 0b_0000_0001, 1063 0, 4, B, O, O, M, 1064 }, 1065 &Overloaded{"BOOM"}, 1066 nil, 1067 }, 1068 { 1069 "is bootstrapping error", 1070 []byte{ 1071 0, 0, 0b_0001_0000, 0b_0000_0010, 1072 0, 4, B, O, O, M, 1073 }, 1074 &IsBootstrapping{"BOOM"}, 1075 nil, 1076 }, 1077 { 1078 "truncate error", 1079 []byte{ 1080 0, 0, 0b_0001_0000, 0b_0000_0011, 1081 0, 4, B, O, O, M, 1082 }, 1083 &TruncateError{"BOOM"}, 1084 nil, 1085 }, 1086 { 1087 "syntax error", 1088 []byte{ 1089 0, 0, 0b_0010_0000, 0b_0000_0000, 1090 0, 4, B, O, O, M, 1091 }, 1092 &SyntaxError{"BOOM"}, 1093 nil, 1094 }, 1095 { 1096 "unauthorized error", 1097 []byte{ 1098 0, 0, 0b_0010_0001, 0b_0000_0000, 1099 0, 4, B, O, O, M, 1100 }, 1101 &Unauthorized{"BOOM"}, 1102 nil, 1103 }, 1104 { 1105 "invalid error", 1106 []byte{ 1107 0, 0, 0b_0010_0010, 0b_0000_0000, 1108 0, 4, B, O, O, M, 1109 }, 1110 &Invalid{"BOOM"}, 1111 nil, 1112 }, 1113 { 1114 "config error", 1115 []byte{ 1116 0, 0, 0b_0010_0011, 0b_0000_0000, 1117 0, 4, B, O, O, M, 1118 }, 1119 &ConfigError{"BOOM"}, 1120 nil, 1121 }, 1122 { 1123 "unavailable", 1124 []byte{ 1125 0, 0, 0b_0001_0000, 0b_0000_0000, 1126 0, 4, B, O, O, M, 1127 0, 6, // consistency 1128 0, 0, 0, 3, 1129 0, 0, 0, 2, 1130 }, 1131 &Unavailable{"BOOM", primitive.ConsistencyLevelLocalQuorum, 3, 2}, 1132 nil, 1133 }, 1134 { 1135 "read timeout", 1136 []byte{ 1137 0, 0, 0b_0001_0010, 0b_0000_0000, 1138 0, 4, B, O, O, M, 1139 0, 6, // consistency 1140 0, 0, 0, 1, 1141 0, 0, 0, 2, 1142 1, // data present 1143 }, 1144 &ReadTimeout{"BOOM", primitive.ConsistencyLevelLocalQuorum, 1, 2, true}, 1145 nil, 1146 }, 1147 { 1148 "write timeout", 1149 []byte{ 1150 0, 0, 0b_0001_0001, 0b_0000_0000, 1151 0, 4, B, O, O, M, 1152 0, 6, // consistency 1153 0, 0, 0, 1, 1154 0, 0, 0, 2, 1155 0, 9, B, A, T, C, H, __, L, O, G, 1156 }, 1157 &WriteTimeout{"BOOM", primitive.ConsistencyLevelLocalQuorum, 1, 2, primitive.WriteTypeBatchLog, 0}, 1158 nil, 1159 }, 1160 { 1161 "function failure", 1162 []byte{ 1163 0, 0, 0b_0001_0100, 0b_0000_0000, 1164 0, 4, B, O, O, M, 1165 0, 3, k, s, _1, 1166 0, 5, f, u, n, c, _1, 1167 0, 2, 1168 0, 3, i, n, t, 1169 0, 7, v, a, r, c, h, a, r, 1170 }, 1171 &FunctionFailure{"BOOM", "ks1", "func1", []string{"int", "varchar"}}, 1172 nil, 1173 }, 1174 { 1175 "already exists", 1176 []byte{ 1177 0, 0, 0b_0010_0100, 0b_0000_0000, 1178 0, 4, B, O, O, M, 1179 0, 3, k, s, _1, 1180 0, 6, t, a, b, l, e, _1, 1181 }, 1182 &AlreadyExists{"BOOM", "ks1", "table1"}, 1183 nil, 1184 }, 1185 { 1186 "unprepared", 1187 []byte{ 1188 0, 0, 0b_0010_0101, 0b_0000_0000, 1189 0, 4, B, O, O, M, 1190 0, 4, 1, 2, 3, 4, 1191 }, 1192 &Unprepared{"BOOM", []byte{1, 2, 3, 4}}, 1193 nil, 1194 }, 1195 } 1196 for _, tt := range tests { 1197 test.Run(tt.name, func(t *testing.T) { 1198 source := bytes.NewBuffer(tt.input) 1199 actual, err := codec.Decode(source, version) 1200 assert.Equal(t, tt.expected, actual) 1201 assert.Equal(t, tt.err, err) 1202 }) 1203 } 1204 }) 1205 } 1206 // num failures in v3, v4 1207 for _, version := range primitive.SupportedProtocolVersionsLesserThanOrEqualTo(primitive.ProtocolVersion4) { 1208 test.Run(fmt.Sprintf("read/write failure version %v", version), func(test *testing.T) { 1209 tests := []decodeTestCase{ 1210 { 1211 "read failure", 1212 []byte{ 1213 0, 0, 0b_0001_0011, 0b_0000_0000, 1214 0, 4, B, O, O, M, 1215 0, 6, // consistency 1216 0, 0, 0, 0, 1217 0, 0, 0, 2, 1218 0, 0, 0, 1, 1219 0, // data present 1220 }, 1221 &ReadFailure{ 1222 "BOOM", 1223 primitive.ConsistencyLevelLocalQuorum, 1224 0, 1225 2, 1226 1, 1227 nil, 1228 false, 1229 }, 1230 nil, 1231 }, 1232 { 1233 "write failure", 1234 []byte{ 1235 0, 0, 0b_0001_0101, 0b_0000_0000, 1236 0, 4, B, O, O, M, 1237 0, 6, // consistency 1238 0, 0, 0, 0, 1239 0, 0, 0, 2, 1240 0, 0, 0, 1, 1241 0, 9, B, A, T, C, H, __, L, O, G, 1242 }, 1243 &WriteFailure{ 1244 "BOOM", 1245 primitive.ConsistencyLevelLocalQuorum, 1246 0, 1247 2, 1248 1, 1249 nil, 1250 primitive.WriteTypeBatchLog, 1251 }, 1252 nil, 1253 }, 1254 } 1255 for _, tt := range tests { 1256 test.Run(tt.name, func(t *testing.T) { 1257 source := bytes.NewBuffer(tt.input) 1258 actual, err := codec.Decode(source, version) 1259 assert.Equal(t, tt.expected, actual) 1260 assert.Equal(t, tt.err, err) 1261 }) 1262 } 1263 }) 1264 } 1265 // reason map in v5, DSE v1, DSE v2 1266 for _, version := range primitive.SupportedProtocolVersionsGreaterThanOrEqualTo(primitive.ProtocolVersion5) { 1267 test.Run(fmt.Sprintf("read/write failure version %v", version), func(test *testing.T) { 1268 tests := []decodeTestCase{ 1269 { 1270 "read failure", 1271 []byte{ 1272 0, 0, 0b_0001_0011, 0b_0000_0000, 1273 0, 4, B, O, O, M, 1274 0, 6, // consistency 1275 0, 0, 0, 0, 1276 0, 0, 0, 2, 1277 0, 0, 0, 1, // map length 1278 4, 192, 168, 1, 1, // map key 1279 0, 1, // map value (reason code) 1280 0, // data present 1281 }, 1282 &ReadFailure{ 1283 "BOOM", 1284 primitive.ConsistencyLevelLocalQuorum, 1285 0, 1286 2, 1287 0, 1288 []*primitive.FailureReason{{net.IPv4(192, 168, 1, 1), primitive.FailureCodeTooManyTombstonesRead}}, 1289 false, 1290 }, 1291 nil, 1292 }, 1293 { 1294 "write failure", 1295 []byte{ 1296 0, 0, 0b_0001_0101, 0b_0000_0000, 1297 0, 4, B, O, O, M, 1298 0, 6, // consistency 1299 0, 0, 0, 0, 1300 0, 0, 0, 2, 1301 0, 0, 0, 1, // map length 1302 4, 192, 168, 1, 1, // map key 1303 0, 1, // map value (reason code) 1304 0, 9, B, A, T, C, H, __, L, O, G, 1305 }, 1306 &WriteFailure{ 1307 "BOOM", 1308 primitive.ConsistencyLevelLocalQuorum, 1309 0, 1310 2, 1311 0, 1312 []*primitive.FailureReason{{net.IPv4(192, 168, 1, 1), primitive.FailureCodeTooManyTombstonesRead}}, 1313 primitive.WriteTypeBatchLog, 1314 }, 1315 nil, 1316 }, 1317 } 1318 for _, tt := range tests { 1319 test.Run(tt.name, func(t *testing.T) { 1320 source := bytes.NewBuffer(tt.input) 1321 actual, err := codec.Decode(source, version) 1322 assert.Equal(t, tt.expected, actual) 1323 assert.Equal(t, tt.err, err) 1324 }) 1325 } 1326 }) 1327 } 1328 // write timeout with contentions in v5 1329 test.Run(fmt.Sprintf("write timeout wiht contentions version %v", primitive.ProtocolVersion5), func(test *testing.T) { 1330 tests := []decodeTestCase{ 1331 { 1332 "write timeout CAS with contentions", 1333 []byte{ 1334 0, 0, 0b_0001_0001, 0b_0000_0000, 1335 0, 4, B, O, O, M, 1336 0, 6, // consistency 1337 0, 0, 0, 1, 1338 0, 0, 0, 2, 1339 0, 3, C, A, S, 1340 0, 5, 1341 }, 1342 &WriteTimeout{"BOOM", primitive.ConsistencyLevelLocalQuorum, 1, 2, primitive.WriteTypeCas, 5}, 1343 nil, 1344 }, 1345 { 1346 "write timeout not CAS", 1347 []byte{ 1348 0, 0, 0b_0001_0001, 0b_0000_0000, 1349 0, 4, B, O, O, M, 1350 0, 6, // consistency 1351 0, 0, 0, 1, 1352 0, 0, 0, 2, 1353 0, 9, B, A, T, C, H, __, L, O, G, 1354 }, 1355 &WriteTimeout{"BOOM", primitive.ConsistencyLevelLocalQuorum, 1, 2, primitive.WriteTypeBatchLog, 0}, 1356 nil, 1357 }, 1358 { 1359 "write timeout CAS missing contentions", 1360 []byte{ 1361 0, 0, 0b_0001_0001, 0b_0000_0000, 1362 0, 4, B, O, O, M, 1363 0, 6, // consistency 1364 0, 0, 0, 1, 1365 0, 0, 0, 2, 1366 0, 3, C, A, S, 1367 }, 1368 nil, 1369 fmt.Errorf("cannot read ERROR WRITE TIMEOUT contentions: %w", fmt.Errorf("cannot read [short]: %w", errors.New("EOF"))), 1370 }, 1371 } 1372 for _, tt := range tests { 1373 test.Run(tt.name, func(t *testing.T) { 1374 source := bytes.NewBuffer(tt.input) 1375 actual, err := codec.Decode(source, primitive.ProtocolVersion5) 1376 assert.Equal(t, tt.expected, actual) 1377 assert.Equal(t, tt.err, err) 1378 }) 1379 } 1380 }) 1381 }