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  }