github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/segment/encode_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 segment 16 17 import ( 18 "bytes" 19 "testing" 20 21 "github.com/stretchr/testify/assert" 22 23 "github.com/datastax/go-cassandra-native-protocol/compression/lz4" 24 ) 25 26 func Test_codec_EncodeSegment(t *testing.T) { 27 tests := []struct { 28 name string 29 compressor PayloadCompressor 30 segment *Segment 31 expected []byte 32 expectErr bool 33 }{ 34 { 35 "payload 1 byte, self-contained, uncompressed", 36 nil, 37 &Segment{ 38 Header: &Header{IsSelfContained: true}, 39 Payload: &Payload{UncompressedData: []byte{1}}, 40 }, 41 []byte{ 42 // header 43 0b_00000001, // payload length bits 0-7 = 1 44 0b_00000000, // payload length bits 8-15 = 0 45 0b_000000_1_0, // from right to left: payload length bit 16 + self-contained flag + header padding (6 bits) 46 0x72, 0x56, 0xac, // crc24 (already tested separately) 47 // payload 48 0b_00000001, // actual payload 49 0xb, 0x2b, 0x9b, 0xba, // crc32 (already tested separately) 50 }, 51 false, 52 }, 53 { 54 "payload 1 byte, multi-part, uncompressed", 55 nil, 56 &Segment{ 57 Header: &Header{IsSelfContained: false}, 58 Payload: &Payload{UncompressedData: []byte{1}}, 59 }, 60 []byte{ 61 // header 62 0b_00000001, // payload length bits 0-7 = 1 63 0b_00000000, // payload length bits 8-15 = 0 64 0b_000000_0_0, // from right to left: payload length bit 16 + self-contained flag + header padding (6 bits) 65 0x6f, 0x87, 0x15, // crc24 (already tested separately) 66 // payload 67 0b_00000001, // actual payload 68 0xb, 0x2b, 0x9b, 0xba, // crc32 (already tested separately) 69 }, 70 false, 71 }, 72 { 73 "payload 10 bytes, self-contained, uncompressed", 74 nil, 75 &Segment{ 76 Header: &Header{IsSelfContained: true}, 77 Payload: &Payload{UncompressedData: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}}, 78 }, 79 []byte{ 80 // header 81 0b_00001010, // payload length bits 0-7 = 10 82 0b_00000000, // payload length bits 8-15 = 0 83 0b_000000_1_0, // from right to left: payload length bit 16 + self-contained flag + header padding (6 bits) 84 0x8c, 0x68, 0x79, // crc24 (already tested separately) 85 // payload 86 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 87 0xa8, 0x32, 0xfa, 0xdf, // crc32 (already tested separately) 88 }, 89 false, 90 }, 91 { 92 "payload 1 byte, self-contained, compressed header format but uncompressed", 93 lz4.Compressor{}, 94 &Segment{ 95 Header: &Header{IsSelfContained: true}, 96 Payload: &Payload{UncompressedData: []byte{1}}, 97 }, 98 []byte{ 99 // header 100 0b_00000001, // compressed payload length bits 0-7 = 1 101 0b_00000000, // compressed payload length bits 8-15 102 0b_0000000_0, // from right to left: compressed payload length bit 16 + uncompressed payload length bits 0-6 = 0 103 0b_00000000, // uncompressed payload length bits 7-14 104 0b_00000_1_00, // from right to left: uncompressed payload length bits 15-16 + self-contained flag + header padding (5 bits) 105 0x6, 0xa5, 0x87, // crc24 (already tested separately) 106 // payload 107 0x1, // uncompressed payload 108 0xb, 0x2b, 0x9b, 0xba, // crc32 (already tested separately) 109 }, 110 false, 111 }, 112 { 113 "payload 1 byte, multi-part, compressed header format but uncompressed", 114 lz4.Compressor{}, 115 &Segment{ 116 Header: &Header{IsSelfContained: false}, 117 Payload: &Payload{UncompressedData: []byte{1}}, 118 }, 119 []byte{ 120 // header 121 0b_00000001, // compressed payload length bits 0-7 = 1 122 0b_00000000, // compressed payload length bits 8-15 123 0b_0000000_0, // from right to left: compressed payload length bit 16 + uncompressed payload length bits 0-6 = 0 124 0b_00000000, // uncompressed payload length bits 7-14 125 0b_00000_0_00, // from right to left: uncompressed payload length bits 15-16 + self-contained flag + header padding (5 bits) 126 0x37, 0x48, 0x63, // crc24 (already tested separately) 127 // payload 128 0x1, // uncompressed payload 129 0xb, 0x2b, 0x9b, 0xba, // crc32 (already tested separately) 130 }, 131 false, 132 }, 133 { 134 "payload 10 bytes, self-contained, compressed header format but uncompressed", 135 lz4.Compressor{}, 136 &Segment{ 137 Header: &Header{IsSelfContained: true}, 138 Payload: &Payload{UncompressedData: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}}, 139 }, 140 []byte{ 141 // header 142 0b_00001010, // compressed payload length bits 0-7 = 10 143 0b_00000000, // compressed payload length bits 8-15 144 0b_0000000_0, // from right to left: compressed payload length bit 16 + uncompressed payload length bits 0-6 = 0 145 0b_00000000, // uncompressed payload length bits 7-14 146 0b_00000_1_00, // from right to left: uncompressed payload length bits 15-16 + self-contained flag + header padding (5 bits) 147 0x8e, 0xdb, 0x58, // crc24 (already tested separately) 148 // payload 149 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, // uncompressed payload 150 0xa8, 0x32, 0xfa, 0xdf, // crc32 (already tested separately) 151 }, 152 false, 153 }, 154 { 155 "payload 100 bytes, self-contained, compressed", 156 lz4.Compressor{}, 157 &Segment{ 158 Header: &Header{IsSelfContained: true}, 159 Payload: &Payload{UncompressedData: make([]byte, 100)}, 160 }, 161 []byte{ 162 // header 163 0b_00011010, // compressed payload length bits 0-7 = 26 164 0b_00000000, // compressed payload length bits 8-15 165 0b_1100100_0, // from right to left: compressed payload length bit 16 + uncompressed payload length bits 0-6 = 100 166 0b_00000000, // uncompressed payload length bits 7-14 167 0b_00000_1_00, // from right to left: uncompressed payload length bits 15-16 + self-contained flag + header padding (5 bits) 168 0x3a, 0xc7, 0xd7, // crc24 (already tested separately) 169 // payload 170 0x1f, 0x0, 0x1, 0x0, 0x3a, 0x0, 0x2, 0x0, 0x0, 0x2, 0x0, 0xe0, 0x0, 171 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // compressed payload 172 0x3e, 0x52, 0x70, 0xe4, // crc32 (already tested separately) 173 }, 174 false, 175 }, 176 { 177 "payload too large", 178 lz4.Compressor{}, 179 &Segment{ 180 Header: &Header{IsSelfContained: true}, 181 Payload: &Payload{UncompressedData: make([]byte, MaxPayloadLength+1)}, 182 }, 183 nil, 184 true, 185 }, 186 } 187 for _, tt := range tests { 188 t.Run(tt.name, func(t *testing.T) { 189 c := &codec{compressor: tt.compressor} 190 actual := &bytes.Buffer{} 191 err := c.EncodeSegment(tt.segment, actual) 192 if tt.expectErr { 193 assert.Error(t, err) 194 } else { 195 assert.NoError(t, err) 196 assert.Equal(t, tt.expected, actual.Bytes()) 197 } 198 }) 199 } 200 } 201 202 func Test_codec_encodeHeaderUncompressed(t *testing.T) { 203 tests := []struct { 204 name string 205 header *Header 206 expected []byte 207 expectErr bool 208 }{ 209 { 210 "payload length 5, self contained", 211 &Header{ 212 IsSelfContained: true, 213 UncompressedPayloadLength: 5, 214 }, 215 []byte{ 216 0b_00000101, // payload length bits 0-7 = 5 217 0b_00000000, // payload length bits 8-15 = 0 218 0b_000000_1_0, // from right to left: payload length bit 16 + self-contained flag + header padding (6 bits) 219 0x19, 0x99, 0x9a, // crc24 (already tested separately) 220 }, 221 false, 222 }, 223 { 224 "payload length 5, multi-part", 225 &Header{ 226 IsSelfContained: false, 227 UncompressedPayloadLength: 5, 228 }, 229 []byte{ 230 0b_00000101, // payload length bits 0-7 = 5 231 0b_00000000, // payload length bits 8-15 = 0 232 0b_000000_0_0, // from right to left: payload length bit 16 + self-contained flag + header padding (6 bits) 233 0x4, 0x48, 0x23, // crc24 (already tested separately) 234 }, 235 false, 236 }, 237 { 238 "payload length max", 239 &Header{ 240 IsSelfContained: true, 241 UncompressedPayloadLength: MaxPayloadLength, 242 }, 243 []byte{ 244 0b_11111111, // payload length bits 0-7 245 0b_11111111, // payload length bits 8-15 246 0b_000000_1_1, // from right to left: payload length bit 16 + self-contained flag + header padding (6 bits) 247 0x25, 0x40, 0x47, // crc24 (already tested separately) 248 }, 249 false, 250 }, 251 } 252 for _, tt := range tests { 253 t.Run(tt.name, func(t *testing.T) { 254 c := &codec{} 255 actual := &bytes.Buffer{} 256 err := c.encodeHeaderUncompressed(tt.header, actual) 257 if tt.expectErr { 258 assert.Error(t, err) 259 } else { 260 assert.NoError(t, err) 261 assert.Equal(t, tt.expected, actual.Bytes()) 262 } 263 }) 264 } 265 } 266 267 func Test_codec_encodeHeaderCompressed(t *testing.T) { 268 tests := []struct { 269 name string 270 header *Header 271 expected []byte 272 expectErr bool 273 }{ 274 { 275 "payload length 5, self contained", 276 &Header{ 277 IsSelfContained: true, 278 UncompressedPayloadLength: 12, 279 CompressedPayloadLength: 5, 280 }, 281 []byte{ 282 0b_00000101, // compressed payload length bits 0-7 = 5 283 0b_00000000, // compressed payload length bits 8-15 284 0b_0001100_0, // from right to left: compressed payload length bit 16 + uncompressed payload length bits 0-6 = 12 285 0b_00000000, // uncompressed payload length bits 7-14 286 0b_00000_1_00, // from right to left: uncompressed payload length bits 15-16 + self-contained flag + header padding (5 bits) 287 0x9e, 0x8, 0x38, // crc24 (already tested separately) 288 }, 289 false, 290 }, 291 { 292 "payload length 5, multi-part", 293 &Header{ 294 IsSelfContained: false, 295 UncompressedPayloadLength: 12, 296 CompressedPayloadLength: 5, 297 }, 298 []byte{ 299 0b_00000101, // compressed payload length bits 0-7 = 5 300 0b_00000000, // compressed payload length bits 8-15 301 0b_0001100_0, // from right to left: compressed payload length bit 16 + uncompressed payload length bits 0-6 = 12 302 0b_00000000, // uncompressed payload length bits 7-14 303 0b_00000_0_00, // from right to left: uncompressed payload length bits 15-16 + self-contained flag + header padding (5 bits) 304 0xaf, 0xe5, 0xdc, // crc24 (already tested separately) 305 }, 306 false, 307 }, 308 { 309 "payload length max", 310 &Header{ 311 IsSelfContained: true, 312 UncompressedPayloadLength: MaxPayloadLength, 313 CompressedPayloadLength: 50_000, // 0_11000011_01010000 314 }, 315 []byte{ 316 0b_01010000, // compressed payload length bits 0-7 317 0b_11000011, // compressed payload length bits 8-15 318 0b_1111111_0, // from right to left: compressed payload length bit 16 + uncompressed payload length bits 0-6 = 12 319 0b_11111111, // uncompressed payload length bits 7-14 320 0b_00000_1_11, // from right to left: uncompressed payload length bits 15-16 + self-contained flag + header padding (5 bits) 321 0xb4, 0x72, 0xaf, // crc24 (already tested separately) 322 }, 323 false, 324 }, 325 } 326 for _, tt := range tests { 327 t.Run(tt.name, func(t *testing.T) { 328 c := &codec{} 329 actual := &bytes.Buffer{} 330 err := c.encodeHeaderCompressed(tt.header, actual) 331 if tt.expectErr { 332 assert.Error(t, err) 333 } else { 334 assert.NoError(t, err) 335 assert.Equal(t, tt.expected, actual.Bytes()) 336 } 337 }) 338 } 339 }