vitess.io/vitess@v0.16.2/go/mysql/encoding_test.go (about)

     1  /*
     2  Copyright 2019 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package mysql
    18  
    19  import (
    20  	"bytes"
    21  	"testing"
    22  
    23  	"github.com/stretchr/testify/assert"
    24  )
    25  
    26  func TestEncLenInt(t *testing.T) {
    27  	tests := []struct {
    28  		value   uint64
    29  		encoded []byte
    30  	}{
    31  		{0x00, []byte{0x00}},
    32  		{0x0a, []byte{0x0a}},
    33  		{0xfa, []byte{0xfa}},
    34  		{0xfb, []byte{0xfc, 0xfb, 0x00}},
    35  		{0xfc, []byte{0xfc, 0xfc, 0x00}},
    36  		{0xfd, []byte{0xfc, 0xfd, 0x00}},
    37  		{0xfe, []byte{0xfc, 0xfe, 0x00}},
    38  		{0xff, []byte{0xfc, 0xff, 0x00}},
    39  		{0x0100, []byte{0xfc, 0x00, 0x01}},
    40  		{0x876a, []byte{0xfc, 0x6a, 0x87}},
    41  		{0xffff, []byte{0xfc, 0xff, 0xff}},
    42  		{0x010000, []byte{0xfd, 0x00, 0x00, 0x01}},
    43  		{0xabcdef, []byte{0xfd, 0xef, 0xcd, 0xab}},
    44  		{0xffffff, []byte{0xfd, 0xff, 0xff, 0xff}},
    45  		{0x01000000, []byte{0xfe, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}},
    46  		{0xa0a1a2a3a4a5a6a7, []byte{0xfe, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0}},
    47  	}
    48  	for _, test := range tests {
    49  		// Check lenEncIntSize first.
    50  		if got := lenEncIntSize(test.value); got != len(test.encoded) {
    51  			t.Errorf("lenEncIntSize returned %v but expected %v for %x", got, len(test.encoded), test.value)
    52  		}
    53  
    54  		// Check successful encoding.
    55  		data := make([]byte, len(test.encoded))
    56  		pos := writeLenEncInt(data, 0, test.value)
    57  		assert.Equal(t, len(test.encoded), pos, "unexpected pos %v after writeLenEncInt(%x), expected %v", pos, test.value, len(test.encoded))
    58  		assert.True(t, bytes.Equal(data, test.encoded), "unexpected encoded value for %x, got %v expected %v", test.value, data, test.encoded)
    59  
    60  		// Check successful encoding with offset.
    61  		data = make([]byte, len(test.encoded)+1)
    62  		pos = writeLenEncInt(data, 1, test.value)
    63  		assert.Equal(t, len(test.encoded)+1, pos, "unexpected pos %v after writeLenEncInt(%x, 1), expected %v", pos, test.value, len(test.encoded)+1)
    64  		assert.True(t, bytes.Equal(data[1:], test.encoded), "unexpected encoded value for %x, got %v expected %v", test.value, data, test.encoded)
    65  
    66  		// Check successful decoding.
    67  		got, pos, ok := readLenEncInt(test.encoded, 0)
    68  		if !ok || got != test.value || pos != len(test.encoded) {
    69  			t.Errorf("readLenEncInt returned %x/%v/%v but expected %x/%v/%v", got, pos, ok, test.value, len(test.encoded), true)
    70  		}
    71  
    72  		// Check failed decoding.
    73  		_, _, ok = readLenEncInt(test.encoded[:len(test.encoded)-1], 0)
    74  		assert.False(t, ok, "readLenEncInt returned ok=true for shorter value %x", test.value)
    75  
    76  	}
    77  }
    78  
    79  func TestEncUint16(t *testing.T) {
    80  	data := make([]byte, 10)
    81  
    82  	val16 := uint16(0xabcd)
    83  
    84  	if got := writeUint16(data, 2, val16); got != 4 {
    85  		t.Errorf("writeUint16 returned %v but expected 4", got)
    86  	}
    87  
    88  	if data[2] != 0xcd || data[3] != 0xab {
    89  		t.Errorf("writeUint16 returned bad result: %v", data)
    90  	}
    91  
    92  	got16, pos, ok := readUint16(data, 2)
    93  	if !ok || got16 != val16 || pos != 4 {
    94  		t.Errorf("readUint16 returned %v/%v/%v but expected %v/%v/%v", got16, pos, ok, val16, 4, true)
    95  	}
    96  
    97  	_, _, ok = readUint16(data, 9)
    98  	assert.False(t, ok, "readUint16 returned ok=true for shorter value")
    99  
   100  }
   101  
   102  func TestEncBytes(t *testing.T) {
   103  	data := make([]byte, 10)
   104  
   105  	if got := writeByte(data, 5, 0xab); got != 6 || data[5] != 0xab {
   106  		t.Errorf("writeByte returned bad result: %v %v", got, data[5])
   107  	}
   108  
   109  	got, pos, ok := readByte(data, 5)
   110  	if !ok || got != 0xab || pos != 6 {
   111  		t.Errorf("readByte returned %v/%v/%v but expected %v/%v/%v", got, pos, ok, 0xab, 6, true)
   112  	}
   113  
   114  	_, _, ok = readByte(data, 10)
   115  	assert.False(t, ok, "readByte returned ok=true for shorter value")
   116  
   117  	b, pos, ok := readBytes(data, 5, 2)
   118  	expected := []byte{0xab, 0x00}
   119  	if !ok || !bytes.Equal(b, expected) || pos != 7 {
   120  		t.Errorf("readBytes returned %v/%v/%v but expected %v/%v/%v", b, pos, ok, expected, 7, true)
   121  	}
   122  
   123  	_, _, ok = readBytes(data, 9, 2)
   124  	assert.False(t, ok, "readBytes returned ok=true for shorter value")
   125  
   126  }
   127  
   128  func TestEncUint32(t *testing.T) {
   129  	data := make([]byte, 10)
   130  
   131  	val32 := uint32(0xabcdef10)
   132  
   133  	if got := writeUint32(data, 2, val32); got != 6 {
   134  		t.Errorf("writeUint32 returned %v but expected 6", got)
   135  	}
   136  
   137  	if data[2] != 0x10 || data[3] != 0xef || data[4] != 0xcd || data[5] != 0xab {
   138  		t.Errorf("writeUint32 returned bad result: %v", data)
   139  	}
   140  
   141  	got32, pos, ok := readUint32(data, 2)
   142  	if !ok || got32 != val32 || pos != 6 {
   143  		t.Errorf("readUint32 returned %v/%v/%v but expected %v/%v/%v", got32, pos, ok, val32, 6, true)
   144  	}
   145  
   146  	_, _, ok = readUint32(data, 7)
   147  	assert.False(t, ok, "readUint32 returned ok=true for shorter value")
   148  
   149  }
   150  
   151  func TestEncUint64(t *testing.T) {
   152  	data := make([]byte, 10)
   153  
   154  	val64 := uint64(0xabcdef1011121314)
   155  
   156  	if got := writeUint64(data, 1, val64); got != 9 {
   157  		t.Errorf("writeUint64 returned %v but expected 9", got)
   158  	}
   159  
   160  	if data[1] != 0x14 || data[2] != 0x13 || data[3] != 0x12 || data[4] != 0x11 ||
   161  		data[5] != 0x10 || data[6] != 0xef || data[7] != 0xcd || data[8] != 0xab {
   162  		t.Errorf("writeUint64 returned bad result: %v", data)
   163  	}
   164  
   165  	got64, pos, ok := readUint64(data, 1)
   166  	if !ok || got64 != val64 || pos != 9 {
   167  		t.Errorf("readUint64 returned %v/%v/%v but expected %v/%v/%v", got64, pos, ok, val64, 6, true)
   168  	}
   169  
   170  	_, _, ok = readUint64(data, 7)
   171  	assert.False(t, ok, "readUint64 returned ok=true for shorter value")
   172  
   173  }
   174  
   175  func TestEncString(t *testing.T) {
   176  	tests := []struct {
   177  		value       string
   178  		lenEncoded  []byte
   179  		nullEncoded []byte
   180  		eofEncoded  []byte
   181  	}{
   182  		{
   183  			"",
   184  			[]byte{0x00},
   185  			[]byte{0x00},
   186  			[]byte{},
   187  		},
   188  		{
   189  			"a",
   190  			[]byte{0x01, 'a'},
   191  			[]byte{'a', 0x00},
   192  			[]byte{'a'},
   193  		},
   194  		{
   195  			"0123456789",
   196  			[]byte{0x0a, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'},
   197  			[]byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0x00},
   198  			[]byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'},
   199  		},
   200  	}
   201  	for _, test := range tests {
   202  		// len encoded tests.
   203  
   204  		// Check lenEncStringSize first.
   205  		if got := lenEncStringSize(test.value); got != len(test.lenEncoded) {
   206  			t.Errorf("lenEncStringSize returned %v but expected %v for %v", got, len(test.lenEncoded), test.value)
   207  		}
   208  
   209  		// Check lenNullString
   210  		if got := lenNullString(test.value); got != len(test.nullEncoded) {
   211  			t.Errorf("lenNullString returned %v but expected %v for %v", got, len(test.nullEncoded), test.value)
   212  		}
   213  
   214  		// Check lenEOFString
   215  		if got := lenEOFString(test.value); got != len(test.eofEncoded) {
   216  			t.Errorf("lenNullString returned %v but expected %v for %v", got, len(test.eofEncoded), test.value)
   217  		}
   218  
   219  		// Check successful encoding.
   220  		data := make([]byte, len(test.lenEncoded))
   221  		pos := writeLenEncString(data, 0, test.value)
   222  		assert.Equal(t, len(test.lenEncoded), pos, "unexpected pos %v after writeLenEncString(%v), expected %v", pos, test.value, len(test.lenEncoded))
   223  		assert.True(t, bytes.Equal(data, test.lenEncoded), "unexpected lenEncoded value for %v, got %v expected %v", test.value, data, test.lenEncoded)
   224  
   225  		// Check successful encoding with offset.
   226  		data = make([]byte, len(test.lenEncoded)+1)
   227  		pos = writeLenEncString(data, 1, test.value)
   228  		assert.Equal(t, len(test.lenEncoded)+1, pos, "unexpected pos %v after writeLenEncString(%v, 1), expected %v", pos, test.value, len(test.lenEncoded)+1)
   229  		assert.True(t, bytes.Equal(data[1:], test.lenEncoded), "unexpected lenEncoded value for %v, got %v expected %v", test.value, data[1:], test.lenEncoded)
   230  
   231  		// Check successful decoding as string.
   232  		got, pos, ok := readLenEncString(test.lenEncoded, 0)
   233  		if !ok || got != test.value || pos != len(test.lenEncoded) {
   234  			t.Errorf("readLenEncString returned %v/%v/%v but expected %v/%v/%v", got, pos, ok, test.value, len(test.lenEncoded), true)
   235  		}
   236  
   237  		// Check failed decoding with shorter data.
   238  		_, _, ok = readLenEncString(test.lenEncoded[:len(test.lenEncoded)-1], 0)
   239  		assert.False(t, ok, "readLenEncString returned ok=true for shorter value %v", test.value)
   240  
   241  		// Check failed decoding with no data.
   242  		_, _, ok = readLenEncString([]byte{}, 0)
   243  		assert.False(t, ok, "readLenEncString returned ok=true for empty value %v", test.value)
   244  
   245  		// Check successful skipping as string.
   246  		pos, ok = skipLenEncString(test.lenEncoded, 0)
   247  		if !ok || pos != len(test.lenEncoded) {
   248  			t.Errorf("skipLenEncString returned %v/%v but expected %v/%v", pos, ok, len(test.lenEncoded), true)
   249  		}
   250  
   251  		// Check failed skipping with shorter data.
   252  		_, ok = skipLenEncString(test.lenEncoded[:len(test.lenEncoded)-1], 0)
   253  		assert.False(t, ok, "skipLenEncString returned ok=true for shorter value %v", test.value)
   254  
   255  		// Check failed skipping with no data.
   256  		_, ok = skipLenEncString([]byte{}, 0)
   257  		assert.False(t, ok, "skipLenEncString returned ok=true for empty value %v", test.value)
   258  
   259  		// Check successful decoding as bytes.
   260  		gotb, pos, ok := readLenEncStringAsBytes(test.lenEncoded, 0)
   261  		if !ok || string(gotb) != test.value || pos != len(test.lenEncoded) {
   262  			t.Errorf("readLenEncString returned %v/%v/%v but expected %v/%v/%v", gotb, pos, ok, test.value, len(test.lenEncoded), true)
   263  		}
   264  
   265  		// Check failed decoding as bytes with shorter data.
   266  		_, _, ok = readLenEncStringAsBytes(test.lenEncoded[:len(test.lenEncoded)-1], 0)
   267  		assert.False(t, ok, "readLenEncStringAsBytes returned ok=true for shorter value %v", test.value)
   268  
   269  		// Check failed decoding as bytes with no data.
   270  		_, _, ok = readLenEncStringAsBytes([]byte{}, 0)
   271  		assert.False(t, ok, "readLenEncStringAsBytes returned ok=true for empty value %v", test.value)
   272  
   273  		// Check successful decoding as bytes.
   274  		gotbcopy, posCopy, ok := readLenEncStringAsBytesCopy(test.lenEncoded, 0)
   275  		if !ok || string(gotb) != test.value || pos != len(test.lenEncoded) {
   276  			t.Errorf("readLenEncString returned %v/%v/%v but expected %v/%v/%v", gotbcopy, posCopy, ok, test.value, len(test.lenEncoded), true)
   277  		}
   278  
   279  		// Check failed decoding as bytes with shorter data.
   280  		_, _, ok = readLenEncStringAsBytesCopy(test.lenEncoded[:len(test.lenEncoded)-1], 0)
   281  		assert.False(t, ok, "readLenEncStringAsBytes returned ok=true for shorter value %v", test.value)
   282  
   283  		// Check failed decoding as bytes with no data.
   284  		_, _, ok = readLenEncStringAsBytesCopy([]byte{}, 0)
   285  		assert.False(t, ok, "readLenEncStringAsBytes returned ok=true for empty value %v", test.value)
   286  
   287  		// null encoded tests.
   288  
   289  		// Check successful encoding.
   290  		data = make([]byte, len(test.nullEncoded))
   291  		pos = writeNullString(data, 0, test.value)
   292  		assert.Equal(t, len(test.nullEncoded), pos, "unexpected pos %v after writeNullString(%v), expected %v", pos, test.value, len(test.nullEncoded))
   293  		assert.True(t, bytes.Equal(data, test.nullEncoded), "unexpected nullEncoded value for %v, got %v expected %v", test.value, data, test.nullEncoded)
   294  
   295  		// Check successful decoding.
   296  		got, pos, ok = readNullString(test.nullEncoded, 0)
   297  		if !ok || got != test.value || pos != len(test.nullEncoded) {
   298  			t.Errorf("readNullString returned %v/%v/%v but expected %v/%v/%v", got, pos, ok, test.value, len(test.nullEncoded), true)
   299  		}
   300  
   301  		// Check failed decoding with shorter data.
   302  		_, _, ok = readNullString(test.nullEncoded[:len(test.nullEncoded)-1], 0)
   303  		assert.False(t, ok, "readNullString returned ok=true for shorter value %v", test.value)
   304  
   305  		// EOF encoded tests.
   306  
   307  		// Check successful encoding.
   308  		data = make([]byte, len(test.eofEncoded))
   309  		pos = writeEOFString(data, 0, test.value)
   310  		assert.Equal(t, len(test.eofEncoded), pos, "unexpected pos %v after writeEOFString(%v), expected %v", pos, test.value, len(test.eofEncoded))
   311  		assert.True(t, bytes.Equal(data, test.eofEncoded[:len(test.eofEncoded)]), "unexpected eofEncoded value for %v, got %v expected %v", test.value, data, test.eofEncoded)
   312  
   313  		// Check successful decoding.
   314  		got, pos, ok = readEOFString(test.eofEncoded, 0)
   315  		if !ok || got != test.value || pos != len(test.eofEncoded) {
   316  			t.Errorf("readEOFString returned %v/%v/%v but expected %v/%v/%v", got, pos, ok, test.value, len(test.eofEncoded), true)
   317  		}
   318  	}
   319  }