github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/pkg/oci/artifact_test.go (about) 1 package oci_test 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "path/filepath" 8 "testing" 9 10 v1 "github.com/google/go-containerregistry/pkg/v1" 11 fakei "github.com/google/go-containerregistry/pkg/v1/fake" 12 "github.com/google/go-containerregistry/pkg/v1/tarball" 13 "github.com/google/go-containerregistry/pkg/v1/types" 14 "github.com/stretchr/testify/assert" 15 "github.com/stretchr/testify/require" 16 17 ftypes "github.com/devseccon/trivy/pkg/fanal/types" 18 "github.com/devseccon/trivy/pkg/oci" 19 "github.com/devseccon/trivy/pkg/utils/fsutils" 20 ) 21 22 type fakeLayer struct { 23 v1.Layer 24 } 25 26 func (f fakeLayer) MediaType() (types.MediaType, error) { 27 return "application/vnd.cncf.openpolicyagent.layer.v1.tar+gzip", nil 28 } 29 30 func TestArtifact_Download(t *testing.T) { 31 layer, err := tarball.LayerFromFile("testdata/test.tar.gz") 32 require.NoError(t, err) 33 34 txtLayer, err := tarball.LayerFromFile("testdata/test.txt") 35 require.NoError(t, err) 36 37 flayer := fakeLayer{layer} 38 39 type layersReturns struct { 40 layers []v1.Layer 41 err error 42 } 43 tests := []struct { 44 name string 45 input string 46 mediaType string 47 layersReturns layersReturns 48 want string 49 wantErr string 50 }{ 51 { 52 name: "happy path", 53 input: "testdata/test.tar.gz", 54 mediaType: "application/vnd.cncf.openpolicyagent.layer.v1.tar+gzip", 55 layersReturns: layersReturns{ 56 layers: []v1.Layer{flayer}, 57 }, 58 want: "Hello, world", 59 }, 60 { 61 name: "sad: two layers", 62 mediaType: "application/vnd.cncf.openpolicyagent.layer.v1.tar+gzip", 63 layersReturns: layersReturns{ 64 layers: []v1.Layer{ 65 layer, 66 layer, 67 }, 68 }, 69 wantErr: "OCI artifact must be a single layer", 70 }, 71 { 72 name: "sad: Layers returns an error", 73 mediaType: "application/vnd.cncf.openpolicyagent.layer.v1.tar+gzip", 74 layersReturns: layersReturns{ 75 err: fmt.Errorf("error"), 76 }, 77 wantErr: "OCI layer error", 78 }, 79 { 80 name: "invalid gzip", 81 input: "testdata/test.txt", 82 layersReturns: layersReturns{ 83 layers: []v1.Layer{txtLayer}, 84 }, 85 wantErr: "unexpected EOF", 86 }, 87 { 88 name: "sad: media type doesn't match", 89 mediaType: "unknown", 90 layersReturns: layersReturns{ 91 layers: []v1.Layer{layer}, 92 }, 93 wantErr: "unacceptable media type", 94 }, 95 } 96 97 for _, tt := range tests { 98 t.Run(tt.name, func(t *testing.T) { 99 tempDir := t.TempDir() 100 fsutils.SetCacheDir(tempDir) 101 102 // Mock image 103 img := new(fakei.FakeImage) 104 img.LayersReturns(tt.layersReturns.layers, tt.layersReturns.err) 105 img.ManifestReturns(&v1.Manifest{ 106 Layers: []v1.Descriptor{ 107 { 108 MediaType: "application/vnd.cncf.openpolicyagent.layer.v1.tar+gzip", 109 Size: 100, 110 Digest: v1.Hash{ 111 Algorithm: "sha256", 112 Hex: "cba33656188782852f58993f45b68bfb8577f64cdcf02a604e3fc2afbeb5f2d8", 113 }, 114 Annotations: map[string]string{ 115 "org.opencontainers.image.title": "bundle.tar.gz", 116 }, 117 }, 118 }, 119 }, nil) 120 121 artifact, err := oci.NewArtifact("repo", true, ftypes.RegistryOptions{}, oci.WithImage(img)) 122 require.NoError(t, err) 123 124 err = artifact.Download(context.Background(), tempDir, oci.DownloadOption{ 125 MediaType: tt.mediaType, 126 }) 127 if tt.wantErr != "" { 128 assert.ErrorContains(t, err, tt.wantErr) 129 return 130 } 131 require.NoError(t, err) 132 133 // Assert 134 got, err := os.ReadFile(filepath.Join(tempDir, "test.txt")) 135 require.NoError(t, err) 136 137 assert.Equal(t, tt.want, string(got)) 138 }) 139 } 140 }