2015-07-13 20:08:13 +00:00
|
|
|
package storage
|
|
|
|
|
|
|
|
import (
|
2016-07-13 23:41:51 +00:00
|
|
|
"fmt"
|
2015-07-17 18:42:47 +00:00
|
|
|
"io"
|
2015-07-13 20:08:13 +00:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/docker/distribution"
|
|
|
|
"github.com/docker/distribution/context"
|
2016-07-13 23:39:34 +00:00
|
|
|
"github.com/docker/distribution/digest"
|
|
|
|
"github.com/docker/distribution/reference"
|
2015-07-13 20:08:13 +00:00
|
|
|
"github.com/docker/distribution/registry/storage/cache/memory"
|
|
|
|
"github.com/docker/distribution/registry/storage/driver"
|
|
|
|
"github.com/docker/distribution/registry/storage/driver/inmemory"
|
2016-07-13 23:39:34 +00:00
|
|
|
"github.com/docker/distribution/testutil"
|
2015-07-13 20:08:13 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type setupEnv struct {
|
|
|
|
ctx context.Context
|
|
|
|
driver driver.StorageDriver
|
|
|
|
expected []string
|
|
|
|
registry distribution.Namespace
|
|
|
|
}
|
|
|
|
|
|
|
|
func setupFS(t *testing.T) *setupEnv {
|
|
|
|
d := inmemory.New()
|
|
|
|
ctx := context.Background()
|
2015-08-18 17:56:27 +00:00
|
|
|
registry, err := NewRegistry(ctx, d, BlobDescriptorCacheProvider(memory.NewInMemoryBlobDescriptorCacheProvider()), EnableRedirect)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("error creating registry: %v", err)
|
|
|
|
}
|
2015-07-13 20:08:13 +00:00
|
|
|
|
|
|
|
repos := []string{
|
2016-07-13 23:39:34 +00:00
|
|
|
"foo/a",
|
|
|
|
"foo/b",
|
|
|
|
"bar/c",
|
|
|
|
"bar/d",
|
|
|
|
"foo/d/in",
|
2015-07-13 20:08:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, repo := range repos {
|
2016-07-13 23:39:34 +00:00
|
|
|
makeRepo(t, ctx, repo, registry)
|
2015-07-13 20:08:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
expected := []string{
|
|
|
|
"bar/c",
|
|
|
|
"bar/d",
|
|
|
|
"foo/a",
|
|
|
|
"foo/b",
|
|
|
|
"foo/d/in",
|
|
|
|
}
|
|
|
|
|
|
|
|
return &setupEnv{
|
|
|
|
ctx: ctx,
|
|
|
|
driver: d,
|
|
|
|
expected: expected,
|
|
|
|
registry: registry,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-13 23:39:34 +00:00
|
|
|
func makeRepo(t *testing.T, ctx context.Context, name string, reg distribution.Namespace) {
|
|
|
|
named, err := reference.ParseNamed(name)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
repo, _ := reg.Repository(ctx, named)
|
|
|
|
manifests, _ := repo.Manifests(ctx)
|
|
|
|
|
|
|
|
layers, err := testutil.CreateRandomLayers(1)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = testutil.UploadBlobs(repo, layers)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("failed to upload layers: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
getKeys := func(digests map[digest.Digest]io.ReadSeeker) (ds []digest.Digest) {
|
|
|
|
for d := range digests {
|
|
|
|
ds = append(ds, d)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
manifest, err := testutil.MakeSchema1Manifest(getKeys(layers))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = manifests.Put(ctx, manifest)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("manifest upload failed: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-07-13 20:08:13 +00:00
|
|
|
func TestCatalog(t *testing.T) {
|
|
|
|
env := setupFS(t)
|
|
|
|
|
2015-07-17 18:42:47 +00:00
|
|
|
p := make([]string, 50)
|
|
|
|
|
|
|
|
numFilled, err := env.registry.Repositories(env.ctx, p, "")
|
2016-07-13 23:39:34 +00:00
|
|
|
if numFilled != len(env.expected) {
|
|
|
|
t.Errorf("missing items in catalog")
|
|
|
|
}
|
2015-07-13 20:08:13 +00:00
|
|
|
|
2016-07-13 23:39:34 +00:00
|
|
|
if !testEq(p, env.expected, len(env.expected)) {
|
2015-07-13 20:08:13 +00:00
|
|
|
t.Errorf("Expected catalog repos err")
|
|
|
|
}
|
|
|
|
|
2015-07-17 18:42:47 +00:00
|
|
|
if err != io.EOF {
|
2015-07-13 20:08:13 +00:00
|
|
|
t.Errorf("Catalog has more values which we aren't expecting")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCatalogInParts(t *testing.T) {
|
|
|
|
env := setupFS(t)
|
|
|
|
|
|
|
|
chunkLen := 2
|
2015-07-17 18:42:47 +00:00
|
|
|
p := make([]string, chunkLen)
|
2015-07-13 20:08:13 +00:00
|
|
|
|
2015-07-17 18:42:47 +00:00
|
|
|
numFilled, err := env.registry.Repositories(env.ctx, p, "")
|
|
|
|
if err == io.EOF || numFilled != len(p) {
|
|
|
|
t.Errorf("Expected more values in catalog")
|
2015-07-13 20:08:13 +00:00
|
|
|
}
|
|
|
|
|
2015-07-17 18:42:47 +00:00
|
|
|
if !testEq(p, env.expected[0:chunkLen], numFilled) {
|
|
|
|
t.Errorf("Expected catalog first chunk err")
|
2015-07-13 20:08:13 +00:00
|
|
|
}
|
|
|
|
|
2015-07-17 18:42:47 +00:00
|
|
|
lastRepo := p[len(p)-1]
|
|
|
|
numFilled, err = env.registry.Repositories(env.ctx, p, lastRepo)
|
2015-07-13 20:08:13 +00:00
|
|
|
|
2015-07-17 18:42:47 +00:00
|
|
|
if err == io.EOF || numFilled != len(p) {
|
|
|
|
t.Errorf("Expected more values in catalog")
|
2015-07-13 20:08:13 +00:00
|
|
|
}
|
|
|
|
|
2015-07-17 18:42:47 +00:00
|
|
|
if !testEq(p, env.expected[chunkLen:chunkLen*2], numFilled) {
|
|
|
|
t.Errorf("Expected catalog second chunk err")
|
2015-07-13 20:08:13 +00:00
|
|
|
}
|
|
|
|
|
2015-07-17 18:42:47 +00:00
|
|
|
lastRepo = p[len(p)-1]
|
|
|
|
numFilled, err = env.registry.Repositories(env.ctx, p, lastRepo)
|
2015-07-13 20:08:13 +00:00
|
|
|
|
2015-07-17 18:42:47 +00:00
|
|
|
if err != io.EOF {
|
|
|
|
t.Errorf("Catalog has more values which we aren't expecting")
|
2015-07-13 20:08:13 +00:00
|
|
|
}
|
|
|
|
|
2015-07-17 18:42:47 +00:00
|
|
|
if !testEq(p, env.expected[chunkLen*2:chunkLen*3-1], numFilled) {
|
|
|
|
t.Errorf("Expected catalog third chunk err")
|
2015-07-13 20:08:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-07-17 18:42:47 +00:00
|
|
|
func testEq(a, b []string, size int) bool {
|
|
|
|
for cnt := 0; cnt < size-1; cnt++ {
|
|
|
|
if a[cnt] != b[cnt] {
|
2015-07-13 20:08:13 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
2016-07-13 23:41:51 +00:00
|
|
|
|
|
|
|
func setupBadWalkEnv(t *testing.T) *setupEnv {
|
|
|
|
d := newBadListDriver()
|
|
|
|
ctx := context.Background()
|
|
|
|
registry, err := NewRegistry(ctx, d, BlobDescriptorCacheProvider(memory.NewInMemoryBlobDescriptorCacheProvider()), EnableRedirect)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("error creating registry: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &setupEnv{
|
|
|
|
ctx: ctx,
|
|
|
|
driver: d,
|
|
|
|
registry: registry,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type badListDriver struct {
|
|
|
|
driver.StorageDriver
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ driver.StorageDriver = &badListDriver{}
|
|
|
|
|
|
|
|
func newBadListDriver() *badListDriver {
|
|
|
|
return &badListDriver{StorageDriver: inmemory.New()}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *badListDriver) List(ctx context.Context, path string) ([]string, error) {
|
|
|
|
return nil, fmt.Errorf("List error")
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCatalogWalkError(t *testing.T) {
|
|
|
|
env := setupBadWalkEnv(t)
|
|
|
|
p := make([]string, 1)
|
|
|
|
|
|
|
|
_, err := env.registry.Repositories(env.ctx, p, "")
|
|
|
|
if err == io.EOF {
|
|
|
|
t.Errorf("Expected catalog driver list error")
|
|
|
|
}
|
|
|
|
}
|