github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/datacodec/tuple_test.go (about)

     1  // Copyright 2021 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 datacodec
    16  
    17  import (
    18  	"errors"
    19  	"testing"
    20  
    21  	"github.com/stretchr/testify/assert"
    22  	"github.com/stretchr/testify/mock"
    23  
    24  	"github.com/datastax/go-cassandra-native-protocol/datatype"
    25  	"github.com/datastax/go-cassandra-native-protocol/primitive"
    26  )
    27  
    28  type (
    29  	SimpleTuple struct {
    30  		Int    int
    31  		Bool   bool
    32  		String *string
    33  	}
    34  	partialTuple struct {
    35  		Int  int
    36  		Bool bool
    37  	}
    38  	excessTuple struct {
    39  		Int    int
    40  		Bool   bool
    41  		String *string
    42  		Float  float64
    43  	}
    44  	complexTuple struct {
    45  		SimpleTuple
    46  		Element2 *excessTuple
    47  	}
    48  )
    49  
    50  var (
    51  	tupleCodecEmpty, _   = NewTuple(datatype.NewTuple())
    52  	tupleCodecSimple, _  = NewTuple(datatype.NewTuple(datatype.Int, datatype.Boolean, datatype.Varchar))
    53  	tupleCodecInts, _    = NewTuple(datatype.NewTuple(datatype.Int, datatype.Int, datatype.Int)) // can be mapped to []int
    54  	tupleCodecComplex, _ = NewTuple(datatype.NewTuple(tupleCodecSimple.DataType(), tupleCodecSimple.DataType()))
    55  )
    56  
    57  var (
    58  	tupleNullsBytes = []byte{
    59  		255, 255, 255, 255, // nil int
    60  		255, 255, 255, 255, // nil boolean
    61  		255, 255, 255, 255, // nil string
    62  	}
    63  	tupleOneTwoThreeTrueAbcBytes = []byte{
    64  		0, 0, 0, 4, // length of int
    65  		0, 0, 0, 123, // int
    66  		0, 0, 0, 1, // length of boolean
    67  		1,          // boolean
    68  		0, 0, 0, 3, // length of string
    69  		a, b, c, // string
    70  	}
    71  	tupleOneTwoThreeFalseNilBytes = []byte{
    72  		0, 0, 0, 4, // length of int
    73  		0, 0, 0, 123, // int
    74  		0, 0, 0, 1, // length of boolean
    75  		0,                  // boolean
    76  		255, 255, 255, 255, // nil string
    77  	}
    78  	tupleZeroFalseNilBytes = []byte{
    79  		0, 0, 0, 4, // length of int
    80  		0, 0, 0, 0, // int
    81  		0, 0, 0, 1, // length of boolean
    82  		0,                  // boolean
    83  		255, 255, 255, 255, // nil string
    84  	}
    85  	tupleComplexBytes = []byte{
    86  		0, 0, 0, 20, // length of element 1
    87  		// element 1
    88  		0, 0, 0, 4, // length of int
    89  		0, 0, 0, 12, // int
    90  		0, 0, 0, 1, // length of boolean
    91  		0,          // boolean
    92  		0, 0, 0, 3, // length of string
    93  		a, b, c, // string
    94  		0, 0, 0, 20, // length of element 2
    95  		// element 2
    96  		0, 0, 0, 4, // length of int
    97  		0, 0, 0, 34, // int
    98  		0, 0, 0, 1, // length of boolean
    99  		1,          // boolean
   100  		0, 0, 0, 3, // length of string
   101  		d, e, f, // string
   102  	}
   103  	tupleComplexWithNullsBytes = []byte{
   104  		0, 0, 0, 20, // length of element 1
   105  		// element 1
   106  		0, 0, 0, 4, // length of int
   107  		0, 0, 0, 12, // int
   108  		0, 0, 0, 1, // length of boolean
   109  		0,          // boolean
   110  		0, 0, 0, 3, // length of string
   111  		a, b, c, // string
   112  		0, 0, 0, 17, // length of element 2
   113  		// element 2
   114  		0, 0, 0, 4, // length of int
   115  		0, 0, 0, 34, // int
   116  		0, 0, 0, 1, // length of boolean
   117  		1,                  // boolean
   118  		255, 255, 255, 255, // nil string
   119  	}
   120  	tupleComplexWithNulls2Bytes = []byte{
   121  		0, 0, 0, 20, // length of element 1
   122  		// element 1
   123  		0, 0, 0, 4, // length of int
   124  		0, 0, 0, 12, // int
   125  		0, 0, 0, 1, // length of boolean
   126  		0,          // boolean
   127  		0, 0, 0, 3, // length of string
   128  		a, b, c, // string
   129  		255, 255, 255, 255, // nil element 2
   130  	}
   131  	tupleOneTwoThreeBytes = []byte{
   132  		0, 0, 0, 4, // length of int
   133  		0, 0, 0, 1, // int
   134  		0, 0, 0, 4, // length of int
   135  		0, 0, 0, 2, // int
   136  		0, 0, 0, 4, // length of int
   137  		0, 0, 0, 3, // int
   138  	}
   139  	tupleOneTwoNilBytes = []byte{
   140  		0, 0, 0, 4, // length of int
   141  		0, 0, 0, 1, // int
   142  		0, 0, 0, 4, // length of int
   143  		0, 0, 0, 2, // int
   144  		255, 255, 255, 255, // nil int
   145  	}
   146  	tupleOneNilNilBytes = []byte{
   147  		0, 0, 0, 4, // length of int
   148  		0, 0, 0, 1, // int
   149  		255, 255, 255, 255, // nil int
   150  		255, 255, 255, 255, // nil int
   151  	}
   152  	tupleMissingBytes = []byte{
   153  		0, 0, 0, 4, // length of int
   154  		0, 0, 0, 123, // int
   155  		0, 0, 0, 1, // length of boolean
   156  		1,          // boolean
   157  		0, 0, 0, 3, // length of string
   158  		// missing string
   159  	}
   160  	tupleIntMissingBytes = []byte{
   161  		0, 0, 0, 4, // length of int
   162  		0, 0, 0, 1, // int
   163  		0, 0, 0, 4, // length of int
   164  		0, 0, 0, 2, // int
   165  		0, 0, 0, 4, // length of int
   166  		// missing int
   167  	}
   168  )
   169  
   170  func TestNewTupleCodec(t *testing.T) {
   171  	tests := []struct {
   172  		name     string
   173  		dataType *datatype.Tuple
   174  		expected Codec
   175  		err      string
   176  	}{
   177  		{
   178  			"simple",
   179  			datatype.NewTuple(datatype.Int, datatype.Varchar),
   180  			&tupleCodec{
   181  				dataType:      datatype.NewTuple(datatype.Int, datatype.Varchar),
   182  				elementCodecs: []Codec{Int, Varchar},
   183  			},
   184  			"",
   185  		},
   186  		{
   187  			"complex",
   188  			datatype.NewTuple(datatype.Int, datatype.NewTuple(datatype.Int, datatype.Varchar)),
   189  			&tupleCodec{
   190  				dataType: datatype.NewTuple(datatype.Int, datatype.NewTuple(datatype.Int, datatype.Varchar)),
   191  				elementCodecs: []Codec{Int, &tupleCodec{
   192  					dataType:      datatype.NewTuple(datatype.Int, datatype.Varchar),
   193  					elementCodecs: []Codec{Int, Varchar},
   194  				}},
   195  			},
   196  			"",
   197  		},
   198  		{
   199  			"empty",
   200  			datatype.NewTuple(),
   201  			&tupleCodec{
   202  				dataType:      datatype.NewTuple(),
   203  				elementCodecs: []Codec{},
   204  			},
   205  			"",
   206  		},
   207  		{
   208  			"wrong child",
   209  			datatype.NewTuple(wrongDataType{}),
   210  			nil,
   211  			"cannot create codec for tuple element 0: cannot create data codec for CQL type 666",
   212  		},
   213  		{
   214  			"nil",
   215  			nil,
   216  			nil,
   217  			"data type is nil",
   218  		},
   219  	}
   220  	for _, tt := range tests {
   221  		t.Run(tt.name, func(t *testing.T) {
   222  			actual, err := NewTuple(tt.dataType)
   223  			assert.Equal(t, tt.expected, actual)
   224  			assertErrorMessage(t, tt.err, err)
   225  		})
   226  	}
   227  }
   228  
   229  func Test_tupleCodec_Encode(t *testing.T) {
   230  	for _, version := range primitive.SupportedProtocolVersionsGreaterThanOrEqualTo(primitive.ProtocolVersion3) {
   231  		t.Run(version.String(), func(t *testing.T) {
   232  			t.Run("[]interface{}", func(t *testing.T) {
   233  				tests := []struct {
   234  					name     string
   235  					codec    Codec
   236  					input    *[]interface{}
   237  					expected []byte
   238  					err      string
   239  				}{
   240  					{"nil", tupleCodecEmpty, nil, nil, ""},
   241  					{"empty", tupleCodecSimple, &[]interface{}{nil, nil, nil}, tupleNullsBytes, ""},
   242  					{"simple", tupleCodecSimple, &[]interface{}{123, true, "abc"}, tupleOneTwoThreeTrueAbcBytes, ""},
   243  					{"simple with pointers", tupleCodecSimple, &[]interface{}{intPtr(123), boolPtr(true), stringPtr("abc")}, tupleOneTwoThreeTrueAbcBytes, ""},
   244  					{"nil element", tupleCodecSimple, &[]interface{}{123, false, nil}, tupleOneTwoThreeFalseNilBytes, ""},
   245  					{"not enough elements", tupleCodecSimple, &[]interface{}{123}, nil, "slice index out of range: 1"},
   246  					{"too many elements", tupleCodecSimple, &[]interface{}{123, true, "abc", "extra"}, tupleOneTwoThreeTrueAbcBytes, ""},
   247  					{"complex", tupleCodecComplex, &[]interface{}{[]interface{}{12, false, "abc"}, []interface{}{34, true, "def"}}, tupleComplexBytes, ""},
   248  				}
   249  				for _, tt := range tests {
   250  					t.Run(tt.name, func(t *testing.T) {
   251  						if tt.input != nil {
   252  							t.Run("value", func(t *testing.T) {
   253  								dest, err := tt.codec.Encode(*tt.input, version)
   254  								assert.Equal(t, tt.expected, dest)
   255  								assertErrorMessage(t, tt.err, err)
   256  							})
   257  						}
   258  						t.Run("pointer", func(t *testing.T) {
   259  							dest, err := tt.codec.Encode(tt.input, version)
   260  							assert.Equal(t, tt.expected, dest)
   261  							assertErrorMessage(t, tt.err, err)
   262  						})
   263  					})
   264  				}
   265  			})
   266  			t.Run("struct simple", func(t *testing.T) {
   267  				tests := []struct {
   268  					name     string
   269  					codec    Codec
   270  					input    *SimpleTuple
   271  					expected []byte
   272  				}{
   273  					{"nil", tupleCodecEmpty, nil, nil},
   274  					{"empty", tupleCodecSimple, &SimpleTuple{}, tupleZeroFalseNilBytes},
   275  					{"simple", tupleCodecSimple, &SimpleTuple{123, true, stringPtr("abc")}, tupleOneTwoThreeTrueAbcBytes},
   276  					{"nil element", tupleCodecSimple, &SimpleTuple{123, false, nil}, tupleOneTwoThreeFalseNilBytes},
   277  				}
   278  				for _, tt := range tests {
   279  					t.Run(tt.name, func(t *testing.T) {
   280  						if tt.input != nil {
   281  							t.Run("value", func(t *testing.T) {
   282  								dest, err := tt.codec.Encode(*tt.input, version)
   283  								assert.Equal(t, tt.expected, dest)
   284  								assert.NoError(t, err)
   285  
   286  							})
   287  						}
   288  						t.Run("pointer", func(t *testing.T) {
   289  							dest, err := tt.codec.Encode(tt.input, version)
   290  							assert.Equal(t, tt.expected, dest)
   291  							assert.NoError(t, err)
   292  						})
   293  					})
   294  				}
   295  			})
   296  			t.Run("struct partial", func(t *testing.T) {
   297  				tests := []struct {
   298  					name     string
   299  					codec    Codec
   300  					input    *partialTuple
   301  					expected []byte
   302  					err      string
   303  				}{
   304  					{"simple", tupleCodecSimple, &partialTuple{123, false}, nil, "no accessible field with index 2 found"},
   305  				}
   306  				for _, tt := range tests {
   307  					t.Run(tt.name, func(t *testing.T) {
   308  						if tt.input != nil {
   309  							t.Run("value", func(t *testing.T) {
   310  								dest, err := tt.codec.Encode(*tt.input, version)
   311  								assert.Equal(t, tt.expected, dest)
   312  								assertErrorMessage(t, tt.err, err)
   313  							})
   314  						}
   315  						t.Run("pointer", func(t *testing.T) {
   316  							dest, err := tt.codec.Encode(tt.input, version)
   317  							assert.Equal(t, tt.expected, dest)
   318  							assertErrorMessage(t, tt.err, err)
   319  						})
   320  					})
   321  				}
   322  			})
   323  			t.Run("struct excess", func(t *testing.T) {
   324  				tests := []struct {
   325  					name     string
   326  					codec    Codec
   327  					input    *excessTuple
   328  					expected []byte
   329  				}{
   330  					{"nil", tupleCodecEmpty, nil, nil},
   331  					{"empty", tupleCodecSimple, &excessTuple{}, tupleZeroFalseNilBytes},
   332  					{"simple", tupleCodecSimple, &excessTuple{123, true, stringPtr("abc"), 42.0}, tupleOneTwoThreeTrueAbcBytes},
   333  				}
   334  				for _, tt := range tests {
   335  					t.Run(tt.name, func(t *testing.T) {
   336  						if tt.input != nil {
   337  							t.Run("value", func(t *testing.T) {
   338  								dest, err := tt.codec.Encode(*tt.input, version)
   339  								assert.Equal(t, tt.expected, dest)
   340  								assert.NoError(t, err)
   341  							})
   342  						}
   343  						t.Run("pointer", func(t *testing.T) {
   344  							dest, err := tt.codec.Encode(tt.input, version)
   345  							assert.Equal(t, tt.expected, dest)
   346  							assert.NoError(t, err)
   347  						})
   348  					})
   349  				}
   350  			})
   351  			t.Run("struct complex", func(t *testing.T) {
   352  				tests := []struct {
   353  					name     string
   354  					codec    Codec
   355  					input    *complexTuple
   356  					expected []byte
   357  				}{
   358  					{"nil", tupleCodecEmpty, nil, nil},
   359  					{"empty", tupleCodecEmpty, &complexTuple{}, nil},
   360  					{"complex", tupleCodecComplex, &complexTuple{
   361  						SimpleTuple{12, false, stringPtr("abc")},
   362  						&excessTuple{34, true, nil, 0.0},
   363  					}, []byte{
   364  						0, 0, 0, 20, // length of element 1
   365  						// element 1
   366  						0, 0, 0, 4, // length of int
   367  						0, 0, 0, 12, // int
   368  						0, 0, 0, 1, // length of boolean
   369  						0,          // boolean
   370  						0, 0, 0, 3, // length of string
   371  						a, b, c, // string
   372  						0, 0, 0, 17, // length of element 2
   373  						// element 2
   374  						0, 0, 0, 4, // length of int
   375  						0, 0, 0, 34, // int
   376  						0, 0, 0, 1, // length of boolean
   377  						1,                  // boolean
   378  						255, 255, 255, 255, // nil string
   379  					}},
   380  					{"nil element", tupleCodecComplex, &complexTuple{
   381  						SimpleTuple{12, false, stringPtr("abc")},
   382  						nil,
   383  					}, []byte{
   384  						0, 0, 0, 20, // length of element 1
   385  						// element 1
   386  						0, 0, 0, 4, // length of int
   387  						0, 0, 0, 12, // int
   388  						0, 0, 0, 1, // length of boolean
   389  						0,          // boolean
   390  						0, 0, 0, 3, // length of string
   391  						a, b, c, // string
   392  						255, 255, 255, 255, // nil element 2
   393  					}},
   394  				}
   395  				for _, tt := range tests {
   396  					t.Run(tt.name, func(t *testing.T) {
   397  						if tt.input != nil {
   398  							t.Run("value", func(t *testing.T) {
   399  								dest, err := tt.codec.Encode(*tt.input, version)
   400  								assert.Equal(t, tt.expected, dest)
   401  								assert.NoError(t, err)
   402  							})
   403  						}
   404  						t.Run("pointer", func(t *testing.T) {
   405  							dest, err := tt.codec.Encode(tt.input, version)
   406  							assert.Equal(t, tt.expected, dest)
   407  							assert.NoError(t, err)
   408  						})
   409  					})
   410  				}
   411  			})
   412  			t.Run("[3]int", func(t *testing.T) {
   413  				tests := []struct {
   414  					name     string
   415  					codec    Codec
   416  					input    *[3]int
   417  					expected []byte
   418  				}{
   419  					{"nil", tupleCodecInts, nil, nil},
   420  					{"non nil", tupleCodecInts, &[3]int{1, 2, 3}, tupleOneTwoThreeBytes},
   421  				}
   422  				for _, tt := range tests {
   423  					t.Run(tt.name, func(t *testing.T) {
   424  						if tt.input != nil {
   425  							t.Run("value", func(t *testing.T) {
   426  								dest, err := tt.codec.Encode(*tt.input, version)
   427  								assert.Equal(t, tt.expected, dest)
   428  								assert.NoError(t, err)
   429  							})
   430  						}
   431  						t.Run("pointer", func(t *testing.T) {
   432  							dest, err := tt.codec.Encode(tt.input, version)
   433  							assert.Equal(t, tt.expected, dest)
   434  							assert.NoError(t, err)
   435  						})
   436  					})
   437  				}
   438  			})
   439  			t.Run("[3]*int", func(t *testing.T) {
   440  				tests := []struct {
   441  					name     string
   442  					codec    Codec
   443  					input    *[3]*int
   444  					expected []byte
   445  				}{
   446  					{"nil", tupleCodecInts, nil, nil},
   447  					{"nil element", tupleCodecInts, &[3]*int{intPtr(1), nil, nil}, tupleOneNilNilBytes},
   448  				}
   449  				for _, tt := range tests {
   450  					t.Run(tt.name, func(t *testing.T) {
   451  						if tt.input != nil {
   452  							t.Run("value", func(t *testing.T) {
   453  								dest, err := tt.codec.Encode(*tt.input, version)
   454  								assert.Equal(t, tt.expected, dest)
   455  								assert.NoError(t, err)
   456  							})
   457  						}
   458  						t.Run("pointer", func(t *testing.T) {
   459  							dest, err := tt.codec.Encode(tt.input, version)
   460  							assert.Equal(t, tt.expected, dest)
   461  							assert.NoError(t, err)
   462  						})
   463  					})
   464  				}
   465  			})
   466  			t.Run("[]int", func(t *testing.T) {
   467  				tests := []struct {
   468  					name     string
   469  					codec    Codec
   470  					input    *[]int
   471  					expected []byte
   472  					err      string
   473  				}{
   474  					{"nil", tupleCodecInts, nil, nil, ""},
   475  					{"non nil", tupleCodecInts, &[]int{1, 2, 3}, tupleOneTwoThreeBytes, ""},
   476  					{"not enough elements", tupleCodecInts, &[]int{1}, nil, "slice index out of range: 1"},
   477  					{"too many elements", tupleCodecInts, &[]int{1, 2, 3, 4, 5}, tupleOneTwoThreeBytes, ""},
   478  				}
   479  				for _, tt := range tests {
   480  					t.Run(tt.name, func(t *testing.T) {
   481  						if tt.input != nil {
   482  							t.Run("value", func(t *testing.T) {
   483  								dest, err := tt.codec.Encode(*tt.input, version)
   484  								assert.Equal(t, tt.expected, dest)
   485  								assertErrorMessage(t, tt.err, err)
   486  							})
   487  						}
   488  						t.Run("pointer", func(t *testing.T) {
   489  							dest, err := tt.codec.Encode(tt.input, version)
   490  							assert.Equal(t, tt.expected, dest)
   491  							assertErrorMessage(t, tt.err, err)
   492  						})
   493  					})
   494  				}
   495  			})
   496  			t.Run("[]*int", func(t *testing.T) {
   497  				tests := []struct {
   498  					name     string
   499  					codec    Codec
   500  					input    *[]*int
   501  					expected []byte
   502  					err      string
   503  				}{
   504  					{"nil", tupleCodecInts, nil, nil, ""},
   505  					{"nil element", tupleCodecInts, &[]*int{intPtr(1), intPtr(2), nil}, tupleOneTwoNilBytes, ""},
   506  					{"not enough elements", tupleCodecInts, &[]*int{intPtr(1)}, nil, "slice index out of range: 1"},
   507  					{"too many elements", tupleCodecInts, &[]*int{intPtr(1), intPtr(2), nil, intPtr(4)}, tupleOneTwoNilBytes, ""},
   508  				}
   509  				for _, tt := range tests {
   510  					t.Run(tt.name, func(t *testing.T) {
   511  						if tt.input != nil {
   512  							t.Run("value", func(t *testing.T) {
   513  								dest, err := tt.codec.Encode(*tt.input, version)
   514  								assert.Equal(t, tt.expected, dest)
   515  								assertErrorMessage(t, tt.err, err)
   516  							})
   517  						}
   518  						t.Run("pointer", func(t *testing.T) {
   519  							dest, err := tt.codec.Encode(tt.input, version)
   520  							assert.Equal(t, tt.expected, dest)
   521  							assertErrorMessage(t, tt.err, err)
   522  						})
   523  					})
   524  				}
   525  			})
   526  		})
   527  	}
   528  	for _, version := range primitive.SupportedProtocolVersionsLesserThan(primitive.ProtocolVersion3) {
   529  		t.Run(version.String(), func(t *testing.T) {
   530  			codec, _ := NewTuple(datatype.NewTuple(datatype.Int))
   531  			dest, err := codec.Encode(nil, version)
   532  			assert.Nil(t, dest)
   533  			assertErrorMessage(t, "data type tuple<int> not supported in "+version.String(), err)
   534  		})
   535  	}
   536  	t.Run("invalid types", func(t *testing.T) {
   537  		dest, err := tupleCodecSimple.Encode(123, primitive.ProtocolVersion5)
   538  		assert.Nil(t, dest)
   539  		assert.EqualError(t, err, "cannot encode int as CQL tuple<int,boolean,varchar> with ProtocolVersion OSS 5: source type not supported")
   540  	})
   541  }
   542  
   543  func Test_tupleCodec_Decode(t *testing.T) {
   544  	for _, version := range primitive.SupportedProtocolVersionsGreaterThanOrEqualTo(primitive.ProtocolVersion3) {
   545  		t.Run(version.String(), func(t *testing.T) {
   546  			t.Run("*interface{}", func(t *testing.T) {
   547  				tests := []struct {
   548  					name     string
   549  					codec    Codec
   550  					input    []byte
   551  					dest     *interface{}
   552  					expected *interface{}
   553  					err      string
   554  					wasNull  bool
   555  				}{
   556  					{"nil input", tupleCodecSimple, nil, new(interface{}), new(interface{}), "", true},
   557  					{"nil elements map to zero values", tupleCodecSimple, tupleNullsBytes, new(interface{}), interfacePtr([]interface{}{nil, nil, nil}), "", false},
   558  					{"simple", tupleCodecSimple, tupleOneTwoThreeTrueAbcBytes, new(interface{}), interfacePtr([]interface{}{int32(123), true, "abc"}), "", false},
   559  					{"complex", tupleCodecComplex, tupleComplexBytes, new(interface{}), interfacePtr([]interface{}{
   560  						[]interface{}{int32(12), false, "abc"},
   561  						[]interface{}{int32(34), true, "def"},
   562  					}), "", false},
   563  					{"nil dest", tupleCodecSimple, tupleOneTwoThreeTrueAbcBytes, nil, nil, "destination is nil", false},
   564  					{"not enough bytes", tupleCodecSimple, tupleMissingBytes, new(interface{}), interfacePtr([]interface{}{int32(123), true, nil}), "cannot read element 2", false},
   565  					{"slice length too large", tupleCodecSimple, tupleOneTwoThreeTrueAbcBytes, interfacePtr([]interface{}{nil, nil, nil, 42.0}), interfacePtr([]interface{}{int32(123), true, "abc"}), "", false},
   566  				}
   567  				for _, tt := range tests {
   568  					t.Run(tt.name, func(t *testing.T) {
   569  						wasNull, err := tt.codec.Decode(tt.input, tt.dest, version)
   570  						assert.Equal(t, tt.expected, tt.dest)
   571  						assert.Equal(t, tt.wasNull, wasNull)
   572  						assertErrorMessage(t, tt.err, err)
   573  					})
   574  				}
   575  			})
   576  			t.Run("*[]interface{}", func(t *testing.T) {
   577  				tests := []struct {
   578  					name     string
   579  					codec    Codec
   580  					input    []byte
   581  					dest     *[]interface{}
   582  					expected *[]interface{}
   583  					err      string
   584  					wasNull  bool
   585  				}{
   586  					{name: "nil input", codec: tupleCodecSimple, dest: new([]interface{}), expected: new([]interface{}), wasNull: true},
   587  					{"nil elements map to zero values", tupleCodecSimple, tupleNullsBytes, new([]interface{}), &[]interface{}{nil, nil, nil}, "", false},
   588  					{"simple", tupleCodecSimple, tupleOneTwoThreeTrueAbcBytes, new([]interface{}), &[]interface{}{int32(123), true, "abc"}, "", false},
   589  					{"complex", tupleCodecComplex, tupleComplexBytes, new([]interface{}), &[]interface{}{
   590  						[]interface{}{int32(12), false, "abc"},
   591  						[]interface{}{int32(34), true, "def"},
   592  					}, "", false},
   593  					{"nil dest", tupleCodecSimple, tupleOneTwoThreeTrueAbcBytes, nil, nil, "destination is nil", false},
   594  					{"not enough bytes", tupleCodecSimple, tupleMissingBytes, new([]interface{}), &[]interface{}{int32(123), true, nil}, "cannot read element 2", false},
   595  					{"slice length too large", tupleCodecSimple, tupleOneTwoThreeTrueAbcBytes, &[]interface{}{nil, nil, nil, 42.0}, &[]interface{}{int32(123), true, "abc"}, "", false},
   596  				}
   597  				for _, tt := range tests {
   598  					t.Run(tt.name, func(t *testing.T) {
   599  						wasNull, err := tt.codec.Decode(tt.input, tt.dest, version)
   600  						assert.Equal(t, tt.expected, tt.dest)
   601  						assert.Equal(t, tt.wasNull, wasNull)
   602  						assertErrorMessage(t, tt.err, err)
   603  					})
   604  				}
   605  			})
   606  			t.Run("struct simple", func(t *testing.T) {
   607  				tests := []struct {
   608  					name     string
   609  					codec    Codec
   610  					input    []byte
   611  					dest     *SimpleTuple
   612  					expected *SimpleTuple
   613  					err      string
   614  					wasNull  bool
   615  				}{
   616  					{"nil input", tupleCodecSimple, nil, &SimpleTuple{}, &SimpleTuple{}, "", true},
   617  					{"empty input", tupleCodecSimple, []byte{}, &SimpleTuple{}, &SimpleTuple{}, "", true},
   618  					{"nil elements", tupleCodecSimple, tupleNullsBytes, &SimpleTuple{}, &SimpleTuple{Int: 0, Bool: false, String: nil}, "", false},
   619  					{"simple", tupleCodecSimple, tupleOneTwoThreeTrueAbcBytes, &SimpleTuple{}, &SimpleTuple{Int: 123, Bool: true, String: stringPtr("abc")}, "", false},
   620  					{"nil dest", tupleCodecSimple, tupleMissingBytes, nil, nil, "destination is nil", false},
   621  				}
   622  				for _, tt := range tests {
   623  					t.Run(tt.name, func(t *testing.T) {
   624  						wasNull, err := tt.codec.Decode(tt.input, tt.dest, version)
   625  						if tt.expected != nil && tt.dest != nil {
   626  							assert.Equal(t, *tt.expected, *tt.dest)
   627  						}
   628  						assert.Equal(t, tt.wasNull, wasNull)
   629  						assertErrorMessage(t, tt.err, err)
   630  					})
   631  				}
   632  			})
   633  			t.Run("struct partial", func(t *testing.T) {
   634  				tests := []struct {
   635  					name     string
   636  					codec    Codec
   637  					input    []byte
   638  					dest     *partialTuple
   639  					expected *partialTuple
   640  					err      string
   641  					wasNull  bool
   642  				}{
   643  					{"simple", tupleCodecSimple, tupleOneTwoThreeTrueAbcBytes, &partialTuple{}, &partialTuple{Int: 123, Bool: true}, "no accessible field with index 2 found", false},
   644  				}
   645  				for _, tt := range tests {
   646  					t.Run(tt.name, func(t *testing.T) {
   647  						wasNull, err := tt.codec.Decode(tt.input, tt.dest, version)
   648  						if tt.expected != nil && tt.dest != nil {
   649  							assert.Equal(t, *tt.expected, *tt.dest)
   650  						}
   651  						assert.Equal(t, tt.wasNull, wasNull)
   652  						assertErrorMessage(t, tt.err, err)
   653  					})
   654  				}
   655  			})
   656  			t.Run("struct excess", func(t *testing.T) {
   657  				tests := []struct {
   658  					name     string
   659  					codec    Codec
   660  					input    []byte
   661  					dest     *excessTuple
   662  					expected *excessTuple
   663  					err      string
   664  					wasNull  bool
   665  				}{
   666  					{"nil input", tupleCodecSimple, nil, &excessTuple{}, &excessTuple{}, "", true},
   667  					{"empty input", tupleCodecSimple, []byte{}, &excessTuple{}, &excessTuple{}, "", true},
   668  					{"nil elements", tupleCodecSimple, tupleNullsBytes, &excessTuple{}, &excessTuple{}, "", false},
   669  					{"simple", tupleCodecSimple, tupleOneTwoThreeTrueAbcBytes, &excessTuple{}, &excessTuple{Int: 123, Bool: true, String: stringPtr("abc")}, "", false},
   670  					{"nil dest", tupleCodecSimple, tupleMissingBytes, nil, nil, "destination is nil", false},
   671  				}
   672  				for _, tt := range tests {
   673  					t.Run(tt.name, func(t *testing.T) {
   674  						wasNull, err := tt.codec.Decode(tt.input, tt.dest, version)
   675  						if tt.expected != nil && tt.dest != nil {
   676  							assert.Equal(t, *tt.expected, *tt.dest)
   677  						}
   678  						assert.Equal(t, tt.wasNull, wasNull)
   679  						assertErrorMessage(t, tt.err, err)
   680  					})
   681  				}
   682  			})
   683  			t.Run("struct complex", func(t *testing.T) {
   684  				tests := []struct {
   685  					name     string
   686  					codec    Codec
   687  					input    []byte
   688  					dest     *complexTuple
   689  					expected *complexTuple
   690  					err      string
   691  					wasNull  bool
   692  				}{
   693  					{"nil", tupleCodecComplex, nil, &complexTuple{}, &complexTuple{}, "", true},
   694  					{"empty", tupleCodecComplex, []byte{}, &complexTuple{}, &complexTuple{}, "", true},
   695  					{"complex", tupleCodecComplex, tupleComplexWithNullsBytes, &complexTuple{}, &complexTuple{
   696  						SimpleTuple{12, false, stringPtr("abc")},
   697  						&excessTuple{34, true, nil, 0.0},
   698  					}, "", false},
   699  					{"nil element", tupleCodecComplex, tupleComplexWithNulls2Bytes, &complexTuple{}, &complexTuple{
   700  						SimpleTuple{12, false, stringPtr("abc")},
   701  						nil,
   702  					}, "", false},
   703  				}
   704  				for _, tt := range tests {
   705  					t.Run(tt.name, func(t *testing.T) {
   706  						wasNull, err := tt.codec.Decode(tt.input, tt.dest, version)
   707  						assert.Equal(t, *tt.expected, *tt.dest)
   708  						assert.Equal(t, tt.wasNull, wasNull)
   709  						assertErrorMessage(t, tt.err, err)
   710  					})
   711  				}
   712  			})
   713  			t.Run("[3]int", func(t *testing.T) {
   714  				tests := []struct {
   715  					name     string
   716  					codec    Codec
   717  					input    []byte
   718  					expected *[3]int
   719  					dest     *[3]int
   720  					err      string
   721  					wasNull  bool
   722  				}{
   723  					{"nil", tupleCodecInts, nil, new([3]int), new([3]int), "", true},
   724  					{"non nil", tupleCodecInts, tupleOneTwoThreeBytes, &[3]int{1, 2, 3}, new([3]int), "", false},
   725  					{"nil dest", tupleCodecInts, tupleOneTwoThreeBytes, nil, nil, "destination is nil", false},
   726  				}
   727  				for _, tt := range tests {
   728  					t.Run(tt.name, func(t *testing.T) {
   729  						wasNull, err := tt.codec.Decode(tt.input, tt.dest, version)
   730  						assert.Equal(t, tt.expected, tt.dest)
   731  						assert.Equal(t, tt.wasNull, wasNull)
   732  						assertErrorMessage(t, tt.err, err)
   733  					})
   734  				}
   735  			})
   736  			t.Run("[3]*int", func(t *testing.T) {
   737  				tests := []struct {
   738  					name     string
   739  					codec    Codec
   740  					input    []byte
   741  					expected *[3]*int
   742  					dest     *[3]*int
   743  					err      string
   744  					wasNull  bool
   745  				}{
   746  					{"nil", tupleCodecInts, nil, new([3]*int), new([3]*int), "", true},
   747  					{"non nil", tupleCodecInts, tupleOneTwoThreeBytes, &[3]*int{intPtr(1), intPtr(2), intPtr(3)}, new([3]*int), "", false},
   748  					{"nil dest", tupleCodecInts, tupleOneTwoThreeBytes, nil, nil, "destination is nil", false},
   749  				}
   750  				for _, tt := range tests {
   751  					t.Run(tt.name, func(t *testing.T) {
   752  						wasNull, err := tt.codec.Decode(tt.input, tt.dest, version)
   753  						assert.Equal(t, tt.expected, tt.dest)
   754  						assert.Equal(t, tt.wasNull, wasNull)
   755  						assertErrorMessage(t, tt.err, err)
   756  					})
   757  				}
   758  			})
   759  			t.Run("[4]int", func(t *testing.T) {
   760  				tests := []struct {
   761  					name     string
   762  					codec    Codec
   763  					input    []byte
   764  					expected *[4]int
   765  					dest     *[4]int
   766  					err      string
   767  					wasNull  bool
   768  				}{
   769  					{"nil", tupleCodecInts, nil, new([4]int), new([4]int), "", true},
   770  					{"non nil", tupleCodecInts, tupleOneTwoThreeBytes, &[4]int{1, 2, 3, 0}, new([4]int), "", false},
   771  					{"nil dest", tupleCodecInts, tupleOneTwoThreeBytes, nil, nil, "destination is nil", false},
   772  				}
   773  				for _, tt := range tests {
   774  					t.Run(tt.name, func(t *testing.T) {
   775  						wasNull, err := tt.codec.Decode(tt.input, tt.dest, version)
   776  						assert.Equal(t, tt.expected, tt.dest)
   777  						assert.Equal(t, tt.wasNull, wasNull)
   778  						assertErrorMessage(t, tt.err, err)
   779  					})
   780  				}
   781  			})
   782  			t.Run("[2]int", func(t *testing.T) {
   783  				tests := []struct {
   784  					name     string
   785  					codec    Codec
   786  					input    []byte
   787  					expected *[2]int
   788  					dest     *[2]int
   789  					err      string
   790  					wasNull  bool
   791  				}{
   792  					{"non nil", tupleCodecInts, tupleOneTwoThreeBytes, &[2]int{1, 2}, new([2]int), "array index out of range: 2", false},
   793  				}
   794  				for _, tt := range tests {
   795  					t.Run(tt.name, func(t *testing.T) {
   796  						wasNull, err := tt.codec.Decode(tt.input, tt.dest, version)
   797  						assert.Equal(t, tt.expected, tt.dest)
   798  						assert.Equal(t, tt.wasNull, wasNull)
   799  						assertErrorMessage(t, tt.err, err)
   800  					})
   801  				}
   802  			})
   803  			t.Run("[]int", func(t *testing.T) {
   804  				tests := []struct {
   805  					name     string
   806  					codec    Codec
   807  					input    []byte
   808  					expected *[]int
   809  					dest     *[]int
   810  					err      string
   811  					wasNull  bool
   812  				}{
   813  					{"nil", tupleCodecInts, nil, new([]int), new([]int), "", true},
   814  					{"non nil", tupleCodecInts, tupleOneTwoThreeBytes, &[]int{1, 2, 3}, new([]int), "", false},
   815  					{"not enough elements", tupleCodecInts, tupleIntMissingBytes, &[]int{1, 2, 0}, new([]int), "cannot read element 2", false},
   816  					{"slice length too small", tupleCodecInts, tupleOneTwoThreeBytes, &[]int{1, 2, 3}, new([]int), "", false},
   817  					{"slice length too large", tupleCodecInts, tupleOneTwoThreeBytes, &[]int{1, 2, 3}, &[]int{0, 0, 0, 0}, "", false},
   818  					{"nil dest", tupleCodecInts, tupleOneTwoThreeBytes, nil, nil, "destination is nil", false},
   819  				}
   820  				for _, tt := range tests {
   821  					t.Run(tt.name, func(t *testing.T) {
   822  						wasNull, err := tt.codec.Decode(tt.input, tt.dest, version)
   823  						assert.Equal(t, tt.expected, tt.dest)
   824  						assert.Equal(t, tt.wasNull, wasNull)
   825  						assertErrorMessage(t, tt.err, err)
   826  					})
   827  				}
   828  			})
   829  			t.Run("[]*int", func(t *testing.T) {
   830  				tests := []struct {
   831  					name     string
   832  					codec    Codec
   833  					input    []byte
   834  					expected *[]*int
   835  					dest     *[]*int
   836  					err      string
   837  					wasNull  bool
   838  				}{
   839  					{"nil", tupleCodecInts, nil, new([]*int), new([]*int), "", true},
   840  					{"non nil", tupleCodecInts, tupleOneTwoThreeBytes, &[]*int{intPtr(1), intPtr(2), intPtr(3)}, new([]*int), "", false},
   841  					{"nil dest", tupleCodecInts, tupleOneTwoThreeBytes, nil, nil, "destination is nil", false},
   842  					{"slice length too small", tupleCodecInts, tupleOneTwoThreeBytes, &[]*int{intPtr(1), intPtr(2), intPtr(3)}, &[]*int{intPtr(1), nil}, "", false},
   843  					{"slice length too large", tupleCodecInts, tupleOneTwoThreeBytes, &[]*int{intPtr(1), intPtr(2), intPtr(3)}, &[]*int{intPtr(0), intPtr(0), intPtr(0), intPtr(0)}, "", false},
   844  				}
   845  				for _, tt := range tests {
   846  					t.Run(tt.name, func(t *testing.T) {
   847  						wasNull, err := tt.codec.Decode(tt.input, tt.dest, version)
   848  						assert.Equal(t, tt.expected, tt.dest)
   849  						assert.Equal(t, tt.wasNull, wasNull)
   850  						assertErrorMessage(t, tt.err, err)
   851  					})
   852  				}
   853  			})
   854  		})
   855  	}
   856  	for _, version := range primitive.SupportedProtocolVersionsLesserThan(primitive.ProtocolVersion3) {
   857  		t.Run(version.String(), func(t *testing.T) {
   858  			codec, _ := NewTuple(datatype.NewTuple(datatype.Int))
   859  			_, err := codec.Decode(nil, nil, version)
   860  			assertErrorMessage(t, "data type tuple<int> not supported in "+version.String(), err)
   861  		})
   862  	}
   863  	t.Run("invalid types", func(t *testing.T) {
   864  		wasNull, err := tupleCodecSimple.Decode([]byte{1, 2, 3}, new(int), primitive.ProtocolVersion5)
   865  		assert.False(t, wasNull)
   866  		assert.EqualError(t, err, "cannot decode CQL tuple<int,boolean,varchar> as *int with ProtocolVersion OSS 5: destination type not supported")
   867  	})
   868  }
   869  
   870  func Test_writeTuple(t *testing.T) {
   871  	type args struct {
   872  		ext           extractor
   873  		elementCodecs []Codec
   874  		version       primitive.ProtocolVersion
   875  	}
   876  	tests := []struct {
   877  		name    string
   878  		args    args
   879  		want    []byte
   880  		wantErr string
   881  	}{
   882  		{
   883  			"cannot extract elem",
   884  			args{
   885  				func() extractor {
   886  					ext := &mockExtractor{}
   887  					ext.On("getElem", 0, 0).Return(nil, errSliceIndexOutOfRange(true, 0))
   888  					return ext
   889  				}(),
   890  				[]Codec{nil},
   891  				primitive.ProtocolVersion5,
   892  			},
   893  			nil,
   894  			"cannot extract element 0: slice index out of range: 0",
   895  		},
   896  		{
   897  			"cannot encode",
   898  			args{
   899  				func() extractor {
   900  					ext := &mockExtractor{}
   901  					ext.On("getElem", 0, 0).Return(123, nil)
   902  					return ext
   903  				}(),
   904  				func() []Codec {
   905  					codec := &mockCodec{}
   906  					codec.On("Encode", 123, primitive.ProtocolVersion5).Return(nil, errors.New("write failed"))
   907  					return []Codec{codec}
   908  				}(),
   909  				primitive.ProtocolVersion5,
   910  			},
   911  			nil,
   912  			"cannot encode element 0: write failed",
   913  		},
   914  		{"success", args{
   915  			func() extractor {
   916  				ext := &mockExtractor{}
   917  				ext.On("getElem", 0, 0).Return(123, nil)
   918  				ext.On("getElem", 1, 1).Return("abc", nil)
   919  				ext.On("getElem", 2, 2).Return(true, nil)
   920  				return ext
   921  			}(),
   922  			func() []Codec {
   923  				codec1 := &mockCodec{}
   924  				codec1.On("Encode", 123, primitive.ProtocolVersion5).Return([]byte{1}, nil)
   925  				codec2 := &mockCodec{}
   926  				codec2.On("Encode", "abc", primitive.ProtocolVersion5).Return([]byte{2}, nil)
   927  				codec3 := &mockCodec{}
   928  				codec3.On("Encode", true, primitive.ProtocolVersion5).Return(nil, nil)
   929  				return []Codec{codec1, codec2, codec3}
   930  			}(),
   931  			primitive.ProtocolVersion5,
   932  		}, []byte{
   933  			0, 0, 0, 1, // elem 1
   934  			1,
   935  			0, 0, 0, 1, // elem 2
   936  			2,
   937  			255, 255, 255, 255, // elem 3 (nil)
   938  		}, ""},
   939  	}
   940  	for _, tt := range tests {
   941  		t.Run(tt.name, func(t *testing.T) {
   942  			got, gotErr := writeTuple(tt.args.ext, tt.args.elementCodecs, tt.args.version)
   943  			assert.Equal(t, tt.want, got)
   944  			assertErrorMessage(t, tt.wantErr, gotErr)
   945  		})
   946  	}
   947  }
   948  
   949  func Test_readTuple(t *testing.T) {
   950  	type args struct {
   951  		source        []byte
   952  		inj           injector
   953  		elementCodecs []Codec
   954  		version       primitive.ProtocolVersion
   955  	}
   956  	tests := []struct {
   957  		name    string
   958  		args    args
   959  		wantErr string
   960  	}{
   961  		{
   962  			"cannot read element",
   963  			args{
   964  				[]byte{
   965  					0, // wrong [bytes]
   966  				},
   967  				nil,
   968  				[]Codec{nil},
   969  				primitive.ProtocolVersion5,
   970  			},
   971  			"cannot read element 0: cannot read [bytes] length: cannot read [int]: unexpected EOF",
   972  		},
   973  		{
   974  			"cannot create element",
   975  			args{
   976  				[]byte{
   977  					0, 0, 0, 1, 123, // [bytes]
   978  				},
   979  				func() injector {
   980  					inj := &mockInjector{}
   981  					inj.On("zeroElem", 0, 0).Return(nil, errors.New("wrong data type"))
   982  					return inj
   983  				}(),
   984  				func() []Codec {
   985  					codec := &mockCodec{}
   986  					codec.On("DataType").Return(datatype.Int)
   987  					return []Codec{codec}
   988  				}(),
   989  				primitive.ProtocolVersion5,
   990  			},
   991  			"cannot create zero element 0: wrong data type",
   992  		},
   993  		{
   994  			"cannot decode element",
   995  			args{
   996  				[]byte{
   997  					0, 0, 0, 1, 123, // [bytes]
   998  				},
   999  				func() injector {
  1000  					inj := &mockInjector{}
  1001  					inj.On("zeroElem", 0, 0).Return(new(int), nil)
  1002  					return inj
  1003  				}(),
  1004  				func() []Codec {
  1005  					codec := &mockCodec{}
  1006  					codec.On("DataType").Return(datatype.Int)
  1007  					codec.On("Decode", []byte{123}, new(int), primitive.ProtocolVersion5).Return(false, errors.New("decode failed"))
  1008  					return []Codec{codec}
  1009  				}(),
  1010  				primitive.ProtocolVersion5,
  1011  			},
  1012  			"cannot decode element 0: decode failed",
  1013  		},
  1014  		{
  1015  			"cannot set element",
  1016  			args{
  1017  				[]byte{
  1018  					0, 0, 0, 1, 123, // [bytes]
  1019  				},
  1020  				func() injector {
  1021  					inj := &mockInjector{}
  1022  					inj.On("zeroElem", 0, 0).Return(new(int), nil)
  1023  					inj.On("setElem", 0, 0, intPtr(123), false, false).Return(errors.New("cannot set elem"))
  1024  					return inj
  1025  				}(),
  1026  				func() []Codec {
  1027  					codec := &mockCodec{}
  1028  					codec.On("DataType").Return(datatype.Int)
  1029  					codec.On("Decode", []byte{123}, new(int), primitive.ProtocolVersion5).Run(func(args mock.Arguments) {
  1030  						decodedElement := args.Get(1).(*int)
  1031  						*decodedElement = 123
  1032  					}).Return(false, nil)
  1033  					return []Codec{codec}
  1034  				}(),
  1035  				primitive.ProtocolVersion5,
  1036  			},
  1037  			"cannot inject element 0: cannot set elem",
  1038  		},
  1039  		{
  1040  			"bytes remaining",
  1041  			args{
  1042  				[]byte{
  1043  					0, 0, 0, 1, 123, // [bytes]
  1044  					1, // trailing bytes
  1045  				},
  1046  				func() injector {
  1047  					inj := &mockInjector{}
  1048  					inj.On("zeroElem", 0, 0).Return(new(int), nil)
  1049  					inj.On("setElem", 0, 0, intPtr(123), false, false).Return(nil)
  1050  					return inj
  1051  				}(),
  1052  				func() []Codec {
  1053  					codec := &mockCodec{}
  1054  					codec.On("DataType").Return(datatype.Int)
  1055  					codec.On("Decode", []byte{123}, new(int), primitive.ProtocolVersion5).Run(func(args mock.Arguments) {
  1056  						decodedElement := args.Get(1).(*int)
  1057  						*decodedElement = 123
  1058  					}).Return(false, nil)
  1059  					return []Codec{codec}
  1060  				}(),
  1061  				primitive.ProtocolVersion5,
  1062  			},
  1063  			"source was not fully read: bytes total: 6, read: 5, remaining: 1",
  1064  		},
  1065  		{
  1066  			"success",
  1067  			args{
  1068  				[]byte{
  1069  					0, 0, 0, 1, 123, // 1st elem
  1070  					0, 0, 0, 3, a, b, c, // 2nd elem
  1071  					255, 255, 255, 255, // 3rd elem (nil)
  1072  				},
  1073  				func() injector {
  1074  					inj := &mockInjector{}
  1075  					inj.On("zeroElem", 0, 0).Return(new(int), nil)
  1076  					inj.On("zeroElem", 1, 1).Return(new(string), nil)
  1077  					inj.On("zeroElem", 2, 2).Return(new(bool), nil)
  1078  					inj.On("setElem", 0, 0, intPtr(123), false, false).Return(nil)
  1079  					inj.On("setElem", 1, 1, stringPtr("abc"), false, false).Return(nil)
  1080  					inj.On("setElem", 2, 2, new(bool), false, true).Return(nil)
  1081  					return inj
  1082  				}(),
  1083  				func() []Codec {
  1084  					codec1 := &mockCodec{}
  1085  					codec1.On("DataType").Return(datatype.Int)
  1086  					codec1.On("Decode", []byte{123}, new(int), primitive.ProtocolVersion5).Run(func(args mock.Arguments) {
  1087  						decodedElement := args.Get(1).(*int)
  1088  						*decodedElement = 123
  1089  					}).Return(false, nil)
  1090  					codec2 := &mockCodec{}
  1091  					codec2.On("DataType").Return(datatype.Varchar)
  1092  					codec2.On("Decode", []byte{a, b, c}, new(string), primitive.ProtocolVersion5).Run(func(args mock.Arguments) {
  1093  						decodedElement := args.Get(1).(*string)
  1094  						*decodedElement = "abc"
  1095  					}).Return(false, nil)
  1096  					codec3 := &mockCodec{}
  1097  					codec3.On("DataType").Return(datatype.Boolean)
  1098  					codec3.On("Decode", []byte(nil), new(bool), primitive.ProtocolVersion5).Return(true, nil)
  1099  					return []Codec{codec1, codec2, codec3}
  1100  				}(),
  1101  				primitive.ProtocolVersion5,
  1102  			},
  1103  			"",
  1104  		},
  1105  	}
  1106  	for _, tt := range tests {
  1107  		t.Run(tt.name, func(t *testing.T) {
  1108  			gotErr := readTuple(tt.args.source, tt.args.inj, tt.args.elementCodecs, tt.args.version)
  1109  			assertErrorMessage(t, tt.wantErr, gotErr)
  1110  		})
  1111  	}
  1112  }