diff options
Diffstat (limited to 'internal/git/gitpipe/catfile_object_test.go')
-rw-r--r-- | internal/git/gitpipe/catfile_object_test.go | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/internal/git/gitpipe/catfile_object_test.go b/internal/git/gitpipe/catfile_object_test.go index 5e40cf444..17ccfe017 100644 --- a/internal/git/gitpipe/catfile_object_test.go +++ b/internal/git/gitpipe/catfile_object_test.go @@ -13,6 +13,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v15/internal/git/localrepo" "gitlab.com/gitlab-org/gitaly/v15/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v15/internal/testhelper/testcfg" + "google.golang.org/grpc/metadata" ) func TestCatfileObject(t *testing.T) { @@ -149,4 +150,50 @@ func TestCatfileObject(t *testing.T) { err: context.Canceled, }, it.Result()) }) + + t.Run("context cancellation with cached process", func(t *testing.T) { + ctx, cancel := context.WithCancel(testhelper.Context(t)) + ctx = testhelper.MergeIncomingMetadata(ctx, metadata.Pairs( + catfile.SessionIDField, "1", + )) + + catfileCache := catfile.NewCache(cfg) + defer catfileCache.Stop() + + objectReader, objectReaderCancel, err := catfileCache.ObjectReader(ctx, repo) + require.NoError(t, err) + defer objectReaderCancel() + + inputIter, inputCh, nextCh := newChanObjectIterator() + + it, err := CatfileObject(ctx, objectReader, inputIter) + require.NoError(t, err) + + // We request a single object from the catfile process. Because the request queue is + // not flushed after every object this means that the request is currently + // outstanding. + <-nextCh + inputCh <- git.ObjectID(lfsPointer1) + + // Wait for the pipeline to request the next object. + <-nextCh + + // We now cancel the context with the outstanding request. In the past, this used to + // block the downstream consumer of the object data. This is because of two reasons: + // + // - When the process is being cached then cancellation of the context doesn't cause + // the process to get killed. So consequentially, the process would sit around + // waiting for input. + // - We didn't flush the queue when the context was cancelled, so the buffered input + // never arrived at the process. + cancel() + + // Now we queue another request that should cause the pipeline to fail. + inputCh <- git.ObjectID(lfsPointer1) + + // Reading the object should now fail because the context got cancelled, but it + // definitely shouldn't block like it did earlier. + require.False(t, it.Next()) + require.Equal(t, context.Canceled, it.Err()) + }) } |