Skip to content

Commit

Permalink
Merge pull request #1577 from mtrmac/mocks
Browse files Browse the repository at this point in the history
Consolidate interface mocks in a testing subpackage
  • Loading branch information
vrothberg committed Jun 14, 2022
2 parents 3c0150e + 4856cb9 commit e609a9f
Show file tree
Hide file tree
Showing 11 changed files with 205 additions and 180 deletions.
19 changes: 17 additions & 2 deletions copy/manifest_test.go
Expand Up @@ -7,6 +7,7 @@ import (
"testing"

"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/internal/testing/mocks"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/types"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
Expand Down Expand Up @@ -198,6 +199,20 @@ func TestDetermineManifestConversion(t *testing.T) {
assert.Error(t, err)
}

// fakeUnparsedImage is an implementation of types.UnparsedImage which only returns itself as a MIME type in Manifest,
// except that "" means “reading the manifest should fail”
type fakeUnparsedImage struct {
mocks.ForbiddenUnparsedImage
mt string
}

func (f fakeUnparsedImage) Manifest(ctx context.Context) ([]byte, string, error) {
if f.mt == "" {
return nil, "", errors.New("Manifest() directed to fail")
}
return nil, f.mt, nil
}

func TestIsMultiImage(t *testing.T) {
// MIME type is available; more or less a smoke test, other cases are handled in manifest.MIMETypeIsMultiImage
for _, c := range []struct {
Expand All @@ -209,14 +224,14 @@ func TestIsMultiImage(t *testing.T) {
{v1.MediaTypeImageManifest, false},
{v1.MediaTypeImageIndex, true},
} {
src := fakeImageSource(c.mt)
src := fakeUnparsedImage{mocks.ForbiddenUnparsedImage{}, c.mt}
res, err := isMultiImage(context.Background(), src)
require.NoError(t, err)
assert.Equal(t, c.expected, res, c.mt)
}

// Error getting manifest MIME type
src := fakeImageSource("")
src := fakeUnparsedImage{mocks.ForbiddenUnparsedImage{}, ""}
_, err := isMultiImage(context.Background(), src)
assert.Error(t, err)
}
Expand Down
81 changes: 18 additions & 63 deletions internal/image/docker_schema2_test.go
Expand Up @@ -12,6 +12,7 @@ import (
"time"

"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/internal/testing/mocks"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/types"
"github.com/opencontainers/go-digest"
Expand All @@ -21,31 +22,6 @@ import (
"github.com/stretchr/testify/require"
)

// unusedImageSource is used when we don't expect the ImageSource to be used in our tests.
type unusedImageSource struct{}

func (f unusedImageSource) Reference() types.ImageReference {
panic("Unexpected call to a mock function")
}
func (f unusedImageSource) Close() error {
panic("Unexpected call to a mock function")
}
func (f unusedImageSource) GetManifest(context.Context, *digest.Digest) ([]byte, string, error) {
panic("Unexpected call to a mock function")
}
func (f unusedImageSource) HasThreadSafeGetBlob() bool {
panic("Unexpected call to a mock function")
}
func (f unusedImageSource) GetBlob(context.Context, types.BlobInfo, types.BlobInfoCache) (io.ReadCloser, int64, error) {
panic("Unexpected call to a mock function")
}
func (f unusedImageSource) GetSignatures(context.Context, *digest.Digest) ([][]byte, error) {
panic("Unexpected call to a mock function")
}
func (f unusedImageSource) LayerInfosForCopy(context.Context, *digest.Digest) ([]types.BlobInfo, error) {
panic("Unexpected call to a mock function")
}

func manifestSchema2FromFixture(t *testing.T, src types.ImageSource, fixture string, mustFail bool) genericManifest {
manifest, err := os.ReadFile(filepath.Join("fixtures", fixture))
require.NoError(t, err)
Expand Down Expand Up @@ -96,7 +72,7 @@ func manifestSchema2FromComponentsLikeFixture(configBlob []byte) genericManifest
func TestManifestSchema2FromManifest(t *testing.T) {
// This just tests that the JSON can be loaded; we test that the parsed
// values are correctly returned in tests for the individual getter methods.
_ = manifestSchema2FromFixture(t, unusedImageSource{}, "schema2.json", false)
_ = manifestSchema2FromFixture(t, mocks.ForbiddenImageSource{}, "schema2.json", false)

_, err := manifestSchema2FromManifest(nil, []byte{})
assert.Error(t, err)
Expand All @@ -110,7 +86,7 @@ func TestManifestSchema2FromComponents(t *testing.T) {

func TestManifestSchema2Serialize(t *testing.T) {
for _, m := range []genericManifest{
manifestSchema2FromFixture(t, unusedImageSource{}, "schema2.json", false),
manifestSchema2FromFixture(t, mocks.ForbiddenImageSource{}, "schema2.json", false),
manifestSchema2FromComponentsLikeFixture(nil),
} {
serialized, err := m.serialize()
Expand All @@ -134,7 +110,7 @@ func TestManifestSchema2Serialize(t *testing.T) {

func TestManifestSchema2ManifestMIMEType(t *testing.T) {
for _, m := range []genericManifest{
manifestSchema2FromFixture(t, unusedImageSource{}, "schema2.json", false),
manifestSchema2FromFixture(t, mocks.ForbiddenImageSource{}, "schema2.json", false),
manifestSchema2FromComponentsLikeFixture(nil),
} {
assert.Equal(t, manifest.DockerV2Schema2MediaType, m.manifestMIMEType())
Expand All @@ -143,7 +119,7 @@ func TestManifestSchema2ManifestMIMEType(t *testing.T) {

func TestManifestSchema2ConfigInfo(t *testing.T) {
for _, m := range []genericManifest{
manifestSchema2FromFixture(t, unusedImageSource{}, "schema2.json", false),
manifestSchema2FromFixture(t, mocks.ForbiddenImageSource{}, "schema2.json", false),
manifestSchema2FromComponentsLikeFixture(nil),
} {
assert.Equal(t, types.BlobInfo{
Expand All @@ -156,8 +132,8 @@ func TestManifestSchema2ConfigInfo(t *testing.T) {

// configBlobImageSource allows testing various GetBlob behaviors in .ConfigBlob()
type configBlobImageSource struct {
unusedImageSource // We inherit almost all of the methods, which just panic()
f func(digest digest.Digest) (io.ReadCloser, int64, error)
mocks.ForbiddenImageSource // We inherit almost all of the methods, which just panic()
f func(digest digest.Digest) (io.ReadCloser, int64, error)
}

func (f configBlobImageSource) GetBlob(ctx context.Context, info types.BlobInfo, _ types.BlobInfoCache) (io.ReadCloser, int64, error) {
Expand Down Expand Up @@ -197,7 +173,7 @@ func TestManifestSchema2ConfigBlob(t *testing.T) {
} {
var src types.ImageSource
if c.cbISfn != nil {
src = configBlobImageSource{unusedImageSource{}, c.cbISfn}
src = configBlobImageSource{f: c.cbISfn}
} else {
src = nil
}
Expand Down Expand Up @@ -225,7 +201,7 @@ func TestManifestSchema2ConfigBlob(t *testing.T) {

func TestManifestSchema2LayerInfo(t *testing.T) {
for _, m := range []genericManifest{
manifestSchema2FromFixture(t, unusedImageSource{}, "schema2.json", false),
manifestSchema2FromFixture(t, mocks.ForbiddenImageSource{}, "schema2.json", false),
manifestSchema2FromComponentsLikeFixture(nil),
} {
assert.Equal(t, []types.BlobInfo{
Expand Down Expand Up @@ -260,7 +236,7 @@ func TestManifestSchema2LayerInfo(t *testing.T) {

func TestManifestSchema2EmbeddedDockerReferenceConflicts(t *testing.T) {
for _, m := range []genericManifest{
manifestSchema2FromFixture(t, unusedImageSource{}, "schema2.json", false),
manifestSchema2FromFixture(t, mocks.ForbiddenImageSource{}, "schema2.json", false),
manifestSchema2FromComponentsLikeFixture(nil),
} {
for _, name := range []string{"busybox", "example.com:5555/ns/repo:tag"} {
Expand Down Expand Up @@ -316,7 +292,7 @@ func TestManifestSchema2Inspect(t *testing.T) {

func TestManifestSchema2UpdatedImageNeedsLayerDiffIDs(t *testing.T) {
for _, m := range []genericManifest{
manifestSchema2FromFixture(t, unusedImageSource{}, "schema2.json", false),
manifestSchema2FromFixture(t, mocks.ForbiddenImageSource{}, "schema2.json", false),
manifestSchema2FromComponentsLikeFixture(nil),
} {
assert.False(t, m.UpdatedImageNeedsLayerDiffIDs(types.ManifestUpdateOptions{
Expand All @@ -332,38 +308,17 @@ type schema2ImageSource struct {
}

func (s2is *schema2ImageSource) Reference() types.ImageReference {
return refImageReferenceMock{s2is.ref}
return refImageReferenceMock{ref: s2is.ref}
}

// refImageReferenceMock is a mock of types.ImageReference which returns itself in DockerReference.
type refImageReferenceMock struct{ reference.Named }

func (ref refImageReferenceMock) Transport() types.ImageTransport {
panic("unexpected call to a mock function")
}
func (ref refImageReferenceMock) StringWithinTransport() string {
panic("unexpected call to a mock function")
type refImageReferenceMock struct {
mocks.ForbiddenImageReference // We inherit almost all of the methods, which just panic()
ref reference.Named
}

func (ref refImageReferenceMock) DockerReference() reference.Named {
return ref.Named
}
func (ref refImageReferenceMock) PolicyConfigurationIdentity() string {
panic("unexpected call to a mock function")
}
func (ref refImageReferenceMock) PolicyConfigurationNamespaces() []string {
panic("unexpected call to a mock function")
}
func (ref refImageReferenceMock) NewImage(ctx context.Context, sys *types.SystemContext) (types.ImageCloser, error) {
panic("unexpected call to a mock function")
}
func (ref refImageReferenceMock) NewImageSource(ctx context.Context, sys *types.SystemContext) (types.ImageSource, error) {
panic("unexpected call to a mock function")
}
func (ref refImageReferenceMock) NewImageDestination(ctx context.Context, sys *types.SystemContext) (types.ImageDestination, error) {
panic("unexpected call to a mock function")
}
func (ref refImageReferenceMock) DeleteImage(ctx context.Context, sys *types.SystemContext) error {
panic("unexpected call to a mock function")
return ref.ref
}

func newSchema2ImageSource(t *testing.T, dockerRef string) *schema2ImageSource {
Expand All @@ -389,7 +344,7 @@ type memoryImageDest struct {
}

func (d *memoryImageDest) Reference() types.ImageReference {
return refImageReferenceMock{d.ref}
return refImageReferenceMock{ref: d.ref}
}
func (d *memoryImageDest) Close() error {
panic("Unexpected call to a mock function")
Expand Down
19 changes: 10 additions & 9 deletions internal/image/oci_test.go
Expand Up @@ -11,6 +11,7 @@ import (
"time"

"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/internal/testing/mocks"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/types"
"github.com/opencontainers/go-digest"
Expand Down Expand Up @@ -75,7 +76,7 @@ func manifestOCI1FromComponentsLikeFixture(configBlob []byte) genericManifest {
func TestManifestOCI1FromManifest(t *testing.T) {
// This just tests that the JSON can be loaded; we test that the parsed
// values are correctly returned in tests for the individual getter methods.
_ = manifestOCI1FromFixture(t, unusedImageSource{}, "oci1.json")
_ = manifestOCI1FromFixture(t, mocks.ForbiddenImageSource{}, "oci1.json")

_, err := manifestOCI1FromManifest(nil, []byte{})
assert.Error(t, err)
Expand All @@ -89,7 +90,7 @@ func TestManifestOCI1FromComponents(t *testing.T) {

func TestManifestOCI1Serialize(t *testing.T) {
for _, m := range []genericManifest{
manifestOCI1FromFixture(t, unusedImageSource{}, "oci1.json"),
manifestOCI1FromFixture(t, mocks.ForbiddenImageSource{}, "oci1.json"),
manifestOCI1FromComponentsLikeFixture(nil),
} {
serialized, err := m.serialize()
Expand All @@ -113,7 +114,7 @@ func TestManifestOCI1Serialize(t *testing.T) {

func TestManifestOCI1ManifestMIMEType(t *testing.T) {
for _, m := range []genericManifest{
manifestOCI1FromFixture(t, unusedImageSource{}, "oci1.json"),
manifestOCI1FromFixture(t, mocks.ForbiddenImageSource{}, "oci1.json"),
manifestOCI1FromComponentsLikeFixture(nil),
} {
assert.Equal(t, imgspecv1.MediaTypeImageManifest, m.manifestMIMEType())
Expand All @@ -122,7 +123,7 @@ func TestManifestOCI1ManifestMIMEType(t *testing.T) {

func TestManifestOCI1ConfigInfo(t *testing.T) {
for _, m := range []genericManifest{
manifestOCI1FromFixture(t, unusedImageSource{}, "oci1.json"),
manifestOCI1FromFixture(t, mocks.ForbiddenImageSource{}, "oci1.json"),
manifestOCI1FromComponentsLikeFixture(nil),
} {
assert.Equal(t, types.BlobInfo{
Expand Down Expand Up @@ -166,7 +167,7 @@ func TestManifestOCI1ConfigBlob(t *testing.T) {
} {
var src types.ImageSource
if c.cbISfn != nil {
src = configBlobImageSource{unusedImageSource{}, c.cbISfn}
src = configBlobImageSource{f: c.cbISfn}
} else {
src = nil
}
Expand Down Expand Up @@ -194,7 +195,7 @@ func TestManifestOCI1ConfigBlob(t *testing.T) {

func TestManifestOCI1LayerInfo(t *testing.T) {
for _, m := range []genericManifest{
manifestOCI1FromFixture(t, unusedImageSource{}, "oci1.json"),
manifestOCI1FromFixture(t, mocks.ForbiddenImageSource{}, "oci1.json"),
manifestOCI1FromComponentsLikeFixture(nil),
} {
assert.Equal(t, []types.BlobInfo{
Expand Down Expand Up @@ -235,7 +236,7 @@ func TestManifestOCI1LayerInfo(t *testing.T) {

func TestManifestOCI1EmbeddedDockerReferenceConflicts(t *testing.T) {
for _, m := range []genericManifest{
manifestOCI1FromFixture(t, unusedImageSource{}, "oci1.json"),
manifestOCI1FromFixture(t, mocks.ForbiddenImageSource{}, "oci1.json"),
manifestOCI1FromComponentsLikeFixture(nil),
} {
for _, name := range []string{"busybox", "example.com:5555/ns/repo:tag"} {
Expand Down Expand Up @@ -291,7 +292,7 @@ func TestManifestOCI1Inspect(t *testing.T) {

func TestManifestOCI1UpdatedImageNeedsLayerDiffIDs(t *testing.T) {
for _, m := range []genericManifest{
manifestOCI1FromFixture(t, unusedImageSource{}, "oci1.json"),
manifestOCI1FromFixture(t, mocks.ForbiddenImageSource{}, "oci1.json"),
manifestOCI1FromComponentsLikeFixture(nil),
} {
assert.False(t, m.UpdatedImageNeedsLayerDiffIDs(types.ManifestUpdateOptions{
Expand All @@ -307,7 +308,7 @@ type oci1ImageSource struct {
}

func (OCIis *oci1ImageSource) Reference() types.ImageReference {
return refImageReferenceMock{OCIis.ref}
return refImageReferenceMock{ref: OCIis.ref}
}

func newOCI1ImageSource(t *testing.T, dockerRef string) *oci1ImageSource {
Expand Down
56 changes: 56 additions & 0 deletions internal/testing/mocks/image_reference.go
@@ -0,0 +1,56 @@
package mocks

import (
"context"

"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/types"
)

// ForbiddenImageReference is used when we don’t expect the ImageReference to be used in our tests.
type ForbiddenImageReference struct{}

// Transport is a mock that panics.
func (ref ForbiddenImageReference) Transport() types.ImageTransport {
panic("unexpected call to a mock function")
}

// StringWithinTransport is a mock that panics.
func (ref ForbiddenImageReference) StringWithinTransport() string {
panic("unexpected call to a mock function")
}

// DockerReference is a mock that panics.
func (ref ForbiddenImageReference) DockerReference() reference.Named {
panic("unexpected call to a mock function")
}

// PolicyConfigurationIdentity is a mock that panics.
func (ref ForbiddenImageReference) PolicyConfigurationIdentity() string {
panic("unexpected call to a mock function")
}

// PolicyConfigurationNamespaces is a mock that panics.
func (ref ForbiddenImageReference) PolicyConfigurationNamespaces() []string {
panic("unexpected call to a mock function")
}

// NewImage is a mock that panics.
func (ref ForbiddenImageReference) NewImage(ctx context.Context, sys *types.SystemContext) (types.ImageCloser, error) {
panic("unexpected call to a mock function")
}

// NewImageSource is a mock that panics.
func (ref ForbiddenImageReference) NewImageSource(ctx context.Context, sys *types.SystemContext) (types.ImageSource, error) {
panic("unexpected call to a mock function")
}

// NewImageDestination is a mock that panics.
func (ref ForbiddenImageReference) NewImageDestination(ctx context.Context, sys *types.SystemContext) (types.ImageDestination, error) {
panic("unexpected call to a mock function")
}

// DeleteImage is a mock that panics.
func (ref ForbiddenImageReference) DeleteImage(ctx context.Context, sys *types.SystemContext) error {
panic("unexpected call to a mock function")
}

0 comments on commit e609a9f

Please sign in to comment.