Skip to content

Commit

Permalink
test: add e2e tests for custom header feature (#837)
Browse files Browse the repository at this point in the history
Signed-off-by: wangxiaoxuan273 <wangxiaoxuan119@gmail.com>
  • Loading branch information
wangxiaoxuan273 authored Mar 13, 2023
1 parent ab56116 commit fe4be39
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 2 deletions.
6 changes: 6 additions & 0 deletions test/e2e/internal/utils/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@ func (opts *ExecOption) MatchErrKeyWords(keywords ...string) *ExecOption {
return opts
}

// MatchRequestHeaders adds keywords matching to each sent request.
func (opts *ExecOption) MatchRequestHeaders(headers ...string) *ExecOption {
opts.stderr = append(opts.stderr, match.NewRequestHeaderMatcher(headers))
return opts
}

// MatchContent adds full content matching to the execution.
func (opts *ExecOption) MatchContent(content string) *ExecOption {
if opts.exitCode == 0 {
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/internal/utils/match/keywords.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import (
)

// keywordMatcher provides selective matching of the output.
// The match will pass if all key words existed case-insensitively in the
// output.
// The match will pass if all the keywords exist case-insensitively
// in the output.
type keywordMatcher []string

func NewKeywordMatcher(kw []string) keywordMatcher {
Expand Down
82 changes: 82 additions & 0 deletions test/e2e/internal/utils/match/request.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
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 match

import (
"fmt"
"strings"

. "github.com/onsi/gomega"
"github.com/onsi/gomega/gbytes"
)

// requestHeaderMatcher provides matching for request content.
// It looks into the debug output of an operation and the match will pass
// if all the headers exist in every sent request.
type requestHeaderMatcher []string

// NewRequestHeaderMatcher returns a request header matcher.
func NewRequestHeaderMatcher(kw []string) requestHeaderMatcher {
return requestHeaderMatcher(kw)
}

// Match matches got with wanted headers.
func (r requestHeaderMatcher) Match(got *gbytes.Buffer) {
var missed []string

raw := string(got.Contents())
reqs := getRequestHeaders(getRequests(raw))
for _, req := range reqs {
for _, w := range r {
if !strings.Contains(req, w) {
missed = append(missed, w)
}
}
}

if len(missed) != 0 {
fmt.Printf("Headers missed: %v\n", missed)
panic("failed to match all headers")
}
}

// getRequests parses raw debug output to a string slice
// containing each request.
func getRequests(debugOutput string) []string {
reqs := strings.Split(debugOutput, "> Request URL:")
Expect(len(reqs) > 0).To(BeTrue(), "should output requests in debug logs")
reqs = reqs[1:]
// trim the response content
for i, req := range reqs {
req = strings.Split(req, "< Response Status:")[0]
reqs[i] = req
}
return reqs
}

// getRequestHeaders takes a string slice containing requests
// and extract request headers from them.
func getRequestHeaders(reqs []string) []string {
headers := make([]string, len(reqs))
for i, req := range reqs {
// extract the header content from each request
_, header, ok := strings.Cut(req, "> Request headers:\n")
if ok {
headers[i] = header
}
}
return headers
}
70 changes: 70 additions & 0 deletions test/e2e/suite/command/custom_header.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,80 @@ limitations under the License.
package command

import (
"fmt"

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

var _ = Describe("Common registry users:", func() {
prepareHeaderTestRepo := func(text string) string {
return fmt.Sprintf("command/headertest/%d/%s", GinkgoRandomSeed(), text)
}
var (
FoobarHeaderInput = "Foo:bar"
FoobarHeader = "\"Foo\": \"bar\"\n"
AbHeaderInput = "A: b"
AbHeader = "\"A\": \" b\"\n"
)
When("custom header is provided", func() {
It("attach", func() {
testRepo := prepareHeaderTestRepo("attach")
tempDir := PrepareTempFiles()
subjectRef := RegistryRef(Host, testRepo, foobar.Tag)
prepare(RegistryRef(Host, ImageRepo, foobar.Tag), subjectRef)
ORAS("attach", "--artifact-type", "test.attach", subjectRef,
fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia),
"-d", "-H", FoobarHeaderInput, "-H", AbHeaderInput).
WithWorkDir(tempDir).MatchRequestHeaders(FoobarHeader, AbHeader).Exec()
})
It("blob", func() {
blobDigest := "sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"
ORAS("blob", "fetch", RegistryRef(Host, ImageRepo, blobDigest), "--descriptor",
"-d", "-H", FoobarHeaderInput, "-H", AbHeaderInput).
MatchRequestHeaders(FoobarHeader, AbHeader).Exec()
})
It("manifest", func() {
ORAS("manifest", "fetch", RegistryRef(Host, ImageRepo, multi_arch.Tag),
"-d", "-H", FoobarHeaderInput, "-H", AbHeaderInput).
MatchRequestHeaders(FoobarHeader, AbHeader).Exec()
})
It("pull", func() {
tempDir := GinkgoT().TempDir()
ORAS("pull", "-d", "-H", FoobarHeaderInput, "-H", AbHeaderInput,
RegistryRef(Host, ImageRepo, "foobar"), "--config", "config.json").
WithWorkDir(tempDir).MatchRequestHeaders(FoobarHeader, AbHeader).Exec()
})
It("push", func() {
repo := prepareHeaderTestRepo("push")
tempDir := GinkgoT().TempDir()
if err := CopyTestFiles(tempDir); err != nil {
panic(err)
}
ORAS("push", "-d", "-H", FoobarHeaderInput, "-H", AbHeaderInput,
RegistryRef(Host, repo, "latest"), "foobar/bar").
WithWorkDir(tempDir).MatchRequestHeaders(FoobarHeader, AbHeader).Exec()
})
It("repo", func() {
ORAS("repository", "list", Host, "-d", "-H", FoobarHeaderInput, "-H", AbHeaderInput).
MatchRequestHeaders(FoobarHeader, AbHeader).Exec()
})
It("tag", func() {
digest := "sha256:e2bfc9cc6a84ec2d7365b5a28c6bc5806b7fa581c9ad7883be955a64e3cc034f"
ORAS("tag", RegistryRef(Host, ImageRepo, digest), "latest",
"-d", "-H", FoobarHeaderInput, "-H", AbHeaderInput).
MatchRequestHeaders(FoobarHeader, AbHeader).Exec()
})
It("login", func() {
ORAS("login", Host, "-u", Username, "-p", Password, "--registry-config", AuthConfigPath,
"-H", FoobarHeaderInput, "-H", AbHeaderInput).
MatchRequestHeaders(FoobarHeader, AbHeader).Exec()
})
})
})

var _ = Describe("OCI image layout users:", func() {
When("custom header is provided", func() {
It("should fail attach", func() {
Expand Down

0 comments on commit fe4be39

Please sign in to comment.