github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/datacodec/injectors_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  	"math/big"
    19  	"net"
    20  	"reflect"
    21  	"testing"
    22  
    23  	"github.com/stretchr/testify/assert"
    24  	"github.com/stretchr/testify/require"
    25  
    26  	"github.com/datastax/go-cassandra-native-protocol/datatype"
    27  	"github.com/datastax/go-cassandra-native-protocol/primitive"
    28  )
    29  
    30  type testStruct struct {
    31  	Value        int
    32  	Pointer      *string
    33  	Slice        []int
    34  	PointerSlice []*string `cassandra:"pointer_slice"`
    35  	Array        [2]int
    36  	PointerArray [2]*string `cassandra:"pointer_array"`
    37  	Map          map[string]interface{}
    38  	Untyped      interface{}
    39  	unexported   bool
    40  }
    41  
    42  func Test_newSliceInjector(t *testing.T) {
    43  	var nilSlice []int
    44  	tests := []struct {
    45  		name      string
    46  		dest      reflect.Value
    47  		wantValue bool
    48  		wantErr   string
    49  	}{
    50  		{"nil", reflect.Value{}, false, "destination type not supported"},
    51  		{"nil typed", reflect.ValueOf(&nilSlice).Elem(), true, ""},
    52  		{"not array nor slice", reflect.ValueOf(&map[string]int{}).Elem(), false, "expected slice or array, got: map[string]int"},
    53  		{"success", reflect.ValueOf(&[]int{1}).Elem(), true, ""},
    54  	}
    55  	for _, tt := range tests {
    56  		t.Run(tt.name, func(t *testing.T) {
    57  			gotValue, gotErr := newSliceInjector(tt.dest)
    58  			if tt.wantValue {
    59  				assert.NotNil(t, gotValue)
    60  			} else {
    61  				assert.Nil(t, gotValue)
    62  			}
    63  			assertErrorMessage(t, tt.wantErr, gotErr)
    64  		})
    65  	}
    66  }
    67  func Test_newStructInjector(t *testing.T) {
    68  	tests := []struct {
    69  		name      string
    70  		dest      reflect.Value
    71  		wantValue bool
    72  		wantErr   string
    73  	}{
    74  		{"nil", reflect.Value{}, false, "destination type not supported"},
    75  		{"not struct", reflect.ValueOf(&map[string]int{}).Elem(), false, "expected struct, got: map[string]int"},
    76  		{"unaddressable", reflect.ValueOf(testStruct{}), false, "destination of type datacodec.testStruct is not addressable"},
    77  		{"success", reflect.ValueOf(&testStruct{}).Elem(), true, ""},
    78  	}
    79  	for _, tt := range tests {
    80  		t.Run(tt.name, func(t *testing.T) {
    81  			gotValue, gotErr := newStructInjector(tt.dest)
    82  			if tt.wantValue {
    83  				assert.NotNil(t, gotValue)
    84  			} else {
    85  				assert.Nil(t, gotValue)
    86  			}
    87  			assertErrorMessage(t, tt.wantErr, gotErr)
    88  		})
    89  	}
    90  }
    91  
    92  func Test_newMapInjector(t *testing.T) {
    93  	var nilMap map[int]int
    94  	tests := []struct {
    95  		name      string
    96  		dest      reflect.Value
    97  		wantValue bool
    98  		wantErr   string
    99  	}{
   100  		{"nil", reflect.Value{}, false, "destination type not supported"},
   101  		{"nil typed", reflect.ValueOf(&nilMap).Elem(), true, ""},
   102  		{"not map", reflect.ValueOf(&[]int{}).Elem(), false, "expected map, got: []int"},
   103  		{"success", reflect.ValueOf(&map[int]int{123: 456}).Elem(), true, ""},
   104  	}
   105  	for _, tt := range tests {
   106  		t.Run(tt.name, func(t *testing.T) {
   107  			gotValue, gotErr := newMapInjector(tt.dest)
   108  			if tt.wantValue {
   109  				assert.NotNil(t, gotValue)
   110  			} else {
   111  				assert.Nil(t, gotValue)
   112  			}
   113  			assertErrorMessage(t, tt.wantErr, gotErr)
   114  		})
   115  	}
   116  }
   117  
   118  func Test_sliceInjector_zeroElem(t *testing.T) {
   119  	tests := []struct {
   120  		name      string
   121  		dest      interface{}
   122  		wantValue interface{}
   123  	}{
   124  		{"[]int", []int{}, intPtr(0)},
   125  		{"[]string", []string{}, stringPtr("")},
   126  		{"[]interface", []interface{}{}, new(interface{})},
   127  		{"[1]interface", [1]interface{}{}, new(interface{})},
   128  	}
   129  	for _, tt := range tests {
   130  		t.Run(tt.name, func(t *testing.T) {
   131  			dest := pointerTo(reflect.ValueOf(tt.dest)).Elem()
   132  			i, err := newSliceInjector(dest)
   133  			require.NoError(t, err)
   134  			gotValue, gotErr := i.zeroElem(-1, nil)
   135  			assert.Equal(t, tt.wantValue, gotValue)
   136  			assert.NoError(t, gotErr)
   137  		})
   138  	}
   139  }
   140  
   141  func Test_structInjector_zeroElem(t *testing.T) {
   142  	tests := []struct {
   143  		name      string
   144  		key       interface{}
   145  		wantValue interface{}
   146  		wantErr   string
   147  	}{
   148  		{"by index value", 0, new(int), ""},
   149  		{"by index pointer", 1, new(string), ""},
   150  		{"by index slice", 2, new([]int), ""},
   151  		{"by index pointer slice", 3, new([]*string), ""},
   152  		{"by index array", 4, new([2]int), ""},
   153  		{"by index pointer array", 5, new([2]*string), ""},
   154  		{"by index map", 6, new(map[string]interface{}), ""},
   155  		{"by index untyped", 7, new(interface{}), ""},
   156  		{"by index out of range neg", -1, nil, "no accessible field with index -1 found in struct datacodec.testStruct"},
   157  		{"by index out of range pos", 100, nil, "no accessible field with index 100 found in struct datacodec.testStruct"},
   158  		{"by name value", "value", new(int), ""},
   159  		{"by name pointer", "pointer", new(string), ""},
   160  		{"by name slice", "slice", new([]int), ""},
   161  		{"by name pointer slice", "pointer_slice", new([]*string), ""},
   162  		{"by name array", "array", new([2]int), ""},
   163  		{"by name pointer array", "pointer_array", new([2]*string), ""},
   164  		{"by name map", "MAP", new(map[string]interface{}), ""},
   165  		{"by name untyped", "Untyped", new(interface{}), ""},
   166  		{"by name unexported", "unexported", nil, "no accessible field with name 'unexported' found in struct datacodec.testStruct"},
   167  		{"by name nonexistent", "nonexistent", nil, "no accessible field with name 'nonexistent' found in struct datacodec.testStruct"},
   168  		{"wrong key", true, nil, "wrong struct field key, expected int or string, got: bool"},
   169  	}
   170  	for _, tt := range tests {
   171  		t.Run(tt.name, func(t *testing.T) {
   172  			i, err := newStructInjector(reflect.ValueOf(&testStruct{}).Elem())
   173  			require.NoError(t, err)
   174  			gotValue, gotErr := i.zeroElem(-1, tt.key)
   175  			assert.Equal(t, tt.wantValue, gotValue)
   176  			assertErrorMessage(t, tt.wantErr, gotErr)
   177  		})
   178  	}
   179  }
   180  
   181  func Test_structInjector_zeroKey(t *testing.T) {
   182  	i, _ := newStructInjector(reflect.ValueOf(&testStruct{}).Elem())
   183  	got, err := i.zeroKey(0)
   184  	assert.Equal(t, new(string), got)
   185  	assert.NoError(t, err)
   186  }
   187  
   188  func Test_mapInjector_zeroKey(t *testing.T) {
   189  	tests := []struct {
   190  		name      string
   191  		dest      interface{}
   192  		wantValue interface{}
   193  		wantErr   string
   194  	}{
   195  		{"map[int]int", map[int]int{}, new(int), ""},
   196  		{"map[*int]int", map[*int]int{}, new(int), ""},
   197  		{"map[string]int", map[string]int{}, new(string), ""},
   198  		{"map[interface{}]int", map[interface{}]int{}, interfacePtr(nil), ""},
   199  	}
   200  	for _, tt := range tests {
   201  		t.Run(tt.name, func(t *testing.T) {
   202  			dest := pointerTo(reflect.ValueOf(tt.dest)).Elem()
   203  			i, err := newMapInjector(dest)
   204  			require.NoError(t, err)
   205  			gotValue, gotErr := i.zeroKey(0)
   206  			assert.Equal(t, tt.wantValue, gotValue)
   207  			assertErrorMessage(t, tt.wantErr, gotErr)
   208  		})
   209  	}
   210  }
   211  
   212  func Test_mapInjector_zeroElem(t *testing.T) {
   213  	tests := []struct {
   214  		name      string
   215  		dest      interface{}
   216  		wantValue interface{}
   217  	}{
   218  		{"map[int]int", map[int]int{}, new(int)},
   219  		{"map[int]string", map[int]string{}, new(string)},
   220  		{"map[int]*string", map[int]*string{}, new(string)},
   221  		{"map[string]interface{}", map[string]interface{}{}, interfacePtr(nil)},
   222  		{"map[string][]map[string]interface{}", map[string][]map[string]interface{}{}, new([]map[string]interface{})},
   223  	}
   224  	for _, tt := range tests {
   225  		t.Run(tt.name, func(t *testing.T) {
   226  			dest := pointerTo(reflect.ValueOf(tt.dest)).Elem()
   227  			i, err := newMapInjector(dest)
   228  			require.NoError(t, err)
   229  			gotValue, gotErr := i.zeroElem(-1, "")
   230  			assert.Equal(t, tt.wantValue, gotValue)
   231  			assert.NoError(t, gotErr)
   232  		})
   233  	}
   234  }
   235  
   236  func Test_sliceInjector_setElem(t *testing.T) {
   237  	tests := []struct {
   238  		name    string
   239  		index   int
   240  		value   interface{}
   241  		wasNull bool
   242  		dest    interface{}
   243  		want    interface{}
   244  		wantErr string
   245  	}{
   246  		{"[]int null", 0, new(int), true, []int{0}, []int{0}, ""},
   247  		{"[]int non null", 0, intPtr(1), false, []int{0}, []int{1}, ""},
   248  		{"[]*int null", 0, new(int), true, []*int{nil}, []*int{nil}, ""},
   249  		{"[]*int non null", 0, intPtr(1), false, []*int{nil}, []*int{intPtr(1)}, ""},
   250  		{"[]*int non null multi", 1, intPtr(1), false, []*int{nil, nil}, []*int{nil, intPtr(1)}, ""},
   251  		{"[]int out of range neg", -1, intPtr(1), false, []int{123, 456}, []int{123, 456}, "slice index out of range: -1"},
   252  		{"[]int out of range neg", 2, intPtr(1), false, []int{123, 456}, []int{123, 456}, "slice index out of range: 2"},
   253  		{"[]interface{} null", 0, new(int), true, []interface{}{nil}, []interface{}{nil}, ""},
   254  		{"[]interface{} non null", 0, intPtr(1), false, []interface{}{nil}, []interface{}{1}, ""},
   255  		{"[]int wrong value", 0, stringPtr("abc"), false, []int{123}, []int{123}, "wrong slice element, expected int, got: string"},
   256  		{"[1]int wrong value", 0, stringPtr("abc"), false, [1]int{123}, [1]int{123}, "wrong array element, expected int, got: string"},
   257  	}
   258  	for _, tt := range tests {
   259  		t.Run(tt.name, func(t *testing.T) {
   260  			dest := pointerTo(reflect.ValueOf(tt.dest)).Elem()
   261  			i, err := newSliceInjector(dest)
   262  			require.NoError(t, err)
   263  			gotErr := i.setElem(tt.index, nil, tt.value, false, tt.wasNull)
   264  			assert.Equal(t, tt.want, tt.dest)
   265  			assertErrorMessage(t, tt.wantErr, gotErr)
   266  		})
   267  	}
   268  }
   269  
   270  func Test_structInjector_setElem(t *testing.T) {
   271  	tests := []struct {
   272  		name    string
   273  		key     interface{}
   274  		value   interface{}
   275  		wasNull bool
   276  		want    testStruct
   277  		wantErr string
   278  	}{
   279  		{"by index value null", 0, new(int), true, testStruct{}, ""},
   280  		{"by index value non null", 0, intPtr(1), false, testStruct{Value: 1}, ""},
   281  		{"by index pointer null", 1, new(string), true, testStruct{}, ""},
   282  		{"by index pointer non null", 1, stringPtr("abc"), false, testStruct{Pointer: stringPtr("abc")}, ""},
   283  		{"by index slice null", 2, new([]int), true, testStruct{}, ""},
   284  		{"by index slice non null", 2, &[]int{123, 456}, false, testStruct{Slice: []int{123, 456}}, ""},
   285  		{"by index pointer slice null", 3, new([]*string), true, testStruct{}, ""},
   286  		{"by index pointer slice non null", 3, &[]*string{stringPtr("abc"), nil}, false, testStruct{PointerSlice: []*string{stringPtr("abc"), nil}}, ""},
   287  		{"by index array null", 4, new([2]int), true, testStruct{}, ""},
   288  		{"by index array non null", 4, &[2]int{123, 456}, false, testStruct{Array: [2]int{123, 456}}, ""},
   289  		{"by index pointer array null", 5, new([2]*string), true, testStruct{}, ""},
   290  		{"by index pointer array non null", 5, &[2]*string{stringPtr("abc"), nil}, false, testStruct{PointerArray: [2]*string{stringPtr("abc"), nil}}, ""},
   291  		{"by index map null", 6, new(map[string]interface{}), true, testStruct{}, ""},
   292  		{"by index map non null", 6, &map[string]interface{}{"abc": 123, "def": nil}, false, testStruct{Map: map[string]interface{}{"abc": 123, "def": nil}}, ""},
   293  		{"by index untyped null", 7, new(interface{}), true, testStruct{}, ""},
   294  		{"by index untyped non null", 7, stringPtr("abc"), false, testStruct{Untyped: "abc"}, ""},
   295  		{"by index untyped wrong type", 7, stringPtr("abc"), false, testStruct{Untyped: "abc"}, ""},
   296  		{"by name value null", "Value", new(int), true, testStruct{}, ""},
   297  		{"by name value non null", "Value", intPtr(1), false, testStruct{Value: 1}, ""},
   298  		{"by name pointer null", "Pointer", new(string), true, testStruct{}, ""},
   299  		{"by name pointer non null", "Pointer", stringPtr("abc"), false, testStruct{Pointer: stringPtr("abc")}, ""},
   300  		{"by name slice null", "Slice", new([]int), true, testStruct{}, ""},
   301  		{"by name slice non null", "Slice", &[]int{123, 456}, false, testStruct{Slice: []int{123, 456}}, ""},
   302  		{"by name pointer slice null", "pointer_slice", new([]*string), true, testStruct{}, ""},
   303  		{"by name pointer slice non null", "pointer_slice", &[]*string{stringPtr("abc"), nil}, false, testStruct{PointerSlice: []*string{stringPtr("abc"), nil}}, ""},
   304  		{"by name array null", "array", new([2]int), true, testStruct{}, ""},
   305  		{"by name array non null", "array", &[2]int{123, 456}, false, testStruct{Array: [2]int{123, 456}}, ""},
   306  		{"by name pointer array null", "pointer_array", new([2]*string), true, testStruct{}, ""},
   307  		{"by name pointer array non null", "pointer_array", &[2]*string{stringPtr("abc"), nil}, false, testStruct{PointerArray: [2]*string{stringPtr("abc"), nil}}, ""},
   308  		{"by name map null", "MAP", new(map[string]interface{}), true, testStruct{}, ""},
   309  		{"by name map non null", "Map", &map[string]interface{}{"abc": 123, "def": nil}, false, testStruct{Map: map[string]interface{}{"abc": 123, "def": nil}}, ""},
   310  		{"by name untyped null", "UNTYPED", new(interface{}), true, testStruct{}, ""},
   311  		{"by name untyped non null", "untyped", stringPtr("abc"), false, testStruct{Untyped: "abc"}, ""},
   312  		{"by name untyped wrong type", "untyped", stringPtr("abc"), false, testStruct{Untyped: "abc"}, ""},
   313  		{"wrong key", true, nil, false, testStruct{}, "no accessible field with name 'true' found in struct datacodec.testStruct"},
   314  		{"wrong value", 0, stringPtr("abc"), false, testStruct{}, "wrong struct field value, expected int, got: string"},
   315  	}
   316  	for _, tt := range tests {
   317  		t.Run(tt.name, func(t *testing.T) {
   318  			dest := testStruct{}
   319  			i, err := newStructInjector(reflect.ValueOf(&dest).Elem())
   320  			require.NoError(t, err)
   321  			// setElem expects the field to have been previously cached
   322  			_, err = i.(*structInjector).locateAndStoreField(tt.key)
   323  			if tt.wantErr == "" {
   324  				require.NoError(t, err)
   325  			}
   326  			gotErr := i.setElem(-1, tt.key, tt.value, false, tt.wasNull)
   327  			assert.Equal(t, tt.want, dest)
   328  			assertErrorMessage(t, tt.wantErr, gotErr)
   329  		})
   330  	}
   331  }
   332  
   333  func Test_mapInjector_setElem(t *testing.T) {
   334  	tests := []struct {
   335  		name         string
   336  		key          interface{}
   337  		value        interface{}
   338  		keyWasNull   bool
   339  		valueWasNull bool
   340  		dest         interface{}
   341  		want         interface{}
   342  		wantErr      string
   343  	}{
   344  		{"[string]int value null", stringPtr("abc"), new(int), false, true, map[string]int{}, map[string]int{"abc": 0}, ""},
   345  		{"[string]int value non null", stringPtr("abc"), intPtr(1), false, false, map[string]int{}, map[string]int{"abc": 1}, ""},
   346  		{"[string]*int value null", stringPtr("abc"), new(int), false, true, map[string]*int{}, map[string]*int{"abc": nil}, ""},
   347  		{"[string]*int value non null", stringPtr("abc"), intPtr(1), false, false, map[string]*int{}, map[string]*int{"abc": intPtr(1)}, ""},
   348  		{"[int]interface{} value null", intPtr(123), new(int), false, true, map[int]interface{}{}, map[int]interface{}{123: nil}, ""},
   349  		{"[int]interface{} value non null", intPtr(123), intPtr(456), false, false, map[int]interface{}{}, map[int]interface{}{123: 456}, ""},
   350  		{"[string]int key null", new(string), intPtr(456), true, false, map[string]int{}, map[string]int{"": 456}, ""},
   351  		{"[*string]int key null", new(string), intPtr(456), true, false, map[*string]int{}, map[*string]int{nil: 456}, ""},
   352  		{"[interface{}]int key null", new(int), intPtr(456), true, false, map[interface{}]int{}, map[interface{}]int{nil: 456}, ""},
   353  		{"[string]int key and value null", new(string), new(int), true, true, map[string]int{}, map[string]int{"": 0}, ""},
   354  		{"[*string]int key and value null", new(string), new(int), true, true, map[*string]int{}, map[*string]int{nil: 0}, ""},
   355  		{"[interface{}]int key and value null", new(int), new(int), true, true, map[interface{}]int{}, map[interface{}]int{nil: 0}, ""},
   356  		{"wrong key", intPtr(123), stringPtr("abc"), false, false, map[string]string{}, map[string]string{}, "wrong map key, expected string, got: int"},
   357  		{"wrong value", stringPtr("abc"), intPtr(456), false, false, map[string]string{}, map[string]string{}, "wrong map value, expected string, got: int"},
   358  	}
   359  	for _, tt := range tests {
   360  		t.Run(tt.name, func(t *testing.T) {
   361  			dest := pointerTo(reflect.ValueOf(tt.dest)).Elem()
   362  			i, err := newMapInjector(dest)
   363  			require.NoError(t, err)
   364  			gotErr := i.setElem(-1, tt.key, tt.value, tt.keyWasNull, tt.valueWasNull)
   365  			assert.Equal(t, tt.want, tt.dest)
   366  			assertErrorMessage(t, tt.wantErr, gotErr)
   367  		})
   368  	}
   369  }
   370  
   371  // A special test to check the sequence zero -> decode -> set on various data types.
   372  func Test_injectors_zeroDecodeAndSet(t *testing.T) {
   373  	udt, _ := datatype.NewUserDefined("ks1", "table1", []string{"f1"}, []datatype.DataType{datatype.Int})
   374  	dataTypes := map[datatype.DataType]interface{}{
   375  		datatype.Ascii:   "ascii",
   376  		datatype.Bigint:  int64(123),
   377  		datatype.Blob:    []byte{1, 2, 3},
   378  		datatype.Boolean: true,
   379  		datatype.Counter: int64(456),
   380  		datatype.Date:    datePos,
   381  		datatype.Decimal: CqlDecimal{
   382  			Unscaled: big.NewInt(123456),
   383  			Scale:    -1,
   384  		},
   385  		datatype.Double:                123.456,
   386  		datatype.Duration:              CqlDuration{12, 34, 5678},
   387  		datatype.Float:                 float32(123.456),
   388  		datatype.Inet:                  net.ParseIP("fe80::aede:48ff:fe00:1122"),
   389  		datatype.Int:                   int32(42),
   390  		datatype.Smallint:              int16(42),
   391  		datatype.Time:                  durationSimple,
   392  		datatype.Timestamp:             timestampPosUTC,
   393  		datatype.Timeuuid:              primitive.UUID{0xC0, 0xD1, 0xD2, 0x1E, 0xBB, 0x01, 0x41, 0x96, 0x86, 0xDB, 0xBC, 0x31, 0x7B, 0xC1, 0x79, 0x6A},
   394  		datatype.Tinyint:               int8(42),
   395  		datatype.Uuid:                  primitive.UUID{0xC0, 0xD1, 0xD2, 0x1E, 0xBB, 0x01, 0x41, 0x96, 0x86, 0xDB, 0xBC, 0x31, 0x7B, 0xC1, 0x79, 0x6A},
   396  		datatype.Varchar:               "UTF-8",
   397  		datatype.Varint:                big.NewInt(123456),
   398  		datatype.NewList(datatype.Int): []*int32{int32Ptr(1), int32Ptr(2), int32Ptr(3)},
   399  		datatype.NewSet(datatype.Int):  []*int32{int32Ptr(1), int32Ptr(2), int32Ptr(3)},
   400  		datatype.NewMap(datatype.Int, datatype.Varchar):   map[*int32]*string{int32Ptr(123): stringPtr("abc")},
   401  		datatype.NewTuple(datatype.Int, datatype.Varchar): []interface{}{int32(123), "abc"},
   402  		udt: map[string]interface{}{"f1": int32(123)},
   403  	}
   404  	for dataType, source := range dataTypes {
   405  		t.Run(dataType.AsCql()+" on interface{} receiver", func(t *testing.T) {
   406  			t.Run("slice element", func(t *testing.T) {
   407  				dest := make([]interface{}, 1)
   408  				inj, err := newSliceInjector(reflect.ValueOf(dest))
   409  				require.NoError(t, err)
   410  				testInjectorAndDataType(t, source, inj, dataType, func() interface{} { return dest[0] })
   411  			})
   412  			t.Run("map value", func(t *testing.T) {
   413  				dest := make(map[int]interface{}, 1)
   414  				inj, err := newMapInjector(reflect.ValueOf(dest))
   415  				require.NoError(t, err)
   416  				testInjectorAndDataType(t, source, inj, dataType, func() interface{} { return dest[0] })
   417  			})
   418  			t.Run("struct field", func(t *testing.T) {
   419  				dest := struct{ Field interface{} }{}
   420  				inj, err := newStructInjector(reflect.ValueOf(&dest).Elem())
   421  				require.NoError(t, err)
   422  				testInjectorAndDataType(t, source, inj, dataType, func() interface{} { return dest.Field })
   423  			})
   424  		})
   425  	}
   426  }
   427  
   428  func testInjectorAndDataType(t *testing.T, source interface{}, inj injector, dataType datatype.DataType, actual func() interface{}) {
   429  	zero, err := inj.zeroElem(0, 0)
   430  	require.NoError(t, err)
   431  	elementCodec, err := NewCodec(dataType)
   432  	require.NoError(t, err)
   433  	bytes, err := elementCodec.Encode(source, primitive.ProtocolVersion5)
   434  	require.NoError(t, err)
   435  	wasNull, err := elementCodec.Decode(bytes, zero, primitive.ProtocolVersion5)
   436  	require.NoError(t, err)
   437  	assert.False(t, wasNull)
   438  	err = inj.setElem(0, 0, zero, false, false)
   439  	require.NoError(t, err)
   440  	a := actual()
   441  	if _, ok := dataType.(*datatype.Map); ok {
   442  		assert.Len(t, a, 1)
   443  		assert.IsType(t, map[*int32]*string{}, a)
   444  		for k, v := range a.(map[*int32]*string) {
   445  			assert.Equal(t, int32(123), *k)
   446  			assert.Equal(t, "abc", *v)
   447  		}
   448  		assert.False(t, wasNull)
   449  	} else {
   450  		assert.Equal(t, source, a)
   451  	}
   452  }