diff options
Diffstat (limited to 'pkg/v1/partial/uncompressed_test.go')
-rw-r--r-- | pkg/v1/partial/uncompressed_test.go | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/pkg/v1/partial/uncompressed_test.go b/pkg/v1/partial/uncompressed_test.go new file mode 100644 index 0000000..ce5a6fa --- /dev/null +++ b/pkg/v1/partial/uncompressed_test.go @@ -0,0 +1,233 @@ +// Copyright 2019 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package partial_test + +import ( + "io" + "os" + "testing" + + "github.com/google/go-containerregistry/internal/compare" + legacy "github.com/google/go-containerregistry/pkg/legacy/tarball" + "github.com/google/go-containerregistry/pkg/name" + v1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/google/go-containerregistry/pkg/v1/mutate" + "github.com/google/go-containerregistry/pkg/v1/partial" + "github.com/google/go-containerregistry/pkg/v1/random" + "github.com/google/go-containerregistry/pkg/v1/tarball" + "github.com/google/go-containerregistry/pkg/v1/types" + "github.com/google/go-containerregistry/pkg/v1/validate" +) + +// foreignLayer implements both partial.Describable and partial.UncompressedLayer. +type foreignLayer struct { + wrapped v1.Layer +} + +func (l *foreignLayer) Digest() (v1.Hash, error) { + return l.wrapped.Digest() +} + +func (l *foreignLayer) Size() (int64, error) { + return l.wrapped.Size() +} + +func (l *foreignLayer) MediaType() (types.MediaType, error) { + return types.DockerForeignLayer, nil +} + +func (l *foreignLayer) Uncompressed() (io.ReadCloser, error) { + return l.wrapped.Uncompressed() +} + +func (l *foreignLayer) DiffID() (v1.Hash, error) { + return l.wrapped.DiffID() +} + +func (l *foreignLayer) Descriptor() (*v1.Descriptor, error) { + r, err := l.wrapped.Compressed() + if err != nil { + return nil, err + } + h, sz, err := v1.SHA256(r) + if err != nil { + return nil, err + } + return &v1.Descriptor{ + Digest: h, + Size: sz, + MediaType: types.DockerForeignLayer, + URLs: []string{"http://example.com"}, + }, nil +} + +func (l *foreignLayer) UncompressedSize() (int64, error) { + return partial.UncompressedSize(l.wrapped) +} + +func TestUncompressedLayer(t *testing.T) { + randLayer, err := random.Layer(1024, types.DockerForeignLayer) + if err != nil { + t.Fatal(err) + } + l := &foreignLayer{randLayer} + + desc, err := partial.Descriptor(l) + if err != nil { + t.Fatal(err) + } + + if want, got := desc.URLs[0], "http://example.com"; want != got { + t.Errorf("URLs[0] = %s != %s", got, want) + } + + layer, err := partial.UncompressedToLayer(l) + if err != nil { + t.Fatal(err) + } + + if err := validate.Layer(layer); err != nil { + t.Errorf("validate.Layer: %v", err) + } + if _, err := partial.UncompressedSize(layer); err != nil { + t.Errorf("partial.UncompressedSize: %v", err) + } +} + +// legacy/tarball.Write + tarball.Image leverages a lot of uncompressed partials. +// +// This is cribbed from pkg/legacy/tarball just to get intra-package coverage. +func TestLegacyWrite(t *testing.T) { + // Make a tempfile for tarball writes. + fp, err := os.CreateTemp("", "") + if err != nil { + t.Fatalf("Error creating temp file.") + } + t.Log(fp.Name()) + defer fp.Close() + defer os.Remove(fp.Name()) + + // Make a random image + layer with Descriptor(). + randImage, err := random.Image(256, 2) + if err != nil { + t.Fatalf("Error creating random image: %v", err) + } + randLayer, err := random.Layer(1024, types.DockerForeignLayer) + if err != nil { + t.Fatal(err) + } + l, err := partial.UncompressedToLayer(&foreignLayer{randLayer}) + if err != nil { + t.Fatal(err) + } + img, err := mutate.AppendLayers(randImage, l) + if err != nil { + t.Fatal(err) + } + tag, err := name.NewTag("gcr.io/foo/bar:latest", name.StrictValidation) + if err != nil { + t.Fatalf("Error creating test tag: %v", err) + } + o, err := os.Create(fp.Name()) + if err != nil { + t.Fatalf("Error creating %q to write image tarball: %v", fp.Name(), err) + } + defer o.Close() + if err := legacy.Write(tag, img, o); err != nil { + t.Fatalf("Unexpected error writing tarball: %v", err) + } + + // Make sure the image is valid and can be loaded. + // Load it both by nil and by its name. + for _, it := range []*name.Tag{nil, &tag} { + tarImage, err := tarball.ImageFromPath(fp.Name(), it) + if err != nil { + t.Fatalf("Unexpected error reading tarball: %v", err) + } + if err := validate.Image(tarImage); err != nil { + t.Errorf("validate.Image: %v", err) + } + if err := compare.Images(img, tarImage); err != nil { + t.Errorf("compare.Images: %v", err) + } + } + + // Try loading a different tag, it should error. + fakeTag, err := name.NewTag("gcr.io/notthistag:latest", name.StrictValidation) + if err != nil { + t.Fatalf("Error generating tag: %v", err) + } + if _, err := tarball.ImageFromPath(fp.Name(), &fakeTag); err == nil { + t.Errorf("Expected error loading tag %v from image", fakeTag) + } +} + +type uncompressedImage struct { + img v1.Image +} + +func (i *uncompressedImage) RawConfigFile() ([]byte, error) { + return i.img.RawConfigFile() +} + +func (i *uncompressedImage) MediaType() (types.MediaType, error) { + return i.img.MediaType() +} + +func (i *uncompressedImage) LayerByDiffID(h v1.Hash) (partial.UncompressedLayer, error) { + return i.img.LayerByDiffID(h) +} + +func (i *uncompressedImage) Descriptor() (*v1.Descriptor, error) { + return partial.Descriptor(i.img) +} + +func TestUncompressed(t *testing.T) { + rnd, err := random.Image(1024, 1) + if err != nil { + t.Fatal(err) + } + + core := &uncompressedImage{rnd} + + img, err := partial.UncompressedToImage(core) + if err != nil { + t.Fatal(err) + } + + if err := validate.Image(img); err != nil { + t.Fatalf("validate.Image: %v", err) + } + if _, err := partial.Descriptor(img); err != nil { + t.Fatalf("partial.Descriptor: %v", err) + } + + layers, err := img.Layers() + if err != nil { + t.Fatal(err) + } + layer, err := partial.UncompressedToLayer(&fastpathLayer{layers[0]}) + if err != nil { + t.Fatal(err) + } + + ok, err := partial.Exists(layer) + if err != nil { + t.Fatal(err) + } + if got, want := ok, true; got != want { + t.Errorf("Exists() = %t != %t", got, want) + } +} |