github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/datacodec/smallint_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 smallintZeroBytes = encodeUint16(0x0000) 30 smallintOneBytes = encodeUint16(0x0001) 31 smallintMinusOneBytes = encodeUint16(0xffff) 32 smallintMaxInt16Bytes = encodeUint16(0x7fff) 33 smallintMinInt16Bytes = encodeUint16(0x8000) 34 ) 35 36 func Test_smallintCodec_Encode(t *testing.T) { 37 for _, version := range primitive.SupportedProtocolVersionsGreaterThanOrEqualTo(primitive.ProtocolVersion4) { 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", int16NilPtr(), nil, ""}, 47 {"non nil", 1, smallintOneBytes, ""}, 48 {"conversion failed", uint16(math.MaxUint16), nil, fmt.Sprintf("cannot encode uint16 as CQL smallint with %v: cannot convert from uint16 to int16: value out of range: 65535", version)}, 49 } 50 for _, tt := range tests { 51 t.Run(tt.name, func(t *testing.T) { 52 actual, err := Smallint.Encode(tt.source, version) 53 assert.Equal(t, tt.expected, actual) 54 assertErrorMessage(t, tt.err, err) 55 }) 56 } 57 }) 58 } 59 for _, version := range primitive.SupportedProtocolVersionsLesserThan(primitive.ProtocolVersion4) { 60 t.Run(version.String(), func(t *testing.T) { 61 tests := []struct { 62 name string 63 source interface{} 64 expected []byte 65 err string 66 }{ 67 {"nil", int16NilPtr(), nil, "data type smallint not supported"}, 68 {"non nil", 1, nil, "data type smallint not supported"}, 69 } 70 for _, tt := range tests { 71 t.Run(tt.name, func(t *testing.T) { 72 actual, err := Smallint.Encode(tt.source, version) 73 assert.Equal(t, tt.expected, actual) 74 assertErrorMessage(t, tt.err, err) 75 }) 76 } 77 }) 78 } 79 } 80 81 func Test_smallintCodec_Decode(t *testing.T) { 82 for _, version := range primitive.SupportedProtocolVersionsGreaterThanOrEqualTo(primitive.ProtocolVersion4) { 83 t.Run(version.String(), func(t *testing.T) { 84 tests := []struct { 85 name string 86 source []byte 87 dest interface{} 88 expected interface{} 89 wasNull bool 90 err string 91 }{ 92 {"null", nil, new(int16), new(int16), true, ""}, 93 {"non null", smallintOneBytes, new(int16), int16Ptr(1), false, ""}, 94 {"non null interface", smallintOneBytes, new(interface{}), interfacePtr(int16(1)), false, ""}, 95 {"read failed", []byte{1}, new(int16), new(int16), false, fmt.Sprintf("cannot decode CQL smallint as *int16 with %v: cannot read int16: expected 2 bytes but got: 1", version)}, 96 {"conversion failed", smallintOneBytes, new(float64), new(float64), false, fmt.Sprintf("cannot decode CQL smallint as *float64 with %v: cannot convert from int16 to *float64: conversion not supported", version)}, 97 } 98 for _, tt := range tests { 99 t.Run(tt.name, func(t *testing.T) { 100 wasNull, err := Smallint.Decode(tt.source, tt.dest, version) 101 assert.Equal(t, tt.expected, tt.dest) 102 assert.Equal(t, tt.wasNull, wasNull) 103 assertErrorMessage(t, tt.err, err) 104 }) 105 } 106 }) 107 } 108 for _, version := range primitive.SupportedProtocolVersionsLesserThan(primitive.ProtocolVersion4) { 109 t.Run(version.String(), func(t *testing.T) { 110 tests := []struct { 111 name string 112 source []byte 113 dest interface{} 114 expected interface{} 115 wasNull bool 116 err string 117 }{ 118 {"null", nil, new(int16), new(int16), true, "data type smallint not supported"}, 119 {"non null", smallintOneBytes, new(int16), new(int16), false, "data type smallint not supported"}, 120 } 121 for _, tt := range tests { 122 t.Run(tt.name, func(t *testing.T) { 123 wasNull, err := Smallint.Decode(tt.source, tt.dest, version) 124 assert.Equal(t, tt.expected, tt.dest) 125 assert.Equal(t, tt.wasNull, wasNull) 126 assertErrorMessage(t, tt.err, err) 127 }) 128 } 129 }) 130 } 131 } 132 133 func Test_convertToInt16(t *testing.T) { 134 tests := []struct { 135 name string 136 input interface{} 137 expected int16 138 wasNil bool 139 err string 140 }{ 141 {"from int", int(1), 1, false, ""}, 142 {"from int out of range pos", int(math.MaxInt16 + 1), 0, false, "cannot convert from int to int16: value out of range: 32768"}, 143 {"from int out of range neg", int(math.MinInt16 - 1), 0, false, "cannot convert from int to int16: value out of range: -32769"}, 144 {"from *int non nil", intPtr(1), 1, false, ""}, 145 {"from *int nil", intNilPtr(), 0, true, ""}, 146 {"from *int out of range pos", intPtr(math.MaxInt16 + 1), 0, false, "cannot convert from *int to int16: value out of range: 32768"}, 147 {"from *int out of range neg", intPtr(math.MinInt16 - 1), 0, false, "cannot convert from *int to int16: value out of range: -32769"}, 148 {"from int64", int64(1), 1, false, ""}, 149 {"from int64 out of range pos", int64(math.MaxInt16 + 1), 0, false, "cannot convert from int64 to int16: value out of range: 32768"}, 150 {"from int64 out of range neg", int64(math.MinInt16 - 1), 0, false, "cannot convert from int64 to int16: value out of range: -32769"}, 151 {"from *int64 non nil", int64Ptr(1), 1, false, ""}, 152 {"from *int64 nil", int64NilPtr(), 0, true, ""}, 153 {"from *int64 out of range pos", int64Ptr(math.MaxInt16 + 1), 0, false, "cannot convert from *int64 to int16: value out of range: 32768"}, 154 {"from *int64 out of range neg", int64Ptr(math.MinInt16 - 1), 0, false, "cannot convert from *int64 to int16: value out of range: -32769"}, 155 {"from int32", int32(1), 1, false, ""}, 156 {"from int32 out of range pos", int32(math.MaxInt16 + 1), 0, false, "cannot convert from int32 to int16: value out of range: 32768"}, 157 {"from int32 out of range neg", int32(math.MinInt16 - 1), 0, false, "cannot convert from int32 to int16: value out of range: -32769"}, 158 {"from *int32 non nil", int32Ptr(1), 1, false, ""}, 159 {"from *int32 nil", int32NilPtr(), 0, true, ""}, 160 {"from *int32 out of range pos", int32Ptr(math.MaxInt16 + 1), 0, false, "cannot convert from *int32 to int16: value out of range: 32768"}, 161 {"from *int32 out of range neg", int32Ptr(math.MinInt16 - 1), 0, false, "cannot convert from *int32 to int16: value out of range: -32769"}, 162 {"from int16", int16(1), 1, false, ""}, 163 {"from *int16 non nil", int16Ptr(1), 1, false, ""}, 164 {"from *int16 nil", int16NilPtr(), 0, true, ""}, 165 {"from int8", int8(1), 1, false, ""}, 166 {"from *int8 non nil", int8Ptr(1), 1, false, ""}, 167 {"from *int8 nil", int8NilPtr(), 0, true, ""}, 168 {"from uint", uint(1), 1, false, ""}, 169 {"from uint out of range", uint(math.MaxInt16 + 1), 0, false, "cannot convert from uint to int16: value out of range: 32768"}, 170 {"from *uint non nil", uintPtr(1), 1, false, ""}, 171 {"from *uint nil", uintNilPtr(), 0, true, ""}, 172 {"from *uint out of range", uintPtr(math.MaxInt16 + 1), 0, false, "cannot convert from *uint to int16: value out of range: 32768"}, 173 {"from uint64", uint64(1), 1, false, ""}, 174 {"from uint64 out of range", uint64(math.MaxInt16 + 1), 0, false, "cannot convert from uint64 to int16: value out of range: 32768"}, 175 {"from *uint64 non nil", uint64Ptr(1), 1, false, ""}, 176 {"from *uint64 nil", uint64NilPtr(), 0, true, ""}, 177 {"from *uint64 out of range", uint64Ptr(math.MaxInt16 + 1), 0, false, "cannot convert from *uint64 to int16: value out of range: 32768"}, 178 {"from uint32", uint32(1), 1, false, ""}, 179 {"from uint32 out of range", uint32(math.MaxInt16 + 1), 0, false, "cannot convert from uint32 to int16: value out of range: 32768"}, 180 {"from *uint32 non nil", uint32Ptr(1), 1, false, ""}, 181 {"from *uint32 nil", uint32NilPtr(), 0, true, ""}, 182 {"from *uint32 out of range", uint32Ptr(math.MaxInt16 + 1), 0, false, "cannot convert from *uint32 to int16: value out of range: 32768"}, 183 {"from uint16", uint16(1), 1, false, ""}, 184 {"from uint16 out of range", uint16(math.MaxInt16 + 1), 0, false, "cannot convert from uint16 to int16: value out of range: 32768"}, 185 {"from *uint16 non nil", uint16Ptr(1), 1, false, ""}, 186 {"from *uint16 nil", uint16NilPtr(), 0, true, ""}, 187 {"from *uint16 out of range", uint16Ptr(math.MaxInt16 + 1), 0, false, "cannot convert from *uint16 to int16: value out of range: 32768"}, 188 {"from uint8", uint8(1), 1, false, ""}, 189 {"from *uint8 non nil", uint8Ptr(1), 1, false, ""}, 190 {"from *uint8 nil", uint8NilPtr(), 0, true, ""}, 191 {"from string", "1", 1, false, ""}, 192 {"from string malformed", "not a number", 0, false, "cannot convert from string to int16: cannot parse 'not a number'"}, 193 {"from string out of range", strconv.Itoa(math.MaxInt16 + 1), 0, false, "cannot convert from string to int16: cannot parse '32768'"}, 194 {"from *string non nil", stringPtr("1"), 1, false, ""}, 195 {"from *string malformed", stringPtr("not a number"), 0, false, "cannot convert from *string to int16: cannot parse 'not a number'"}, 196 {"from *string out of range", stringPtr(strconv.Itoa(math.MaxInt16 + 1)), 0, false, "cannot convert from *string to int16: cannot parse '32768'"}, 197 {"from *string nil", stringNilPtr(), 0, true, ""}, 198 {"from untyped nil", nil, 0, true, ""}, 199 {"from unsupported value type", 42.0, 0, false, "cannot convert from float64 to int16: conversion not supported"}, 200 {"from unsupported pointer type", float64Ptr(42.0), 0, false, "cannot convert from *float64 to int16: conversion not supported"}, 201 } 202 for _, tt := range tests { 203 t.Run(tt.name, func(t *testing.T) { 204 dest, wasNil, err := convertToInt16(tt.input) 205 assert.Equal(t, tt.expected, dest) 206 assert.Equal(t, tt.wasNil, wasNil) 207 assertErrorMessage(t, tt.err, err) 208 }) 209 } 210 } 211 212 func Test_convertFromInt16(t *testing.T) { 213 tests := []struct { 214 name string 215 val int16 216 wasNull bool 217 dest interface{} 218 expected interface{} 219 err string 220 }{ 221 {"to *interface{} nil dest", 1, false, interfaceNilPtr(), interfaceNilPtr(), "cannot convert from int16 to *interface {}: destination is nil"}, 222 {"to *interface{} nil source", 0, true, new(interface{}), new(interface{}), ""}, 223 {"to *interface{} non nil", 1, false, new(interface{}), interfacePtr(int16(1)), ""}, 224 {"to *int nil dest", 1, false, intNilPtr(), intNilPtr(), "cannot convert from int16 to *int: destination is nil"}, 225 {"to *int nil source", 0, true, new(int), intPtr(0), ""}, 226 {"to *int non nil", 1, false, new(int), intPtr(1), ""}, 227 {"to *int64 nil dest", 1, false, int64NilPtr(), int64NilPtr(), "cannot convert from int16 to *int64: destination is nil"}, 228 {"to *int64 nil source", 0, true, new(int64), int64Ptr(0), ""}, 229 {"to *int64 non nil", 1, false, new(int64), int64Ptr(1), ""}, 230 {"to *int32 nil dest", 1, false, int32NilPtr(), int32NilPtr(), "cannot convert from int16 to *int32: destination is nil"}, 231 {"to *int32 nil source", 0, true, new(int32), int32Ptr(0), ""}, 232 {"to *int32 non nil", 1, false, new(int32), int32Ptr(1), ""}, 233 {"to *int16 nil dest", 1, false, int16NilPtr(), int16NilPtr(), "cannot convert from int16 to *int16: destination is nil"}, 234 {"to *int16 nil source", 0, true, new(int16), int16Ptr(0), ""}, 235 {"to *int16 non nil", 1, false, new(int16), int16Ptr(1), ""}, 236 {"to *int8 nil dest", 1, false, int8NilPtr(), int8NilPtr(), "cannot convert from int16 to *int8: destination is nil"}, 237 {"to *int8 nil source", 0, true, new(int8), int8Ptr(0), ""}, 238 {"to *int8 non nil", 1, false, new(int8), int8Ptr(1), ""}, 239 {"to *int8 out of range pos", math.MaxInt8 + 1, false, new(int8), int8Ptr(0), "cannot convert from int16 to *int8: value out of range: 128"}, 240 {"to *int8 out of range neg", math.MinInt8 - 1, false, new(int8), int8Ptr(0), "cannot convert from int16 to *int8: value out of range: -129"}, 241 {"to *uint nil dest", 1, false, uintNilPtr(), uintNilPtr(), "cannot convert from int16 to *uint: destination is nil"}, 242 {"to *uint nil source", 0, true, new(uint), uintPtr(0), ""}, 243 {"to *uint non nil", 1, false, new(uint), uintPtr(1), ""}, 244 {"to *uint out of range neg", -1, false, new(uint), new(uint), "cannot convert from int16 to *uint: value out of range: -1"}, 245 {"to *uint64 nil dest", 1, false, uint64NilPtr(), uint64NilPtr(), "cannot convert from int16 to *uint64: destination is nil"}, 246 {"to *uint64 nil source", 0, true, new(uint64), uint64Ptr(0), ""}, 247 {"to *uint64 non nil", 1, false, new(uint64), uint64Ptr(1), ""}, 248 {"to *uint64 out of range neg", -1, false, new(uint64), uint64Ptr(0), "cannot convert from int16 to *uint64: value out of range: -1"}, 249 {"to *uint32 nil dest", 1, false, uint32NilPtr(), uint32NilPtr(), "cannot convert from int16 to *uint32: destination is nil"}, 250 {"to *uint32 nil source", 0, true, new(uint32), uint32Ptr(0), ""}, 251 {"to *uint32 non nil", 1, false, new(uint32), uint32Ptr(1), ""}, 252 {"to *uint32 out of range neg", -1, false, new(uint32), uint32Ptr(0), "cannot convert from int16 to *uint32: value out of range: -1"}, 253 {"to *uint16 nil dest", 1, false, uint16NilPtr(), uint16NilPtr(), "cannot convert from int16 to *uint16: destination is nil"}, 254 {"to *uint16 nil source", 0, true, new(uint16), uint16Ptr(0), ""}, 255 {"to *uint16 non nil", 1, false, new(uint16), uint16Ptr(1), ""}, 256 {"to *uint16 out of range neg", -1, false, new(uint16), uint16Ptr(0), "cannot convert from int16 to *uint16: value out of range: -1"}, 257 {"to *uint8 nil dest", 1, false, uint8NilPtr(), uint8NilPtr(), "cannot convert from int16 to *uint8: destination is nil"}, 258 {"to *uint8 nil source", 0, true, new(uint8), uint8Ptr(0), ""}, 259 {"to *uint8 non nil", 1, false, new(uint8), uint8Ptr(1), ""}, 260 {"to *uint8 out of range pos", math.MaxUint8 + 1, false, new(uint8), uint8Ptr(0), "cannot convert from int16 to *uint8: value out of range: 256"}, 261 {"to *uint8 out of range neg", -1, false, new(uint8), uint8Ptr(0), "cannot convert from int16 to *uint8: value out of range: -1"}, 262 {"to *string nil dest", 1, false, stringNilPtr(), stringNilPtr(), "cannot convert from int16 to *string: destination is nil"}, 263 {"to *string nil source", 0, true, new(string), new(string), ""}, 264 {"to *string non nil", 1, false, new(string), stringPtr("1"), ""}, 265 {"to untyped nil", 1, false, nil, nil, "cannot convert from int16 to <nil>: destination is nil"}, 266 {"to non pointer", 1, false, int16(0), int16(0), "cannot convert from int16 to int16: destination is not pointer"}, 267 {"to unsupported pointer type", 1, false, new(float64), new(float64), "cannot convert from int16 to *float64: conversion not supported"}, 268 } 269 for _, tt := range tests { 270 t.Run(tt.name, func(t *testing.T) { 271 err := convertFromInt16(tt.val, tt.wasNull, tt.dest) 272 assert.Equal(t, tt.expected, tt.dest) 273 assertErrorMessage(t, tt.err, err) 274 }) 275 } 276 } 277 278 func Test_writeInt16(t *testing.T) { 279 tests := []struct { 280 name string 281 val int16 282 expected []byte 283 }{ 284 {"zero", 0, smallintZeroBytes}, 285 {"positive", 1, smallintOneBytes}, 286 {"negative", -1, smallintMinusOneBytes}, 287 {"max", math.MaxInt16, smallintMaxInt16Bytes}, 288 {"min", math.MinInt16, smallintMinInt16Bytes}, 289 } 290 for _, tt := range tests { 291 t.Run(tt.name, func(t *testing.T) { 292 actual := writeInt16(tt.val) 293 assert.Equal(t, tt.expected, actual) 294 }) 295 } 296 } 297 298 func Test_readInt16(t *testing.T) { 299 tests := []struct { 300 name string 301 source []byte 302 expected int16 303 wasNull bool 304 err string 305 }{ 306 {"nil", nil, 0, true, ""}, 307 {"empty", []byte{}, 0, true, ""}, 308 {"wrong length", []byte{1}, 0, false, "cannot read int16: expected 2 bytes but got: 1"}, 309 {"zero", smallintZeroBytes, 0, false, ""}, 310 {"positive", smallintOneBytes, 1, false, ""}, 311 {"negative", smallintMinusOneBytes, -1, false, ""}, 312 {"max", smallintMaxInt16Bytes, math.MaxInt16, false, ""}, 313 {"min", smallintMinInt16Bytes, math.MinInt16, false, ""}, 314 } 315 for _, tt := range tests { 316 t.Run(tt.name, func(t *testing.T) { 317 actual, wasNull, err := readInt16(tt.source) 318 assert.Equal(t, tt.expected, actual) 319 assert.Equal(t, tt.wasNull, wasNull) 320 assertErrorMessage(t, tt.err, err) 321 }) 322 } 323 }