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

     1  package storage
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/rand"
     6  	"io"
     7  	"os"
     8  	"testing"
     9  
    10  	"github.com/docker/distribution/context"
    11  	"github.com/docker/distribution/digest"
    12  	storagedriver "github.com/docker/distribution/registry/storage/driver"
    13  	"github.com/docker/distribution/registry/storage/driver/inmemory"
    14  )
    15  
    16  // TestSimpleWrite takes the fileWriter through common write operations
    17  // ensuring data integrity.
    18  func TestSimpleWrite(t *testing.T) {
    19  	content := make([]byte, 1<<20)
    20  	n, err := rand.Read(content)
    21  	if err != nil {
    22  		t.Fatalf("unexpected error building random data: %v", err)
    23  	}
    24  
    25  	if n != len(content) {
    26  		t.Fatalf("random read did't fill buffer")
    27  	}
    28  
    29  	dgst, err := digest.FromReader(bytes.NewReader(content))
    30  	if err != nil {
    31  		t.Fatalf("unexpected error digesting random content: %v", err)
    32  	}
    33  
    34  	driver := inmemory.New()
    35  	path := "/random"
    36  	ctx := context.Background()
    37  
    38  	fw, err := newFileWriter(ctx, driver, path)
    39  	if err != nil {
    40  		t.Fatalf("unexpected error creating fileWriter: %v", err)
    41  	}
    42  	defer fw.Close()
    43  
    44  	n, err = fw.Write(content)
    45  	if err != nil {
    46  		t.Fatalf("unexpected error writing content: %v", err)
    47  	}
    48  	fw.Flush()
    49  
    50  	if n != len(content) {
    51  		t.Fatalf("unexpected write length: %d != %d", n, len(content))
    52  	}
    53  
    54  	fr, err := newFileReader(ctx, driver, path, int64(len(content)))
    55  	if err != nil {
    56  		t.Fatalf("unexpected error creating fileReader: %v", err)
    57  	}
    58  	defer fr.Close()
    59  
    60  	verifier, err := digest.NewDigestVerifier(dgst)
    61  	if err != nil {
    62  		t.Fatalf("unexpected error getting digest verifier: %s", err)
    63  	}
    64  
    65  	io.Copy(verifier, fr)
    66  
    67  	if !verifier.Verified() {
    68  		t.Fatalf("unable to verify write data")
    69  	}
    70  
    71  	// Check the seek position is equal to the content length
    72  	end, err := fw.Seek(0, os.SEEK_END)
    73  	if err != nil {
    74  		t.Fatalf("unexpected error seeking: %v", err)
    75  	}
    76  
    77  	if end != int64(len(content)) {
    78  		t.Fatalf("write did not advance offset: %d != %d", end, len(content))
    79  	}
    80  
    81  	// Double the content
    82  	doubled := append(content, content...)
    83  	doubledgst, err := digest.FromReader(bytes.NewReader(doubled))
    84  	if err != nil {
    85  		t.Fatalf("unexpected error digesting doubled content: %v", err)
    86  	}
    87  
    88  	nn, err := fw.ReadFrom(bytes.NewReader(content))
    89  	if err != nil {
    90  		t.Fatalf("unexpected error doubling content: %v", err)
    91  	}
    92  
    93  	if nn != int64(len(content)) {
    94  		t.Fatalf("writeat was short: %d != %d", n, len(content))
    95  	}
    96  
    97  	fr, err = newFileReader(ctx, driver, path, int64(len(doubled)))
    98  	if err != nil {
    99  		t.Fatalf("unexpected error creating fileReader: %v", err)
   100  	}
   101  	defer fr.Close()
   102  
   103  	verifier, err = digest.NewDigestVerifier(doubledgst)
   104  	if err != nil {
   105  		t.Fatalf("unexpected error getting digest verifier: %s", err)
   106  	}
   107  
   108  	io.Copy(verifier, fr)
   109  
   110  	if !verifier.Verified() {
   111  		t.Fatalf("unable to verify write data")
   112  	}
   113  
   114  	// Check that Write updated the offset.
   115  	end, err = fw.Seek(0, os.SEEK_END)
   116  	if err != nil {
   117  		t.Fatalf("unexpected error seeking: %v", err)
   118  	}
   119  
   120  	if end != int64(len(doubled)) {
   121  		t.Fatalf("write did not advance offset: %d != %d", end, len(doubled))
   122  	}
   123  
   124  	// Now, we copy from one path to another, running the data through the
   125  	// fileReader to fileWriter, rather than the driver.Move command to ensure
   126  	// everything is working correctly.
   127  	fr, err = newFileReader(ctx, driver, path, int64(len(doubled)))
   128  	if err != nil {
   129  		t.Fatalf("unexpected error creating fileReader: %v", err)
   130  	}
   131  	defer fr.Close()
   132  
   133  	fw, err = newFileWriter(ctx, driver, "/copied")
   134  	if err != nil {
   135  		t.Fatalf("unexpected error creating fileWriter: %v", err)
   136  	}
   137  	defer fw.Close()
   138  
   139  	nn, err = io.Copy(fw, fr)
   140  	if err != nil {
   141  		t.Fatalf("unexpected error copying data: %v", err)
   142  	}
   143  
   144  	if nn != int64(len(doubled)) {
   145  		t.Fatalf("unexpected copy length: %d != %d", nn, len(doubled))
   146  	}
   147  
   148  	fr, err = newFileReader(ctx, driver, "/copied", int64(len(doubled)))
   149  	if err != nil {
   150  		t.Fatalf("unexpected error creating fileReader: %v", err)
   151  	}
   152  	defer fr.Close()
   153  
   154  	verifier, err = digest.NewDigestVerifier(doubledgst)
   155  	if err != nil {
   156  		t.Fatalf("unexpected error getting digest verifier: %s", err)
   157  	}
   158  
   159  	io.Copy(verifier, fr)
   160  
   161  	if !verifier.Verified() {
   162  		t.Fatalf("unable to verify write data")
   163  	}
   164  }
   165  
   166  func TestBufferedFileWriter(t *testing.T) {
   167  	ctx := context.Background()
   168  	writer, err := newFileWriter(ctx, inmemory.New(), "/random")
   169  
   170  	if err != nil {
   171  		t.Fatalf("Failed to initialize bufferedFileWriter: %v", err.Error())
   172  	}
   173  
   174  	// write one byte and ensure the offset hasn't been incremented.
   175  	// offset will only get incremented when the buffer gets flushed
   176  	short := []byte{byte(1)}
   177  
   178  	writer.Write(short)
   179  
   180  	if writer.offset > 0 {
   181  		t.Fatalf("WriteStream called prematurely")
   182  	}
   183  
   184  	// write enough data to cause the buffer to flush and confirm
   185  	// the offset has been incremented
   186  	long := make([]byte, fileWriterBufferSize)
   187  	_, err = rand.Read(long)
   188  	if err != nil {
   189  		t.Fatalf("unexpected error building random data: %v", err)
   190  	}
   191  	for i := range long {
   192  		long[i] = byte(i)
   193  	}
   194  	writer.Write(long)
   195  	writer.Close()
   196  	if writer.offset != (fileWriterBufferSize + 1) {
   197  		t.Fatalf("WriteStream not called when buffer capacity reached")
   198  	}
   199  }
   200  
   201  func BenchmarkFileWriter(b *testing.B) {
   202  	b.StopTimer() // not sure how long setup above will take
   203  	for i := 0; i < b.N; i++ {
   204  		// Start basic fileWriter initialization
   205  		fw := fileWriter{
   206  			driver: inmemory.New(),
   207  			path:   "/random",
   208  		}
   209  		ctx := context.Background()
   210  		if fi, err := fw.driver.Stat(ctx, fw.path); err != nil {
   211  			switch err := err.(type) {
   212  			case storagedriver.PathNotFoundError:
   213  				// ignore, offset is zero
   214  			default:
   215  				b.Fatalf("Failed to initialize fileWriter: %v", err.Error())
   216  			}
   217  		} else {
   218  			if fi.IsDir() {
   219  				b.Fatalf("Cannot write to a directory")
   220  			}
   221  
   222  			fw.size = fi.Size()
   223  		}
   224  
   225  		randomBytes := make([]byte, 1<<20)
   226  		_, err := rand.Read(randomBytes)
   227  		if err != nil {
   228  			b.Fatalf("unexpected error building random data: %v", err)
   229  		}
   230  		// End basic file writer initialization
   231  
   232  		b.StartTimer()
   233  		for j := 0; j < 100; j++ {
   234  			fw.Write(randomBytes)
   235  		}
   236  		b.StopTimer()
   237  	}
   238  }
   239  
   240  func BenchmarkBufferedFileWriter(b *testing.B) {
   241  	b.StopTimer() // not sure how long setup above will take
   242  	ctx := context.Background()
   243  	for i := 0; i < b.N; i++ {
   244  		bfw, err := newFileWriter(ctx, inmemory.New(), "/random")
   245  
   246  		if err != nil {
   247  			b.Fatalf("Failed to initialize bufferedFileWriter: %v", err.Error())
   248  		}
   249  
   250  		randomBytes := make([]byte, 1<<20)
   251  		_, err = rand.Read(randomBytes)
   252  		if err != nil {
   253  			b.Fatalf("unexpected error building random data: %v", err)
   254  		}
   255  
   256  		b.StartTimer()
   257  		for j := 0; j < 100; j++ {
   258  			bfw.Write(randomBytes)
   259  		}
   260  		b.StopTimer()
   261  	}
   262  }