...

Source file src/github.com/google/go-containerregistry/pkg/v1/cache/fs_test.go

Documentation: github.com/google/go-containerregistry/pkg/v1/cache

     1  // Copyright 2021 Google LLC All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package cache
    16  
    17  import (
    18  	"errors"
    19  	"io"
    20  	"os"
    21  	"testing"
    22  
    23  	v1 "github.com/google/go-containerregistry/pkg/v1"
    24  	"github.com/google/go-containerregistry/pkg/v1/random"
    25  	"github.com/google/go-containerregistry/pkg/v1/tarball"
    26  	"github.com/google/go-containerregistry/pkg/v1/types"
    27  )
    28  
    29  func TestFilesystemCache(t *testing.T) {
    30  	dir := t.TempDir()
    31  
    32  	numLayers := 5
    33  	img, err := random.Image(10, int64(numLayers))
    34  	if err != nil {
    35  		t.Fatalf("random.Image: %v", err)
    36  	}
    37  	c := NewFilesystemCache(dir)
    38  	img = Image(img, c)
    39  
    40  	// Read all the (compressed) layers to populate the cache.
    41  	ls, err := img.Layers()
    42  	if err != nil {
    43  		t.Fatalf("Layers: %v", err)
    44  	}
    45  	for i, l := range ls {
    46  		rc, err := l.Compressed()
    47  		if err != nil {
    48  			t.Fatalf("layer[%d].Compressed: %v", i, err)
    49  		}
    50  		if _, err := io.Copy(io.Discard, rc); err != nil {
    51  			t.Fatalf("Error reading contents: %v", err)
    52  		}
    53  		rc.Close()
    54  	}
    55  
    56  	// Check that layers exist in the fs cache.
    57  	dirEntries, err := os.ReadDir(dir)
    58  	if err != nil {
    59  		t.Fatalf("ReadDir: %v", err)
    60  	}
    61  	if got, want := len(dirEntries), numLayers; got != want {
    62  		t.Errorf("Got %d cached files, want %d", got, want)
    63  	}
    64  	for _, de := range dirEntries {
    65  		fi, err := de.Info()
    66  		if err != nil {
    67  			t.Fatal(err)
    68  		}
    69  		if fi.Size() == 0 {
    70  			t.Errorf("Cached file %q is empty", fi.Name())
    71  		}
    72  	}
    73  
    74  	// Read all (uncompressed) layers, those populate the cache too.
    75  	for i, l := range ls {
    76  		rc, err := l.Uncompressed()
    77  		if err != nil {
    78  			t.Fatalf("layer[%d].Compressed: %v", i, err)
    79  		}
    80  		if _, err := io.Copy(io.Discard, rc); err != nil {
    81  			t.Fatalf("Error reading contents: %v", err)
    82  		}
    83  		rc.Close()
    84  	}
    85  
    86  	// Check that double the layers are present now, both compressed and
    87  	// uncompressed.
    88  	dirEntries, err = os.ReadDir(dir)
    89  	if err != nil {
    90  		t.Fatalf("ReadDir: %v", err)
    91  	}
    92  	if got, want := len(dirEntries), numLayers*2; got != want {
    93  		t.Errorf("Got %d cached files, want %d", got, want)
    94  	}
    95  	for _, de := range dirEntries {
    96  		fi, err := de.Info()
    97  		if err != nil {
    98  			t.Fatal(err)
    99  		}
   100  		if fi.Size() == 0 {
   101  			t.Errorf("Cached file %q is empty", fi.Name())
   102  		}
   103  	}
   104  
   105  	// Delete a cached layer, see it disappear.
   106  	l := ls[0]
   107  	h, err := l.Digest()
   108  	if err != nil {
   109  		t.Fatalf("layer.Digest: %v", err)
   110  	}
   111  	if err := c.Delete(h); err != nil {
   112  		t.Errorf("cache.Delete: %v", err)
   113  	}
   114  	dirEntries, err = os.ReadDir(dir)
   115  	if err != nil {
   116  		t.Fatalf("ReadDir: %v", err)
   117  	}
   118  	if got, want := len(dirEntries), numLayers*2-1; got != want {
   119  		t.Errorf("Got %d cached files, want %d", got, want)
   120  	}
   121  
   122  	// Read the image again, see the layer reappear.
   123  	for i, l := range ls {
   124  		rc, err := l.Compressed()
   125  		if err != nil {
   126  			t.Fatalf("layer[%d].Compressed: %v", i, err)
   127  		}
   128  		if _, err := io.Copy(io.Discard, rc); err != nil {
   129  			t.Fatalf("Error reading contents: %v", err)
   130  		}
   131  		rc.Close()
   132  	}
   133  
   134  	// Check that layers exist in the fs cache.
   135  	dirEntries, err = os.ReadDir(dir)
   136  	if err != nil {
   137  		t.Fatalf("ReadDir: %v", err)
   138  	}
   139  	if got, want := len(dirEntries), numLayers*2; got != want {
   140  		t.Errorf("Got %d cached files, want %d", got, want)
   141  	}
   142  	for _, de := range dirEntries {
   143  		fi, err := de.Info()
   144  		if err != nil {
   145  			t.Fatal(err)
   146  		}
   147  		if fi.Size() == 0 {
   148  			t.Errorf("Cached file %q is empty", fi.Name())
   149  		}
   150  	}
   151  }
   152  
   153  func TestErrNotFound(t *testing.T) {
   154  	dir := t.TempDir()
   155  
   156  	c := NewFilesystemCache(dir)
   157  	h := v1.Hash{Algorithm: "fake", Hex: "not-found"}
   158  	if _, err := c.Get(h); !errors.Is(err, ErrNotFound) {
   159  		t.Errorf("Get(%q): %v", h, err)
   160  	}
   161  	if err := c.Delete(h); !errors.Is(err, ErrNotFound) {
   162  		t.Errorf("Delete(%q): %v", h, err)
   163  	}
   164  }
   165  
   166  func TestErrUnexpectedEOF(t *testing.T) {
   167  	dir := t.TempDir()
   168  
   169  	// create a random layer
   170  	l, err := random.Layer(10, types.DockerLayer)
   171  	if err != nil {
   172  		t.Fatalf("random.Layer: %v", err)
   173  	}
   174  	rc, err := l.Compressed()
   175  	if err != nil {
   176  		t.Fatalf("layer.Compressed(): %v", err)
   177  	}
   178  
   179  	h, err := l.Digest()
   180  	if err != nil {
   181  		t.Fatalf("layer.Digest(): %v", err)
   182  	}
   183  	p := cachepath(dir, h)
   184  
   185  	// Write only the first segment of the compressed layer to produce an
   186  	// UnexpectedEOF error when reading it
   187  	buf := make([]byte, 10)
   188  	n, err := rc.Read(buf)
   189  	if err != nil {
   190  		t.Fatalf("Read(buf): %v", err)
   191  	}
   192  	if err := os.WriteFile(p, buf[:n], 0644); err != nil {
   193  		t.Fatalf("os.WriteFile(%s, buf[:%d]): %v", p, n, err)
   194  	}
   195  
   196  	c := NewFilesystemCache(dir)
   197  
   198  	// make sure LayerFromFile returns UnexpectedEOF
   199  	if _, err := tarball.LayerFromFile(p); !errors.Is(err, io.ErrUnexpectedEOF) {
   200  		t.Fatalf("tarball.LayerFromFile(%s): expected %v, got %v", p, io.ErrUnexpectedEOF, err)
   201  	}
   202  
   203  	// Try to Get the layer
   204  	if _, err := c.Get(h); !errors.Is(err, ErrNotFound) {
   205  		t.Errorf("Get(%q): %v", h, err)
   206  	}
   207  
   208  	// If we had an UnexpectedEOF and the cache deleted the broken layer no file
   209  	// should exist
   210  	if _, err := os.Stat(p); !os.IsNotExist(err) {
   211  		t.Errorf("os.Stat(%q): %v", p, err)
   212  	}
   213  }
   214  

View as plain text