func newTestInfoStore() (*infoStore, *stop.Stopper) { stopper := stop.NewStopper() nc := &base.NodeIDContainer{} nc.Set(context.TODO(), 1) is := newInfoStore(log.AmbientContext{}, nc, emptyAddr, stopper) return is, stopper }
func TestRangeIterForward(t *testing.T) { defer leaktest.AfterTest(t)() stopper := stop.NewStopper() defer stopper.Stop() g, clock := makeGossip(t, stopper) ds := NewDistSender(DistSenderConfig{ Clock: clock, RangeDescriptorDB: alphaRangeDescriptorDB, }, g) ctx := context.Background() ri := NewRangeIterator(ds) i := 0 span := roachpb.RSpan{ Key: roachpb.RKey(roachpb.KeyMin), EndKey: roachpb.RKey([]byte("z")), } for ri.Seek(ctx, span.Key, Ascending); ri.Valid(); ri.Next(ctx) { if !reflect.DeepEqual(alphaRangeDescriptors[i], ri.Desc()) { t.Fatalf("%d: expected %v; got %v", i, alphaRangeDescriptors[i], ri.Desc()) } i++ if !ri.NeedAnother(span) { break } } }
func TestRangeStatsInit(t *testing.T) { defer leaktest.AfterTest(t)() tc := testContext{} stopper := stop.NewStopper() defer stopper.Stop() tc.Start(t, stopper) ms := enginepb.MVCCStats{ LiveBytes: 1, KeyBytes: 2, ValBytes: 3, IntentBytes: 4, LiveCount: 5, KeyCount: 6, ValCount: 7, IntentCount: 8, IntentAge: 9, GCBytesAge: 10, LastUpdateNanos: 11, } if err := engine.MVCCSetRangeStats(context.Background(), tc.engine, 1, &ms); err != nil { t.Fatal(err) } loadMS, err := engine.MVCCGetRangeStats(context.Background(), tc.engine, tc.repl.RangeID) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(ms, loadMS) { t.Errorf("mvcc stats mismatch %+v != %+v", ms, loadMS) } }
func TestStopper(t *testing.T) { defer leaktest.AfterTest(t)() s := stop.NewStopper() running := make(chan struct{}) waiting := make(chan struct{}) cleanup := make(chan struct{}) s.RunWorker(func() { <-running }) go func() { <-s.ShouldStop() select { case <-waiting: t.Fatal("expected stopper to have blocked") case <-time.After(1 * time.Millisecond): // Expected. } close(running) select { case <-waiting: // Success. case <-time.After(100 * time.Millisecond): t.Fatal("stopper should have finished waiting") } close(cleanup) }() s.Stop() close(waiting) <-cleanup }
func TestSpanStatsGRPCResponse(t *testing.T) { defer leaktest.AfterTest(t)() ts := startServer(t) defer ts.Stopper().Stop() rpcStopper := stop.NewStopper() defer rpcStopper.Stop() rpcContext := rpc.NewContext(log.AmbientContext{}, ts.RPCContext().Config, ts.Clock(), rpcStopper) request := serverpb.SpanStatsRequest{ NodeID: "1", StartKey: []byte(roachpb.RKeyMin), EndKey: []byte(roachpb.RKeyMax), } url := ts.ServingAddr() conn, err := rpcContext.GRPCDial(url) if err != nil { t.Fatal(err) } client := serverpb.NewStatusClient(conn) response, err := client.SpanStats(context.Background(), &request) if err != nil { t.Fatal(err) } if a, e := int(response.RangeCount), ExpectedInitialRangeCount(); a != e { t.Errorf("expected %d ranges, found %d", e, a) } }
func runDebugRangeData(cmd *cobra.Command, args []string) error { stopper := stop.NewStopper() defer stopper.Stop() if len(args) != 2 { return errors.New("two arguments required: dir range_id") } db, err := openStore(cmd, args[0], stopper) if err != nil { return err } rangeID, err := parseRangeID(args[1]) if err != nil { return err } desc, err := loadRangeDescriptor(db, rangeID) if err != nil { return err } iter := storage.NewReplicaDataIterator(&desc, db, debugCtx.replicated) for ; iter.Valid(); iter.Next() { if _, err := printKeyValue(engine.MVCCKeyValue{ Key: iter.Key(), Value: iter.Value(), }); err != nil { return err } } return iter.Error() }
// TestStopperRunTaskPanic ensures that a panic handler can recover panicking // tasks, and that no tasks are leaked when they panic. func TestStopperRunTaskPanic(t *testing.T) { defer leaktest.AfterTest(t)() ch := make(chan interface{}) s := stop.NewStopper(stop.OnPanic(func(v interface{}) { ch <- v })) // If RunTask were not panic-safe, Stop() would deadlock. type testFn func() explode := func() { panic(ch) } for i, test := range []testFn{ func() { _ = s.RunTask(explode) }, func() { _ = s.RunAsyncTask(context.Background(), func(_ context.Context) { explode() }) }, func() { _ = s.RunLimitedAsyncTask( context.Background(), make(chan struct{}, 1), true, /* wait */ func(_ context.Context) { explode() }, ) }, func() { s.RunWorker(explode) }, } { go test() recovered := <-ch if recovered != ch { t.Errorf("%d: unexpected recovered value: %+v", i, recovered) } } }
// TestClientDisconnectRedundant verifies that the gossip server // will drop an outgoing client connection that is already an // inbound client connection of another node. func TestClientDisconnectRedundant(t *testing.T) { defer leaktest.AfterTest(t)() stopper := stop.NewStopper() defer stopper.Stop() local := startGossip(1, stopper, t, metric.NewRegistry()) remote := startGossip(2, stopper, t, metric.NewRegistry()) // startClient requires locks are held, so acquire here. local.mu.Lock() remote.mu.Lock() rAddr := remote.mu.is.NodeAddr lAddr := local.mu.is.NodeAddr local.startClient(&rAddr, remote.NodeID.Get()) remote.startClient(&lAddr, local.NodeID.Get()) local.mu.Unlock() remote.mu.Unlock() local.manage() remote.manage() util.SucceedsSoon(t, func() error { // Check which of the clients is connected to the other. ok1 := local.findClient(func(c *client) bool { return c.addr.String() == rAddr.String() }) != nil ok2 := remote.findClient(func(c *client) bool { return c.addr.String() == lAddr.String() }) != nil // We expect node 2 to disconnect; if both are still connected, // it's possible that node 1 gossiped before node 2 connected, in // which case we have to gossip from node 1 to trigger the // disconnect redundant client code. if ok1 && ok2 { if err := local.AddInfo("local-key", nil, time.Second); err != nil { t.Fatal(err) } } else if ok1 && !ok2 && verifyServerMaps(local, 0) && verifyServerMaps(remote, 1) { return nil } return errors.New("local client to remote not yet closed as redundant") }) }
// TestClientDisallowMultipleConns verifies that the server disallows // multiple connections from the same client node ID. func TestClientDisallowMultipleConns(t *testing.T) { defer leaktest.AfterTest(t)() stopper := stop.NewStopper() defer stopper.Stop() local := startGossip(1, stopper, t, metric.NewRegistry()) remote := startGossip(2, stopper, t, metric.NewRegistry()) local.mu.Lock() remote.mu.Lock() rAddr := remote.mu.is.NodeAddr // Start two clients from local to remote. RPC client cache is // disabled via the context, so we'll start two different outgoing // connections. local.startClient(&rAddr, remote.NodeID.Get()) local.startClient(&rAddr, remote.NodeID.Get()) local.mu.Unlock() remote.mu.Unlock() local.manage() remote.manage() util.SucceedsSoon(t, func() error { // Verify that the remote server has only a single incoming // connection and the local server has only a single outgoing // connection. local.mu.Lock() remote.mu.Lock() outgoing := local.outgoing.len() incoming := remote.mu.incoming.len() local.mu.Unlock() remote.mu.Unlock() if outgoing == 1 && incoming == 1 && verifyServerMaps(local, 0) && verifyServerMaps(remote, 1) { return nil } return errors.Errorf("incorrect number of incoming (%d) or outgoing (%d) connections", incoming, outgoing) }) }
// startFakeServerGossips creates local gossip instances and remote // faked gossip instance. The remote gossip instance launches its // faked gossip service just for check the client message. func startFakeServerGossips( t *testing.T, localNodeID roachpb.NodeID, ) (*Gossip, *fakeGossipServer, *stop.Stopper) { stopper := stop.NewStopper() lRPCContext := rpc.NewContext(log.AmbientContext{}, &base.Config{Insecure: true}, nil, stopper) lserver := rpc.NewServer(lRPCContext) local := NewTest(localNodeID, lRPCContext, lserver, nil, stopper, metric.NewRegistry()) lln, err := netutil.ListenAndServeGRPC(stopper, lserver, util.IsolatedTestAddr) if err != nil { t.Fatal(err) } local.start(lln.Addr()) rRPCContext := rpc.NewContext(log.AmbientContext{}, &base.Config{Insecure: true}, nil, stopper) rserver := rpc.NewServer(rRPCContext) rln, err := netutil.ListenAndServeGRPC(stopper, rserver, util.IsolatedTestAddr) if err != nil { t.Fatal(err) } remote := newFakeGossipServer(rserver, stopper) addr := rln.Addr() remote.nodeAddr = util.MakeUnresolvedAddr(addr.Network(), addr.String()) return local, remote, stopper }
// TestClientGossip verifies a client can gossip a delta to the server. func TestClientGossip(t *testing.T) { defer leaktest.AfterTest(t)() stopper := stop.NewStopper() local := startGossip(1, stopper, t, metric.NewRegistry()) remote := startGossip(2, stopper, t, metric.NewRegistry()) disconnected := make(chan *client, 1) c := newClient(log.AmbientContext{}, remote.GetNodeAddr(), makeMetrics()) defer func() { stopper.Stop() if c != <-disconnected { t.Errorf("expected client disconnect after remote close") } }() if err := local.AddInfo("local-key", nil, time.Hour); err != nil { t.Fatal(err) } if err := remote.AddInfo("remote-key", nil, time.Hour); err != nil { t.Fatal(err) } gossipSucceedsSoon(t, stopper, disconnected, map[*client]*Gossip{ c: local, }, func() error { if _, err := remote.GetInfo("local-key"); err != nil { return err } if _, err := local.GetInfo("remote-key"); err != nil { return err } return nil }) }
func TestHeartbeatCB(t *testing.T) { defer leaktest.AfterTest(t)() stopper := stop.NewStopper() defer stopper.Stop() clock := hlc.NewClock(time.Unix(0, 20).UnixNano, time.Nanosecond) serverCtx := newNodeTestContext(clock, stopper) s, ln := newTestServer(t, serverCtx, true) remoteAddr := ln.Addr().String() RegisterHeartbeatServer(s, &HeartbeatService{ clock: clock, remoteClockMonitor: serverCtx.RemoteClocks, }) // Clocks don't matter in this test. clientCtx := newNodeTestContext(clock, stopper) var once sync.Once ch := make(chan struct{}) clientCtx.HeartbeatCB = func() { once.Do(func() { close(ch) }) } _, err := clientCtx.GRPCDial(remoteAddr) if err != nil { t.Fatal(err) } <-ch }
// TestScannerTiming verifies that ranges are scanned, regardless // of how many, to match scanInterval. func TestScannerTiming(t *testing.T) { defer leaktest.AfterTest(t)() const count = 3 const runTime = 100 * time.Millisecond const maxError = 7500 * time.Microsecond durations := []time.Duration{ 15 * time.Millisecond, 25 * time.Millisecond, } for i, duration := range durations { testutils.SucceedsSoon(t, func() error { ranges := newTestRangeSet(count, t) q := &testQueue{} s := newReplicaScanner(log.AmbientContext{}, duration, 0, ranges) s.AddQueues(q) mc := hlc.NewManualClock(123) clock := hlc.NewClock(mc.UnixNano, time.Nanosecond) stopper := stop.NewStopper() s.Start(clock, stopper) time.Sleep(runTime) stopper.Stop() avg := s.avgScan() log.Infof(context.Background(), "%d: average scan: %s", i, avg) if avg.Nanoseconds()-duration.Nanoseconds() > maxError.Nanoseconds() || duration.Nanoseconds()-avg.Nanoseconds() > maxError.Nanoseconds() { return errors.Errorf("expected %s, got %s: exceeds max error of %s", duration, avg, maxError) } return nil }) } }
func TestClockOffsetMetrics(t *testing.T) { defer leaktest.AfterTest(t)() stopper := stop.NewStopper() defer stopper.Stop() clock := hlc.NewClock(hlc.NewManualClock(123).UnixNano, 20*time.Nanosecond) monitor := newRemoteClockMonitor(clock, time.Hour) monitor.mu.offsets = map[string]RemoteOffset{ "0": { Offset: 13, Uncertainty: 7, MeasuredAt: 6, }, } if err := monitor.VerifyClockOffset(context.TODO()); err != nil { t.Fatal(err) } if a, e := monitor.Metrics().ClockOffsetMeanNanos.Value(), int64(13); a != e { t.Errorf("mean %d != expected %d", a, e) } if a, e := monitor.Metrics().ClockOffsetStdDevNanos.Value(), int64(7); a != e { t.Errorf("stdDev %d != expected %d", a, e) } }
// ExtendLease and ReleaseLease errors should not, by themselves, cause the // migration process to fail. Not being able to acquire the lease should, but // we don't test that here due to the added code that would be needed to change // its retry settings to allow for testing it in a reasonable amount of time. func TestLeaseErrors(t *testing.T) { db := &fakeDB{kvs: make(map[string][]byte)} mgr := Manager{ stopper: stop.NewStopper(), leaseManager: &fakeLeaseManager{ extendErr: fmt.Errorf("context deadline exceeded"), releaseErr: fmt.Errorf("context deadline exceeded"), }, db: db, } defer mgr.stopper.Stop() migration := noopMigration1 backwardCompatibleMigrations = []migrationDescriptor{migration} if err := mgr.EnsureMigrations(context.Background()); err != nil { t.Error(err) } if _, ok := db.kvs[string(migrationKey(migration))]; !ok { t.Errorf("expected key %s to be written, but it wasn't", migrationKey(migration)) } if len(db.kvs) != len(backwardCompatibleMigrations) { t.Errorf("expected %d key to be written, but %d were", len(backwardCompatibleMigrations), len(db.kvs)) } }
// TestClientForwardUnresolved verifies that a client does not resolve a forward // address prematurely. func TestClientForwardUnresolved(t *testing.T) { defer leaktest.AfterTest(t)() stopper := stop.NewStopper() defer stopper.Stop() const nodeID = 1 local := startGossip(nodeID, stopper, t, metric.NewRegistry()) addr := local.GetNodeAddr() client := newClient(log.AmbientContext{}, addr, makeMetrics()) // never started newAddr := util.UnresolvedAddr{ NetworkField: "tcp", AddressField: "localhost:2345", } reply := &Response{ NodeID: nodeID, Addr: *addr, AlternateNodeID: nodeID + 1, AlternateAddr: &newAddr, } if err := client.handleResponse( context.TODO(), local, reply, ); !testutils.IsError(err, "received forward") { t.Fatal(err) } if !proto.Equal(client.forwardAddr, &newAddr) { t.Fatalf("unexpected forward address %v, expected %v", client.forwardAddr, &newAddr) } }
// The lease not having enough time left on it to finish migrations should // cause the process to exit via a call to log.Fatal. func TestLeaseExpiration(t *testing.T) { db := &fakeDB{kvs: make(map[string][]byte)} mgr := Manager{ stopper: stop.NewStopper(), leaseManager: &fakeLeaseManager{leaseTimeRemaining: time.Nanosecond}, db: db, } defer mgr.stopper.Stop() oldLeaseRefreshInterval := leaseRefreshInterval leaseRefreshInterval = time.Microsecond defer func() { leaseRefreshInterval = oldLeaseRefreshInterval }() exitCalled := make(chan bool) log.SetExitFunc(func(int) { exitCalled <- true }) defer log.SetExitFunc(os.Exit) waitForExitMigration := migrationDescriptor{ name: "wait for exit to be called", workFn: func(context.Context, runner) error { select { case <-exitCalled: return nil case <-time.After(10 * time.Second): return fmt.Errorf("timed out waiting for exit to be called") } }, } backwardCompatibleMigrations = []migrationDescriptor{waitForExitMigration} if err := mgr.EnsureMigrations(context.Background()); err != nil { t.Error(err) } }
func TestGossipRaceLogStatus(t *testing.T) { defer leaktest.AfterTest(t)() stopper := stop.NewStopper() defer stopper.Stop() local := startGossip(1, stopper, t, metric.NewRegistry()) local.mu.Lock() peer := startGossip(2, stopper, t, metric.NewRegistry()) local.startClient(&peer.mu.is.NodeAddr) local.mu.Unlock() // Race gossiping against LogStatus. gun := make(chan struct{}) for i := uint8(0); i < 10; i++ { go func() { <-gun local.LogStatus() gun <- struct{}{} }() gun <- struct{}{} if err := local.AddInfo( strconv.FormatUint(uint64(i), 10), []byte{i}, time.Hour, ); err != nil { t.Fatal(err) } <-gun } close(gun) }
// TestTxnCoordSenderSingleRoundtripTxn checks that a batch which completely // holds the writing portion of a Txn (including EndTransaction) does not // launch a heartbeat goroutine at all. func TestTxnCoordSenderSingleRoundtripTxn(t *testing.T) { defer leaktest.AfterTest(t)() stopper := stop.NewStopper() manual := hlc.NewManualClock(123) clock := hlc.NewClock(manual.UnixNano, 20*time.Nanosecond) senderFunc := func(_ context.Context, ba roachpb.BatchRequest) (*roachpb.BatchResponse, *roachpb.Error) { br := ba.CreateReply() txnClone := ba.Txn.Clone() br.Txn = &txnClone br.Txn.Writing = true return br, nil } ambient := log.AmbientContext{Tracer: tracing.NewTracer()} ts := NewTxnCoordSender( ambient, senderFn(senderFunc), clock, false, stopper, MakeTxnMetrics(metric.TestSampleInterval), ) // Stop the stopper manually, prior to trying the transaction. This has the // effect of returning a NodeUnavailableError for any attempts at launching // a heartbeat goroutine. stopper.Stop() var ba roachpb.BatchRequest key := roachpb.Key("test") ba.Add(&roachpb.BeginTransactionRequest{Span: roachpb.Span{Key: key}}) ba.Add(&roachpb.PutRequest{Span: roachpb.Span{Key: key}}) ba.Add(&roachpb.EndTransactionRequest{}) ba.Txn = &roachpb.Transaction{Name: "test"} _, pErr := ts.Send(context.Background(), ba) if pErr != nil { t.Fatal(pErr) } }
func TestRangeIterSeekForward(t *testing.T) { defer leaktest.AfterTest(t)() stopper := stop.NewStopper() defer stopper.Stop() g, clock := makeGossip(t, stopper) ds := NewDistSender(DistSenderConfig{ Clock: clock, RangeDescriptorDB: alphaRangeDescriptorDB, }, g) ctx := context.Background() ri := NewRangeIterator(ds, false /*reverse*/) i := 0 for ri.Seek(ctx, roachpb.RKey(roachpb.KeyMin)); ri.Valid(); { if !reflect.DeepEqual(alphaRangeDescriptors[i], ri.Desc()) { t.Fatalf("%d: expected %v; got %v", i, alphaRangeDescriptors[i], ri.Desc()) } i += 2 // Skip even ranges. nextByte := ri.Desc().EndKey[0] + 1 if nextByte >= byte('z') { break } seekKey := roachpb.RKey([]byte{nextByte}) ri.Seek(ctx, seekKey) if !ri.Key().Equal(seekKey) { t.Errorf("expected iterator key %s; got %s", seekKey, ri.Key()) } } }
func TestStopperShouldQuiesce(t *testing.T) { defer leaktest.AfterTest(t)() s := stop.NewStopper() running := make(chan struct{}) runningTask := make(chan struct{}) waiting := make(chan struct{}) cleanup := make(chan struct{}) // Run a worker. A call to stopper.Stop() will not close until all workers // have completed, and this worker will complete when the "running" channel // is closed. s.RunWorker(func() { <-running }) // Run an asynchronous task. A stopper which has been Stop()ed will not // close it's ShouldStop() channel until all tasks have completed. This task // will complete when the "runningTask" channel is closed. if err := s.RunAsyncTask(context.Background(), func(_ context.Context) { <-runningTask }); err != nil { t.Fatal(err) } go func() { // The ShouldQuiesce() channel should close as soon as the stopper is // Stop()ed. <-s.ShouldQuiesce() // However, the ShouldStop() channel should still be blocked because the // async task started above is still running, meaning we haven't quiesceed // yet. select { case <-s.ShouldStop(): t.Fatal("expected ShouldStop() to block until quiesceing complete") default: // Expected. } // After completing the running task, the ShouldStop() channel should // now close. close(runningTask) <-s.ShouldStop() // However, the working running above prevents the call to Stop() from // returning; it blocks until the runner's goroutine is finished. We // use the "waiting" channel to detect this. select { case <-waiting: t.Fatal("expected stopper to have blocked") default: // Expected. } // Finally, close the "running" channel, which should cause the original // call to Stop() to return. close(running) <-waiting close(cleanup) }() s.Stop() close(waiting) <-cleanup }
func TestRangeIterReverse(t *testing.T) { defer leaktest.AfterTest(t)() stopper := stop.NewStopper() defer stopper.Stop() g, clock := makeGossip(t, stopper) ds := NewDistSender(DistSenderConfig{ Clock: clock, RangeDescriptorDB: alphaRangeDescriptorDB, }, g) ctx := context.Background() ri := NewRangeIterator(ds, true /*reverse*/) i := len(alphaRangeDescriptors) - 1 for ri.Seek(ctx, roachpb.RKey([]byte{'z'})); ri.Valid(); ri.Next(ctx) { if !reflect.DeepEqual(alphaRangeDescriptors[i], ri.Desc()) { t.Fatalf("%d: expected %v; got %v", i, alphaRangeDescriptors[i], ri.Desc()) } i-- if !ri.NeedAnother(roachpb.RSpan{ Key: roachpb.RKey(roachpb.KeyMin), }) { break } } }
func TestStopperIsStopped(t *testing.T) { defer leaktest.AfterTest(t)() s := stop.NewStopper() bc := newBlockingCloser() s.AddCloser(bc) go s.Stop() select { case <-s.ShouldStop(): case <-time.After(100 * time.Millisecond): t.Fatal("stopper should have finished waiting") } select { case <-s.IsStopped(): t.Fatal("expected blocked closer to prevent stop") case <-time.After(1 * time.Millisecond): // Expected. } bc.Unblock() select { case <-s.IsStopped(): // Expected case <-time.After(100 * time.Millisecond): t.Fatal("stopper should have finished stopping") } }
// TestBatchScanWithDelete verifies that a scan containing // a single deleted value returns nothing. func TestBatchScanWithDelete(t *testing.T) { defer leaktest.AfterTest(t)() stopper := stop.NewStopper() defer stopper.Stop() e := NewInMem(roachpb.Attributes{}, 1<<20) stopper.AddCloser(e) b := e.NewBatch() defer b.Close() // Write initial value, then delete via batch. if err := e.Put(mvccKey("a"), []byte("value")); err != nil { t.Fatal(err) } if err := b.Clear(mvccKey("a")); err != nil { t.Fatal(err) } kvs, err := Scan(b, mvccKey(roachpb.RKeyMin), mvccKey(roachpb.RKeyMax), 0) if err != nil { t.Fatal(err) } if len(kvs) != 0 { t.Errorf("expected empty scan with batch-deleted value; got %v", kvs) } }
func TestRangeIterSeekReverse(t *testing.T) { defer leaktest.AfterTest(t)() stopper := stop.NewStopper() defer stopper.Stop() g, clock := makeGossip(t, stopper) ds := NewDistSender(DistSenderConfig{ Clock: clock, RangeDescriptorDB: alphaRangeDescriptorDB, }, g) ctx := context.Background() ri := NewRangeIterator(ds) i := len(alphaRangeDescriptors) - 1 for ri.Seek(ctx, roachpb.RKey([]byte{'z'}), Descending); ri.Valid(); { if !reflect.DeepEqual(alphaRangeDescriptors[i], ri.Desc()) { t.Fatalf("%d: expected %v; got %v", i, alphaRangeDescriptors[i], ri.Desc()) } i -= 2 // Skip every other range. nextByte := ri.Desc().StartKey[0] - 1 if nextByte <= byte('a') { break } seekKey := roachpb.RKey([]byte{nextByte}) ri.Seek(ctx, seekKey, Descending) if !ri.Key().Equal(seekKey) { t.Errorf("expected iterator key %s; got %s", seekKey, ri.Key()) } } }
// TestBatchScanMaxWithDeleted verifies that if a deletion // in the updates map shadows an entry from the engine, the // max on a scan is still reached. func TestBatchScanMaxWithDeleted(t *testing.T) { defer leaktest.AfterTest(t)() stopper := stop.NewStopper() defer stopper.Stop() e := NewInMem(roachpb.Attributes{}, 1<<20) stopper.AddCloser(e) b := e.NewBatch() defer b.Close() // Write two values. if err := e.Put(mvccKey("a"), []byte("value1")); err != nil { t.Fatal(err) } if err := e.Put(mvccKey("b"), []byte("value2")); err != nil { t.Fatal(err) } // Now, delete "a" in batch. if err := b.Clear(mvccKey("a")); err != nil { t.Fatal(err) } // A scan with max=1 should scan "b". kvs, err := Scan(b, mvccKey(roachpb.RKeyMin), mvccKey(roachpb.RKeyMax), 1) if err != nil { t.Fatal(err) } if len(kvs) != 1 || !bytes.Equal(kvs[0].Key.Key, []byte("b")) { t.Errorf("expected scan of \"b\"; got %v", kvs) } }
// Verify that when we enqueue the same range multiple times for the same // reason, it is only processed once. func TestSchedulerBuffering(t *testing.T) { defer leaktest.AfterTest(t)() p := newTestProcessor() s := newRaftScheduler(log.AmbientContext{}, nil, p, 1) stopper := stop.NewStopper() defer stopper.Stop() s.Start(stopper) testCases := []struct { state raftScheduleState expected string }{ {stateRaftReady, "ready=[1:1] request=[] tick=[]"}, {stateRaftRequest, "ready=[1:1] request=[1:1] tick=[]"}, {stateRaftTick, "ready=[1:1] request=[1:1] tick=[1:1]"}, {stateRaftReady | stateRaftRequest | stateRaftTick, "ready=[1:2] request=[1:2] tick=[1:2]"}, } for _, c := range testCases { s.signal(s.enqueueN(c.state, 1, 1, 1, 1, 1)) util.SucceedsSoon(t, func() error { if s := p.String(); c.expected != s { return errors.Errorf("expected %s, but got %s", c.expected, s) } return nil }) } }
// TestBatchConcurrency verifies operation of batch when the // underlying engine has concurrent modifications to overlapping // keys. This should never happen with the way Cockroach uses // batches, but worth verifying. func TestBatchConcurrency(t *testing.T) { defer leaktest.AfterTest(t)() stopper := stop.NewStopper() defer stopper.Stop() e := NewInMem(roachpb.Attributes{}, 1<<20) stopper.AddCloser(e) b := e.NewBatch() defer b.Close() // Write a merge to the batch. if err := b.Merge(mvccKey("a"), appender("bar")); err != nil { t.Fatal(err) } val, err := b.Get(mvccKey("a")) if err != nil { t.Fatal(err) } if !compareMergedValues(t, val, appender("bar")) { t.Error("mismatch of \"a\"") } // Write an engine value. if err := e.Put(mvccKey("a"), appender("foo")); err != nil { t.Fatal(err) } // Now, read again and verify that the merge happens on top of the mod. val, err = b.Get(mvccKey("a")) if err != nil { t.Fatal(err) } if !bytes.Equal(val, appender("foobar")) { t.Error("mismatch of \"a\"") } }
func BenchmarkReplicaSnapshot(b *testing.B) { defer tracing.Disable()() storeCfg := TestStoreConfig(nil) storeCfg.TestingKnobs.DisableSplitQueue = true stopper := stop.NewStopper() defer stopper.Stop() store := createTestStoreWithConfig(b, stopper, &storeCfg) // We want to manually control the size of the raft log. store.SetRaftLogQueueActive(false) rep, err := store.GetReplica(rangeID) if err != nil { b.Fatal(err) } snapSize := rep.GetMaxBytes() if err := fillTestRange(rep, snapSize); err != nil { b.Fatal(err) } b.SetBytes(snapSize) b.ResetTimer() for i := 0; i < b.N; i++ { if _, err := rep.GetSnapshot(context.Background(), "bench"); err != nil { b.Fatal(err) } rep.CloseOutSnap() } }
// runWithAllEngines creates a new engine of each supported type and // invokes the supplied test func with each instance. func runWithAllEngines(test func(e Engine, t *testing.T), t *testing.T) { stopper := stop.NewStopper() defer stopper.Stop() inMem := NewInMem(inMemAttrs, testCacheSize) stopper.AddCloser(inMem) test(inMem, t) }