vitess.io/vitess@v0.16.2/go/vt/vtgr/controller/refresh_test.go (about) 1 /* 2 Copyright 2021 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 controller 18 19 import ( 20 "context" 21 "fmt" 22 "sort" 23 "testing" 24 "time" 25 26 "github.com/golang/mock/gomock" 27 "github.com/stretchr/testify/assert" 28 29 "vitess.io/vitess/go/vt/logutil" 30 topodatapb "vitess.io/vitess/go/vt/proto/topodata" 31 "vitess.io/vitess/go/vt/topo" 32 "vitess.io/vitess/go/vt/topo/memorytopo" 33 "vitess.io/vitess/go/vt/vtctl/grpcvtctldserver/testutil" 34 "vitess.io/vitess/go/vt/vtgr/config" 35 ) 36 37 func TestRefreshTabletsInShard(t *testing.T) { 38 ctrl := gomock.NewController(t) 39 defer ctrl.Finish() 40 ctx := context.Background() 41 ts := memorytopo.NewServer("test_cell") 42 defer ts.Close() 43 ts.CreateKeyspace(ctx, "ks", &topodatapb.Keyspace{}) 44 ts.CreateShard(ctx, "ks", "0") 45 tablet1 := buildTabletInfo(uint32(0), testHost, testPort0, topodatapb.TabletType_PRIMARY, time.Time{}) 46 tablet2 := buildTabletInfo(uint32(1), testHost, testPort1, topodatapb.TabletType_SPARE, time.Time{}) 47 tablet3 := buildTabletInfo(uint32(2), testHost, 0, topodatapb.TabletType_REPLICA, time.Time{}) 48 testutil.AddTablet(ctx, t, ts, tablet1.Tablet, nil) 49 testutil.AddTablet(ctx, t, ts, tablet2.Tablet, nil) 50 testutil.AddTablet(ctx, t, ts, tablet3.Tablet, nil) 51 cfg := &config.VTGRConfig{BootstrapGroupSize: 3, MinNumReplica: 0, BackoffErrorWaitTimeSeconds: 1, BootstrapWaitTimeSeconds: 1} 52 shard := NewGRShard("ks", "0", nil, nil, ts, nil, cfg, testPort0, true) 53 assert.Equal(t, "ks", shard.shardStatusCollector.status.Keyspace) 54 assert.Equal(t, "0", shard.shardStatusCollector.status.Shard) 55 shard.refreshTabletsInShardLocked(context.Background()) 56 instances := shard.instances 57 // only have 2 instances here because we filter out the spare tablet 58 assert.Equal(t, 2, len(instances)) 59 sort.Slice(instances[:], func(i, j int) bool { 60 return instances[i].alias < instances[j].alias 61 }) 62 assert.Equal(t, testHost, instances[0].tablet.Hostname) 63 assert.Equal(t, int32(testPort0), instances[0].tablet.MysqlPort) 64 assert.Equal(t, topodatapb.TabletType_PRIMARY, instances[0].tablet.Type) 65 // host 3 is missing mysql host but we still put it in the instances list here 66 assert.Equal(t, testHost, instances[1].instanceKey.Hostname) 67 assert.Equal(t, int32(0), instances[1].tablet.MysqlPort) 68 assert.Equal(t, topodatapb.TabletType_REPLICA, instances[1].tablet.Type) 69 } 70 71 func TestRefreshWithCells(t *testing.T) { 72 ctx := context.Background() 73 ts := memorytopo.NewServer("cell1", "cell2", "cell3") 74 defer ts.Close() 75 ts.CreateKeyspace(ctx, "ks", &topodatapb.Keyspace{}) 76 ts.CreateShard(ctx, "ks", "0") 77 tablet1 := buildTabletInfoWithCell(uint32(0), testHost, "cell1", testPort0, topodatapb.TabletType_REPLICA, time.Time{}) 78 tablet2 := buildTabletInfoWithCell(uint32(1), testHost, "cell2", testPort1, topodatapb.TabletType_REPLICA, time.Time{}) 79 tablet3 := buildTabletInfoWithCell(uint32(2), testHost, "cell3", testPort2, topodatapb.TabletType_REPLICA, time.Time{}) 80 testutil.AddTablet(ctx, t, ts, tablet1.Tablet, nil) 81 testutil.AddTablet(ctx, t, ts, tablet2.Tablet, nil) 82 testutil.AddTablet(ctx, t, ts, tablet3.Tablet, nil) 83 cfg := &config.VTGRConfig{BootstrapGroupSize: 3, MinNumReplica: 0, BackoffErrorWaitTimeSeconds: 1, BootstrapWaitTimeSeconds: 1} 84 shard := NewGRShard("ks", "0", []string{"cell1", "cell3"}, nil, ts, nil, cfg, testPort0, true) 85 shard.refreshTabletsInShardLocked(context.Background()) 86 instances := shard.instances 87 // only have 2 instances here because we are not watching cell2 88 assert.Equal(t, 2, len(instances)) 89 sort.Slice(instances[:], func(i, j int) bool { 90 return instances[i].alias < instances[j].alias 91 }) 92 assert.Equal(t, "cell1-0000000000", instances[0].alias) 93 assert.Equal(t, "cell3-0000000002", instances[1].alias) 94 } 95 96 func TestRefreshWithEmptyCells(t *testing.T) { 97 ctx := context.Background() 98 ts := memorytopo.NewServer("cell1", "cell2", "cell3") 99 defer ts.Close() 100 ts.CreateKeyspace(ctx, "ks", &topodatapb.Keyspace{}) 101 ts.CreateShard(ctx, "ks", "0") 102 tablet1 := buildTabletInfoWithCell(uint32(0), testHost, "cell1", testPort0, topodatapb.TabletType_REPLICA, time.Time{}) 103 tablet2 := buildTabletInfoWithCell(uint32(1), testHost, "cell2", testPort1, topodatapb.TabletType_REPLICA, time.Time{}) 104 tablet3 := buildTabletInfoWithCell(uint32(2), testHost, "cell3", testPort2, topodatapb.TabletType_REPLICA, time.Time{}) 105 testutil.AddTablet(ctx, t, ts, tablet1.Tablet, nil) 106 testutil.AddTablet(ctx, t, ts, tablet2.Tablet, nil) 107 testutil.AddTablet(ctx, t, ts, tablet3.Tablet, nil) 108 cfg := &config.VTGRConfig{BootstrapGroupSize: 3, MinNumReplica: 0, BackoffErrorWaitTimeSeconds: 1, BootstrapWaitTimeSeconds: 1} 109 shard := NewGRShard("ks", "0", nil, nil, ts, nil, cfg, testPort0, true) 110 shard.refreshTabletsInShardLocked(context.Background()) 111 instances := shard.instances 112 // nil cell will return everything 113 assert.Equal(t, 3, len(instances)) 114 sort.Slice(instances[:], func(i, j int) bool { 115 return instances[i].alias < instances[j].alias 116 }) 117 assert.Equal(t, "cell1-0000000000", instances[0].alias) 118 assert.Equal(t, "cell2-0000000001", instances[1].alias) 119 assert.Equal(t, "cell3-0000000002", instances[2].alias) 120 } 121 122 func TestLockRelease(t *testing.T) { 123 ctx := context.Background() 124 ts := memorytopo.NewServer("cell1", "cell2", "cell3") 125 defer ts.Close() 126 ts.CreateKeyspace(ctx, "ks", &topodatapb.Keyspace{}) 127 ts.CreateShard(ctx, "ks", "0") 128 cfg := &config.VTGRConfig{BootstrapGroupSize: 3, MinNumReplica: 0, BackoffErrorWaitTimeSeconds: 1, BootstrapWaitTimeSeconds: 1} 129 shard := NewGRShard("ks", "0", nil, nil, ts, nil, cfg, testPort0, true) 130 ctx, err := shard.LockShard(ctx, "") 131 assert.NoError(t, err) 132 // make sure we get the lock 133 err = shard.checkShardLocked(ctx) 134 assert.NoError(t, err) 135 assert.NotNil(t, shard.unlock) 136 shard.UnlockShard() 137 assert.Nil(t, shard.unlock) 138 err = shard.checkShardLocked(ctx) 139 assert.EqualError(t, err, "lost topology lock; aborting: shard ks/0 is not locked (no lockInfo in map)") 140 } 141 142 func buildTabletInfo(id uint32, host string, mysqlPort int, ttype topodatapb.TabletType, primaryTermTime time.Time) *topo.TabletInfo { 143 return buildTabletInfoWithCell(id, host, "test_cell", mysqlPort, ttype, primaryTermTime) 144 } 145 146 func buildTabletInfoWithCell(id uint32, host, cell string, mysqlPort int, ttype topodatapb.TabletType, primaryTermTime time.Time) *topo.TabletInfo { 147 alias := &topodatapb.TabletAlias{Cell: cell, Uid: id} 148 return &topo.TabletInfo{Tablet: &topodatapb.Tablet{ 149 Alias: alias, 150 Hostname: host, 151 MysqlHostname: host, 152 MysqlPort: int32(mysqlPort), 153 Keyspace: "ks", 154 Shard: "0", 155 Type: ttype, 156 PrimaryTermStartTime: logutil.TimeToProto(primaryTermTime), 157 Tags: map[string]string{"hostname": fmt.Sprintf("host_%d", id)}, 158 }} 159 }