// NewServer starts a new unregistered TabletServer. // You have to end it with StopService once testing is done. func NewServer(config tabletserver.Config, connParams sqldb.ConnParams, enableRowcache bool) (*tabletserver.TabletServer, error) { dbcfgs := dbconfigs.DBConfigs{ App: dbconfigs.DBConfig{ ConnParams: connParams, Keyspace: "vttest", Shard: "0", EnableRowcache: enableRowcache, EnableInvalidator: false, }, } mysqld := mysqlctl.NewMysqld( "Dba", "App", &mysqlctl.Mycnf{}, &dbcfgs.Dba, &dbcfgs.App.ConnParams, &dbcfgs.Repl) Target = query.Target{ Keyspace: "vttest", Shard: "0", TabletType: topodata.TabletType_MASTER, } server := tabletserver.NewTabletServer(config) err := server.StartService(&Target, &dbcfgs, nil, mysqld) if err != nil { return nil, err } return server, nil }
// StartDefaultServer starts the default server and initializes // all the global variables. This function should only be called // once at the beginning of the test. func StartDefaultServer(connParams sqldb.ConnParams, schemaOverrides []tabletserver.SchemaOverride) error { dbcfgs := dbconfigs.DBConfigs{ App: dbconfigs.DBConfig{ ConnParams: connParams, Keyspace: "vttest", Shard: "0", EnableRowcache: true, EnableInvalidator: false, }, } mysqld := mysqlctl.NewMysqld( "Dba", "App", &mysqlctl.Mycnf{}, &dbcfgs.Dba, &dbcfgs.App.ConnParams, &dbcfgs.Repl) BaseConfig = tabletserver.DefaultQsConfig BaseConfig.RowCache.Binary = vttest.MemcachedPath() BaseConfig.RowCache.Socket = path.Join(os.TempDir(), "memcache.sock") BaseConfig.RowCache.Connections = 100 BaseConfig.EnableAutoCommit = true BaseConfig.StrictTableAcl = true Target = query.Target{ Keyspace: "vttest", Shard: "0", TabletType: topodata.TabletType_MASTER, } DefaultServer = tabletserver.NewTabletServer(BaseConfig) DefaultServer.Register() err := DefaultServer.StartService(&Target, &dbcfgs, schemaOverrides, mysqld) if err != nil { return fmt.Errorf("could not start service: %v\n", err) } // Start http service. ln, err := net.Listen("tcp", ":0") if err != nil { return fmt.Errorf("could not start listener: %v\n", err) } ServerAddress = fmt.Sprintf("http://%s", ln.Addr().String()) go http.Serve(ln, nil) for { time.Sleep(10 * time.Millisecond) response, err := http.Get(fmt.Sprintf("%s/debug/vars", ServerAddress)) if err == nil { response.Body.Close() break } } return nil }
// StartServer starts the server and initializes // all the global variables. This function should only be called // once at the beginning of the test. func StartServer(connParams sqldb.ConnParams) error { dbcfgs := dbconfigs.DBConfigs{ App: dbconfigs.DBConfig{ ConnParams: connParams, Keyspace: "vttest", Shard: "0", }, } mysqld := mysqlctl.NewMysqld( "Dba", "App", &mysqlctl.Mycnf{}, &dbcfgs.Dba, &dbcfgs.App.ConnParams, &dbcfgs.Repl) BaseConfig = tabletserver.DefaultQsConfig BaseConfig.EnableAutoCommit = true BaseConfig.StrictTableAcl = true Target = querypb.Target{ Keyspace: "vttest", Shard: "0", TabletType: topodatapb.TabletType_MASTER, } Server = tabletserver.NewTabletServer(BaseConfig) Server.Register() err := Server.StartService(Target, dbcfgs, mysqld) if err != nil { return fmt.Errorf("could not start service: %v\n", err) } // Start http service. ln, err := net.Listen("tcp", ":0") if err != nil { return fmt.Errorf("could not start listener: %v\n", err) } ServerAddress = fmt.Sprintf("http://%s", ln.Addr().String()) go http.Serve(ln, nil) for { time.Sleep(10 * time.Millisecond) response, err := http.Get(fmt.Sprintf("%s/debug/vars", ServerAddress)) if err == nil { response.Body.Close() break } } return nil }
func waitForFilteredReplication(t *testing.T, expectedErr string, initialStats *pbq.RealtimeStats, broadcastStatsFunc func() *pbq.RealtimeStats) { ts := zktopo.NewTestServer(t, []string{"cell1", "cell2"}) wr := wrangler.New(logutil.NewConsoleLogger(), ts, tmclient.NewTabletManagerClient(), time.Second) vp := NewVtctlPipe(t, ts) defer vp.Close() // source of the filtered replication. We don't start its loop because we don't connect to it. source := NewFakeTablet(t, wr, "cell1", 0, pbt.TabletType_MASTER, TabletKeyspaceShard(t, keyspace, "0")) // dest is the master of the dest shard which receives filtered replication events. dest := NewFakeTablet(t, wr, "cell1", 1, pbt.TabletType_MASTER, TabletKeyspaceShard(t, keyspace, destShard)) dest.StartActionLoop(t, wr) defer dest.StopActionLoop(t) // Build topology state as we would expect it when filtered replication is enabled. ctx := context.Background() wr.SetSourceShards(ctx, keyspace, destShard, []*pbt.TabletAlias{source.Tablet.GetAlias()}, nil) // Set a BinlogPlayerMap to avoid a nil panic when the explicit RunHealthCheck // is called by WaitForFilteredReplication. // Note that for this test we don't mock the BinlogPlayerMap i.e. although // its state says no filtered replication is running, the code under test will // observe otherwise because we call TabletServer.BroadcastHealth() directly and // skip going through the tabletmanager's agent. dest.Agent.BinlogPlayerMap = tabletmanager.NewBinlogPlayerMap(ts, nil, nil) // Use real, but trimmed down QueryService. testConfig := tabletserver.DefaultQsConfig testConfig.EnablePublishStats = false testConfig.DebugURLPrefix = fmt.Sprintf("TestWaitForFilteredReplication-%d-", rand.Int63()) qs := tabletserver.NewTabletServer(testConfig) grpcqueryservice.RegisterForTest(dest.RPCServer, qs) qs.BroadcastHealth(42, initialStats) // run vtctl WaitForFilteredReplication stopBroadcasting := make(chan struct{}) go func() { defer close(stopBroadcasting) err := vp.Run([]string{"WaitForFilteredReplication", "-max_delay", "10s", dest.Tablet.Keyspace + "/" + dest.Tablet.Shard}) if expectedErr == "" { if err != nil { t.Fatalf("WaitForFilteredReplication must not fail: %v", err) } } else { if err == nil || !strings.Contains(err.Error(), expectedErr) { t.Fatalf("WaitForFilteredReplication wrong error. got: %v want substring: %v", err, expectedErr) } } }() // Broadcast health record as long as vtctl is running. for { // Give vtctl a head start to consume the initial stats. // (We do this because there's unfortunately no way to explicitly // synchronize with the point where conn.StreamHealth() has started.) // (Tests won't break if vtctl misses the initial stats. Only coverage // will be impacted.) timer := time.NewTimer(1 * time.Millisecond) select { case <-stopBroadcasting: timer.Stop() return case <-timer.C: qs.BroadcastHealth(42, broadcastStatsFunc()) // Pace the flooding broadcasting to waste less CPU. timer.Reset(1 * time.Millisecond) } } // vtctl WaitForFilteredReplication returned. }