Path: blob/main/components/content-service/pkg/layer/provider_test.go
2500 views
// Copyright (c) 2020 Gitpod GmbH. All rights reserved.1// Licensed under the GNU Affero General Public License (AGPL).2// See License.AGPL.txt in the project root for license information.34package layer56import (7"bytes"8"context"9"encoding/json"10"errors"11"flag"12"fmt"13"io"14"io/fs"15"net/http"16"os"17"strings"18"testing"1920"github.com/google/go-cmp/cmp"21"github.com/opencontainers/go-digest"2223csapi "github.com/gitpod-io/gitpod/content-service/api"24"github.com/gitpod-io/gitpod/content-service/pkg/storage"25)2627const (28ownerID = "workspace-owner"29workspaceID = "workspace-id"30)3132var (33update = flag.Bool("update", false, "update .golden files")34force = flag.Bool("force", false, "overwrite .golden files even if they already exist")35)3637func TestGetContentLayer(t *testing.T) {38tests := []struct {39Name string40ContentManifestType string41ContentManifest *csapi.WorkspaceContentManifest42Backup *storage.DownloadInfo43Initializer *csapi.WorkspaceInitializer44}{45{46Name: "git initializer",47Initializer: &csapi.WorkspaceInitializer{48Spec: &csapi.WorkspaceInitializer_Git{49Git: &csapi.GitInitializer{50CheckoutLocation: "/foo",51CloneTaget: "head",52Config: &csapi.GitConfig{53Authentication: csapi.GitAuthMethod_NO_AUTH,54},55RemoteUri: "somewhere-else",56TargetMode: csapi.CloneTargetMode_LOCAL_BRANCH,57},58},59},60},61{62Name: "legacy backup",63Backup: &storage.DownloadInfo{64URL: "https://somewhere-else.com/backup.tar",65},66},67}6869for _, test := range tests {70t.Run(test.Name, func(t *testing.T) {71var (72mf []byte73err error74objs = make(map[string]*storage.DownloadInfo)75)76if test.ContentManifest != nil {77mf, err = json.Marshal(test.ContentManifest)78if err != nil {79t.Fatal(err)80return81}8283objs[fmt.Sprintf(fmtWorkspaceManifest, workspaceID)] = &storage.DownloadInfo{84Meta: storage.ObjectMeta{85ContentType: test.ContentManifestType,86Digest: digest.FromBytes(mf).String(),87},88Size: int64(len(mf)),89URL: "http://content-manifest",90}9192for _, l := range test.ContentManifest.Layers {93objs[l.Object] = &storage.DownloadInfo{94Meta: storage.ObjectMeta{95Digest: l.Digest.String(),96},97URL: fmt.Sprintf("http://some-storage-system/%s/%s", l.Bucket, l.Object),98}99}100}101if test.Backup != nil {102objs[fmt.Sprintf(fmtLegacyBackupName, workspaceID)] = test.Backup103}104105s := &testStorage{Objs: objs}106p := &Provider{107Storage: s,108Client: &http.Client{109Transport: roundTripFunc(func(req *http.Request) *http.Response {110switch req.URL.String() {111case "http://content-manifest":112return &http.Response{113StatusCode: http.StatusOK,114Header: make(http.Header),115Body: io.NopCloser(bytes.NewReader(mf)),116}117default:118return &http.Response{119StatusCode: http.StatusNotFound,120Header: make(http.Header),121}122}123}),124},125}126l, m, rerr := p.GetContentLayer(context.Background(), ownerID, workspaceID, test.Initializer)127128type fixture struct {129Layer []Layer `json:"layer,omitempty"`130Manifest *csapi.WorkspaceContentManifest `json:"contentManifest,omitempty"`131Error string `json:"error,omitempty"`132}133134var got fixture135if rerr != nil {136got.Error = rerr.Error()137}138got.Layer = l139got.Manifest = m140141var (142want fixture143fixfn = fmt.Sprintf("fixtures/%s.json", strings.ToLower(strings.ReplaceAll(test.Name, " ", "_")))144)145if *update {146want = got147fixc, err := json.MarshalIndent(want, "", " ")148if err != nil {149t.Fatalf("cannot marshal fixture: %q", err)150return151}152153if _, err := os.Stat(fixfn); err == nil && !*force {154t.Fatalf("fixture %s exists already - not overwriting", fixfn)155}156157err = os.WriteFile(fixfn, fixc, 0600)158if err != nil {159t.Fatalf("cannot write fixture: %q", err)160return161}162} else {163fixc, err := os.ReadFile(fixfn)164if errors.Is(err, fs.ErrNotExist) && !*update {165t.Fatalf("no fixture %s. Run test with -update", fixfn)166return167}168if err != nil {169t.Fatalf("cannot load fixture: %q", err)170}171172err = json.Unmarshal(fixc, &want)173if err != nil {174t.Fatalf("cannot unmarshal fixture: %q", err)175return176}177}178179if diff := cmp.Diff(want, got); diff != "" {180t.Errorf("Fixture mismatch (-want +got):\n%s", diff)181}182})183}184}185186type testStorage struct {187Objs map[string]*storage.DownloadInfo188}189190// Bucket provides the bucket name for a particular user191func (*testStorage) Bucket(userID string) string {192return "bucket-" + userID193}194195func (*testStorage) BlobObject(userID, name string) (string, error) {196return "blobs/" + name, nil197}198199func (s *testStorage) EnsureExists(ctx context.Context, bucket string) (err error) {200return nil201}202203func (s *testStorage) DiskUsage(ctx context.Context, bucket string, prefix string) (size int64, err error) {204return 0, nil205}206207func (s *testStorage) SignDownload(ctx context.Context, bucket, obj string, options *storage.SignedURLOptions) (info *storage.DownloadInfo, err error) {208info, ok := s.Objs[obj]209if !ok || info == nil {210return nil, storage.ErrNotFound211}212return info, nil213}214215func (s *testStorage) SignUpload(ctx context.Context, bucket, obj string, options *storage.SignedURLOptions) (info *storage.UploadInfo, err error) {216return nil, nil217}218219func (s *testStorage) DeleteObject(ctx context.Context, bucket string, query *storage.DeleteObjectQuery) error {220return nil221}222223func (s *testStorage) DeleteBucket(ctx context.Context, userID, bucket string) error {224return nil225}226227func (*testStorage) BackupObject(ownerID string, workspaceID string, name string) string {228return ""229}230231func (*testStorage) InstanceObject(ownerID string, workspaceID string, instanceID string, name string) string {232return ""233}234235func (*testStorage) ObjectHash(ctx context.Context, bucket string, obj string) (string, error) {236return "", nil237}238239func (*testStorage) ObjectExists(ctx context.Context, bucket string, path string) (bool, error) {240return false, nil241}242243type roundTripFunc func(req *http.Request) *http.Response244245// RoundTrip .246func (f roundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) {247return f(req), nil248}249250251