Repository: deislabs/ratify
Pull request #671 (2023-02-24 18:57:07)

test: add more unit tests
# Description

## What this PR does / why we need it:
Adds more unit tests to improve code coverage

## Which issue(s) this PR fixes *(optional, using `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when the PR gets merged)*:
Fixes #

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update

# How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Please also list any relevant details for your test configuration

- [x] unit tests pass

# Checklist:

- [ ] Does the affected code have corresponding tests?
- [ ] Are the changes documented, not just with inline documentation, but also with conceptual documentation such as an overview of a new feature, or task-based documentation like a tutorial? Consider if this change should be announced on your project blog.
- [ ] Does this introduce breaking changes that would require an announcement or bumping the major version?
- [ ] Do all new files have appropriate license header?



Patch:
diff --git a/pkg/referrerstore/oras/mocks/oras_repository.go b/pkg/referrerstore/oras/mocks/oras_repository.go
index 6f743d8..3ba2d38 100644
--- a/pkg/referrerstore/oras/mocks/oras_repository.go
+++ b/pkg/referrerstore/oras/mocks/oras_repository.go
@@ -17,7 +17,9 @@ package mocks
 
 import (
 	"context"
+	"io"
 
+	"github.com/opencontainers/go-digest"
 	oci "github.com/opencontainers/image-spec/specs-go/v1"
 	"oras.land/oras-go/v2/errdef"
 	"oras.land/oras-go/v2/registry"
@@ -25,7 +27,20 @@ import (
 
 type TestRepository struct {
 	registry.Repository
-	ResolveMap map[string]oci.Descriptor
+	ResolveMap    map[string]oci.Descriptor
+	ReferrersList []oci.Descriptor
+	FetchMap      map[digest.Digest]io.ReadCloser
+	BlobStoreTest TestBlobStore
+}
+
+type TestBlobStore struct {
+	registry.BlobStore
+	BlobMap map[string]BlobPair
+}
+
+type BlobPair struct {
+	Descriptor oci.Descriptor
+	Reader     io.ReadCloser
 }
 
 func (r TestRepository) Resolve(ctx context.Context, reference string) (oci.Descriptor, error) {
@@ -34,3 +49,25 @@ func (r TestRepository) Resolve(ctx context.Context, reference string) (oci.Desc
 	}
 	return oci.Descriptor{}, errdef.ErrNotFound
 }
+
+func (r TestRepository) Referrers(ctx context.Context, desc oci.Descriptor, artifactType string, fn func(referrers []oci.Descriptor) error) error {
+	return fn(r.ReferrersList)
+}
+
+func (r TestRepository) Fetch(ctx context.Context, target oci.Descriptor) (io.ReadCloser, error) {
+	if reader, ok := r.FetchMap[target.Digest]; ok {
+		return reader, nil
+	}
+	return nil, errdef.ErrNotFound
+}
+
+func (r TestRepository) Blobs() registry.BlobStore {
+	return r.BlobStoreTest
+}
+
+func (b TestBlobStore) FetchReference(ctx context.Context, reference string) (oci.Descriptor, io.ReadCloser, error) {
+	if pair, ok := b.BlobMap[reference]; ok {
+		return pair.Descriptor, pair.Reader, nil
+	}
+	return oci.Descriptor{}, nil, errdef.ErrNotFound
+}
diff --git a/pkg/referrerstore/oras/mocks/oras_storage.go b/pkg/referrerstore/oras/mocks/oras_storage.go
new file mode 100644
index 0000000..e6f60d8
--- /dev/null
+++ b/pkg/referrerstore/oras/mocks/oras_storage.go
@@ -0,0 +1,50 @@
+/*
+Copyright The Ratify Authors.
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package mocks
+
+import (
+	"context"
+	"io"
+
+	"github.com/opencontainers/go-digest"
+	oci "github.com/opencontainers/image-spec/specs-go/v1"
+	"oras.land/oras-go/v2/content"
+	"oras.land/oras-go/v2/errdef"
+)
+
+type TestStorage struct {
+	content.Storage
+	ExistsMap map[digest.Digest]io.Reader
+}
+
+func (s TestStorage) Exists(ctx context.Context, target oci.Descriptor) (bool, error) {
+	if _, ok := s.ExistsMap[target.Digest]; ok {
+		return true, nil
+	}
+	return false, nil
+}
+
+func (s TestStorage) Push(ctx context.Context, expected oci.Descriptor, content io.Reader) error {
+	s.ExistsMap[expected.Digest] = content
+	return nil
+}
+
+func (s TestStorage) Fetch(ctx context.Context, target oci.Descriptor) (io.ReadCloser, error) {
+	if reader, ok := s.ExistsMap[target.Digest]; ok {
+		return io.NopCloser(reader), nil
+	}
+	return nil, errdef.ErrNotFound
+}
diff --git a/pkg/referrerstore/oras/oras.go b/pkg/referrerstore/oras/oras.go
index b8acffe..a6a7713 100644
--- a/pkg/referrerstore/oras/oras.go
+++ b/pkg/referrerstore/oras/oras.go
@@ -29,8 +29,10 @@ import (
 	"time"
 
 	oci "github.com/opencontainers/image-spec/specs-go/v1"
+	"oras.land/oras-go/v2/content"
 	ocitarget "oras.land/oras-go/v2/content/oci"
 	"oras.land/oras-go/v2/errdef"
+	"oras.land/oras-go/v2/registry"
 	"oras.land/oras-go/v2/registry/remote"
 	"oras.land/oras-go/v2/registry/remote/auth"
 	"oras.land/oras-go/v2/registry/remote/errcode"
@@ -79,19 +81,20 @@ type OrasStoreConf struct {
 type orasStoreFactory struct{}
 
 type authCacheEntry struct {
-	client    *remote.Repository
+	client    registry.Repository
 	expiresOn time.Time
 }
 
 type orasStore struct {
 	config                 *OrasStoreConf
 	rawConfig              config.StoreConfig
-	localCache             *ocitarget.Store
+	localCache             content.Storage
 	authProvider           authprovider.AuthProvider
 	authCache              sync.Map
 	subjectDescriptorCache sync.Map
 	httpClient             *http.Client
 	httpClientInsecure     *http.Client
+	createRepository       func(ctx context.Context, store *orasStore, targetRef common.Reference) (registry.Repository, time.Time, error)
 }
 
 func init() {
@@ -177,7 +180,8 @@ func createBaseStore(version string, storeConfig config.StorePluginConfig) (*ora
 		localCache:         localRegistry,
 		authProvider:       authenticationProvider,
 		httpClient:         secureRetryClient.StandardClient(),
-		httpClientInsecure: insecureRetryClient.StandardClient()}, nil
+		httpClientInsecure: insecureRetryClient.StandardClient(),
+		createRepository:   createDefaultRepository}, nil
 }
 
 func (store *orasStore) Name() string {
@@ -189,7 +193,7 @@ func (store *orasStore) GetConfig() *config.StoreConfig {
 }
 
 func (store *orasStore) ListReferrers(ctx context.Context, subjectReference common.Reference, artifactTypes []string, nextToken string, subjectDesc *ocispecs.SubjectDescriptor) (referrerstore.ListReferrersResult, error) {
-	repository, expiry, err := store.createRepository(ctx, subjectReference)
+	repository, expiry, err := store.createRepository(ctx, store, subjectReference)
 	if err != nil {
 		return referrerstore.ListReferrersResult{}, err
 	}
@@ -247,7 +251,7 @@ func (store *orasStore) ListReferrers(ctx context.Context, subjectReference comm
 
 func (store *orasStore) GetBlobContent(ctx context.Context, subjectReference common.Reference, digest digest.Digest) ([]byte, error) {
 	var err error
-	repository, expiry, err := store.createRepository(ctx, subjectReference)
+	repository, expiry, err := store.createRepository(ctx, store, subjectReference)
 	if err != nil {
 		return nil, err
 	}
@@ -292,7 +296,7 @@ func (store *orasStore) GetBlobContent(ctx context.Context, subjectReference com
 }
 
 func (store *orasStore) GetReferenceManifest(ctx context.Context, subjectReference common.Reference, referenceDesc ocispecs.ReferenceDescriptor) (ocispecs.ReferenceManifest, error) {
-	repository, expiry, err := store.createRepository(ctx, subjectReference)
+	repository, expiry, err := store.createRepository(ctx, store, subjectReference)
 	if err != nil {
 		return ocispecs.ReferenceManifest{}, err
 	}
@@ -363,7 +367,7 @@ func (store *orasStore) GetSubjectDescriptor(ctx context.Context, subjectReferen
 	}
 
 	logrus.Debugf("no digest provided for reference %s. attempting to resolve...", subjectReference.Original)
-	repository, expiry, err := store.createRepository(ctx, subjectReference)
+	repository, expiry, err := store.createRepository(ctx, store, subjectReference)
 	if err != nil {
 		return nil, err
 	}
@@ -384,7 +388,7 @@ func (store *orasStore) GetSubjectDescriptor(ctx context.Context, subjectReferen
 	return &ocispecs.SubjectDescriptor{Descriptor: desc}, nil
 }
 
-func (store *orasStore) createRepository(ctx context.Context, targetRef common.Reference) (*remote.Repository, time.Time, error) {
+func createDefaultRepository(ctx context.Context, store *orasStore, targetRef common.Reference) (registry.Repository, time.Time, error) {
 	if store.authProvider == nil || !store.authProvider.Enabled(ctx) {
 		return nil, time.Now(), fmt.Errorf("auth provider not properly enabled")
 	}
@@ -456,7 +460,7 @@ func (store *orasStore) getRawContentFromCache(ctx context.Context, descriptor o
 	return buf, nil
 }
 
-func (store *orasStore) addAuthCache(ref string, repository *remote.Repository, expiry time.Time) {
+func (store *orasStore) addAuthCache(ref string, repository registry.Repository, expiry time.Time) {
 	store.authCache.LoadOrStore(ref, authCacheEntry{
 		client:    repository,
 		expiresOn: expiry,


Test patch:
diff --git a/config/config_test.go b/config/config_test.go
index 3b4722c..74cfd23 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -172,3 +172,11 @@ func TestLoad_ComputeHash(t *testing.T) {
 		t.Fatalf("Unexpected configuration hash, expected %v, actual %v", expectedHash, config.fileHash)
 	}
 }
+
+func TestGetHomeDir(t *testing.T) {
+	homeDir = "test"
+	testOutput := getHomeDir()
+	if testOutput != homeDir {
+		t.Fatalf("mismatch of home directory: expected %s, actual %s", homeDir, testOutput)
+	}
+}
diff --git a/pkg/referrerstore/factory/factory_test.go b/pkg/referrerstore/factory/factory_test.go
index 37bac06..03d9b47 100644
--- a/pkg/referrerstore/factory/factory_test.go
+++ b/pkg/referrerstore/factory/factory_test.go
@@ -16,8 +16,12 @@ limitations under the License.
 package factory
 
 import (
+	"errors"
+	"os"
+	"path"
 	"testing"
 
+	"github.com/deislabs/ratify/pkg/featureflag"
 	"github.com/deislabs/ratify/pkg/referrerstore"
 	"github.com/deislabs/ratify/pkg/referrerstore/config"
 	"github.com/deislabs/ratify/pkg/referrerstore/mocks"
@@ -87,3 +91,41 @@ func TestCreateStoresFromConfig_PluginStores_ReturnsExpected(t *testing.T) {
 		t.Fatalf("type assertion failed expected a plugin store")
 	}
 }
+
+func TestCreateStoresFromConfig_DynamicPluginStores_ReturnsExpected(t *testing.T) {
+	os.Setenv("RATIFY_DYNAMIC_PLUGINS", "1")
+	featureflag.InitFeatureFlagsFromEnv()
+	storeConfig := map[string]interface{}{
+		"name": "plugin-store",
+		"source": map[string]interface{}{
+			"artifact": "wabbitnetworks.azurecr.io/test/sample-verifier-plugin:v1",
+		},
+	}
+
+	storesConfig := config.StoresConfig{
+		Stores: []config.StorePluginConfig{storeConfig},
+	}
+
+	stores, err := CreateStoresFromConfig(storesConfig, "")
+
+	if err != nil {
+		t.Fatalf("create stores failed with err %v", err)
+	}
+
+	if len(stores) != 1 {
+		t.Fatalf("expected to have %d stores, actual count %d", 1, len(stores))
+	}
+
+	if stores[0].Name() != "plugin-store" {
+		t.Fatalf("expected to create plugin store")
+	}
+
+	if _, ok := stores[0].(*plugin.StorePlugin); !ok {
+		t.Fatalf("type assertion failed expected a plugin store")
+	}
+
+	pluginPath := path.Join(stores[0].GetConfig().PluginBinDirs[0], stores[0].Name())
+	if _, err := os.Stat(pluginPath); errors.Is(err, os.ErrNotExist) {
+		t.Fatalf("downloaded plugin not found in path")
+	}
+}
diff --git a/pkg/referrerstore/oras/oras_test.go b/pkg/referrerstore/oras/oras_test.go
new file mode 100644
index 0000000..7bdac5e
--- /dev/null
+++ b/pkg/referrerstore/oras/oras_test.go
@@ -0,0 +1,472 @@
+/*
+Copyright The Ratify Authors.
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package oras
+
+import (
+	"bytes"
+	"context"
+	"encoding/json"
+	"fmt"
+	"io"
+	"reflect"
+	"testing"
+	"time"
+
+	"github.com/deislabs/ratify/pkg/common"
+	"github.com/deislabs/ratify/pkg/ocispecs"
+	"github.com/deislabs/ratify/pkg/referrerstore/config"
+	"github.com/deislabs/ratify/pkg/referrerstore/oras/mocks"
+	"github.com/opencontainers/go-digest"
+	oci "github.com/opencontainers/image-spec/specs-go/v1"
+	"oras.land/oras-go/v2/registry"
+)
+
+const inputOriginalPath = "localhost:5000/net-monitor:v0"
+
+// TestORASName tests the Name method of the oras store.
+func TestORASName(t *testing.T) {
+	conf := config.StorePluginConfig{
+		"name": "oras",
+	}
+	store, err := createBaseStore("1.0.0", conf)
+	if err != nil {
+		t.Fatalf("failed to create oras store: %v", err)
+	}
+	output := store.Name()
+	if output != "oras" {
+		t.Fatalf("expected name to be 'oras', got '%s'", output)
+	}
+}
+
+// TestORASGetConfig tests the GetConfig method of the oras store.
+func TestORASGetConfig(t *testing.T) {
+	conf := config.StorePluginConfig{
+		"name": "oras",
+	}
+	expectedRawConfig := config.StoreConfig{Version: "1.0.0", Store: conf}
+	store, err := createBaseStore("1.0.0", conf)
+	if err != nil {
+		t.Fatalf("failed to create oras store: %v", err)
+	}
+	output := store.GetConfig()
+	if !reflect.DeepEqual(*output, expectedRawConfig) {
+		t.Fatalf("expected raw config to be %v, got %v", expectedRawConfig, output)
+	}
+}
+
+// TestORASGetSubjectDescriptor_CacheMiss tests the case where the subject descriptor cache is empty
+func TestORASGetSubjectDescriptor_CacheMiss(t *testing.T) {
+	conf := config.StorePluginConfig{
+		"name": "oras",
+	}
+	ctx := context.Background()
+	store, err := createBaseStore("1.0.0", conf)
+	if err != nil {
+		t.Fatalf("failed to create oras store: %v", err)
+	}
+	testRepo := mocks.TestRepository{
+		ResolveMap: map[string]oci.Descriptor{
+			inputOriginalPath: {
+				Digest: digest.FromString("testDigest"),
+			},
+		},
+	}
+	store.createRepository = func(ctx context.Context, store *orasStore, targetRef common.Reference) (registry.Repository, time.Time, error) {
+		return testRepo, time.Now().Add(time.Minute), nil
+	}
+	inputRef := common.Reference{
+		Original: inputOriginalPath,
+		Digest:   digest.FromString("testDigest"),
+	}
+	subjDesc, err := store.GetSubjectDescriptor(ctx, inputRef)
+	if err != nil {
+		t.Fatalf("failed to get subject descriptor: %v", err)
+	}
+	if subjDesc.Digest != digest.FromString("testDigest") {
+		t.Fatalf("expected digest %s, got %s", digest.FromString("testDigest"), subjDesc.Digest)
+	}
+}
+
+// TestORASGetSubjectDescriptor_CacheHit tests that the subject descriptor cache is used
+func TestORASGetSubjectDescriptor_CacheHit(t *testing.T) {
+	conf := config.StorePluginConfig{
+		"name": "oras",
+	}
+	ctx := context.Background()
+	store, err := createBaseStore("1.0.0", conf)
+	if err != nil {
+		t.Fatalf("failed to create oras store: %v", err)
+	}
+	firstDigest := digest.FromString("firstDigest")
+	secondDigest := digest.FromString("secondDigest")
+	store.subjectDescriptorCache.Store(firstDigest, oci.Descriptor{Digest: secondDigest})
+	testRepo := mocks.TestRepository{
+		ResolveMap: map[string]oci.Descriptor{
+			inputOriginalPath: {
+				Digest: firstDigest,
+			},
+		},
+	}
+	store.createRepository = func(ctx context.Context, store *orasStore, targetRef common.Reference) (registry.Repository, time.Time, error) {
+		return testRepo, time.Now().Add(time.Minute), nil
+	}
+	inputRef := common.Reference{
+		Original: inputOriginalPath,
+		Digest:   firstDigest,
+	}
+	subjDesc, err := store.GetSubjectDescriptor(ctx, inputRef)
+	if err != nil {
+		t.Fatalf("failed to get subject descriptor: %v", err)
+	}
+	if subjDesc.Digest != secondDigest {
+		t.Fatalf("expected digest %s, got %s", secondDigest, subjDesc.Digest)
+	}
+}
+
+func TestORASListReferrers_SubjectDesc(t *testing.T) {
+	conf := config.StorePluginConfig{
+		"name":          "oras",
+		"cosignEnabled": false,
+	}
+	ctx := context.Background()
+	subjectDigest := digest.FromString("testDigest")
+	referrerDigest := digest.FromString("testArtifactDigest")
+	store, err := createBaseStore("1.0.0", conf)
+	if err != nil {
+		t.Fatalf("failed to create oras store: %v", err)
+	}
+	subjectDesc := ocispecs.SubjectDescriptor{
+		Descriptor: oci.Descriptor{
+			Digest: subjectDigest,
+		},
+	}
+	testRepo := mocks.TestRepository{
+		ResolveMap: map[string]oci.Descriptor{
+			inputOriginalPath: subjectDesc.Descriptor,
+		},
+		ReferrersList: []oci.Descriptor{
+			{
+				Digest:       referrerDigest,
+				ArtifactType: "application/vnd.cncf.notary.v2",
+			},
+		},
+	}
+	store.createRepository = func(ctx context.Context, store *orasStore, targetRef common.Reference) (registry.Repository, time.Time, error) {
+		return testRepo, time.Now().Add(time.Minute), nil
+	}
+	inputRef := common.Reference{
+		Original: inputOriginalPath,
+		Digest:   subjectDigest,
+	}
+	referrers, err := store.ListReferrers(ctx, inputRef, []string{}, "", &subjectDesc)
+	if err != nil {
+		t.Fatalf("failed to list referrers: %v", err)
+	}
+
+	if referrers.NextToken != "" {
+		t.Fatalf("expected next token to be empty, got %s", referrers.NextToken)
+	}
+
+	if len(referrers.Referrers) != 1 {
+		t.Fatalf("expected 1 referrer, got %d", len(referrers.Referrers))
+	}
+
+	if referrers.Referrers[0].Digest != referrerDigest {
+		t.Fatalf("expected digest %s, got %s", referrerDigest, referrers.Referrers[0].Digest)
+	}
+
+	if referrers.Referrers[0].ArtifactType != "application/vnd.cncf.notary.v2" {
+		t.Fatalf("expected artifact type %s, got %s", "application/vnd.cncf.notary.v2", referrers.Referrers[0].ArtifactType)
+	}
+}
+
+func TestORASListReferrers_NoSubjectDesc(t *testing.T) {
+	conf := config.StorePluginConfig{
+		"name":          "oras",
+		"cosignEnabled": false,
+	}
+	ctx := context.Background()
+	subjectDigest := digest.FromString("testDigest")
+	referrerDigest := digest.FromString("testArtifactDigest")
+	store, err := createBaseStore("1.0.0", conf)
+	if err != nil {
+		t.Fatalf("failed to create oras store: %v", err)
+	}
+	subjectDesc := ocispecs.SubjectDescriptor{
+		Descriptor: oci.Descriptor{
+			Digest: subjectDigest,
+		},
+	}
+	testRepo := mocks.TestRepository{
+		ResolveMap: map[string]oci.Descriptor{
+			inputOriginalPath: subjectDesc.Descriptor,
+		},
+		ReferrersList: []oci.Descriptor{
+			{
+				Digest:       referrerDigest,
+				ArtifactType: "application/vnd.cncf.notary.v2",
+			},
+		},
+	}
+	store.createRepository = func(ctx context.Context, store *orasStore, targetRef common.Reference) (registry.Repository, time.Time, error) {
+		return testRepo, time.Now().Add(time.Minute), nil
+	}
+	inputRef := common.Reference{
+		Original: inputOriginalPath,
+		Digest:   subjectDigest,
+	}
+	referrers, err := store.ListReferrers(ctx, inputRef, []string{}, "", nil)
+	if err != nil {
+		t.Fatalf("failed to list referrers: %v", err)
+	}
+
+	if referrers.NextToken != "" {
+		t.Fatalf("expected next token to be empty, got %s", referrers.NextToken)
+	}
+
+	if len(referrers.Referrers) != 1 {
+		t.Fatalf("expected 1 referrer, got %d", len(referrers.Referrers))
+	}
+
+	if referrers.Referrers[0].Digest != referrerDigest {
+		t.Fatalf("expected digest %s, got %s", referrerDigest, referrers.Referrers[0].Digest)
+	}
+
+	if referrers.Referrers[0].ArtifactType != "application/vnd.cncf.notary.v2" {
+		t.Fatalf("expected artifact type %s, got %s", "application/vnd.cncf.notary.v2", referrers.Referrers[0].ArtifactType)
+	}
+}
+
+// TODO: add cosign test for List Referrers
+
+// TestORASGetReferenceManifest_CachedDesc tests that the reference manifest is returned from the cache if it exists
+func TestORASGetReferenceManifest_CachedDesc(t *testing.T) {
+	conf := config.StorePluginConfig{
+		"name": "oras",
+	}
+	ctx := context.Background()
+	firstDigest := digest.FromString("testDigest")
+	artifactDigest := digest.FromString("testArtifactDigest")
+	expectedReferenceMediatype := "application/vnd.oci.image.manifest.right.v1+json"
+	wrongReferenceMediatype := "application/vnd.oci.image.manifest.wrong.v1+json"
+	store, err := createBaseStore("1.0.0", conf)
+	if err != nil {
+		t.Fatalf("failed to create oras store: %v", err)
+	}
+	manifestCached := oci.Manifest{
+		MediaType: expectedReferenceMediatype,
+		Config:    oci.Descriptor{},
+		Layers:    []oci.Descriptor{},
+	}
+	manifestCachedBytes, err := json.Marshal(manifestCached)
+	if err != nil {
+		t.Fatalf("failed to marshal cached manifest: %v", err)
+	}
+	manifestNotCached := oci.Manifest{
+		MediaType: wrongReferenceMediatype,
+		Config:    oci.Descriptor{},
+		Layers:    []oci.Descriptor{},
+	}
+	manifestNotCachedBytes, err := json.Marshal(manifestNotCached)
+	if err != nil {
+		t.Fatalf("failed to marshal not cached manifest: %v", err)
+	}
+	testRepo := mocks.TestRepository{
+		FetchMap: map[digest.Digest]io.ReadCloser{
+			artifactDigest: io.NopCloser(bytes.NewReader(manifestNotCachedBytes)),
+		},
+	}
+	store.createRepository = func(ctx context.Context, store *orasStore, targetRef common.Reference) (registry.Repository, time.Time, error) {
+		return testRepo, time.Now().Add(time.Minute), nil
+	}
+	store.localCache = mocks.TestStorage{
+		ExistsMap: map[digest.Digest]io.Reader{
+			artifactDigest: bytes.NewReader(manifestCachedBytes),
+		},
+	}
+	inputRef := common.Reference{
+		Original: inputOriginalPath,
+		Digest:   firstDigest,
+	}
+	manifest, err := store.GetReferenceManifest(ctx, inputRef, ocispecs.ReferenceDescriptor{
+		Descriptor: oci.Descriptor{
+			MediaType: oci.MediaTypeArtifactManifest,
+			Digest:    artifactDigest,
+		},
+	})
+	if err != nil {
+		t.Fatalf("failed to get reference manifest: %v", err)
+	}
+	if manifest.MediaType != expectedReferenceMediatype {
+		t.Fatalf("expected media type %s, got %s", expectedReferenceMediatype, manifest.MediaType)
+	}
+}
+
+// TestORASGetReferenceManifest_NotCachedDesc tests that the reference manifest is fetched from the registry if it is not cached
+func TestORASGetReferenceManifest_NotCachedDesc(t *testing.T) {
+	conf := config.StorePluginConfig{
+		"name": "oras",
+	}
+	ctx := context.Background()
+	firstDigest := digest.FromString("testDigest")
+	artifactDigest := digest.FromString("testArtifactDigest")
+	artifactDigestNotCached := digest.FromString("testArtifactDigestNotCached")
+	expectedReferenceMediatype := "application/vnd.oci.image.manifest.right.v1+json"
+	wrongReferenceMediatype := "application/vnd.oci.image.manifest.wrong.v1+json"
+	store, err := createBaseStore("1.0.0", conf)
+	if err != nil {
+		t.Fatalf("failed to create oras store: %v", err)
+	}
+	manifestCached := oci.Manifest{
+		MediaType: wrongReferenceMediatype,
+		Config:    oci.Descriptor{},
+		Layers:    []oci.Descriptor{},
+	}
+	manifestCachedBytes, err := json.Marshal(manifestCached)
+	if err != nil {
+		t.Fatalf("failed to marshal cached manifest: %v", err)
+	}
+	manifestNotCached := oci.Manifest{
+		MediaType: expectedReferenceMediatype,
+		Config:    oci.Descriptor{},
+		Layers:    []oci.Descriptor{},
+	}
+	manifestNotCachedBytes, err := json.Marshal(manifestNotCached)
+	if err != nil {
+		t.Fatalf("failed to marshal not cached manifest: %v", err)
+	}
+	testRepo := mocks.TestRepository{
+		FetchMap: map[digest.Digest]io.ReadCloser{
+			artifactDigest: io.NopCloser(bytes.NewReader(manifestNotCachedBytes)),
+		},
+	}
+	store.createRepository = func(ctx context.Context, store *orasStore, targetRef common.Reference) (registry.Repository, time.Time, error) {
+		return testRepo, time.Now().Add(time.Minute), nil
+	}
+	store.localCache = mocks.TestStorage{
+		ExistsMap: map[digest.Digest]io.Reader{
+			artifactDigestNotCached: bytes.NewReader(manifestCachedBytes),
+		},
+	}
+	inputRef := common.Reference{
+		Original: inputOriginalPath,
+		Digest:   firstDigest,
+	}
+	manifest, err := store.GetReferenceManifest(ctx, inputRef, ocispecs.ReferenceDescriptor{
+		Descriptor: oci.Descriptor{
+			MediaType: oci.MediaTypeArtifactManifest,
+			Digest:    artifactDigest,
+		},
+	})
+	if err != nil {
+		t.Fatalf("failed to get reference manifest: %v", err)
+	}
+	if manifest.MediaType != expectedReferenceMediatype {
+		t.Fatalf("expected media type %s, got %s", expectedReferenceMediatype, manifest.MediaType)
+	}
+}
+
+// TestORASGetBlobContent_CachedDesc tests that the blob content is fetched from the cache if it is cached
+func TestORASGetBlobContent_CachedDesc(t *testing.T) {
+	conf := config.StorePluginConfig{
+		"name": "oras",
+	}
+	ctx := context.Background()
+	firstDigest := digest.FromString("testDigest")
+	blobDigest := digest.FromString("testBlobDigest")
+	expectedContent := []byte("test content")
+	inputRef := common.Reference{
+		Original: inputOriginalPath,
+		Path:     inputOriginalPath,
+		Digest:   firstDigest,
+	}
+	store, err := createBaseStore("1.0.0", conf)
+	if err != nil {
+		t.Fatalf("failed to create oras store: %v", err)
+	}
+	testRepo := mocks.TestRepository{
+		BlobStoreTest: mocks.TestBlobStore{
+			BlobMap: map[string]mocks.BlobPair{
+				fmt.Sprintf("%s@%s", inputRef.Path, blobDigest.String()): {
+					Descriptor: oci.Descriptor{
+						Digest: blobDigest,
+					},
+					Reader: io.NopCloser(bytes.NewReader(expectedContent)),
+				},
+			},
+		},
+	}
+	store.createRepository = func(ctx context.Context, store *orasStore, targetRef common.Reference) (registry.Repository, time.Time, error) {
+		return testRepo, time.Now().Add(time.Minute), nil
+	}
+	store.localCache = mocks.TestStorage{
+		ExistsMap: map[digest.Digest]io.Reader{
+			blobDigest: bytes.NewReader(expectedContent),
+		},
+	}
+	content, err := store.GetBlobContent(ctx, inputRef, blobDigest)
+	if err != nil {
+		t.Fatalf("failed to get blob content: %v", err)
+	}
+	if !bytes.Equal(content, expectedContent) {
+		t.Fatalf("expected content %s, got %s", expectedContent, content)
+	}
+}
+
+// TestORASGetBlobContent_NotCachedDesc tests that the blob content is fetched from the registry if it is not cached
+func TestORASGetBlobContent_NotCachedDesc(t *testing.T) {
+	conf := config.StorePluginConfig{
+		"name": "oras",
+	}
+	ctx := context.Background()
+	firstDigest := digest.FromString("testDigest")
+	blobDigest := digest.FromString("testBlobDigest")
+	expectedContent := []byte("test content")
+	inputRef := common.Reference{
+		Original: inputOriginalPath,
+		Path:     inputOriginalPath,
+		Digest:   firstDigest,
+	}
+	store, err := createBaseStore("1.0.0", conf)
+	if err != nil {
+		t.Fatalf("failed to create oras store: %v", err)
+	}
+	testRepo := mocks.TestRepository{
+		BlobStoreTest: mocks.TestBlobStore{
+			BlobMap: map[string]mocks.BlobPair{
+				fmt.Sprintf("%s@%s", inputRef.Path, blobDigest.String()): {
+					Descriptor: oci.Descriptor{
+						Digest: blobDigest,
+					},
+					Reader: io.NopCloser(bytes.NewReader(expectedContent)),
+				},
+			},
+		},
+	}
+	store.createRepository = func(ctx context.Context, store *orasStore, targetRef common.Reference) (registry.Repository, time.Time, error) {
+		return testRepo, time.Now().Add(time.Minute), nil
+	}
+	store.localCache = mocks.TestStorage{
+		ExistsMap: map[digest.Digest]io.Reader{},
+	}
+	content, err := store.GetBlobContent(ctx, inputRef, blobDigest)
+	if err != nil {
+		t.Fatalf("failed to get blob content: %v", err)
+	}
+	if !bytes.Equal(content, expectedContent) {
+		t.Fatalf("expected content %s, got %s", expectedContent, content)
+	}
+}
diff --git a/pkg/referrerstore/oras/utils_test.go b/pkg/referrerstore/oras/utils_test.go
index df89989..db2c5c7 100644
--- a/pkg/referrerstore/oras/utils_test.go
+++ b/pkg/referrerstore/oras/utils_test.go
@@ -20,9 +20,85 @@ import (
 	"testing"
 
 	"github.com/deislabs/ratify/pkg/ocispecs"
+	"github.com/opencontainers/go-digest"
 	oci "github.com/opencontainers/image-spec/specs-go/v1"
 )
 
+func TestIsInsecureRegistry(t *testing.T) {
+	testCases := []struct {
+		desc     string
+		registry string
+		config   OrasStoreConf
+		expected bool
+	}{
+		{
+			desc:     "secure registry with http disabled",
+			registry: "ghcr.io/test/registry:v0",
+			config: OrasStoreConf{
+				Name: "oras",
+			},
+			expected: false,
+		},
+		{
+			desc:     "insecure registry with http enabled",
+			registry: "registry:5000/test/registry:v0",
+			config: OrasStoreConf{
+				Name:    "oras",
+				UseHttp: true,
+			},
+			expected: true,
+		},
+		{
+			desc:     "localhost insecure registry with http not specified",
+			registry: "localhost:5000/test/registry:v0",
+			config: OrasStoreConf{
+				Name: "oras",
+			},
+			expected: true,
+		},
+		{
+			desc:     "loopback ipv4 insecure registry with http not specified",
+			registry: "127.0.0.1:5000/test/registry:v0",
+			config: OrasStoreConf{
+				Name: "oras",
+			},
+			expected: true,
+		},
+		{
+			desc:     "loopback ipv6 insecure registry with http not specified",
+			registry: "::1:5000/test/registry:v0",
+			config: OrasStoreConf{
+				Name: "oras",
+			},
+			expected: true,
+		},
+	}
+	for _, testCase := range testCases {
+		t.Run(testCase.desc, func(t *testing.T) {
+			output := isInsecureRegistry(testCase.registry, &testCase.config)
+			if output != testCase.expected {
+				t.Fatalf("mismatch of insecure registry type: expected %v, actual %v", testCase.expected, output)
+			}
+		})
+	}
+}
+
+func TestOciDescriptorToReferenceDescriptor(t *testing.T) {
+	input := oci.Descriptor{
+		Digest:       digest.FromString("test"),
+		Size:         5,
+		ArtifactType: "test_type",
+	}
+	expected := ocispecs.ReferenceDescriptor{
+		Descriptor:   input,
+		ArtifactType: "test_type",
+	}
+	output := OciDescriptorToReferenceDescriptor(input)
+	if output.ArtifactType != expected.ArtifactType || output.Descriptor.Digest.String() != expected.Descriptor.Digest.String() {
+		t.Fatalf("mismatch of reference descriptor: expected %v, actual %v", expected, output)
+	}
+}
+
 func TestOciManifestToReferenceManifest(t *testing.T) {
 	type args struct {
 		ociManifest oci.Manifest