...

Source file src/github.com/docker/distribution/registry/storage/filereader_test.go

Documentation: github.com/docker/distribution/registry/storage

     1  package storage
     2  
     3  import (
     4  	"bytes"
     5  	crand "crypto/rand"
     6  	"io"
     7  	mrand "math/rand"
     8  	"testing"
     9  
    10  	"github.com/docker/distribution/context"
    11  	"github.com/docker/distribution/registry/storage/driver/inmemory"
    12  	"github.com/opencontainers/go-digest"
    13  )
    14  
    15  func TestSimpleRead(t *testing.T) {
    16  	ctx := context.Background()
    17  	content := make([]byte, 1<<20)
    18  	n, err := crand.Read(content)
    19  	if err != nil {
    20  		t.Fatalf("unexpected error building random data: %v", err)
    21  	}
    22  
    23  	if n != len(content) {
    24  		t.Fatalf("random read didn't fill buffer")
    25  	}
    26  
    27  	dgst, err := digest.FromReader(bytes.NewReader(content))
    28  	if err != nil {
    29  		t.Fatalf("unexpected error digesting random content: %v", err)
    30  	}
    31  
    32  	driver := inmemory.New()
    33  	path := "/random"
    34  
    35  	if err := driver.PutContent(ctx, path, content); err != nil {
    36  		t.Fatalf("error putting patterned content: %v", err)
    37  	}
    38  
    39  	fr, err := newFileReader(ctx, driver, path, int64(len(content)))
    40  	if err != nil {
    41  		t.Fatalf("error allocating file reader: %v", err)
    42  	}
    43  
    44  	verifier := dgst.Verifier()
    45  	io.Copy(verifier, fr)
    46  
    47  	if !verifier.Verified() {
    48  		t.Fatalf("unable to verify read data")
    49  	}
    50  }
    51  
    52  func TestFileReaderSeek(t *testing.T) {
    53  	driver := inmemory.New()
    54  	pattern := "01234567890ab" // prime length block
    55  	repititions := 1024
    56  	path := "/patterned"
    57  	content := bytes.Repeat([]byte(pattern), repititions)
    58  	ctx := context.Background()
    59  
    60  	if err := driver.PutContent(ctx, path, content); err != nil {
    61  		t.Fatalf("error putting patterned content: %v", err)
    62  	}
    63  
    64  	fr, err := newFileReader(ctx, driver, path, int64(len(content)))
    65  
    66  	if err != nil {
    67  		t.Fatalf("unexpected error creating file reader: %v", err)
    68  	}
    69  
    70  	// Seek all over the place, in blocks of pattern size and make sure we get
    71  	// the right data.
    72  	for _, repitition := range mrand.Perm(repititions - 1) {
    73  		targetOffset := int64(len(pattern) * repitition)
    74  		// Seek to a multiple of pattern size and read pattern size bytes
    75  		offset, err := fr.Seek(targetOffset, io.SeekStart)
    76  		if err != nil {
    77  			t.Fatalf("unexpected error seeking: %v", err)
    78  		}
    79  
    80  		if offset != targetOffset {
    81  			t.Fatalf("did not seek to correct offset: %d != %d", offset, targetOffset)
    82  		}
    83  
    84  		p := make([]byte, len(pattern))
    85  
    86  		n, err := fr.Read(p)
    87  		if err != nil {
    88  			t.Fatalf("error reading pattern: %v", err)
    89  		}
    90  
    91  		if n != len(pattern) {
    92  			t.Fatalf("incorrect read length: %d != %d", n, len(pattern))
    93  		}
    94  
    95  		if string(p) != pattern {
    96  			t.Fatalf("incorrect read content: %q != %q", p, pattern)
    97  		}
    98  
    99  		// Check offset
   100  		current, err := fr.Seek(0, io.SeekCurrent)
   101  		if err != nil {
   102  			t.Fatalf("error checking current offset: %v", err)
   103  		}
   104  
   105  		if current != targetOffset+int64(len(pattern)) {
   106  			t.Fatalf("unexpected offset after read: %v", err)
   107  		}
   108  	}
   109  
   110  	start, err := fr.Seek(0, io.SeekStart)
   111  	if err != nil {
   112  		t.Fatalf("error seeking to start: %v", err)
   113  	}
   114  
   115  	if start != 0 {
   116  		t.Fatalf("expected to seek to start: %v != 0", start)
   117  	}
   118  
   119  	end, err := fr.Seek(0, io.SeekEnd)
   120  	if err != nil {
   121  		t.Fatalf("error checking current offset: %v", err)
   122  	}
   123  
   124  	if end != int64(len(content)) {
   125  		t.Fatalf("expected to seek to end: %v != %v", end, len(content))
   126  	}
   127  
   128  	// 4. Seek before start, ensure error.
   129  
   130  	// seek before start
   131  	before, err := fr.Seek(-1, io.SeekStart)
   132  	if err == nil {
   133  		t.Fatalf("error expected, returned offset=%v", before)
   134  	}
   135  
   136  	// 5. Seek after end,
   137  	after, err := fr.Seek(1, io.SeekEnd)
   138  	if err != nil {
   139  		t.Fatalf("unexpected error expected, returned offset=%v", after)
   140  	}
   141  
   142  	p := make([]byte, 16)
   143  	n, err := fr.Read(p)
   144  
   145  	if n != 0 {
   146  		t.Fatalf("bytes reads %d != %d", n, 0)
   147  	}
   148  
   149  	if err != io.EOF {
   150  		t.Fatalf("expected io.EOF, got %v", err)
   151  	}
   152  }
   153  
   154  // TestFileReaderNonExistentFile ensures the reader behaves as expected with a
   155  // missing or zero-length remote file. While the file may not exist, the
   156  // reader should not error out on creation and should return 0-bytes from the
   157  // read method, with an io.EOF error.
   158  func TestFileReaderNonExistentFile(t *testing.T) {
   159  	driver := inmemory.New()
   160  	fr, err := newFileReader(context.Background(), driver, "/doesnotexist", 10)
   161  	if err != nil {
   162  		t.Fatalf("unexpected error initializing reader: %v", err)
   163  	}
   164  
   165  	var buf [1024]byte
   166  
   167  	n, err := fr.Read(buf[:])
   168  	if n != 0 {
   169  		t.Fatalf("non-zero byte read reported: %d != 0", n)
   170  	}
   171  
   172  	if err != io.EOF {
   173  		t.Fatalf("read on missing file should return io.EOF, got %v", err)
   174  	}
   175  }
   176  
   177  // TestLayerReadErrors covers the various error return type for different
   178  // conditions that can arise when reading a layer.
   179  func TestFileReaderErrors(t *testing.T) {
   180  	// TODO(stevvooe): We need to cover error return types, driven by the
   181  	// errors returned via the HTTP API. For now, here is an incomplete list:
   182  	//
   183  	// 	1. Layer Not Found: returned when layer is not found or access is
   184  	//        denied.
   185  	//	2. Layer Unavailable: returned when link references are unresolved,
   186  	//     but layer is known to the registry.
   187  	//  3. Layer Invalid: This may more split into more errors, but should be
   188  	//     returned when name or tarsum does not reference a valid error. We
   189  	//     may also need something to communication layer verification errors
   190  	//     for the inline tarsum check.
   191  	//	4. Timeout: timeouts to backend. Need to better understand these
   192  	//     failure cases and how the storage driver propagates these errors
   193  	//     up the stack.
   194  }
   195  

View as plain text