github.com/dolthub/go-mysql-server@v0.18.0/sql/types/enum_test.go (about) 1 // Copyright 2022 Dolthub, Inc. 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 types 16 17 import ( 18 "fmt" 19 "reflect" 20 "strconv" 21 "testing" 22 "time" 23 24 "github.com/stretchr/testify/assert" 25 "github.com/stretchr/testify/require" 26 27 "github.com/dolthub/go-mysql-server/sql" 28 ) 29 30 func TestEnumCompare(t *testing.T) { 31 tests := []struct { 32 vals []string 33 collation sql.CollationID 34 val1 interface{} 35 val2 interface{} 36 expectedCmp int 37 }{ 38 {[]string{"one", "two"}, sql.Collation_Default, nil, 1, 1}, 39 {[]string{"one", "two"}, sql.Collation_Default, "one", nil, -1}, 40 {[]string{"one", "two"}, sql.Collation_Default, nil, nil, 0}, 41 {[]string{"one", "two"}, sql.Collation_Default, 1, "two", -1}, 42 {[]string{"one", "two"}, sql.Collation_Default, 2, []byte("one"), 1}, 43 {[]string{"one", "two"}, sql.Collation_Default, "one", 1, 0}, 44 {[]string{"one", "two"}, sql.Collation_Default, "one", "two", -1}, 45 {[]string{"two", "one"}, sql.Collation_Default, "two", "one", -1}, 46 {[]string{"0", "1", "2"}, sql.Collation_Default, 3, "2", 0}, 47 {[]string{"0", "1", "2"}, sql.Collation_Default, 2, "1", 0}, 48 {[]string{"0", "1", "2"}, sql.Collation_Default, "3", "2", 0}, 49 {[]string{"one", "two"}, sql.Collation_Default, "ten", "twenty", 0}, 50 {[]string{"one", "two"}, sql.Collation_Default, "one", "hundred", 1}, 51 {[]string{"one", "two"}, sql.Collation_Default, "hundred", "one", -1}, 52 } 53 54 for _, test := range tests { 55 t.Run(fmt.Sprintf("%v %v %v %v", test.vals, test.collation, test.val1, test.val2), func(t *testing.T) { 56 typ := MustCreateEnumType(test.vals, test.collation) 57 cmp, err := typ.Compare(test.val1, test.val2) 58 require.NoError(t, err) 59 assert.Equal(t, test.expectedCmp, cmp) 60 }) 61 } 62 } 63 64 func TestEnumCreate(t *testing.T) { 65 tests := []struct { 66 vals []string 67 collation sql.CollationID 68 expectedValToIndex map[string]int 69 expectedErr bool 70 }{ 71 {[]string{"one"}, sql.Collation_Default, map[string]int{"one": 1}, false}, 72 {[]string{" one ", " two "}, sql.Collation_Default, 73 map[string]int{" one": 1, " two": 2}, false}, 74 {[]string{"0", "1", "2"}, sql.Collation_Default, 75 map[string]int{"0": 1, "1": 2, "2": 3}, false}, 76 {[]string{"one", "one "}, sql.Collation_binary, 77 map[string]int{"one": 1, "one ": 2}, false}, 78 {[]string{}, sql.Collation_Default, nil, true}, 79 {[]string{"one", "one"}, sql.Collation_Default, nil, true}, 80 {[]string{"one", "one "}, sql.Collation_Default, nil, true}, 81 } 82 83 for _, test := range tests { 84 t.Run(fmt.Sprintf("%v %v %v", test.vals, test.collation, test.expectedValToIndex), func(t *testing.T) { 85 typ, err := CreateEnumType(test.vals, test.collation) 86 if test.expectedErr { 87 assert.Error(t, err) 88 } else { 89 require.NoError(t, err) 90 assert.True(t, test.collation.Equals(typ.Collation())) 91 for val, i := range test.expectedValToIndex { 92 str, ok := typ.At(i) 93 if assert.True(t, ok) { 94 assert.Equal(t, val, str) 95 } 96 index := typ.IndexOf(val) 97 assert.Equal(t, i, index) 98 } 99 } 100 }) 101 } 102 } 103 104 func TestEnumCreateTooLarge(t *testing.T) { 105 vals := make([]string, 65536) 106 for i := range vals { 107 vals[i] = strconv.Itoa(i) 108 } 109 _, err := CreateEnumType(vals, sql.Collation_Default) 110 require.Error(t, err) 111 } 112 113 func TestEnumConvert(t *testing.T) { 114 tests := []struct { 115 vals []string 116 collation sql.CollationID 117 val interface{} 118 expectedVal interface{} 119 expectedErr bool 120 }{ 121 {[]string{"one", "two"}, sql.Collation_Default, nil, nil, false}, 122 {[]string{"one", "two"}, sql.Collation_Default, int(1), "one", false}, 123 {[]string{"one", "two"}, sql.Collation_Default, int8(2), "two", false}, 124 {[]string{"one", "two"}, sql.Collation_Default, int16(1), "one", false}, 125 {[]string{"one", "two"}, sql.Collation_Default, int32(2), "two", false}, 126 {[]string{"one", "two"}, sql.Collation_Default, int64(1), "one", false}, 127 {[]string{"one", "two"}, sql.Collation_Default, uint(2), "two", false}, 128 {[]string{"one", "two"}, sql.Collation_Default, uint8(1), "one", false}, 129 {[]string{"one", "two"}, sql.Collation_Default, uint16(2), "two", false}, 130 {[]string{"one", "two"}, sql.Collation_Default, uint32(1), "one", false}, 131 {[]string{"one", "two"}, sql.Collation_Default, uint64(2), "two", false}, 132 {[]string{"one", "two"}, sql.Collation_Default, "one", "one", false}, 133 {[]string{"one", "two"}, sql.Collation_Default, []byte("two"), "two", false}, 134 {[]string{"0", "1", "2"}, sql.Collation_Default, 3, "2", false}, 135 {[]string{"0", "1", "2"}, sql.Collation_Default, 2, "1", false}, 136 {[]string{"0", "1", "2"}, sql.Collation_Default, "3", "2", false}, 137 {[]string{"0", "1", "2"}, sql.Collation_Default, "2", "2", false}, 138 139 {[]string{"one", "two"}, sql.Collation_Default, 3, nil, true}, 140 {[]string{"one", "two"}, sql.Collation_Default, 0, nil, true}, 141 {[]string{"one", "two"}, sql.Collation_Default, "three", nil, true}, 142 {[]string{"one", "two"}, sql.Collation_Default, time.Date(2019, 12, 12, 12, 12, 12, 0, time.UTC), nil, true}, 143 } 144 145 for _, test := range tests { 146 t.Run(fmt.Sprintf("%v %v %v", test.vals, test.collation, test.val), func(t *testing.T) { 147 typ := MustCreateEnumType(test.vals, test.collation) 148 val, _, err := typ.Convert(test.val) 149 if test.expectedErr { 150 assert.Error(t, err) 151 } else { 152 require.NoError(t, err) 153 if test.val != nil { 154 umar, ok := typ.At(int(val.(uint16))) 155 require.True(t, ok) 156 cmp, err := typ.Compare(test.val, umar) 157 require.NoError(t, err) 158 assert.Equal(t, 0, cmp) 159 assert.Equal(t, typ.ValueType(), reflect.TypeOf(val)) 160 } else { 161 assert.Equal(t, test.expectedVal, val) 162 } 163 } 164 }) 165 } 166 } 167 168 func TestEnumString(t *testing.T) { 169 tests := []struct { 170 vals []string 171 collation sql.CollationID 172 expectedStr string 173 }{ 174 {[]string{"one"}, sql.Collation_Default, "enum('one')"}, 175 {[]string{"مرحبا", "こんにちは"}, sql.Collation_Default, "enum('مرحبا','こんにちは')"}, 176 {[]string{" hi ", " lo "}, sql.Collation_Default, "enum(' hi',' lo')"}, 177 {[]string{"a"}, sql.Collation_Default.CharacterSet().BinaryCollation(), 178 fmt.Sprintf("enum('a') COLLATE %v", sql.Collation_Default.CharacterSet().BinaryCollation())}, 179 } 180 181 for _, test := range tests { 182 t.Run(fmt.Sprintf("%v %v", test.vals, test.collation), func(t *testing.T) { 183 typ := MustCreateEnumType(test.vals, test.collation) 184 assert.Equal(t, test.expectedStr, typ.String()) 185 }) 186 } 187 } 188 189 func TestEnumZero(t *testing.T) { 190 tests := []struct { 191 vals []string 192 }{ 193 {[]string{"a"}}, 194 {[]string{"a", "b"}}, 195 } 196 197 for _, test := range tests { 198 t.Run(fmt.Sprintf("%v ok", test.vals), func(t *testing.T) { 199 typ := MustCreateEnumType(test.vals, sql.Collation_Default) 200 v, ok := typ.Zero().(uint16) 201 assert.True(t, ok) 202 assert.Equal(t, uint16(1), v) 203 }) 204 } 205 }