github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/datacodec/inet_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  	"net"
    20  	"testing"
    21  
    22  	"github.com/stretchr/testify/assert"
    23  
    24  	"github.com/datastax/go-cassandra-native-protocol/datatype"
    25  	"github.com/datastax/go-cassandra-native-protocol/primitive"
    26  )
    27  
    28  var (
    29  	inetZero  = net.IP{}
    30  	inetAddr4 = net.IPv4(192, 168, 1, 1).To4()
    31  	inetAddr6 = net.IP{0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34}
    32  )
    33  
    34  var (
    35  	inetAddr4Bytes = []byte{192, 168, 1, 1}
    36  	inetAddr6Bytes = []byte{0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34}
    37  )
    38  
    39  func Test_inetCodec_DataType(t *testing.T) {
    40  	assert.Equal(t, datatype.Inet, Inet.DataType())
    41  }
    42  
    43  func Test_inetCodec_Encode(t *testing.T) {
    44  	for _, version := range primitive.SupportedProtocolVersions() {
    45  		t.Run(version.String(), func(t *testing.T) {
    46  			tests := []struct {
    47  				name     string
    48  				source   interface{}
    49  				expected []byte
    50  				err      string
    51  			}{
    52  				{"nil", nil, nil, ""},
    53  				{"nil pointer", new(net.IP), nil, ""},
    54  				{"zero", inetZero, nil, ""},
    55  				{"non nil v4", inetAddr4, inetAddr4Bytes, ""},
    56  				{"non nil v6", inetAddr6, inetAddr6Bytes, ""},
    57  				{"non nil v4 pointer", &inetAddr4, inetAddr4Bytes, ""},
    58  				{"non nil v6 pointer", &inetAddr6, inetAddr6Bytes, ""},
    59  				{"conversion failed", 123, nil, fmt.Sprintf("cannot encode int as CQL inet with %v: cannot convert from int to net.IP: conversion not supported", version)},
    60  			}
    61  			for _, tt := range tests {
    62  				t.Run(tt.name, func(t *testing.T) {
    63  					actual, err := Inet.Encode(tt.source, version)
    64  					assert.Equal(t, tt.expected, actual)
    65  					assertErrorMessage(t, tt.err, err)
    66  				})
    67  			}
    68  		})
    69  	}
    70  }
    71  
    72  func Test_inetCodec_Decode(t *testing.T) {
    73  	for _, version := range primitive.SupportedProtocolVersions() {
    74  		t.Run(version.String(), func(t *testing.T) {
    75  			tests := []struct {
    76  				name     string
    77  				source   []byte
    78  				dest     interface{}
    79  				expected interface{}
    80  				wasNull  bool
    81  				err      string
    82  			}{
    83  				{"null", nil, new(net.IP), new(net.IP), true, ""},
    84  				{"zero", []byte{}, new(net.IP), new(net.IP), true, ""},
    85  				{"non null v4", inetAddr4Bytes, new(net.IP), &inetAddr4, false, ""},
    86  				{"non null v6", inetAddr6Bytes, new(net.IP), &inetAddr6, false, ""},
    87  				{"non null interface", inetAddr4Bytes, new(interface{}), interfacePtr(inetAddr4), false, ""},
    88  				{"invalid", []byte{1, 2, 3}, new(net.IP), new(net.IP), false, fmt.Sprintf("cannot decode CQL inet as *net.IP with %v: cannot read net.IP: expected 4 or 16 bytes but got: 3", version)},
    89  				{"conversion failed", inetAddr4Bytes, new(float64), new(float64), false, fmt.Sprintf("cannot decode CQL inet as *float64 with %v: cannot convert from net.IP to *float64: conversion not supported", version)},
    90  			}
    91  			for _, tt := range tests {
    92  				t.Run(tt.name, func(t *testing.T) {
    93  					wasNull, err := Inet.Decode(tt.source, tt.dest, version)
    94  					assert.Equal(t, tt.expected, tt.dest)
    95  					assert.Equal(t, tt.wasNull, wasNull)
    96  					assertErrorMessage(t, tt.err, err)
    97  				})
    98  			}
    99  		})
   100  	}
   101  }
   102  
   103  func Test_convertToIP(t *testing.T) {
   104  	tests := []struct {
   105  		name     string
   106  		source   interface{}
   107  		wantDest net.IP
   108  		wantErr  string
   109  	}{
   110  		{"from net.IP", inetAddr4, inetAddr4, ""},
   111  		{"from *net.IP", &inetAddr4, inetAddr4, ""},
   112  		{"from *net.IP nil", netIPNilPtr(), nil, ""},
   113  		{"from []byte", inetAddr4Bytes, inetAddr4, ""},
   114  		{"from *[]byte", &inetAddr4Bytes, inetAddr4, ""},
   115  		{"from *[]byte nil", byteSliceNilPtr(), nil, ""},
   116  		{"from *[]byte wrong length", []byte{1, 2, 3}, net.IP{1, 2, 3}, ""}, // will be rejected by writeInet
   117  		{"from string", inetAddr4.String(), inetAddr4, ""},
   118  		{"from string wrong", "not a valid IP", nil, "cannot convert from string to net.IP: cannot parse 'not a valid IP': net.ParseIP(text) failed"},
   119  		{"from *string", stringPtr(inetAddr4.String()), inetAddr4, ""},
   120  		{"from *string nil", stringNilPtr(), nil, ""},
   121  		{"from *string wrong", stringPtr("not a valid IP"), nil, "cannot convert from *string to net.IP: cannot parse 'not a valid IP': net.ParseIP(text) failed"},
   122  		{"from untyped nil", nil, nil, ""},
   123  		{"from unsupported value type", 123, nil, "cannot convert from int to net.IP: conversion not supported"},
   124  		{"from unsupported pointer type", intPtr(123), nil, "cannot convert from *int to net.IP: conversion not supported"},
   125  	}
   126  	for _, tt := range tests {
   127  		t.Run(tt.name, func(t *testing.T) {
   128  			gotDest, gotErr := convertToIP(tt.source)
   129  			assert.Equal(t, tt.wantDest, gotDest)
   130  			assertErrorMessage(t, tt.wantErr, gotErr)
   131  		})
   132  	}
   133  }
   134  
   135  func Test_convertFromIP(t *testing.T) {
   136  	tests := []struct {
   137  		name     string
   138  		val      net.IP
   139  		wasNull  bool
   140  		dest     interface{}
   141  		expected interface{}
   142  		err      string
   143  	}{
   144  		{"to *interface{} nil dest", inetAddr4, false, interfaceNilPtr(), interfaceNilPtr(), "cannot convert from net.IP to *interface {}: destination is nil"},
   145  		{"to *interface{} nil source", nil, true, new(interface{}), new(interface{}), ""},
   146  		{"to *interface{} non nil", inetAddr4, false, new(interface{}), interfacePtr(inetAddr4), ""},
   147  		{"to *net.IP nil dest", inetAddr4, false, netIPNilPtr(), netIPNilPtr(), "cannot convert from net.IP to *net.IP: destination is nil"},
   148  		{"to *net.IP nil source", nil, true, new(net.IP), new(net.IP), ""},
   149  		{"to *net.IP empty source", inetZero, true, new(net.IP), new(net.IP), ""},
   150  		{"to *net.IP wrong length", net.IP{1, 2, 3}, false, new(net.IP), &net.IP{1, 2, 3}, ""}, // will be rejected by readInet
   151  		{"to *net.IP v4 non nil", inetAddr4, false, new(net.IP), &inetAddr4, ""},
   152  		{"to *net.IP v6 non nil", inetAddr6, false, new(net.IP), &inetAddr6, ""},
   153  		{"to *[]byte nil dest", inetAddr4, false, byteSliceNilPtr(), byteSliceNilPtr(), "cannot convert from net.IP to *[]uint8: destination is nil"},
   154  		{"to *[]byte nil source", nil, true, new([]byte), new([]byte), ""},
   155  		{"to *[]byte empty source", inetZero, true, new([]byte), new([]byte), ""},
   156  		{"to *[]byte v4 non nil", inetAddr4, false, new([]byte), &inetAddr4Bytes, ""},
   157  		{"to *[]byte v6 non nil", inetAddr6, false, new([]byte), &inetAddr6Bytes, ""},
   158  		{"to *string nil dest", inetAddr4, false, stringNilPtr(), stringNilPtr(), "cannot convert from net.IP to *string: destination is nil"},
   159  		{"to *string nil source", nil, true, new(string), new(string), ""},
   160  		{"to *string empty source", inetZero, true, new(string), new(string), ""},
   161  		{"to *string v4 non nil", inetAddr4, false, new(string), stringPtr(inetAddr4.String()), ""},
   162  		{"to *string v6 non nil", inetAddr6, false, new(string), stringPtr(inetAddr6.String()), ""},
   163  		{"to untyped nil", inetAddr4, false, nil, nil, "cannot convert from net.IP to <nil>: destination is nil"},
   164  		{"to non pointer", inetAddr4, false, net.IP{}, net.IP{}, "cannot convert from net.IP to net.IP: destination is not pointer"},
   165  		{"to unsupported pointer type", inetAddr4, false, new(float64), new(float64), "cannot convert from net.IP to *float64: conversion not supported"},
   166  	}
   167  	for _, tt := range tests {
   168  		t.Run(tt.name, func(t *testing.T) {
   169  			gotErr := convertFromIP(tt.val, tt.wasNull, tt.dest)
   170  			assert.Equal(t, tt.expected, tt.dest)
   171  			assertErrorMessage(t, tt.err, gotErr)
   172  		})
   173  	}
   174  }
   175  
   176  func Test_writeInet(t *testing.T) {
   177  	tests := []struct {
   178  		name     string
   179  		val      net.IP
   180  		expected []byte
   181  		err      string
   182  	}{
   183  		{"nil", nil, nil, ""},
   184  		{"empty", net.IP{}, nil, ""},
   185  		{"non nil v4", inetAddr4, inetAddr4Bytes, ""},
   186  		{"non nil v6", inetAddr6, inetAddr6Bytes, ""},
   187  		{"invalid", net.IP{1, 2, 3}, nil, "cannot write net.IP: expected 4 or 16 bytes but got: 3"},
   188  	}
   189  	for _, tt := range tests {
   190  		t.Run(tt.name, func(t *testing.T) {
   191  			actual, err := writeInet(tt.val)
   192  			assert.Equal(t, tt.expected, actual)
   193  			assertErrorMessage(t, tt.err, err)
   194  		})
   195  	}
   196  }
   197  
   198  func Test_readInet(t *testing.T) {
   199  	tests := []struct {
   200  		name     string
   201  		source   []byte
   202  		expected net.IP
   203  		wasNull  bool
   204  		err      string
   205  	}{
   206  		{"nil", nil, nil, true, ""},
   207  		{"empty", []byte{}, nil, true, ""},
   208  		{"wrong length", []byte{1}, nil, false, "cannot read net.IP: expected 4 or 16 bytes but got: 1"},
   209  		{"non nil v4", inetAddr4Bytes, inetAddr4, false, ""},
   210  		{"non nil v6", inetAddr6Bytes, inetAddr6, false, ""},
   211  	}
   212  	for _, tt := range tests {
   213  		t.Run(tt.name, func(t *testing.T) {
   214  			actual, wasNull, err := readInet(tt.source)
   215  			assert.Equal(t, tt.expected, actual)
   216  			assert.Equal(t, tt.wasNull, wasNull)
   217  			assertErrorMessage(t, tt.err, err)
   218  		})
   219  	}
   220  }