github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/message/supported_test.go (about) 1 // Copyright 2020 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 message 16 17 import ( 18 "bytes" 19 "errors" 20 "testing" 21 22 "github.com/stretchr/testify/assert" 23 24 "github.com/datastax/go-cassandra-native-protocol/primitive" 25 ) 26 27 func TestSupported_DeepCopy(t *testing.T) { 28 msg := &Supported{ 29 Options: map[string][]string{ 30 "opt1": {"val1"}, 31 "opt2": {"val2"}, 32 }, 33 } 34 35 cloned := msg.DeepCopy() 36 assert.Equal(t, msg, cloned) 37 38 cloned.Options["opt1"] = []string{"val5"} 39 cloned.Options["opt3"] = []string{"val6"} 40 41 assert.NotEqual(t, msg, cloned) 42 43 assert.Equal(t, "val1", msg.Options["opt1"][0]) 44 assert.Equal(t, "val2", msg.Options["opt2"][0]) 45 46 assert.Equal(t, "val5", cloned.Options["opt1"][0]) 47 assert.Equal(t, "val2", cloned.Options["opt2"][0]) 48 assert.Equal(t, "val6", cloned.Options["opt3"][0]) 49 } 50 51 func TestSupportedCodec_Encode(test *testing.T) { 52 codec := &supportedCodec{} 53 for _, version := range primitive.SupportedProtocolVersions() { 54 test.Run(version.String(), func(test *testing.T) { 55 tests := []struct { 56 name string 57 input Message 58 expected [][]byte // required because there can be multiple valid encodings 59 err error 60 }{ 61 { 62 "supported with nil options", 63 &Supported{}, 64 [][]byte{{0, 0}}, 65 nil, 66 }, 67 { 68 "supported with empty options", 69 &Supported{Options: map[string][]string{}}, 70 [][]byte{{0, 0}}, 71 nil, 72 }, 73 { 74 "supported with 1 option", 75 &Supported{Options: map[string][]string{"option1": {"value1a", "value1b"}}}, 76 [][]byte{{ 77 0, 1, // map length 78 // key "option1" 79 0, 7, o, p, t, i, o, n, _1, 80 // list length 81 0, 2, 82 // value1a 83 0, 7, v, a, l, u, e, _1, a, 84 // value1b 85 0, 7, v, a, l, u, e, _1, b, 86 }}, 87 nil, 88 }, 89 { 90 "supported with 2 options", 91 &Supported{Options: map[string][]string{"option1": {"value1a", "value1b"}, "option2": {"value2a", "value2b"}}}, 92 // we have two possible encodings because maps do not have deterministic iteration order 93 [][]byte{ 94 { 95 0, 2, // map length 96 // key "option1" 97 0, 7, o, p, t, i, o, n, _1, 98 // list length 99 0, 2, 100 // value1a 101 0, 7, v, a, l, u, e, _1, a, 102 // value1b 103 0, 7, v, a, l, u, e, _1, b, 104 // key "option2" 105 0, 7, o, p, t, i, o, n, _2, 106 // list length 107 0, 2, 108 // value1a 109 0, 7, v, a, l, u, e, _2, a, 110 // value1b 111 0, 7, v, a, l, u, e, _2, b, 112 }, 113 { 114 0, 2, // map length 115 // key "option2" 116 0, 7, o, p, t, i, o, n, _2, 117 // list length 118 0, 2, 119 // value1a 120 0, 7, v, a, l, u, e, _2, a, 121 // value1b 122 0, 7, v, a, l, u, e, _2, b, 123 // key "option1" 124 0, 7, o, p, t, i, o, n, _1, 125 // list length 126 0, 2, 127 // value1a 128 0, 7, v, a, l, u, e, _1, a, 129 // value1b 130 0, 7, v, a, l, u, e, _1, b, 131 }, 132 }, 133 nil, 134 }, 135 { 136 "not a supported", 137 &Options{}, 138 nil, 139 errors.New("expected *message.Supported, got *message.Options"), 140 }, 141 } 142 for _, tt := range tests { 143 test.Run(tt.name, func(t *testing.T) { 144 dest := &bytes.Buffer{} 145 err := codec.Encode(tt.input, dest, version) 146 if err == nil { 147 assert.Contains(t, tt.expected, dest.Bytes()) 148 assert.Nil(t, tt.err) 149 } else { 150 assert.Equal(t, tt.err, err) 151 } 152 }) 153 } 154 }) 155 } 156 } 157 158 func TestSupportedCodec_EncodedLength(test *testing.T) { 159 codec := &supportedCodec{} 160 for _, version := range primitive.SupportedProtocolVersions() { 161 test.Run(version.String(), func(test *testing.T) { 162 tests := []encodedLengthTestCase{ 163 { 164 "supported with nil options", 165 &Supported{}, 166 primitive.LengthOfShort, // map length 167 nil, 168 }, 169 { 170 "supported with empty options", 171 &Supported{Options: map[string][]string{}}, 172 primitive.LengthOfShort, // map length 173 nil, 174 }, 175 { 176 "supported with 1 option", 177 &Supported{Options: map[string][]string{"option1": {"value1a", "value1b"}}}, 178 primitive.LengthOfShort + // map length 179 primitive.LengthOfString("option1") + // map key 180 primitive.LengthOfShort + // list length 181 primitive.LengthOfString("value1a") + // map value 182 primitive.LengthOfString("value1b"), // map value 183 nil, 184 }, 185 { 186 "supported with 2 options", 187 &Supported{Options: map[string][]string{"option1": {"value1a", "value1b"}, "option2": {"value2a", "value2b"}}}, 188 primitive.LengthOfShort + // map length 189 primitive.LengthOfString("option1") + // map key 190 primitive.LengthOfShort + // list length 191 primitive.LengthOfString("value1a") + // map value 192 primitive.LengthOfString("value1b") + // map value 193 primitive.LengthOfString("option2") + // map key 194 primitive.LengthOfShort + // list length 195 primitive.LengthOfString("value2a") + // map value 196 primitive.LengthOfString("value2b"), // map value 197 nil, 198 }, 199 { 200 "not a supported", 201 &Options{}, 202 -1, 203 errors.New("expected *message.Supported, got *message.Options"), 204 }, 205 } 206 for _, tt := range tests { 207 test.Run(tt.name, func(t *testing.T) { 208 actual, err := codec.EncodedLength(tt.input, version) 209 assert.Equal(t, tt.expected, actual) 210 assert.Equal(t, tt.err, err) 211 }) 212 } 213 }) 214 } 215 } 216 217 func TestSupportedCodec_Decode(test *testing.T) { 218 codec := &supportedCodec{} 219 for _, version := range primitive.SupportedProtocolVersions() { 220 test.Run(version.String(), func(test *testing.T) { 221 tests := []decodeTestCase{ 222 { 223 "supported with empty options", 224 []byte{0, 0}, 225 &Supported{Options: map[string][]string{}}, 226 nil, 227 }, 228 { 229 "supported with 1 option", 230 []byte{ 231 0, 1, // map length 232 // key "option1" 233 0, 7, o, p, t, i, o, n, _1, 234 // list length 235 0, 2, 236 // value1a 237 0, 7, v, a, l, u, e, _1, a, 238 // value1b 239 0, 7, v, a, l, u, e, _1, b, 240 }, 241 &Supported{Options: map[string][]string{"option1": {"value1a", "value1b"}}}, 242 nil, 243 }, 244 { 245 "supported with 2 options", 246 // we have two possible encodings because maps do not have deterministic iteration order 247 []byte{ 248 0, 2, // map length 249 // key "option1" 250 0, 7, o, p, t, i, o, n, _1, 251 // list length 252 0, 2, 253 // value1a 254 0, 7, v, a, l, u, e, _1, a, 255 // value1b 256 0, 7, v, a, l, u, e, _1, b, 257 // key "option2" 258 0, 7, o, p, t, i, o, n, _2, 259 // list length 260 0, 2, 261 // value1a 262 0, 7, v, a, l, u, e, _2, a, 263 // value1b 264 0, 7, v, a, l, u, e, _2, b, 265 }, 266 &Supported{Options: map[string][]string{"option1": {"value1a", "value1b"}, "option2": {"value2a", "value2b"}}}, 267 nil, 268 }, 269 } 270 for _, tt := range tests { 271 test.Run(tt.name, func(t *testing.T) { 272 source := bytes.NewBuffer(tt.input) 273 actual, err := codec.Decode(source, version) 274 assert.Equal(t, tt.expected, actual) 275 assert.Equal(t, tt.err, err) 276 }) 277 } 278 }) 279 } 280 }