Skip to content

Commit 64a406f

Browse files
Test for catchup stop on completion (#3306)
Adding a test for the fix in #3299 ## Test Plan This is a test
1 parent 8f62aff commit 64a406f

File tree

1 file changed

+89
-0
lines changed

1 file changed

+89
-0
lines changed

test/e2e-go/features/catchup/basicCatchup_test.go

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,3 +331,92 @@ func shutdownClonedNode(nodeDataDir string, f *fixtures.RestClientFixture, t *te
331331
os.RemoveAll(nodeDataDir)
332332
}
333333
}
334+
335+
// TestBasicCatchupCompletes confirms the the catchup eventually completes and stops.
336+
func TestBasicCatchupCompletes(t *testing.T) {
337+
partitiontest.PartitionTest(t)
338+
defer fixtures.ShutdownSynchronizedTest(t)
339+
340+
if testing.Short() {
341+
t.Skip()
342+
}
343+
t.Parallel()
344+
a := require.New(fixtures.SynchronizedTest(t))
345+
346+
// Make the network progress faster
347+
consensus := make(config.ConsensusProtocols)
348+
fastProtocol := config.Consensus[protocol.ConsensusCurrentVersion]
349+
fastProtocol.ApprovedUpgrades = map[protocol.ConsensusVersion]uint64{}
350+
fastProtocol.AgreementFilterTimeoutPeriod0 = 400 * time.Millisecond
351+
fastProtocol.AgreementFilterTimeout = 400 * time.Millisecond
352+
consensus[protocol.ConsensusCurrentVersion] = fastProtocol
353+
354+
// Setup the fixture with the modified fast consensus
355+
var fixture fixtures.RestClientFixture
356+
fixture.SetConsensus(consensus)
357+
fixture.Setup(t, filepath.Join("nettemplates", "TwoNodes100Second.json"))
358+
defer fixture.Shutdown()
359+
360+
// Get 2nd node so we wait until we know they're at target block
361+
nc, err := fixture.GetNodeController("Node")
362+
a.NoError(err)
363+
364+
// Let the network make some progress.
365+
// Make it long enough so the catchup to it is longer than a single round agreement
366+
a.NoError(err)
367+
waitForRound := uint64(100)
368+
369+
// Now prepare a third node
370+
cloneDataDir := filepath.Join(fixture.PrimaryDataDir(), "../clone")
371+
cloneLedger := false
372+
err = fixture.NC.Clone(cloneDataDir, cloneLedger)
373+
a.NoError(err)
374+
375+
// Wait for the network to make some progess.
376+
err = fixture.ClientWaitForRoundWithTimeout(fixture.GetAlgodClientForController(nc), waitForRound)
377+
a.NoError(err)
378+
379+
// Start the third node to catchup.
380+
startTime := time.Now()
381+
cloneClient, err := fixture.StartNode(cloneDataDir)
382+
a.NoError(err)
383+
defer shutdownClonedNode(cloneDataDir, &fixture, t)
384+
385+
// Wait for it to catchup
386+
err = fixture.LibGoalFixture.ClientWaitForRoundWithTimeout(cloneClient, waitForRound)
387+
a.NoError(err)
388+
389+
// Calculate the catchup time
390+
catchupTime := time.Since(startTime)
391+
392+
// Check if curStatus.CatchupTime, the "Time since last block" is less than the catchup time.
393+
// - If the catchup has not stopped, this value will keep on growing, and eventually be larger than the time
394+
// of a single round agreement.
395+
// - If the catchup stops after it completes, this value will be the time since the last round was
396+
// obtained through the agreement, and be much smaller than the catchup time.
397+
client := fixture.GetAlgodClientForController(fixture.LibGoalFixture.GetNodeControllerForDataDir(cloneDataDir))
398+
399+
// Prevent false positive
400+
// - Since obtaining the exact catchup time is not possible, wait catchupTime again, to make sure curStatus.CatchupTime
401+
// will be at least our estimated catchupTime (since it keeps on growing if catchup has not stopped).
402+
time.Sleep(catchupTime)
403+
404+
// Prevent false negative
405+
// The network may have made some progress since waitForRound, it could be that the
406+
// third node is still catching up even after getting to waitForRound.
407+
// Moreover, it takes some time to transition from the catchup to agreement.
408+
// Give it some more time and check again..
409+
pass := false
410+
for x := 0; x < 100; x++ {
411+
curStatus, statusErr := client.Status()
412+
require.NoError(t, statusErr, "fixture should be able to get node status")
413+
currentStateMsec := time.Duration(curStatus.CatchupTime).Milliseconds()
414+
catchupMsec := catchupTime.Milliseconds()
415+
pass = currentStateMsec < catchupMsec
416+
if pass {
417+
break
418+
}
419+
time.Sleep(100 * time.Millisecond)
420+
}
421+
a.True(pass)
422+
}

0 commit comments

Comments
 (0)