github.com/bazelbuild/remote-apis-sdks@v0.0.0-20240425170053-8a36686a6350/go/pkg/reader/reader_test.go (about)

     1  package reader
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"testing"
     7  
     8  	"github.com/bazelbuild/remote-apis-sdks/go/pkg/testutil"
     9  	"github.com/google/go-cmp/cmp"
    10  	"github.com/klauspost/compress/zstd"
    11  )
    12  
    13  func TestFileReaderSeeks(t *testing.T) {
    14  	t.Parallel()
    15  	tests := []struct {
    16  		name         string
    17  		IOBuffSize   int
    18  		dataBuffSize int
    19  		blob         string
    20  		seekOffset   int64
    21  		wantResetErr error
    22  	}{
    23  		{
    24  			name:         "Smaller data buffer",
    25  			IOBuffSize:   10,
    26  			dataBuffSize: 3,
    27  			blob:         "1234567",
    28  			seekOffset:   2,
    29  			wantResetErr: nil,
    30  		},
    31  		{
    32  			name:         "Smaller io buffer",
    33  			IOBuffSize:   1,
    34  			dataBuffSize: 3,
    35  			blob:         "1234567",
    36  			seekOffset:   2,
    37  			wantResetErr: nil,
    38  		},
    39  	}
    40  
    41  	for _, tc := range tests {
    42  		tc := tc
    43  		t.Run(tc.name, func(t *testing.T) {
    44  			t.Parallel()
    45  			path, err := testutil.CreateFile(t, false, tc.blob)
    46  			if err != nil {
    47  				t.Fatalf("Failed to make temp file: %v", err)
    48  			}
    49  
    50  			data := make([]byte, tc.dataBuffSize)
    51  
    52  			r := NewFileReadSeeker(path, tc.IOBuffSize)
    53  			defer r.Close()
    54  			if _, err := r.Read(data); err == nil {
    55  				t.Errorf("Read() = should have err'd on unitialized reader")
    56  			}
    57  			if err := r.Initialize(); err != nil {
    58  				t.Fatalf("Failed to initialize reader: %v", err)
    59  			}
    60  
    61  			n, err := io.ReadFull(r, data)
    62  			if n != tc.dataBuffSize {
    63  				t.Errorf("Read() = %d bytes, expected %d", n, tc.dataBuffSize)
    64  			}
    65  			if err != nil {
    66  				t.Errorf("Read() = %v err, expected nil", err)
    67  			}
    68  			if diff := cmp.Diff(string(data), tc.blob[:tc.dataBuffSize]); diff != "" {
    69  				t.Errorf("Read() = incorrect result, diff(-want, +got): %v", diff)
    70  			}
    71  
    72  			r.SeekOffset(tc.seekOffset)
    73  			if _, err := r.Read(data); err != errNotInitialized {
    74  				t.Errorf("Read() should have failed with %q, got %q", errNotInitialized, err)
    75  			}
    76  			if err := r.Initialize(); err != nil {
    77  				t.Fatalf("Failed to initialize reader: %v", err)
    78  			}
    79  
    80  			n, err = io.ReadFull(r, data)
    81  			if n != tc.dataBuffSize {
    82  				t.Errorf("Read() = %d bytes, expected %d", n, tc.dataBuffSize)
    83  			}
    84  			if err != nil {
    85  				t.Errorf("Read() = %v err, expected nil", err)
    86  			}
    87  			endRead := int(tc.seekOffset) + tc.dataBuffSize
    88  			if endRead > len(tc.blob) {
    89  				endRead = len(tc.blob)
    90  			}
    91  			if diff := cmp.Diff(string(data), tc.blob[tc.seekOffset:endRead]); diff != "" {
    92  				t.Errorf("Read() = incorrect result, diff(-want, +got): %v", diff)
    93  			}
    94  		})
    95  	}
    96  
    97  }
    98  
    99  func TestFileReaderSeeksPastOffset(t *testing.T) {
   100  	t.Parallel()
   101  	path, err := testutil.CreateFile(t, false, "12345")
   102  	if err != nil {
   103  		t.Fatalf("Failed to make temp file: %v", err)
   104  	}
   105  
   106  	r := NewFileReadSeeker(path, 10)
   107  	// Past Offset
   108  	r.SeekOffset(10)
   109  	if err := r.Initialize(); err != nil {
   110  		t.Fatalf("Failed to initialize reader: %v", err)
   111  	}
   112  
   113  	data := make([]byte, 1)
   114  	if _, err := r.Read(data); err == nil {
   115  		t.Errorf("Expected err, got nil")
   116  	}
   117  }
   118  
   119  func TestCompressedReader(t *testing.T) {
   120  	t.Parallel()
   121  	tests := []struct {
   122  		name string
   123  		blob string
   124  	}{
   125  		{
   126  			name: "basic",
   127  			blob: "12345",
   128  		},
   129  		{
   130  			name: "looong",
   131  			blob: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
   132  		},
   133  		{
   134  			name: "empty blob",
   135  			blob: "",
   136  		},
   137  		{
   138  			name: "1MB zero blob",
   139  			blob: string(make([]byte, 1*1024*1024)),
   140  		},
   141  	}
   142  
   143  	for _, tc := range tests {
   144  		name := tc.name
   145  		blob := tc.blob
   146  		t.Run(name, func(t *testing.T) {
   147  			t.Parallel()
   148  
   149  			path, err := testutil.CreateFile(t, false, blob)
   150  			if err != nil {
   151  				t.Fatalf("Failed to initialize temp file: %v", err)
   152  			}
   153  
   154  			buf := bytes.NewBuffer([]byte{})
   155  			encd, err := zstd.NewWriter(buf)
   156  			if err != nil {
   157  				t.Fatalf("Failed to initialize compressor: %v", err)
   158  			}
   159  			if _, err = encd.Write([]byte(blob)); err != nil {
   160  				t.Fatalf("Failed to compress data: %v", err)
   161  			}
   162  			if err = encd.Close(); err != nil {
   163  				t.Fatalf("Failed to finish compressing data: %v", err)
   164  			}
   165  			compressedData := buf.Bytes()
   166  
   167  			r, err := NewCompressedFileSeeker(path, 10)
   168  			if err != nil {
   169  				t.Fatalf("Failed to create compressor reader: %v", err)
   170  			}
   171  
   172  			if _, err := io.ReadAll(r); err != errNotInitialized {
   173  				t.Errorf("Read() should have failed with %q, got %q", errNotInitialized, err)
   174  			}
   175  
   176  			if err := r.Initialize(); err != nil {
   177  				t.Fatalf("Failed to initialize reader: %v", err)
   178  			}
   179  
   180  			got, err := io.ReadAll(r)
   181  			if err != nil {
   182  				t.Fatalf("Read() returned error: %v", err)
   183  			}
   184  
   185  			if diff := cmp.Diff(compressedData, got); diff != "" {
   186  				t.Errorf("Read() = incorrect result, diff(-want, +got): %v", diff)
   187  				t.Errorf("Read() = wrong length, wanted %d, got %d", len(compressedData), len(got))
   188  			}
   189  
   190  			// The reader should continue to return an io.EOF and no bytes on
   191  			// subsequent Read() calls, until it's re-initialized.
   192  			got, err = io.ReadAll(r)
   193  			if err != nil {
   194  				t.Errorf("Unexpected error reading a consumed seeker: %v", err)
   195  			}
   196  			if len(got) != 0 {
   197  				t.Errorf("Unexpected result from reading a consumed seeker: %v", got)
   198  			}
   199  
   200  			// After a SeekOffset(0), doing the same operations all over again
   201  			// should produce the same results.
   202  			if err := r.SeekOffset(0); err != nil {
   203  				t.Fatalf("SeekOffset(0) failed: %v", err)
   204  			}
   205  			if err := r.Initialize(); err != nil {
   206  				t.Fatalf("Failed to initialize reader: %v", err)
   207  			}
   208  
   209  			got, err = io.ReadAll(r)
   210  			if err != nil {
   211  				t.Fatalf("Read() returned error: %v", err)
   212  			}
   213  
   214  			if diff := cmp.Diff(compressedData, got); diff != "" {
   215  				t.Errorf("Read() = incorrect result, diff(-want, +got): %v", diff)
   216  			}
   217  		})
   218  	}
   219  }