github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/datacodec/varchar_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 datacodec
    16  
    17  import (
    18  	"fmt"
    19  	"testing"
    20  
    21  	"github.com/stretchr/testify/assert"
    22  
    23  	"github.com/datastax/go-cassandra-native-protocol/datatype"
    24  	"github.com/datastax/go-cassandra-native-protocol/primitive"
    25  )
    26  
    27  var (
    28  	abcBytes   = []byte("abc")
    29  	greekBytes = []byte("Μιλάτε αγγλικά;")
    30  	abcRunes   = []rune("abc")
    31  	greekRunes = []rune("Μιλάτε αγγλικά;")
    32  )
    33  
    34  func Test_stringCodec_DataType(t *testing.T) {
    35  	assert.Equal(t, datatype.Varchar, Varchar.DataType())
    36  	assert.Equal(t, datatype.Ascii, Ascii.DataType())
    37  }
    38  
    39  func Test_stringCodec_Encode(t *testing.T) {
    40  	codecs := []Codec{Varchar, Ascii}
    41  	for _, codec := range codecs {
    42  		t.Run(codec.DataType().AsCql(), func(t *testing.T) {
    43  			for _, version := range primitive.SupportedProtocolVersions() {
    44  				t.Run(version.String(), func(t *testing.T) {
    45  					tests := []struct {
    46  						name     string
    47  						source   interface{}
    48  						expected []byte
    49  						err      string
    50  					}{
    51  						{"nil", nil, nil, ""},
    52  						{"nil pointer", stringNilPtr(), nil, ""},
    53  						{"empty", "", []byte{}, ""},
    54  						{"non nil", "abc", abcBytes, ""},
    55  						{"conversion failed", 123, nil, fmt.Sprintf("cannot encode int as CQL %v with %v: cannot convert from int to []uint8: conversion not supported", codec.DataType(), version)},
    56  					}
    57  					for _, tt := range tests {
    58  						t.Run(tt.name, func(t *testing.T) {
    59  							actual, err := codec.Encode(tt.source, version)
    60  							assert.Equal(t, tt.expected, actual)
    61  							assertErrorMessage(t, tt.err, err)
    62  						})
    63  					}
    64  				})
    65  			}
    66  		})
    67  	}
    68  }
    69  
    70  func Test_stringCodec_Decode(t *testing.T) {
    71  	codecs := []Codec{Varchar, Ascii}
    72  	for _, codec := range codecs {
    73  		t.Run(codec.DataType().AsCql(), func(t *testing.T) {
    74  			for _, version := range primitive.SupportedProtocolVersions() {
    75  				t.Run(version.String(), func(t *testing.T) {
    76  					tests := []struct {
    77  						name     string
    78  						source   []byte
    79  						dest     interface{}
    80  						expected interface{}
    81  						wasNull  bool
    82  						err      string
    83  					}{
    84  						{"null", nil, new(string), new(string), true, ""},
    85  						{"non null", abcBytes, new(string), stringPtr("abc"), false, ""},
    86  						{"non null interface", abcBytes, new(interface{}), interfacePtr("abc"), false, ""},
    87  						{"conversion failed", abcBytes, new(float64), new(float64), false, fmt.Sprintf("cannot decode CQL %v as *float64 with %v: cannot convert from []uint8 to *float64: conversion not supported", codec.DataType(), version)},
    88  					}
    89  					for _, tt := range tests {
    90  						t.Run(tt.name, func(t *testing.T) {
    91  							wasNull, err := codec.Decode(tt.source, tt.dest, version)
    92  							assert.Equal(t, tt.expected, tt.dest)
    93  							assert.Equal(t, tt.wasNull, wasNull)
    94  							assertErrorMessage(t, tt.err, err)
    95  						})
    96  					}
    97  				})
    98  			}
    99  		})
   100  	}
   101  }
   102  
   103  func Test_convertToStringBytes(t *testing.T) {
   104  	tests := []struct {
   105  		name     string
   106  		source   interface{}
   107  		wantDest []byte
   108  		wantErr  string
   109  	}{
   110  		{"from []byte", abcBytes, abcBytes, ""},
   111  		{"from *[]byte", &greekBytes, greekBytes, ""},
   112  		{"from *[]byte nil", byteSliceNilPtr(), nil, ""},
   113  		{"from []rune", abcRunes, abcBytes, ""},
   114  		{"from *[]rune", &greekRunes, greekBytes, ""},
   115  		{"from *[]rune nil", runeSliceNilPtr(), nil, ""},
   116  		{"from string", "abc", abcBytes, ""},
   117  		{"from *string", stringPtr("abc"), abcBytes, ""},
   118  		{"from *string nil", stringNilPtr(), nil, ""},
   119  		{"from untyped nil", nil, nil, ""},
   120  		{"from unsupported value type", 42.0, nil, "cannot convert from float64 to []uint8: conversion not supported"},
   121  		{"from unsupported pointer type", float64Ptr(42.0), nil, "cannot convert from *float64 to []uint8: conversion not supported"},
   122  	}
   123  	for _, tt := range tests {
   124  		t.Run(tt.name, func(t *testing.T) {
   125  			gotDest, gotErr := convertToStringBytes(tt.source)
   126  			assert.Equal(t, tt.wantDest, gotDest)
   127  			assertErrorMessage(t, tt.wantErr, gotErr)
   128  		})
   129  	}
   130  }
   131  
   132  func Test_convertFromStringBytes(t *testing.T) {
   133  	tests := []struct {
   134  		name     string
   135  		val      []byte
   136  		wasNull  bool
   137  		dest     interface{}
   138  		expected interface{}
   139  		err      string
   140  	}{
   141  		{"to *interface{} nil dest", []byte{1}, false, interfaceNilPtr(), interfaceNilPtr(), "cannot convert from []uint8 to *interface {}: destination is nil"},
   142  		{"to *interface{} nil source", nil, true, new(interface{}), new(interface{}), ""},
   143  		{"to *interface{} non nil", abcBytes, false, new(interface{}), interfacePtr("abc"), ""},
   144  		{"to *byte[] nil dest", []byte{1}, false, byteSliceNilPtr(), byteSliceNilPtr(), "cannot convert from []uint8 to *[]uint8: destination is nil"},
   145  		{"to *byte[] nil source", nil, true, new([]byte), new([]byte), ""},
   146  		{"to *byte[] empty source", []byte{}, false, new([]byte), &[]byte{}, ""},
   147  		{"to *byte[] non nil", abcBytes, false, new([]byte), &abcBytes, ""},
   148  		{"to *rune[] nil dest", []byte{1}, false, runeSliceNilPtr(), runeSliceNilPtr(), "cannot convert from []uint8 to *[]int32: destination is nil"},
   149  		{"to *rune[] nil source", nil, true, new([]rune), new([]rune), ""},
   150  		{"to *rune[] empty source", []byte{}, false, new([]rune), &[]rune{}, ""},
   151  		{"to *rune[] non nil", abcBytes, false, new([]rune), &abcRunes, ""},
   152  		{"to *string nil dest", []byte{1}, false, stringNilPtr(), stringNilPtr(), "cannot convert from []uint8 to *string: destination is nil"},
   153  		{"to *string nil source", nil, true, new(string), new(string), ""},
   154  		{"to *string empty source", []byte{}, false, new(string), new(string), ""},
   155  		{"to *string non nil", abcBytes, false, new(string), stringPtr("abc"), ""},
   156  		{"to untyped nil", []byte{1}, false, nil, nil, "cannot convert from []uint8 to <nil>: destination is nil"},
   157  		{"to non pointer", []byte{1}, false, []byte{}, []byte{}, "cannot convert from []uint8 to []uint8: destination is not pointer"},
   158  		{"to unsupported pointer type", []byte{1}, false, new(float64), new(float64), "cannot convert from []uint8 to *float64: conversion not supported"},
   159  	}
   160  	for _, tt := range tests {
   161  		t.Run(tt.name, func(t *testing.T) {
   162  			gotWasNull, gotErr := convertFromStringBytes(tt.val, tt.dest)
   163  			assert.Equal(t, tt.expected, tt.dest)
   164  			assert.Equal(t, tt.wasNull, gotWasNull)
   165  			assertErrorMessage(t, tt.err, gotErr)
   166  		})
   167  	}
   168  }