github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/datacodec/uuid_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 "testing" 20 21 "github.com/stretchr/testify/assert" 22 23 "github.com/datastax/go-cassandra-native-protocol/datatype" 24 "github.com/datastax/go-cassandra-native-protocol/primitive" 25 ) 26 27 var ( 28 uuid = primitive.UUID{0xC0, 0xD1, 0xD2, 0x1E, 0xBB, 0x01, 0x41, 0x96, 0x86, 0xDB, 0xBC, 0x31, 0x7B, 0xC1, 0x79, 0x6A} 29 uuidBytes = []byte{0xC0, 0xD1, 0xD2, 0x1E, 0xBB, 0x01, 0x41, 0x96, 0x86, 0xDB, 0xBC, 0x31, 0x7B, 0xC1, 0x79, 0x6A} 30 ) 31 32 func Test_uuidCodec_DataType(t *testing.T) { 33 assert.Equal(t, datatype.Uuid, Uuid.DataType()) 34 assert.Equal(t, datatype.Timeuuid, Timeuuid.DataType()) 35 } 36 37 func Test_uuidCodec_Encode(t *testing.T) { 38 codecs := []Codec{Uuid, Timeuuid} 39 for _, codec := range codecs { 40 t.Run(codec.DataType().AsCql(), func(t *testing.T) { 41 for _, version := range primitive.SupportedProtocolVersions() { 42 t.Run(version.String(), func(t *testing.T) { 43 tests := []struct { 44 name string 45 source interface{} 46 expected []byte 47 err string 48 }{ 49 {"nil", nil, nil, ""}, 50 {"nil pointer", uuidNilPtr(), nil, ""}, 51 {"zero", primitive.UUID{}, (&primitive.UUID{}).Bytes(), ""}, 52 {"non nil", uuid, uuidBytes, ""}, 53 {"non nil pointer", &uuid, uuidBytes, ""}, 54 {"conversion failed", 123, nil, fmt.Sprintf("cannot encode int as CQL %v with %v: cannot convert from int to []uint8: conversion not supported", codec.DataType(), version)}, 55 } 56 for _, tt := range tests { 57 t.Run(tt.name, func(t *testing.T) { 58 actual, err := codec.Encode(tt.source, version) 59 assert.Equal(t, tt.expected, actual) 60 assertErrorMessage(t, tt.err, err) 61 }) 62 } 63 }) 64 } 65 }) 66 } 67 } 68 69 func Test_uuidCodec_Decode(t *testing.T) { 70 codecs := []Codec{Uuid, Timeuuid} 71 for _, codec := range codecs { 72 t.Run(codec.DataType().AsCql(), func(t *testing.T) { 73 for _, version := range primitive.SupportedProtocolVersions() { 74 t.Run(version.String(), func(t *testing.T) { 75 tests := []struct { 76 name string 77 source []byte 78 dest interface{} 79 expected interface{} 80 wasNull bool 81 err string 82 }{ 83 {"null", nil, new(primitive.UUID), new(primitive.UUID), true, ""}, 84 {"zero", []byte{}, new(primitive.UUID), new(primitive.UUID), true, ""}, 85 {"non null", uuidBytes, new(primitive.UUID), &uuid, false, ""}, 86 {"non null interface", uuidBytes, new(interface{}), interfacePtr(uuid), false, ""}, 87 {"invalid", []byte{1, 2, 3}, new(primitive.UUID), new(primitive.UUID), false, fmt.Sprintf("cannot decode CQL %v as *primitive.UUID with %v: cannot read []uint8: expected 16 bytes but got: 3", codec.DataType(), version)}, 88 {"conversion failed", uuidBytes, new(float64), new(float64), false, fmt.Sprintf("cannot decode CQL %v as *float64 with %v: cannot convert from []uint8 to *float64: conversion not supported", codec.DataType(), version)}, 89 } 90 for _, tt := range tests { 91 t.Run(tt.name, func(t *testing.T) { 92 wasNull, err := codec.Decode(tt.source, tt.dest, version) 93 assert.Equal(t, tt.expected, tt.dest) 94 assert.Equal(t, tt.wasNull, wasNull) 95 assertErrorMessage(t, tt.err, err) 96 }) 97 } 98 }) 99 } 100 }) 101 } 102 } 103 104 func Test_convertToUuid(t *testing.T) { 105 tests := []struct { 106 name string 107 source interface{} 108 wantDest []byte 109 wantErr string 110 }{ 111 {"from primitive.UUID", uuid, uuidBytes, ""}, 112 {"from *primitive.UUID", &uuid, uuidBytes, ""}, 113 {"from *primitive.UUID nil", uuidNilPtr(), nil, ""}, 114 {"from []byte", uuidBytes, uuidBytes, ""}, 115 {"from []byte wrong length", []byte{1, 2, 3}, nil, "cannot convert from []uint8 to []uint8: expected 16 bytes but got: 3"}, 116 {"from []byte wrong length oversize", []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, nil, "cannot convert from []uint8 to []uint8: expected 16 bytes but got: 17"}, 117 {"from *[]byte", &uuidBytes, uuidBytes, ""}, 118 {"from *[]byte nil", byteSliceNilPtr(), nil, ""}, 119 {"from *[]byte wrong length", &[]byte{1, 2, 3}, nil, "cannot convert from *[]uint8 to []uint8: expected 16 bytes but got: 3"}, 120 {"from *[]byte wrong length oversize", &[]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, nil, "cannot convert from *[]uint8 to []uint8: expected 16 bytes but got: 17"}, 121 {"from [16]byte", [16]byte(uuid), uuidBytes, ""}, 122 {"from *[16]byte", byteArrayPtr(uuid), uuidBytes, ""}, 123 {"from *[16]byte nil", byteArrayNilPtr(), nil, ""}, 124 {"from string", uuid.String(), uuidBytes, ""}, 125 {"from string wrong", "not a valid uuid", nil, "cannot convert from string to []uint8: invalid UUID: \"not a valid uuid\""}, 126 {"from *string", stringPtr(uuid.String()), uuidBytes, ""}, 127 {"from *string nil", byteSliceNilPtr(), nil, ""}, 128 {"from *string wrong", stringPtr("not a valid uuid"), nil, "cannot convert from *string to []uint8: invalid UUID: \"not a valid uuid\""}, 129 {"from untyped nil", nil, nil, ""}, 130 {"from unsupported value type", 123, nil, "cannot convert from int to []uint8: conversion not supported"}, 131 {"from unsupported pointer type", intPtr(123), nil, "cannot convert from *int to []uint8: conversion not supported"}, 132 } 133 for _, tt := range tests { 134 t.Run(tt.name, func(t *testing.T) { 135 gotDest, gotErr := convertToUuidBytes(tt.source) 136 assert.Equal(t, tt.wantDest, gotDest) 137 assertErrorMessage(t, tt.wantErr, gotErr) 138 }) 139 } 140 } 141 142 func Test_convertFromUuid(t *testing.T) { 143 tests := []struct { 144 name string 145 val []byte 146 wasNull bool 147 dest interface{} 148 expected interface{} 149 err string 150 }{ 151 {"to *interface{} nil dest", uuidBytes, false, interfaceNilPtr(), interfaceNilPtr(), "cannot convert from []uint8 to *interface {}: destination is nil"}, 152 {"to *interface{} nil source", nil, true, new(interface{}), new(interface{}), ""}, 153 {"to *interface{} non nil", uuidBytes, false, new(interface{}), interfacePtr(uuid), ""}, 154 {"to *primitive.UUID nil dest", uuidBytes, false, uuidNilPtr(), uuidNilPtr(), "cannot convert from []uint8 to *primitive.UUID: destination is nil"}, 155 {"to *primitive.UUID empty source", []byte{}, true, new(primitive.UUID), new(primitive.UUID), ""}, 156 {"to *primitive.UUID wrong length", []byte{1, 2, 3}, false, new(primitive.UUID), &primitive.UUID{1, 2, 3}, ""}, 157 {"to *primitive.UUID wrong length oversize", []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, false, new(primitive.UUID), &primitive.UUID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, ""}, 158 {"to *primitive.UUID non nil", uuidBytes, false, new(primitive.UUID), &uuid, ""}, 159 {"to *[]byte nil dest", uuidBytes, false, byteSliceNilPtr(), byteSliceNilPtr(), "cannot convert from []uint8 to *[]uint8: destination is nil"}, 160 {"to *[]byte empty source", []byte{}, true, new([]byte), new([]byte), ""}, 161 {"to *[]byte non nil", uuidBytes, false, new([]byte), &uuidBytes, ""}, 162 {"to *[]byte wrong length", []byte{1, 2, 3}, false, new([]byte), &[]byte{1, 2, 3}, ""}, 163 {"to *[]byte wrong length oversize", []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, false, new([]byte), &[]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, ""}, 164 {"to *[16]byte nil dest", uuidBytes, false, byteArrayNilPtr(), byteArrayNilPtr(), "cannot convert from []uint8 to *[16]uint8: destination is nil"}, 165 {"to *[16]byte empty source", []byte{}, true, new([16]byte), new([16]byte), ""}, 166 {"to *[16]byte non nil", uuidBytes, false, new([16]byte), byteArrayPtr(uuid), ""}, 167 {"to *[16]byte wrong length", []byte{1, 2, 3}, false, new([16]byte), &[16]byte{1, 2, 3}, ""}, 168 {"to *[16]byte wrong length oversize", []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, false, new([16]byte), &[16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, ""}, 169 {"to *string nil dest", uuidBytes, false, stringNilPtr(), stringNilPtr(), "cannot convert from []uint8 to *string: destination is nil"}, 170 {"to *string empty source", []byte{}, true, new(string), new(string), ""}, 171 {"to *string non nil", uuidBytes, false, new(string), stringPtr(uuid.String()), ""}, 172 {"to *string wrong length", []byte{1, 2, 3}, false, new(string), stringPtr("01020300-0000-0000-0000-000000000000"), ""}, 173 {"to *string wrong length oversize", []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, false, new(string), stringPtr("01020304-0506-0708-090a-0b0c0d0e0f10"), ""}, 174 {"to untyped nil", uuidBytes, false, nil, nil, "cannot convert from []uint8 to <nil>: destination is nil"}, 175 {"to non pointer", uuidBytes, false, primitive.UUID{}, primitive.UUID{}, "cannot convert from []uint8 to primitive.UUID: destination is not pointer"}, 176 {"to unsupported pointer type", uuidBytes, false, new(float64), new(float64), "cannot convert from []uint8 to *float64: conversion not supported"}, 177 } 178 for _, tt := range tests { 179 t.Run(tt.name, func(t *testing.T) { 180 gotErr := convertFromUuidBytes(tt.val, tt.wasNull, tt.dest) 181 assert.Equal(t, tt.expected, tt.dest) 182 assertErrorMessage(t, tt.err, gotErr) 183 }) 184 } 185 } 186 187 func Test_readUuid(t *testing.T) { 188 tests := []struct { 189 name string 190 source []byte 191 expected []byte 192 wasNull bool 193 err string 194 }{ 195 {"null", nil, nil, true, ""}, 196 {"empty", []byte{}, nil, true, ""}, 197 {"wrong length", []byte{1}, nil, false, "cannot read []uint8: expected 16 bytes but got: 1"}, 198 {"non null", uuidBytes, uuidBytes, false, ""}, 199 } 200 for _, tt := range tests { 201 t.Run(tt.name, func(t *testing.T) { 202 actual, wasNull, err := readUuid(tt.source) 203 assert.Equal(t, tt.expected, actual) 204 assert.Equal(t, tt.wasNull, wasNull) 205 assertErrorMessage(t, tt.err, err) 206 }) 207 } 208 }