github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/petri/acyclic/tenant/manager_test.go (about) 1 // Copyright 2020 WHTCORPS INC, 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 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package tenant_test 15 16 import ( 17 "context" 18 "fmt" 19 "runtime" 20 "testing" 21 "time" 22 23 "github.com/whtcorpsinc/BerolinaSQL/terror" 24 . "github.com/whtcorpsinc/check" 25 "github.com/whtcorpsinc/errors" 26 "github.com/whtcorpsinc/milevadb/causetstore/mockstore" 27 . "github.com/whtcorpsinc/milevadb/dbs" 28 "github.com/whtcorpsinc/milevadb/soliton/logutil" 29 "github.com/whtcorpsinc/milevadb/tenant" 30 "go.etcd.io/etcd/clientv3" 31 "go.etcd.io/etcd/clientv3/concurrency" 32 "go.etcd.io/etcd/integration" 33 goctx "golang.org/x/net/context" 34 ) 35 36 const testLease = 5 * time.Millisecond 37 38 func TestT(t *testing.T) { 39 TestingT(t) 40 } 41 42 func checkTenant(d DBS, fbVal bool) (isTenant bool) { 43 manager := d.TenantManager() 44 // The longest to wait for 30 seconds to 45 // make sure that campaigning tenants is completed. 46 for i := 0; i < 6000; i++ { 47 time.Sleep(5 * time.Millisecond) 48 isTenant = manager.IsTenant() 49 if isTenant == fbVal { 50 break 51 } 52 } 53 return 54 } 55 56 func TestSingle(t *testing.T) { 57 if runtime.GOOS == "windows" { 58 t.Skip("integration.NewClusterV3 will create file contains a colon which is not allowed on Windows") 59 } 60 causetstore, err := mockstore.NewMockStore() 61 if err != nil { 62 t.Fatal(err) 63 } 64 defer causetstore.Close() 65 66 clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 1}) 67 defer clus.Terminate(t) 68 cli := clus.RandClient() 69 ctx := goctx.Background() 70 d := NewDBS( 71 ctx, 72 WithEtcdClient(cli), 73 WithStore(causetstore), 74 WithLease(testLease), 75 ) 76 err = d.Start(nil) 77 if err != nil { 78 t.Fatalf("DBS start failed %v", err) 79 } 80 defer d.Stop() 81 82 isTenant := checkTenant(d, true) 83 if !isTenant { 84 t.Fatalf("expect true, got isTenant:%v", isTenant) 85 } 86 87 // test for newStochastik failed 88 ctx, cancel := goctx.WithCancel(ctx) 89 manager := tenant.NewTenantManager(ctx, cli, "dbs", "dbs_id", DBSTenantKey) 90 cancel() 91 err = manager.CampaignTenant() 92 if !terror.ErrorEqual(err, goctx.Canceled) && 93 !terror.ErrorEqual(err, goctx.DeadlineExceeded) { 94 t.Fatalf("campaigned result don't match, err %v", err) 95 } 96 isTenant = checkTenant(d, true) 97 if !isTenant { 98 t.Fatalf("expect true, got isTenant:%v", isTenant) 99 } 100 // The test is used to exit campaign loop. 101 d.TenantManager().Cancel() 102 isTenant = checkTenant(d, false) 103 if isTenant { 104 t.Fatalf("expect false, got isTenant:%v", isTenant) 105 } 106 time.Sleep(200 * time.Millisecond) 107 tenantID, _ := manager.GetTenantID(goctx.Background()) 108 // The error is ok to be not nil since we canceled the manager. 109 if tenantID != "" { 110 t.Fatalf("tenant %s is not empty", tenantID) 111 } 112 } 113 114 func TestCluster(t *testing.T) { 115 if runtime.GOOS == "windows" { 116 t.Skip("integration.NewClusterV3 will create file contains a colon which is not allowed on Windows") 117 } 118 tmpTTL := 3 119 orignalTTL := tenant.ManagerStochastikTTL 120 tenant.ManagerStochastikTTL = tmpTTL 121 defer func() { 122 tenant.ManagerStochastikTTL = orignalTTL 123 }() 124 causetstore, err := mockstore.NewMockStore() 125 if err != nil { 126 t.Fatal(err) 127 } 128 defer causetstore.Close() 129 clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 4}) 130 defer clus.Terminate(t) 131 132 cli := clus.Client(0) 133 d := NewDBS( 134 goctx.Background(), 135 WithEtcdClient(cli), 136 WithStore(causetstore), 137 WithLease(testLease), 138 ) 139 err = d.Start(nil) 140 if err != nil { 141 t.Fatalf("DBS start failed %v", err) 142 } 143 isTenant := checkTenant(d, true) 144 if !isTenant { 145 t.Fatalf("expect true, got isTenant:%v", isTenant) 146 } 147 cli1 := clus.Client(1) 148 d1 := NewDBS( 149 goctx.Background(), 150 WithEtcdClient(cli1), 151 WithStore(causetstore), 152 WithLease(testLease), 153 ) 154 err = d1.Start(nil) 155 if err != nil { 156 t.Fatalf("DBS start failed %v", err) 157 } 158 isTenant = checkTenant(d1, false) 159 if isTenant { 160 t.Fatalf("expect false, got isTenant:%v", isTenant) 161 } 162 163 // Delete the leader key, the d1 become the tenant. 164 cliRW := clus.Client(2) 165 err = deleteLeader(cliRW, DBSTenantKey) 166 if err != nil { 167 t.Fatal(err) 168 } 169 isTenant = checkTenant(d, false) 170 if isTenant { 171 t.Fatalf("expect false, got isTenant:%v", isTenant) 172 } 173 d.Stop() 174 175 // d3 (not tenant) stop 176 cli3 := clus.Client(3) 177 d3 := NewDBS( 178 goctx.Background(), 179 WithEtcdClient(cli3), 180 WithStore(causetstore), 181 WithLease(testLease), 182 ) 183 err = d3.Start(nil) 184 if err != nil { 185 t.Fatalf("DBS start failed %v", err) 186 } 187 defer d3.Stop() 188 isTenant = checkTenant(d3, false) 189 if isTenant { 190 t.Fatalf("expect false, got isTenant:%v", isTenant) 191 } 192 d3.Stop() 193 194 // Cancel the tenant context, there is no tenant. 195 d1.Stop() 196 time.Sleep(time.Duration(tmpTTL+1) * time.Second) 197 stochastik, err := concurrency.NewStochastik(cliRW) 198 if err != nil { 199 t.Fatalf("new stochastik failed %v", err) 200 } 201 elec := concurrency.NewElection(stochastik, DBSTenantKey) 202 logPrefix := fmt.Sprintf("[dbs] %s tenantManager %s", DBSTenantKey, "useless id") 203 logCtx := logutil.WithKeyValue(context.Background(), "tenant info", logPrefix) 204 _, err = tenant.GetTenantInfo(goctx.Background(), logCtx, elec, "useless id") 205 if !terror.ErrorEqual(err, concurrency.ErrElectionNoLeader) { 206 t.Fatalf("get tenant info result don't match, err %v", err) 207 } 208 } 209 210 func deleteLeader(cli *clientv3.Client, prefixKey string) error { 211 stochastik, err := concurrency.NewStochastik(cli) 212 if err != nil { 213 return errors.Trace(err) 214 } 215 defer stochastik.Close() 216 elec := concurrency.NewElection(stochastik, prefixKey) 217 resp, err := elec.Leader(goctx.Background()) 218 if err != nil { 219 return errors.Trace(err) 220 } 221 _, err = cli.Delete(goctx.Background(), string(resp.Ekvs[0].Key)) 222 return errors.Trace(err) 223 }