github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/datacodec/inet_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 "net" 20 "testing" 21 22 "github.com/stretchr/testify/assert" 23 24 "github.com/datastax/go-cassandra-native-protocol/datatype" 25 "github.com/datastax/go-cassandra-native-protocol/primitive" 26 ) 27 28 var ( 29 inetZero = net.IP{} 30 inetAddr4 = net.IPv4(192, 168, 1, 1).To4() 31 inetAddr6 = net.IP{0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34} 32 ) 33 34 var ( 35 inetAddr4Bytes = []byte{192, 168, 1, 1} 36 inetAddr6Bytes = []byte{0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34} 37 ) 38 39 func Test_inetCodec_DataType(t *testing.T) { 40 assert.Equal(t, datatype.Inet, Inet.DataType()) 41 } 42 43 func Test_inetCodec_Encode(t *testing.T) { 44 for _, version := range primitive.SupportedProtocolVersions() { 45 t.Run(version.String(), func(t *testing.T) { 46 tests := []struct { 47 name string 48 source interface{} 49 expected []byte 50 err string 51 }{ 52 {"nil", nil, nil, ""}, 53 {"nil pointer", new(net.IP), nil, ""}, 54 {"zero", inetZero, nil, ""}, 55 {"non nil v4", inetAddr4, inetAddr4Bytes, ""}, 56 {"non nil v6", inetAddr6, inetAddr6Bytes, ""}, 57 {"non nil v4 pointer", &inetAddr4, inetAddr4Bytes, ""}, 58 {"non nil v6 pointer", &inetAddr6, inetAddr6Bytes, ""}, 59 {"conversion failed", 123, nil, fmt.Sprintf("cannot encode int as CQL inet with %v: cannot convert from int to net.IP: conversion not supported", version)}, 60 } 61 for _, tt := range tests { 62 t.Run(tt.name, func(t *testing.T) { 63 actual, err := Inet.Encode(tt.source, version) 64 assert.Equal(t, tt.expected, actual) 65 assertErrorMessage(t, tt.err, err) 66 }) 67 } 68 }) 69 } 70 } 71 72 func Test_inetCodec_Decode(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(net.IP), new(net.IP), true, ""}, 84 {"zero", []byte{}, new(net.IP), new(net.IP), true, ""}, 85 {"non null v4", inetAddr4Bytes, new(net.IP), &inetAddr4, false, ""}, 86 {"non null v6", inetAddr6Bytes, new(net.IP), &inetAddr6, false, ""}, 87 {"non null interface", inetAddr4Bytes, new(interface{}), interfacePtr(inetAddr4), false, ""}, 88 {"invalid", []byte{1, 2, 3}, new(net.IP), new(net.IP), false, fmt.Sprintf("cannot decode CQL inet as *net.IP with %v: cannot read net.IP: expected 4 or 16 bytes but got: 3", version)}, 89 {"conversion failed", inetAddr4Bytes, new(float64), new(float64), false, fmt.Sprintf("cannot decode CQL inet as *float64 with %v: cannot convert from net.IP to *float64: conversion not supported", version)}, 90 } 91 for _, tt := range tests { 92 t.Run(tt.name, func(t *testing.T) { 93 wasNull, err := Inet.Decode(tt.source, tt.dest, version) 94 assert.Equal(t, tt.expected, tt.dest) 95 assert.Equal(t, tt.wasNull, wasNull) 96 assertErrorMessage(t, tt.err, err) 97 }) 98 } 99 }) 100 } 101 } 102 103 func Test_convertToIP(t *testing.T) { 104 tests := []struct { 105 name string 106 source interface{} 107 wantDest net.IP 108 wantErr string 109 }{ 110 {"from net.IP", inetAddr4, inetAddr4, ""}, 111 {"from *net.IP", &inetAddr4, inetAddr4, ""}, 112 {"from *net.IP nil", netIPNilPtr(), nil, ""}, 113 {"from []byte", inetAddr4Bytes, inetAddr4, ""}, 114 {"from *[]byte", &inetAddr4Bytes, inetAddr4, ""}, 115 {"from *[]byte nil", byteSliceNilPtr(), nil, ""}, 116 {"from *[]byte wrong length", []byte{1, 2, 3}, net.IP{1, 2, 3}, ""}, // will be rejected by writeInet 117 {"from string", inetAddr4.String(), inetAddr4, ""}, 118 {"from string wrong", "not a valid IP", nil, "cannot convert from string to net.IP: cannot parse 'not a valid IP': net.ParseIP(text) failed"}, 119 {"from *string", stringPtr(inetAddr4.String()), inetAddr4, ""}, 120 {"from *string nil", stringNilPtr(), nil, ""}, 121 {"from *string wrong", stringPtr("not a valid IP"), nil, "cannot convert from *string to net.IP: cannot parse 'not a valid IP': net.ParseIP(text) failed"}, 122 {"from untyped nil", nil, nil, ""}, 123 {"from unsupported value type", 123, nil, "cannot convert from int to net.IP: conversion not supported"}, 124 {"from unsupported pointer type", intPtr(123), nil, "cannot convert from *int to net.IP: conversion not supported"}, 125 } 126 for _, tt := range tests { 127 t.Run(tt.name, func(t *testing.T) { 128 gotDest, gotErr := convertToIP(tt.source) 129 assert.Equal(t, tt.wantDest, gotDest) 130 assertErrorMessage(t, tt.wantErr, gotErr) 131 }) 132 } 133 } 134 135 func Test_convertFromIP(t *testing.T) { 136 tests := []struct { 137 name string 138 val net.IP 139 wasNull bool 140 dest interface{} 141 expected interface{} 142 err string 143 }{ 144 {"to *interface{} nil dest", inetAddr4, false, interfaceNilPtr(), interfaceNilPtr(), "cannot convert from net.IP to *interface {}: destination is nil"}, 145 {"to *interface{} nil source", nil, true, new(interface{}), new(interface{}), ""}, 146 {"to *interface{} non nil", inetAddr4, false, new(interface{}), interfacePtr(inetAddr4), ""}, 147 {"to *net.IP nil dest", inetAddr4, false, netIPNilPtr(), netIPNilPtr(), "cannot convert from net.IP to *net.IP: destination is nil"}, 148 {"to *net.IP nil source", nil, true, new(net.IP), new(net.IP), ""}, 149 {"to *net.IP empty source", inetZero, true, new(net.IP), new(net.IP), ""}, 150 {"to *net.IP wrong length", net.IP{1, 2, 3}, false, new(net.IP), &net.IP{1, 2, 3}, ""}, // will be rejected by readInet 151 {"to *net.IP v4 non nil", inetAddr4, false, new(net.IP), &inetAddr4, ""}, 152 {"to *net.IP v6 non nil", inetAddr6, false, new(net.IP), &inetAddr6, ""}, 153 {"to *[]byte nil dest", inetAddr4, false, byteSliceNilPtr(), byteSliceNilPtr(), "cannot convert from net.IP to *[]uint8: destination is nil"}, 154 {"to *[]byte nil source", nil, true, new([]byte), new([]byte), ""}, 155 {"to *[]byte empty source", inetZero, true, new([]byte), new([]byte), ""}, 156 {"to *[]byte v4 non nil", inetAddr4, false, new([]byte), &inetAddr4Bytes, ""}, 157 {"to *[]byte v6 non nil", inetAddr6, false, new([]byte), &inetAddr6Bytes, ""}, 158 {"to *string nil dest", inetAddr4, false, stringNilPtr(), stringNilPtr(), "cannot convert from net.IP to *string: destination is nil"}, 159 {"to *string nil source", nil, true, new(string), new(string), ""}, 160 {"to *string empty source", inetZero, true, new(string), new(string), ""}, 161 {"to *string v4 non nil", inetAddr4, false, new(string), stringPtr(inetAddr4.String()), ""}, 162 {"to *string v6 non nil", inetAddr6, false, new(string), stringPtr(inetAddr6.String()), ""}, 163 {"to untyped nil", inetAddr4, false, nil, nil, "cannot convert from net.IP to <nil>: destination is nil"}, 164 {"to non pointer", inetAddr4, false, net.IP{}, net.IP{}, "cannot convert from net.IP to net.IP: destination is not pointer"}, 165 {"to unsupported pointer type", inetAddr4, false, new(float64), new(float64), "cannot convert from net.IP to *float64: conversion not supported"}, 166 } 167 for _, tt := range tests { 168 t.Run(tt.name, func(t *testing.T) { 169 gotErr := convertFromIP(tt.val, tt.wasNull, tt.dest) 170 assert.Equal(t, tt.expected, tt.dest) 171 assertErrorMessage(t, tt.err, gotErr) 172 }) 173 } 174 } 175 176 func Test_writeInet(t *testing.T) { 177 tests := []struct { 178 name string 179 val net.IP 180 expected []byte 181 err string 182 }{ 183 {"nil", nil, nil, ""}, 184 {"empty", net.IP{}, nil, ""}, 185 {"non nil v4", inetAddr4, inetAddr4Bytes, ""}, 186 {"non nil v6", inetAddr6, inetAddr6Bytes, ""}, 187 {"invalid", net.IP{1, 2, 3}, nil, "cannot write net.IP: expected 4 or 16 bytes but got: 3"}, 188 } 189 for _, tt := range tests { 190 t.Run(tt.name, func(t *testing.T) { 191 actual, err := writeInet(tt.val) 192 assert.Equal(t, tt.expected, actual) 193 assertErrorMessage(t, tt.err, err) 194 }) 195 } 196 } 197 198 func Test_readInet(t *testing.T) { 199 tests := []struct { 200 name string 201 source []byte 202 expected net.IP 203 wasNull bool 204 err string 205 }{ 206 {"nil", nil, nil, true, ""}, 207 {"empty", []byte{}, nil, true, ""}, 208 {"wrong length", []byte{1}, nil, false, "cannot read net.IP: expected 4 or 16 bytes but got: 1"}, 209 {"non nil v4", inetAddr4Bytes, inetAddr4, false, ""}, 210 {"non nil v6", inetAddr6Bytes, inetAddr6, false, ""}, 211 } 212 for _, tt := range tests { 213 t.Run(tt.name, func(t *testing.T) { 214 actual, wasNull, err := readInet(tt.source) 215 assert.Equal(t, tt.expected, actual) 216 assert.Equal(t, tt.wasNull, wasNull) 217 assertErrorMessage(t, tt.err, err) 218 }) 219 } 220 }