Skip to content

Commit

Permalink
test(e2e): add e2e specs for oras attach (#805)
Browse files Browse the repository at this point in the history
Signed-off-by: Billy Zha <jinzha1@microsoft.com>
  • Loading branch information
qweeah committed Feb 16, 2023
1 parent 89dc7a5 commit 4d97bbd
Show file tree
Hide file tree
Showing 6 changed files with 218 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,30 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package scenario
package foobar

import "oras.land/oras/test/e2e/internal/utils/match"

var (
blobFileNames = []string{
BlobFileNames = []string{
"foobar/foo1",
"foobar/foo2",
"foobar/bar",
}
pushFileStateKeys = []match.StateKey{
{Digest: "2c26b46b68ff", Name: blobFileNames[0]},
{Digest: "2c26b46b68ff", Name: blobFileNames[1]},
{Digest: "fcde2b2edba5", Name: blobFileNames[2]},
PushFileStateKeys = []match.StateKey{
{Digest: "2c26b46b68ff", Name: BlobFileNames[0]},
{Digest: "2c26b46b68ff", Name: BlobFileNames[1]},
{Digest: "fcde2b2edba5", Name: BlobFileNames[2]},
}

configFileName = "foobar/config.json"
configFileStateKey = match.StateKey{
ConfigFileName = "foobar/config.json"
ConfigFileStateKey = match.StateKey{
Digest: "46b68ac1696c", Name: "application/vnd.unknown.config.v1+json",
}

attachFileName = "foobar/to-be-attached"
attachFileMedia = "test/oras.e2e"
attachFileStateKey = match.StateKey{
Digest: "d3b29f7d12d9", Name: attachFileName,
AttachFileName = "foobar/to-be-attached"
AttachFileMedia = "test/oras.e2e"
AttachFileStateKey = match.StateKey{
Digest: "d3b29f7d12d9", Name: AttachFileName,
}
)
9 changes: 8 additions & 1 deletion test/e2e/internal/utils/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,14 @@ import (

var testFileRoot string

// CopyTestData copies test data into the temp test folder.
// CopyTestDataToTemp copies test data into a temp folder and return it.
func CopyTestDataToTemp() string {
tempDir := GinkgoT().TempDir()
Expect(CopyTestData(tempDir)).ShouldNot(HaveOccurred())
return tempDir
}

// CopyTestData copies test data into dstRoot.
func CopyTestData(dstRoot string) error {
return filepath.WalkDir(testFileRoot, func(path string, d fs.DirEntry, err error) error {
if err != nil {
Expand Down
178 changes: 178 additions & 0 deletions test/e2e/suite/command/attach.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
/*
Copyright The ORAS 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 command

import (
"encoding/json"
"fmt"
"path/filepath"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"oras.land/oras/test/e2e/internal/testdata/foobar"
. "oras.land/oras/test/e2e/internal/utils"
"oras.land/oras/test/e2e/internal/utils/match"
)

func attachTestRepo(text string) string {
return fmt.Sprintf("command/attach/%d/%s", GinkgoRandomSeed(), text)
}

var _ = Describe("ORAS beginners:", func() {
When("running attach command", func() {
RunAndShowPreviewInHelp([]string{"attach"})

It("should show preview and help doc", func() {
ORAS("attach", "--help").MatchKeyWords("[Preview] Attach", PreviewDesc, ExampleDesc).Exec()
})

It("should fail when no subject reference provided", func() {
ORAS("attach", "--artifact-type", "oras.test").ExpectFailure().MatchErrKeyWords("Error:").Exec()
})

It("should fail if no file reference or manifest annotation provided", func() {
ORAS("attach", "--artifact-type", "oras.test", Reference(Host, ImageRepo, FoobarImageTag)).
ExpectFailure().MatchErrKeyWords("Error: no blob or manifest annotation are provided").Exec()
})
})
})

var _ = Describe("Common registry users:", func() {
When("running attach command", func() {
It("should attach a file to a subject", func() {
testRepo := attachTestRepo("simple")
tempDir := CopyTestDataToTemp()
subjectRef := Reference(Host, testRepo, FoobarImageTag)
prepare(Reference(Host, ImageRepo, FoobarImageTag), subjectRef)
ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)).
WithWorkDir(tempDir).
MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec()
})

It("should attach a file to a subject and export the built manifest", func() {
// prepare
testRepo := attachTestRepo("export-manifest")
tempDir := CopyTestDataToTemp()
exportName := "manifest.json"
subjectRef := Reference(Host, testRepo, FoobarImageTag)
prepare(Reference(Host, ImageRepo, FoobarImageTag), subjectRef)
// test
ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--export-manifest", exportName).
WithWorkDir(tempDir).
MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec()
// validate
var index ocispec.Index
bytes := ORAS("discover", subjectRef, "-o", "json").Exec().Out.Contents()
Expect(json.Unmarshal(bytes, &index)).ShouldNot(HaveOccurred())
Expect(len(index.Manifests)).To(Equal(1))
fetched := ORAS("manifest", "fetch", Reference(Host, testRepo, index.Manifests[0].Digest.String())).Exec().Out.Contents()
MatchFile(filepath.Join(tempDir, exportName), string(fetched), DefaultTimeout)
})
It("should attach a file via a OCI Image", func() {
testRepo := attachTestRepo("image")
tempDir := CopyTestDataToTemp()
subjectRef := Reference(Host, testRepo, FoobarImageTag)
prepare(Reference(Host, ImageRepo, FoobarImageTag), subjectRef)
// test
ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--image-spec", "v1.1-image").
WithWorkDir(tempDir).
MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec()

// validate
var index ocispec.Index
bytes := ORAS("discover", subjectRef, "-o", "json").Exec().Out.Contents()
Expect(json.Unmarshal(bytes, &index)).ShouldNot(HaveOccurred())
Expect(len(index.Manifests)).To(Equal(1))
Expect(index.Manifests[0].MediaType).To(Equal(ocispec.MediaTypeImageManifest))
})
It("should attach a file via a OCI Artifact", func() {
testRepo := attachTestRepo("artifact")
tempDir := CopyTestDataToTemp()
subjectRef := Reference(Host, testRepo, FoobarImageTag)
prepare(Reference(Host, ImageRepo, FoobarImageTag), subjectRef)
// test
ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--image-spec", "v1.1-artifact").
WithWorkDir(tempDir).
MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec()

// validate
var index ocispec.Index
bytes := ORAS("discover", subjectRef, "-o", "json").Exec().Out.Contents()
Expect(json.Unmarshal(bytes, &index)).ShouldNot(HaveOccurred())
Expect(len(index.Manifests)).To(Equal(1))
Expect(index.Manifests[0].MediaType).To(Equal(ocispec.MediaTypeArtifactManifest))
})
})
})

var _ = Describe("Fallback registry users:", func() {
When("running attach command", func() {
It("should attach a file via a OCI Image", func() {
testRepo := attachTestRepo("fallback/image")
tempDir := CopyTestDataToTemp()
subjectRef := Reference(FallbackHost, testRepo, FoobarImageTag)
prepare(Reference(FallbackHost, ArtifactRepo, FoobarImageTag), subjectRef)
// test
ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--image-spec", "v1.1-image").
WithWorkDir(tempDir).
MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec()

// validate
var index ocispec.Index
bytes := ORAS("discover", subjectRef, "-o", "json").Exec().Out.Contents()
Expect(json.Unmarshal(bytes, &index)).ShouldNot(HaveOccurred())
Expect(len(index.Manifests)).To(Equal(1))
Expect(index.Manifests[0].MediaType).To(Equal(ocispec.MediaTypeImageManifest))
})

It("should attach a file via a OCI Image by default", func() {
testRepo := attachTestRepo("fallback/default")
tempDir := CopyTestDataToTemp()
subjectRef := Reference(FallbackHost, testRepo, FoobarImageTag)
prepare(Reference(FallbackHost, ArtifactRepo, FoobarImageTag), subjectRef)
// test
ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--image-spec", "v1.1-image").
WithWorkDir(tempDir).
MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec()

// validate
var index ocispec.Index
bytes := ORAS("discover", subjectRef, "-o", "json").Exec().Out.Contents()
Expect(json.Unmarshal(bytes, &index)).ShouldNot(HaveOccurred())
Expect(len(index.Manifests)).To(Equal(1))
Expect(index.Manifests[0].MediaType).To(Equal(ocispec.MediaTypeImageManifest))
})

It("should attach a file via a OCI Image and generate referrer via tag schema", func() {
testRepo := attachTestRepo("fallback/tag_schema")
tempDir := CopyTestDataToTemp()
subjectRef := Reference(FallbackHost, testRepo, FoobarImageTag)
prepare(Reference(FallbackHost, ArtifactRepo, FoobarImageTag), subjectRef)
// test
ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--image-spec", "v1.1-image", "--distribution-spec", "v1.1-referrers-tag").
WithWorkDir(tempDir).
MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec()

// validate
var index ocispec.Index
bytes := ORAS("discover", subjectRef, "--distribution-spec", "v1.1-referrers-tag", "-o", "json").Exec().Out.Contents()
Expect(json.Unmarshal(bytes, &index)).ShouldNot(HaveOccurred())
Expect(len(index.Manifests)).To(Equal(1))
Expect(index.Manifests[0].MediaType).To(Equal(ocispec.MediaTypeImageManifest))
})
})
})
2 changes: 1 addition & 1 deletion test/e2e/suite/command/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
)

func prepare(src string, dst string) {
ORAS("cp", src, dst).Exec()
ORAS("cp", src, dst).WithDescription("prepare test env").Exec()
}

func validate(repoRef string, tag string, gone bool) {
Expand Down
31 changes: 16 additions & 15 deletions test/e2e/suite/scenario/oci_artifact.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"path/filepath"

. "github.com/onsi/ginkgo/v2"
"oras.land/oras/test/e2e/internal/testdata/foobar"
. "oras.land/oras/test/e2e/internal/utils"
"oras.land/oras/test/e2e/internal/utils/match"
)
Expand All @@ -39,20 +40,20 @@ var _ = Describe("Common OCI artifact users:", Ordered, func() {
pulledManifest := "packed.json"
pullRoot := "pulled"
It("should push and pull an artifact", func() {
ORAS("push", Reference(Host, repo, tag), "--artifact-type", "test-artifact", blobFileNames[0], blobFileNames[1], blobFileNames[2], "-v", "--export-manifest", pulledManifest).
MatchStatus(pushFileStateKeys, true, 3).
ORAS("push", Reference(Host, repo, tag), "--artifact-type", "test-artifact", foobar.BlobFileNames[0], foobar.BlobFileNames[1], foobar.BlobFileNames[2], "-v", "--export-manifest", pulledManifest).
MatchStatus(foobar.PushFileStateKeys, true, 3).
WithWorkDir(tempDir).
WithDescription("push with manifest exported").Exec()

fetched := ORAS("manifest", "fetch", Reference(Host, repo, tag)).Exec()
MatchFile(filepath.Join(tempDir, pulledManifest), string(fetched.Out.Contents()), DefaultTimeout)

ORAS("pull", Reference(Host, repo, tag), "-v", "-o", pullRoot).
MatchStatus(pushFileStateKeys, true, 3).
MatchStatus(foobar.PushFileStateKeys, true, 3).
WithWorkDir(tempDir).
WithDescription("pull artFiles with config").Exec()

for _, f := range blobFileNames {
for _, f := range foobar.BlobFileNames {
Binary("diff", filepath.Join(f), filepath.Join(pullRoot, f)).
WithWorkDir(tempDir).
WithDescription("download identical file " + f).Exec()
Expand All @@ -61,40 +62,40 @@ var _ = Describe("Common OCI artifact users:", Ordered, func() {

It("should attach and pull an artifact", func() {
subject := Reference(Host, repo, tag)
ORAS("attach", subject, "--artifact-type", "test.artifact1", fmt.Sprint(attachFileName, ":", attachFileMedia), "-v", "--export-manifest", pulledManifest).
MatchStatus([]match.StateKey{attachFileStateKey}, true, 1).
ORAS("attach", subject, "--artifact-type", "test.artifact1", fmt.Sprint(foobar.AttachFileName, ":", foobar.AttachFileMedia), "-v", "--export-manifest", pulledManifest).
MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, true, 1).
WithWorkDir(tempDir).
WithDescription("attach with manifest exported").Exec()

session := ORAS("discover", subject, "-o", "json").Exec()
digest := string(Binary("jq", "-r", ".manifests[].digest").WithInput(session.Out).Exec().Out.Contents())
fetched := ORAS("manifest", "fetch", Reference(Host, repo, digest)).MatchKeyWords(attachFileMedia).Exec()
fetched := ORAS("manifest", "fetch", Reference(Host, repo, digest)).MatchKeyWords(foobar.AttachFileMedia).Exec()
MatchFile(filepath.Join(tempDir, pulledManifest), string(fetched.Out.Contents()), DefaultTimeout)

ORAS("pull", Reference(Host, repo, digest), "-v", "-o", pullRoot).
MatchStatus([]match.StateKey{attachFileStateKey}, true, 1).
MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, true, 1).
WithWorkDir(tempDir).
WithDescription("pull attached artifact").Exec()
Binary("diff", filepath.Join(attachFileName), filepath.Join(pullRoot, attachFileName)).
Binary("diff", filepath.Join(foobar.AttachFileName), filepath.Join(pullRoot, foobar.AttachFileName)).
WithWorkDir(tempDir).
WithDescription("download identical file " + attachFileName).Exec()
WithDescription("download identical file " + foobar.AttachFileName).Exec()

ORAS("attach", subject, "--artifact-type", "test.artifact2", fmt.Sprint(attachFileName, ":", attachFileMedia), "-v", "--export-manifest", pulledManifest).
MatchStatus([]match.StateKey{attachFileStateKey}, true, 1).
ORAS("attach", subject, "--artifact-type", "test.artifact2", fmt.Sprint(foobar.AttachFileName, ":", foobar.AttachFileMedia), "-v", "--export-manifest", pulledManifest).
MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, true, 1).
WithWorkDir(tempDir).
WithDescription("attach again with manifest exported").Exec()

session = ORAS("discover", subject, "-o", "json", "--artifact-type", "test.artifact2").Exec()
digest = string(Binary("jq", "-r", ".manifests[].digest").WithInput(session.Out).Exec().Out.Contents())
fetched = ORAS("manifest", "fetch", Reference(Host, repo, digest)).MatchKeyWords(attachFileMedia).Exec()
fetched = ORAS("manifest", "fetch", Reference(Host, repo, digest)).MatchKeyWords(foobar.AttachFileMedia).Exec()
MatchFile(filepath.Join(tempDir, pulledManifest), string(fetched.Out.Contents()), DefaultTimeout)

ORAS("pull", Reference(Host, repo, string(digest)), "-v", "-o", pullRoot, "--include-subject").
MatchStatus(append(pushFileStateKeys, attachFileStateKey), true, 4).
MatchStatus(append(foobar.PushFileStateKeys, foobar.AttachFileStateKey), true, 4).
WithWorkDir(tempDir).
WithDescription("pull attached artifact and subject").Exec()

for _, f := range append(blobFileNames, attachFileName) {
for _, f := range append(foobar.BlobFileNames, foobar.AttachFileName) {
Binary("diff", filepath.Join(f), filepath.Join(pullRoot, f)).
WithWorkDir(tempDir).
WithDescription("download identical file " + f).Exec()
Expand Down
5 changes: 3 additions & 2 deletions test/e2e/suite/scenario/oci_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ import (
"path/filepath"

. "github.com/onsi/ginkgo/v2"
"oras.land/oras/test/e2e/internal/testdata/foobar"
. "oras.land/oras/test/e2e/internal/utils"
)

var _ = Describe("OCI image user:", Ordered, func() {
repo := "scenario/oci-image"
files := append([]string{configFileName}, blobFileNames...)
statusKeys := append(pushFileStateKeys, configFileStateKey)
files := append([]string{foobar.ConfigFileName}, foobar.BlobFileNames...)
statusKeys := append(foobar.PushFileStateKeys, foobar.ConfigFileStateKey)
When("pushing images and check", func() {
tag := "image"
var tempDir string
Expand Down

0 comments on commit 4d97bbd

Please sign in to comment.