vitess.io/vitess@v0.16.2/go/vt/vttablet/tabletserver/messager/engine_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 messager 18 19 import ( 20 "context" 21 "reflect" 22 "testing" 23 24 "vitess.io/vitess/go/mysql/fakesqldb" 25 "vitess.io/vitess/go/sqltypes" 26 vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" 27 "vitess.io/vitess/go/vt/vterrors" 28 "vitess.io/vitess/go/vt/vttablet/tabletserver/schema" 29 "vitess.io/vitess/go/vt/vttablet/tabletserver/tabletenv" 30 ) 31 32 var meTable = &schema.Table{ 33 Type: schema.Message, 34 MessageInfo: newMMTable().MessageInfo, 35 } 36 37 func TestEngineSchemaChanged(t *testing.T) { 38 db := fakesqldb.New(t) 39 defer db.Close() 40 engine := newTestEngine(db) 41 defer engine.Close() 42 tables := map[string]*schema.Table{ 43 "t1": meTable, 44 "t2": { 45 Type: schema.NoType, 46 }, 47 } 48 engine.schemaChanged(tables, []string{"t1", "t2"}, nil, nil) 49 got := extractManagerNames(engine.managers) 50 want := map[string]bool{"t1": true} 51 if !reflect.DeepEqual(got, want) { 52 t.Errorf("got: %+v, want %+v", got, want) 53 } 54 tables = map[string]*schema.Table{ 55 "t1": meTable, 56 "t2": { 57 Type: schema.NoType, 58 }, 59 "t3": meTable, 60 } 61 engine.schemaChanged(tables, []string{"t3"}, nil, nil) 62 got = extractManagerNames(engine.managers) 63 want = map[string]bool{"t1": true, "t3": true} 64 if !reflect.DeepEqual(got, want) { 65 t.Errorf("got: %+v, want %+v", got, want) 66 } 67 tables = map[string]*schema.Table{ 68 "t1": meTable, 69 "t2": { 70 Type: schema.NoType, 71 }, 72 "t4": meTable, 73 } 74 engine.schemaChanged(tables, []string{"t4"}, nil, []string{"t3", "t5"}) 75 got = extractManagerNames(engine.managers) 76 want = map[string]bool{"t1": true, "t4": true} 77 if !reflect.DeepEqual(got, want) { 78 t.Errorf("got: %+v, want %+v", got, want) 79 } 80 // Test update 81 tables = map[string]*schema.Table{ 82 "t1": meTable, 83 "t2": meTable, 84 "t4": { 85 Type: schema.NoType, 86 }, 87 } 88 engine.schemaChanged(tables, nil, []string{"t2", "t4"}, nil) 89 got = extractManagerNames(engine.managers) 90 want = map[string]bool{"t1": true, "t2": true} 91 if !reflect.DeepEqual(got, want) { 92 t.Errorf("got: %+v, want %+v", got, want) 93 } 94 } 95 96 func extractManagerNames(in map[string]*messageManager) map[string]bool { 97 out := make(map[string]bool) 98 for k := range in { 99 out[k] = true 100 } 101 return out 102 } 103 104 func TestSubscribe(t *testing.T) { 105 db := fakesqldb.New(t) 106 defer db.Close() 107 engine := newTestEngine(db) 108 tables := map[string]*schema.Table{ 109 "t1": meTable, 110 "t2": meTable, 111 } 112 engine.schemaChanged(tables, []string{"t1", "t2"}, nil, nil) 113 f1, ch1 := newEngineReceiver() 114 f2, ch2 := newEngineReceiver() 115 // Each receiver is subscribed to different managers. 116 engine.Subscribe(context.Background(), "t1", f1) 117 <-ch1 118 engine.Subscribe(context.Background(), "t2", f2) 119 <-ch2 120 engine.managers["t1"].Add(&MessageRow{Row: []sqltypes.Value{sqltypes.NewVarBinary("1")}}) 121 engine.managers["t2"].Add(&MessageRow{Row: []sqltypes.Value{sqltypes.NewVarBinary("2")}}) 122 <-ch1 123 <-ch2 124 125 // Error case. 126 want := "message table t3 not found" 127 _, err := engine.Subscribe(context.Background(), "t3", f1) 128 if err == nil || err.Error() != want { 129 t.Errorf("Subscribe: %v, want %s", err, want) 130 } 131 132 // After close, Subscribe should return a closed channel. 133 engine.Close() 134 _, err = engine.Subscribe(context.Background(), "t1", nil) 135 if got, want := vterrors.Code(err), vtrpcpb.Code_UNAVAILABLE; got != want { 136 t.Errorf("Subscribed on closed engine error code: %v, want %v", got, want) 137 } 138 } 139 140 func TestEngineGenerate(t *testing.T) { 141 db := fakesqldb.New(t) 142 defer db.Close() 143 engine := newTestEngine(db) 144 defer engine.Close() 145 engine.schemaChanged(map[string]*schema.Table{ 146 "t1": meTable, 147 }, []string{"t1"}, nil, nil) 148 149 if _, err := engine.GetGenerator("t1"); err != nil { 150 t.Error(err) 151 } 152 want := "message table t2 not found in schema" 153 if _, err := engine.GetGenerator("t2"); err == nil || err.Error() != want { 154 t.Errorf("engine.GenerateAckQuery(invalid): %v, want %s", err, want) 155 } 156 } 157 158 func newTestEngine(db *fakesqldb.DB) *Engine { 159 config := tabletenv.NewDefaultConfig() 160 tsv := &fakeTabletServer{ 161 Env: tabletenv.NewEnv(config, "MessagerTest"), 162 } 163 se := schema.NewEngine(tsv) 164 te := NewEngine(tsv, se, newFakeVStreamer()) 165 te.Open() 166 return te 167 } 168 169 func newEngineReceiver() (f func(qr *sqltypes.Result) error, ch chan *sqltypes.Result) { 170 ch = make(chan *sqltypes.Result, 1) 171 return func(qr *sqltypes.Result) error { 172 ch <- qr 173 return nil 174 }, ch 175 }