Skip to content

Commit 80fcd3a

Browse files
committed
fix: add assertions for response completion
1 parent 6b1439e commit 80fcd3a

File tree

1 file changed

+77
-21
lines changed

1 file changed

+77
-21
lines changed

impl/graphsync_test.go

+77-21
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ func TestRejectRequestsByDefault(t *testing.T) {
184184

185185
requestor := td.GraphSyncHost1()
186186
// setup responder to disable default validation, meaning all requests are rejected
187-
_ = td.GraphSyncHost2(RejectAllRequestsByDefault())
188-
187+
responder := td.GraphSyncHost2(RejectAllRequestsByDefault())
188+
assertComplete := assertCompletionFunction(responder, 1)
189189
blockChainLength := 5
190190
blockChain := testutil.SetupBlockChain(ctx, t, td.persistence2, 5, blockChainLength)
191191

@@ -196,6 +196,8 @@ func TestRejectRequestsByDefault(t *testing.T) {
196196
testutil.VerifySingleTerminalError(ctx, t, errChan)
197197

198198
drain(requestor)
199+
drain(responder)
200+
assertComplete(ctx, t)
199201

200202
tracing := collectTracing(t)
201203
require.ElementsMatch(t, []string{
@@ -229,7 +231,7 @@ func TestGraphsyncRoundTripRequestBudgetRequestor(t *testing.T) {
229231

230232
// initialize graphsync on second node to response to requests
231233
responder := td.GraphSyncHost2()
232-
234+
assertCancelOrComplete := assertCancelOrCompleteFunction(responder, 1)
233235
progressChan, errChan := requestor.Request(ctx, td.host2.ID(), blockChain.TipLink, blockChain.Selector(), td.extension)
234236

235237
// response budgets don't include the root block, so total links traverse with be one more than expected
@@ -239,19 +241,21 @@ func TestGraphsyncRoundTripRequestBudgetRequestor(t *testing.T) {
239241

240242
drain(requestor)
241243
drain(responder)
242-
244+
wasCancelled := assertCancelOrComplete(ctx, t)
243245
tracing := collectTracing(t)
244246
traceStrings := tracing.TracesToStrings()
245-
// TODO: this may or may not appear
246247
require.Contains(t, traceStrings, "response(0)->executeTask(0)")
247-
// may or may not contain one of these: "response(0)->abortRequest(0)"
248-
// TODO: figure out why and confirm this is OK
248+
if wasCancelled {
249+
require.Contains(t, traceStrings, "response(0)->abortRequest(0)")
250+
}
249251
require.Contains(t, traceStrings, "request(0)->newRequest(0)")
250252
require.Contains(t, traceStrings, "request(0)->executeTask(0)")
251253
require.Contains(t, traceStrings, "request(0)->terminateRequest(0)")
252254
// has ErrBudgetExceeded exception recorded in the right place
253255
tracing.SingleExceptionEvent(t, "request(0)->executeTask(0)", "ErrBudgetExceeded", "traversal budget exceeded", true)
254-
tracing.SingleExceptionEvent(t, "response(0)->executeTask(0)", "ContextCancelError", ipldutil.ContextCancelError{}.Error(), true)
256+
if wasCancelled {
257+
tracing.SingleExceptionEvent(t, "response(0)->executeTask(0)", "ContextCancelError", ipldutil.ContextCancelError{}.Error(), true)
258+
}
255259
}
256260

257261
func TestGraphsyncRoundTripRequestBudgetResponder(t *testing.T) {
@@ -529,7 +533,7 @@ func TestGraphsyncRoundTripIgnoreNBlocks(t *testing.T) {
529533

530534
// initialize graphsync on second node to response to requests
531535
responder := td.GraphSyncHost2()
532-
536+
assertComplete := assertCompletionFunction(responder, 1)
533537
totalSent := 0
534538
totalSentOnWire := 0
535539
responder.RegisterOutgoingBlockHook(func(p peer.ID, requestData graphsync.RequestData, blockData graphsync.BlockData, hookActions graphsync.OutgoingBlockHookActions) {
@@ -553,7 +557,7 @@ func TestGraphsyncRoundTripIgnoreNBlocks(t *testing.T) {
553557

554558
drain(requestor)
555559
drain(responder)
556-
560+
assertComplete(ctx, t)
557561
tracing := collectTracing(t)
558562
require.ElementsMatch(t, []string{
559563
"response(0)->executeTask(0)",
@@ -600,7 +604,7 @@ func TestPauseResume(t *testing.T) {
600604
hookActions.TerminateWithError(errors.New("should have sent extension"))
601605
}
602606
})
603-
607+
assertOneRequestCompletes := assertCompletionFunction(responder, 1)
604608
progressChan, errChan := requestor.Request(ctx, td.host2.ID(), blockChain.TipLink, blockChain.Selector(), td.extension)
605609

606610
blockChain.VerifyResponseRange(ctx, progressChan, 0, stopPoint)
@@ -636,12 +640,11 @@ func TestPauseResume(t *testing.T) {
636640

637641
drain(requestor)
638642
drain(responder)
639-
643+
assertOneRequestCompletes(ctx, t)
640644
tracing := collectTracing(t)
641645
traceStrings := tracing.TracesToStrings()
642646
require.Contains(t, traceStrings, "response(0)->executeTask(0)")
643-
// may or may not contain an extra execute: "response(0)->executeTask(1)"
644-
// TODO: figure out why and confirm this is OK
647+
require.Contains(t, traceStrings, "response(0)->executeTask(1)")
645648
require.Contains(t, traceStrings, "request(0)->newRequest(0)")
646649
require.Contains(t, traceStrings, "request(0)->executeTask(0)")
647650
require.Contains(t, traceStrings, "request(0)->terminateRequest(0)")
@@ -668,6 +671,7 @@ func TestPauseResumeRequest(t *testing.T) {
668671

669672
// initialize graphsync on second node to response to requests
670673
responder := td.GraphSyncHost2()
674+
assertCancelOrComplete := assertCancelOrCompleteFunction(responder, 2)
671675

672676
stopPoint := 50
673677
blocksReceived := 0
@@ -699,14 +703,23 @@ func TestPauseResumeRequest(t *testing.T) {
699703

700704
drain(requestor)
701705
drain(responder)
702-
706+
// the request may actually only get sent onces -- it depends
707+
// on whether the responder completes its send before getting the cancel
708+
// signal. even if the request pauses before the request is over,
709+
// it may not make another graphsync request if it
710+
// ingested the blocks into the temporary cache
711+
wasCancelled := assertCancelOrComplete(ctx, t)
712+
if wasCancelled {
713+
// should get max 1 cancel
714+
require.False(t, assertCancelOrComplete(ctx, t))
715+
}
703716
tracing := collectTracing(t)
704717
traceStrings := tracing.TracesToStrings()
705718
require.Contains(t, traceStrings, "response(0)->executeTask(0)")
706-
// may or may not contain this: "response(0)->abortRequest(0)"
707-
// TODO: figure out why and confirm this is OK
708-
// may or may not contain an extra response+execute: "response(1)->executeTask(0)"
709-
// TODO: figure out why and confirm this is OK
719+
if wasCancelled {
720+
require.Contains(t, traceStrings, "response(0)->abortRequest(0)")
721+
require.Contains(t, traceStrings, "response(1)->executeTask(0)")
722+
}
710723
require.Contains(t, traceStrings, "request(0)->newRequest(0)")
711724
require.Contains(t, traceStrings, "request(0)->executeTask(0)")
712725
require.Contains(t, traceStrings, "request(0)->executeTask(1)")
@@ -766,6 +779,7 @@ func TestPauseResumeViaUpdate(t *testing.T) {
766779
hookActions.UnpauseResponse()
767780
}
768781
})
782+
assertComplete := assertCompletionFunction(responder, 1)
769783
progressChan, errChan := requestor.Request(ctx, td.host2.ID(), blockChain.TipLink, blockChain.Selector(), td.extension)
770784

771785
blockChain.VerifyWholeChain(ctx, progressChan)
@@ -777,6 +791,7 @@ func TestPauseResumeViaUpdate(t *testing.T) {
777791

778792
drain(requestor)
779793
drain(responder)
794+
assertComplete(ctx, t)
780795

781796
tracing := collectTracing(t)
782797
// j, _ := json.MarshalIndent(tracing.FindSpans("executeTask"), "", " ")
@@ -852,6 +867,7 @@ func TestPauseResumeViaUpdateOnBlockHook(t *testing.T) {
852867
hookActions.UnpauseResponse()
853868
}
854869
})
870+
assertComplete := assertCompletionFunction(responder, 1)
855871
progressChan, errChan := requestor.Request(ctx, td.host2.ID(), blockChain.TipLink, blockChain.Selector(), td.extension)
856872

857873
blockChain.VerifyWholeChain(ctx, progressChan)
@@ -863,6 +879,7 @@ func TestPauseResumeViaUpdateOnBlockHook(t *testing.T) {
863879

864880
drain(requestor)
865881
drain(responder)
882+
assertComplete(ctx, t)
866883

867884
tracing := collectTracing(t)
868885
require.ElementsMatch(t, []string{
@@ -962,7 +979,7 @@ func TestNetworkDisconnect(t *testing.T) {
962979
traceStrings := tracing.TracesToStrings()
963980
require.Contains(t, traceStrings, "response(0)->executeTask(0)")
964981
// may contain multiple abortRequest traces as the network error can bubble up >1 times
965-
require.Contains(t, traceStrings, "response(0)->abortRequest(0)")
982+
// but these will only record if the request is still executing
966983
require.Contains(t, traceStrings, "request(0)->newRequest(0)")
967984
require.Contains(t, traceStrings, "request(0)->executeTask(0)")
968985
require.Contains(t, traceStrings, "request(0)->terminateRequest(0)")
@@ -1032,6 +1049,7 @@ func TestGraphsyncRoundTripAlternatePersistenceAndNodes(t *testing.T) {
10321049

10331050
// initialize graphsync on second node to response to requests
10341051
responder := td.GraphSyncHost2()
1052+
assertComplete := assertCompletionFunction(responder, 2)
10351053

10361054
// alternate storing location for responder
10371055
altStore1 := make(map[ipld.Link][]byte)
@@ -1086,6 +1104,8 @@ func TestGraphsyncRoundTripAlternatePersistenceAndNodes(t *testing.T) {
10861104

10871105
drain(requestor)
10881106
drain(responder)
1107+
assertComplete(ctx, t)
1108+
assertComplete(ctx, t)
10891109

10901110
tracing := collectTracing(t)
10911111
// two complete request traces expected
@@ -1117,6 +1137,7 @@ func TestGraphsyncRoundTripMultipleAlternatePersistence(t *testing.T) {
11171137

11181138
// initialize graphsync on second node to response to requests
11191139
responder := td.GraphSyncHost2()
1140+
assertComplete := assertCompletionFunction(responder, 2)
11201141

11211142
// alternate storing location for responder
11221143
altStore1 := make(map[ipld.Link][]byte)
@@ -1170,6 +1191,8 @@ func TestGraphsyncRoundTripMultipleAlternatePersistence(t *testing.T) {
11701191

11711192
drain(requestor)
11721193
drain(responder)
1194+
assertComplete(ctx, t)
1195+
assertComplete(ctx, t)
11731196

11741197
tracing := collectTracing(t)
11751198
// two complete request traces expected
@@ -1217,14 +1240,15 @@ func TestRoundTripLargeBlocksSlowNetwork(t *testing.T) {
12171240

12181241
// initialize graphsync on second node to response to requests
12191242
responder := td.GraphSyncHost2()
1220-
1243+
assertComplete := assertCompletionFunction(responder, 1)
12211244
progressChan, errChan := requestor.Request(ctx, td.host2.ID(), blockChain.TipLink, blockChain.Selector())
12221245

12231246
blockChain.VerifyWholeChain(ctx, progressChan)
12241247
testutil.VerifyEmptyErrors(ctx, t, errChan)
12251248

12261249
drain(requestor)
12271250
drain(responder)
1251+
assertComplete(ctx, t)
12281252

12291253
tracing := collectTracing(t)
12301254
require.ElementsMatch(t, []string{
@@ -1484,6 +1508,38 @@ func drain(gs graphsync.GraphExchange) {
14841508
gs.(*GraphSync).responseManager.Synchronize()
14851509
}
14861510

1511+
func assertCompletionFunction(gs graphsync.GraphExchange, completedRequestCount int) func(context.Context, *testing.T) {
1512+
completedResponse := make(chan struct{}, completedRequestCount)
1513+
gs.RegisterCompletedResponseListener(func(p peer.ID, request graphsync.RequestData, status graphsync.ResponseStatusCode) {
1514+
completedResponse <- struct{}{}
1515+
})
1516+
return func(ctx context.Context, t *testing.T) {
1517+
testutil.AssertDoesReceive(ctx, t, completedResponse, "request never completed")
1518+
}
1519+
}
1520+
1521+
func assertCancelOrCompleteFunction(gs graphsync.GraphExchange, requestCount int) func(context.Context, *testing.T) bool {
1522+
completedResponse := make(chan struct{}, requestCount)
1523+
gs.RegisterCompletedResponseListener(func(p peer.ID, request graphsync.RequestData, status graphsync.ResponseStatusCode) {
1524+
completedResponse <- struct{}{}
1525+
})
1526+
cancelledResponse := make(chan struct{}, requestCount)
1527+
gs.RegisterRequestorCancelledListener(func(p peer.ID, request graphsync.RequestData) {
1528+
cancelledResponse <- struct{}{}
1529+
})
1530+
return func(ctx context.Context, t *testing.T) bool {
1531+
select {
1532+
case <-ctx.Done():
1533+
require.FailNow(t, "request did not cancel or complete")
1534+
return false
1535+
case <-completedResponse:
1536+
return false
1537+
case <-cancelledResponse:
1538+
return true
1539+
}
1540+
}
1541+
}
1542+
14871543
func newGsTestData(ctx context.Context, t *testing.T) *gsTestData {
14881544
t.Helper()
14891545
td := &gsTestData{ctx: ctx}

0 commit comments

Comments
 (0)