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