github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/datacodec/tinyint_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 tinyintZeroBytes = []byte{0x00} 30 tinyintOneBytes = []byte{0x01} 31 tinyintMinusOneBytes = []byte{0xff} 32 tinyintMaxInt8Bytes = []byte{0x7f} 33 tinyintMinInt8Bytes = []byte{0x80} 34 ) 35 36 func Test_tinyintCodec_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", int8NilPtr(), nil, ""}, 47 {"non nil", 1, tinyintOneBytes, ""}, 48 {"conversion failed", uint8(math.MaxUint8), nil, fmt.Sprintf("cannot encode uint8 as CQL tinyint with %v: cannot convert from uint8 to int8: value out of range: 255", version)}, 49 } 50 for _, tt := range tests { 51 t.Run(tt.name, func(t *testing.T) { 52 actual, err := Tinyint.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", int8NilPtr(), nil, "data type tinyint not supported"}, 68 {"non nil", 1, nil, "data type tinyint not supported"}, 69 } 70 for _, tt := range tests { 71 t.Run(tt.name, func(t *testing.T) { 72 actual, err := Tinyint.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_tinyintCodec_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(int8), new(int8), true, ""}, 93 {"non null", tinyintOneBytes, new(int8), int8Ptr(1), false, ""}, 94 {"non null interface", tinyintOneBytes, new(interface{}), interfacePtr(int8(1)), false, ""}, 95 {"read failed", []byte{1, 2}, new(int8), new(int8), false, fmt.Sprintf("cannot decode CQL tinyint as *int8 with %v: cannot read int8: expected 1 bytes but got: 2", version)}, 96 {"conversion failed", tinyintOneBytes, new(float64), new(float64), false, fmt.Sprintf("cannot decode CQL tinyint as *float64 with %v: cannot convert from int8 to *float64: conversion not supported", version)}, 97 } 98 for _, tt := range tests { 99 t.Run(tt.name, func(t *testing.T) { 100 wasNull, err := Tinyint.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(int8), new(int8), true, "data type tinyint not supported"}, 119 {"non null", tinyintOneBytes, new(int8), new(int8), false, "data type tinyint not supported"}, 120 } 121 for _, tt := range tests { 122 t.Run(tt.name, func(t *testing.T) { 123 wasNull, err := Tinyint.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_convertToInt8(t *testing.T) { 134 tests := []struct { 135 name string 136 input interface{} 137 expected int8 138 wasNil bool 139 err string 140 }{ 141 {"from int", int(1), 1, false, ""}, 142 {"from int out of range pos", int(math.MaxInt8 + 1), 0, false, "cannot convert from int to int8: value out of range: 128"}, 143 {"from int out of range neg", int(math.MinInt8 - 1), 0, false, "cannot convert from int to int8: value out of range: -129"}, 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.MaxInt8 + 1), 0, false, "cannot convert from *int to int8: value out of range: 128"}, 147 {"from *int out of range neg", intPtr(math.MinInt8 - 1), 0, false, "cannot convert from *int to int8: value out of range: -129"}, 148 {"from int64", int64(1), 1, false, ""}, 149 {"from int64 out of range pos", int64(math.MaxInt8 + 1), 0, false, "cannot convert from int64 to int8: value out of range: 128"}, 150 {"from int64 out of range neg", int64(math.MinInt8 - 1), 0, false, "cannot convert from int64 to int8: value out of range: -129"}, 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.MaxInt8 + 1), 0, false, "cannot convert from *int64 to int8: value out of range: 128"}, 154 {"from *int64 out of range neg", int64Ptr(math.MinInt8 - 1), 0, false, "cannot convert from *int64 to int8: value out of range: -129"}, 155 {"from int32", int32(1), 1, false, ""}, 156 {"from int32 out of range pos", int32(math.MaxInt8 + 1), 0, false, "cannot convert from int32 to int8: value out of range: 128"}, 157 {"from int32 out of range neg", int32(math.MinInt8 - 1), 0, false, "cannot convert from int32 to int8: value out of range: -129"}, 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.MaxInt8 + 1), 0, false, "cannot convert from *int32 to int8: value out of range: 128"}, 161 {"from *int32 out of range neg", int32Ptr(math.MinInt8 - 1), 0, false, "cannot convert from *int32 to int8: value out of range: -129"}, 162 {"from int16", int16(1), 1, false, ""}, 163 {"from *int16 non nil", int16Ptr(1), 1, false, ""}, 164 {"from *int16 out of range pos", int16Ptr(math.MaxInt8 + 1), 0, false, "cannot convert from *int16 to int8: value out of range: 128"}, 165 {"from *int16 out of range neg", int16Ptr(math.MinInt8 - 1), 0, false, "cannot convert from *int16 to int8: value out of range: -129"}, 166 {"from *int16 nil", int16NilPtr(), 0, true, ""}, 167 {"from int8", int8(1), 1, false, ""}, 168 {"from *int8 non nil", int8Ptr(1), 1, false, ""}, 169 {"from *int8 nil", int8NilPtr(), 0, true, ""}, 170 {"from uint", uint(1), 1, false, ""}, 171 {"from uint out of range", uint(math.MaxInt8 + 1), 0, false, "cannot convert from uint to int8: value out of range: 128"}, 172 {"from *uint non nil", uintPtr(1), 1, false, ""}, 173 {"from *uint nil", uintNilPtr(), 0, true, ""}, 174 {"from *uint out of range", uintPtr(math.MaxInt8 + 1), 0, false, "cannot convert from *uint to int8: value out of range: 128"}, 175 {"from uint64", uint64(1), 1, false, ""}, 176 {"from uint64 out of range", uint64(math.MaxInt8 + 1), 0, false, "cannot convert from uint64 to int8: value out of range: 128"}, 177 {"from *uint64 non nil", uint64Ptr(1), 1, false, ""}, 178 {"from *uint64 nil", uint64NilPtr(), 0, true, ""}, 179 {"from *uint64 out of range", uint64Ptr(math.MaxInt8 + 1), 0, false, "cannot convert from *uint64 to int8: value out of range: 128"}, 180 {"from uint32", uint32(1), 1, false, ""}, 181 {"from uint32 out of range", uint32(math.MaxInt8 + 1), 0, false, "cannot convert from uint32 to int8: value out of range: 128"}, 182 {"from *uint32 non nil", uint32Ptr(1), 1, false, ""}, 183 {"from *uint32 nil", uint32NilPtr(), 0, true, ""}, 184 {"from *uint32 out of range", uint32Ptr(math.MaxInt8 + 1), 0, false, "cannot convert from *uint32 to int8: value out of range: 128"}, 185 {"from uint16", uint16(1), 1, false, ""}, 186 {"from uint16 out of range", uint16(math.MaxInt8 + 1), 0, false, "cannot convert from uint16 to int8: value out of range: 128"}, 187 {"from *uint16 non nil", uint16Ptr(1), 1, false, ""}, 188 {"from *uint16 nil", uint16NilPtr(), 0, true, ""}, 189 {"from *uint16 out of range", uint16Ptr(math.MaxInt8 + 1), 0, false, "cannot convert from *uint16 to int8: value out of range: 128"}, 190 {"from uint8", uint8(1), 1, false, ""}, 191 {"from *uint8 non nil", uint8Ptr(1), 1, false, ""}, 192 {"from *uint8 nil", uint8NilPtr(), 0, true, ""}, 193 {"from string", "1", 1, false, ""}, 194 {"from string malformed", "not a number", 0, false, "cannot convert from string to int8: cannot parse 'not a number'"}, 195 {"from string out of range", strconv.Itoa(math.MaxInt8 + 1), 0, false, "cannot convert from string to int8: cannot parse '128'"}, 196 {"from *string non nil", stringPtr("1"), 1, false, ""}, 197 {"from *string malformed", stringPtr("not a number"), 0, false, "cannot convert from *string to int8: cannot parse 'not a number'"}, 198 {"from *string out of range", stringPtr(strconv.Itoa(math.MaxInt8 + 1)), 0, false, "cannot convert from *string to int8: cannot parse '128'"}, 199 {"from *string nil", stringNilPtr(), 0, true, ""}, 200 {"from untyped nil", nil, 0, true, ""}, 201 {"from unsupported value type", 42.0, 0, false, "cannot convert from float64 to int8: conversion not supported"}, 202 {"from unsupported pointer type", float64Ptr(42.0), 0, false, "cannot convert from *float64 to int8: conversion not supported"}, 203 } 204 for _, tt := range tests { 205 t.Run(tt.name, func(t *testing.T) { 206 dest, wasNil, err := convertToInt8(tt.input) 207 assert.Equal(t, tt.expected, dest) 208 assert.Equal(t, tt.wasNil, wasNil) 209 assertErrorMessage(t, tt.err, err) 210 }) 211 } 212 } 213 214 func Test_convertFromInt8(t *testing.T) { 215 tests := []struct { 216 name string 217 val int8 218 wasNull bool 219 dest interface{} 220 expected interface{} 221 err string 222 }{ 223 {"to *interface{} nil dest", 1, false, interfaceNilPtr(), interfaceNilPtr(), "cannot convert from int8 to *interface {}: destination is nil"}, 224 {"to *interface{} nil source", 0, true, new(interface{}), new(interface{}), ""}, 225 {"to *interface{} non nil", 1, false, new(interface{}), interfacePtr(int8(1)), ""}, 226 {"to *int nil dest", 1, false, intNilPtr(), intNilPtr(), "cannot convert from int8 to *int: destination is nil"}, 227 {"to *int nil source", 0, true, new(int), intPtr(0), ""}, 228 {"to *int non nil", 1, false, new(int), intPtr(1), ""}, 229 {"to *int64 nil dest", 1, false, int64NilPtr(), int64NilPtr(), "cannot convert from int8 to *int64: destination is nil"}, 230 {"to *int64 nil source", 0, true, new(int64), int64Ptr(0), ""}, 231 {"to *int64 non nil", 1, false, new(int64), int64Ptr(1), ""}, 232 {"to *int32 nil dest", 1, false, int32NilPtr(), int32NilPtr(), "cannot convert from int8 to *int32: destination is nil"}, 233 {"to *int32 nil source", 0, true, new(int32), int32Ptr(0), ""}, 234 {"to *int32 non nil", 1, false, new(int32), int32Ptr(1), ""}, 235 {"to *int16 nil dest", 1, false, int16NilPtr(), int16NilPtr(), "cannot convert from int8 to *int16: destination is nil"}, 236 {"to *int16 nil source", 0, true, new(int16), int16Ptr(0), ""}, 237 {"to *int16 non nil", 1, false, new(int16), int16Ptr(1), ""}, 238 {"to *int8 nil dest", 1, false, int8NilPtr(), int8NilPtr(), "cannot convert from int8 to *int8: destination is nil"}, 239 {"to *int8 nil source", 0, true, new(int8), int8Ptr(0), ""}, 240 {"to *int8 non nil", 1, false, new(int8), int8Ptr(1), ""}, 241 {"to *uint nil dest", 1, false, uintNilPtr(), uintNilPtr(), "cannot convert from int8 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 int8 to *uint: value out of range: -1"}, 245 {"to *uint64 nil dest", 1, false, uint64NilPtr(), uint64NilPtr(), "cannot convert from int8 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 int8 to *uint64: value out of range: -1"}, 249 {"to *uint32 nil dest", 1, false, uint32NilPtr(), uint32NilPtr(), "cannot convert from int8 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 int8 to *uint32: value out of range: -1"}, 253 {"to *uint16 nil dest", 1, false, uint16NilPtr(), uint16NilPtr(), "cannot convert from int8 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 int8 to *uint16: value out of range: -1"}, 257 {"to *uint8 nil dest", 1, false, uint8NilPtr(), uint8NilPtr(), "cannot convert from int8 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 neg", -1, false, new(uint8), uint8Ptr(0), "cannot convert from int8 to *uint8: value out of range: -1"}, 261 {"to *string nil dest", 1, false, stringNilPtr(), stringNilPtr(), "cannot convert from int8 to *string: destination is nil"}, 262 {"to *string nil source", 0, true, new(string), new(string), ""}, 263 {"to *string non nil", 1, false, new(string), stringPtr("1"), ""}, 264 {"to untyped nil", 1, false, nil, nil, "cannot convert from int8 to <nil>: destination is nil"}, 265 {"to non pointer", 1, false, int8(0), int8(0), "cannot convert from int8 to int8: destination is not pointer"}, 266 {"to unsupported pointer type", 1, false, new(float64), new(float64), "cannot convert from int8 to *float64: conversion not supported"}, 267 } 268 for _, tt := range tests { 269 t.Run(tt.name, func(t *testing.T) { 270 err := convertFromInt8(tt.val, tt.wasNull, tt.dest) 271 assert.Equal(t, tt.expected, tt.dest) 272 assertErrorMessage(t, tt.err, err) 273 }) 274 } 275 } 276 277 func Test_writeInt8(t *testing.T) { 278 tests := []struct { 279 name string 280 val int8 281 expected []byte 282 }{ 283 {"zero", 0, tinyintZeroBytes}, 284 {"positive", 1, tinyintOneBytes}, 285 {"negative", -1, tinyintMinusOneBytes}, 286 {"max", math.MaxInt8, tinyintMaxInt8Bytes}, 287 {"min", math.MinInt8, tinyintMinInt8Bytes}, 288 } 289 for _, tt := range tests { 290 t.Run(tt.name, func(t *testing.T) { 291 actual := writeInt8(tt.val) 292 assert.Equal(t, tt.expected, actual) 293 }) 294 } 295 } 296 297 func Test_readInt8(t *testing.T) { 298 tests := []struct { 299 name string 300 source []byte 301 expected int8 302 wasNull bool 303 err string 304 }{ 305 {"nil", nil, 0, true, ""}, 306 {"empty", []byte{}, 0, true, ""}, 307 {"wrong length", []byte{1, 2}, 0, false, "cannot read int8: expected 1 bytes but got: 2"}, 308 {"zero", tinyintZeroBytes, 0, false, ""}, 309 {"positive", tinyintOneBytes, 1, false, ""}, 310 {"negative", tinyintMinusOneBytes, -1, false, ""}, 311 {"max", tinyintMaxInt8Bytes, math.MaxInt8, false, ""}, 312 {"min", tinyintMinInt8Bytes, math.MinInt8, false, ""}, 313 } 314 for _, tt := range tests { 315 t.Run(tt.name, func(t *testing.T) { 316 actual, wasNull, err := readInt8(tt.source) 317 assert.Equal(t, tt.expected, actual) 318 assert.Equal(t, tt.wasNull, wasNull) 319 assertErrorMessage(t, tt.err, err) 320 }) 321 } 322 }