github.com/mika/distribution@v2.2.2-0.20160108133430-a75790e3d8e0+incompatible/registry/storage/filereader_test.go (about)

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