Repository: apigee/registry
Pull request #457 (2022-02-01 18:12:48)

Add tests and decompression support for GetArtifactContents 
I noticed we didn't have tests for this RPC method, so I copied the cases from `TestGetApiSpecContents` and adjusted them for the artifact resource type. One of the cases failed, which led me to find that `GetArtifactContents` wasn't decompressing gzipped artifact contents as it [claims to support](https://github.com/apigee/registry/blob/61c5bc7df3a3ddbdb9587ae184b5d26a2931b39e/google/cloud/apigeeregistry/v1/registry_service.proto#L328). This PR adds that functionality and some tests for the method.


Patch:
diff --git a/server/registry/actions_artifacts.go b/server/registry/actions_artifacts.go
index b3c9023..1ab7ef1 100644
--- a/server/registry/actions_artifacts.go
+++ b/server/registry/actions_artifacts.go
@@ -17,6 +17,7 @@ package registry
 import (
 	"context"
 	"fmt"
+	"strings"
 
 	"github.com/apigee/registry/rpc"
 	"github.com/apigee/registry/server/registry/internal/storage"
@@ -186,6 +187,14 @@ func (s *RegistryServer) GetArtifactContents(ctx context.Context, req *rpc.GetAr
 		return nil, err
 	}
 
+	if strings.Contains(artifact.MimeType, "+gzip") {
+		artifact.MimeType = strings.ReplaceAll(artifact.MimeType, "+gzip", "")
+		blob.Contents, err = models.GUnzippedBytes(blob.Contents)
+		if err != nil {
+			return nil, status.Errorf(codes.FailedPrecondition, "failed to unzip contents with gzip MIME type: %s", err)
+		}
+	}
+
 	return &httpbody.HttpBody{
 		ContentType: artifact.MimeType,
 		Data:        blob.Contents,


Test patch:
diff --git a/server/registry/actions_artifacts_test.go b/server/registry/actions_artifacts_test.go
index 69c3527..86d942f 100644
--- a/server/registry/actions_artifacts_test.go
+++ b/server/registry/actions_artifacts_test.go
@@ -480,6 +480,69 @@ func TestGetArtifactResponseCodes(t *testing.T) {
 	}
 }
 
+func TestGetArtifactContents(t *testing.T) {
+	tests := []struct {
+		desc string
+		seed *rpc.Artifact
+		req  *rpc.GetArtifactContentsRequest
+		want codes.Code
+	}{
+		{
+			desc: "resource not found",
+			seed: &rpc.Artifact{Name: "projects/my-project/locations/global/artifacts/my-artifact"},
+			req: &rpc.GetArtifactContentsRequest{
+				Name: "projects/my-project/locations/global/artifacts/doesnt-exist",
+			},
+			want: codes.NotFound,
+		},
+		{
+			desc: "case insensitive identifiers",
+			seed: &rpc.Artifact{Name: "projects/my-project/locations/global/artifacts/my-artifact"},
+			req: &rpc.GetArtifactContentsRequest{
+				Name: "projects/My-Project/locations/global/artifacts/My-Artifact",
+			},
+			want: codes.OK,
+		},
+		{
+			desc: "inappropriate contents suffix in resource name",
+			seed: &rpc.Artifact{
+				Name:     "projects/my-project/locations/global/artifacts/my-artifact",
+				Contents: []byte{},
+			},
+			req: &rpc.GetArtifactContentsRequest{
+				Name: "projects/my-project/locations/global/artifacts/my-artifact/contents",
+			},
+			want: codes.InvalidArgument,
+		},
+		{
+			desc: "gzip mimetype with empty contents",
+			seed: &rpc.Artifact{
+				Name:     "projects/my-project/locations/global/artifacts/my-artifact",
+				MimeType: "application/x.openapi+gzip;version=3.0.0",
+				Contents: []byte{},
+			},
+			req: &rpc.GetArtifactContentsRequest{
+				Name: "projects/my-project/locations/global/artifacts/my-artifact",
+			},
+			want: codes.FailedPrecondition,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			ctx := context.Background()
+			server := defaultTestServer(t)
+			if err := seeder.SeedArtifacts(ctx, server, test.seed); err != nil {
+				t.Fatalf("Setup/Seeding: Failed to seed registry: %s", err)
+			}
+
+			if _, err := server.GetArtifactContents(ctx, test.req); status.Code(err) != test.want {
+				t.Errorf("GetArtifactContents(%+v) returned status code %q, want %q: %v", test.req, status.Code(err), test.want, err)
+			}
+		})
+	}
+}
+
 func TestListArtifacts(t *testing.T) {
 	tests := []struct {
 		desc      string