Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add E2E specs for oras blob push #706

Merged
merged 22 commits into from
Dec 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions test/e2e/internal/utils/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"regexp"
"time"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gbytes"
)
Expand Down Expand Up @@ -63,6 +64,15 @@ func MatchFile(filepath string, want string, timeout time.Duration) {
Eventually(gbytes.BufferReader(f)).WithTimeout(timeout).Should(gbytes.Say(want))
}

// WriteTempFile writes content into name under a temp folder.
func WriteTempFile(name string, content string) (path string) {
tempDir := GinkgoT().TempDir()
path = filepath.Join(tempDir, name)
err := os.WriteFile(path, []byte(content), 0666)
Expect(err).ToNot(HaveOccurred())
return path
}

func copyFile(srcFile, dstFile string) error {
to, err := os.Create(dstFile)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions test/e2e/suite/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ var _ = Describe("Common registry user", Ordered, func() {
RunWithoutLogin("push", "-a", "key=value", Host+"/repo:tag")
RunWithoutLogin("pull", Host+"/repo:tag")
RunWithoutLogin("manifest", "fetch", Host+"/repo:tag")
RunWithoutLogin("blob", "push", Host+"/repo", WriteTempFile("blob", "test"))
RunWithoutLogin("tag", Host+"/repo:tag", "tag1")
RunWithoutLogin("repo", "ls", Host)
RunWithoutLogin("repo", "tags", Reference(Host, "repo", ""))
Expand Down
108 changes: 92 additions & 16 deletions test/e2e/suite/command/blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,80 @@ limitations under the License.
package command

import (
"os"
"fmt"
"path/filepath"
"strconv"
"strings"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gbytes"
. "oras.land/oras/test/e2e/internal/utils"
)

const (
pushContent = "test-blob"
pushDigest = "sha256:e1ca41574914ba00e8ed5c8fc78ec8efdfd48941c7e48ad74dad8ada7f2066d8"
wrongDigest = "sha256:e1ca41574914ba00e8ed5c8fc78ec8efdfd48941c7e48ad74dad8ada7f2066d9"
pushDescFmt = `{"mediaType":"%s","digest":"sha256:e1ca41574914ba00e8ed5c8fc78ec8efdfd48941c7e48ad74dad8ada7f2066d8","size":9}`
)

var _ = Describe("ORAS beginners:", func() {
repoFmt := fmt.Sprintf("command/blob/push/%d/%%s", GinkgoRandomSeed())
When("running blob command", func() {
runAndShowPreviewInHelp([]string{"blob"})
RunAndShowPreviewInHelp([]string{"blob"})

When("running `blob push`", func() {
RunAndShowPreviewInHelp([]string{"blob", "push"}, preview_desc, example_desc)
It("should fail to read blob content and password from stdin at the same time", func() {
repo := fmt.Sprintf(repoFmt, "password-stdin")
ORAS("blob", "push", Reference(Host, repo, ""), "--password-stdin", "-").
WithFailureCheck().
MatchTrimmedContent("Error: `-` read file from input and `--password-stdin` read password from input cannot be both used").Exec()
})
It("should fail to push a blob from stdin but no blob size provided", func() {
repo := fmt.Sprintf(repoFmt, "no-size")
ORAS("blob", "push", Reference(Host, repo, pushDigest), "-").
WithInput(strings.NewReader(pushContent)).
WithFailureCheck().
MatchTrimmedContent("Error: `--size` must be provided if the blob is read from stdin").Exec()
})

It("should fail to push a blob from stdin if invalid blob size provided", func() {
repo := fmt.Sprintf(repoFmt, "invalid-stdin-size")
ORAS("blob", "push", Reference(Host, repo, pushDigest), "-", "--size", "3").
WithInput(strings.NewReader(pushContent)).WithFailureCheck().
Exec()
})

It("should fail to push a blob from stdin if invalid digest provided", func() {
repo := fmt.Sprintf(repoFmt, "invalid-stdin-digest")
ORAS("blob", "push", Reference(Host, repo, wrongDigest), "-", "--size", strconv.Itoa(len(pushContent))).
WithInput(strings.NewReader(pushContent)).WithFailureCheck().
Exec()
})

It("should fail to push a blob from file if invalid blob size provided", func() {
repo := fmt.Sprintf(repoFmt, "invalid-file-digest")
blobPath := WriteTempFile("blob", pushContent)
ORAS("blob", "push", Reference(Host, repo, pushDigest), blobPath, "--size", "3").
WithFailureCheck().
Exec()
})

It("should fail to push a blob from file if invalid digest provided", func() {
repo := fmt.Sprintf(repoFmt, "invalid-stdin-size")
blobPath := WriteTempFile("blob", pushContent)
ORAS("blob", "push", Reference(Host, repo, wrongDigest), blobPath, "--size", strconv.Itoa(len(pushContent))).
WithInput(strings.NewReader(pushContent)).WithFailureCheck().
Exec()
})

It("should fail if no reference is provided", func() {
ORAS("blob", "push").WithFailureCheck().Exec()
})
})

When("running `blob fetch`", func() {
runAndShowPreviewInHelp([]string{"blob", "fetch"}, preview_desc, example_desc)
RunAndShowPreviewInHelp([]string{"blob", "fetch"}, preview_desc, example_desc)

It("should call sub-commands with aliases", func() {
ORAS("blob", "get", "--help").
Expand Down Expand Up @@ -69,10 +128,35 @@ var _ = Describe("ORAS beginners:", func() {
})

var _ = Describe("Common registry users:", func() {
repoFmt := fmt.Sprintf("command/blob/push/%d/%%s", GinkgoRandomSeed())
When("running `blob push`", func() {
It("should push a blob from a file and output the descriptor with specific media-type", func() {
mediaType := "test.media"
repo := fmt.Sprintf(repoFmt, "blob-file-media-type")
blobPath := WriteTempFile("blob", pushContent)
ORAS("blob", "push", Reference(Host, repo, ""), blobPath, "--media-type", mediaType, "--descriptor").
MatchContent(fmt.Sprintf(pushDescFmt, mediaType)).Exec()
ORAS("blob", "fetch", Reference(Host, repo, pushDigest), "--output", "-").MatchContent(pushContent).Exec()

ORAS("blob", "push", Reference(Host, repo, ""), blobPath, "-v").
WithDescription("skip the pushing if the blob already exists in the target repo").
MatchKeyWords("Exists").Exec()

})

It("should push a blob from a stdin and output the descriptor with specific media-type", func() {
mediaType := "test.media"
repo := fmt.Sprintf(repoFmt, "blob-file-media-type")
ORAS("blob", "push", Reference(Host, repo, pushDigest), "-", "--media-type", mediaType, "--descriptor", "--size", strconv.Itoa(len(pushContent))).
WithInput(strings.NewReader(pushContent)).
MatchContent(fmt.Sprintf(pushDescFmt, mediaType)).Exec()
ORAS("blob", "fetch", Reference(Host, repo, pushDigest), "--output", "-").MatchContent(pushContent).Exec()
})
})

var blobDigest = "sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"
var blobContent = "foo"
var blobDescriptor = `{"mediaType":"application/octet-stream","digest":"sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae","size":3}`

When("running `blob fetch`", func() {
It("should fetch blob descriptor ", func() {
ORAS("blob", "fetch", Reference(Host, repo, blobDigest), "--descriptor").
Expand All @@ -87,23 +171,15 @@ var _ = Describe("Common registry users:", func() {
contentPath := filepath.Join(tempDir, "fetched")
ORAS("blob", "fetch", Reference(Host, repo, blobDigest), "--output", contentPath).
WithWorkDir(tempDir).Exec()
Expect(contentPath).Should(BeAnExistingFile())
f, err := os.Open(contentPath)
Expect(err).ShouldNot(HaveOccurred())
defer f.Close()
Eventually(gbytes.BufferReader(f)).Should(gbytes.Say(blobContent))
MatchFile(contentPath, blobContent, DefaultTimeout)
})
It("should fetch blob descriptor and output content to a file", func() {
tempDir := GinkgoT().TempDir()
contentPath := filepath.Join(tempDir, "fetched")
ORAS("blob", "fetch", Reference(Host, repo, blobDigest), "--output", contentPath, "--descriptor").
MatchContent(blobDescriptor).
WithWorkDir(tempDir).Exec()
Expect(contentPath).Should(BeAnExistingFile())
f, err := os.Open(contentPath)
Expect(err).ShouldNot(HaveOccurred())
defer f.Close()
Eventually(gbytes.BufferReader(f)).Should(gbytes.Say(blobContent))
MatchFile(contentPath, blobContent, DefaultTimeout)
})
})
})
6 changes: 3 additions & 3 deletions test/e2e/suite/command/manifest.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ const (

var _ = Describe("ORAS beginners:", func() {
When("running manifest command", func() {
runAndShowPreviewInHelp([]string{"manifest"})
runAndShowPreviewInHelp([]string{"manifest", "fetch"}, preview_desc, example_desc)
RunAndShowPreviewInHelp([]string{"manifest"})
RunAndShowPreviewInHelp([]string{"manifest", "fetch"}, preview_desc, example_desc)

It("should call sub-commands with aliases", func() {
ORAS("manifest", "get", "--help").
Expand Down Expand Up @@ -80,7 +80,7 @@ var _ = Describe("ORAS beginners:", func() {
})
})

func runAndShowPreviewInHelp(args []string, keywords ...string) {
func RunAndShowPreviewInHelp(args []string, keywords ...string) {
It(fmt.Sprintf("should run %q command", strings.Join(args, " ")), func() {
ORAS(append(args, "--help")...).
MatchKeyWords(append(keywords, "[Preview] "+args[len(args)-1], "\nUsage:")...).
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/suite/command/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (

var _ = Describe("ORAS beginners:", func() {
When("running repo command", func() {
runAndShowPreviewInHelp([]string{"repo"})
RunAndShowPreviewInHelp([]string{"repo"})
When("running `repo ls`", func() {
It("should show preview in help", func() {
ORAS("repo", "ls", "--help").MatchKeyWords("[Preview] List", preview_desc, example_desc).Exec()
Expand Down
6 changes: 1 addition & 5 deletions test/e2e/suite/command/tag.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,13 @@ limitations under the License.
package command

import (
"fmt"

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

var repoFmt = fmt.Sprintf("command/tag/%%s/%d/%%s", GinkgoRandomSeed())

var _ = Describe("ORAS beginners:", func() {
When("running repo command", func() {
runAndShowPreviewInHelp([]string{"tag"})
RunAndShowPreviewInHelp([]string{"tag"})
It("should fail when no manifest reference provided", func() {
ORAS("tag").WithFailureCheck().MatchErrKeyWords("Error:").Exec()
})
Expand Down