From 1a50e154e6d662936cacd3d226d559256ec486f8 Mon Sep 17 00:00:00 2001 From: "H. Shay" Date: Tue, 6 Aug 2024 14:20:04 -0700 Subject: [PATCH 1/3] add a basic test fetching thumbnail from federation endpoint --- tests/media_thumbnail_test.go | 68 ++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/tests/media_thumbnail_test.go b/tests/media_thumbnail_test.go index 15f103b7..eb7013fd 100644 --- a/tests/media_thumbnail_test.go +++ b/tests/media_thumbnail_test.go @@ -2,19 +2,23 @@ package tests import ( "bytes" + "context" + "github.com/matrix-org/complement" + "github.com/matrix-org/complement/client" + "github.com/matrix-org/complement/federation" + "github.com/matrix-org/complement/helpers" + "github.com/matrix-org/complement/internal/data" "github.com/matrix-org/complement/runtime" + "github.com/matrix-org/gomatrixserverlib/fclient" + "github.com/matrix-org/gomatrixserverlib/spec" "image/jpeg" "image/png" "io" "net/http" "net/url" + "strconv" "strings" "testing" - - "github.com/matrix-org/complement" - "github.com/matrix-org/complement/client" - "github.com/matrix-org/complement/helpers" - "github.com/matrix-org/complement/internal/data" ) // TODO: add JPEG testing @@ -68,6 +72,60 @@ func TestRemotePngThumbnail(t *testing.T) { } } +func TestFederationThumbnail(t *testing.T) { + runtime.SkipIf(t, runtime.Dendrite) + + deployment := complement.Deploy(t, 1) + defer deployment.Destroy(t) + + alice := deployment.Register(t, "hs1", helpers.RegistrationOpts{}) + + srv := federation.NewServer(t, deployment, + federation.HandleKeyRequests(), + ) + cancel := srv.Listen() + defer cancel() + origin := spec.ServerName(srv.ServerName()) + + fileName := "test.png" + contentType := "image/png" + + uri := alice.UploadContent(t, data.LargePng, fileName, contentType) + _, mediaId := client.SplitMxc(uri) + + fedReq := fclient.NewFederationRequest( + "GET", + origin, + "hs1", + "/_matrix/federation/v1/media/thumbnail/"+mediaId+"?method=crop&width=14&height=14&animated=false", + ) + + resp, err := srv.DoFederationRequest(context.Background(), t, deployment, fedReq) + if err != nil { + t.Fatalf("thumbnail request for uploaded file failed: %s", err) + } + if resp.StatusCode != http.StatusOK { + t.Fatalf("thumbnail request for uploaded file failed with status code: %v", resp.StatusCode) + } + + resType := resp.Header.Get("Content-Type") + mimeType := strings.Split(resType, ";")[0] + + if mimeType != "multipart/mixed" { + t.Fatalf("thumbnail request did not return multipart/mixed response, returned %s instead", mimeType) + } + + body, err := io.ReadAll(resp.Body) + length := len(body) + + contentLength, err := strconv.Atoi(resp.Header.Get("Content-Length")) + + if contentLength != length { + t.Fatalf("Content-Length and actual length are different: %d, %d", contentLength, length) + } + +} + func fetchAndValidateThumbnail(t *testing.T, c *client.CSAPI, mxcUri string, authenticated bool) { t.Helper() From c8b0fcfb4dd2e4d980b5467a7f35115a082827bb Mon Sep 17 00:00:00 2001 From: "H. Shay" Date: Mon, 19 Aug 2024 14:01:54 -0700 Subject: [PATCH 2/3] test federation thumbnail body against thumbnail body --- tests/media_thumbnail_test.go | 61 ++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/tests/media_thumbnail_test.go b/tests/media_thumbnail_test.go index eb7013fd..74250a54 100644 --- a/tests/media_thumbnail_test.go +++ b/tests/media_thumbnail_test.go @@ -14,9 +14,10 @@ import ( "image/jpeg" "image/png" "io" + "mime" + "mime/multipart" "net/http" "net/url" - "strconv" "strings" "testing" ) @@ -91,39 +92,67 @@ func TestFederationThumbnail(t *testing.T) { contentType := "image/png" uri := alice.UploadContent(t, data.LargePng, fileName, contentType) - _, mediaId := client.SplitMxc(uri) + mediaOrigin, mediaId := client.SplitMxc(uri) + + path := []string{"_matrix", "media", "v3", "thumbnail", mediaOrigin, mediaId} + res := alice.MustDo(t, "GET", path, client.WithQueries(url.Values{ + "width": []string{"32"}, + "height": []string{"32"}, + "method": []string{"scale"}, + })) + + if res.StatusCode != 200 { + t.Fatalf("thumbnail request for uploaded file failed") + } + + body, err := io.ReadAll(res.Body) + if err != nil { + t.Fatalf("thumbnail request for uploaded file failed: %s", err) + } fedReq := fclient.NewFederationRequest( "GET", origin, "hs1", - "/_matrix/federation/v1/media/thumbnail/"+mediaId+"?method=crop&width=14&height=14&animated=false", + "/_matrix/federation/v1/media/thumbnail/"+mediaId+"?method=scale&width=32&height=32", ) resp, err := srv.DoFederationRequest(context.Background(), t, deployment, fedReq) if err != nil { - t.Fatalf("thumbnail request for uploaded file failed: %s", err) + t.Fatalf("federation thumbnail request for uploaded file failed: %s", err) } if resp.StatusCode != http.StatusOK { - t.Fatalf("thumbnail request for uploaded file failed with status code: %v", resp.StatusCode) + t.Fatalf("federation thumbnail request for uploaded file failed with status code: %v", resp.StatusCode) } - resType := resp.Header.Get("Content-Type") - mimeType := strings.Split(resType, ";")[0] + resContentType := resp.Header.Get("Content-Type") + _, params, err := mime.ParseMediaType(resContentType) - if mimeType != "multipart/mixed" { - t.Fatalf("thumbnail request did not return multipart/mixed response, returned %s instead", mimeType) + if err != nil { + t.Fatalf("failed to parse multipart response: %s", err) } - body, err := io.ReadAll(resp.Body) - length := len(body) - - contentLength, err := strconv.Atoi(resp.Header.Get("Content-Length")) + reader := multipart.NewReader(resp.Body, params["boundary"]) + for { + p, err := reader.NextPart() + if err == io.EOF { // End of the multipart content + break + } + if err != nil { + t.Fatalf("failed to read multipart response: %s", err) + } - if contentLength != length { - t.Fatalf("Content-Length and actual length are different: %d, %d", contentLength, length) + partContentType := p.Header.Get("Content-Type") + if partContentType == contentType { + imageBody, err := io.ReadAll(p) + if err != nil { + t.Fatalf("failed to read multipart part %s: %s", partContentType, err) + } + if !bytes.Equal(imageBody, body) { + t.Fatalf("body does not match uploaded file") + } + } } - } func fetchAndValidateThumbnail(t *testing.T, c *client.CSAPI, mxcUri string, authenticated bool) { From a1d9f3d292bcc2e97c6db81128d745f6734e6781 Mon Sep 17 00:00:00 2001 From: "H. Shay" Date: Thu, 22 Aug 2024 10:11:23 -0700 Subject: [PATCH 3/3] verify we we actually got an image --- tests/media_thumbnail_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/media_thumbnail_test.go b/tests/media_thumbnail_test.go index 74250a54..19a8cb5b 100644 --- a/tests/media_thumbnail_test.go +++ b/tests/media_thumbnail_test.go @@ -132,6 +132,7 @@ func TestFederationThumbnail(t *testing.T) { t.Fatalf("failed to parse multipart response: %s", err) } + foundImage := false reader := multipart.NewReader(resp.Body, params["boundary"]) for { p, err := reader.NextPart() @@ -151,8 +152,12 @@ func TestFederationThumbnail(t *testing.T) { if !bytes.Equal(imageBody, body) { t.Fatalf("body does not match uploaded file") } + foundImage = true } } + if !foundImage { + t.Fatalf("No image was found in response.") + } } func fetchAndValidateThumbnail(t *testing.T, c *client.CSAPI, mxcUri string, authenticated bool) {