diff options
Diffstat (limited to 'internal/vfs/zip/archive_test.go')
-rw-r--r-- | internal/vfs/zip/archive_test.go | 137 |
1 files changed, 111 insertions, 26 deletions
diff --git a/internal/vfs/zip/archive_test.go b/internal/vfs/zip/archive_test.go index 2474d419..e1b0d116 100644 --- a/internal/vfs/zip/archive_test.go +++ b/internal/vfs/zip/archive_test.go @@ -72,30 +72,107 @@ func TestOpen(t *testing.T) { func TestOpenCached(t *testing.T) { var requests int64 - zip, cleanup := openZipArchive(t, &requests) + testServerURL, cleanup := newZipFileServerURL(t, "group/zip.gitlab.io/public-without-dirs.zip", &requests) defer cleanup() - t.Run("open file first time", func(t *testing.T) { - requestsStart := requests - f, err := zip.Open(context.Background(), "index.html") - require.NoError(t, err) - defer f.Close() + fs := New() + + // We use array instead of map to ensure + // predictable ordering of test execution + tests := []struct { + name string + vfsPath string + filePath string + expectedArchiveStatus archiveStatus + expectedOpenErr error + expectedReadErr error + expectedRequests int64 + }{ + { + name: "open file first time", + vfsPath: testServerURL + "/public.zip", + filePath: "index.html", + // we expect five requests to: + // read resource and zip metadata + // read file: data offset and content + expectedRequests: 5, + expectedArchiveStatus: archiveOpened, + }, + { + name: "open file second time", + vfsPath: testServerURL + "/public.zip", + filePath: "index.html", + // we expect one request to read file with cached data offset + expectedRequests: 1, + expectedArchiveStatus: archiveOpened, + }, + { + name: "when the URL changes", + vfsPath: testServerURL + "/public.zip?new-secret", + filePath: "index.html", + expectedRequests: 1, + expectedArchiveStatus: archiveOpened, + }, + { + name: "when opening cached file and content changes", + vfsPath: testServerURL + "/public.zip?changed-content=1", + filePath: "index.html", + expectedRequests: 1, + // we receive an error on `read` as `open` offset is already cached + expectedReadErr: httprange.ErrRangeRequestsNotSupported, + expectedArchiveStatus: archiveCorrupted, + }, + { + name: "after content change archive is reloaded", + vfsPath: testServerURL + "/public.zip?new-secret", + filePath: "index.html", + expectedRequests: 5, + expectedArchiveStatus: archiveOpened, + }, + { + name: "when opening non-cached file and content changes", + vfsPath: testServerURL + "/public.zip?changed-content=1", + filePath: "subdir/hello.html", + expectedRequests: 1, + // we receive an error on `read` as `open` offset is already cached + expectedOpenErr: httprange.ErrRangeRequestsNotSupported, + expectedArchiveStatus: archiveCorrupted, + }, + } - _, err = ioutil.ReadAll(f) - require.NoError(t, err) - require.Equal(t, int64(2), atomic.LoadInt64(&requests)-requestsStart, "we expect two requests to read file: data offset and content") - }) + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + start := atomic.LoadInt64(&requests) + zip, err := fs.Root(context.Background(), test.vfsPath) + require.NoError(t, err) - t.Run("open file second time", func(t *testing.T) { - requestsStart := atomic.LoadInt64(&requests) - f, err := zip.Open(context.Background(), "index.html") - require.NoError(t, err) - defer f.Close() + f, err := zip.Open(context.Background(), test.filePath) + if test.expectedOpenErr != nil { + require.Equal(t, test.expectedOpenErr, err) + status, _ := zip.(*zipArchive).openStatus() + require.Equal(t, test.expectedArchiveStatus, status) + return + } - _, err = ioutil.ReadAll(f) - require.NoError(t, err) - require.Equal(t, int64(1), atomic.LoadInt64(&requests)-requestsStart, "we expect one request to read file with cached data offset") - }) + require.NoError(t, err) + defer f.Close() + + _, err = ioutil.ReadAll(f) + if test.expectedReadErr != nil { + require.Equal(t, test.expectedReadErr, err) + status, _ := zip.(*zipArchive).openStatus() + require.Equal(t, test.expectedArchiveStatus, status) + return + } + + require.NoError(t, err) + status, _ := zip.(*zipArchive).openStatus() + require.Equal(t, test.expectedArchiveStatus, status) + + end := atomic.LoadInt64(&requests) + require.Equal(t, test.expectedRequests, end-start) + }) + } } func TestLstat(t *testing.T) { @@ -246,11 +323,11 @@ func TestArchiveCanBeReadAfterOpenCtxCanceled(t *testing.T) { defer cleanup() fs := New().(*zipVFS) - zip := newArchive(fs, testServerURL+"/public.zip", time.Second) + zip := newArchive(fs, time.Second) ctx, cancel := context.WithCancel(context.Background()) cancel() - err := zip.openArchive(ctx) + err := zip.openArchive(ctx, testServerURL+"/public.zip") require.EqualError(t, err, context.Canceled.Error()) <-zip.done @@ -269,9 +346,9 @@ func TestReadArchiveFails(t *testing.T) { defer cleanup() fs := New().(*zipVFS) - zip := newArchive(fs, testServerURL+"/unkown.html", time.Second) + zip := newArchive(fs, time.Second) - err := zip.openArchive(context.Background()) + err := zip.openArchive(context.Background(), testServerURL+"/unkown.html") require.Error(t, err) require.Contains(t, err.Error(), httprange.ErrNotFound.Error()) @@ -289,9 +366,9 @@ func openZipArchive(t *testing.T, requests *int64) (*zipArchive, func()) { testServerURL, cleanup := newZipFileServerURL(t, "group/zip.gitlab.io/public-without-dirs.zip", requests) fs := New().(*zipVFS) - zip := newArchive(fs, testServerURL+"/public.zip", time.Second) + zip := newArchive(fs, time.Second) - err := zip.openArchive(context.Background()) + err := zip.openArchive(context.Background(), testServerURL+"/public.zip") require.NoError(t, err) // public/ public/index.html public/404.html public/symlink.html @@ -312,10 +389,18 @@ func newZipFileServerURL(t *testing.T, zipFilePath string, requests *int64) (str m := http.NewServeMux() m.HandleFunc("/public.zip", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - http.ServeFile(w, r, zipFilePath) if requests != nil { atomic.AddInt64(requests, 1) } + + r.ParseForm() + + if changedContent := r.Form.Get("changed-content"); changedContent != "" { + w.WriteHeader(http.StatusRequestedRangeNotSatisfiable) + return + } + + http.ServeFile(w, r, zipFilePath) })) testServer := httptest.NewServer(m) |