github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/io/io_test.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package io_test 6 7 import ( 8 "bytes" 9 "errors" 10 "fmt" 11 . "io" 12 "os" 13 "strings" 14 "sync" 15 "sync/atomic" 16 "testing" 17 ) 18 19 // A version of bytes.Buffer without ReadFrom and WriteTo 20 type Buffer struct { 21 bytes.Buffer 22 ReaderFrom // conflicts with and hides bytes.Buffer's ReaderFrom. 23 WriterTo // conflicts with and hides bytes.Buffer's WriterTo. 24 } 25 26 // Simple tests, primarily to verify the ReadFrom and WriteTo callouts inside Copy, CopyBuffer and CopyN. 27 28 func TestCopy(t *testing.T) { 29 rb := new(Buffer) 30 wb := new(Buffer) 31 rb.WriteString("hello, world.") 32 Copy(wb, rb) 33 if wb.String() != "hello, world." { 34 t.Errorf("Copy did not work properly") 35 } 36 } 37 38 func TestCopyNegative(t *testing.T) { 39 rb := new(Buffer) 40 wb := new(Buffer) 41 rb.WriteString("hello") 42 Copy(wb, &LimitedReader{R: rb, N: -1}) 43 if wb.String() != "" { 44 t.Errorf("Copy on LimitedReader with N<0 copied data") 45 } 46 47 CopyN(wb, rb, -1) 48 if wb.String() != "" { 49 t.Errorf("CopyN with N<0 copied data") 50 } 51 } 52 53 func TestCopyBuffer(t *testing.T) { 54 rb := new(Buffer) 55 wb := new(Buffer) 56 rb.WriteString("hello, world.") 57 CopyBuffer(wb, rb, make([]byte, 1)) // Tiny buffer to keep it honest. 58 if wb.String() != "hello, world." { 59 t.Errorf("CopyBuffer did not work properly") 60 } 61 } 62 63 func TestCopyBufferNil(t *testing.T) { 64 rb := new(Buffer) 65 wb := new(Buffer) 66 rb.WriteString("hello, world.") 67 CopyBuffer(wb, rb, nil) // Should allocate a buffer. 68 if wb.String() != "hello, world." { 69 t.Errorf("CopyBuffer did not work properly") 70 } 71 } 72 73 func TestCopyReadFrom(t *testing.T) { 74 rb := new(Buffer) 75 wb := new(bytes.Buffer) // implements ReadFrom. 76 rb.WriteString("hello, world.") 77 Copy(wb, rb) 78 if wb.String() != "hello, world." { 79 t.Errorf("Copy did not work properly") 80 } 81 } 82 83 func TestCopyWriteTo(t *testing.T) { 84 rb := new(bytes.Buffer) // implements WriteTo. 85 wb := new(Buffer) 86 rb.WriteString("hello, world.") 87 Copy(wb, rb) 88 if wb.String() != "hello, world." { 89 t.Errorf("Copy did not work properly") 90 } 91 } 92 93 // Version of bytes.Buffer that checks whether WriteTo was called or not 94 type writeToChecker struct { 95 bytes.Buffer 96 writeToCalled bool 97 } 98 99 func (wt *writeToChecker) WriteTo(w Writer) (int64, error) { 100 wt.writeToCalled = true 101 return wt.Buffer.WriteTo(w) 102 } 103 104 // It's preferable to choose WriterTo over ReaderFrom, since a WriterTo can issue one large write, 105 // while the ReaderFrom must read until EOF, potentially allocating when running out of buffer. 106 // Make sure that we choose WriterTo when both are implemented. 107 func TestCopyPriority(t *testing.T) { 108 rb := new(writeToChecker) 109 wb := new(bytes.Buffer) 110 rb.WriteString("hello, world.") 111 Copy(wb, rb) 112 if wb.String() != "hello, world." { 113 t.Errorf("Copy did not work properly") 114 } else if !rb.writeToCalled { 115 t.Errorf("WriteTo was not prioritized over ReadFrom") 116 } 117 } 118 119 type zeroErrReader struct { 120 err error 121 } 122 123 func (r zeroErrReader) Read(p []byte) (int, error) { 124 return copy(p, []byte{0}), r.err 125 } 126 127 type errWriter struct { 128 err error 129 } 130 131 func (w errWriter) Write([]byte) (int, error) { 132 return 0, w.err 133 } 134 135 // In case a Read results in an error with non-zero bytes read, and 136 // the subsequent Write also results in an error, the error from Write 137 // is returned, as it is the one that prevented progressing further. 138 func TestCopyReadErrWriteErr(t *testing.T) { 139 er, ew := errors.New("readError"), errors.New("writeError") 140 r, w := zeroErrReader{err: er}, errWriter{err: ew} 141 n, err := Copy(w, r) 142 if n != 0 || err != ew { 143 t.Errorf("Copy(zeroErrReader, errWriter) = %d, %v; want 0, writeError", n, err) 144 } 145 } 146 147 func TestCopyN(t *testing.T) { 148 rb := new(Buffer) 149 wb := new(Buffer) 150 rb.WriteString("hello, world.") 151 CopyN(wb, rb, 5) 152 if wb.String() != "hello" { 153 t.Errorf("CopyN did not work properly") 154 } 155 } 156 157 func TestCopyNReadFrom(t *testing.T) { 158 rb := new(Buffer) 159 wb := new(bytes.Buffer) // implements ReadFrom. 160 rb.WriteString("hello") 161 CopyN(wb, rb, 5) 162 if wb.String() != "hello" { 163 t.Errorf("CopyN did not work properly") 164 } 165 } 166 167 func TestCopyNWriteTo(t *testing.T) { 168 rb := new(bytes.Buffer) // implements WriteTo. 169 wb := new(Buffer) 170 rb.WriteString("hello, world.") 171 CopyN(wb, rb, 5) 172 if wb.String() != "hello" { 173 t.Errorf("CopyN did not work properly") 174 } 175 } 176 177 func BenchmarkCopyNSmall(b *testing.B) { 178 bs := bytes.Repeat([]byte{0}, 512+1) 179 rd := bytes.NewReader(bs) 180 buf := new(Buffer) 181 b.ResetTimer() 182 183 for i := 0; i < b.N; i++ { 184 CopyN(buf, rd, 512) 185 rd.Reset(bs) 186 } 187 } 188 189 func BenchmarkCopyNLarge(b *testing.B) { 190 bs := bytes.Repeat([]byte{0}, (32*1024)+1) 191 rd := bytes.NewReader(bs) 192 buf := new(Buffer) 193 b.ResetTimer() 194 195 for i := 0; i < b.N; i++ { 196 CopyN(buf, rd, 32*1024) 197 rd.Reset(bs) 198 } 199 } 200 201 type noReadFrom struct { 202 w Writer 203 } 204 205 func (w *noReadFrom) Write(p []byte) (n int, err error) { 206 return w.w.Write(p) 207 } 208 209 type wantedAndErrReader struct{} 210 211 func (wantedAndErrReader) Read(p []byte) (int, error) { 212 return len(p), errors.New("wantedAndErrReader error") 213 } 214 215 func TestCopyNEOF(t *testing.T) { 216 // Test that EOF behavior is the same regardless of whether 217 // argument to CopyN has ReadFrom. 218 219 b := new(bytes.Buffer) 220 221 n, err := CopyN(&noReadFrom{b}, strings.NewReader("foo"), 3) 222 if n != 3 || err != nil { 223 t.Errorf("CopyN(noReadFrom, foo, 3) = %d, %v; want 3, nil", n, err) 224 } 225 226 n, err = CopyN(&noReadFrom{b}, strings.NewReader("foo"), 4) 227 if n != 3 || err != EOF { 228 t.Errorf("CopyN(noReadFrom, foo, 4) = %d, %v; want 3, EOF", n, err) 229 } 230 231 n, err = CopyN(b, strings.NewReader("foo"), 3) // b has read from 232 if n != 3 || err != nil { 233 t.Errorf("CopyN(bytes.Buffer, foo, 3) = %d, %v; want 3, nil", n, err) 234 } 235 236 n, err = CopyN(b, strings.NewReader("foo"), 4) // b has read from 237 if n != 3 || err != EOF { 238 t.Errorf("CopyN(bytes.Buffer, foo, 4) = %d, %v; want 3, EOF", n, err) 239 } 240 241 n, err = CopyN(b, wantedAndErrReader{}, 5) 242 if n != 5 || err != nil { 243 t.Errorf("CopyN(bytes.Buffer, wantedAndErrReader, 5) = %d, %v; want 5, nil", n, err) 244 } 245 246 n, err = CopyN(&noReadFrom{b}, wantedAndErrReader{}, 5) 247 if n != 5 || err != nil { 248 t.Errorf("CopyN(noReadFrom, wantedAndErrReader, 5) = %d, %v; want 5, nil", n, err) 249 } 250 } 251 252 func TestReadAtLeast(t *testing.T) { 253 var rb bytes.Buffer 254 testReadAtLeast(t, &rb) 255 } 256 257 // A version of bytes.Buffer that returns n > 0, err on Read 258 // when the input is exhausted. 259 type dataAndErrorBuffer struct { 260 err error 261 bytes.Buffer 262 } 263 264 func (r *dataAndErrorBuffer) Read(p []byte) (n int, err error) { 265 n, err = r.Buffer.Read(p) 266 if n > 0 && r.Buffer.Len() == 0 && err == nil { 267 err = r.err 268 } 269 return 270 } 271 272 func TestReadAtLeastWithDataAndEOF(t *testing.T) { 273 var rb dataAndErrorBuffer 274 rb.err = EOF 275 testReadAtLeast(t, &rb) 276 } 277 278 func TestReadAtLeastWithDataAndError(t *testing.T) { 279 var rb dataAndErrorBuffer 280 rb.err = fmt.Errorf("fake error") 281 testReadAtLeast(t, &rb) 282 } 283 284 func testReadAtLeast(t *testing.T, rb ReadWriter) { 285 rb.Write([]byte("0123")) 286 buf := make([]byte, 2) 287 n, err := ReadAtLeast(rb, buf, 2) 288 if err != nil { 289 t.Error(err) 290 } 291 if n != 2 { 292 t.Errorf("expected to have read 2 bytes, got %v", n) 293 } 294 n, err = ReadAtLeast(rb, buf, 4) 295 if err != ErrShortBuffer { 296 t.Errorf("expected ErrShortBuffer got %v", err) 297 } 298 if n != 0 { 299 t.Errorf("expected to have read 0 bytes, got %v", n) 300 } 301 n, err = ReadAtLeast(rb, buf, 1) 302 if err != nil { 303 t.Error(err) 304 } 305 if n != 2 { 306 t.Errorf("expected to have read 2 bytes, got %v", n) 307 } 308 n, err = ReadAtLeast(rb, buf, 2) 309 if err != EOF { 310 t.Errorf("expected EOF, got %v", err) 311 } 312 if n != 0 { 313 t.Errorf("expected to have read 0 bytes, got %v", n) 314 } 315 rb.Write([]byte("4")) 316 n, err = ReadAtLeast(rb, buf, 2) 317 want := ErrUnexpectedEOF 318 if rb, ok := rb.(*dataAndErrorBuffer); ok && rb.err != EOF { 319 want = rb.err 320 } 321 if err != want { 322 t.Errorf("expected %v, got %v", want, err) 323 } 324 if n != 1 { 325 t.Errorf("expected to have read 1 bytes, got %v", n) 326 } 327 } 328 329 func TestTeeReader(t *testing.T) { 330 src := []byte("hello, world") 331 dst := make([]byte, len(src)) 332 rb := bytes.NewBuffer(src) 333 wb := new(bytes.Buffer) 334 r := TeeReader(rb, wb) 335 if n, err := ReadFull(r, dst); err != nil || n != len(src) { 336 t.Fatalf("ReadFull(r, dst) = %d, %v; want %d, nil", n, err, len(src)) 337 } 338 if !bytes.Equal(dst, src) { 339 t.Errorf("bytes read = %q want %q", dst, src) 340 } 341 if !bytes.Equal(wb.Bytes(), src) { 342 t.Errorf("bytes written = %q want %q", wb.Bytes(), src) 343 } 344 if n, err := r.Read(dst); n != 0 || err != EOF { 345 t.Errorf("r.Read at EOF = %d, %v want 0, EOF", n, err) 346 } 347 rb = bytes.NewBuffer(src) 348 pr, pw := Pipe() 349 pr.Close() 350 r = TeeReader(rb, pw) 351 if n, err := ReadFull(r, dst); n != 0 || err != ErrClosedPipe { 352 t.Errorf("closed tee: ReadFull(r, dst) = %d, %v; want 0, EPIPE", n, err) 353 } 354 } 355 356 func TestSectionReader_ReadAt(t *testing.T) { 357 dat := "a long sample data, 1234567890" 358 tests := []struct { 359 data string 360 off int 361 n int 362 bufLen int 363 at int 364 exp string 365 err error 366 }{ 367 {data: "", off: 0, n: 10, bufLen: 2, at: 0, exp: "", err: EOF}, 368 {data: dat, off: 0, n: len(dat), bufLen: 0, at: 0, exp: "", err: nil}, 369 {data: dat, off: len(dat), n: 1, bufLen: 1, at: 0, exp: "", err: EOF}, 370 {data: dat, off: 0, n: len(dat) + 2, bufLen: len(dat), at: 0, exp: dat, err: nil}, 371 {data: dat, off: 0, n: len(dat), bufLen: len(dat) / 2, at: 0, exp: dat[:len(dat)/2], err: nil}, 372 {data: dat, off: 0, n: len(dat), bufLen: len(dat), at: 0, exp: dat, err: nil}, 373 {data: dat, off: 0, n: len(dat), bufLen: len(dat) / 2, at: 2, exp: dat[2 : 2+len(dat)/2], err: nil}, 374 {data: dat, off: 3, n: len(dat), bufLen: len(dat) / 2, at: 2, exp: dat[5 : 5+len(dat)/2], err: nil}, 375 {data: dat, off: 3, n: len(dat) / 2, bufLen: len(dat)/2 - 2, at: 2, exp: dat[5 : 5+len(dat)/2-2], err: nil}, 376 {data: dat, off: 3, n: len(dat) / 2, bufLen: len(dat)/2 + 2, at: 2, exp: dat[5 : 5+len(dat)/2-2], err: EOF}, 377 {data: dat, off: 0, n: 0, bufLen: 0, at: -1, exp: "", err: EOF}, 378 {data: dat, off: 0, n: 0, bufLen: 0, at: 1, exp: "", err: EOF}, 379 } 380 for i, tt := range tests { 381 r := strings.NewReader(tt.data) 382 s := NewSectionReader(r, int64(tt.off), int64(tt.n)) 383 buf := make([]byte, tt.bufLen) 384 if n, err := s.ReadAt(buf, int64(tt.at)); n != len(tt.exp) || string(buf[:n]) != tt.exp || err != tt.err { 385 t.Fatalf("%d: ReadAt(%d) = %q, %v; expected %q, %v", i, tt.at, buf[:n], err, tt.exp, tt.err) 386 } 387 } 388 } 389 390 func TestSectionReader_Seek(t *testing.T) { 391 // Verifies that NewSectionReader's Seeker behaves like bytes.NewReader (which is like strings.NewReader) 392 br := bytes.NewReader([]byte("foo")) 393 sr := NewSectionReader(br, 0, int64(len("foo"))) 394 395 for _, whence := range []int{SeekStart, SeekCurrent, SeekEnd} { 396 for offset := int64(-3); offset <= 4; offset++ { 397 brOff, brErr := br.Seek(offset, whence) 398 srOff, srErr := sr.Seek(offset, whence) 399 if (brErr != nil) != (srErr != nil) || brOff != srOff { 400 t.Errorf("For whence %d, offset %d: bytes.Reader.Seek = (%v, %v) != SectionReader.Seek = (%v, %v)", 401 whence, offset, brOff, brErr, srErr, srOff) 402 } 403 } 404 } 405 406 // And verify we can just seek past the end and get an EOF 407 got, err := sr.Seek(100, SeekStart) 408 if err != nil || got != 100 { 409 t.Errorf("Seek = %v, %v; want 100, nil", got, err) 410 } 411 412 n, err := sr.Read(make([]byte, 10)) 413 if n != 0 || err != EOF { 414 t.Errorf("Read = %v, %v; want 0, EOF", n, err) 415 } 416 } 417 418 func TestSectionReader_Size(t *testing.T) { 419 tests := []struct { 420 data string 421 want int64 422 }{ 423 {"a long sample data, 1234567890", 30}, 424 {"", 0}, 425 } 426 427 for _, tt := range tests { 428 r := strings.NewReader(tt.data) 429 sr := NewSectionReader(r, 0, int64(len(tt.data))) 430 if got := sr.Size(); got != tt.want { 431 t.Errorf("Size = %v; want %v", got, tt.want) 432 } 433 } 434 } 435 436 func TestSectionReader_Max(t *testing.T) { 437 r := strings.NewReader("abcdef") 438 const maxint64 = 1<<63 - 1 439 sr := NewSectionReader(r, 3, maxint64) 440 n, err := sr.Read(make([]byte, 3)) 441 if n != 3 || err != nil { 442 t.Errorf("Read = %v %v, want 3, nil", n, err) 443 } 444 n, err = sr.Read(make([]byte, 3)) 445 if n != 0 || err != EOF { 446 t.Errorf("Read = %v, %v, want 0, EOF", n, err) 447 } 448 } 449 450 // largeWriter returns an invalid count that is larger than the number 451 // of bytes provided (issue 39978). 452 type largeWriter struct { 453 err error 454 } 455 456 func (w largeWriter) Write(p []byte) (int, error) { 457 return len(p) + 1, w.err 458 } 459 460 func TestCopyLargeWriter(t *testing.T) { 461 want := ErrInvalidWrite 462 rb := new(Buffer) 463 wb := largeWriter{} 464 rb.WriteString("hello, world.") 465 if _, err := Copy(wb, rb); err != want { 466 t.Errorf("Copy error: got %v, want %v", err, want) 467 } 468 469 want = errors.New("largeWriterError") 470 rb = new(Buffer) 471 wb = largeWriter{err: want} 472 rb.WriteString("hello, world.") 473 if _, err := Copy(wb, rb); err != want { 474 t.Errorf("Copy error: got %v, want %v", err, want) 475 } 476 } 477 478 func TestNopCloserWriterToForwarding(t *testing.T) { 479 for _, tc := range [...]struct { 480 Name string 481 r Reader 482 }{ 483 {"not a WriterTo", Reader(nil)}, 484 {"a WriterTo", struct { 485 Reader 486 WriterTo 487 }{}}, 488 } { 489 nc := NopCloser(tc.r) 490 491 _, expected := tc.r.(WriterTo) 492 _, got := nc.(WriterTo) 493 if expected != got { 494 t.Errorf("NopCloser incorrectly forwards WriterTo for %s, got %t want %t", tc.Name, got, expected) 495 } 496 } 497 } 498 499 func TestOffsetWriter_Seek(t *testing.T) { 500 tmpfilename := "TestOffsetWriter_Seek" 501 tmpfile, err := os.CreateTemp(t.TempDir(), tmpfilename) 502 if err != nil || tmpfile == nil { 503 t.Fatalf("CreateTemp(%s) failed: %v", tmpfilename, err) 504 } 505 defer tmpfile.Close() 506 w := NewOffsetWriter(tmpfile, 0) 507 508 // Should throw error errWhence if whence is not valid 509 t.Run("errWhence", func(t *testing.T) { 510 for _, whence := range []int{-3, -2, -1, 3, 4, 5} { 511 var offset int64 = 0 512 gotOff, gotErr := w.Seek(offset, whence) 513 if gotOff != 0 || gotErr != ErrWhence { 514 t.Errorf("For whence %d, offset %d, OffsetWriter.Seek got: (%d, %v), want: (%d, %v)", 515 whence, offset, gotOff, gotErr, 0, ErrWhence) 516 } 517 } 518 }) 519 520 // Should throw error errOffset if offset is negative 521 t.Run("errOffset", func(t *testing.T) { 522 for _, whence := range []int{SeekStart, SeekCurrent} { 523 for offset := int64(-3); offset < 0; offset++ { 524 gotOff, gotErr := w.Seek(offset, whence) 525 if gotOff != 0 || gotErr != ErrOffset { 526 t.Errorf("For whence %d, offset %d, OffsetWriter.Seek got: (%d, %v), want: (%d, %v)", 527 whence, offset, gotOff, gotErr, 0, ErrOffset) 528 } 529 } 530 } 531 }) 532 533 // Normal tests 534 t.Run("normal", func(t *testing.T) { 535 tests := []struct { 536 offset int64 537 whence int 538 returnOff int64 539 }{ 540 // keep in order 541 {whence: SeekStart, offset: 1, returnOff: 1}, 542 {whence: SeekStart, offset: 2, returnOff: 2}, 543 {whence: SeekStart, offset: 3, returnOff: 3}, 544 {whence: SeekCurrent, offset: 1, returnOff: 4}, 545 {whence: SeekCurrent, offset: 2, returnOff: 6}, 546 {whence: SeekCurrent, offset: 3, returnOff: 9}, 547 } 548 for idx, tt := range tests { 549 gotOff, gotErr := w.Seek(tt.offset, tt.whence) 550 if gotOff != tt.returnOff || gotErr != nil { 551 t.Errorf("%d:: For whence %d, offset %d, OffsetWriter.Seek got: (%d, %v), want: (%d, <nil>)", 552 idx+1, tt.whence, tt.offset, gotOff, gotErr, tt.returnOff) 553 } 554 } 555 }) 556 } 557 558 func TestOffsetWriter_WriteAt(t *testing.T) { 559 const content = "0123456789ABCDEF" 560 contentSize := int64(len(content)) 561 tmpdir, err := os.MkdirTemp(t.TempDir(), "TestOffsetWriter_WriteAt") 562 if err != nil { 563 t.Fatal(err) 564 } 565 566 work := func(off, at int64) { 567 position := fmt.Sprintf("off_%d_at_%d", off, at) 568 tmpfile, err := os.CreateTemp(tmpdir, position) 569 if err != nil || tmpfile == nil { 570 t.Fatalf("CreateTemp(%s) failed: %v", position, err) 571 } 572 defer tmpfile.Close() 573 574 var writeN int64 575 var wg sync.WaitGroup 576 // Concurrent writes, one byte at a time 577 for step, value := range []byte(content) { 578 wg.Add(1) 579 go func(wg *sync.WaitGroup, tmpfile *os.File, value byte, off, at int64, step int) { 580 defer wg.Done() 581 582 w := NewOffsetWriter(tmpfile, off) 583 n, e := w.WriteAt([]byte{value}, at+int64(step)) 584 if e != nil { 585 t.Errorf("WriteAt failed. off: %d, at: %d, step: %d\n error: %v", off, at, step, e) 586 } 587 atomic.AddInt64(&writeN, int64(n)) 588 }(&wg, tmpfile, value, off, at, step) 589 } 590 wg.Wait() 591 592 // Read one more byte to reach EOF 593 buf := make([]byte, contentSize+1) 594 readN, err := tmpfile.ReadAt(buf, off+at) 595 if err != EOF { 596 t.Fatalf("ReadAt failed: %v", err) 597 } 598 readContent := string(buf[:contentSize]) 599 if writeN != int64(readN) || writeN != contentSize || readContent != content { 600 t.Fatalf("%s:: WriteAt(%s, %d) error. \ngot n: %v, content: %s \nexpected n: %v, content: %v", 601 position, content, at, readN, readContent, contentSize, content) 602 } 603 } 604 for off := int64(0); off < 2; off++ { 605 for at := int64(0); at < 2; at++ { 606 work(off, at) 607 } 608 } 609 } 610 611 func TestOffsetWriter_Write(t *testing.T) { 612 const content = "0123456789ABCDEF" 613 contentSize := len(content) 614 tmpdir := t.TempDir() 615 616 makeOffsetWriter := func(name string) (*OffsetWriter, *os.File) { 617 tmpfilename := "TestOffsetWriter_Write_" + name 618 tmpfile, err := os.CreateTemp(tmpdir, tmpfilename) 619 if err != nil || tmpfile == nil { 620 t.Fatalf("CreateTemp(%s) failed: %v", tmpfilename, err) 621 } 622 return NewOffsetWriter(tmpfile, 0), tmpfile 623 } 624 checkContent := func(name string, f *os.File) { 625 // Read one more byte to reach EOF 626 buf := make([]byte, contentSize+1) 627 readN, err := f.ReadAt(buf, 0) 628 if err != EOF { 629 t.Fatalf("ReadAt failed, err: %v", err) 630 } 631 readContent := string(buf[:contentSize]) 632 if readN != contentSize || readContent != content { 633 t.Fatalf("%s error. \ngot n: %v, content: %s \nexpected n: %v, content: %v", 634 name, readN, readContent, contentSize, content) 635 } 636 } 637 638 var name string 639 name = "Write" 640 t.Run(name, func(t *testing.T) { 641 // Write directly (off: 0, at: 0) 642 // Write content to file 643 w, f := makeOffsetWriter(name) 644 defer f.Close() 645 for _, value := range []byte(content) { 646 n, err := w.Write([]byte{value}) 647 if err != nil { 648 t.Fatalf("Write failed, n: %d, err: %v", n, err) 649 } 650 } 651 checkContent(name, f) 652 653 // Copy -> Write 654 // Copy file f to file f2 655 name = "Copy" 656 w2, f2 := makeOffsetWriter(name) 657 defer f2.Close() 658 Copy(w2, f) 659 checkContent(name, f2) 660 }) 661 662 // Copy -> WriteTo -> Write 663 // Note: strings.Reader implements the io.WriterTo interface. 664 name = "Write_Of_Copy_WriteTo" 665 t.Run(name, func(t *testing.T) { 666 w, f := makeOffsetWriter(name) 667 defer f.Close() 668 Copy(w, strings.NewReader(content)) 669 checkContent(name, f) 670 }) 671 }