github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/tools/readers/readers_test.go (about) 1 // Package readers provides implementation for common reader types 2 /* 3 * Copyright (c) 2018-2024, NVIDIA CORPORATION. All rights reserved. 4 */ 5 package readers_test 6 7 import ( 8 "io" 9 "os" 10 "path" 11 "reflect" 12 "testing" 13 14 "github.com/NVIDIA/aistore/cmn/cos" 15 "github.com/NVIDIA/aistore/memsys" 16 "github.com/NVIDIA/aistore/tools/readers" 17 "github.com/NVIDIA/aistore/tools/tassert" 18 ) 19 20 const mmName = "readers_test" 21 22 func TestFileReader(t *testing.T) { 23 r, err := readers.NewRandFile("/tmp", "seek", 10240, cos.ChecksumNone) 24 if err != nil { 25 t.Fatal("Failed to create file reader", err) 26 } 27 tassert.CheckFatal(t, r.Close()) 28 } 29 30 func testReaderBasic(t *testing.T, r readers.Reader, size int64) { 31 _, err := r.Seek(0, io.SeekStart) 32 if err != nil { 33 t.Fatal("Failed to seek", err) 34 } 35 36 data := make([]byte, size) 37 n, err := r.Read(data) 38 if err != nil || int64(n) != size { 39 t.Fatal("Failed to read all data", n, err) 40 } 41 42 { 43 // Seek from start and read should return the correct data 44 n, err := r.Seek(100, io.SeekStart) 45 if err != nil || n != 100 { 46 t.Fatal("Failed to seek", n, err) 47 } 48 49 buf := make([]byte, 20) 50 m, err := r.Read(buf) 51 if err != nil || m != 20 { 52 t.Fatal("Failed to read after seek", n, err) 53 } 54 55 if !reflect.DeepEqual(buf, data[100:120]) { 56 t.Fatal("Failed to match data after seek and read", buf, data[100:120]) 57 } 58 59 r.Seek(0, io.SeekStart) 60 } 61 62 { 63 // Seek from end and read should return the correct data 64 _, err := r.Seek(-40, io.SeekEnd) 65 if err != nil { 66 t.Fatal("Failed to seek", err) 67 } 68 69 buf := make([]byte, 20) 70 m, err := r.Read(buf) 71 if err != nil || m != 20 { 72 t.Fatal("Failed to read after seek", n, err) 73 } 74 75 if !reflect.DeepEqual(buf, data[size-40:size-20]) { 76 t.Fatal("Failed to match data after seek and read", buf, data[size-40:size-20]) 77 } 78 79 r.Seek(0, io.SeekStart) 80 } 81 82 { 83 // Seek from end and read should return the correct data 84 _, err := r.Seek(-40, io.SeekEnd) 85 if err != nil { 86 t.Fatal("Failed to seek", err) 87 } 88 89 buf := make([]byte, 20) 90 m, err := r.Read(buf) 91 if err != nil || m != 20 { 92 t.Fatal("Failed to read after seek", n, err) 93 } 94 95 if !reflect.DeepEqual(buf, data[size-40:size-20]) { 96 t.Fatal("Failed to match data after seek and read", buf, data[size-40:size-20]) 97 } 98 99 r.Seek(0, io.SeekStart) 100 } 101 } 102 103 // NOTE: These are testcases that fail when running on SGReader. 104 func testReaderAdv(t *testing.T, r readers.Reader, size int64) { 105 buf := make([]byte, size) 106 _, err := r.Seek(0, io.SeekStart) 107 if err != nil { 108 t.Fatal("Failed to seek", err) 109 } 110 111 data := make([]byte, size) 112 n, err := r.Read(data) 113 if err != nil || int64(n) != size { 114 t.Fatal("Failed to read all data", n, err) 115 } 116 117 { 118 // Seek pass EOF 119 _, err := r.Seek(size+10, io.SeekStart) 120 if err != nil { 121 t.Fatal("Failed to seek pass EOF", err) 122 } 123 124 buf := make([]byte, 20) 125 _, err = r.Read(buf) 126 if err == nil { 127 t.Fatal("Failed to return error while reading pass EOF") 128 } 129 130 r.Seek(0, io.SeekStart) 131 } 132 133 { 134 // Seek relative and read should return the correct data 135 _, err := r.Seek(size-40, io.SeekStart) 136 if err != nil { 137 t.Fatal("Failed to seek", err) 138 } 139 140 n, err := r.Seek(-20, io.SeekCurrent) 141 if err != nil || n != size-60 { 142 t.Fatal("Failed to seek", n, err) 143 } 144 145 buf := make([]byte, 20) 146 m, err := r.Read(buf) 147 if err != nil || m != 20 { 148 t.Fatal("Failed to read after seek", n, err) 149 } 150 151 if !reflect.DeepEqual(buf, data[size-60:size-40]) { 152 t.Fatal("Failed to match data after seek and read", buf, data[size-60:size-40]) 153 } 154 155 r.Seek(0, io.SeekStart) 156 } 157 158 { 159 // Read return the correct number of data when there are enough data 160 m, err := r.Seek(0, io.SeekStart) 161 if err != nil { 162 t.Fatal("Failed to seek", err) 163 } 164 165 if m != 0 { 166 t.Fatal("Failed to seek to begin", m) 167 } 168 169 n, err := r.Read(buf[:size-20]) 170 if err != nil { 171 t.Fatal("Failed to seek", err) 172 } 173 174 if int64(n) != size-20 { 175 t.Fatalf("Failed to seek, expected %d, actual %d", size-20, n) 176 } 177 178 n, err = r.Read(buf[:8]) 179 if err != nil || n != 8 { 180 t.Fatal("Failed to read", n, err) 181 } 182 183 n, err = r.Read(buf[:8]) 184 if err != nil || n != 8 { 185 t.Fatal("Failed to read", n, err) 186 } 187 188 n, err = r.Read(buf[:8]) 189 if err != nil || n != 4 { 190 t.Fatal("Failed to read when there is less data", n, err) 191 } 192 193 _, err = r.Read(buf) 194 if err != io.EOF { 195 t.Fatal("Failed to read when it is EOF", err) 196 } 197 } 198 199 { 200 // Read return the correct number of data when there are enough data 201 o, err := r.Seek(-20, io.SeekEnd) 202 if err != nil { 203 t.Fatal("Failed to seek", err) 204 } 205 if o != size-20 { 206 t.Fatalf("Failed to seek, offset expected %d, actual %d", size-20, o) 207 } 208 209 buf := make([]byte, 8) 210 n, err := r.Read(buf) 211 if err != nil || n != 8 { 212 t.Fatal("Failed to read", n, err) 213 } 214 215 n, err = r.Read(buf) 216 if err != nil || n != 8 { 217 t.Fatal("Failed to read", n, err) 218 } 219 220 n, err = r.Read(buf) 221 if err != nil || n != 4 { 222 t.Fatal("Failed to read when there is less data", n, err) 223 } 224 225 _, err = r.Read(buf) 226 if err != io.EOF { 227 t.Fatal("Failed to read when it is EOF", err) 228 } 229 } 230 } 231 232 func TestRandReader(t *testing.T) { 233 size := int64(1024) 234 r, err := readers.NewRand(size, cos.ChecksumXXHash) 235 if err != nil { 236 t.Fatal(err) 237 } 238 testReaderBasic(t, r, size) 239 testReaderAdv(t, r, size) 240 r.Close() 241 } 242 243 func TestSGReader(t *testing.T) { 244 mmsa, _ := memsys.NewMMSA(mmName, false) 245 defer mmsa.Terminate(false) 246 { 247 // Basic read 248 size := int64(1024) 249 sgl := mmsa.NewSGL(size) 250 defer sgl.Free() 251 252 r, err := readers.NewSG(sgl, size, cos.ChecksumXXHash) 253 if err != nil { 254 t.Fatal(err) 255 } 256 257 buf := make([]byte, size) 258 n, err := r.Read(buf[:512]) 259 if err != nil && err != io.EOF { 260 t.Fatal(err) 261 } 262 263 if n != 512 { 264 t.Fatalf("Read returned wrong number of bytes, expected = %d, actual = %d", 512, n) 265 } 266 267 n, err = r.Read(buf) 268 if err != nil && err != io.EOF { 269 t.Fatal(err) 270 } 271 272 if n != 512 { 273 t.Fatalf("Read returned wrong number of bytes, expected = %d, actual = %d", 512, n) 274 } 275 276 r.Close() 277 } 278 279 { 280 size := int64(1024) 281 sgl := mmsa.NewSGL(size) 282 defer sgl.Free() 283 284 r, err := readers.NewSG(sgl, size, cos.ChecksumXXHash) 285 if err != nil { 286 t.Fatal(err) 287 } 288 testReaderBasic(t, r, size) 289 r.Close() 290 } 291 } 292 293 func BenchmarkFileReaderCreateWithHash1M(b *testing.B) { 294 filepath := "/tmp" 295 fn := "reader-test" 296 297 for range b.N { 298 r, err := readers.NewRandFile(filepath, fn, cos.MiB, cos.ChecksumXXHash) 299 if err != nil { 300 os.Remove(path.Join(filepath, fn)) 301 b.Fatal(err) 302 } 303 if err := r.Close(); err != nil { 304 os.Remove(path.Join(filepath, fn)) 305 b.Fatal(err) 306 } 307 os.Remove(path.Join(filepath, fn)) 308 } 309 } 310 311 func BenchmarkRandReaderCreateWithHash1M(b *testing.B) { 312 for range b.N { 313 r, err := readers.NewRand(cos.MiB, cos.ChecksumXXHash) 314 r.Close() 315 if err != nil { 316 b.Fatal(err) 317 } 318 } 319 } 320 321 func BenchmarkSGReaderCreateWithHash1M(b *testing.B) { 322 mmsa, _ := memsys.NewMMSA(mmName, false) 323 sgl := mmsa.NewSGL(cos.MiB) 324 defer func() { 325 sgl.Free() 326 mmsa.Terminate(false) 327 }() 328 329 for range b.N { 330 sgl.Reset() 331 r, err := readers.NewSG(sgl, cos.MiB, cos.ChecksumXXHash) 332 r.Close() 333 if err != nil { 334 b.Fatal(err) 335 } 336 } 337 } 338 339 func BenchmarkFileReaderCreateNoHash1M(b *testing.B) { 340 filepath := "/tmp" 341 fn := "reader-test" 342 343 for range b.N { 344 r, err := readers.NewRandFile(filepath, fn, cos.MiB, cos.ChecksumNone) 345 if err != nil { 346 os.Remove(path.Join(filepath, fn)) 347 b.Fatal(err) 348 } 349 if err := r.Close(); err != nil { 350 os.Remove(path.Join(filepath, fn)) 351 b.Fatal(err) 352 } 353 os.Remove(path.Join(filepath, fn)) 354 } 355 } 356 357 func BenchmarkRandReaderCreateNoHash1M(b *testing.B) { 358 for range b.N { 359 r, err := readers.NewRand(cos.MiB, cos.ChecksumNone) 360 r.Close() 361 if err != nil { 362 b.Fatal(err) 363 } 364 } 365 } 366 367 func BenchmarkSGReaderCreateNoHash1M(b *testing.B) { 368 mmsa, _ := memsys.NewMMSA(mmName, false) 369 sgl := mmsa.NewSGL(cos.MiB) 370 defer func() { 371 sgl.Free() 372 mmsa.Terminate(false) 373 }() 374 375 for range b.N { 376 sgl.Reset() 377 r, err := readers.NewSG(sgl, cos.MiB, cos.ChecksumNone) 378 r.Close() 379 if err != nil { 380 b.Fatal(err) 381 } 382 } 383 }