get.porter.sh/porter@v1.3.0/pkg/porter/archive_test.go (about) 1 package porter 2 3 import ( 4 "context" 5 "testing" 6 7 "get.porter.sh/porter/pkg" 8 "get.porter.sh/porter/pkg/cnab" 9 "get.porter.sh/porter/tests" 10 "github.com/cnabio/cnab-go/bundle" 11 "github.com/cnabio/cnab-to-oci/relocation" 12 "github.com/cnabio/image-relocation/pkg/image" 13 "github.com/stretchr/testify/require" 14 ) 15 16 func TestArchive_ParentDirDoesNotExist(t *testing.T) { 17 p := NewTestPorter(t) 18 defer p.Close() 19 20 opts := ArchiveOptions{} 21 opts.Reference = "myreg/mybuns:v0.1.0" 22 23 err := opts.Validate(context.Background(), []string{"/path/to/file"}, p.Porter) 24 require.NoError(t, err, "expected no validation error to occur") 25 26 err = p.Archive(context.Background(), opts) 27 require.EqualError(t, err, "parent directory \"/path/to\" does not exist") 28 } 29 30 func TestArchive_Validate(t *testing.T) { 31 p := NewTestPorter(t) 32 defer p.Close() 33 34 testcases := []struct { 35 name string 36 args []string 37 reference string 38 compressionLevel string 39 wantError string 40 }{ 41 {"no arg", nil, "", "", "destination file is required"}, 42 {"no tag", []string{"/path/to/file"}, "", "", "must provide a value for --reference of the form REGISTRY/bundle:tag"}, 43 {"too many args", []string{"/path/to/file", "moar args!"}, "myreg/mybuns:v0.1.0", "", "only one positional argument may be specified, the archive file name, but multiple were received: [/path/to/file moar args!]"}, 44 {"invalid compression level", []string{"/path/to/file"}, "myreg/mybuns:v0.1.0", "NotValidCompression", "invalid compression level: NotValidCompression"}, 45 {"no compression level", []string{"/path/to/file"}, "myreg/mybuns:v0.1.0", "NoCompression", ""}, 46 {"just right", []string{"/path/to/file"}, "myreg/mybuns:v0.1.0", "", ""}, 47 } 48 49 for _, tc := range testcases { 50 t.Run(tc.name, func(t *testing.T) { 51 opts := ArchiveOptions{} 52 opts.Reference = tc.reference 53 opts.CompressionLevel = tc.compressionLevel 54 55 err := opts.Validate(context.Background(), tc.args, p.Porter) 56 if tc.wantError != "" { 57 require.EqualError(t, err, tc.wantError) 58 } else { 59 require.NoError(t, err, "expected no validation error to occur") 60 } 61 }) 62 } 63 } 64 65 func TestArchive_ArchiveDirectory(t *testing.T) { 66 p := NewTestPorter(t) 67 defer p.Close() 68 ex := exporter{ 69 fs: p.FileSystem, 70 } 71 72 dir, err := ex.createArchiveFolder("examples/test-bundle-0.2.0") 73 require.NoError(t, err) 74 require.Contains(t, dir, "examples-test-bundle-0.2.0") 75 76 tests.AssertDirectoryPermissionsEqual(t, dir, pkg.FileModeDirectory) 77 } 78 79 func TestArchive_AddImage(t *testing.T) { 80 p := NewTestPorter(t) 81 defer p.Close() 82 83 testcases := []struct { 84 name string 85 relocationMap relocation.ImageRelocationMap 86 inputImg string 87 expectedImg string 88 hasErr bool 89 expectedErrMsg string 90 }{ 91 {"no relocation map set", nil, "image:v0.1.0", "", true, "relocation map is not provided"}, 92 {"image not found in relocation map", relocation.ImageRelocationMap{"image:v0.1.0": "image@sha256:123"}, "not-found-image:v0.2.0", "", true, "can not locate the referenced image"}, 93 {"image successfully added", relocation.ImageRelocationMap{"image:v0.1.0": "image@sha256:123"}, "image:v0.1.0", "image@sha256:123", false, ""}, 94 } 95 96 for _, tc := range testcases { 97 tc := tc 98 t.Run(tc.name, func(t *testing.T) { 99 baseImage := bundle.BaseImage{Image: tc.inputImg, Digest: "digest"} 100 ex := exporter{relocationMap: tc.relocationMap, imageStore: mockImageStore{t: t, expected: tc.expectedImg}} 101 err := ex.addImage(baseImage) 102 if tc.hasErr { 103 tests.RequireErrorContains(t, err, tc.expectedErrMsg) 104 } else { 105 require.NoError(t, err) 106 } 107 }) 108 } 109 110 } 111 112 func TestArchive_PrepareArtifacts_Sorting(t *testing.T) { 113 p := NewTestPorter(t) 114 defer p.Close() 115 116 testcases := []struct { 117 name string 118 relocationMap relocation.ImageRelocationMap 119 inputImgs []string 120 expectedImgs []string 121 }{ 122 {"images sorted", relocation.ImageRelocationMap{"c:v0.1.0": "c@sha256:789", "a:v0.1.0": "a@sha256:123", "b:v0.1.0": "b@sha256:456"}, 123 []string{"b:v0.1.0", "c:v0.1.0", "a:v0.1.0"}, 124 []string{"a@sha256:123", "b@sha256:456", "c@sha256:789"}}, 125 {"numbers too", relocation.ImageRelocationMap{"a:v0.1.0": "a@sha256:123", "0b:v0.1.0": "0b@sha256:456"}, 126 []string{"0b:v0.1.0", "a:v0.1.0"}, 127 []string{"0b@sha256:456", "a@sha256:123"}}, 128 } 129 130 for _, tc := range testcases { 131 tc := tc 132 t.Run(tc.name, func(t *testing.T) { 133 images := make(map[string]bundle.Image) 134 b := cnab.NewBundle(bundle.Bundle{Images: images}) 135 for _, inputImg := range tc.inputImgs { 136 images[inputImg] = bundle.Image{BaseImage: bundle.BaseImage{Image: inputImg, Digest: "digest"}} 137 } 138 collectedImages := make([]string, 0) 139 imageStore := mockCollectingImageStore{t: t, addedImages: &collectedImages} 140 ex := exporter{relocationMap: tc.relocationMap, imageStore: imageStore} 141 142 err := ex.prepareArtifacts(b) 143 144 require.Equal(t, tc.expectedImgs, collectedImages) 145 require.NoError(t, err) 146 }) 147 } 148 149 } 150 151 type mockCollectingImageStore struct { 152 t *testing.T 153 addedImages *[]string 154 } 155 156 func (m mockCollectingImageStore) Add(img string) (contentDigest string, err error) { 157 *m.addedImages = append(*m.addedImages, img) 158 return "digest", nil 159 } 160 161 func (m mockCollectingImageStore) Push(dig image.Digest, src image.Name, dst image.Name) error { 162 return nil 163 } 164 165 type mockImageStore struct { 166 t *testing.T 167 expected string 168 } 169 170 func (m mockImageStore) Add(img string) (contentDigest string, err error) { 171 require.Equal(m.t, m.expected, img) 172 return "digest", nil 173 } 174 175 func (m mockImageStore) Push(dig image.Digest, src image.Name, dst image.Name) error { 176 return nil 177 }