github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/primitive/vint_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 primitive 16 17 import ( 18 "bytes" 19 "errors" 20 "io" 21 "math" 22 "testing" 23 24 "github.com/stretchr/testify/assert" 25 ) 26 27 var ( 28 vintMaxInt32Bytes = []byte{0xf0, 0xff, 0xff, 0xff, 0xfe} 29 vintMinInt32Bytes = []byte{0xf0, 0xff, 0xff, 0xff, 0xff} 30 vintMaxInt64Bytes = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe} 31 vintMinInt64Bytes = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} 32 ) 33 34 func TestReadUnsignedVint(t *testing.T) { 35 tests := []struct { 36 name string 37 source []byte 38 wantVint uint64 39 wantRead int 40 wantErr string 41 }{ 42 {"1", []byte{1}, 1, 1, ""}, 43 {"2", []byte{2}, 2, 1, ""}, 44 {"3", []byte{3}, 3, 1, ""}, 45 {"max int32", vintMaxInt32Bytes, encodeZigZag(math.MaxInt32), 5, ""}, 46 {"min int32", vintMinInt32Bytes, encodeZigZag(math.MinInt32), 5, ""}, 47 {"max int64", vintMaxInt64Bytes, encodeZigZag(math.MaxInt64), 9, ""}, 48 {"min int64", vintMinInt64Bytes, encodeZigZag(math.MinInt64), 9, ""}, 49 {"empty", []byte{}, 0, 0, "cannot read [unsigned vint]: EOF"}, 50 {"wrong length", []byte{255}, 0, 1, "cannot read [unsigned vint]: EOF"}, 51 {"wrong length 2", []byte{255, 0, 0, 0, 0, 0, 0, 0}, 0, 8, "cannot read [unsigned vint]: unexpected EOF"}, 52 } 53 for _, tt := range tests { 54 t.Run(tt.name, func(t *testing.T) { 55 source := bytes.NewReader(tt.source) 56 gotVint, gotRead, gotErr := ReadUnsignedVint(source) 57 if tt.wantErr == "" { 58 assert.NoError(t, gotErr) 59 } else { 60 assert.EqualError(t, gotErr, tt.wantErr) 61 } 62 assert.Equal(t, tt.wantVint, gotVint) 63 assert.Equal(t, tt.wantRead, gotRead) 64 }) 65 } 66 } 67 68 func TestWriteUnsignedVint(t *testing.T) { 69 tests := []struct { 70 name string 71 val uint64 72 wantBytes []byte 73 wantWritten int 74 wantErr string 75 }{ 76 {"1", 1, []byte{1}, 1, ""}, 77 {"2", 2, []byte{2}, 1, ""}, 78 {"3", 3, []byte{3}, 1, ""}, 79 {"max int32", encodeZigZag(math.MaxInt32), vintMaxInt32Bytes, 5, ""}, 80 {"min int32", encodeZigZag(math.MinInt32), vintMinInt32Bytes, 5, ""}, 81 {"max int64", encodeZigZag(math.MaxInt64), vintMaxInt64Bytes, 9, ""}, 82 {"min int64", encodeZigZag(math.MinInt64), vintMinInt64Bytes, 9, ""}, 83 {"write failed", 0, nil, 0, "cannot write [unsigned vint]: write failed"}, 84 } 85 for _, tt := range tests { 86 t.Run(tt.name, func(t *testing.T) { 87 var dest io.Writer 88 if tt.wantErr == "" { 89 dest = &bytes.Buffer{} 90 } else { 91 dest = mockWriter{} 92 } 93 gotWritten, gotErr := WriteUnsignedVint(tt.val, dest) 94 if tt.wantErr == "" { 95 assert.NoError(t, gotErr) 96 assert.Equal(t, tt.wantBytes, dest.(*bytes.Buffer).Bytes()) 97 } else { 98 assert.EqualError(t, gotErr, tt.wantErr) 99 } 100 assert.Equal(t, tt.wantWritten, gotWritten) 101 }) 102 } 103 } 104 105 func TestLengthOfUnsignedVint(t *testing.T) { 106 assert.Equal(t, 1, LengthOfUnsignedVint(1)) 107 assert.Equal(t, 1, LengthOfUnsignedVint(2)) 108 assert.Equal(t, 1, LengthOfUnsignedVint(3)) 109 assert.Equal(t, 5, LengthOfUnsignedVint(encodeZigZag(math.MaxInt32))) 110 assert.Equal(t, 5, LengthOfUnsignedVint(encodeZigZag(math.MinInt32))) 111 assert.Equal(t, 9, LengthOfUnsignedVint(encodeZigZag(math.MaxInt64))) 112 assert.Equal(t, 9, LengthOfUnsignedVint(encodeZigZag(math.MinInt64))) 113 } 114 115 func TestReadVint(t *testing.T) { 116 tests := []struct { 117 name string 118 source []byte 119 wantVint int64 120 wantRead int 121 err string 122 }{ 123 {"1", []byte{2}, 1, 1, ""}, 124 {"2", []byte{4}, 2, 1, ""}, 125 {"3", []byte{6}, 3, 1, ""}, 126 {"-1", []byte{1}, -1, 1, ""}, 127 {"-2", []byte{3}, -2, 1, ""}, 128 {"-3", []byte{5}, -3, 1, ""}, 129 {"max int32", vintMaxInt32Bytes, math.MaxInt32, 5, ""}, 130 {"min int32", vintMinInt32Bytes, math.MinInt32, 5, ""}, 131 {"max int64", vintMaxInt64Bytes, math.MaxInt64, 9, ""}, 132 {"min int64", vintMinInt64Bytes, math.MinInt64, 9, ""}, 133 {"empty", []byte{}, 0, 0, "cannot read [vint]: cannot read [unsigned vint]: EOF"}, 134 {"wrong length", []byte{255}, 0, 1, "cannot read [vint]: cannot read [unsigned vint]: EOF"}, 135 {"wrong length 2", []byte{255, 0, 0, 0, 0, 0, 0, 0}, 0, 8, "cannot read [vint]: cannot read [unsigned vint]: unexpected EOF"}, 136 } 137 for _, tt := range tests { 138 t.Run(tt.name, func(t *testing.T) { 139 source := bytes.NewReader(tt.source) 140 gotVint, gotRead, err := ReadVint(source) 141 if tt.err == "" { 142 assert.NoError(t, err) 143 } else { 144 assert.EqualError(t, err, tt.err) 145 } 146 assert.Equal(t, tt.wantVint, gotVint) 147 assert.Equal(t, tt.wantRead, gotRead) 148 }) 149 } 150 } 151 152 func TestWriteVint(t *testing.T) { 153 tests := []struct { 154 name string 155 val int64 156 wantBytes []byte 157 wantWritten int 158 wantErr string 159 }{ 160 {"1", 1, []byte{2}, 1, ""}, 161 {"2", 2, []byte{4}, 1, ""}, 162 {"3", 3, []byte{6}, 1, ""}, 163 {"-1", -1, []byte{1}, 1, ""}, 164 {"-2", -2, []byte{3}, 1, ""}, 165 {"-3", -3, []byte{5}, 1, ""}, 166 {"max int32", math.MaxInt32, vintMaxInt32Bytes, 5, ""}, 167 {"min int32", math.MinInt32, vintMinInt32Bytes, 5, ""}, 168 {"max int64", math.MaxInt64, vintMaxInt64Bytes, 9, ""}, 169 {"min int64", math.MinInt64, vintMinInt64Bytes, 9, ""}, 170 {"write failed", 0, nil, 0, "cannot write [vint]: cannot write [unsigned vint]: write failed"}, 171 } 172 for _, tt := range tests { 173 t.Run(tt.name, func(t *testing.T) { 174 var dest io.Writer 175 if tt.wantErr == "" { 176 dest = &bytes.Buffer{} 177 } else { 178 dest = mockWriter{} 179 } 180 gotWritten, gotErr := WriteVint(tt.val, dest) 181 if tt.wantErr == "" { 182 assert.NoError(t, gotErr) 183 assert.Equal(t, tt.wantBytes, dest.(*bytes.Buffer).Bytes()) 184 } else { 185 assert.EqualError(t, gotErr, tt.wantErr) 186 } 187 assert.Equal(t, tt.wantWritten, gotWritten) 188 }) 189 } 190 } 191 192 func TestLengthOfVint(t *testing.T) { 193 assert.Equal(t, 1, LengthOfVint(1)) 194 assert.Equal(t, 1, LengthOfVint(2)) 195 assert.Equal(t, 1, LengthOfVint(3)) 196 assert.Equal(t, 1, LengthOfVint(-1)) 197 assert.Equal(t, 1, LengthOfVint(-2)) 198 assert.Equal(t, 1, LengthOfVint(-3)) 199 assert.Equal(t, 5, LengthOfVint(math.MaxInt32)) 200 assert.Equal(t, 5, LengthOfVint(math.MinInt32)) 201 assert.Equal(t, 9, LengthOfVint(math.MaxInt64)) 202 assert.Equal(t, 9, LengthOfVint(math.MinInt64)) 203 } 204 205 type mockWriter struct{} 206 207 func (m mockWriter) Write(_ []byte) (n int, err error) { return 0, errors.New("write failed") }