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 }