From 26388a79dd746317d96e11ccb92708ac4dfe3714 Mon Sep 17 00:00:00 2001 From: Xiaoxuan Wang Date: Tue, 23 Jan 2024 06:01:08 +0000 Subject: [PATCH] increase coverage Signed-off-by: Xiaoxuan Wang --- content/oci/oci.go | 2 +- internal/manifestutil/parser_test.go | 132 +++++++++++++++++++++++++++ 2 files changed, 133 insertions(+), 1 deletion(-) diff --git a/content/oci/oci.go b/content/oci/oci.go index a42cdaea..c9a05a29 100644 --- a/content/oci/oci.go +++ b/content/oci/oci.go @@ -538,7 +538,7 @@ func (s *Store) gcIndex(ctx context.Context) error { tagged.Add(desc.Digest) } - // index referers manifests + // index referrer manifests for ref, desc := range refMap { if ref != desc.Digest.String() || tagged.Contains(desc.Digest) { continue diff --git a/internal/manifestutil/parser_test.go b/internal/manifestutil/parser_test.go index 70b2114a..5f9c09fa 100644 --- a/internal/manifestutil/parser_test.go +++ b/internal/manifestutil/parser_test.go @@ -19,15 +19,49 @@ import ( "bytes" "context" "encoding/json" + "errors" + "fmt" + "io" "reflect" "testing" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "golang.org/x/sync/errgroup" + "oras.land/oras-go/v2/content/memory" "oras.land/oras-go/v2/internal/cas" + "oras.land/oras-go/v2/internal/container/set" "oras.land/oras-go/v2/internal/docker" + "oras.land/oras-go/v2/internal/spec" ) +var ErrBadFetch = errors.New("bad fetch error") + +// testStorage implements Fetcher +type testStorage struct { + store *memory.Store + badFetch set.Set[digest.Digest] +} + +func (s *testStorage) Push(ctx context.Context, expected ocispec.Descriptor, reader io.Reader) error { + return s.store.Push(ctx, expected, reader) +} + +func (s *testStorage) Fetch(ctx context.Context, target ocispec.Descriptor) (io.ReadCloser, error) { + if s.badFetch.Contains(target.Digest) { + return nil, ErrBadFetch + } + return s.store.Fetch(ctx, target) +} + +// func (s *testStorage) Exists(ctx context.Context, target ocispec.Descriptor) (bool, error) { +// return s.store.Exists(ctx, target) +// } + +// func (s *testStorage) Predecessors(ctx context.Context, node ocispec.Descriptor) ([]ocispec.Descriptor, error) { +// return s.store.Predecessors(ctx, node) +// } + func TestConfig(t *testing.T) { storage := cas.NewMemory() @@ -254,3 +288,101 @@ func TestSubject(t *testing.T) { t.Errorf("Subject() = %v, want %v", got, nil) } } + +func TestSubject_ErrorPath(t *testing.T) { + s := testStorage{ + store: memory.New(), + badFetch: set.New[digest.Digest](), + } + ctx := context.Background() + + // generate test content + var blobs [][]byte + var descs []ocispec.Descriptor + appendBlob := func(mediaType string, artifactType string, blob []byte) { + blobs = append(blobs, blob) + descs = append(descs, ocispec.Descriptor{ + MediaType: mediaType, + ArtifactType: artifactType, + Annotations: map[string]string{"test": "content"}, + Digest: digest.FromBytes(blob), + Size: int64(len(blob)), + }) + } + generateImageManifest := func(config ocispec.Descriptor, subject *ocispec.Descriptor, layers ...ocispec.Descriptor) { + manifest := ocispec.Manifest{ + MediaType: ocispec.MediaTypeImageManifest, + Config: config, + Subject: subject, + Layers: layers, + Annotations: map[string]string{"test": "content"}, + } + manifestJSON, err := json.Marshal(manifest) + if err != nil { + t.Fatal(err) + } + appendBlob(ocispec.MediaTypeImageManifest, manifest.Config.MediaType, manifestJSON) + } + generateArtifactManifest := func(subject *ocispec.Descriptor, blobs ...ocispec.Descriptor) { + artifact := spec.Artifact{ + MediaType: spec.MediaTypeArtifactManifest, + ArtifactType: "artifact", + Subject: subject, + Blobs: blobs, + Annotations: map[string]string{"test": "content"}, + } + manifestJSON, err := json.Marshal(artifact) + if err != nil { + t.Fatal(err) + } + appendBlob(spec.MediaTypeArtifactManifest, artifact.ArtifactType, manifestJSON) + } + generateIndex := func(subject *ocispec.Descriptor, manifests ...ocispec.Descriptor) { + index := ocispec.Index{ + MediaType: ocispec.MediaTypeImageIndex, + ArtifactType: "index", + Subject: subject, + Manifests: manifests, + Annotations: map[string]string{"test": "content"}, + } + indexJSON, err := json.Marshal(index) + if err != nil { + t.Fatal(err) + } + appendBlob(ocispec.MediaTypeImageIndex, index.ArtifactType, indexJSON) + } + appendBlob("image manifest", "image config", []byte("config")) // Blob 0 + appendBlob(ocispec.MediaTypeImageLayer, "layer", []byte("foo")) // Blob 1 + appendBlob(ocispec.MediaTypeImageLayer, "layer", []byte("bar")) // Blob 2 + appendBlob(ocispec.MediaTypeImageLayer, "layer", []byte("hello")) // Blob 3 + generateImageManifest(descs[0], nil, descs[1]) // Blob 4 + generateImageManifest(descs[0], &descs[4], descs[2]) // Blob 5 + generateArtifactManifest(&descs[5], descs[3]) // Blob 6 + generateIndex(&descs[6]) // Blob 7 + s.badFetch.Add(descs[5].Digest) + s.badFetch.Add(descs[6].Digest) + s.badFetch.Add(descs[7].Digest) + + eg, egCtx := errgroup.WithContext(ctx) + for i := range blobs { + eg.Go(func(i int) func() error { + return func() error { + err := s.Push(egCtx, descs[i], bytes.NewReader(blobs[i])) + if err != nil { + return fmt.Errorf("failed to push test content to src: %d: %v", i, err) + } + return nil + } + }(i)) + } + if err := eg.Wait(); err != nil { + t.Fatal(err) + } + + for i := 5; i < 7; i++ { + _, err := Subject(ctx, &s, descs[i]) + if !errors.Is(err, ErrBadFetch) { + t.Errorf("Store.Referrers(%d) error = %v, want %v", i, err, ErrBadFetch) + } + } +}