github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/primitive/string_multimap_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 primitive
    16  
    17  import (
    18  	"bytes"
    19  	"errors"
    20  	"fmt"
    21  	"io/ioutil"
    22  	"testing"
    23  
    24  	"github.com/stretchr/testify/assert"
    25  )
    26  
    27  func TestReadStringMultiMap(t *testing.T) {
    28  	tests := []struct {
    29  		name      string
    30  		source    []byte
    31  		expected  map[string][]string
    32  		remaining []byte
    33  		err       error
    34  	}{
    35  		{"empty string multimap", []byte{0, 0}, map[string][]string{}, []byte{}, nil},
    36  		{"multimap 1 key 1 value", []byte{
    37  			0, 1, // map length
    38  			0, 5, h, e, l, l, o, // key: hello
    39  			0, 1, // list length
    40  			0, 5, w, o, r, l, d, // value1: world
    41  		}, map[string][]string{"hello": {"world"}}, []byte{}, nil},
    42  		{"multimap 1 key 2 values", []byte{
    43  			0, 1, // map length
    44  			0, 5, h, e, l, l, o, // key: hello
    45  			0, 2, // list length
    46  			0, 5, w, o, r, l, d, // value1: world
    47  			0, 5, m, u, n, d, o, // value2: mundo
    48  		}, map[string][]string{"hello": {"world", "mundo"}}, []byte{}, nil},
    49  		// FIXME map iteration order
    50  		//{"multimap 2 keys 2 values", []byte{
    51  		//	0, 2, // map length
    52  		//	0, 5, h, e, l, l, o, // key1: hello
    53  		//	0, 2, // list length
    54  		//	0, 5, w, o, r, l, d, // value1: world
    55  		//	0, 5, m, u, n, d, o, // value2: mundo
    56  		//	0, 6, h, o, l, 0xc3, 0xa0, 0x21, // key2: holà!
    57  		//	0, 2, // list length
    58  		//	0, 5, w, o, r, l, d, // value1: world
    59  		//	0, 5, m, u, n, d, o, // value2: mundo
    60  		//}, map[string][]string{
    61  		//	"hello": {"world", "mundo"},
    62  		//	"holà!": {"world", "mundo"},
    63  		//}, []byte{}, nil},
    64  		{
    65  			"cannot read map length",
    66  			[]byte{0},
    67  			nil,
    68  			[]byte{},
    69  			fmt.Errorf(
    70  				"cannot read [string multimap] length: %w",
    71  				fmt.Errorf("cannot read [short]: %w", errors.New("unexpected EOF")),
    72  			),
    73  		},
    74  		{
    75  			"cannot read key length",
    76  			[]byte{0, 1, 0},
    77  			nil,
    78  			[]byte{},
    79  			fmt.Errorf(
    80  				"cannot read [string multimap] entry 0 key: %w",
    81  				fmt.Errorf("cannot read [string] length: %w",
    82  					fmt.Errorf("cannot read [short]: %w", errors.New("unexpected EOF"))),
    83  			),
    84  		},
    85  		{
    86  			"cannot read list length",
    87  			[]byte{0, 1, 0, 1, k, 0},
    88  			nil,
    89  			[]byte{},
    90  			fmt.Errorf(
    91  				"cannot read [string multimap] entry 0 value: %w",
    92  				fmt.Errorf("cannot read [string list] length: %w",
    93  					fmt.Errorf("cannot read [short]: %w", errors.New("unexpected EOF"))),
    94  			),
    95  		},
    96  		{
    97  			"cannot read element length",
    98  			[]byte{0, 1, 0, 1, k, 0, 1, 0},
    99  			nil,
   100  			[]byte{},
   101  			fmt.Errorf(
   102  				"cannot read [string multimap] entry 0 value: %w",
   103  				fmt.Errorf("cannot read [string list] element 0: %w",
   104  					fmt.Errorf("cannot read [string] length: %w",
   105  						fmt.Errorf("cannot read [short]: %w", errors.New("unexpected EOF")))),
   106  			),
   107  		},
   108  		{
   109  			"cannot read list",
   110  			[]byte{0, 1, 0, 1, k, 0, 1, 0, 5, h, e, l, l},
   111  			nil,
   112  			[]byte{},
   113  			fmt.Errorf("cannot read [string multimap] entry 0 value: %w",
   114  				fmt.Errorf("cannot read [string list] element 0: %w",
   115  					fmt.Errorf("cannot read [string] content: %w", errors.New("unexpected EOF")))),
   116  		},
   117  	}
   118  	for _, tt := range tests {
   119  		t.Run(tt.name, func(t *testing.T) {
   120  			buf := bytes.NewReader(tt.source)
   121  			actual, err := ReadStringMultiMap(buf)
   122  			assert.Equal(t, tt.expected, actual)
   123  			assert.Equal(t, tt.err, err)
   124  			remaining, _ := ioutil.ReadAll(buf)
   125  			assert.Equal(t, tt.remaining, remaining)
   126  		})
   127  	}
   128  }
   129  
   130  func TestWriteStringMultiMap(t *testing.T) {
   131  	tests := []struct {
   132  		name     string
   133  		input    map[string][]string
   134  		expected []byte
   135  		err      error
   136  	}{
   137  		{
   138  			"empty string multimap",
   139  			map[string][]string{},
   140  			[]byte{0, 0},
   141  			nil,
   142  		},
   143  		// not officially allowed by the specs, but better safe than sorry
   144  		{
   145  			"nil string multimap",
   146  			nil,
   147  			[]byte{0, 0},
   148  			nil,
   149  		},
   150  		{
   151  			"multimap 1 key 1 value",
   152  			map[string][]string{"hello": {"world"}},
   153  			[]byte{
   154  				0, 1, // map length
   155  				0, 5, h, e, l, l, o, // key: hello
   156  				0, 1, // list length
   157  				0, 5, w, o, r, l, d, // value1: world
   158  			},
   159  			nil,
   160  		},
   161  		{
   162  			"multimap 1 key 2 values",
   163  			map[string][]string{"hello": {"world", "mundo"}},
   164  			[]byte{
   165  				0, 1, // map length
   166  				0, 5, h, e, l, l, o, // key: hello
   167  				0, 2, // list length
   168  				0, 5, w, o, r, l, d, // value1: world
   169  				0, 5, m, u, n, d, o, // value2: mundo
   170  			},
   171  			nil,
   172  		},
   173  		// FIXME map iteration order
   174  		//{"multimap 2 keys 2 values",
   175  		//	map[string][]string{
   176  		//		"hello": {"world", "mundo"},
   177  		//		"holà!": {"world", "mundo"},
   178  		//	},
   179  		//	[]byte{
   180  		//		0, 2, // map length
   181  		//		0, 5, h, e, l, l, o, // key1: hello
   182  		//		0, 2, // list length
   183  		//		0, 5, w, o, r, l, d, // value1: world
   184  		//		0, 5, m, u, n, d, o, // value2: mundo
   185  		//		0, 6, h, o, l, 0xc3, 0xa0, 0x21, // key2: holà!
   186  		//		0, 2, // list length
   187  		//		0, 5, w, o, r, l, d, // value1: world
   188  		//		0, 5, m, u, n, d, o, // value2: mundo
   189  		//	},
   190  		//	nil},
   191  	}
   192  	for _, tt := range tests {
   193  		t.Run(tt.name, func(t *testing.T) {
   194  			buf := &bytes.Buffer{}
   195  			err := WriteStringMultiMap(tt.input, buf)
   196  			assert.Equal(t, tt.expected, buf.Bytes())
   197  			assert.Equal(t, tt.err, err)
   198  		})
   199  	}
   200  }