|
|
@@ -1014,6 +1014,49 @@ func TestDeleteBehindSymlink(t *testing.T) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// Reproduces https://github.com/syncthing/syncthing/issues/6559
|
|
|
+func TestPullCtxCancel(t *testing.T) {
|
|
|
+ m, f := setupSendReceiveFolder()
|
|
|
+ defer cleanupSRFolder(f, m)
|
|
|
+
|
|
|
+ pullChan := make(chan pullBlockState)
|
|
|
+ finisherChan := make(chan *sharedPullerState)
|
|
|
+
|
|
|
+ var cancel context.CancelFunc
|
|
|
+ f.ctx, cancel = context.WithCancel(context.Background())
|
|
|
+
|
|
|
+ go f.pullerRoutine(pullChan, finisherChan)
|
|
|
+ defer close(pullChan)
|
|
|
+
|
|
|
+ emptyState := func() pullBlockState {
|
|
|
+ return pullBlockState{
|
|
|
+ sharedPullerState: newSharedPullerState(protocol.FileInfo{}, nil, f.folderID, "", nil, nil, false, false, protocol.FileInfo{}, false),
|
|
|
+ block: protocol.BlockInfo{},
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ cancel()
|
|
|
+
|
|
|
+ done := make(chan struct{})
|
|
|
+ defer close(done)
|
|
|
+ for i := 0; i < 2; i++ {
|
|
|
+ go func() {
|
|
|
+ select {
|
|
|
+ case pullChan <- emptyState():
|
|
|
+ case <-done:
|
|
|
+ }
|
|
|
+ }()
|
|
|
+ select {
|
|
|
+ case s := <-finisherChan:
|
|
|
+ if s.failed() == nil {
|
|
|
+ t.Errorf("state %v not failed", i)
|
|
|
+ }
|
|
|
+ case <-time.After(5 * time.Second):
|
|
|
+ t.Fatalf("timed out before receiving state %v on finisherChan", i)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
func cleanupSharedPullerState(s *sharedPullerState) {
|
|
|
s.mut.Lock()
|
|
|
defer s.mut.Unlock()
|