github.com/avfs/avfs@v0.33.1-0.20240303173310-c6ba67c33eb7/test/test_file.go (about) 1 // 2 // Copyright 2021 The AVFS authors 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 package test 18 19 import ( 20 "bytes" 21 "io" 22 "io/fs" 23 "os" 24 "reflect" 25 "testing" 26 "time" 27 28 "github.com/avfs/avfs" 29 ) 30 31 func (ts *Suite) TestFile(t *testing.T) { 32 ts.RunTests(t, UsrTest, 33 ts.TestFileChdir, 34 ts.TestFileCloseWrite, 35 ts.TestFileCloseRead, 36 ts.TestFileFd, 37 ts.TestFileName, 38 ts.TestFileRead, 39 ts.TestFileReadAt, 40 ts.TestFileReadDir, 41 ts.TestFileReaddirnames, 42 ts.TestFileSeek, 43 ts.TestFileStat, 44 ts.TestFileSync, 45 ts.TestFileTruncate, 46 ts.TestFileWrite, 47 ts.TestFileWriteAt, 48 ts.TestFileWriteString, 49 ts.TestFileWriteTime) 50 51 // Tests to be run as root 52 adminUser := ts.idm.AdminUser() 53 ts.RunTests(t, adminUser.Name(), 54 ts.TestFileChmod, 55 ts.TestFileChown, 56 ) 57 } 58 59 // TestFileChdir tests File.Chdir function. 60 func (ts *Suite) TestFileChdir(t *testing.T, testDir string) { 61 dirs := ts.createSampleDirs(t, testDir) 62 vfs := ts.vfsTest 63 64 t.Run("FileChdir", func(t *testing.T) { 65 for _, dir := range dirs { 66 f, err := vfs.OpenFile(dir.Path, os.O_RDONLY, 0) 67 RequireNoError(t, err, "OpenFile %s", dir.Path) 68 69 defer f.Close() 70 71 err = f.Chdir() 72 AssertNoError(t, err, "Chdir %s", dir.Path) 73 74 curDir, err := vfs.Getwd() 75 AssertNoError(t, err, "Getwd %s", dir.Path) 76 77 if curDir != dir.Path { 78 t.Errorf("Getwd : want current directory to be %s, got %s", dir.Path, curDir) 79 } 80 } 81 }) 82 83 t.Run("FileChdirOnFile", func(t *testing.T) { 84 f, fileName := ts.openedEmptyFile(t, testDir) 85 86 defer f.Close() 87 88 err := f.Chdir() 89 AssertPathError(t, err).Op("chdir").Path(fileName). 90 OSType(avfs.OsLinux).Err(avfs.ErrNotADirectory).Test(). 91 OSType(avfs.OsWindows).Err(avfs.ErrWinDirNameInvalid).Test() 92 }) 93 94 t.Run("FileChdirClosed", func(t *testing.T) { 95 f, fileName := ts.closedFile(t, testDir) 96 97 err := f.Chdir() 98 AssertPathError(t, err).Op("chdir").Path(fileName).Err(fs.ErrClosed).Test() 99 }) 100 101 t.Run("FileChdirNonExisting", func(t *testing.T) { 102 f := ts.openedNonExistingFile(t, testDir) 103 104 err := f.Chdir() 105 AssertInvalid(t, err, "Chdir") 106 }) 107 } 108 109 // TestFileChmod tests File.Chmod function. 110 func (ts *Suite) TestFileChmod(t *testing.T, testDir string) { 111 vfs := ts.vfsTest 112 113 if vfs.HasFeature(avfs.FeatReadOnly) { 114 f, fileName := ts.openedEmptyFile(t, testDir) 115 116 defer f.Close() 117 118 err := f.Chmod(0) 119 AssertPathError(t, err).Op("chmod").Path(fileName).ErrPermDenied().Test() 120 121 return 122 } 123 124 t.Run("FileChmodClosed", func(t *testing.T) { 125 f, fileName := ts.closedFile(t, testDir) 126 127 err := f.Chmod(avfs.DefaultFilePerm) 128 AssertPathError(t, err).Op("chmod").Path(fileName).Err(fs.ErrClosed).Test() 129 }) 130 131 t.Run("FileChmodNonExisting", func(t *testing.T) { 132 f := ts.openedNonExistingFile(t, testDir) 133 134 err := f.Chmod(0) 135 AssertInvalid(t, err, "Chmod") 136 }) 137 } 138 139 // TestFileChown tests File.Chown function. 140 func (ts *Suite) TestFileChown(t *testing.T, testDir string) { 141 vfs := ts.vfsTest 142 143 if vfs.HasFeature(avfs.FeatReadOnly) { 144 f, fileName := ts.openedEmptyFile(t, testDir) 145 146 defer f.Close() 147 148 err := f.Chown(0, 0) 149 AssertPathError(t, err).Op("chown").Path(fileName).ErrPermDenied().Test() 150 151 return 152 } 153 154 t.Run("FileChown", func(t *testing.T) { 155 f, _ := ts.openedEmptyFile(t, testDir) 156 157 defer f.Close() 158 159 u := vfs.User() 160 uid, gid := u.Uid(), u.Gid() 161 162 err := f.Chown(uid, gid) 163 164 AssertPathError(t, err).Op("chown"). 165 OSType(avfs.OsLinux).NoError().Test(). 166 OSType(avfs.OsWindows).Path(f.Name()).Err(avfs.ErrWinNotSupported).Test() 167 }) 168 169 t.Run("FileChownClosed", func(t *testing.T) { 170 f, fileName := ts.closedFile(t, testDir) 171 172 err := f.Chown(0, 0) 173 AssertPathError(t, err).Op("chown").Path(fileName).Err(fs.ErrClosed).Test() 174 }) 175 176 t.Run("FileChownNonExisting", func(t *testing.T) { 177 f := ts.openedNonExistingFile(t, testDir) 178 179 err := f.Chown(0, 0) 180 AssertInvalid(t, err, "Chown") 181 }) 182 } 183 184 // TestFileCloseRead tests File.Close function for read only files. 185 func (ts *Suite) TestFileCloseRead(t *testing.T, testDir string) { 186 data := []byte("AAABBBCCCDDD") 187 path := ts.existingFile(t, testDir, data) 188 vfs := ts.vfsTest 189 190 t.Run("FileCloseReadOnly", func(t *testing.T) { 191 openInfo, err := vfs.Stat(path) 192 RequireNoError(t, err, "Stat %s", path) 193 194 f, err := vfs.OpenFile(path, os.O_RDONLY, 0) 195 RequireNoError(t, err, "OpenFile %s", path) 196 197 err = f.Close() 198 RequireNoError(t, err, "Close %s", path) 199 200 closeInfo, err := vfs.Stat(path) 201 RequireNoError(t, err, "Stat %s", path) 202 203 if !reflect.DeepEqual(openInfo, closeInfo) { 204 t.Errorf("Stat %s : open info != close info\n%v\n%v", path, openInfo, closeInfo) 205 } 206 207 err = f.Close() 208 AssertPathError(t, err).Op("close").Path(path).Err(fs.ErrClosed).Test() 209 }) 210 211 t.Run("FileCloseNonExisting", func(t *testing.T) { 212 f := ts.openedNonExistingFile(t, testDir) 213 214 err := f.Close() 215 AssertInvalid(t, err, "Close") 216 }) 217 } 218 219 // TestFileCloseWrite tests File.Close function for read/write files. 220 func (ts *Suite) TestFileCloseWrite(t *testing.T, testDir string) { 221 vfs := ts.vfsTest 222 if vfs.HasFeature(avfs.FeatReadOnly) { 223 return 224 } 225 226 data := []byte("AAABBBCCCDDD") 227 path := ts.existingFile(t, testDir, data) 228 229 openInfo, err := vfs.Stat(path) 230 RequireNoError(t, err, "Stat %s", path) 231 232 t.Run("FileCloseWrite", func(t *testing.T) { 233 f, err := vfs.OpenFile(path, os.O_APPEND|os.O_WRONLY, avfs.DefaultFilePerm) 234 RequireNoError(t, err, "OpenFile %s", path) 235 236 n, err := f.Write(data) 237 RequireNoError(t, err, "Write %s", path) 238 239 if n != len(data) { 240 t.Fatalf("Write : want bytes written to be %d, got %d", len(data), n) 241 } 242 243 err = f.Close() 244 RequireNoError(t, err, "Close %s", path) 245 246 closeInfo, err := vfs.Stat(path) 247 RequireNoError(t, err, "Stat %s", path) 248 249 if reflect.DeepEqual(openInfo, closeInfo) { 250 t.Errorf("Stat %s : open info != close info\n%v\n%v", path, openInfo, closeInfo) 251 } 252 253 err = f.Close() 254 AssertPathError(t, err).Op("close").Path(path).Err(fs.ErrClosed).Test() 255 }) 256 } 257 258 // TestFileFd tests File.Fd function. 259 func (ts *Suite) TestFileFd(t *testing.T, testDir string) { 260 f, fileName := ts.closedFile(t, testDir) 261 262 fd := f.Fd() 263 if fd != ^(uintptr(0)) { 264 t.Errorf("Fd %s : want Fd to be %d, got %d", fileName, ^(uintptr(0)), fd) 265 } 266 } 267 268 // TestFileName tests File.Name function. 269 func (ts *Suite) TestFileName(t *testing.T, testDir string) { 270 f, wantName := ts.closedFile(t, testDir) 271 272 name := f.Name() 273 if name != wantName { 274 t.Errorf("Name %s : want Name to be %s, got %s", wantName, wantName, name) 275 } 276 } 277 278 // FileNilPtr test calls to File methods when f is a nil File. 279 func FileNilPtr(t *testing.T, f avfs.File) { 280 err := f.Chdir() 281 AssertInvalid(t, err, "Chdir") 282 283 err = f.Chmod(0) 284 AssertInvalid(t, err, "Chmod") 285 286 err = f.Chown(0, 0) 287 AssertInvalid(t, err, "Chown") 288 289 err = f.Close() 290 AssertInvalid(t, err, "Close") 291 292 AssertPanic(t, "f.Name()", func() { _ = f.Name() }) 293 294 fd := f.Fd() 295 if fd != ^(uintptr(0)) { 296 t.Errorf("Fd : want fd to be %d, got %d", 0, fd) 297 } 298 299 _, err = f.Read([]byte{}) 300 AssertInvalid(t, err, "Read") 301 302 _, err = f.ReadAt([]byte{}, 0) 303 AssertInvalid(t, err, "ReadAt") 304 305 _, err = f.ReadDir(0) 306 AssertInvalid(t, err, "ReadDir") 307 308 _, err = f.Readdirnames(0) 309 AssertInvalid(t, err, "Readdirnames") 310 311 _, err = f.Seek(0, io.SeekStart) 312 AssertInvalid(t, err, "Seek") 313 314 _, err = f.Stat() 315 AssertInvalid(t, err, "Stat") 316 317 err = f.Sync() 318 AssertInvalid(t, err, "Sync") 319 320 err = f.Truncate(0) 321 AssertInvalid(t, err, "Truncate") 322 323 _, err = f.Write([]byte{}) 324 AssertInvalid(t, err, "Write") 325 326 _, err = f.WriteAt([]byte{}, 0) 327 AssertInvalid(t, err, "WriteAt") 328 329 _, err = f.WriteString("") 330 AssertInvalid(t, err, "WriteString") 331 } 332 333 // TestFileRead tests File.Read function. 334 func (ts *Suite) TestFileRead(t *testing.T, testDir string) { 335 data := []byte("AAABBBCCCDDD") 336 path := ts.existingFile(t, testDir, data) 337 vfs := ts.vfsTest 338 339 t.Run("FileRead", func(t *testing.T) { 340 const bufSize = 5 341 342 f, err := vfs.OpenFile(path, os.O_RDONLY, avfs.DefaultFilePerm) 343 RequireNoError(t, err, "OpenFile %s", path) 344 345 defer f.Close() 346 347 buf := make([]byte, bufSize) 348 349 for i := 0; ; i += bufSize { 350 n, err1 := f.Read(buf) 351 if err1 != nil { 352 if err1 == io.EOF { 353 break 354 } 355 356 t.Errorf("Read : want error to be %v, got %v", io.EOF, err1) 357 } 358 359 if !bytes.Equal(buf[:n], data[i:i+n]) { 360 t.Errorf("Read : want content to be %s, got %s", buf[:n], data[i:i+n]) 361 } 362 } 363 }) 364 365 t.Run("FileReadNonExisting", func(t *testing.T) { 366 f := ts.openedNonExistingFile(t, testDir) 367 buf := make([]byte, 0) 368 369 _, err := f.Read(buf) 370 AssertInvalid(t, err, "Read") 371 }) 372 373 t.Run("FileReadOnDir", func(t *testing.T) { 374 f, err := vfs.OpenFile(testDir, os.O_RDONLY, 0) 375 RequireNoError(t, err, "OpenFile %s", testDir) 376 377 defer f.Close() 378 379 b := make([]byte, 1) 380 381 _, err = f.Read(b) 382 AssertPathError(t, err).Op("read").Path(testDir). 383 OSType(avfs.OsLinux).Err(avfs.ErrIsADirectory).Test(). 384 OSType(avfs.OsWindows).Err(avfs.ErrWinIncorrectFunc).Test() 385 }) 386 387 t.Run("FileReadClosed", func(t *testing.T) { 388 f, fileName := ts.closedFile(t, testDir) 389 390 b := make([]byte, 1) 391 392 _, err := f.Read(b) 393 AssertPathError(t, err).Op("read").Path(fileName).Err(fs.ErrClosed).Test() 394 }) 395 } 396 397 // TestFileReadAt tests File.ReadAt function. 398 func (ts *Suite) TestFileReadAt(t *testing.T, testDir string) { 399 data := []byte("AAABBBCCCDDD") 400 path := ts.existingFile(t, testDir, data) 401 vfs := ts.vfsTest 402 403 t.Run("FileReadAt", func(t *testing.T) { 404 const bufSize = 3 405 406 f, err := vfs.OpenFile(path, os.O_RDONLY, avfs.DefaultFilePerm) 407 RequireNoError(t, err, "OpenFile %s", path) 408 409 defer f.Close() 410 411 var n int 412 413 rb := make([]byte, bufSize) 414 for i := len(data); i > 0; i -= bufSize { 415 n, err = f.ReadAt(rb, int64(i-bufSize)) 416 RequireNoError(t, err, "ReadAt %s", path) 417 418 if n != bufSize { 419 t.Errorf("ReadAt : want bytes read to be %d, got %d", bufSize, n) 420 } 421 422 if !bytes.Equal(rb, data[i-bufSize:i]) { 423 t.Errorf("ReadAt : want bytes read to be %d, got %d", bufSize, n) 424 } 425 } 426 }) 427 428 t.Run("FileReadAtNonExisting", func(t *testing.T) { 429 f := ts.openedNonExistingFile(t, testDir) 430 buf := make([]byte, 0) 431 432 _, err := f.ReadAt(buf, 0) 433 AssertInvalid(t, err, "ReadAt") 434 }) 435 436 t.Run("FileReadAtAfterEndOfFile", func(t *testing.T) { 437 f, err := vfs.OpenFile(path, os.O_RDONLY, 0) 438 RequireNoError(t, err, "OpenFile %s", path) 439 440 defer f.Close() 441 442 b := make([]byte, 1) 443 444 off := int64(len(data) * 2) 445 446 n, err := f.ReadAt(b, off) 447 if err != io.EOF { 448 t.Errorf("ReadAt : want error to be %v, got %v", io.EOF, err) 449 } 450 451 if n != 0 { 452 t.Errorf("ReadAt : want bytes read to be 0, got %d", n) 453 } 454 455 n, err = f.ReadAt(b, -1) 456 AssertPathError(t, err).Op("readat").Path(path).Err(avfs.ErrNegativeOffset).Test() 457 458 if n != 0 { 459 t.Errorf("ReadAt : want bytes read to be 0, got %d", n) 460 } 461 }) 462 463 t.Run("FileReadAtOnDir", func(t *testing.T) { 464 f, err := vfs.OpenFile(testDir, os.O_RDONLY, 0) 465 RequireNoError(t, err, "OpenFile %s", path) 466 467 defer f.Close() 468 469 b := make([]byte, 1) 470 471 _, err = f.ReadAt(b, 0) 472 AssertPathError(t, err).Op("read").Path(testDir). 473 OSType(avfs.OsLinux).Err(avfs.ErrIsADirectory).Test(). 474 OSType(avfs.OsWindows).Err(avfs.ErrWinIncorrectFunc).Test() 475 }) 476 477 t.Run("FileReadAtClosed", func(t *testing.T) { 478 f, fileName := ts.closedFile(t, testDir) 479 480 b := make([]byte, 1) 481 482 _, err := f.ReadAt(b, 0) 483 AssertPathError(t, err).Op("read").Path(fileName).Err(fs.ErrClosed).Test() 484 }) 485 } 486 487 // TestFileReadDir tests File.ReadDir function. 488 func (ts *Suite) TestFileReadDir(t *testing.T, testDir string) { 489 rndTree := ts.randomDir(t, testDir) 490 wantDirs := len(rndTree.Dirs()) 491 wantFiles := len(rndTree.Files()) 492 wantSymlinks := len(rndTree.SymLinks()) 493 vfs := ts.vfsTest 494 495 const maxRead = 7 496 497 t.Run("FileReadDirN", func(t *testing.T) { 498 f, err := vfs.OpenFile(testDir, os.O_RDONLY, 0) 499 RequireNoError(t, err, "OpenFile %s", testDir) 500 501 defer f.Close() 502 503 var dirEntries []fs.DirEntry 504 505 for { 506 dirEntriesN, err := f.ReadDir(maxRead) 507 if err == io.EOF { 508 break 509 } 510 511 RequireNoError(t, err, "ReadDir %s", testDir) 512 513 dirEntries = append(dirEntries, dirEntriesN...) 514 } 515 516 var gotDirs, gotFiles, gotSymlinks int 517 518 for _, dirEntry := range dirEntries { 519 switch { 520 case dirEntry.IsDir(): 521 gotDirs++ 522 case dirEntry.Type()&fs.ModeSymlink != 0: 523 gotSymlinks++ 524 default: 525 gotFiles++ 526 } 527 } 528 529 if wantDirs != gotDirs { 530 t.Errorf("ReadDirN : want number of dirs to be %d, got %d", wantDirs, gotDirs) 531 } 532 533 if wantFiles != gotFiles { 534 t.Errorf("ReadDirN : want number of files to be %d, got %d", wantFiles, gotFiles) 535 } 536 537 if wantSymlinks != gotSymlinks { 538 t.Errorf("ReadDirN : want number of symbolic links to be %d, got %d", wantSymlinks, gotSymlinks) 539 } 540 }) 541 542 t.Run("FileReadDirExistingFile", func(t *testing.T) { 543 f, fileName := ts.openedEmptyFile(t, testDir) 544 545 defer f.Close() 546 547 _, err := f.ReadDir(-1) 548 AssertPathError(t, err).Path(fileName). 549 OSType(avfs.OsLinux).Op("readdirent").Err(avfs.ErrNotADirectory).Test(). 550 OSType(avfs.OsWindows).Op("readdir").Err(avfs.ErrWinPathNotFound).Test() 551 }) 552 553 t.Run("FileReadDirClosed", func(t *testing.T) { 554 f, fileName := ts.closedFile(t, testDir) 555 556 _, err := f.ReadDir(-1) 557 AssertPathError(t, err).Path(fileName). 558 OSType(avfs.OsLinux).Op("readdirent").Err(avfs.ErrFileClosing).Test(). 559 OSType(avfs.OsWindows).Op("readdir").Err(avfs.ErrWinInvalidHandle).Test() 560 }) 561 562 t.Run("FileReadDirNonExisting", func(t *testing.T) { 563 f := ts.openedNonExistingFile(t, testDir) 564 565 _, err := f.ReadDir(-1) 566 AssertInvalid(t, err, "ReadDir") 567 }) 568 } 569 570 // TestFileReaddirnames tests File.Readdirnames function. 571 func (ts *Suite) TestFileReaddirnames(t *testing.T, testDir string) { 572 rndTree := ts.randomDir(t, testDir) 573 wantAll := len(rndTree.Dirs()) + len(rndTree.Files()) + len(rndTree.SymLinks()) 574 575 vfs := ts.vfsTest 576 existingFile := vfs.Join(testDir, rndTree.Files()[0].Name) 577 578 t.Run("FileReaddirnamesAll", func(t *testing.T) { 579 f, err := vfs.OpenFile(testDir, os.O_RDONLY, 0) 580 RequireNoError(t, err, "OpenFile %s", testDir) 581 582 defer f.Close() 583 584 names, err := f.Readdirnames(-1) 585 RequireNoError(t, err, "Readdirnames %s", testDir) 586 587 if wantAll != len(names) { 588 t.Errorf("TestFileReaddirnames : want number of elements to be %d, got %d", wantAll, len(names)) 589 } 590 }) 591 592 t.Run("FileReaddirnamesN", func(t *testing.T) { 593 f, err := vfs.OpenFile(testDir, os.O_RDONLY, 0) 594 RequireNoError(t, err, "OpenFile %s", testDir) 595 596 defer f.Close() 597 598 var names []string 599 600 for { 601 namesN, err := f.Readdirnames(11) 602 if err == io.EOF { 603 break 604 } 605 606 RequireNoError(t, err, "ReadDirNamesN %s", testDir) 607 608 names = append(names, namesN...) 609 } 610 611 gotAll := len(names) 612 if len(names) != wantAll { 613 t.Errorf("ReadDirNamesN : want number of elements to be %d, got %d", wantAll, gotAll) 614 } 615 }) 616 617 t.Run("FileReaddirnamesExistingFile", func(t *testing.T) { 618 f, err := vfs.OpenFile(existingFile, os.O_RDONLY, 0) 619 RequireNoError(t, err, "OpenFile %s", existingFile) 620 621 defer f.Close() 622 623 _, err = f.Readdirnames(-1) 624 AssertPathError(t, err).Path(f.Name()). 625 OSType(avfs.OsLinux).Op("readdirent").Err(avfs.ErrNotADirectory).Test(). 626 OSType(avfs.OsWindows).Op("readdir").Err(avfs.ErrWinPathNotFound).Test() 627 }) 628 629 t.Run("FileReaddirnamesClosed", func(t *testing.T) { 630 f, fileName := ts.closedFile(t, testDir) 631 632 _, err := f.Readdirnames(-1) 633 AssertPathError(t, err).Path(fileName). 634 OSType(avfs.OsLinux).Op("readdirent").Err(avfs.ErrFileClosing).Test(). 635 OSType(avfs.OsWindows).Op("readdir").Err(avfs.ErrWinInvalidHandle).Test() 636 }) 637 638 t.Run("FileReaddirnamesNonExisting", func(t *testing.T) { 639 f := ts.openedNonExistingFile(t, testDir) 640 641 _, err := f.Readdirnames(-1) 642 AssertInvalid(t, err, "Readdirnames") 643 }) 644 } 645 646 // TestFileSeek tests File.Seek function. 647 func (ts *Suite) TestFileSeek(t *testing.T, testDir string) { 648 data := []byte("AAABBBCCCDDD") 649 path := ts.existingFile(t, testDir, data) 650 vfs := ts.vfsTest 651 652 f, err := vfs.OpenFile(path, os.O_RDONLY, 0) 653 RequireNoError(t, err, "OpenFile %s", path) 654 655 defer f.Close() 656 657 pos := int64(0) 658 lenData := int64(len(data)) 659 660 t.Run("TestFileSeek", func(t *testing.T) { 661 for i := 0; i < len(data); i++ { 662 pos, err = f.Seek(int64(i), io.SeekStart) 663 RequireNoError(t, err, "Seek %s", path) 664 665 if int(pos) != i { 666 t.Errorf("Seek : want position to be %d, got %d", i, pos) 667 } 668 } 669 670 for i := 0; i < len(data); i++ { 671 pos, err = f.Seek(-int64(i), io.SeekEnd) 672 RequireNoError(t, err, "Seek %s", path) 673 674 if int(pos) != len(data)-i { 675 t.Errorf("Seek : want position to be %d, got %d", i, pos) 676 } 677 } 678 679 _, err = f.Seek(0, io.SeekEnd) 680 RequireNoError(t, err, "Seek %s", path) 681 682 for i := len(data) - 1; i >= 0; i-- { 683 pos, err = f.Seek(-1, io.SeekCurrent) 684 RequireNoError(t, err, "Seek %s", path) 685 686 if int(pos) != i { 687 t.Errorf("Seek : want position to be %d, got %d", i, pos) 688 } 689 } 690 }) 691 692 t.Run("FileSeekInvalidStart", func(t *testing.T) { 693 pos, err = f.Seek(-1, io.SeekStart) 694 AssertPathError(t, err).Op("seek").Path(f.Name()). 695 OSType(avfs.OsLinux).Err(avfs.ErrInvalidArgument).Test(). 696 OSType(avfs.OsWindows).Err(avfs.ErrWinNegativeSeek).Test() 697 698 if pos != 0 { 699 t.Errorf("Seek : want pos to be %d, got %d", 0, pos) 700 } 701 702 wantPos := lenData * 2 703 704 pos, err = f.Seek(wantPos, io.SeekStart) 705 RequireNoError(t, err, "Seek %s", path) 706 707 if pos != wantPos { 708 t.Errorf("Seek : want pos to be %d, got %d", wantPos, pos) 709 } 710 }) 711 712 t.Run("FileSeekInvalidEnd", func(t *testing.T) { 713 pos, err = f.Seek(1, io.SeekEnd) 714 RequireNoError(t, err, "Seek %s", path) 715 716 wantPos := lenData + 1 717 if pos != wantPos { 718 t.Errorf("Seek : want pos to be %d, got %d", wantPos, pos) 719 } 720 721 pos, err = f.Seek(-lenData*2, io.SeekEnd) 722 AssertPathError(t, err).Op("seek").Path(f.Name()). 723 OSType(avfs.OsLinux).Err(avfs.ErrInvalidArgument).Test(). 724 OSType(avfs.OsWindows).Err(avfs.ErrWinNegativeSeek).Test() 725 726 if pos != 0 { 727 t.Errorf("Seek : want pos to be %d, got %d", 0, pos) 728 } 729 }) 730 731 t.Run("FileSeekInvalidCur", func(t *testing.T) { 732 wantPos := lenData / 2 733 734 pos, err = f.Seek(wantPos, io.SeekStart) 735 if err != nil || pos != wantPos { 736 t.Fatalf("Seek : want pos to be 0 and error to be nil, got %d, %v", pos, err) 737 } 738 739 pos, err = f.Seek(-lenData, io.SeekCurrent) 740 AssertPathError(t, err).Op("seek").Path(f.Name()). 741 OSType(avfs.OsLinux).Err(avfs.ErrInvalidArgument).Test(). 742 OSType(avfs.OsWindows).Err(avfs.ErrWinNegativeSeek).Test() 743 744 if pos != 0 { 745 t.Errorf("Seek : want pos to be %d, got %d", 0, pos) 746 } 747 748 pos, err = f.Seek(lenData, io.SeekCurrent) 749 RequireNoError(t, err, "Seek %s", path) 750 751 if pos != lenData/2+lenData { 752 t.Errorf("Seek : want pos to be %d, got %d", wantPos, pos) 753 } 754 }) 755 756 t.Run("FileSeekInvalidWhence", func(t *testing.T) { 757 pos, err = f.Seek(0, 10) 758 759 AssertPathError(t, err).Op("seek").Path(f.Name()). 760 OSType(avfs.OsLinux).Err(avfs.ErrInvalidArgument).Test(). 761 OSType(avfs.OsWindows).NoError().Test() 762 763 if pos != 0 { 764 t.Errorf("Seek : want pos to be %d, got %d", 0, pos) 765 } 766 }) 767 768 t.Run("FileSeekOnDir", func(t *testing.T) { 769 f, err = vfs.OpenFile(testDir, os.O_RDONLY, 0) 770 RequireNoError(t, err, "OpenFile %s", testDir) 771 772 defer f.Close() 773 774 _, err = f.Seek(0, io.SeekStart) 775 RequireNoError(t, err, "Seek %s", testDir) 776 }) 777 778 t.Run("FileSeekClosed", func(t *testing.T) { 779 f, fileName := ts.closedFile(t, testDir) 780 781 _, err = f.Seek(0, io.SeekStart) 782 AssertPathError(t, err).Op("seek").Path(fileName).Err(fs.ErrClosed).Test() 783 }) 784 785 t.Run("FileSeekNonExisting", func(t *testing.T) { 786 f := ts.openedNonExistingFile(t, testDir) 787 788 _, err = f.Seek(0, io.SeekStart) 789 AssertInvalid(t, err, "Seek") 790 }) 791 } 792 793 // TestFileStat tests File.Stat function. 794 func (ts *Suite) TestFileStat(t *testing.T, testDir string) { 795 dirs := ts.createSampleDirs(t, testDir) 796 files := ts.createSampleFiles(t, testDir) 797 _ = ts.createSampleSymlinks(t, testDir) 798 vfs := ts.vfsTest 799 800 t.Run("FileStatDir", func(t *testing.T) { 801 for _, dir := range dirs { 802 f, err := vfs.OpenFile(dir.Path, os.O_RDONLY, 0) 803 RequireNoError(t, err, "OpenFile %s", testDir) 804 805 info, err := f.Stat() 806 if !AssertNoError(t, err, "Stat %s", dir.Path) { 807 _ = f.Close() 808 809 continue 810 } 811 812 if vfs.Base(dir.Path) != info.Name() { 813 t.Errorf("Stat %s : want name to be %s, got %s", dir.Path, vfs.Base(dir.Path), info.Name()) 814 } 815 816 wantMode := (dir.Mode | fs.ModeDir) &^ vfs.UMask() 817 if vfs.OSType() == avfs.OsWindows { 818 wantMode = fs.ModeDir | fs.ModePerm 819 } 820 821 if wantMode != info.Mode() { 822 t.Errorf("Stat %s : want mode to be %s, got %s", dir.Path, wantMode, info.Mode()) 823 } 824 825 _ = f.Close() 826 } 827 }) 828 829 t.Run("FileStatFile", func(t *testing.T) { 830 for _, file := range files { 831 f, err := vfs.OpenFile(file.Path, os.O_RDONLY, 0) 832 RequireNoError(t, err, "OpenFile %s", file.Path) 833 834 info, err := f.Stat() 835 if !AssertNoError(t, err, "Stat %s", file.Path) { 836 _ = f.Close() 837 838 continue 839 } 840 841 if info.Name() != vfs.Base(file.Path) { 842 t.Errorf("Stat %s : want name to be %s, got %s", file.Path, vfs.Base(file.Path), info.Name()) 843 } 844 845 wantMode := file.Mode &^ vfs.UMask() 846 if vfs.OSType() == avfs.OsWindows { 847 wantMode = avfs.DefaultFilePerm 848 } 849 850 if wantMode != info.Mode() { 851 t.Errorf("Stat %s : want mode to be %s, got %s", file.Path, wantMode, info.Mode()) 852 } 853 854 wantSize := int64(len(file.Content)) 855 if wantSize != info.Size() { 856 t.Errorf("Lstat %s : want size to be %d, got %d", file.Path, wantSize, info.Size()) 857 } 858 859 _ = f.Close() 860 } 861 }) 862 863 t.Run("FileStatSymlink", func(t *testing.T) { 864 for _, sl := range ts.sampleSymlinksEval(testDir) { 865 f, err := vfs.OpenFile(sl.NewPath, os.O_RDONLY, 0) 866 RequireNoError(t, err, "OpenFile %s", sl.NewPath) 867 868 info, err := f.Stat() 869 if !AssertNoError(t, err, "Stat %s", sl.NewPath) { 870 _ = f.Close() 871 872 continue 873 } 874 875 wantName := vfs.Base(sl.OldPath) 876 if sl.IsSymlink { 877 wantName = vfs.Base(sl.NewPath) 878 } 879 880 wantMode := sl.Mode 881 882 if wantName != info.Name() { 883 t.Errorf("Stat %s : want name to be %s, got %s", sl.NewPath, wantName, info.Name()) 884 } 885 886 if ts.canTestPerm && wantMode != info.Mode() { 887 t.Errorf("Stat %s : want mode to be %s, got %s", sl.NewPath, wantMode, info.Mode()) 888 } 889 890 _ = f.Close() 891 } 892 }) 893 894 t.Run("FileStatNonExistingFile", func(t *testing.T) { 895 f := ts.openedNonExistingFile(t, testDir) 896 897 _, err := f.Stat() 898 AssertInvalid(t, err, "Stat") 899 }) 900 901 t.Run("FileStatSubDirOnFile", func(t *testing.T) { 902 path := vfs.Join(files[0].Path, defaultNonExisting) 903 904 f, err := vfs.OpenFile(path, os.O_RDONLY, 0) 905 AssertPathError(t, err).Op("open").Path(path). 906 OSType(avfs.OsLinux).Err(avfs.ErrNotADirectory).Test(). 907 OSType(avfs.OsWindows).Err(avfs.ErrWinPathNotFound).Test() 908 909 _, err = f.Stat() 910 AssertInvalid(t, err, "Stat") 911 }) 912 913 t.Run("FileStatClosed", func(t *testing.T) { 914 f, fileName := ts.closedFile(t, testDir) 915 916 _, err := f.Stat() 917 AssertPathError(t, err).Path(fileName). 918 OSType(avfs.OsLinux).Op("stat").Err(avfs.ErrFileClosing).Test(). 919 OSType(avfs.OsWindows).Op("GetFileType").Err(avfs.ErrWinInvalidHandle).Test() 920 }) 921 922 t.Run("FileStatNonExisting", func(t *testing.T) { 923 f := ts.openedNonExistingFile(t, testDir) 924 925 _, err := f.Stat() 926 AssertInvalid(t, err, "Stat") 927 }) 928 } 929 930 // TestFileSync tests File.Sync function. 931 func (ts *Suite) TestFileSync(t *testing.T, testDir string) { 932 vfs := ts.vfsTest 933 934 if vfs.HasFeature(avfs.FeatReadOnly) { 935 f := ts.openedNonExistingFile(t, testDir) 936 937 err := f.Sync() 938 AssertPathError(t, err).Op("sync").Path(avfs.NotImplemented).ErrPermDenied().Test() 939 940 return 941 } 942 943 t.Run("FileSyncClosed", func(t *testing.T) { 944 f, fileName := ts.closedFile(t, testDir) 945 946 err := f.Sync() 947 AssertPathError(t, err).Op("sync").Path(fileName).Err(fs.ErrClosed).Test() 948 }) 949 950 t.Run("FileSyncNonExisting", func(t *testing.T) { 951 f := ts.openedNonExistingFile(t, testDir) 952 953 err := f.Sync() 954 AssertInvalid(t, err, "Sync") 955 }) 956 } 957 958 // TestFileTruncate tests File.Truncate function. 959 func (ts *Suite) TestFileTruncate(t *testing.T, testDir string) { 960 vfs := ts.vfsTest 961 962 if vfs.HasFeature(avfs.FeatReadOnly) { 963 f, fileName := ts.openedEmptyFile(t, testDir) 964 965 defer f.Close() 966 967 err := f.Truncate(0) 968 AssertPathError(t, err).Op("truncate").Path(fileName).ErrPermDenied().Test() 969 970 return 971 } 972 973 data := []byte("AAABBBCCCDDD") 974 975 t.Run("FileTruncate", func(t *testing.T) { 976 path := ts.existingFile(t, testDir, data) 977 978 f, err := vfs.OpenFile(path, os.O_RDWR, avfs.DefaultFilePerm) 979 RequireNoError(t, err, "OpenFile %s", path) 980 981 defer f.Close() 982 983 b := make([]byte, len(data)) 984 985 for i := len(data) - 1; i >= 0; i-- { 986 err = f.Truncate(int64(i)) 987 RequireNoError(t, err, "Truncate %s", path) 988 989 _, err = f.ReadAt(b, 0) 990 if err != io.EOF { 991 t.Errorf("Read : want error to be EOF, got %v", err) 992 } 993 994 if !bytes.Equal(data[:i], b[:i]) { 995 t.Errorf("Truncate : want data to be %s, got %s", data[:i], b[:i]) 996 } 997 } 998 }) 999 1000 t.Run("FileTruncateOnDir", func(t *testing.T) { 1001 f, err := vfs.OpenFile(testDir, os.O_RDONLY, 0) 1002 RequireNoError(t, err, "OpenFile %s", testDir) 1003 1004 defer f.Close() 1005 1006 err = f.Truncate(0) 1007 AssertPathError(t, err).Op("truncate").Path(testDir). 1008 OSType(avfs.OsLinux).Err(avfs.ErrInvalidArgument).Test(). 1009 OSType(avfs.OsWindows).Err(avfs.ErrWinAccessDenied).Test() 1010 }) 1011 1012 t.Run("FileTruncateSizeNegative", func(t *testing.T) { 1013 path := ts.existingFile(t, testDir, data) 1014 1015 f, err := vfs.OpenFile(path, os.O_RDWR, avfs.DefaultFilePerm) 1016 RequireNoError(t, err, "OpenFile %s", path) 1017 1018 defer f.Close() 1019 1020 err = f.Truncate(-1) 1021 AssertPathError(t, err).Op("truncate").Path(path). 1022 OSType(avfs.OsLinux).Err(avfs.ErrInvalidArgument).Test(). 1023 OSType(avfs.OsWindows).Err(avfs.ErrWinNegativeSeek).Test() 1024 }) 1025 1026 t.Run("FileTruncateSizeBiggerFileSize", func(t *testing.T) { 1027 path := ts.existingFile(t, testDir, data) 1028 1029 f, err := vfs.OpenFile(path, os.O_RDWR, avfs.DefaultFilePerm) 1030 RequireNoError(t, err, "OpenFile %s", path) 1031 1032 newSize := len(data) * 2 1033 1034 err = f.Truncate(int64(newSize)) 1035 RequireNoError(t, err, "Truncate %s", path) 1036 1037 info, err := f.Stat() 1038 RequireNoError(t, err, "Stat %s", path) 1039 1040 if newSize != int(info.Size()) { 1041 t.Errorf("Stat : want size to be %d, got %d", newSize, info.Size()) 1042 } 1043 1044 f.Close() 1045 1046 gotContent, err := vfs.ReadFile(path) 1047 RequireNoError(t, err, "ReadFile %s", path) 1048 1049 wantAdded := bytes.Repeat([]byte{0}, len(data)) 1050 gotAdded := gotContent[len(data):] 1051 1052 if !bytes.Equal(wantAdded, gotAdded) { 1053 t.Errorf("Bytes Added : want %v, got %v", wantAdded, gotAdded) 1054 } 1055 }) 1056 1057 t.Run("FileTruncateNonExistingFile", func(t *testing.T) { 1058 f := ts.openedNonExistingFile(t, testDir) 1059 1060 err := f.Truncate(0) 1061 AssertInvalid(t, err, "Truncate") 1062 }) 1063 1064 t.Run("FileTruncateClosed", func(t *testing.T) { 1065 f, fileName := ts.closedFile(t, testDir) 1066 1067 err := f.Truncate(0) 1068 AssertPathError(t, err).Op("truncate").Path(fileName).Err(fs.ErrClosed).Test() 1069 }) 1070 } 1071 1072 // TestFileWrite tests File.Write function. 1073 func (ts *Suite) TestFileWrite(t *testing.T, testDir string) { 1074 vfs := ts.vfsTest 1075 1076 if vfs.HasFeature(avfs.FeatReadOnly) { 1077 f, fileName := ts.openedEmptyFile(t, testDir) 1078 1079 defer f.Close() 1080 1081 _, err := f.Write([]byte{}) 1082 AssertPathError(t, err).Op("write").Path(fileName).ErrPermDenied().Test() 1083 1084 return 1085 } 1086 1087 data := []byte("AAABBBCCCDDD") 1088 1089 t.Run("FileWrite", func(t *testing.T) { 1090 path := vfs.Join(testDir, "TestFileWrite.txt") 1091 1092 f, err := vfs.Create(path) 1093 RequireNoError(t, err, "Create %s", path) 1094 1095 defer f.Close() 1096 1097 for i := 0; i < len(data); i += 3 { 1098 buf3 := data[i : i+3] 1099 1100 var n int 1101 1102 n, err = f.Write(buf3) 1103 RequireNoError(t, err, "Write %s", path) 1104 1105 if len(buf3) != n { 1106 t.Errorf("Write : want bytes written to be %d, got %d", len(buf3), n) 1107 } 1108 } 1109 1110 rb, err := vfs.ReadFile(path) 1111 RequireNoError(t, err, "ReadFile %s", path) 1112 1113 if !bytes.Equal(rb, data) { 1114 t.Errorf("ReadFile : want content to be %s, got %s", data, rb) 1115 } 1116 }) 1117 1118 t.Run("FileWriteNonExisting", func(t *testing.T) { 1119 f := ts.openedNonExistingFile(t, testDir) 1120 buf := make([]byte, 0) 1121 1122 _, err := f.Write(buf) 1123 AssertInvalid(t, err, "Write") 1124 }) 1125 1126 t.Run("FileWriteReadOnly", func(t *testing.T) { 1127 path := ts.existingFile(t, testDir, data) 1128 1129 f, err := vfs.OpenFile(path, os.O_RDONLY, 0) 1130 RequireNoError(t, err, "OpenFile %s", path) 1131 1132 defer f.Close() 1133 1134 b := make([]byte, len(data)*2) 1135 n, err := f.Write(b) 1136 AssertPathError(t, err).Op("write").Path(path). 1137 OSType(avfs.OsLinux).Err(avfs.ErrBadFileDesc).Test(). 1138 OSType(avfs.OsWindows).Err(avfs.ErrWinAccessDenied).Test() 1139 1140 if n != 0 { 1141 t.Errorf("Write : want bytes written to be 0, got %d", n) 1142 } 1143 1144 n, err = f.Read(b) 1145 RequireNoError(t, err, "Read %s", path) 1146 1147 if !bytes.Equal(data, b[:n]) { 1148 t.Errorf("Read : want data to be %s, got %s", data, b[:n]) 1149 } 1150 }) 1151 1152 t.Run("FileWriteOnDir", func(t *testing.T) { 1153 f, err := vfs.OpenFile(testDir, os.O_RDONLY, 0) 1154 RequireNoError(t, err, "OpenFile %s", testDir) 1155 1156 defer f.Close() 1157 1158 b := make([]byte, 1) 1159 1160 _, err = f.Write(b) 1161 AssertPathError(t, err).Op("write").Path(testDir). 1162 OSType(avfs.OsLinux).Err(avfs.ErrBadFileDesc).Test(). 1163 OSType(avfs.OsWindows).Err(avfs.ErrWinAccessDenied).Test() 1164 }) 1165 1166 t.Run("FileWriteClosed", func(t *testing.T) { 1167 b := make([]byte, 1) 1168 1169 f, fileName := ts.closedFile(t, testDir) 1170 _, err := f.Write(b) 1171 AssertPathError(t, err).Op("write").Path(fileName).Err(fs.ErrClosed).Test() 1172 }) 1173 } 1174 1175 // TestFileWriteAt tests File.WriteAt function. 1176 func (ts *Suite) TestFileWriteAt(t *testing.T, testDir string) { 1177 vfs := ts.vfsTest 1178 1179 if vfs.HasFeature(avfs.FeatReadOnly) { 1180 f, fileName := ts.openedEmptyFile(t, testDir) 1181 1182 _, err := f.WriteAt([]byte{}, 0) 1183 AssertPathError(t, err).Op("write").Path(fileName).ErrPermDenied().Test() 1184 1185 return 1186 } 1187 1188 data := []byte("AAABBBCCCDDD") 1189 1190 t.Run("FileWriteAt", func(t *testing.T) { 1191 path := vfs.Join(testDir, "TestFileWriteAt.txt") 1192 1193 f, err := vfs.OpenFile(path, os.O_CREATE|os.O_RDWR, avfs.DefaultFilePerm) 1194 RequireNoError(t, err, "OpenFile %s", path) 1195 1196 defer f.Close() 1197 1198 for i := len(data); i > 0; i -= 3 { 1199 var n int 1200 n, err = f.WriteAt(data[i-3:i], int64(i-3)) 1201 RequireNoError(t, err, "WriteAt %s", path) 1202 1203 if n != 3 { 1204 t.Errorf("WriteAt : want bytes written to be %d, got %d", 3, n) 1205 } 1206 } 1207 1208 err = f.Close() 1209 RequireNoError(t, err, "Close %s", path) 1210 1211 rb, err := vfs.ReadFile(path) 1212 RequireNoError(t, err, "ReadFile %s", path) 1213 1214 if !bytes.Equal(rb, data) { 1215 t.Errorf("ReadFile : want content to be %s, got %s", data, rb) 1216 } 1217 }) 1218 1219 t.Run("FileWriteAtNonExisting", func(t *testing.T) { 1220 f := ts.openedNonExistingFile(t, testDir) 1221 buf := make([]byte, 0) 1222 1223 _, err := f.WriteAt(buf, 0) 1224 AssertInvalid(t, err, "WriteAt") 1225 }) 1226 1227 t.Run("FileWriteAtNegativeOffset", func(t *testing.T) { 1228 path := ts.existingFile(t, testDir, data) 1229 1230 f, err := vfs.OpenFile(path, os.O_RDWR, avfs.DefaultDirPerm) 1231 RequireNoError(t, err, "OpenFile %s", path) 1232 1233 defer f.Close() 1234 1235 n, err := f.WriteAt(data, -1) 1236 AssertPathError(t, err).Op("writeat").Path(path).Err(avfs.ErrNegativeOffset).Test() 1237 1238 if n != 0 { 1239 t.Errorf("WriteAt : want bytes written to be 0, got %d", n) 1240 } 1241 }) 1242 1243 t.Run("FileWriteAtAfterEndOfFile", func(t *testing.T) { 1244 path := ts.existingFile(t, testDir, data) 1245 1246 f, err := vfs.OpenFile(path, os.O_RDWR, avfs.DefaultFilePerm) 1247 RequireNoError(t, err, "OpenFile %s", path) 1248 1249 defer f.Close() 1250 1251 off := int64(len(data) * 3) 1252 1253 n, err := f.WriteAt(data, off) 1254 RequireNoError(t, err, "WriteAt %s", path) 1255 1256 if n != len(data) { 1257 t.Errorf("WriteAt : want bytes written to be %d, got %d", len(data), n) 1258 } 1259 1260 want := make([]byte, int(off)+len(data)) 1261 _ = copy(want, data) 1262 _ = copy(want[off:], data) 1263 1264 got, err := vfs.ReadFile(path) 1265 RequireNoError(t, err, "ReadFile %s", path) 1266 1267 if !bytes.Equal(want, got) { 1268 t.Errorf("want : %s\ngot : %s", want, got) 1269 } 1270 }) 1271 1272 t.Run("FileWriteAtReadOnly", func(t *testing.T) { 1273 path := ts.existingFile(t, testDir, data) 1274 1275 f, err := vfs.OpenFile(path, os.O_RDONLY, 0) 1276 RequireNoError(t, err, "OpenFile %s", path) 1277 1278 defer f.Close() 1279 1280 b := make([]byte, len(data)*2) 1281 1282 n, err := f.WriteAt(b, 0) 1283 AssertPathError(t, err).Op("write").Path(path). 1284 OSType(avfs.OsLinux).Err(avfs.ErrBadFileDesc).Test(). 1285 OSType(avfs.OsWindows).Err(avfs.ErrWinAccessDenied).Test() 1286 1287 if n != 0 { 1288 t.Errorf("WriteAt : want bytes read to be 0, got %d", n) 1289 } 1290 1291 n, err = f.ReadAt(b, 0) 1292 if err != io.EOF { 1293 t.Errorf("ReadAt : want error to be EOF, got %v", err) 1294 } 1295 1296 if !bytes.Equal(data, b[:n]) { 1297 t.Errorf("ReadAt : want data to be %s, got %s", data, b[:n]) 1298 } 1299 }) 1300 1301 t.Run("FileWriteAtOnDir", func(t *testing.T) { 1302 f, err := vfs.OpenFile(testDir, os.O_RDONLY, 0) 1303 RequireNoError(t, err, "OpenFile %s", testDir) 1304 1305 defer f.Close() 1306 1307 b := make([]byte, 1) 1308 1309 _, err = f.WriteAt(b, 0) 1310 AssertPathError(t, err).Op("write").Path(testDir). 1311 OSType(avfs.OsLinux).Err(avfs.ErrBadFileDesc).Test(). 1312 OSType(avfs.OsWindows).Err(avfs.ErrWinAccessDenied).Test() 1313 }) 1314 1315 t.Run("FileWriteAtClosed", func(t *testing.T) { 1316 b := make([]byte, 1) 1317 1318 f, fileName := ts.closedFile(t, testDir) 1319 1320 _, err := f.WriteAt(b, 0) 1321 AssertPathError(t, err).Op("write").Path(fileName).Err(fs.ErrClosed).Test() 1322 }) 1323 } 1324 1325 // TestFileWriteString tests File.WriteString function. 1326 func (ts *Suite) TestFileWriteString(t *testing.T, testDir string) { 1327 vfs := ts.vfsTest 1328 1329 if vfs.HasFeature(avfs.FeatReadOnly) { 1330 f := ts.openedNonExistingFile(t, testDir) 1331 1332 _, err := f.WriteString("") 1333 AssertPathError(t, err).Op("write").Path(f.Name()).ErrPermDenied().Test() 1334 1335 return 1336 } 1337 1338 t.Run("FileWriteNonExisting", func(t *testing.T) { 1339 f := ts.openedNonExistingFile(t, testDir) 1340 1341 _, err := f.WriteString("") 1342 AssertInvalid(t, err, "WriteString") 1343 }) 1344 } 1345 1346 // TestFileWriteTime checks that modification time is updated on write operations. 1347 func (ts *Suite) TestFileWriteTime(t *testing.T, testDir string) { 1348 vfs := ts.vfsTest 1349 if vfs.HasFeature(avfs.FeatReadOnly) { 1350 return 1351 } 1352 1353 var previous time.Time 1354 1355 f, fileName := ts.openedEmptyFile(t, testDir) 1356 1357 // CompareTime tests if the modification time of the file has changed. 1358 compareTime := func(mustChange bool) { 1359 time.Sleep(10 * time.Millisecond) 1360 1361 info, err := vfs.Stat(fileName) 1362 RequireNoError(t, err, "Stat %s", fileName) 1363 1364 // Don't compare for the first time. 1365 if previous.IsZero() { 1366 previous = info.ModTime() 1367 1368 return 1369 } 1370 1371 current := info.ModTime() 1372 if mustChange && !current.After(previous) { 1373 t.Errorf("CompareTime : want previous < current time\ngot prev = %v, curr = %v", previous, current) 1374 } 1375 1376 if !mustChange && !current.Equal(previous) { 1377 t.Errorf("CompareTime : want previous = current time\ngot prev = %v, curr = %v", previous, current) 1378 } 1379 1380 previous = current 1381 } 1382 1383 compareTime(true) 1384 1385 data := []byte("AAABBBCCCDDD") 1386 1387 t.Run("TimeWrite", func(t *testing.T) { 1388 _, err := f.Write(data) 1389 RequireNoError(t, err, "Write") 1390 1391 compareTime(true) 1392 }) 1393 1394 t.Run("TimeWriteAt", func(t *testing.T) { 1395 _, err := f.WriteAt(data, 5) 1396 RequireNoError(t, err, "WriteAt") 1397 1398 compareTime(true) 1399 }) 1400 1401 t.Run("TimeTruncate", func(t *testing.T) { 1402 err := f.Truncate(5) 1403 RequireNoError(t, err, "Truncate") 1404 1405 compareTime(true) 1406 }) 1407 1408 t.Run("TimeClose", func(t *testing.T) { 1409 err := f.Close() 1410 RequireNoError(t, err, "Close") 1411 1412 compareTime(false) 1413 }) 1414 }