From a9794ec7ccc2804361d69bab53d85cfec9f2838c Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Fri, 9 Jun 2023 11:35:08 +0200 Subject: [PATCH] feat: add a bunch of tests --- gateway/gateway_test.go | 183 ++++++++++++++++++++++++++--- gateway/handler_codec_test.go | 2 +- gateway/handler_unixfs_dir_test.go | 2 +- gateway/testdata/fixtures.car | Bin 2647 -> 2950 bytes 4 files changed, 168 insertions(+), 19 deletions(-) diff --git a/gateway/gateway_test.go b/gateway/gateway_test.go index 7f4e31ee5..02230fc99 100644 --- a/gateway/gateway_test.go +++ b/gateway/gateway_test.go @@ -26,7 +26,7 @@ func TestGatewayGet(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - k, err := backend.resolvePathNoRootsReturned(ctx, ipath.Join(ipath.IpfsPath(root), t.Name(), "fnord")) + k, err := backend.resolvePathNoRootsReturned(ctx, ipath.Join(ipath.IpfsPath(root), "subdir", "fnord")) require.NoError(t, err) backend.namesys["/ipns/example.com"] = path.FromCid(k.Cid()) @@ -92,7 +92,7 @@ func TestPretty404(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - k, err := backend.resolvePathNoRootsReturned(ctx, ipath.Join(ipath.IpfsPath(root), t.Name())) + k, err := backend.resolvePathNoRootsReturned(ctx, ipath.Join(ipath.IpfsPath(root), "subdir-404")) assert.NoError(t, err) host := "example.net" @@ -131,19 +131,171 @@ func TestPretty404(t *testing.T) { } } -func TestCacheControlImmutable(t *testing.T) { +func TestHeaders(t *testing.T) { + t.Parallel() + ts, _, root := newTestServerAndNode(t, nil) - req := mustNewRequest(t, http.MethodGet, ts.URL+"/ipfs/"+root.String()+"/", nil) - res := mustDoWithoutRedirect(t, req) + var ( + dirCID = "bafybeihta5xfgxcmyxyq6druvidc7es6ogffdd6zel22l3y4wddju5xxsu" + dirPath = "/ipfs/" + root.String() + "/subdir/" + dirRoots = "bafybeifhvgr4ufgwpoj2iyrymrigjhpexvsyfm2elafebkmrei4skunihe," + dirCID + + fileCID = "bafkreiba3vpkcqpc6xtp3hsatzcod6iwneouzjoq7ymy4m2js6gc3czt6i" + filePath = "/ipfs/" + root.String() + "/subdir/fnord" + fileRoots = dirRoots + "," + fileCID - // check the immutable tag isn't set - hdrs, ok := res.Header["Cache-Control"] - if ok { - for _, hdr := range hdrs { - assert.NotContains(t, hdr, "immutable", "unexpected Cache-Control: immutable on directory listing") + dagCborCID = "bafyreiaocls5bt2ha5vszv5pwz34zzcdf3axk3uqa56bgsgvlkbezw67hq" + dagCborPath = "/ipfs/" + root.String() + "/subdir/dag-cbor-document" + dagCborRoots = dirRoots + "," + dagCborCID + ) + + t.Run("Control-Cache-Immutable is not immutable for directories", func(t *testing.T) { + req := mustNewRequest(t, http.MethodGet, ts.URL+"/ipfs/"+root.String()+"/", nil) + res := mustDoWithoutRedirect(t, req) + + // check the immutable tag isn't set + hdrs, ok := res.Header["Cache-Control"] + if ok { + for _, hdr := range hdrs { + assert.NotContains(t, hdr, "immutable", "unexpected Cache-Control: immutable on directory listing") + } } - } + }) + + t.Run("ETag contains expected values", func(t *testing.T) { + test := func(responseFormat string, path string, format string, args ...any) { + t.Run(responseFormat, func(t *testing.T) { + url := ts.URL + path + req := mustNewRequest(t, http.MethodGet, url, nil) + req.Header.Add("Accept", responseFormat) + res := mustDoWithoutRedirect(t, req) + require.Equal(t, http.StatusOK, res.StatusCode) + require.Regexp(t, `^`+fmt.Sprintf(format, args...)+`$`, res.Header.Get("Etag")) + }) + } + test("", dirPath, `"DirIndex-(.*)_CID-%s"`, dirCID) + test("text/html", dirPath, `"DirIndex-(.*)_CID-%s"`, dirCID) + test(carResponseFormat, dirPath, `W/"%s.car.5ovg7dign8ug"`, root.String()) // ETags of CARs on a Path have the root CID in the Etag and hashed information to derive the correct Etag of the full request. + test(rawResponseFormat, dirPath, `"%s.raw"`, dirCID) + test(tarResponseFormat, dirPath, `W/"%s.x-tar"`, dirCID) + + test("", filePath, `"%s"`, fileCID) + test("text/html", filePath, `"%s"`, fileCID) + test(carResponseFormat, filePath, `W/"%s.car.fivdlu5uk7ab6"`, root.String()) + test(rawResponseFormat, filePath, `"%s.raw"`, fileCID) + test(tarResponseFormat, filePath, `W/"%s.x-tar"`, fileCID) + + test("", dagCborPath, `"%s.dag-cbor"`, dagCborCID) + test("text/html", dagCborPath+"/", `"DagIndex-(.*)_CID-%s"`, dagCborCID) + test(carResponseFormat, dagCborPath, `W/"%s.car.5b4vl0vt6odpt"`, root.String()) + test(rawResponseFormat, dagCborPath, `"%s.raw"`, dagCborCID) + test(dagJsonResponseFormat, dagCborPath, `"%s.dag-json"`, dagCborCID) + test(dagCborResponseFormat, dagCborPath, `"%s.dag-cbor"`, dagCborCID) + }) + + t.Run("If-None-Match with previous Etag returns Not Modified", func(t *testing.T) { + test := func(responseFormat string, path string) { + t.Run(responseFormat, func(t *testing.T) { + url := ts.URL + path + req := mustNewRequest(t, http.MethodGet, url, nil) + req.Header.Add("Accept", responseFormat) + res := mustDoWithoutRedirect(t, req) + require.Equal(t, http.StatusOK, res.StatusCode) + etag := res.Header.Get("Etag") + require.NotEmpty(t, etag) + req = mustNewRequest(t, http.MethodGet, url, nil) + req.Header.Add("Accept", responseFormat) + req.Header.Add("If-None-Match", etag) + res = mustDoWithoutRedirect(t, req) + require.Equal(t, http.StatusNotModified, res.StatusCode) + }) + } + + test("", dirPath) + test("text/html", dirPath) + test(carResponseFormat, dirPath) + test(rawResponseFormat, dirPath) + test(tarResponseFormat, dirPath) + + test("", filePath) + test("text/html", filePath) + test(carResponseFormat, filePath) + test(rawResponseFormat, filePath) + test(tarResponseFormat, filePath) + + test("", dagCborPath) + test("text/html", dagCborPath+"/") + test(carResponseFormat, dagCborPath) + test(rawResponseFormat, dagCborPath) + test(dagJsonResponseFormat, dagCborPath) + test(dagCborResponseFormat, dagCborPath) + }) + + t.Run("X-Ipfs-Roots contains expected values", func(t *testing.T) { + test := func(responseFormat string, path string, roots string) { + t.Run(responseFormat, func(t *testing.T) { + url := ts.URL + path + req := mustNewRequest(t, http.MethodGet, url, nil) + req.Header.Add("Accept", responseFormat) + res := mustDoWithoutRedirect(t, req) + require.Equal(t, http.StatusOK, res.StatusCode) + require.Equal(t, roots, res.Header.Get("X-Ipfs-Roots")) + }) + } + + test("", dirPath, dirRoots) + test("text/html", dirPath, dirRoots) + test(carResponseFormat, dirPath, dirRoots) + test(rawResponseFormat, dirPath, dirRoots) + test(tarResponseFormat, dirPath, dirRoots) + + test("", filePath, fileRoots) + test("text/html", filePath, fileRoots) + test(carResponseFormat, filePath, fileRoots) + test(rawResponseFormat, filePath, fileRoots) + test(tarResponseFormat, filePath, fileRoots) + + test("", dagCborPath, dagCborRoots) + test("text/html", dagCborPath+"/", dagCborRoots) + test(carResponseFormat, dagCborPath, dagCborRoots) + test(rawResponseFormat, dagCborPath, dagCborRoots) + test(dagJsonResponseFormat, dagCborPath, dagCborRoots) + test(dagCborResponseFormat, dagCborPath, dagCborRoots) + }) + + t.Run("If-None-Match with wrong value forces path resolution, but X-Ipfs-Roots is correct (regression)", func(t *testing.T) { + test := func(responseFormat string, path string, roots string) { + t.Run(responseFormat, func(t *testing.T) { + url := ts.URL + path + req := mustNewRequest(t, http.MethodGet, url, nil) + req.Header.Add("Accept", responseFormat) + req.Header.Add("If-None-Match", "just-some-gibberish") + res := mustDoWithoutRedirect(t, req) + require.Equal(t, http.StatusOK, res.StatusCode) + require.Equal(t, roots, res.Header.Get("X-Ipfs-Roots")) + }) + } + + test("", dirPath, dirRoots) + test("text/html", dirPath, dirRoots) + test(carResponseFormat, dirPath, dirRoots) + test(rawResponseFormat, dirPath, dirRoots) + test(tarResponseFormat, dirPath, dirRoots) + + test("", filePath, fileRoots) + test("text/html", filePath, fileRoots) + test(carResponseFormat, filePath, fileRoots) + test(rawResponseFormat, filePath, fileRoots) + test(tarResponseFormat, filePath, fileRoots) + + test("", dagCborPath, dagCborRoots) + test("text/html", dagCborPath+"/", dagCborRoots) + test(carResponseFormat, dagCborPath, dagCborRoots) + test(rawResponseFormat, dagCborPath, dagCborRoots) + test(dagJsonResponseFormat, dagCborPath, dagCborRoots) + test(dagCborResponseFormat, dagCborPath, dagCborRoots) + }) } func TestGoGetSupport(t *testing.T) { @@ -157,7 +309,6 @@ func TestGoGetSupport(t *testing.T) { func TestRedirects(t *testing.T) { t.Parallel() - // Move here? t.Run("IPNS Base58 Multihash Redirect", func(t *testing.T) { ts, _, _ := newTestServerAndNode(t, nil) @@ -282,7 +433,6 @@ func TestDeserializedResponses(t *testing.T) { }, }, }) - t.Logf("test server url: %s", ts.URL) trustedFormats := []string{"", "dag-json", "dag-cbor", "tar", "json", "cbor"} trustlessFormats := []string{"raw", "car"} @@ -305,7 +455,7 @@ func TestDeserializedResponses(t *testing.T) { doIpfsCidPathRequests := func(t *testing.T, formats []string, host string, expectedStatus int) { for _, format := range formats { - doRequest(t, "/ipfs/"+root.String()+"/EmptyDir/?format="+format, host, expectedStatus) + doRequest(t, "/ipfs/"+root.String()+"/empty-dir/?format="+format, host, expectedStatus) } } @@ -363,7 +513,6 @@ func TestDeserializedResponses(t *testing.T) { }, }, }) - t.Logf("test server url: %s", ts.URL) doRequest := func(t *testing.T, path, host string, expectedStatus int) { req := mustNewRequest(t, http.MethodGet, ts.URL+path, nil) @@ -378,11 +527,11 @@ func TestDeserializedResponses(t *testing.T) { // DNSLink only. Not supported for trustless. Supported for trusted, except // format=ipns-record which is unavailable for DNSLink. doRequest(t, "/", "trustless.com", http.StatusNotAcceptable) - doRequest(t, "/EmptyDir/", "trustless.com", http.StatusNotAcceptable) + doRequest(t, "/empty-dir/", "trustless.com", http.StatusNotAcceptable) doRequest(t, "/?format=ipns-record", "trustless.com", http.StatusNotAcceptable) doRequest(t, "/", "trusted.com", http.StatusOK) - doRequest(t, "/EmptyDir/", "trusted.com", http.StatusOK) + doRequest(t, "/empty-dir/", "trusted.com", http.StatusOK) doRequest(t, "/?format=ipns-record", "trusted.com", http.StatusBadRequest) }) } diff --git a/gateway/handler_codec_test.go b/gateway/handler_codec_test.go index 993f6f4a1..f850e9a0d 100644 --- a/gateway/handler_codec_test.go +++ b/gateway/handler_codec_test.go @@ -31,7 +31,7 @@ func TestDagJsonCborPreview(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - resolvedPath, err := backend.resolvePathNoRootsReturned(ctx, ipath.Join(ipath.IpfsPath(root), t.Name(), "example")) + resolvedPath, err := backend.resolvePathNoRootsReturned(ctx, ipath.Join(ipath.IpfsPath(root), "subdir", "dag-cbor-document")) require.NoError(t, err) cidStr := resolvedPath.Cid().String() diff --git a/gateway/handler_unixfs_dir_test.go b/gateway/handler_unixfs_dir_test.go index 2cf111e87..5b60f8b5f 100644 --- a/gateway/handler_unixfs_dir_test.go +++ b/gateway/handler_unixfs_dir_test.go @@ -18,7 +18,7 @@ func TestIPNSHostnameBacklinks(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - k, err := backend.resolvePathNoRootsReturned(ctx, ipath.Join(ipath.IpfsPath(root), t.Name())) + k, err := backend.resolvePathNoRootsReturned(ctx, ipath.Join(ipath.IpfsPath(root), "subdir-special-chars")) require.NoError(t, err) // create /ipns/example.net/foo/ diff --git a/gateway/testdata/fixtures.car b/gateway/testdata/fixtures.car index cea5d462d10299b8043adaa0beecac3f22ddd152..9a991c2f30e0c0b4fd505e951671aeec71960529 100644 GIT binary patch delta 749 zcmcaE(k7m0wJ5bHKfk27@rG7}Dg$GIkiznni%*GMtDd|h$s#2nW$u%`sZE<*BDfq@ zPE@i~4P0TFUY1%^oSC1;*uYGT^2rg5Zp_A9DwFRps?-Z{rsfuuRO+T=7D=!O8FHzB zOnAWmKXJo3x&7v`i#ivjxxUx2wEMb*k+Es+*NsbV@#k+9V#`Y{E=f(1c*F?P@|is^ zIL7DbM}9t&Rc!i`;tIP0`)?|JUHV>T!?9Uq-=_+(6_+M~ESbP2WD2oGsKv8q@=8Wo z0WOG?u8Dz(#8E~e`^h4V>T)7b!Qz6{ zzRjptPtdtW5DOnYK6B{NikTCV56ylUQIHeAvD)Kz`@yyKJ1c$C{z-4K6=H|jSuC-N z5oApmC@ctS(y51-zVTgTy`-{zOUjJJOBUVEk<|R$;sC%sVI@)25Fxhz-pi|oe^XR!T7Y9tj(k@DVUO& zuA7{cU!dRb~wab|uV<2+_!lnWV6T%lgi;hI}eQt6UeB*7x&$fW|(sB@y^+>*pI zt$kB|@Gq3)HCcU0M~_Ww!pWsGKVH&(t-v897LrjGerjvy^w3sF`POf28-Mo+U1mottj9iSHZ8@SC0W>VK AzW@LL