vitess.io/vitess@v0.16.2/go/vt/vttablet/tabletserver/schema/load_table_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 schema 18 19 import ( 20 "context" 21 "errors" 22 "reflect" 23 "strings" 24 "testing" 25 "time" 26 27 "github.com/stretchr/testify/assert" 28 "github.com/stretchr/testify/require" 29 30 "vitess.io/vitess/go/mysql/fakesqldb" 31 "vitess.io/vitess/go/sqltypes" 32 querypb "vitess.io/vitess/go/vt/proto/query" 33 "vitess.io/vitess/go/vt/sqlparser" 34 "vitess.io/vitess/go/vt/vttablet/tabletserver/connpool" 35 "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" 36 ) 37 38 func TestLoadTable(t *testing.T) { 39 db := fakesqldb.New(t) 40 defer db.Close() 41 mockLoadTableQueries(db) 42 table, err := newTestLoadTable("USER_TABLE", "test table", db) 43 if err != nil { 44 t.Fatal(err) 45 } 46 want := &Table{ 47 Name: sqlparser.NewIdentifierCS("test_table"), 48 Fields: []*querypb.Field{{ 49 Name: "pk", 50 Type: sqltypes.Int32, 51 }, { 52 Name: "name", 53 Type: sqltypes.Int32, 54 }, { 55 Name: "addr", 56 Type: sqltypes.Int32, 57 }}, 58 } 59 assert.Equal(t, want, table) 60 } 61 62 func TestLoadTableSequence(t *testing.T) { 63 db := fakesqldb.New(t) 64 defer db.Close() 65 mockLoadTableQueries(db) 66 table, err := newTestLoadTable("USER_TABLE", "vitess_sequence", db) 67 if err != nil { 68 t.Fatal(err) 69 } 70 want := &Table{ 71 Name: sqlparser.NewIdentifierCS("test_table"), 72 Type: Sequence, 73 SequenceInfo: &SequenceInfo{}, 74 } 75 table.Fields = nil 76 table.PKColumns = nil 77 if !reflect.DeepEqual(table, want) { 78 t.Errorf("Table:\n%#v, want\n%#v", table, want) 79 } 80 } 81 82 func TestLoadTableMessage(t *testing.T) { 83 db := fakesqldb.New(t) 84 defer db.Close() 85 mockMessageTableQueries(db) 86 table, err := newTestLoadTable("USER_TABLE", "vitess_message,vt_ack_wait=30,vt_purge_after=120,vt_batch_size=1,vt_cache_size=10,vt_poller_interval=30", db) 87 if err != nil { 88 t.Fatal(err) 89 } 90 want := &Table{ 91 Name: sqlparser.NewIdentifierCS("test_table"), 92 Type: Message, 93 Fields: []*querypb.Field{{ 94 Name: "id", 95 Type: sqltypes.Int64, 96 }, { 97 Name: "priority", 98 Type: sqltypes.Int64, 99 }, { 100 Name: "time_next", 101 Type: sqltypes.Int64, 102 }, { 103 Name: "epoch", 104 Type: sqltypes.Int64, 105 }, { 106 Name: "time_acked", 107 Type: sqltypes.Int64, 108 }, { 109 Name: "message", 110 Type: sqltypes.VarBinary, 111 }}, 112 MessageInfo: &MessageInfo{ 113 Fields: []*querypb.Field{{ 114 Name: "id", 115 Type: sqltypes.Int64, 116 }, { 117 Name: "message", 118 Type: sqltypes.VarBinary, 119 }}, 120 AckWaitDuration: 30 * time.Second, 121 PurgeAfterDuration: 120 * time.Second, 122 MinBackoff: 30 * time.Second, 123 BatchSize: 1, 124 CacheSize: 10, 125 PollInterval: 30 * time.Second, 126 }, 127 } 128 assert.Equal(t, want, table) 129 130 // Test loading min/max backoff 131 table, err = newTestLoadTable("USER_TABLE", "vitess_message,vt_ack_wait=30,vt_purge_after=120,vt_batch_size=1,vt_cache_size=10,vt_poller_interval=30,vt_min_backoff=10,vt_max_backoff=100", db) 132 require.NoError(t, err) 133 want.MessageInfo.MinBackoff = 10 * time.Second 134 want.MessageInfo.MaxBackoff = 100 * time.Second 135 assert.Equal(t, want, table) 136 137 // 138 // multiple tests for vt_message_cols 139 // 140 origFields := want.MessageInfo.Fields 141 142 // Test loading id column from vt_message_cols 143 table, err = newTestLoadTable("USER_TABLE", "vitess_message,vt_message_cols=id,vt_ack_wait=30,vt_purge_after=120,vt_batch_size=1,vt_cache_size=10,vt_poller_interval=30,vt_min_backoff=10,vt_max_backoff=100", db) 144 require.NoError(t, err) 145 want.MessageInfo.Fields = []*querypb.Field{{ 146 Name: "id", 147 Type: sqltypes.Int64, 148 }} 149 assert.Equal(t, want, table) 150 151 // Test loading message column from vt_message_cols 152 _, err = newTestLoadTable("USER_TABLE", "vitess_message,vt_message_cols=message,vt_ack_wait=30,vt_purge_after=120,vt_batch_size=1,vt_cache_size=10,vt_poller_interval=30,vt_min_backoff=10,vt_max_backoff=100", db) 153 require.Equal(t, errors.New("vt_message_cols must begin with id: test_table"), err) 154 155 // Test loading id & message columns from vt_message_cols 156 table, err = newTestLoadTable("USER_TABLE", "vitess_message,vt_message_cols=id|message,vt_ack_wait=30,vt_purge_after=120,vt_batch_size=1,vt_cache_size=10,vt_poller_interval=30,vt_min_backoff=10,vt_max_backoff=100", db) 157 require.NoError(t, err) 158 want.MessageInfo.Fields = []*querypb.Field{{ 159 Name: "id", 160 Type: sqltypes.Int64, 161 }, { 162 Name: "message", 163 Type: sqltypes.VarBinary, 164 }} 165 assert.Equal(t, want, table) 166 167 // Test loading id & message columns in reverse order from vt_message_cols 168 _, err = newTestLoadTable("USER_TABLE", "vitess_message,vt_message_cols=message|id,vt_ack_wait=30,vt_purge_after=120,vt_batch_size=1,vt_cache_size=10,vt_poller_interval=30,vt_min_backoff=10,vt_max_backoff=100", db) 169 require.Equal(t, errors.New("vt_message_cols must begin with id: test_table"), err) 170 171 // Test setting zero columns on vt_message_cols, which is ignored and loads the default columns 172 table, err = newTestLoadTable("USER_TABLE", "vitess_message,vt_message_cols,vt_ack_wait=30,vt_purge_after=120,vt_batch_size=1,vt_cache_size=10,vt_poller_interval=30,vt_min_backoff=10,vt_max_backoff=100", db) 173 require.NoError(t, err) 174 want.MessageInfo.Fields = []*querypb.Field{{ 175 Name: "id", 176 Type: sqltypes.Int64, 177 }, { 178 Name: "message", 179 Type: sqltypes.VarBinary, 180 }} 181 assert.Equal(t, want, table) 182 183 // reset fields after all vt_message_cols tests 184 want.MessageInfo.Fields = origFields 185 186 // 187 // end vt_message_cols tests 188 // 189 190 // Missing property 191 _, err = newTestLoadTable("USER_TABLE", "vitess_message,vt_ack_wait=30", db) 192 wanterr := "not specified for message table" 193 if err == nil || !strings.Contains(err.Error(), wanterr) { 194 t.Errorf("newTestLoadTable: %v, want %s", err, wanterr) 195 } 196 197 mockLoadTableQueries(db) 198 _, err = newTestLoadTable("USER_TABLE", "vitess_message,vt_ack_wait=30,vt_purge_after=120,vt_batch_size=1,vt_cache_size=10,vt_poller_interval=30", db) 199 wanterr = "missing from message table: test_table" 200 if err == nil || !strings.Contains(err.Error(), wanterr) { 201 t.Errorf("newTestLoadTable: %v, must contain %s", err, wanterr) 202 } 203 } 204 205 func newTestLoadTable(tableType string, comment string, db *fakesqldb.DB) (*Table, error) { 206 ctx := context.Background() 207 appParams := db.ConnParams() 208 dbaParams := db.ConnParams() 209 connPool := connpool.NewPool(tabletenv.NewEnv(nil, "SchemaTest"), "", tabletenv.ConnPoolConfig{ 210 Size: 2, 211 IdleTimeoutSeconds: 10, 212 }) 213 connPool.Open(appParams, dbaParams, appParams) 214 conn, err := connPool.Get(ctx, nil) 215 if err != nil { 216 return nil, err 217 } 218 defer conn.Recycle() 219 220 return LoadTable(conn, "fakesqldb", "test_table", comment) 221 } 222 223 func mockLoadTableQueries(db *fakesqldb.DB) { 224 db.ClearQueryPattern() 225 db.MockQueriesForTable("test_table", &sqltypes.Result{ 226 Fields: []*querypb.Field{{ 227 Name: "pk", 228 Type: sqltypes.Int32, 229 }, { 230 Name: "name", 231 Type: sqltypes.Int32, 232 }, { 233 Name: "addr", 234 Type: sqltypes.Int32, 235 }}, 236 }) 237 } 238 239 func mockMessageTableQueries(db *fakesqldb.DB) { 240 db.ClearQueryPattern() 241 db.MockQueriesForTable("test_table", &sqltypes.Result{ 242 Fields: []*querypb.Field{{ 243 Name: "id", 244 Type: sqltypes.Int64, 245 }, { 246 Name: "priority", 247 Type: sqltypes.Int64, 248 }, { 249 Name: "time_next", 250 Type: sqltypes.Int64, 251 }, { 252 Name: "epoch", 253 Type: sqltypes.Int64, 254 }, { 255 Name: "time_acked", 256 Type: sqltypes.Int64, 257 }, { 258 Name: "message", 259 Type: sqltypes.VarBinary, 260 }}, 261 }) 262 }