github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/datacodec/int_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 "fmt" 19 "math" 20 "strconv" 21 "testing" 22 23 "github.com/stretchr/testify/assert" 24 25 "github.com/datastax/go-cassandra-native-protocol/primitive" 26 ) 27 28 var ( 29 intZeroBytes = encodeUint32(0x00000000) 30 intOneBytes = encodeUint32(0x00000001) 31 intMinusOneBytes = encodeUint32(0xffffffff) 32 intMaxInt32Bytes = encodeUint32(0x7fffffff) 33 intMinInt32Bytes = encodeUint32(0x80000000) 34 ) 35 36 func Test_intCodec_Encode(t *testing.T) { 37 for _, version := range primitive.SupportedProtocolVersions() { 38 t.Run(version.String(), func(t *testing.T) { 39 tests := []struct { 40 name string 41 source interface{} 42 expected []byte 43 err string 44 }{ 45 {"nil", nil, nil, ""}, 46 {"nil pointer", int32NilPtr(), nil, ""}, 47 {"non nil", 1, intOneBytes, ""}, 48 {"conversion failed", uint32(math.MaxUint32), nil, fmt.Sprintf("cannot encode uint32 as CQL int with %v: cannot convert from uint32 to int32: value out of range: 4294967295", version)}, 49 } 50 for _, tt := range tests { 51 t.Run(tt.name, func(t *testing.T) { 52 actual, err := Int.Encode(tt.source, version) 53 assert.Equal(t, tt.expected, actual) 54 assertErrorMessage(t, tt.err, err) 55 }) 56 } 57 }) 58 } 59 } 60 61 func Test_intCodec_Decode(t *testing.T) { 62 for _, version := range primitive.SupportedProtocolVersions() { 63 t.Run(version.String(), func(t *testing.T) { 64 tests := []struct { 65 name string 66 source []byte 67 dest interface{} 68 expected interface{} 69 wasNull bool 70 err string 71 }{ 72 {"null", nil, new(int32), new(int32), true, ""}, 73 {"non null", intOneBytes, new(int32), int32Ptr(1), false, ""}, 74 {"non null interface", intOneBytes, new(interface{}), interfacePtr(int32(1)), false, ""}, 75 {"read failed", []byte{1}, new(int32), new(int32), false, fmt.Sprintf("cannot decode CQL int as *int32 with %v: cannot read int32: expected 4 bytes but got: 1", version)}, 76 {"conversion failed", intOneBytes, new(float64), new(float64), false, fmt.Sprintf("cannot decode CQL int as *float64 with %v: cannot convert from int32 to *float64: conversion not supported", version)}, 77 } 78 for _, tt := range tests { 79 t.Run(tt.name, func(t *testing.T) { 80 wasNull, err := Int.Decode(tt.source, tt.dest, version) 81 assert.Equal(t, tt.expected, tt.dest) 82 assert.Equal(t, tt.wasNull, wasNull) 83 assertErrorMessage(t, tt.err, err) 84 }) 85 } 86 }) 87 } 88 } 89 90 func Test_convertToInt32(t *testing.T) { 91 tests := []struct { 92 name string 93 input interface{} 94 expected int32 95 wasNil bool 96 err string 97 }{ 98 {"from int", int(1), 1, false, ""}, 99 {"from int out of range pos", int(math.MaxInt32 + 1), 0, false, "cannot convert from int to int32: value out of range: 2147483648"}, 100 {"from int out of range neg", int(math.MinInt32 - 1), 0, false, "cannot convert from int to int32: value out of range: -2147483649"}, 101 {"from *int non nil", intPtr(1), 1, false, ""}, 102 {"from *int nil", intNilPtr(), 0, true, ""}, 103 {"from *int out of range pos", intPtr(math.MaxInt32 + 1), 0, false, "cannot convert from *int to int32: value out of range: 2147483648"}, 104 {"from *int out of range neg", intPtr(math.MinInt32 - 1), 0, false, "cannot convert from *int to int32: value out of range: -2147483649"}, 105 {"from int64", int64(1), 1, false, ""}, 106 {"from int64 out of range pos", int64(math.MaxInt32 + 1), 0, false, "cannot convert from int64 to int32: value out of range: 2147483648"}, 107 {"from int64 out of range neg", int64(math.MinInt32 - 1), 0, false, "cannot convert from int64 to int32: value out of range: -2147483649"}, 108 {"from *int64 non nil", int64Ptr(1), 1, false, ""}, 109 {"from *int64 nil", int64NilPtr(), 0, true, ""}, 110 {"from *int64 out of range pos", int64Ptr(math.MaxInt32 + 1), 0, false, "cannot convert from *int64 to int32: value out of range: 2147483648"}, 111 {"from *int64 out of range neg", int64Ptr(math.MinInt32 - 1), 0, false, "cannot convert from *int64 to int32: value out of range: -2147483649"}, 112 {"from int32", int32(1), 1, false, ""}, 113 {"from *int32 non nil", int32Ptr(1), 1, false, ""}, 114 {"from *int32 nil", int32NilPtr(), 0, true, ""}, 115 {"from int16", int16(1), 1, false, ""}, 116 {"from *int16 non nil", int16Ptr(1), 1, false, ""}, 117 {"from *int16 nil", int16NilPtr(), 0, true, ""}, 118 {"from int8", int8(1), 1, false, ""}, 119 {"from *int8 non nil", int8Ptr(1), 1, false, ""}, 120 {"from *int8 nil", int8NilPtr(), 0, true, ""}, 121 {"from uint", uint(1), 1, false, ""}, 122 {"from uint out of range", uint(math.MaxInt32 + 1), 0, false, "cannot convert from uint to int32: value out of range: 2147483648"}, 123 {"from *uint non nil", uintPtr(1), 1, false, ""}, 124 {"from *uint nil", uintNilPtr(), 0, true, ""}, 125 {"from *uint out of range", uintPtr(math.MaxInt32 + 1), 0, false, "cannot convert from *uint to int32: value out of range: 2147483648"}, 126 {"from uint64", uint64(1), 1, false, ""}, 127 {"from uint64 out of range", uint64(math.MaxInt32 + 1), 0, false, "cannot convert from uint64 to int32: value out of range: 2147483648"}, 128 {"from *uint64 non nil", uint64Ptr(1), 1, false, ""}, 129 {"from *uint64 nil", uint64NilPtr(), 0, true, ""}, 130 {"from *uint64 out of range", uint64Ptr(math.MaxInt32 + 1), 0, false, "cannot convert from *uint64 to int32: value out of range: 2147483648"}, 131 {"from uint32", uint32(1), 1, false, ""}, 132 {"from uint32 out of range", uint32(math.MaxInt32 + 1), 0, false, "cannot convert from uint32 to int32: value out of range: 2147483648"}, 133 {"from *uint32 non nil", uint32Ptr(1), 1, false, ""}, 134 {"from *uint32 nil", uint32NilPtr(), 0, true, ""}, 135 {"from *uint32 out of range", uint32Ptr(math.MaxInt32 + 1), 0, false, "cannot convert from *uint32 to int32: value out of range: 2147483648"}, 136 {"from uint16", uint16(1), 1, false, ""}, 137 {"from *uint16 non nil", uint16Ptr(1), 1, false, ""}, 138 {"from *uint16 nil", uint16NilPtr(), 0, true, ""}, 139 {"from uint8", uint8(1), 1, false, ""}, 140 {"from *uint8 non nil", uint8Ptr(1), 1, false, ""}, 141 {"from *uint8 nil", uint8NilPtr(), 0, true, ""}, 142 {"from string", "1", 1, false, ""}, 143 {"from string malformed", "not a number", 0, false, "cannot convert from string to int32: cannot parse 'not a number'"}, 144 {"from string out of range", strconv.Itoa(math.MaxInt32 + 1), 0, false, "cannot convert from string to int32: cannot parse '2147483648'"}, 145 {"from *string non nil", stringPtr("1"), 1, false, ""}, 146 {"from *string malformed", stringPtr("not a number"), 0, false, "cannot convert from *string to int32: cannot parse 'not a number'"}, 147 {"from *string out of range", stringPtr(strconv.Itoa(math.MaxInt32 + 1)), 0, false, "cannot convert from *string to int32: cannot parse '2147483648'"}, 148 {"from *string nil", stringNilPtr(), 0, true, ""}, 149 {"from untyped nil", nil, 0, true, ""}, 150 {"from unsupported value type", 42.0, 0, false, "cannot convert from float64 to int32: conversion not supported"}, 151 {"from unsupported pointer type", float64Ptr(42.0), 0, false, "cannot convert from *float64 to int32: conversion not supported"}, 152 } 153 for _, tt := range tests { 154 t.Run(tt.name, func(t *testing.T) { 155 dest, wasNil, err := convertToInt32(tt.input) 156 assert.Equal(t, tt.expected, dest) 157 assert.Equal(t, tt.wasNil, wasNil) 158 assertErrorMessage(t, tt.err, err) 159 }) 160 } 161 } 162 163 func Test_convertFromInt32(t *testing.T) { 164 tests := []struct { 165 name string 166 val int32 167 wasNull bool 168 dest interface{} 169 expected interface{} 170 err string 171 }{ 172 {"to *interface{} nil dest", 1, false, interfaceNilPtr(), interfaceNilPtr(), "cannot convert from int32 to *interface {}: destination is nil"}, 173 {"to *interface{} nil source", 0, true, new(interface{}), new(interface{}), ""}, 174 {"to *interface{} non nil", 1, false, new(interface{}), interfacePtr(int32(1)), ""}, 175 {"to *int nil dest", 1, false, intNilPtr(), intNilPtr(), "cannot convert from int32 to *int: destination is nil"}, 176 {"to *int nil source", 0, true, new(int), intPtr(0), ""}, 177 {"to *int non nil", 1, false, new(int), intPtr(1), ""}, 178 {"to *int64 nil dest", 1, false, int64NilPtr(), int64NilPtr(), "cannot convert from int32 to *int64: destination is nil"}, 179 {"to *int64 nil source", 0, true, new(int64), int64Ptr(0), ""}, 180 {"to *int64 non nil", 1, false, new(int64), int64Ptr(1), ""}, 181 {"to *int32 nil dest", 1, false, int32NilPtr(), int32NilPtr(), "cannot convert from int32 to *int32: destination is nil"}, 182 {"to *int32 nil source", 0, true, new(int32), int32Ptr(0), ""}, 183 {"to *int32 non nil", 1, false, new(int32), int32Ptr(1), ""}, 184 {"to *int16 nil dest", 1, false, int16NilPtr(), int16NilPtr(), "cannot convert from int32 to *int16: destination is nil"}, 185 {"to *int16 nil source", 0, true, new(int16), int16Ptr(0), ""}, 186 {"to *int16 non nil", 1, false, new(int16), int16Ptr(1), ""}, 187 {"to *int16 out of range pos", math.MaxInt16 + 1, false, new(int16), int16Ptr(0), "cannot convert from int32 to *int16: value out of range: 32768"}, 188 {"to *int16 out of range neg", math.MinInt16 - 1, false, new(int16), int16Ptr(0), "cannot convert from int32 to *int16: value out of range: -32769"}, 189 {"to *int8 nil dest", 1, false, int8NilPtr(), int8NilPtr(), "cannot convert from int32 to *int8: destination is nil"}, 190 {"to *int8 nil source", 0, true, new(int8), int8Ptr(0), ""}, 191 {"to *int8 non nil", 1, false, new(int8), int8Ptr(1), ""}, 192 {"to *int8 out of range pos", math.MaxInt8 + 1, false, new(int8), int8Ptr(0), "cannot convert from int32 to *int8: value out of range: 128"}, 193 {"to *int8 out of range neg", math.MinInt8 - 1, false, new(int8), int8Ptr(0), "cannot convert from int32 to *int8: value out of range: -129"}, 194 {"to *uint nil dest", 1, false, uintNilPtr(), uintNilPtr(), "cannot convert from int32 to *uint: destination is nil"}, 195 {"to *uint nil source", 0, true, new(uint), uintPtr(0), ""}, 196 {"to *uint non nil", 1, false, new(uint), uintPtr(1), ""}, 197 {"to *uint out of range neg", -1, false, new(uint), new(uint), "cannot convert from int32 to *uint: value out of range: -1"}, 198 {"to *uint64 nil dest", 1, false, uint64NilPtr(), uint64NilPtr(), "cannot convert from int32 to *uint64: destination is nil"}, 199 {"to *uint64 nil source", 0, true, new(uint64), uint64Ptr(0), ""}, 200 {"to *uint64 non nil", 1, false, new(uint64), uint64Ptr(1), ""}, 201 {"to *uint64 out of range neg", -1, false, new(uint64), uint64Ptr(0), "cannot convert from int32 to *uint64: value out of range: -1"}, 202 {"to *uint32 nil dest", 1, false, uint32NilPtr(), uint32NilPtr(), "cannot convert from int32 to *uint32: destination is nil"}, 203 {"to *uint32 nil source", 0, true, new(uint32), uint32Ptr(0), ""}, 204 {"to *uint32 non nil", 1, false, new(uint32), uint32Ptr(1), ""}, 205 {"to *uint32 out of range neg", -1, false, new(uint32), uint32Ptr(0), "cannot convert from int32 to *uint32: value out of range: -1"}, 206 {"to *uint16 nil dest", 1, false, uint16NilPtr(), uint16NilPtr(), "cannot convert from int32 to *uint16: destination is nil"}, 207 {"to *uint16 nil source", 0, true, new(uint16), uint16Ptr(0), ""}, 208 {"to *uint16 non nil", 1, false, new(uint16), uint16Ptr(1), ""}, 209 {"to *uint16 out of range pos", math.MaxUint16 + 1, false, new(uint16), uint16Ptr(0), "cannot convert from int32 to *uint16: value out of range: 65536"}, 210 {"to *uint16 out of range neg", -1, false, new(uint16), uint16Ptr(0), "cannot convert from int32 to *uint16: value out of range: -1"}, 211 {"to *uint8 nil dest", 1, false, uint8NilPtr(), uint8NilPtr(), "cannot convert from int32 to *uint8: destination is nil"}, 212 {"to *uint8 nil source", 0, true, new(uint8), uint8Ptr(0), ""}, 213 {"to *uint8 non nil", 1, false, new(uint8), uint8Ptr(1), ""}, 214 {"to *uint8 out of range pos", math.MaxUint8 + 1, false, new(uint8), uint8Ptr(0), "cannot convert from int32 to *uint8: value out of range: 256"}, 215 {"to *uint8 out of range neg", -1, false, new(uint8), uint8Ptr(0), "cannot convert from int32 to *uint8: value out of range: -1"}, 216 {"to *string nil dest", 1, false, stringNilPtr(), stringNilPtr(), "cannot convert from int32 to *string: destination is nil"}, 217 {"to *string nil source", 0, true, new(string), new(string), ""}, 218 {"to *string non nil", 1, false, new(string), stringPtr("1"), ""}, 219 {"to untyped nil", 1, false, nil, nil, "cannot convert from int32 to <nil>: destination is nil"}, 220 {"to non pointer", 1, false, int32(0), int32(0), "cannot convert from int32 to int32: destination is not pointer"}, 221 {"to unsupported pointer type", 1, false, new(float64), new(float64), "cannot convert from int32 to *float64: conversion not supported"}, 222 } 223 for _, tt := range tests { 224 t.Run(tt.name, func(t *testing.T) { 225 err := convertFromInt32(tt.val, tt.wasNull, tt.dest) 226 assert.Equal(t, tt.expected, tt.dest) 227 assertErrorMessage(t, tt.err, err) 228 }) 229 } 230 } 231 232 func Test_writeInt32(t *testing.T) { 233 tests := []struct { 234 name string 235 val int32 236 expected []byte 237 }{ 238 {"zero", 0, intZeroBytes}, 239 {"positive", 1, intOneBytes}, 240 {"negative", -1, intMinusOneBytes}, 241 {"max", math.MaxInt32, intMaxInt32Bytes}, 242 {"min", math.MinInt32, intMinInt32Bytes}, 243 } 244 for _, tt := range tests { 245 t.Run(tt.name, func(t *testing.T) { 246 actual := writeInt32(tt.val) 247 assert.Equal(t, tt.expected, actual) 248 }) 249 } 250 } 251 252 func Test_readInt32(t *testing.T) { 253 tests := []struct { 254 name string 255 source []byte 256 expected int32 257 wasNull bool 258 err string 259 }{ 260 {"nil", nil, 0, true, ""}, 261 {"empty", []byte{}, 0, true, ""}, 262 {"wrong length", []byte{1}, 0, false, "cannot read int32: expected 4 bytes but got: 1"}, 263 {"zero", intZeroBytes, 0, false, ""}, 264 {"positive", intOneBytes, 1, false, ""}, 265 {"negative", intMinusOneBytes, -1, false, ""}, 266 {"max", intMaxInt32Bytes, math.MaxInt32, false, ""}, 267 {"min", intMinInt32Bytes, math.MinInt32, false, ""}, 268 } 269 for _, tt := range tests { 270 t.Run(tt.name, func(t *testing.T) { 271 actual, wasNull, err := readInt32(tt.source) 272 assert.Equal(t, tt.expected, actual) 273 assert.Equal(t, tt.wasNull, wasNull) 274 assertErrorMessage(t, tt.err, err) 275 }) 276 } 277 }