Update go dependencies
This commit is contained in:
parent
15ffb51394
commit
bb4d483837
1621 changed files with 86368 additions and 284392 deletions
371
vendor/github.com/docker/distribution/digestset/set_test.go
generated
vendored
371
vendor/github.com/docker/distribution/digestset/set_test.go
generated
vendored
|
|
@ -1,371 +0,0 @@
|
|||
package digestset
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
_ "crypto/sha512"
|
||||
"encoding/binary"
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
func assertEqualDigests(t *testing.T, d1, d2 digest.Digest) {
|
||||
if d1 != d2 {
|
||||
t.Fatalf("Digests do not match:\n\tActual: %s\n\tExpected: %s", d1, d2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLookup(t *testing.T) {
|
||||
digests := []digest.Digest{
|
||||
"sha256:1234511111111111111111111111111111111111111111111111111111111111",
|
||||
"sha256:1234111111111111111111111111111111111111111111111111111111111111",
|
||||
"sha256:1234611111111111111111111111111111111111111111111111111111111111",
|
||||
"sha256:5432111111111111111111111111111111111111111111111111111111111111",
|
||||
"sha256:6543111111111111111111111111111111111111111111111111111111111111",
|
||||
"sha256:6432111111111111111111111111111111111111111111111111111111111111",
|
||||
"sha256:6542111111111111111111111111111111111111111111111111111111111111",
|
||||
"sha256:6532111111111111111111111111111111111111111111111111111111111111",
|
||||
}
|
||||
|
||||
dset := NewSet()
|
||||
for i := range digests {
|
||||
if err := dset.Add(digests[i]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
dgst, err := dset.Lookup("54")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assertEqualDigests(t, dgst, digests[3])
|
||||
|
||||
dgst, err = dset.Lookup("1234")
|
||||
if err == nil {
|
||||
t.Fatal("Expected ambiguous error looking up: 1234")
|
||||
}
|
||||
if err != ErrDigestAmbiguous {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
dgst, err = dset.Lookup("9876")
|
||||
if err == nil {
|
||||
t.Fatal("Expected ambiguous error looking up: 9876")
|
||||
}
|
||||
if err != ErrDigestNotFound {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
dgst, err = dset.Lookup("sha256:1234")
|
||||
if err == nil {
|
||||
t.Fatal("Expected ambiguous error looking up: sha256:1234")
|
||||
}
|
||||
if err != ErrDigestAmbiguous {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
dgst, err = dset.Lookup("sha256:12345")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assertEqualDigests(t, dgst, digests[0])
|
||||
|
||||
dgst, err = dset.Lookup("sha256:12346")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assertEqualDigests(t, dgst, digests[2])
|
||||
|
||||
dgst, err = dset.Lookup("12346")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assertEqualDigests(t, dgst, digests[2])
|
||||
|
||||
dgst, err = dset.Lookup("12345")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assertEqualDigests(t, dgst, digests[0])
|
||||
}
|
||||
|
||||
func TestAddDuplication(t *testing.T) {
|
||||
digests := []digest.Digest{
|
||||
"sha256:1234111111111111111111111111111111111111111111111111111111111111",
|
||||
"sha256:1234511111111111111111111111111111111111111111111111111111111111",
|
||||
"sha256:1234611111111111111111111111111111111111111111111111111111111111",
|
||||
"sha256:5432111111111111111111111111111111111111111111111111111111111111",
|
||||
"sha256:6543111111111111111111111111111111111111111111111111111111111111",
|
||||
"sha512:65431111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
|
||||
"sha512:65421111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
|
||||
"sha512:65321111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
|
||||
}
|
||||
|
||||
dset := NewSet()
|
||||
for i := range digests {
|
||||
if err := dset.Add(digests[i]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(dset.entries) != 8 {
|
||||
t.Fatal("Invalid dset size")
|
||||
}
|
||||
|
||||
if err := dset.Add(digest.Digest("sha256:1234511111111111111111111111111111111111111111111111111111111111")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(dset.entries) != 8 {
|
||||
t.Fatal("Duplicate digest insert allowed")
|
||||
}
|
||||
|
||||
if err := dset.Add(digest.Digest("sha384:123451111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(dset.entries) != 9 {
|
||||
t.Fatal("Insert with different algorithm not allowed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemove(t *testing.T) {
|
||||
digests, err := createDigests(10)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
dset := NewSet()
|
||||
for i := range digests {
|
||||
if err := dset.Add(digests[i]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
dgst, err := dset.Lookup(digests[0].String())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if dgst != digests[0] {
|
||||
t.Fatalf("Unexpected digest value:\n\tExpected: %s\n\tActual: %s", digests[0], dgst)
|
||||
}
|
||||
|
||||
if err := dset.Remove(digests[0]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := dset.Lookup(digests[0].String()); err != ErrDigestNotFound {
|
||||
t.Fatalf("Expected error %v when looking up removed digest, got %v", ErrDigestNotFound, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAll(t *testing.T) {
|
||||
digests, err := createDigests(100)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
dset := NewSet()
|
||||
for i := range digests {
|
||||
if err := dset.Add(digests[i]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
all := map[digest.Digest]struct{}{}
|
||||
for _, dgst := range dset.All() {
|
||||
all[dgst] = struct{}{}
|
||||
}
|
||||
|
||||
if len(all) != len(digests) {
|
||||
t.Fatalf("Unexpected number of unique digests found:\n\tExpected: %d\n\tActual: %d", len(digests), len(all))
|
||||
}
|
||||
|
||||
for i, dgst := range digests {
|
||||
if _, ok := all[dgst]; !ok {
|
||||
t.Fatalf("Missing element at position %d: %s", i, dgst)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func assertEqualShort(t *testing.T, actual, expected string) {
|
||||
if actual != expected {
|
||||
t.Fatalf("Unexpected short value:\n\tExpected: %s\n\tActual: %s", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShortCodeTable(t *testing.T) {
|
||||
digests := []digest.Digest{
|
||||
"sha256:1234111111111111111111111111111111111111111111111111111111111111",
|
||||
"sha256:1234511111111111111111111111111111111111111111111111111111111111",
|
||||
"sha256:1234611111111111111111111111111111111111111111111111111111111111",
|
||||
"sha256:5432111111111111111111111111111111111111111111111111111111111111",
|
||||
"sha256:6543111111111111111111111111111111111111111111111111111111111111",
|
||||
"sha256:6432111111111111111111111111111111111111111111111111111111111111",
|
||||
"sha256:6542111111111111111111111111111111111111111111111111111111111111",
|
||||
"sha256:6532111111111111111111111111111111111111111111111111111111111111",
|
||||
}
|
||||
|
||||
dset := NewSet()
|
||||
for i := range digests {
|
||||
if err := dset.Add(digests[i]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
dump := ShortCodeTable(dset, 2)
|
||||
|
||||
if len(dump) < len(digests) {
|
||||
t.Fatalf("Error unexpected size: %d, expecting %d", len(dump), len(digests))
|
||||
}
|
||||
assertEqualShort(t, dump[digests[0]], "12341")
|
||||
assertEqualShort(t, dump[digests[1]], "12345")
|
||||
assertEqualShort(t, dump[digests[2]], "12346")
|
||||
assertEqualShort(t, dump[digests[3]], "54")
|
||||
assertEqualShort(t, dump[digests[4]], "6543")
|
||||
assertEqualShort(t, dump[digests[5]], "64")
|
||||
assertEqualShort(t, dump[digests[6]], "6542")
|
||||
assertEqualShort(t, dump[digests[7]], "653")
|
||||
}
|
||||
|
||||
func createDigests(count int) ([]digest.Digest, error) {
|
||||
r := rand.New(rand.NewSource(25823))
|
||||
digests := make([]digest.Digest, count)
|
||||
for i := range digests {
|
||||
h := sha256.New()
|
||||
if err := binary.Write(h, binary.BigEndian, r.Int63()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
digests[i] = digest.NewDigest("sha256", h)
|
||||
}
|
||||
return digests, nil
|
||||
}
|
||||
|
||||
func benchAddNTable(b *testing.B, n int) {
|
||||
digests, err := createDigests(n)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
dset := &Set{entries: digestEntries(make([]*digestEntry, 0, n))}
|
||||
for j := range digests {
|
||||
if err = dset.Add(digests[j]); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func benchLookupNTable(b *testing.B, n int, shortLen int) {
|
||||
digests, err := createDigests(n)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
dset := &Set{entries: digestEntries(make([]*digestEntry, 0, n))}
|
||||
for i := range digests {
|
||||
if err := dset.Add(digests[i]); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
shorts := make([]string, 0, n)
|
||||
for _, short := range ShortCodeTable(dset, shortLen) {
|
||||
shorts = append(shorts, short)
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err = dset.Lookup(shorts[i%n]); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func benchRemoveNTable(b *testing.B, n int) {
|
||||
digests, err := createDigests(n)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
dset := &Set{entries: digestEntries(make([]*digestEntry, 0, n))}
|
||||
b.StopTimer()
|
||||
for j := range digests {
|
||||
if err = dset.Add(digests[j]); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
b.StartTimer()
|
||||
for j := range digests {
|
||||
if err = dset.Remove(digests[j]); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func benchShortCodeNTable(b *testing.B, n int, shortLen int) {
|
||||
digests, err := createDigests(n)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
dset := &Set{entries: digestEntries(make([]*digestEntry, 0, n))}
|
||||
for i := range digests {
|
||||
if err := dset.Add(digests[i]); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
ShortCodeTable(dset, shortLen)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAdd10(b *testing.B) {
|
||||
benchAddNTable(b, 10)
|
||||
}
|
||||
|
||||
func BenchmarkAdd100(b *testing.B) {
|
||||
benchAddNTable(b, 100)
|
||||
}
|
||||
|
||||
func BenchmarkAdd1000(b *testing.B) {
|
||||
benchAddNTable(b, 1000)
|
||||
}
|
||||
|
||||
func BenchmarkRemove10(b *testing.B) {
|
||||
benchRemoveNTable(b, 10)
|
||||
}
|
||||
|
||||
func BenchmarkRemove100(b *testing.B) {
|
||||
benchRemoveNTable(b, 100)
|
||||
}
|
||||
|
||||
func BenchmarkRemove1000(b *testing.B) {
|
||||
benchRemoveNTable(b, 1000)
|
||||
}
|
||||
|
||||
func BenchmarkLookup10(b *testing.B) {
|
||||
benchLookupNTable(b, 10, 12)
|
||||
}
|
||||
|
||||
func BenchmarkLookup100(b *testing.B) {
|
||||
benchLookupNTable(b, 100, 12)
|
||||
}
|
||||
|
||||
func BenchmarkLookup1000(b *testing.B) {
|
||||
benchLookupNTable(b, 1000, 12)
|
||||
}
|
||||
|
||||
func BenchmarkShortCode10(b *testing.B) {
|
||||
benchShortCodeNTable(b, 10, 12)
|
||||
}
|
||||
func BenchmarkShortCode100(b *testing.B) {
|
||||
benchShortCodeNTable(b, 100, 12)
|
||||
}
|
||||
func BenchmarkShortCode1000(b *testing.B) {
|
||||
benchShortCodeNTable(b, 1000, 12)
|
||||
}
|
||||
625
vendor/github.com/docker/distribution/reference/normalize_test.go
generated
vendored
625
vendor/github.com/docker/distribution/reference/normalize_test.go
generated
vendored
|
|
@ -1,625 +0,0 @@
|
|||
package reference
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/distribution/digestset"
|
||||
"github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
func TestValidateReferenceName(t *testing.T) {
|
||||
validRepoNames := []string{
|
||||
"docker/docker",
|
||||
"library/debian",
|
||||
"debian",
|
||||
"docker.io/docker/docker",
|
||||
"docker.io/library/debian",
|
||||
"docker.io/debian",
|
||||
"index.docker.io/docker/docker",
|
||||
"index.docker.io/library/debian",
|
||||
"index.docker.io/debian",
|
||||
"127.0.0.1:5000/docker/docker",
|
||||
"127.0.0.1:5000/library/debian",
|
||||
"127.0.0.1:5000/debian",
|
||||
"thisisthesongthatneverendsitgoesonandonandonthisisthesongthatnev",
|
||||
|
||||
// This test case was moved from invalid to valid since it is valid input
|
||||
// when specified with a hostname, it removes the ambiguity from about
|
||||
// whether the value is an identifier or repository name
|
||||
"docker.io/1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a",
|
||||
}
|
||||
invalidRepoNames := []string{
|
||||
"https://github.com/docker/docker",
|
||||
"docker/Docker",
|
||||
"-docker",
|
||||
"-docker/docker",
|
||||
"-docker.io/docker/docker",
|
||||
"docker///docker",
|
||||
"docker.io/docker/Docker",
|
||||
"docker.io/docker///docker",
|
||||
"1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a",
|
||||
}
|
||||
|
||||
for _, name := range invalidRepoNames {
|
||||
_, err := ParseNormalizedNamed(name)
|
||||
if err == nil {
|
||||
t.Fatalf("Expected invalid repo name for %q", name)
|
||||
}
|
||||
}
|
||||
|
||||
for _, name := range validRepoNames {
|
||||
_, err := ParseNormalizedNamed(name)
|
||||
if err != nil {
|
||||
t.Fatalf("Error parsing repo name %s, got: %q", name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateRemoteName(t *testing.T) {
|
||||
validRepositoryNames := []string{
|
||||
// Sanity check.
|
||||
"docker/docker",
|
||||
|
||||
// Allow 64-character non-hexadecimal names (hexadecimal names are forbidden).
|
||||
"thisisthesongthatneverendsitgoesonandonandonthisisthesongthatnev",
|
||||
|
||||
// Allow embedded hyphens.
|
||||
"docker-rules/docker",
|
||||
|
||||
// Allow multiple hyphens as well.
|
||||
"docker---rules/docker",
|
||||
|
||||
//Username doc and image name docker being tested.
|
||||
"doc/docker",
|
||||
|
||||
// single character names are now allowed.
|
||||
"d/docker",
|
||||
"jess/t",
|
||||
|
||||
// Consecutive underscores.
|
||||
"dock__er/docker",
|
||||
}
|
||||
for _, repositoryName := range validRepositoryNames {
|
||||
_, err := ParseNormalizedNamed(repositoryName)
|
||||
if err != nil {
|
||||
t.Errorf("Repository name should be valid: %v. Error: %v", repositoryName, err)
|
||||
}
|
||||
}
|
||||
|
||||
invalidRepositoryNames := []string{
|
||||
// Disallow capital letters.
|
||||
"docker/Docker",
|
||||
|
||||
// Only allow one slash.
|
||||
"docker///docker",
|
||||
|
||||
// Disallow 64-character hexadecimal.
|
||||
"1a3f5e7d9c1b3a5f7e9d1c3b5a7f9e1d3c5b7a9f1e3d5d7c9b1a3f5e7d9c1b3a",
|
||||
|
||||
// Disallow leading and trailing hyphens in namespace.
|
||||
"-docker/docker",
|
||||
"docker-/docker",
|
||||
"-docker-/docker",
|
||||
|
||||
// Don't allow underscores everywhere (as opposed to hyphens).
|
||||
"____/____",
|
||||
|
||||
"_docker/_docker",
|
||||
|
||||
// Disallow consecutive periods.
|
||||
"dock..er/docker",
|
||||
"dock_.er/docker",
|
||||
"dock-.er/docker",
|
||||
|
||||
// No repository.
|
||||
"docker/",
|
||||
|
||||
//namespace too long
|
||||
"this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255_this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255_this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255_this_is_not_a_valid_namespace_because_its_lenth_is_greater_than_255/docker",
|
||||
}
|
||||
for _, repositoryName := range invalidRepositoryNames {
|
||||
if _, err := ParseNormalizedNamed(repositoryName); err == nil {
|
||||
t.Errorf("Repository name should be invalid: %v", repositoryName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseRepositoryInfo(t *testing.T) {
|
||||
type tcase struct {
|
||||
RemoteName, FamiliarName, FullName, AmbiguousName, Domain string
|
||||
}
|
||||
|
||||
tcases := []tcase{
|
||||
{
|
||||
RemoteName: "fooo/bar",
|
||||
FamiliarName: "fooo/bar",
|
||||
FullName: "docker.io/fooo/bar",
|
||||
AmbiguousName: "index.docker.io/fooo/bar",
|
||||
Domain: "docker.io",
|
||||
},
|
||||
{
|
||||
RemoteName: "library/ubuntu",
|
||||
FamiliarName: "ubuntu",
|
||||
FullName: "docker.io/library/ubuntu",
|
||||
AmbiguousName: "library/ubuntu",
|
||||
Domain: "docker.io",
|
||||
},
|
||||
{
|
||||
RemoteName: "nonlibrary/ubuntu",
|
||||
FamiliarName: "nonlibrary/ubuntu",
|
||||
FullName: "docker.io/nonlibrary/ubuntu",
|
||||
AmbiguousName: "",
|
||||
Domain: "docker.io",
|
||||
},
|
||||
{
|
||||
RemoteName: "other/library",
|
||||
FamiliarName: "other/library",
|
||||
FullName: "docker.io/other/library",
|
||||
AmbiguousName: "",
|
||||
Domain: "docker.io",
|
||||
},
|
||||
{
|
||||
RemoteName: "private/moonbase",
|
||||
FamiliarName: "127.0.0.1:8000/private/moonbase",
|
||||
FullName: "127.0.0.1:8000/private/moonbase",
|
||||
AmbiguousName: "",
|
||||
Domain: "127.0.0.1:8000",
|
||||
},
|
||||
{
|
||||
RemoteName: "privatebase",
|
||||
FamiliarName: "127.0.0.1:8000/privatebase",
|
||||
FullName: "127.0.0.1:8000/privatebase",
|
||||
AmbiguousName: "",
|
||||
Domain: "127.0.0.1:8000",
|
||||
},
|
||||
{
|
||||
RemoteName: "private/moonbase",
|
||||
FamiliarName: "example.com/private/moonbase",
|
||||
FullName: "example.com/private/moonbase",
|
||||
AmbiguousName: "",
|
||||
Domain: "example.com",
|
||||
},
|
||||
{
|
||||
RemoteName: "privatebase",
|
||||
FamiliarName: "example.com/privatebase",
|
||||
FullName: "example.com/privatebase",
|
||||
AmbiguousName: "",
|
||||
Domain: "example.com",
|
||||
},
|
||||
{
|
||||
RemoteName: "private/moonbase",
|
||||
FamiliarName: "example.com:8000/private/moonbase",
|
||||
FullName: "example.com:8000/private/moonbase",
|
||||
AmbiguousName: "",
|
||||
Domain: "example.com:8000",
|
||||
},
|
||||
{
|
||||
RemoteName: "privatebasee",
|
||||
FamiliarName: "example.com:8000/privatebasee",
|
||||
FullName: "example.com:8000/privatebasee",
|
||||
AmbiguousName: "",
|
||||
Domain: "example.com:8000",
|
||||
},
|
||||
{
|
||||
RemoteName: "library/ubuntu-12.04-base",
|
||||
FamiliarName: "ubuntu-12.04-base",
|
||||
FullName: "docker.io/library/ubuntu-12.04-base",
|
||||
AmbiguousName: "index.docker.io/library/ubuntu-12.04-base",
|
||||
Domain: "docker.io",
|
||||
},
|
||||
{
|
||||
RemoteName: "library/foo",
|
||||
FamiliarName: "foo",
|
||||
FullName: "docker.io/library/foo",
|
||||
AmbiguousName: "docker.io/foo",
|
||||
Domain: "docker.io",
|
||||
},
|
||||
{
|
||||
RemoteName: "library/foo/bar",
|
||||
FamiliarName: "library/foo/bar",
|
||||
FullName: "docker.io/library/foo/bar",
|
||||
AmbiguousName: "",
|
||||
Domain: "docker.io",
|
||||
},
|
||||
{
|
||||
RemoteName: "store/foo/bar",
|
||||
FamiliarName: "store/foo/bar",
|
||||
FullName: "docker.io/store/foo/bar",
|
||||
AmbiguousName: "",
|
||||
Domain: "docker.io",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tcase := range tcases {
|
||||
refStrings := []string{tcase.FamiliarName, tcase.FullName}
|
||||
if tcase.AmbiguousName != "" {
|
||||
refStrings = append(refStrings, tcase.AmbiguousName)
|
||||
}
|
||||
|
||||
var refs []Named
|
||||
for _, r := range refStrings {
|
||||
named, err := ParseNormalizedNamed(r)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
refs = append(refs, named)
|
||||
}
|
||||
|
||||
for _, r := range refs {
|
||||
if expected, actual := tcase.FamiliarName, FamiliarName(r); expected != actual {
|
||||
t.Fatalf("Invalid normalized reference for %q. Expected %q, got %q", r, expected, actual)
|
||||
}
|
||||
if expected, actual := tcase.FullName, r.String(); expected != actual {
|
||||
t.Fatalf("Invalid canonical reference for %q. Expected %q, got %q", r, expected, actual)
|
||||
}
|
||||
if expected, actual := tcase.Domain, Domain(r); expected != actual {
|
||||
t.Fatalf("Invalid domain for %q. Expected %q, got %q", r, expected, actual)
|
||||
}
|
||||
if expected, actual := tcase.RemoteName, Path(r); expected != actual {
|
||||
t.Fatalf("Invalid remoteName for %q. Expected %q, got %q", r, expected, actual)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseReferenceWithTagAndDigest(t *testing.T) {
|
||||
shortRef := "busybox:latest@sha256:86e0e091d0da6bde2456dbb48306f3956bbeb2eae1b5b9a43045843f69fe4aaa"
|
||||
ref, err := ParseNormalizedNamed(shortRef)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if expected, actual := "docker.io/library/"+shortRef, ref.String(); actual != expected {
|
||||
t.Fatalf("Invalid parsed reference for %q: expected %q, got %q", ref, expected, actual)
|
||||
}
|
||||
|
||||
if _, isTagged := ref.(NamedTagged); !isTagged {
|
||||
t.Fatalf("Reference from %q should support tag", ref)
|
||||
}
|
||||
if _, isCanonical := ref.(Canonical); !isCanonical {
|
||||
t.Fatalf("Reference from %q should support digest", ref)
|
||||
}
|
||||
if expected, actual := shortRef, FamiliarString(ref); actual != expected {
|
||||
t.Fatalf("Invalid parsed reference for %q: expected %q, got %q", ref, expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidReferenceComponents(t *testing.T) {
|
||||
if _, err := ParseNormalizedNamed("-foo"); err == nil {
|
||||
t.Fatal("Expected WithName to detect invalid name")
|
||||
}
|
||||
ref, err := ParseNormalizedNamed("busybox")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := WithTag(ref, "-foo"); err == nil {
|
||||
t.Fatal("Expected WithName to detect invalid tag")
|
||||
}
|
||||
if _, err := WithDigest(ref, digest.Digest("foo")); err == nil {
|
||||
t.Fatal("Expected WithDigest to detect invalid digest")
|
||||
}
|
||||
}
|
||||
|
||||
func equalReference(r1, r2 Reference) bool {
|
||||
switch v1 := r1.(type) {
|
||||
case digestReference:
|
||||
if v2, ok := r2.(digestReference); ok {
|
||||
return v1 == v2
|
||||
}
|
||||
case repository:
|
||||
if v2, ok := r2.(repository); ok {
|
||||
return v1 == v2
|
||||
}
|
||||
case taggedReference:
|
||||
if v2, ok := r2.(taggedReference); ok {
|
||||
return v1 == v2
|
||||
}
|
||||
case canonicalReference:
|
||||
if v2, ok := r2.(canonicalReference); ok {
|
||||
return v1 == v2
|
||||
}
|
||||
case reference:
|
||||
if v2, ok := r2.(reference); ok {
|
||||
return v1 == v2
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func TestParseAnyReference(t *testing.T) {
|
||||
tcases := []struct {
|
||||
Reference string
|
||||
Equivalent string
|
||||
Expected Reference
|
||||
Digests []digest.Digest
|
||||
}{
|
||||
{
|
||||
Reference: "redis",
|
||||
Equivalent: "docker.io/library/redis",
|
||||
},
|
||||
{
|
||||
Reference: "redis:latest",
|
||||
Equivalent: "docker.io/library/redis:latest",
|
||||
},
|
||||
{
|
||||
Reference: "docker.io/library/redis:latest",
|
||||
Equivalent: "docker.io/library/redis:latest",
|
||||
},
|
||||
{
|
||||
Reference: "redis@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
|
||||
Equivalent: "docker.io/library/redis@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
|
||||
},
|
||||
{
|
||||
Reference: "docker.io/library/redis@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
|
||||
Equivalent: "docker.io/library/redis@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
|
||||
},
|
||||
{
|
||||
Reference: "dmcgowan/myapp",
|
||||
Equivalent: "docker.io/dmcgowan/myapp",
|
||||
},
|
||||
{
|
||||
Reference: "dmcgowan/myapp:latest",
|
||||
Equivalent: "docker.io/dmcgowan/myapp:latest",
|
||||
},
|
||||
{
|
||||
Reference: "docker.io/mcgowan/myapp:latest",
|
||||
Equivalent: "docker.io/mcgowan/myapp:latest",
|
||||
},
|
||||
{
|
||||
Reference: "dmcgowan/myapp@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
|
||||
Equivalent: "docker.io/dmcgowan/myapp@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
|
||||
},
|
||||
{
|
||||
Reference: "docker.io/dmcgowan/myapp@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
|
||||
Equivalent: "docker.io/dmcgowan/myapp@sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
|
||||
},
|
||||
{
|
||||
Reference: "dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
|
||||
Expected: digestReference("sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"),
|
||||
Equivalent: "sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
|
||||
},
|
||||
{
|
||||
Reference: "sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
|
||||
Expected: digestReference("sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"),
|
||||
Equivalent: "sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
|
||||
},
|
||||
{
|
||||
Reference: "dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9",
|
||||
Equivalent: "docker.io/library/dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9",
|
||||
},
|
||||
{
|
||||
Reference: "dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9",
|
||||
Expected: digestReference("sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"),
|
||||
Equivalent: "sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
|
||||
Digests: []digest.Digest{
|
||||
digest.Digest("sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"),
|
||||
digest.Digest("sha256:abcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"),
|
||||
},
|
||||
},
|
||||
{
|
||||
Reference: "dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9",
|
||||
Equivalent: "docker.io/library/dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9",
|
||||
Digests: []digest.Digest{
|
||||
digest.Digest("sha256:abcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"),
|
||||
},
|
||||
},
|
||||
{
|
||||
Reference: "dbcc1c",
|
||||
Expected: digestReference("sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"),
|
||||
Equivalent: "sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c",
|
||||
Digests: []digest.Digest{
|
||||
digest.Digest("sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"),
|
||||
digest.Digest("sha256:abcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"),
|
||||
},
|
||||
},
|
||||
{
|
||||
Reference: "dbcc1",
|
||||
Equivalent: "docker.io/library/dbcc1",
|
||||
Digests: []digest.Digest{
|
||||
digest.Digest("sha256:dbcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"),
|
||||
digest.Digest("sha256:abcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"),
|
||||
},
|
||||
},
|
||||
{
|
||||
Reference: "dbcc1c",
|
||||
Equivalent: "docker.io/library/dbcc1c",
|
||||
Digests: []digest.Digest{
|
||||
digest.Digest("sha256:abcc1c35ac38df41fd2f5e4130b32ffdb93ebae8b3dbe638c23575912276fc9c"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tcase := range tcases {
|
||||
var ref Reference
|
||||
var err error
|
||||
if len(tcase.Digests) == 0 {
|
||||
ref, err = ParseAnyReference(tcase.Reference)
|
||||
} else {
|
||||
ds := digestset.NewSet()
|
||||
for _, dgst := range tcase.Digests {
|
||||
if err := ds.Add(dgst); err != nil {
|
||||
t.Fatalf("Error adding digest %s: %v", dgst.String(), err)
|
||||
}
|
||||
}
|
||||
ref, err = ParseAnyReferenceWithSet(tcase.Reference, ds)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("Error parsing reference %s: %v", tcase.Reference, err)
|
||||
}
|
||||
if ref.String() != tcase.Equivalent {
|
||||
t.Fatalf("Unexpected string: %s, expected %s", ref.String(), tcase.Equivalent)
|
||||
}
|
||||
|
||||
expected := tcase.Expected
|
||||
if expected == nil {
|
||||
expected, err = Parse(tcase.Equivalent)
|
||||
if err != nil {
|
||||
t.Fatalf("Error parsing reference %s: %v", tcase.Equivalent, err)
|
||||
}
|
||||
}
|
||||
if !equalReference(ref, expected) {
|
||||
t.Errorf("Unexpected reference %#v, expected %#v", ref, expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizedSplitHostname(t *testing.T) {
|
||||
testcases := []struct {
|
||||
input string
|
||||
domain string
|
||||
name string
|
||||
}{
|
||||
{
|
||||
input: "test.com/foo",
|
||||
domain: "test.com",
|
||||
name: "foo",
|
||||
},
|
||||
{
|
||||
input: "test_com/foo",
|
||||
domain: "docker.io",
|
||||
name: "test_com/foo",
|
||||
},
|
||||
{
|
||||
input: "docker/migrator",
|
||||
domain: "docker.io",
|
||||
name: "docker/migrator",
|
||||
},
|
||||
{
|
||||
input: "test.com:8080/foo",
|
||||
domain: "test.com:8080",
|
||||
name: "foo",
|
||||
},
|
||||
{
|
||||
input: "test-com:8080/foo",
|
||||
domain: "test-com:8080",
|
||||
name: "foo",
|
||||
},
|
||||
{
|
||||
input: "foo",
|
||||
domain: "docker.io",
|
||||
name: "library/foo",
|
||||
},
|
||||
{
|
||||
input: "xn--n3h.com/foo",
|
||||
domain: "xn--n3h.com",
|
||||
name: "foo",
|
||||
},
|
||||
{
|
||||
input: "xn--n3h.com:18080/foo",
|
||||
domain: "xn--n3h.com:18080",
|
||||
name: "foo",
|
||||
},
|
||||
{
|
||||
input: "docker.io/foo",
|
||||
domain: "docker.io",
|
||||
name: "library/foo",
|
||||
},
|
||||
{
|
||||
input: "docker.io/library/foo",
|
||||
domain: "docker.io",
|
||||
name: "library/foo",
|
||||
},
|
||||
{
|
||||
input: "docker.io/library/foo/bar",
|
||||
domain: "docker.io",
|
||||
name: "library/foo/bar",
|
||||
},
|
||||
}
|
||||
for _, testcase := range testcases {
|
||||
failf := func(format string, v ...interface{}) {
|
||||
t.Logf(strconv.Quote(testcase.input)+": "+format, v...)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
named, err := ParseNormalizedNamed(testcase.input)
|
||||
if err != nil {
|
||||
failf("error parsing name: %s", err)
|
||||
}
|
||||
domain, name := SplitHostname(named)
|
||||
if domain != testcase.domain {
|
||||
failf("unexpected domain: got %q, expected %q", domain, testcase.domain)
|
||||
}
|
||||
if name != testcase.name {
|
||||
failf("unexpected name: got %q, expected %q", name, testcase.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatchError(t *testing.T) {
|
||||
named, err := ParseAnyReference("foo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = FamiliarMatch("[-x]", named)
|
||||
if err == nil {
|
||||
t.Fatalf("expected an error, got nothing")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatch(t *testing.T) {
|
||||
matchCases := []struct {
|
||||
reference string
|
||||
pattern string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
reference: "foo",
|
||||
pattern: "foo/**/ba[rz]",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
reference: "foo/any/bat",
|
||||
pattern: "foo/**/ba[rz]",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
reference: "foo/a/bar",
|
||||
pattern: "foo/**/ba[rz]",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
reference: "foo/b/baz",
|
||||
pattern: "foo/**/ba[rz]",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
reference: "foo/c/baz:tag",
|
||||
pattern: "foo/**/ba[rz]",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
reference: "foo/c/baz:tag",
|
||||
pattern: "foo/*/baz:tag",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
reference: "foo/c/baz:tag",
|
||||
pattern: "foo/c/baz:tag",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
reference: "example.com/foo/c/baz:tag",
|
||||
pattern: "*/foo/c/baz",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
reference: "example.com/foo/c/baz:tag",
|
||||
pattern: "example.com/foo/c/baz",
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
for _, c := range matchCases {
|
||||
named, err := ParseAnyReference(c.reference)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
actual, err := FamiliarMatch(c.pattern, named)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if actual != c.expected {
|
||||
t.Fatalf("expected %s match %s to be %v, was %v", c.reference, c.pattern, c.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
659
vendor/github.com/docker/distribution/reference/reference_test.go
generated
vendored
659
vendor/github.com/docker/distribution/reference/reference_test.go
generated
vendored
|
|
@ -1,659 +0,0 @@
|
|||
package reference
|
||||
|
||||
import (
|
||||
_ "crypto/sha256"
|
||||
_ "crypto/sha512"
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
func TestReferenceParse(t *testing.T) {
|
||||
// referenceTestcases is a unified set of testcases for
|
||||
// testing the parsing of references
|
||||
referenceTestcases := []struct {
|
||||
// input is the repository name or name component testcase
|
||||
input string
|
||||
// err is the error expected from Parse, or nil
|
||||
err error
|
||||
// repository is the string representation for the reference
|
||||
repository string
|
||||
// domain is the domain expected in the reference
|
||||
domain string
|
||||
// tag is the tag for the reference
|
||||
tag string
|
||||
// digest is the digest for the reference (enforces digest reference)
|
||||
digest string
|
||||
}{
|
||||
{
|
||||
input: "test_com",
|
||||
repository: "test_com",
|
||||
},
|
||||
{
|
||||
input: "test.com:tag",
|
||||
repository: "test.com",
|
||||
tag: "tag",
|
||||
},
|
||||
{
|
||||
input: "test.com:5000",
|
||||
repository: "test.com",
|
||||
tag: "5000",
|
||||
},
|
||||
{
|
||||
input: "test.com/repo:tag",
|
||||
domain: "test.com",
|
||||
repository: "test.com/repo",
|
||||
tag: "tag",
|
||||
},
|
||||
{
|
||||
input: "test:5000/repo",
|
||||
domain: "test:5000",
|
||||
repository: "test:5000/repo",
|
||||
},
|
||||
{
|
||||
input: "test:5000/repo:tag",
|
||||
domain: "test:5000",
|
||||
repository: "test:5000/repo",
|
||||
tag: "tag",
|
||||
},
|
||||
{
|
||||
input: "test:5000/repo@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
domain: "test:5000",
|
||||
repository: "test:5000/repo",
|
||||
digest: "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
},
|
||||
{
|
||||
input: "test:5000/repo:tag@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
domain: "test:5000",
|
||||
repository: "test:5000/repo",
|
||||
tag: "tag",
|
||||
digest: "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
},
|
||||
{
|
||||
input: "test:5000/repo",
|
||||
domain: "test:5000",
|
||||
repository: "test:5000/repo",
|
||||
},
|
||||
{
|
||||
input: "",
|
||||
err: ErrNameEmpty,
|
||||
},
|
||||
{
|
||||
input: ":justtag",
|
||||
err: ErrReferenceInvalidFormat,
|
||||
},
|
||||
{
|
||||
input: "@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
err: ErrReferenceInvalidFormat,
|
||||
},
|
||||
{
|
||||
input: "repo@sha256:ffffffffffffffffffffffffffffffffff",
|
||||
err: digest.ErrDigestInvalidLength,
|
||||
},
|
||||
{
|
||||
input: "validname@invaliddigest:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
err: digest.ErrDigestUnsupported,
|
||||
},
|
||||
{
|
||||
input: "Uppercase:tag",
|
||||
err: ErrNameContainsUppercase,
|
||||
},
|
||||
// FIXME "Uppercase" is incorrectly handled as a domain-name here, therefore passes.
|
||||
// See https://github.com/docker/distribution/pull/1778, and https://github.com/docker/docker/pull/20175
|
||||
//{
|
||||
// input: "Uppercase/lowercase:tag",
|
||||
// err: ErrNameContainsUppercase,
|
||||
//},
|
||||
{
|
||||
input: "test:5000/Uppercase/lowercase:tag",
|
||||
err: ErrNameContainsUppercase,
|
||||
},
|
||||
{
|
||||
input: "lowercase:Uppercase",
|
||||
repository: "lowercase",
|
||||
tag: "Uppercase",
|
||||
},
|
||||
{
|
||||
input: strings.Repeat("a/", 128) + "a:tag",
|
||||
err: ErrNameTooLong,
|
||||
},
|
||||
{
|
||||
input: strings.Repeat("a/", 127) + "a:tag-puts-this-over-max",
|
||||
domain: "a",
|
||||
repository: strings.Repeat("a/", 127) + "a",
|
||||
tag: "tag-puts-this-over-max",
|
||||
},
|
||||
{
|
||||
input: "aa/asdf$$^/aa",
|
||||
err: ErrReferenceInvalidFormat,
|
||||
},
|
||||
{
|
||||
input: "sub-dom1.foo.com/bar/baz/quux",
|
||||
domain: "sub-dom1.foo.com",
|
||||
repository: "sub-dom1.foo.com/bar/baz/quux",
|
||||
},
|
||||
{
|
||||
input: "sub-dom1.foo.com/bar/baz/quux:some-long-tag",
|
||||
domain: "sub-dom1.foo.com",
|
||||
repository: "sub-dom1.foo.com/bar/baz/quux",
|
||||
tag: "some-long-tag",
|
||||
},
|
||||
{
|
||||
input: "b.gcr.io/test.example.com/my-app:test.example.com",
|
||||
domain: "b.gcr.io",
|
||||
repository: "b.gcr.io/test.example.com/my-app",
|
||||
tag: "test.example.com",
|
||||
},
|
||||
{
|
||||
input: "xn--n3h.com/myimage:xn--n3h.com", // ☃.com in punycode
|
||||
domain: "xn--n3h.com",
|
||||
repository: "xn--n3h.com/myimage",
|
||||
tag: "xn--n3h.com",
|
||||
},
|
||||
{
|
||||
input: "xn--7o8h.com/myimage:xn--7o8h.com@sha512:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", // 🐳.com in punycode
|
||||
domain: "xn--7o8h.com",
|
||||
repository: "xn--7o8h.com/myimage",
|
||||
tag: "xn--7o8h.com",
|
||||
digest: "sha512:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
},
|
||||
{
|
||||
input: "foo_bar.com:8080",
|
||||
repository: "foo_bar.com",
|
||||
tag: "8080",
|
||||
},
|
||||
{
|
||||
input: "foo/foo_bar.com:8080",
|
||||
domain: "foo",
|
||||
repository: "foo/foo_bar.com",
|
||||
tag: "8080",
|
||||
},
|
||||
}
|
||||
for _, testcase := range referenceTestcases {
|
||||
failf := func(format string, v ...interface{}) {
|
||||
t.Logf(strconv.Quote(testcase.input)+": "+format, v...)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
repo, err := Parse(testcase.input)
|
||||
if testcase.err != nil {
|
||||
if err == nil {
|
||||
failf("missing expected error: %v", testcase.err)
|
||||
} else if testcase.err != err {
|
||||
failf("mismatched error: got %v, expected %v", err, testcase.err)
|
||||
}
|
||||
continue
|
||||
} else if err != nil {
|
||||
failf("unexpected parse error: %v", err)
|
||||
continue
|
||||
}
|
||||
if repo.String() != testcase.input {
|
||||
failf("mismatched repo: got %q, expected %q", repo.String(), testcase.input)
|
||||
}
|
||||
|
||||
if named, ok := repo.(Named); ok {
|
||||
if named.Name() != testcase.repository {
|
||||
failf("unexpected repository: got %q, expected %q", named.Name(), testcase.repository)
|
||||
}
|
||||
domain, _ := SplitHostname(named)
|
||||
if domain != testcase.domain {
|
||||
failf("unexpected domain: got %q, expected %q", domain, testcase.domain)
|
||||
}
|
||||
} else if testcase.repository != "" || testcase.domain != "" {
|
||||
failf("expected named type, got %T", repo)
|
||||
}
|
||||
|
||||
tagged, ok := repo.(Tagged)
|
||||
if testcase.tag != "" {
|
||||
if ok {
|
||||
if tagged.Tag() != testcase.tag {
|
||||
failf("unexpected tag: got %q, expected %q", tagged.Tag(), testcase.tag)
|
||||
}
|
||||
} else {
|
||||
failf("expected tagged type, got %T", repo)
|
||||
}
|
||||
} else if ok {
|
||||
failf("unexpected tagged type")
|
||||
}
|
||||
|
||||
digested, ok := repo.(Digested)
|
||||
if testcase.digest != "" {
|
||||
if ok {
|
||||
if digested.Digest().String() != testcase.digest {
|
||||
failf("unexpected digest: got %q, expected %q", digested.Digest().String(), testcase.digest)
|
||||
}
|
||||
} else {
|
||||
failf("expected digested type, got %T", repo)
|
||||
}
|
||||
} else if ok {
|
||||
failf("unexpected digested type")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// TestWithNameFailure tests cases where WithName should fail. Cases where it
|
||||
// should succeed are covered by TestSplitHostname, below.
|
||||
func TestWithNameFailure(t *testing.T) {
|
||||
testcases := []struct {
|
||||
input string
|
||||
err error
|
||||
}{
|
||||
{
|
||||
input: "",
|
||||
err: ErrNameEmpty,
|
||||
},
|
||||
{
|
||||
input: ":justtag",
|
||||
err: ErrReferenceInvalidFormat,
|
||||
},
|
||||
{
|
||||
input: "@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
err: ErrReferenceInvalidFormat,
|
||||
},
|
||||
{
|
||||
input: "validname@invaliddigest:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
err: ErrReferenceInvalidFormat,
|
||||
},
|
||||
{
|
||||
input: strings.Repeat("a/", 128) + "a:tag",
|
||||
err: ErrNameTooLong,
|
||||
},
|
||||
{
|
||||
input: "aa/asdf$$^/aa",
|
||||
err: ErrReferenceInvalidFormat,
|
||||
},
|
||||
}
|
||||
for _, testcase := range testcases {
|
||||
failf := func(format string, v ...interface{}) {
|
||||
t.Logf(strconv.Quote(testcase.input)+": "+format, v...)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
_, err := WithName(testcase.input)
|
||||
if err == nil {
|
||||
failf("no error parsing name. expected: %s", testcase.err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitHostname(t *testing.T) {
|
||||
testcases := []struct {
|
||||
input string
|
||||
domain string
|
||||
name string
|
||||
}{
|
||||
{
|
||||
input: "test.com/foo",
|
||||
domain: "test.com",
|
||||
name: "foo",
|
||||
},
|
||||
{
|
||||
input: "test_com/foo",
|
||||
domain: "",
|
||||
name: "test_com/foo",
|
||||
},
|
||||
{
|
||||
input: "test:8080/foo",
|
||||
domain: "test:8080",
|
||||
name: "foo",
|
||||
},
|
||||
{
|
||||
input: "test.com:8080/foo",
|
||||
domain: "test.com:8080",
|
||||
name: "foo",
|
||||
},
|
||||
{
|
||||
input: "test-com:8080/foo",
|
||||
domain: "test-com:8080",
|
||||
name: "foo",
|
||||
},
|
||||
{
|
||||
input: "xn--n3h.com:18080/foo",
|
||||
domain: "xn--n3h.com:18080",
|
||||
name: "foo",
|
||||
},
|
||||
}
|
||||
for _, testcase := range testcases {
|
||||
failf := func(format string, v ...interface{}) {
|
||||
t.Logf(strconv.Quote(testcase.input)+": "+format, v...)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
named, err := WithName(testcase.input)
|
||||
if err != nil {
|
||||
failf("error parsing name: %s", err)
|
||||
}
|
||||
domain, name := SplitHostname(named)
|
||||
if domain != testcase.domain {
|
||||
failf("unexpected domain: got %q, expected %q", domain, testcase.domain)
|
||||
}
|
||||
if name != testcase.name {
|
||||
failf("unexpected name: got %q, expected %q", name, testcase.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type serializationType struct {
|
||||
Description string
|
||||
Field Field
|
||||
}
|
||||
|
||||
func TestSerialization(t *testing.T) {
|
||||
testcases := []struct {
|
||||
description string
|
||||
input string
|
||||
name string
|
||||
tag string
|
||||
digest string
|
||||
err error
|
||||
}{
|
||||
{
|
||||
description: "empty value",
|
||||
err: ErrNameEmpty,
|
||||
},
|
||||
{
|
||||
description: "just a name",
|
||||
input: "example.com:8000/named",
|
||||
name: "example.com:8000/named",
|
||||
},
|
||||
{
|
||||
description: "name with a tag",
|
||||
input: "example.com:8000/named:tagged",
|
||||
name: "example.com:8000/named",
|
||||
tag: "tagged",
|
||||
},
|
||||
{
|
||||
description: "name with digest",
|
||||
input: "other.com/named@sha256:1234567890098765432112345667890098765432112345667890098765432112",
|
||||
name: "other.com/named",
|
||||
digest: "sha256:1234567890098765432112345667890098765432112345667890098765432112",
|
||||
},
|
||||
}
|
||||
for _, testcase := range testcases {
|
||||
failf := func(format string, v ...interface{}) {
|
||||
t.Logf(strconv.Quote(testcase.input)+": "+format, v...)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
m := map[string]string{
|
||||
"Description": testcase.description,
|
||||
"Field": testcase.input,
|
||||
}
|
||||
b, err := json.Marshal(m)
|
||||
if err != nil {
|
||||
failf("error marshalling: %v", err)
|
||||
}
|
||||
t := serializationType{}
|
||||
|
||||
if err := json.Unmarshal(b, &t); err != nil {
|
||||
if testcase.err == nil {
|
||||
failf("error unmarshalling: %v", err)
|
||||
}
|
||||
if err != testcase.err {
|
||||
failf("wrong error, expected %v, got %v", testcase.err, err)
|
||||
}
|
||||
|
||||
continue
|
||||
} else if testcase.err != nil {
|
||||
failf("expected error unmarshalling: %v", testcase.err)
|
||||
}
|
||||
|
||||
if t.Description != testcase.description {
|
||||
failf("wrong description, expected %q, got %q", testcase.description, t.Description)
|
||||
}
|
||||
|
||||
ref := t.Field.Reference()
|
||||
|
||||
if named, ok := ref.(Named); ok {
|
||||
if named.Name() != testcase.name {
|
||||
failf("unexpected repository: got %q, expected %q", named.Name(), testcase.name)
|
||||
}
|
||||
} else if testcase.name != "" {
|
||||
failf("expected named type, got %T", ref)
|
||||
}
|
||||
|
||||
tagged, ok := ref.(Tagged)
|
||||
if testcase.tag != "" {
|
||||
if ok {
|
||||
if tagged.Tag() != testcase.tag {
|
||||
failf("unexpected tag: got %q, expected %q", tagged.Tag(), testcase.tag)
|
||||
}
|
||||
} else {
|
||||
failf("expected tagged type, got %T", ref)
|
||||
}
|
||||
} else if ok {
|
||||
failf("unexpected tagged type")
|
||||
}
|
||||
|
||||
digested, ok := ref.(Digested)
|
||||
if testcase.digest != "" {
|
||||
if ok {
|
||||
if digested.Digest().String() != testcase.digest {
|
||||
failf("unexpected digest: got %q, expected %q", digested.Digest().String(), testcase.digest)
|
||||
}
|
||||
} else {
|
||||
failf("expected digested type, got %T", ref)
|
||||
}
|
||||
} else if ok {
|
||||
failf("unexpected digested type")
|
||||
}
|
||||
|
||||
t = serializationType{
|
||||
Description: testcase.description,
|
||||
Field: AsField(ref),
|
||||
}
|
||||
|
||||
b2, err := json.Marshal(t)
|
||||
if err != nil {
|
||||
failf("error marshing serialization type: %v", err)
|
||||
}
|
||||
|
||||
if string(b) != string(b2) {
|
||||
failf("unexpected serialized value: expected %q, got %q", string(b), string(b2))
|
||||
}
|
||||
|
||||
// Ensure t.Field is not implementing "Reference" directly, getting
|
||||
// around the Reference type system
|
||||
var fieldInterface interface{} = t.Field
|
||||
if _, ok := fieldInterface.(Reference); ok {
|
||||
failf("field should not implement Reference interface")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithTag(t *testing.T) {
|
||||
testcases := []struct {
|
||||
name string
|
||||
digest digest.Digest
|
||||
tag string
|
||||
combined string
|
||||
}{
|
||||
{
|
||||
name: "test.com/foo",
|
||||
tag: "tag",
|
||||
combined: "test.com/foo:tag",
|
||||
},
|
||||
{
|
||||
name: "foo",
|
||||
tag: "tag2",
|
||||
combined: "foo:tag2",
|
||||
},
|
||||
{
|
||||
name: "test.com:8000/foo",
|
||||
tag: "tag4",
|
||||
combined: "test.com:8000/foo:tag4",
|
||||
},
|
||||
{
|
||||
name: "test.com:8000/foo",
|
||||
tag: "TAG5",
|
||||
combined: "test.com:8000/foo:TAG5",
|
||||
},
|
||||
{
|
||||
name: "test.com:8000/foo",
|
||||
digest: "sha256:1234567890098765432112345667890098765",
|
||||
tag: "TAG5",
|
||||
combined: "test.com:8000/foo:TAG5@sha256:1234567890098765432112345667890098765",
|
||||
},
|
||||
}
|
||||
for _, testcase := range testcases {
|
||||
failf := func(format string, v ...interface{}) {
|
||||
t.Logf(strconv.Quote(testcase.name)+": "+format, v...)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
named, err := WithName(testcase.name)
|
||||
if err != nil {
|
||||
failf("error parsing name: %s", err)
|
||||
}
|
||||
if testcase.digest != "" {
|
||||
canonical, err := WithDigest(named, testcase.digest)
|
||||
if err != nil {
|
||||
failf("error adding digest")
|
||||
}
|
||||
named = canonical
|
||||
}
|
||||
|
||||
tagged, err := WithTag(named, testcase.tag)
|
||||
if err != nil {
|
||||
failf("WithTag failed: %s", err)
|
||||
}
|
||||
if tagged.String() != testcase.combined {
|
||||
failf("unexpected: got %q, expected %q", tagged.String(), testcase.combined)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithDigest(t *testing.T) {
|
||||
testcases := []struct {
|
||||
name string
|
||||
digest digest.Digest
|
||||
tag string
|
||||
combined string
|
||||
}{
|
||||
{
|
||||
name: "test.com/foo",
|
||||
digest: "sha256:1234567890098765432112345667890098765",
|
||||
combined: "test.com/foo@sha256:1234567890098765432112345667890098765",
|
||||
},
|
||||
{
|
||||
name: "foo",
|
||||
digest: "sha256:1234567890098765432112345667890098765",
|
||||
combined: "foo@sha256:1234567890098765432112345667890098765",
|
||||
},
|
||||
{
|
||||
name: "test.com:8000/foo",
|
||||
digest: "sha256:1234567890098765432112345667890098765",
|
||||
combined: "test.com:8000/foo@sha256:1234567890098765432112345667890098765",
|
||||
},
|
||||
{
|
||||
name: "test.com:8000/foo",
|
||||
digest: "sha256:1234567890098765432112345667890098765",
|
||||
tag: "latest",
|
||||
combined: "test.com:8000/foo:latest@sha256:1234567890098765432112345667890098765",
|
||||
},
|
||||
}
|
||||
for _, testcase := range testcases {
|
||||
failf := func(format string, v ...interface{}) {
|
||||
t.Logf(strconv.Quote(testcase.name)+": "+format, v...)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
named, err := WithName(testcase.name)
|
||||
if err != nil {
|
||||
failf("error parsing name: %s", err)
|
||||
}
|
||||
if testcase.tag != "" {
|
||||
tagged, err := WithTag(named, testcase.tag)
|
||||
if err != nil {
|
||||
failf("error adding tag")
|
||||
}
|
||||
named = tagged
|
||||
}
|
||||
digested, err := WithDigest(named, testcase.digest)
|
||||
if err != nil {
|
||||
failf("WithDigest failed: %s", err)
|
||||
}
|
||||
if digested.String() != testcase.combined {
|
||||
failf("unexpected: got %q, expected %q", digested.String(), testcase.combined)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseNamed(t *testing.T) {
|
||||
testcases := []struct {
|
||||
input string
|
||||
domain string
|
||||
name string
|
||||
err error
|
||||
}{
|
||||
{
|
||||
input: "test.com/foo",
|
||||
domain: "test.com",
|
||||
name: "foo",
|
||||
},
|
||||
{
|
||||
input: "test:8080/foo",
|
||||
domain: "test:8080",
|
||||
name: "foo",
|
||||
},
|
||||
{
|
||||
input: "test_com/foo",
|
||||
err: ErrNameNotCanonical,
|
||||
},
|
||||
{
|
||||
input: "test.com",
|
||||
err: ErrNameNotCanonical,
|
||||
},
|
||||
{
|
||||
input: "foo",
|
||||
err: ErrNameNotCanonical,
|
||||
},
|
||||
{
|
||||
input: "library/foo",
|
||||
err: ErrNameNotCanonical,
|
||||
},
|
||||
{
|
||||
input: "docker.io/library/foo",
|
||||
domain: "docker.io",
|
||||
name: "library/foo",
|
||||
},
|
||||
// Ambiguous case, parser will add "library/" to foo
|
||||
{
|
||||
input: "docker.io/foo",
|
||||
err: ErrNameNotCanonical,
|
||||
},
|
||||
}
|
||||
for _, testcase := range testcases {
|
||||
failf := func(format string, v ...interface{}) {
|
||||
t.Logf(strconv.Quote(testcase.input)+": "+format, v...)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
named, err := ParseNamed(testcase.input)
|
||||
if err != nil && testcase.err == nil {
|
||||
failf("error parsing name: %s", err)
|
||||
continue
|
||||
} else if err == nil && testcase.err != nil {
|
||||
failf("parsing succeded: expected error %v", testcase.err)
|
||||
continue
|
||||
} else if err != testcase.err {
|
||||
failf("unexpected error %v, expected %v", err, testcase.err)
|
||||
continue
|
||||
} else if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
domain, name := SplitHostname(named)
|
||||
if domain != testcase.domain {
|
||||
failf("unexpected domain: got %q, expected %q", domain, testcase.domain)
|
||||
}
|
||||
if name != testcase.name {
|
||||
failf("unexpected name: got %q, expected %q", name, testcase.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
553
vendor/github.com/docker/distribution/reference/regexp_test.go
generated
vendored
553
vendor/github.com/docker/distribution/reference/regexp_test.go
generated
vendored
|
|
@ -1,553 +0,0 @@
|
|||
package reference
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type regexpMatch struct {
|
||||
input string
|
||||
match bool
|
||||
subs []string
|
||||
}
|
||||
|
||||
func checkRegexp(t *testing.T, r *regexp.Regexp, m regexpMatch) {
|
||||
matches := r.FindStringSubmatch(m.input)
|
||||
if m.match && matches != nil {
|
||||
if len(matches) != (r.NumSubexp()+1) || matches[0] != m.input {
|
||||
t.Fatalf("Bad match result %#v for %q", matches, m.input)
|
||||
}
|
||||
if len(matches) < (len(m.subs) + 1) {
|
||||
t.Errorf("Expected %d sub matches, only have %d for %q", len(m.subs), len(matches)-1, m.input)
|
||||
}
|
||||
for i := range m.subs {
|
||||
if m.subs[i] != matches[i+1] {
|
||||
t.Errorf("Unexpected submatch %d: %q, expected %q for %q", i+1, matches[i+1], m.subs[i], m.input)
|
||||
}
|
||||
}
|
||||
} else if m.match {
|
||||
t.Errorf("Expected match for %q", m.input)
|
||||
} else if matches != nil {
|
||||
t.Errorf("Unexpected match for %q", m.input)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDomainRegexp(t *testing.T) {
|
||||
hostcases := []regexpMatch{
|
||||
{
|
||||
input: "test.com",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "test.com:10304",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "test.com:http",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "localhost",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "localhost:8080",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "a",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "a.b",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "ab.cd.com",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "a-b.com",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "-ab.com",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "ab-.com",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "ab.c-om",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "ab.-com",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "ab.com-",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "0101.com",
|
||||
match: true, // TODO(dmcgowan): valid if this should be allowed
|
||||
},
|
||||
{
|
||||
input: "001a.com",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "b.gbc.io:443",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "b.gbc.io",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "xn--n3h.com", // ☃.com in punycode
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "Asdf.com", // uppercase character
|
||||
match: true,
|
||||
},
|
||||
}
|
||||
r := regexp.MustCompile(`^` + DomainRegexp.String() + `$`)
|
||||
for i := range hostcases {
|
||||
checkRegexp(t, r, hostcases[i])
|
||||
}
|
||||
}
|
||||
|
||||
func TestFullNameRegexp(t *testing.T) {
|
||||
if anchoredNameRegexp.NumSubexp() != 2 {
|
||||
t.Fatalf("anchored name regexp should have two submatches: %v, %v != 2",
|
||||
anchoredNameRegexp, anchoredNameRegexp.NumSubexp())
|
||||
}
|
||||
|
||||
testcases := []regexpMatch{
|
||||
{
|
||||
input: "",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "short",
|
||||
match: true,
|
||||
subs: []string{"", "short"},
|
||||
},
|
||||
{
|
||||
input: "simple/name",
|
||||
match: true,
|
||||
subs: []string{"simple", "name"},
|
||||
},
|
||||
{
|
||||
input: "library/ubuntu",
|
||||
match: true,
|
||||
subs: []string{"library", "ubuntu"},
|
||||
},
|
||||
{
|
||||
input: "docker/stevvooe/app",
|
||||
match: true,
|
||||
subs: []string{"docker", "stevvooe/app"},
|
||||
},
|
||||
{
|
||||
input: "aa/aa/aa/aa/aa/aa/aa/aa/aa/bb/bb/bb/bb/bb/bb",
|
||||
match: true,
|
||||
subs: []string{"aa", "aa/aa/aa/aa/aa/aa/aa/aa/bb/bb/bb/bb/bb/bb"},
|
||||
},
|
||||
{
|
||||
input: "aa/aa/bb/bb/bb",
|
||||
match: true,
|
||||
subs: []string{"aa", "aa/bb/bb/bb"},
|
||||
},
|
||||
{
|
||||
input: "a/a/a/a",
|
||||
match: true,
|
||||
subs: []string{"a", "a/a/a"},
|
||||
},
|
||||
{
|
||||
input: "a/a/a/a/",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "a//a/a",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "a",
|
||||
match: true,
|
||||
subs: []string{"", "a"},
|
||||
},
|
||||
{
|
||||
input: "a/aa",
|
||||
match: true,
|
||||
subs: []string{"a", "aa"},
|
||||
},
|
||||
{
|
||||
input: "a/aa/a",
|
||||
match: true,
|
||||
subs: []string{"a", "aa/a"},
|
||||
},
|
||||
{
|
||||
input: "foo.com",
|
||||
match: true,
|
||||
subs: []string{"", "foo.com"},
|
||||
},
|
||||
{
|
||||
input: "foo.com/",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "foo.com:8080/bar",
|
||||
match: true,
|
||||
subs: []string{"foo.com:8080", "bar"},
|
||||
},
|
||||
{
|
||||
input: "foo.com:http/bar",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "foo.com/bar",
|
||||
match: true,
|
||||
subs: []string{"foo.com", "bar"},
|
||||
},
|
||||
{
|
||||
input: "foo.com/bar/baz",
|
||||
match: true,
|
||||
subs: []string{"foo.com", "bar/baz"},
|
||||
},
|
||||
{
|
||||
input: "localhost:8080/bar",
|
||||
match: true,
|
||||
subs: []string{"localhost:8080", "bar"},
|
||||
},
|
||||
{
|
||||
input: "sub-dom1.foo.com/bar/baz/quux",
|
||||
match: true,
|
||||
subs: []string{"sub-dom1.foo.com", "bar/baz/quux"},
|
||||
},
|
||||
{
|
||||
input: "blog.foo.com/bar/baz",
|
||||
match: true,
|
||||
subs: []string{"blog.foo.com", "bar/baz"},
|
||||
},
|
||||
{
|
||||
input: "a^a",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "aa/asdf$$^/aa",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "asdf$$^/aa",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "aa-a/a",
|
||||
match: true,
|
||||
subs: []string{"aa-a", "a"},
|
||||
},
|
||||
{
|
||||
input: strings.Repeat("a/", 128) + "a",
|
||||
match: true,
|
||||
subs: []string{"a", strings.Repeat("a/", 127) + "a"},
|
||||
},
|
||||
{
|
||||
input: "a-/a/a/a",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "foo.com/a-/a/a",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "-foo/bar",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "foo/bar-",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "foo-/bar",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "foo/-bar",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "_foo/bar",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "foo_bar",
|
||||
match: true,
|
||||
subs: []string{"", "foo_bar"},
|
||||
},
|
||||
{
|
||||
input: "foo_bar.com",
|
||||
match: true,
|
||||
subs: []string{"", "foo_bar.com"},
|
||||
},
|
||||
{
|
||||
input: "foo_bar.com:8080",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "foo_bar.com:8080/app",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "foo.com/foo_bar",
|
||||
match: true,
|
||||
subs: []string{"foo.com", "foo_bar"},
|
||||
},
|
||||
{
|
||||
input: "____/____",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "_docker/_docker",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "docker_/docker_",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "b.gcr.io/test.example.com/my-app",
|
||||
match: true,
|
||||
subs: []string{"b.gcr.io", "test.example.com/my-app"},
|
||||
},
|
||||
{
|
||||
input: "xn--n3h.com/myimage", // ☃.com in punycode
|
||||
match: true,
|
||||
subs: []string{"xn--n3h.com", "myimage"},
|
||||
},
|
||||
{
|
||||
input: "xn--7o8h.com/myimage", // 🐳.com in punycode
|
||||
match: true,
|
||||
subs: []string{"xn--7o8h.com", "myimage"},
|
||||
},
|
||||
{
|
||||
input: "example.com/xn--7o8h.com/myimage", // 🐳.com in punycode
|
||||
match: true,
|
||||
subs: []string{"example.com", "xn--7o8h.com/myimage"},
|
||||
},
|
||||
{
|
||||
input: "example.com/some_separator__underscore/myimage",
|
||||
match: true,
|
||||
subs: []string{"example.com", "some_separator__underscore/myimage"},
|
||||
},
|
||||
{
|
||||
input: "example.com/__underscore/myimage",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "example.com/..dots/myimage",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "example.com/.dots/myimage",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "example.com/nodouble..dots/myimage",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "example.com/nodouble..dots/myimage",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "docker./docker",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: ".docker/docker",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "docker-/docker",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "-docker/docker",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "do..cker/docker",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "do__cker:8080/docker",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "do__cker/docker",
|
||||
match: true,
|
||||
subs: []string{"", "do__cker/docker"},
|
||||
},
|
||||
{
|
||||
input: "b.gcr.io/test.example.com/my-app",
|
||||
match: true,
|
||||
subs: []string{"b.gcr.io", "test.example.com/my-app"},
|
||||
},
|
||||
{
|
||||
input: "registry.io/foo/project--id.module--name.ver---sion--name",
|
||||
match: true,
|
||||
subs: []string{"registry.io", "foo/project--id.module--name.ver---sion--name"},
|
||||
},
|
||||
{
|
||||
input: "Asdf.com/foo/bar", // uppercase character in hostname
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "Foo/FarB", // uppercase characters in remote name
|
||||
match: false,
|
||||
},
|
||||
}
|
||||
for i := range testcases {
|
||||
checkRegexp(t, anchoredNameRegexp, testcases[i])
|
||||
}
|
||||
}
|
||||
|
||||
func TestReferenceRegexp(t *testing.T) {
|
||||
if ReferenceRegexp.NumSubexp() != 3 {
|
||||
t.Fatalf("anchored name regexp should have three submatches: %v, %v != 3",
|
||||
ReferenceRegexp, ReferenceRegexp.NumSubexp())
|
||||
}
|
||||
|
||||
testcases := []regexpMatch{
|
||||
{
|
||||
input: "registry.com:8080/myapp:tag",
|
||||
match: true,
|
||||
subs: []string{"registry.com:8080/myapp", "tag", ""},
|
||||
},
|
||||
{
|
||||
input: "registry.com:8080/myapp@sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912",
|
||||
match: true,
|
||||
subs: []string{"registry.com:8080/myapp", "", "sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912"},
|
||||
},
|
||||
{
|
||||
input: "registry.com:8080/myapp:tag2@sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912",
|
||||
match: true,
|
||||
subs: []string{"registry.com:8080/myapp", "tag2", "sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912"},
|
||||
},
|
||||
{
|
||||
input: "registry.com:8080/myapp@sha256:badbadbadbad",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "registry.com:8080/myapp:invalid~tag",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "bad_hostname.com:8080/myapp:tag",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input:// localhost treated as name, missing tag with 8080 as tag
|
||||
"localhost:8080@sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912",
|
||||
match: true,
|
||||
subs: []string{"localhost", "8080", "sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912"},
|
||||
},
|
||||
{
|
||||
input: "localhost:8080/name@sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912",
|
||||
match: true,
|
||||
subs: []string{"localhost:8080/name", "", "sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912"},
|
||||
},
|
||||
{
|
||||
input: "localhost:http/name@sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
// localhost will be treated as an image name without a host
|
||||
input: "localhost@sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912",
|
||||
match: true,
|
||||
subs: []string{"localhost", "", "sha256:be178c0543eb17f5f3043021c9e5fcf30285e557a4fc309cce97ff9ca6182912"},
|
||||
},
|
||||
{
|
||||
input: "registry.com:8080/myapp@bad",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "registry.com:8080/myapp@2bad",
|
||||
match: false, // TODO(dmcgowan): Support this as valid
|
||||
},
|
||||
}
|
||||
|
||||
for i := range testcases {
|
||||
checkRegexp(t, ReferenceRegexp, testcases[i])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestIdentifierRegexp(t *testing.T) {
|
||||
fullCases := []regexpMatch{
|
||||
{
|
||||
input: "da304e823d8ca2b9d863a3c897baeb852ba21ea9a9f1414736394ae7fcaf9821",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "7EC43B381E5AEFE6E04EFB0B3F0693FF2A4A50652D64AEC573905F2DB5889A1C",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "da304e823d8ca2b9d863a3c897baeb852ba21ea9a9f1414736394ae7fcaf",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "sha256:da304e823d8ca2b9d863a3c897baeb852ba21ea9a9f1414736394ae7fcaf9821",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "da304e823d8ca2b9d863a3c897baeb852ba21ea9a9f1414736394ae7fcaf98218482",
|
||||
match: false,
|
||||
},
|
||||
}
|
||||
|
||||
shortCases := []regexpMatch{
|
||||
{
|
||||
input: "da304e823d8ca2b9d863a3c897baeb852ba21ea9a9f1414736394ae7fcaf9821",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "7EC43B381E5AEFE6E04EFB0B3F0693FF2A4A50652D64AEC573905F2DB5889A1C",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "da304e823d8ca2b9d863a3c897baeb852ba21ea9a9f1414736394ae7fcaf",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
input: "sha256:da304e823d8ca2b9d863a3c897baeb852ba21ea9a9f1414736394ae7fcaf9821",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "da304e823d8ca2b9d863a3c897baeb852ba21ea9a9f1414736394ae7fcaf98218482",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "da304",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
input: "da304e",
|
||||
match: true,
|
||||
},
|
||||
}
|
||||
|
||||
for i := range fullCases {
|
||||
checkRegexp(t, anchoredIdentifierRegexp, fullCases[i])
|
||||
}
|
||||
|
||||
for i := range shortCases {
|
||||
checkRegexp(t, anchoredShortIdentifierRegexp, shortCases[i])
|
||||
}
|
||||
}
|
||||
108
vendor/github.com/docker/spdystream/priority_test.go
generated
vendored
108
vendor/github.com/docker/spdystream/priority_test.go
generated
vendored
|
|
@ -1,108 +0,0 @@
|
|||
package spdystream
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/spdystream/spdy"
|
||||
)
|
||||
|
||||
func TestPriorityQueueOrdering(t *testing.T) {
|
||||
queue := NewPriorityFrameQueue(150)
|
||||
data1 := &spdy.DataFrame{}
|
||||
data2 := &spdy.DataFrame{}
|
||||
data3 := &spdy.DataFrame{}
|
||||
data4 := &spdy.DataFrame{}
|
||||
queue.Push(data1, 2)
|
||||
queue.Push(data2, 1)
|
||||
queue.Push(data3, 1)
|
||||
queue.Push(data4, 0)
|
||||
|
||||
if queue.Pop() != data4 {
|
||||
t.Fatalf("Wrong order, expected data4 first")
|
||||
}
|
||||
if queue.Pop() != data2 {
|
||||
t.Fatalf("Wrong order, expected data2 second")
|
||||
}
|
||||
if queue.Pop() != data3 {
|
||||
t.Fatalf("Wrong order, expected data3 third")
|
||||
}
|
||||
if queue.Pop() != data1 {
|
||||
t.Fatalf("Wrong order, expected data1 fourth")
|
||||
}
|
||||
|
||||
// Insert 50 Medium priority frames
|
||||
for i := spdy.StreamId(50); i < 100; i++ {
|
||||
queue.Push(&spdy.DataFrame{StreamId: i}, 1)
|
||||
}
|
||||
// Insert 50 low priority frames
|
||||
for i := spdy.StreamId(100); i < 150; i++ {
|
||||
queue.Push(&spdy.DataFrame{StreamId: i}, 2)
|
||||
}
|
||||
// Insert 50 high priority frames
|
||||
for i := spdy.StreamId(0); i < 50; i++ {
|
||||
queue.Push(&spdy.DataFrame{StreamId: i}, 0)
|
||||
}
|
||||
|
||||
for i := spdy.StreamId(0); i < 150; i++ {
|
||||
frame := queue.Pop()
|
||||
if frame.(*spdy.DataFrame).StreamId != i {
|
||||
t.Fatalf("Wrong frame\nActual: %d\nExpecting: %d", frame.(*spdy.DataFrame).StreamId, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriorityQueueSync(t *testing.T) {
|
||||
queue := NewPriorityFrameQueue(150)
|
||||
var wg sync.WaitGroup
|
||||
insertRange := func(start, stop spdy.StreamId, priority uint8) {
|
||||
for i := start; i < stop; i++ {
|
||||
queue.Push(&spdy.DataFrame{StreamId: i}, priority)
|
||||
}
|
||||
wg.Done()
|
||||
}
|
||||
wg.Add(3)
|
||||
go insertRange(spdy.StreamId(100), spdy.StreamId(150), 2)
|
||||
go insertRange(spdy.StreamId(0), spdy.StreamId(50), 0)
|
||||
go insertRange(spdy.StreamId(50), spdy.StreamId(100), 1)
|
||||
|
||||
wg.Wait()
|
||||
for i := spdy.StreamId(0); i < 150; i++ {
|
||||
frame := queue.Pop()
|
||||
if frame.(*spdy.DataFrame).StreamId != i {
|
||||
t.Fatalf("Wrong frame\nActual: %d\nExpecting: %d", frame.(*spdy.DataFrame).StreamId, i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPriorityQueueBlocking(t *testing.T) {
|
||||
queue := NewPriorityFrameQueue(15)
|
||||
for i := 0; i < 15; i++ {
|
||||
queue.Push(&spdy.DataFrame{}, 2)
|
||||
}
|
||||
doneChan := make(chan bool)
|
||||
go func() {
|
||||
queue.Push(&spdy.DataFrame{}, 2)
|
||||
close(doneChan)
|
||||
}()
|
||||
select {
|
||||
case <-doneChan:
|
||||
t.Fatalf("Push succeeded, expected to block")
|
||||
case <-time.After(time.Millisecond):
|
||||
break
|
||||
}
|
||||
|
||||
queue.Pop()
|
||||
|
||||
select {
|
||||
case <-doneChan:
|
||||
break
|
||||
case <-time.After(time.Millisecond):
|
||||
t.Fatalf("Push should have succeeded, but timeout reached")
|
||||
}
|
||||
|
||||
for i := 0; i < 15; i++ {
|
||||
queue.Pop()
|
||||
}
|
||||
}
|
||||
644
vendor/github.com/docker/spdystream/spdy/spdy_test.go
generated
vendored
644
vendor/github.com/docker/spdystream/spdy/spdy_test.go
generated
vendored
|
|
@ -1,644 +0,0 @@
|
|||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package spdy
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/zlib"
|
||||
"encoding/base64"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var HeadersFixture = http.Header{
|
||||
"Url": []string{"http://www.google.com/"},
|
||||
"Method": []string{"get"},
|
||||
"Version": []string{"http/1.1"},
|
||||
}
|
||||
|
||||
func TestHeaderParsing(t *testing.T) {
|
||||
var headerValueBlockBuf bytes.Buffer
|
||||
writeHeaderValueBlock(&headerValueBlockBuf, HeadersFixture)
|
||||
const bogusStreamId = 1
|
||||
newHeaders, err := parseHeaderValueBlock(&headerValueBlockBuf, bogusStreamId)
|
||||
if err != nil {
|
||||
t.Fatal("parseHeaderValueBlock:", err)
|
||||
}
|
||||
if !reflect.DeepEqual(HeadersFixture, newHeaders) {
|
||||
t.Fatal("got: ", newHeaders, "\nwant: ", HeadersFixture)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateParseSynStreamFrameCompressionDisable(t *testing.T) {
|
||||
buffer := new(bytes.Buffer)
|
||||
// Fixture framer for no compression test.
|
||||
framer := &Framer{
|
||||
headerCompressionDisabled: true,
|
||||
w: buffer,
|
||||
headerBuf: new(bytes.Buffer),
|
||||
r: buffer,
|
||||
}
|
||||
synStreamFrame := SynStreamFrame{
|
||||
CFHeader: ControlFrameHeader{
|
||||
version: Version,
|
||||
frameType: TypeSynStream,
|
||||
},
|
||||
StreamId: 2,
|
||||
Headers: HeadersFixture,
|
||||
}
|
||||
if err := framer.WriteFrame(&synStreamFrame); err != nil {
|
||||
t.Fatal("WriteFrame without compression:", err)
|
||||
}
|
||||
frame, err := framer.ReadFrame()
|
||||
if err != nil {
|
||||
t.Fatal("ReadFrame without compression:", err)
|
||||
}
|
||||
parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
|
||||
if !ok {
|
||||
t.Fatal("Parsed incorrect frame type:", frame)
|
||||
}
|
||||
if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
|
||||
t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateParseSynStreamFrameCompressionEnable(t *testing.T) {
|
||||
buffer := new(bytes.Buffer)
|
||||
framer, err := NewFramer(buffer, buffer)
|
||||
synStreamFrame := SynStreamFrame{
|
||||
CFHeader: ControlFrameHeader{
|
||||
version: Version,
|
||||
frameType: TypeSynStream,
|
||||
},
|
||||
StreamId: 2,
|
||||
Headers: HeadersFixture,
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create new framer:", err)
|
||||
}
|
||||
if err := framer.WriteFrame(&synStreamFrame); err != nil {
|
||||
t.Fatal("WriteFrame with compression:", err)
|
||||
}
|
||||
frame, err := framer.ReadFrame()
|
||||
if err != nil {
|
||||
t.Fatal("ReadFrame with compression:", err)
|
||||
}
|
||||
parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
|
||||
if !ok {
|
||||
t.Fatal("Parsed incorrect frame type:", frame)
|
||||
}
|
||||
if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
|
||||
t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateParseSynReplyFrameCompressionDisable(t *testing.T) {
|
||||
buffer := new(bytes.Buffer)
|
||||
framer := &Framer{
|
||||
headerCompressionDisabled: true,
|
||||
w: buffer,
|
||||
headerBuf: new(bytes.Buffer),
|
||||
r: buffer,
|
||||
}
|
||||
synReplyFrame := SynReplyFrame{
|
||||
CFHeader: ControlFrameHeader{
|
||||
version: Version,
|
||||
frameType: TypeSynReply,
|
||||
},
|
||||
StreamId: 2,
|
||||
Headers: HeadersFixture,
|
||||
}
|
||||
if err := framer.WriteFrame(&synReplyFrame); err != nil {
|
||||
t.Fatal("WriteFrame without compression:", err)
|
||||
}
|
||||
frame, err := framer.ReadFrame()
|
||||
if err != nil {
|
||||
t.Fatal("ReadFrame without compression:", err)
|
||||
}
|
||||
parsedSynReplyFrame, ok := frame.(*SynReplyFrame)
|
||||
if !ok {
|
||||
t.Fatal("Parsed incorrect frame type:", frame)
|
||||
}
|
||||
if !reflect.DeepEqual(synReplyFrame, *parsedSynReplyFrame) {
|
||||
t.Fatal("got: ", *parsedSynReplyFrame, "\nwant: ", synReplyFrame)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateParseSynReplyFrameCompressionEnable(t *testing.T) {
|
||||
buffer := new(bytes.Buffer)
|
||||
framer, err := NewFramer(buffer, buffer)
|
||||
synReplyFrame := SynReplyFrame{
|
||||
CFHeader: ControlFrameHeader{
|
||||
version: Version,
|
||||
frameType: TypeSynReply,
|
||||
},
|
||||
StreamId: 2,
|
||||
Headers: HeadersFixture,
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create new framer:", err)
|
||||
}
|
||||
if err := framer.WriteFrame(&synReplyFrame); err != nil {
|
||||
t.Fatal("WriteFrame with compression:", err)
|
||||
}
|
||||
frame, err := framer.ReadFrame()
|
||||
if err != nil {
|
||||
t.Fatal("ReadFrame with compression:", err)
|
||||
}
|
||||
parsedSynReplyFrame, ok := frame.(*SynReplyFrame)
|
||||
if !ok {
|
||||
t.Fatal("Parsed incorrect frame type:", frame)
|
||||
}
|
||||
if !reflect.DeepEqual(synReplyFrame, *parsedSynReplyFrame) {
|
||||
t.Fatal("got: ", *parsedSynReplyFrame, "\nwant: ", synReplyFrame)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateParseRstStream(t *testing.T) {
|
||||
buffer := new(bytes.Buffer)
|
||||
framer, err := NewFramer(buffer, buffer)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create new framer:", err)
|
||||
}
|
||||
rstStreamFrame := RstStreamFrame{
|
||||
CFHeader: ControlFrameHeader{
|
||||
version: Version,
|
||||
frameType: TypeRstStream,
|
||||
},
|
||||
StreamId: 1,
|
||||
Status: InvalidStream,
|
||||
}
|
||||
if err := framer.WriteFrame(&rstStreamFrame); err != nil {
|
||||
t.Fatal("WriteFrame:", err)
|
||||
}
|
||||
frame, err := framer.ReadFrame()
|
||||
if err != nil {
|
||||
t.Fatal("ReadFrame:", err)
|
||||
}
|
||||
parsedRstStreamFrame, ok := frame.(*RstStreamFrame)
|
||||
if !ok {
|
||||
t.Fatal("Parsed incorrect frame type:", frame)
|
||||
}
|
||||
if !reflect.DeepEqual(rstStreamFrame, *parsedRstStreamFrame) {
|
||||
t.Fatal("got: ", *parsedRstStreamFrame, "\nwant: ", rstStreamFrame)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateParseSettings(t *testing.T) {
|
||||
buffer := new(bytes.Buffer)
|
||||
framer, err := NewFramer(buffer, buffer)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create new framer:", err)
|
||||
}
|
||||
settingsFrame := SettingsFrame{
|
||||
CFHeader: ControlFrameHeader{
|
||||
version: Version,
|
||||
frameType: TypeSettings,
|
||||
},
|
||||
FlagIdValues: []SettingsFlagIdValue{
|
||||
{FlagSettingsPersistValue, SettingsCurrentCwnd, 10},
|
||||
{FlagSettingsPersisted, SettingsUploadBandwidth, 1},
|
||||
},
|
||||
}
|
||||
if err := framer.WriteFrame(&settingsFrame); err != nil {
|
||||
t.Fatal("WriteFrame:", err)
|
||||
}
|
||||
frame, err := framer.ReadFrame()
|
||||
if err != nil {
|
||||
t.Fatal("ReadFrame:", err)
|
||||
}
|
||||
parsedSettingsFrame, ok := frame.(*SettingsFrame)
|
||||
if !ok {
|
||||
t.Fatal("Parsed incorrect frame type:", frame)
|
||||
}
|
||||
if !reflect.DeepEqual(settingsFrame, *parsedSettingsFrame) {
|
||||
t.Fatal("got: ", *parsedSettingsFrame, "\nwant: ", settingsFrame)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateParsePing(t *testing.T) {
|
||||
buffer := new(bytes.Buffer)
|
||||
framer, err := NewFramer(buffer, buffer)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create new framer:", err)
|
||||
}
|
||||
pingFrame := PingFrame{
|
||||
CFHeader: ControlFrameHeader{
|
||||
version: Version,
|
||||
frameType: TypePing,
|
||||
},
|
||||
Id: 31337,
|
||||
}
|
||||
if err := framer.WriteFrame(&pingFrame); err != nil {
|
||||
t.Fatal("WriteFrame:", err)
|
||||
}
|
||||
if pingFrame.CFHeader.Flags != 0 {
|
||||
t.Fatal("Incorrect frame type:", pingFrame)
|
||||
}
|
||||
frame, err := framer.ReadFrame()
|
||||
if err != nil {
|
||||
t.Fatal("ReadFrame:", err)
|
||||
}
|
||||
parsedPingFrame, ok := frame.(*PingFrame)
|
||||
if !ok {
|
||||
t.Fatal("Parsed incorrect frame type:", frame)
|
||||
}
|
||||
if parsedPingFrame.CFHeader.Flags != 0 {
|
||||
t.Fatal("Parsed incorrect frame type:", parsedPingFrame)
|
||||
}
|
||||
if !reflect.DeepEqual(pingFrame, *parsedPingFrame) {
|
||||
t.Fatal("got: ", *parsedPingFrame, "\nwant: ", pingFrame)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateParseGoAway(t *testing.T) {
|
||||
buffer := new(bytes.Buffer)
|
||||
framer, err := NewFramer(buffer, buffer)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create new framer:", err)
|
||||
}
|
||||
goAwayFrame := GoAwayFrame{
|
||||
CFHeader: ControlFrameHeader{
|
||||
version: Version,
|
||||
frameType: TypeGoAway,
|
||||
},
|
||||
LastGoodStreamId: 31337,
|
||||
Status: 1,
|
||||
}
|
||||
if err := framer.WriteFrame(&goAwayFrame); err != nil {
|
||||
t.Fatal("WriteFrame:", err)
|
||||
}
|
||||
if goAwayFrame.CFHeader.Flags != 0 {
|
||||
t.Fatal("Incorrect frame type:", goAwayFrame)
|
||||
}
|
||||
if goAwayFrame.CFHeader.length != 8 {
|
||||
t.Fatal("Incorrect frame type:", goAwayFrame)
|
||||
}
|
||||
frame, err := framer.ReadFrame()
|
||||
if err != nil {
|
||||
t.Fatal("ReadFrame:", err)
|
||||
}
|
||||
parsedGoAwayFrame, ok := frame.(*GoAwayFrame)
|
||||
if !ok {
|
||||
t.Fatal("Parsed incorrect frame type:", frame)
|
||||
}
|
||||
if parsedGoAwayFrame.CFHeader.Flags != 0 {
|
||||
t.Fatal("Incorrect frame type:", parsedGoAwayFrame)
|
||||
}
|
||||
if parsedGoAwayFrame.CFHeader.length != 8 {
|
||||
t.Fatal("Incorrect frame type:", parsedGoAwayFrame)
|
||||
}
|
||||
if !reflect.DeepEqual(goAwayFrame, *parsedGoAwayFrame) {
|
||||
t.Fatal("got: ", *parsedGoAwayFrame, "\nwant: ", goAwayFrame)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateParseHeadersFrame(t *testing.T) {
|
||||
buffer := new(bytes.Buffer)
|
||||
framer := &Framer{
|
||||
headerCompressionDisabled: true,
|
||||
w: buffer,
|
||||
headerBuf: new(bytes.Buffer),
|
||||
r: buffer,
|
||||
}
|
||||
headersFrame := HeadersFrame{
|
||||
CFHeader: ControlFrameHeader{
|
||||
version: Version,
|
||||
frameType: TypeHeaders,
|
||||
},
|
||||
StreamId: 2,
|
||||
}
|
||||
headersFrame.Headers = HeadersFixture
|
||||
if err := framer.WriteFrame(&headersFrame); err != nil {
|
||||
t.Fatal("WriteFrame without compression:", err)
|
||||
}
|
||||
frame, err := framer.ReadFrame()
|
||||
if err != nil {
|
||||
t.Fatal("ReadFrame without compression:", err)
|
||||
}
|
||||
parsedHeadersFrame, ok := frame.(*HeadersFrame)
|
||||
if !ok {
|
||||
t.Fatal("Parsed incorrect frame type:", frame)
|
||||
}
|
||||
if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
|
||||
t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateParseHeadersFrameCompressionEnable(t *testing.T) {
|
||||
buffer := new(bytes.Buffer)
|
||||
headersFrame := HeadersFrame{
|
||||
CFHeader: ControlFrameHeader{
|
||||
version: Version,
|
||||
frameType: TypeHeaders,
|
||||
},
|
||||
StreamId: 2,
|
||||
}
|
||||
headersFrame.Headers = HeadersFixture
|
||||
|
||||
framer, err := NewFramer(buffer, buffer)
|
||||
if err := framer.WriteFrame(&headersFrame); err != nil {
|
||||
t.Fatal("WriteFrame with compression:", err)
|
||||
}
|
||||
frame, err := framer.ReadFrame()
|
||||
if err != nil {
|
||||
t.Fatal("ReadFrame with compression:", err)
|
||||
}
|
||||
parsedHeadersFrame, ok := frame.(*HeadersFrame)
|
||||
if !ok {
|
||||
t.Fatal("Parsed incorrect frame type:", frame)
|
||||
}
|
||||
if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
|
||||
t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateParseWindowUpdateFrame(t *testing.T) {
|
||||
buffer := new(bytes.Buffer)
|
||||
framer, err := NewFramer(buffer, buffer)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create new framer:", err)
|
||||
}
|
||||
windowUpdateFrame := WindowUpdateFrame{
|
||||
CFHeader: ControlFrameHeader{
|
||||
version: Version,
|
||||
frameType: TypeWindowUpdate,
|
||||
},
|
||||
StreamId: 31337,
|
||||
DeltaWindowSize: 1,
|
||||
}
|
||||
if err := framer.WriteFrame(&windowUpdateFrame); err != nil {
|
||||
t.Fatal("WriteFrame:", err)
|
||||
}
|
||||
if windowUpdateFrame.CFHeader.Flags != 0 {
|
||||
t.Fatal("Incorrect frame type:", windowUpdateFrame)
|
||||
}
|
||||
if windowUpdateFrame.CFHeader.length != 8 {
|
||||
t.Fatal("Incorrect frame type:", windowUpdateFrame)
|
||||
}
|
||||
frame, err := framer.ReadFrame()
|
||||
if err != nil {
|
||||
t.Fatal("ReadFrame:", err)
|
||||
}
|
||||
parsedWindowUpdateFrame, ok := frame.(*WindowUpdateFrame)
|
||||
if !ok {
|
||||
t.Fatal("Parsed incorrect frame type:", frame)
|
||||
}
|
||||
if parsedWindowUpdateFrame.CFHeader.Flags != 0 {
|
||||
t.Fatal("Incorrect frame type:", parsedWindowUpdateFrame)
|
||||
}
|
||||
if parsedWindowUpdateFrame.CFHeader.length != 8 {
|
||||
t.Fatal("Incorrect frame type:", parsedWindowUpdateFrame)
|
||||
}
|
||||
if !reflect.DeepEqual(windowUpdateFrame, *parsedWindowUpdateFrame) {
|
||||
t.Fatal("got: ", *parsedWindowUpdateFrame, "\nwant: ", windowUpdateFrame)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateParseDataFrame(t *testing.T) {
|
||||
buffer := new(bytes.Buffer)
|
||||
framer, err := NewFramer(buffer, buffer)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create new framer:", err)
|
||||
}
|
||||
dataFrame := DataFrame{
|
||||
StreamId: 1,
|
||||
Data: []byte{'h', 'e', 'l', 'l', 'o'},
|
||||
}
|
||||
if err := framer.WriteFrame(&dataFrame); err != nil {
|
||||
t.Fatal("WriteFrame:", err)
|
||||
}
|
||||
frame, err := framer.ReadFrame()
|
||||
if err != nil {
|
||||
t.Fatal("ReadFrame:", err)
|
||||
}
|
||||
parsedDataFrame, ok := frame.(*DataFrame)
|
||||
if !ok {
|
||||
t.Fatal("Parsed incorrect frame type:", frame)
|
||||
}
|
||||
if !reflect.DeepEqual(dataFrame, *parsedDataFrame) {
|
||||
t.Fatal("got: ", *parsedDataFrame, "\nwant: ", dataFrame)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompressionContextAcrossFrames(t *testing.T) {
|
||||
buffer := new(bytes.Buffer)
|
||||
framer, err := NewFramer(buffer, buffer)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create new framer:", err)
|
||||
}
|
||||
headersFrame := HeadersFrame{
|
||||
CFHeader: ControlFrameHeader{
|
||||
version: Version,
|
||||
frameType: TypeHeaders,
|
||||
},
|
||||
StreamId: 2,
|
||||
Headers: HeadersFixture,
|
||||
}
|
||||
if err := framer.WriteFrame(&headersFrame); err != nil {
|
||||
t.Fatal("WriteFrame (HEADERS):", err)
|
||||
}
|
||||
synStreamFrame := SynStreamFrame{
|
||||
ControlFrameHeader{
|
||||
Version,
|
||||
TypeSynStream,
|
||||
0, // Flags
|
||||
0, // length
|
||||
},
|
||||
2, // StreamId
|
||||
0, // AssociatedTOStreamID
|
||||
0, // Priority
|
||||
1, // Slot
|
||||
nil, // Headers
|
||||
}
|
||||
synStreamFrame.Headers = HeadersFixture
|
||||
|
||||
if err := framer.WriteFrame(&synStreamFrame); err != nil {
|
||||
t.Fatal("WriteFrame (SYN_STREAM):", err)
|
||||
}
|
||||
frame, err := framer.ReadFrame()
|
||||
if err != nil {
|
||||
t.Fatal("ReadFrame (HEADERS):", err, buffer.Bytes())
|
||||
}
|
||||
parsedHeadersFrame, ok := frame.(*HeadersFrame)
|
||||
if !ok {
|
||||
t.Fatalf("expected HeadersFrame; got %T %v", frame, frame)
|
||||
}
|
||||
if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
|
||||
t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
|
||||
}
|
||||
frame, err = framer.ReadFrame()
|
||||
if err != nil {
|
||||
t.Fatal("ReadFrame (SYN_STREAM):", err, buffer.Bytes())
|
||||
}
|
||||
parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
|
||||
if !ok {
|
||||
t.Fatalf("expected SynStreamFrame; got %T %v", frame, frame)
|
||||
}
|
||||
if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
|
||||
t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMultipleSPDYFrames(t *testing.T) {
|
||||
// Initialize the framers.
|
||||
pr1, pw1 := io.Pipe()
|
||||
pr2, pw2 := io.Pipe()
|
||||
writer, err := NewFramer(pw1, pr2)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create writer:", err)
|
||||
}
|
||||
reader, err := NewFramer(pw2, pr1)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create reader:", err)
|
||||
}
|
||||
|
||||
// Set up the frames we're actually transferring.
|
||||
headersFrame := HeadersFrame{
|
||||
CFHeader: ControlFrameHeader{
|
||||
version: Version,
|
||||
frameType: TypeHeaders,
|
||||
},
|
||||
StreamId: 2,
|
||||
Headers: HeadersFixture,
|
||||
}
|
||||
synStreamFrame := SynStreamFrame{
|
||||
CFHeader: ControlFrameHeader{
|
||||
version: Version,
|
||||
frameType: TypeSynStream,
|
||||
},
|
||||
StreamId: 2,
|
||||
Headers: HeadersFixture,
|
||||
}
|
||||
|
||||
// Start the goroutines to write the frames.
|
||||
go func() {
|
||||
if err := writer.WriteFrame(&headersFrame); err != nil {
|
||||
t.Fatal("WriteFrame (HEADERS): ", err)
|
||||
}
|
||||
if err := writer.WriteFrame(&synStreamFrame); err != nil {
|
||||
t.Fatal("WriteFrame (SYN_STREAM): ", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Read the frames and verify they look as expected.
|
||||
frame, err := reader.ReadFrame()
|
||||
if err != nil {
|
||||
t.Fatal("ReadFrame (HEADERS): ", err)
|
||||
}
|
||||
parsedHeadersFrame, ok := frame.(*HeadersFrame)
|
||||
if !ok {
|
||||
t.Fatal("Parsed incorrect frame type:", frame)
|
||||
}
|
||||
if !reflect.DeepEqual(headersFrame, *parsedHeadersFrame) {
|
||||
t.Fatal("got: ", *parsedHeadersFrame, "\nwant: ", headersFrame)
|
||||
}
|
||||
frame, err = reader.ReadFrame()
|
||||
if err != nil {
|
||||
t.Fatal("ReadFrame (SYN_STREAM):", err)
|
||||
}
|
||||
parsedSynStreamFrame, ok := frame.(*SynStreamFrame)
|
||||
if !ok {
|
||||
t.Fatal("Parsed incorrect frame type.")
|
||||
}
|
||||
if !reflect.DeepEqual(synStreamFrame, *parsedSynStreamFrame) {
|
||||
t.Fatal("got: ", *parsedSynStreamFrame, "\nwant: ", synStreamFrame)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadMalformedZlibHeader(t *testing.T) {
|
||||
// These were constructed by corrupting the first byte of the zlib
|
||||
// header after writing.
|
||||
malformedStructs := map[string]string{
|
||||
"SynStreamFrame": "gAIAAQAAABgAAAACAAAAAAAAF/nfolGyYmAAAAAA//8=",
|
||||
"SynReplyFrame": "gAIAAgAAABQAAAACAAAX+d+iUbJiYAAAAAD//w==",
|
||||
"HeadersFrame": "gAIACAAAABQAAAACAAAX+d+iUbJiYAAAAAD//w==",
|
||||
}
|
||||
for name, bad := range malformedStructs {
|
||||
b, err := base64.StdEncoding.DecodeString(bad)
|
||||
if err != nil {
|
||||
t.Errorf("Unable to decode base64 encoded frame %s: %v", name, err)
|
||||
}
|
||||
buf := bytes.NewBuffer(b)
|
||||
reader, err := NewFramer(buf, buf)
|
||||
if err != nil {
|
||||
t.Fatalf("NewFramer: %v", err)
|
||||
}
|
||||
_, err = reader.ReadFrame()
|
||||
if err != zlib.ErrHeader {
|
||||
t.Errorf("Frame %s, expected: %#v, actual: %#v", name, zlib.ErrHeader, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: these tests are too weak for updating SPDY spec. Fix me.
|
||||
|
||||
type zeroStream struct {
|
||||
frame Frame
|
||||
encoded string
|
||||
}
|
||||
|
||||
var streamIdZeroFrames = map[string]zeroStream{
|
||||
"SynStreamFrame": {
|
||||
&SynStreamFrame{StreamId: 0},
|
||||
"gAIAAQAAABgAAAAAAAAAAAAAePnfolGyYmAAAAAA//8=",
|
||||
},
|
||||
"SynReplyFrame": {
|
||||
&SynReplyFrame{StreamId: 0},
|
||||
"gAIAAgAAABQAAAAAAAB4+d+iUbJiYAAAAAD//w==",
|
||||
},
|
||||
"RstStreamFrame": {
|
||||
&RstStreamFrame{StreamId: 0},
|
||||
"gAIAAwAAAAgAAAAAAAAAAA==",
|
||||
},
|
||||
"HeadersFrame": {
|
||||
&HeadersFrame{StreamId: 0},
|
||||
"gAIACAAAABQAAAAAAAB4+d+iUbJiYAAAAAD//w==",
|
||||
},
|
||||
"DataFrame": {
|
||||
&DataFrame{StreamId: 0},
|
||||
"AAAAAAAAAAA=",
|
||||
},
|
||||
"PingFrame": {
|
||||
&PingFrame{Id: 0},
|
||||
"gAIABgAAAAQAAAAA",
|
||||
},
|
||||
}
|
||||
|
||||
func TestNoZeroStreamId(t *testing.T) {
|
||||
t.Log("skipping") // TODO: update to work with SPDY3
|
||||
return
|
||||
|
||||
for name, f := range streamIdZeroFrames {
|
||||
b, err := base64.StdEncoding.DecodeString(f.encoded)
|
||||
if err != nil {
|
||||
t.Errorf("Unable to decode base64 encoded frame %s: %v", f, err)
|
||||
continue
|
||||
}
|
||||
framer, err := NewFramer(ioutil.Discard, bytes.NewReader(b))
|
||||
if err != nil {
|
||||
t.Fatalf("NewFramer: %v", err)
|
||||
}
|
||||
err = framer.WriteFrame(f.frame)
|
||||
checkZeroStreamId(t, name, "WriteFrame", err)
|
||||
|
||||
_, err = framer.ReadFrame()
|
||||
checkZeroStreamId(t, name, "ReadFrame", err)
|
||||
}
|
||||
}
|
||||
|
||||
func checkZeroStreamId(t *testing.T, frame string, method string, err error) {
|
||||
if err == nil {
|
||||
t.Errorf("%s ZeroStreamId, no error on %s", method, frame)
|
||||
return
|
||||
}
|
||||
eerr, ok := err.(*Error)
|
||||
if !ok || eerr.Err != ZeroStreamId {
|
||||
t.Errorf("%s ZeroStreamId, incorrect error %#v, frame %s", method, eerr, frame)
|
||||
}
|
||||
}
|
||||
113
vendor/github.com/docker/spdystream/spdy_bench_test.go
generated
vendored
113
vendor/github.com/docker/spdystream/spdy_bench_test.go
generated
vendored
|
|
@ -1,113 +0,0 @@
|
|||
package spdystream
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func configureServer() (io.Closer, string, *sync.WaitGroup) {
|
||||
authenticated = true
|
||||
wg := &sync.WaitGroup{}
|
||||
server, listen, serverErr := runServer(wg)
|
||||
|
||||
if serverErr != nil {
|
||||
panic(serverErr)
|
||||
}
|
||||
|
||||
return server, listen, wg
|
||||
}
|
||||
|
||||
func BenchmarkDial10000(b *testing.B) {
|
||||
server, addr, wg := configureServer()
|
||||
|
||||
defer func() {
|
||||
server.Close()
|
||||
wg.Wait()
|
||||
}()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
conn, dialErr := net.Dial("tcp", addr)
|
||||
if dialErr != nil {
|
||||
panic(fmt.Sprintf("Error dialing server: %s", dialErr))
|
||||
}
|
||||
conn.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDialWithSPDYStream10000(b *testing.B) {
|
||||
server, addr, wg := configureServer()
|
||||
|
||||
defer func() {
|
||||
server.Close()
|
||||
wg.Wait()
|
||||
}()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
conn, dialErr := net.Dial("tcp", addr)
|
||||
if dialErr != nil {
|
||||
b.Fatalf("Error dialing server: %s", dialErr)
|
||||
}
|
||||
|
||||
spdyConn, spdyErr := NewConnection(conn, false)
|
||||
if spdyErr != nil {
|
||||
b.Fatalf("Error creating spdy connection: %s", spdyErr)
|
||||
}
|
||||
go spdyConn.Serve(NoOpStreamHandler)
|
||||
|
||||
closeErr := spdyConn.Close()
|
||||
if closeErr != nil {
|
||||
b.Fatalf("Error closing connection: %s, closeErr")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func benchmarkStreamWithDataAndSize(size uint64, b *testing.B) {
|
||||
server, addr, wg := configureServer()
|
||||
|
||||
defer func() {
|
||||
server.Close()
|
||||
wg.Wait()
|
||||
}()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
conn, dialErr := net.Dial("tcp", addr)
|
||||
if dialErr != nil {
|
||||
b.Fatalf("Error dialing server: %s", dialErr)
|
||||
}
|
||||
|
||||
spdyConn, spdyErr := NewConnection(conn, false)
|
||||
if spdyErr != nil {
|
||||
b.Fatalf("Error creating spdy connection: %s", spdyErr)
|
||||
}
|
||||
|
||||
go spdyConn.Serve(MirrorStreamHandler)
|
||||
|
||||
stream, err := spdyConn.CreateStream(http.Header{}, nil, false)
|
||||
|
||||
writer := make([]byte, size)
|
||||
|
||||
stream.Write(writer)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
reader := make([]byte, size)
|
||||
stream.Read(reader)
|
||||
|
||||
stream.Close()
|
||||
|
||||
closeErr := spdyConn.Close()
|
||||
if closeErr != nil {
|
||||
b.Fatalf("Error closing connection: %s, closeErr")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkStreamWith1Byte10000(b *testing.B) { benchmarkStreamWithDataAndSize(1, b) }
|
||||
func BenchmarkStreamWith1KiloByte10000(b *testing.B) { benchmarkStreamWithDataAndSize(1024, b) }
|
||||
func BenchmarkStreamWith1Megabyte10000(b *testing.B) { benchmarkStreamWithDataAndSize(1024*1024, b) }
|
||||
1171
vendor/github.com/docker/spdystream/spdy_test.go
generated
vendored
1171
vendor/github.com/docker/spdystream/spdy_test.go
generated
vendored
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue