func TestPeriodic(t *testing.T) { fc := clockwork.NewFakeClock() rg := &fakeRevGetter{testutil.NewRecorderStream(), 0} compactable := &fakeCompactable{testutil.NewRecorderStream()} tb := &Periodic{ clock: fc, periodInHour: 1, rg: rg, c: compactable, } tb.Run() defer tb.Stop() n := int(time.Hour / checkCompactionInterval) // collect 3 hours of revisions for i := 0; i < 3; i++ { // advance one hour, one revision for each interval for j := 0; j < n; j++ { fc.Advance(checkCompactionInterval) rg.Wait(1) } // ready to acknowledge hour "i"; unblock clock fc.Advance(checkCompactionInterval) a, err := compactable.Wait(1) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(a[0].Params[0], &pb.CompactionRequest{Revision: int64(i*n) + 1}) { t.Errorf("compact request = %v, want %v", a[0].Params[0], &pb.CompactionRequest{Revision: int64(i*n) + 1}) } } }
func TestPeriodic(t *testing.T) { fc := clockwork.NewFakeClock() compactable := &fakeCompactable{testutil.NewRecorderStream()} tb := &Periodic{ clock: fc, periodInHour: 1, rg: &fakeRevGetter{}, c: compactable, } tb.Run() defer tb.Stop() n := int(time.Hour / checkCompactionInterval) for i := 0; i < 3; i++ { for j := 0; j < n; j++ { time.Sleep(5 * time.Millisecond) fc.Advance(checkCompactionInterval) } a, err := compactable.Wait(1) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(a[0].Params[0], &pb.CompactionRequest{Revision: int64(i*n) + 1}) { t.Errorf("compact request = %v, want %v", a[0].Params[0], &pb.CompactionRequest{Revision: int64(i*n) + 1}) } } }
func TestPeriodicPause(t *testing.T) { fc := clockwork.NewFakeClock() compactable := &fakeCompactable{testutil.NewRecorderStream()} rg := &fakeRevGetter{testutil.NewRecorderStream(), 0} tb := &Periodic{ clock: fc, periodInHour: 1, rg: rg, c: compactable, } tb.Run() tb.Pause() // tb will collect 3 hours of revisions but not compact since paused n := int(time.Hour / checkCompactionInterval) for i := 0; i < 3*n; i++ { fc.Advance(checkCompactionInterval) rg.Wait(1) } // tb ends up waiting for the clock select { case a := <-compactable.Chan(): t.Fatalf("unexpected action %v", a) case <-time.After(10 * time.Millisecond): } // tb resumes to being blocked on the clock tb.Resume() // unblock clock, will kick off a compaction at hour 3 fc.Advance(checkCompactionInterval) a, err := compactable.Wait(1) if err != nil { t.Fatal(err) } // compact the revision from hour 2 wreq := &pb.CompactionRequest{Revision: int64(2*n + 1)} if !reflect.DeepEqual(a[0].Params[0], wreq) { t.Errorf("compact request = %v, want %v", a[0].Params[0], wreq.Revision) } }
// TestPipelineSend tests that pipeline could send data using roundtripper // and increase success count in stats. func TestPipelineSend(t *testing.T) { tr := &roundTripperRecorder{rec: testutil.NewRecorderStream()} picker := mustNewURLPicker(t, []string{"http://localhost:2380"}) tp := &Transport{pipelineRt: tr} p := startTestPipeline(tp, picker) p.msgc <- raftpb.Message{Type: raftpb.MsgApp} tr.rec.Wait(1) p.stop() if p.followerStats.Counts.Success != 1 { t.Errorf("success = %d, want 1", p.followerStats.Counts.Success) } }
func TestPeriodicPause(t *testing.T) { fc := clockwork.NewFakeClock() compactable := &fakeCompactable{testutil.NewRecorderStream()} rg := &fakeRevGetter{testutil.NewRecorderStream(), 0} tb := &Periodic{ clock: fc, periodInHour: 1, rg: rg, c: compactable, } tb.Run() tb.Pause() n := int(time.Hour / checkCompactionInterval) for i := 0; i < 3*n; i++ { rg.Wait(1) fc.Advance(checkCompactionInterval) } select { case a := <-compactable.Chan(): t.Fatalf("unexpected action %v", a) case <-time.After(10 * time.Millisecond): } tb.Resume() rg.Wait(1) fc.Advance(checkCompactionInterval) a, err := compactable.Wait(1) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(a[0].Params[0], &pb.CompactionRequest{Revision: int64(2*n) + 2}) { t.Errorf("compact request = %v, want %v", a[0].Params[0], &pb.CompactionRequest{Revision: int64(2*n) + 2}) } }
// TestPipelineKeepSendingWhenPostError tests that pipeline can keep // sending messages if previous messages meet post error. func TestPipelineKeepSendingWhenPostError(t *testing.T) { tr := &respRoundTripper{rec: testutil.NewRecorderStream(), err: fmt.Errorf("roundtrip error")} picker := mustNewURLPicker(t, []string{"http://localhost:2380"}) tp := &Transport{pipelineRt: tr} p := startTestPipeline(tp, picker) defer p.stop() for i := 0; i < 50; i++ { p.msgc <- raftpb.Message{Type: raftpb.MsgApp} } _, err := tr.rec.Wait(50) if err != nil { t.Errorf("unexpected wait error %v", err) } }
// TestPipelineKeepSendingWhenPostError tests that pipeline can keep // sending messages if previous messages meet post error. func TestPipelineKeepSendingWhenPostError(t *testing.T) { tr := &respRoundTripper{rec: testutil.NewRecorderStream(), err: fmt.Errorf("roundtrip error")} picker := mustNewURLPicker(t, []string{"http://localhost:2380"}) fs := &stats.FollowerStats{} tp := &Transport{pipelineRt: tr} p := newPipeline(tp, picker, types.ID(2), types.ID(1), types.ID(1), newPeerStatus(types.ID(1)), fs, &fakeRaft{}, nil) defer p.stop() for i := 0; i < 50; i++ { p.msgc <- raftpb.Message{Type: raftpb.MsgApp} } _, err := tr.rec.Wait(50) if err != nil { t.Errorf("unexpected wait error %v", err) } }
// TestPipelineSendFailed tests that when send func meets the post error, // it increases fail count in stats. func TestPipelineSendFailed(t *testing.T) { picker := mustNewURLPicker(t, []string{"http://localhost:2380"}) rt := newRespRoundTripper(0, errors.New("blah")) rt.rec = testutil.NewRecorderStream() tp := &Transport{pipelineRt: rt} p := startTestPipeline(tp, picker) p.msgc <- raftpb.Message{Type: raftpb.MsgApp} if _, err := rt.rec.Wait(1); err != nil { t.Fatal(err) } p.stop() if p.followerStats.Counts.Fail != 1 { t.Errorf("fail = %d, want 1", p.followerStats.Counts.Fail) } }
func newReadyNode() *readyNode { return &readyNode{ nodeRecorder{testutil.NewRecorderStream()}, make(chan raft.Ready, 1)} }
func NewStorageRecorderStream(db string) *storageRecorder { return &storageRecorder{testutil.NewRecorderStream(), db} }
func newNodeRecorderStream() *nodeRecorder { return &nodeRecorder{testutil.NewRecorderStream()} }