github.com/scaleoutsean/fusego@v0.0.0-20220224074057-4a6429e46bb8/samples/memfs/memfs_test.go (about) 1 // Copyright 2015 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package memfs_test 16 17 import ( 18 "bytes" 19 "io" 20 "io/ioutil" 21 "os" 22 "os/user" 23 "path" 24 "reflect" 25 "runtime" 26 "strconv" 27 "syscall" 28 "testing" 29 "time" 30 31 fallocate "github.com/detailyang/go-fallocate" 32 "github.com/scaleoutsean/fusego" 33 "github.com/scaleoutsean/fusego/fusetesting" 34 "github.com/scaleoutsean/fusego/samples" 35 "github.com/scaleoutsean/fusego/samples/memfs" 36 . "github.com/jacobsa/oglematchers" 37 . "github.com/jacobsa/ogletest" 38 "golang.org/x/sys/unix" 39 ) 40 41 func TestMemFS(t *testing.T) { RunTests(t) } 42 43 // The radius we use for "expect mtime is within"-style assertions. We can't 44 // share a synchronized clock with the ultimate source of mtimes because with 45 // writeback caching enabled the kernel manufactures them based on wall time. 46 const timeSlop = 25 * time.Millisecond 47 48 //////////////////////////////////////////////////////////////////////// 49 // Helpers 50 //////////////////////////////////////////////////////////////////////// 51 52 func currentUid() uint32 { 53 user, err := user.Current() 54 if err != nil { 55 panic(err) 56 } 57 58 uid, err := strconv.ParseUint(user.Uid, 10, 32) 59 if err != nil { 60 panic(err) 61 } 62 63 return uint32(uid) 64 } 65 66 func currentGid() uint32 { 67 user, err := user.Current() 68 if err != nil { 69 panic(err) 70 } 71 72 gid, err := strconv.ParseUint(user.Gid, 10, 32) 73 if err != nil { 74 panic(err) 75 } 76 77 return uint32(gid) 78 } 79 80 // Transform the supplied mode by the current umask. 81 func applyUmask(m os.FileMode) os.FileMode { 82 // HACK(jacobsa): Use umask(2) to change and restore the umask in order to 83 // figure out what the mask is. See the listing in `man getumask`. 84 umask := syscall.Umask(0) 85 syscall.Umask(umask) 86 87 // Apply it. 88 return m &^ os.FileMode(umask) 89 } 90 91 //////////////////////////////////////////////////////////////////////// 92 // Boilerplate 93 //////////////////////////////////////////////////////////////////////// 94 95 type memFSTest struct { 96 samples.SampleTest 97 } 98 99 func (t *memFSTest) SetUp(ti *TestInfo) { 100 t.Server = memfs.NewMemFS(currentUid(), currentGid()) 101 t.SampleTest.SetUp(ti) 102 } 103 104 //////////////////////////////////////////////////////////////////////// 105 // Basics 106 //////////////////////////////////////////////////////////////////////// 107 108 type MemFSTest struct { 109 memFSTest 110 } 111 112 func init() { RegisterTestSuite(&MemFSTest{}) } 113 114 func (t *MemFSTest) ContentsOfEmptyFileSystem() { 115 entries, err := fusetesting.ReadDirPicky(t.Dir) 116 117 AssertEq(nil, err) 118 ExpectThat(entries, ElementsAre()) 119 } 120 121 func (t *MemFSTest) Mkdir_OneLevel() { 122 var err error 123 var fi os.FileInfo 124 var stat *syscall.Stat_t 125 var entries []os.FileInfo 126 127 dirName := path.Join(t.Dir, "dir") 128 129 // Create a directory within the root. 130 createTime := time.Now() 131 err = os.Mkdir(dirName, 0754) 132 AssertEq(nil, err) 133 134 // Stat the directory. 135 fi, err = os.Stat(dirName) 136 stat = fi.Sys().(*syscall.Stat_t) 137 138 AssertEq(nil, err) 139 ExpectEq("dir", fi.Name()) 140 ExpectEq(0, fi.Size()) 141 ExpectEq(os.ModeDir|applyUmask(0754), fi.Mode()) 142 ExpectThat(fi, fusetesting.MtimeIsWithin(createTime, timeSlop)) 143 ExpectThat(fi, fusetesting.BirthtimeIsWithin(createTime, timeSlop)) 144 ExpectTrue(fi.IsDir()) 145 146 ExpectNe(0, stat.Ino) 147 ExpectEq(1, stat.Nlink) 148 ExpectEq(currentUid(), stat.Uid) 149 ExpectEq(currentGid(), stat.Gid) 150 ExpectEq(0, stat.Size) 151 152 // Check the root's mtime. 153 fi, err = os.Stat(t.Dir) 154 155 AssertEq(nil, err) 156 ExpectThat(fi, fusetesting.MtimeIsWithin(createTime, timeSlop)) 157 158 // Read the directory. 159 entries, err = fusetesting.ReadDirPicky(dirName) 160 161 AssertEq(nil, err) 162 ExpectThat(entries, ElementsAre()) 163 164 // Read the root. 165 entries, err = fusetesting.ReadDirPicky(t.Dir) 166 167 AssertEq(nil, err) 168 AssertEq(1, len(entries)) 169 170 fi = entries[0] 171 ExpectEq("dir", fi.Name()) 172 ExpectEq(os.ModeDir|applyUmask(0754), fi.Mode()) 173 } 174 175 func (t *MemFSTest) Mkdir_TwoLevels() { 176 var err error 177 var fi os.FileInfo 178 var stat *syscall.Stat_t 179 var entries []os.FileInfo 180 181 // Create a directory within the root. 182 err = os.Mkdir(path.Join(t.Dir, "parent"), 0700) 183 AssertEq(nil, err) 184 185 // Create a child of that directory. 186 createTime := time.Now() 187 err = os.Mkdir(path.Join(t.Dir, "parent/dir"), 0754) 188 AssertEq(nil, err) 189 190 // Stat the directory. 191 fi, err = os.Stat(path.Join(t.Dir, "parent/dir")) 192 stat = fi.Sys().(*syscall.Stat_t) 193 194 AssertEq(nil, err) 195 ExpectEq("dir", fi.Name()) 196 ExpectEq(0, fi.Size()) 197 ExpectEq(os.ModeDir|applyUmask(0754), fi.Mode()) 198 ExpectThat(fi, fusetesting.MtimeIsWithin(createTime, timeSlop)) 199 ExpectThat(fi, fusetesting.BirthtimeIsWithin(createTime, timeSlop)) 200 ExpectTrue(fi.IsDir()) 201 202 ExpectNe(0, stat.Ino) 203 ExpectEq(1, stat.Nlink) 204 ExpectEq(currentUid(), stat.Uid) 205 ExpectEq(currentGid(), stat.Gid) 206 ExpectEq(0, stat.Size) 207 208 // Check the parent's mtime. 209 fi, err = os.Stat(path.Join(t.Dir, "parent")) 210 AssertEq(nil, err) 211 ExpectThat(fi, fusetesting.MtimeIsWithin(createTime, timeSlop)) 212 213 // Read the directory. 214 entries, err = fusetesting.ReadDirPicky(path.Join(t.Dir, "parent/dir")) 215 216 AssertEq(nil, err) 217 ExpectThat(entries, ElementsAre()) 218 219 // Read the parent. 220 entries, err = fusetesting.ReadDirPicky(path.Join(t.Dir, "parent")) 221 222 AssertEq(nil, err) 223 AssertEq(1, len(entries)) 224 225 fi = entries[0] 226 ExpectEq("dir", fi.Name()) 227 ExpectEq(os.ModeDir|applyUmask(0754), fi.Mode()) 228 } 229 230 func (t *MemFSTest) Mkdir_AlreadyExists() { 231 var err error 232 dirName := path.Join(t.Dir, "dir") 233 234 // Create the directory once. 235 err = os.Mkdir(dirName, 0754) 236 AssertEq(nil, err) 237 238 // Attempt to create it again. 239 err = os.Mkdir(dirName, 0754) 240 241 AssertNe(nil, err) 242 ExpectThat(err, Error(HasSubstr("exists"))) 243 } 244 245 func (t *MemFSTest) Mkdir_IntermediateIsFile() { 246 var err error 247 248 // Create a file. 249 fileName := path.Join(t.Dir, "foo") 250 err = ioutil.WriteFile(fileName, []byte{}, 0700) 251 AssertEq(nil, err) 252 253 // Attempt to create a directory within the file. 254 dirName := path.Join(fileName, "dir") 255 err = os.Mkdir(dirName, 0754) 256 257 AssertNe(nil, err) 258 ExpectThat(err, Error(HasSubstr("not a directory"))) 259 } 260 261 func (t *MemFSTest) Mkdir_IntermediateIsNonExistent() { 262 var err error 263 264 // Attempt to create a sub-directory of a non-existent sub-directory. 265 dirName := path.Join(t.Dir, "foo/dir") 266 err = os.Mkdir(dirName, 0754) 267 268 AssertNe(nil, err) 269 ExpectThat(err, Error(HasSubstr("no such file or directory"))) 270 } 271 272 func (t *MemFSTest) Mkdir_PermissionDenied() { 273 var err error 274 275 // Create a directory within the root without write permissions. 276 err = os.Mkdir(path.Join(t.Dir, "parent"), 0500) 277 AssertEq(nil, err) 278 279 // Attempt to create a child of that directory. 280 err = os.Mkdir(path.Join(t.Dir, "parent/dir"), 0754) 281 282 AssertNe(nil, err) 283 ExpectThat(err, Error(HasSubstr("permission denied"))) 284 } 285 286 func (t *MemFSTest) CreateNewFile_InRoot() { 287 var err error 288 var fi os.FileInfo 289 var stat *syscall.Stat_t 290 291 // Write a file. 292 fileName := path.Join(t.Dir, "foo") 293 const contents = "Hello\x00world" 294 295 createTime := time.Now() 296 err = ioutil.WriteFile(fileName, []byte(contents), 0400) 297 AssertEq(nil, err) 298 299 // Stat it. 300 fi, err = os.Stat(fileName) 301 stat = fi.Sys().(*syscall.Stat_t) 302 303 AssertEq(nil, err) 304 ExpectEq("foo", fi.Name()) 305 ExpectEq(len(contents), fi.Size()) 306 ExpectEq(applyUmask(0400), fi.Mode()) 307 ExpectThat(fi, fusetesting.MtimeIsWithin(createTime, timeSlop)) 308 ExpectThat(fi, fusetesting.BirthtimeIsWithin(createTime, timeSlop)) 309 ExpectFalse(fi.IsDir()) 310 311 ExpectNe(0, stat.Ino) 312 ExpectEq(1, stat.Nlink) 313 ExpectEq(currentUid(), stat.Uid) 314 ExpectEq(currentGid(), stat.Gid) 315 ExpectEq(len(contents), stat.Size) 316 317 // Read it back. 318 slice, err := ioutil.ReadFile(fileName) 319 AssertEq(nil, err) 320 ExpectEq(contents, string(slice)) 321 } 322 323 func (t *MemFSTest) CreateNewFile_InSubDir() { 324 var err error 325 var fi os.FileInfo 326 var stat *syscall.Stat_t 327 328 // Create a sub-dir. 329 dirName := path.Join(t.Dir, "dir") 330 err = os.Mkdir(dirName, 0700) 331 AssertEq(nil, err) 332 333 // Write a file. 334 fileName := path.Join(dirName, "foo") 335 const contents = "Hello\x00world" 336 337 createTime := time.Now() 338 err = ioutil.WriteFile(fileName, []byte(contents), 0400) 339 AssertEq(nil, err) 340 341 // Stat it. 342 fi, err = os.Stat(fileName) 343 stat = fi.Sys().(*syscall.Stat_t) 344 345 AssertEq(nil, err) 346 ExpectEq("foo", fi.Name()) 347 ExpectEq(len(contents), fi.Size()) 348 ExpectEq(applyUmask(0400), fi.Mode()) 349 ExpectThat(fi, fusetesting.MtimeIsWithin(createTime, timeSlop)) 350 ExpectThat(fi, fusetesting.BirthtimeIsWithin(createTime, timeSlop)) 351 ExpectFalse(fi.IsDir()) 352 353 ExpectNe(0, stat.Ino) 354 ExpectEq(1, stat.Nlink) 355 ExpectEq(currentUid(), stat.Uid) 356 ExpectEq(currentGid(), stat.Gid) 357 ExpectEq(len(contents), stat.Size) 358 359 // Read it back. 360 slice, err := ioutil.ReadFile(fileName) 361 AssertEq(nil, err) 362 ExpectEq(contents, string(slice)) 363 } 364 365 func (t *MemFSTest) ModifyExistingFile_InRoot() { 366 var err error 367 var n int 368 var fi os.FileInfo 369 var stat *syscall.Stat_t 370 371 // Write a file. 372 fileName := path.Join(t.Dir, "foo") 373 374 createTime := time.Now() 375 err = ioutil.WriteFile(fileName, []byte("Hello, world!"), 0600) 376 AssertEq(nil, err) 377 378 // Open the file and modify it. 379 f, err := os.OpenFile(fileName, os.O_WRONLY, 0400) 380 t.ToClose = append(t.ToClose, f) 381 AssertEq(nil, err) 382 383 modifyTime := time.Now() 384 n, err = f.WriteAt([]byte("H"), 0) 385 AssertEq(nil, err) 386 AssertEq(1, n) 387 388 // Stat the file. 389 fi, err = os.Stat(fileName) 390 stat = fi.Sys().(*syscall.Stat_t) 391 392 AssertEq(nil, err) 393 ExpectEq("foo", fi.Name()) 394 ExpectEq(len("Hello, world!"), fi.Size()) 395 ExpectEq(applyUmask(0600), fi.Mode()) 396 ExpectThat(fi, fusetesting.MtimeIsWithin(modifyTime, timeSlop)) 397 ExpectThat(fi, fusetesting.BirthtimeIsWithin(createTime, timeSlop)) 398 ExpectFalse(fi.IsDir()) 399 400 ExpectNe(0, stat.Ino) 401 ExpectEq(1, stat.Nlink) 402 ExpectEq(currentUid(), stat.Uid) 403 ExpectEq(currentGid(), stat.Gid) 404 ExpectEq(len("Hello, world!"), stat.Size) 405 406 // Read the file back. 407 slice, err := ioutil.ReadFile(fileName) 408 AssertEq(nil, err) 409 ExpectEq("Hello, world!", string(slice)) 410 } 411 412 func (t *MemFSTest) ModifyExistingFile_InSubDir() { 413 var err error 414 var n int 415 var fi os.FileInfo 416 var stat *syscall.Stat_t 417 418 // Create a sub-directory. 419 dirName := path.Join(t.Dir, "dir") 420 err = os.Mkdir(dirName, 0700) 421 AssertEq(nil, err) 422 423 // Write a file. 424 fileName := path.Join(dirName, "foo") 425 426 createTime := time.Now() 427 err = ioutil.WriteFile(fileName, []byte("Hello, world!"), 0600) 428 AssertEq(nil, err) 429 430 // Open the file and modify it. 431 f, err := os.OpenFile(fileName, os.O_WRONLY, 0400) 432 t.ToClose = append(t.ToClose, f) 433 AssertEq(nil, err) 434 435 modifyTime := time.Now() 436 n, err = f.WriteAt([]byte("H"), 0) 437 AssertEq(nil, err) 438 AssertEq(1, n) 439 440 // Stat the file. 441 fi, err = os.Stat(fileName) 442 stat = fi.Sys().(*syscall.Stat_t) 443 444 AssertEq(nil, err) 445 ExpectEq("foo", fi.Name()) 446 ExpectEq(len("Hello, world!"), fi.Size()) 447 ExpectEq(applyUmask(0600), fi.Mode()) 448 ExpectThat(fi, fusetesting.MtimeIsWithin(modifyTime, timeSlop)) 449 ExpectThat(fi, fusetesting.BirthtimeIsWithin(createTime, timeSlop)) 450 ExpectFalse(fi.IsDir()) 451 452 ExpectNe(0, stat.Ino) 453 ExpectEq(1, stat.Nlink) 454 ExpectEq(currentUid(), stat.Uid) 455 ExpectEq(currentGid(), stat.Gid) 456 ExpectEq(len("Hello, world!"), stat.Size) 457 458 // Read the file back. 459 slice, err := ioutil.ReadFile(fileName) 460 AssertEq(nil, err) 461 ExpectEq("Hello, world!", string(slice)) 462 } 463 464 func (t *MemFSTest) UnlinkFile_Exists() { 465 var err error 466 467 // Write a file. 468 fileName := path.Join(t.Dir, "foo") 469 err = ioutil.WriteFile(fileName, []byte("Hello, world!"), 0600) 470 AssertEq(nil, err) 471 472 // Unlink it. 473 err = os.Remove(fileName) 474 AssertEq(nil, err) 475 476 // Statting it should fail. 477 _, err = os.Stat(fileName) 478 479 AssertNe(nil, err) 480 ExpectThat(err, Error(HasSubstr("no such file"))) 481 482 // Nothing should be in the directory. 483 entries, err := fusetesting.ReadDirPicky(t.Dir) 484 AssertEq(nil, err) 485 ExpectThat(entries, ElementsAre()) 486 } 487 488 func (t *MemFSTest) UnlinkFile_NonExistent() { 489 err := os.Remove(path.Join(t.Dir, "foo")) 490 491 AssertNe(nil, err) 492 ExpectThat(err, Error(HasSubstr("no such file"))) 493 } 494 495 func (t *MemFSTest) UnlinkFile_StillOpen() { 496 fileName := path.Join(t.Dir, "foo") 497 498 // Create and open a file. 499 f, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE, 0600) 500 t.ToClose = append(t.ToClose, f) 501 AssertEq(nil, err) 502 503 // Write some data into it. 504 n, err := f.Write([]byte("taco")) 505 AssertEq(nil, err) 506 AssertEq(4, n) 507 508 // Unlink it. 509 err = os.Remove(fileName) 510 AssertEq(nil, err) 511 512 // The directory should no longer contain it. 513 entries, err := fusetesting.ReadDirPicky(t.Dir) 514 AssertEq(nil, err) 515 ExpectThat(entries, ElementsAre()) 516 517 // We should be able to stat the file. It should still show as having 518 // contents, but with no links. 519 fi, err := f.Stat() 520 521 AssertEq(nil, err) 522 ExpectEq(4, fi.Size()) 523 ExpectEq(0, fi.Sys().(*syscall.Stat_t).Nlink) 524 525 // The contents should still be available. 526 buf := make([]byte, 1024) 527 n, err = f.ReadAt(buf, 0) 528 529 AssertEq(io.EOF, err) 530 AssertEq(4, n) 531 ExpectEq("taco", string(buf[:4])) 532 533 // Writing should still work, too. 534 n, err = f.Write([]byte("burrito")) 535 AssertEq(nil, err) 536 AssertEq(len("burrito"), n) 537 } 538 539 func (t *MemFSTest) Rmdir_NonEmpty() { 540 var err error 541 542 // Create two levels of directories. 543 err = os.MkdirAll(path.Join(t.Dir, "foo/bar"), 0754) 544 AssertEq(nil, err) 545 546 // Attempt to remove the parent. 547 err = os.Remove(path.Join(t.Dir, "foo")) 548 549 AssertNe(nil, err) 550 ExpectThat(err, Error(HasSubstr("not empty"))) 551 } 552 553 func (t *MemFSTest) Rmdir_Empty() { 554 var err error 555 var entries []os.FileInfo 556 557 // Create two levels of directories. 558 err = os.MkdirAll(path.Join(t.Dir, "foo/bar"), 0754) 559 AssertEq(nil, err) 560 561 // Remove the leaf. 562 rmTime := time.Now() 563 err = os.Remove(path.Join(t.Dir, "foo/bar")) 564 AssertEq(nil, err) 565 566 // There should be nothing left in the parent. 567 entries, err = fusetesting.ReadDirPicky(path.Join(t.Dir, "foo")) 568 569 AssertEq(nil, err) 570 ExpectThat(entries, ElementsAre()) 571 572 // Check the parent's mtime. 573 fi, err := os.Stat(path.Join(t.Dir, "foo")) 574 AssertEq(nil, err) 575 ExpectThat(fi, fusetesting.MtimeIsWithin(rmTime, timeSlop)) 576 577 // Remove the parent. 578 err = os.Remove(path.Join(t.Dir, "foo")) 579 AssertEq(nil, err) 580 581 // Now the root directory should be empty, too. 582 entries, err = fusetesting.ReadDirPicky(t.Dir) 583 584 AssertEq(nil, err) 585 ExpectThat(entries, ElementsAre()) 586 } 587 588 func (t *MemFSTest) Rmdir_NonExistent() { 589 err := os.Remove(path.Join(t.Dir, "blah")) 590 591 AssertNe(nil, err) 592 ExpectThat(err, Error(HasSubstr("no such file or directory"))) 593 } 594 595 func (t *MemFSTest) Rmdir_OpenedForReading() { 596 var err error 597 598 // Create a directory. 599 createTime := time.Now() 600 err = os.Mkdir(path.Join(t.Dir, "dir"), 0700) 601 AssertEq(nil, err) 602 603 // Open the directory for reading. 604 f, err := os.Open(path.Join(t.Dir, "dir")) 605 defer func() { 606 if f != nil { 607 ExpectEq(nil, f.Close()) 608 } 609 }() 610 611 AssertEq(nil, err) 612 613 // Remove the directory. 614 err = os.Remove(path.Join(t.Dir, "dir")) 615 AssertEq(nil, err) 616 617 // Create a new directory, with the same name even, and add some contents 618 // within it. 619 err = os.MkdirAll(path.Join(t.Dir, "dir/foo"), 0700) 620 AssertEq(nil, err) 621 622 err = os.MkdirAll(path.Join(t.Dir, "dir/bar"), 0700) 623 AssertEq(nil, err) 624 625 err = os.MkdirAll(path.Join(t.Dir, "dir/baz"), 0700) 626 AssertEq(nil, err) 627 628 // We should still be able to stat the open file handle. It should show up as 629 // unlinked. 630 fi, err := f.Stat() 631 632 ExpectEq("dir", fi.Name()) 633 ExpectThat(fi, fusetesting.MtimeIsWithin(createTime, timeSlop)) 634 ExpectEq(0, fi.Sys().(*syscall.Stat_t).Nlink) 635 636 // Attempt to read from the directory. This shouldn't see any junk from the 637 // new directory. It should either succeed with an empty result or should 638 // return ENOENT. 639 names, err := f.Readdirnames(0) 640 641 if err != nil { 642 ExpectThat(err, Error(HasSubstr("no such file"))) 643 } else { 644 ExpectThat(names, ElementsAre()) 645 } 646 } 647 648 func (t *MemFSTest) CaseSensitive() { 649 var err error 650 651 // Create a file. 652 err = ioutil.WriteFile(path.Join(t.Dir, "file"), []byte{}, 0400) 653 AssertEq(nil, err) 654 655 // Create a directory. 656 err = os.Mkdir(path.Join(t.Dir, "dir"), 0400) 657 AssertEq(nil, err) 658 659 // Attempt to stat with the wrong case. 660 names := []string{ 661 "FILE", 662 "File", 663 "filE", 664 "DIR", 665 "Dir", 666 "dIr", 667 } 668 669 for _, name := range names { 670 _, err = os.Stat(path.Join(t.Dir, name)) 671 AssertNe(nil, err, "Name: %s", name) 672 AssertThat(err, Error(HasSubstr("no such file or directory"))) 673 } 674 } 675 676 func (t *MemFSTest) WriteOverlapsEndOfFile() { 677 var err error 678 var n int 679 680 // Create a file. 681 f, err := os.Create(path.Join(t.Dir, "foo")) 682 t.ToClose = append(t.ToClose, f) 683 AssertEq(nil, err) 684 685 // Make it 4 bytes long. 686 err = f.Truncate(4) 687 AssertEq(nil, err) 688 689 // Write the range [2, 6). 690 n, err = f.WriteAt([]byte("taco"), 2) 691 AssertEq(nil, err) 692 AssertEq(4, n) 693 694 // Read the full contents of the file. 695 contents, err := ioutil.ReadAll(f) 696 AssertEq(nil, err) 697 ExpectEq("\x00\x00taco", string(contents)) 698 } 699 700 func (t *MemFSTest) WriteStartsAtEndOfFile() { 701 var err error 702 var n int 703 704 // Create a file. 705 f, err := os.Create(path.Join(t.Dir, "foo")) 706 t.ToClose = append(t.ToClose, f) 707 AssertEq(nil, err) 708 709 // Make it 2 bytes long. 710 err = f.Truncate(2) 711 AssertEq(nil, err) 712 713 // Write the range [2, 6). 714 n, err = f.WriteAt([]byte("taco"), 2) 715 AssertEq(nil, err) 716 AssertEq(4, n) 717 718 // Read the full contents of the file. 719 contents, err := ioutil.ReadAll(f) 720 AssertEq(nil, err) 721 ExpectEq("\x00\x00taco", string(contents)) 722 } 723 724 func (t *MemFSTest) WriteStartsPastEndOfFile() { 725 var err error 726 var n int 727 728 // Create a file. 729 f, err := os.Create(path.Join(t.Dir, "foo")) 730 t.ToClose = append(t.ToClose, f) 731 AssertEq(nil, err) 732 733 // Write the range [2, 6). 734 n, err = f.WriteAt([]byte("taco"), 2) 735 AssertEq(nil, err) 736 AssertEq(4, n) 737 738 // Read the full contents of the file. 739 contents, err := ioutil.ReadAll(f) 740 AssertEq(nil, err) 741 ExpectEq("\x00\x00taco", string(contents)) 742 } 743 744 func (t *MemFSTest) WriteAtDoesntChangeOffset_NotAppendMode() { 745 var err error 746 var n int 747 748 // Create a file. 749 f, err := os.Create(path.Join(t.Dir, "foo")) 750 t.ToClose = append(t.ToClose, f) 751 AssertEq(nil, err) 752 753 // Make it 16 bytes long. 754 err = f.Truncate(16) 755 AssertEq(nil, err) 756 757 // Seek to offset 4. 758 _, err = f.Seek(4, 0) 759 AssertEq(nil, err) 760 761 // Write the range [10, 14). 762 n, err = f.WriteAt([]byte("taco"), 2) 763 AssertEq(nil, err) 764 AssertEq(4, n) 765 766 // We should still be at offset 4. 767 offset, err := getFileOffset(f) 768 AssertEq(nil, err) 769 ExpectEq(4, offset) 770 } 771 772 func (t *MemFSTest) WriteAtDoesntChangeOffset_AppendMode() { 773 var err error 774 var n int 775 776 // Create a file in append mode. 777 f, err := os.OpenFile( 778 path.Join(t.Dir, "foo"), 779 os.O_RDWR|os.O_CREATE, 780 0600) 781 782 t.ToClose = append(t.ToClose, f) 783 AssertEq(nil, err) 784 785 // Make it 16 bytes long. 786 err = f.Truncate(16) 787 AssertEq(nil, err) 788 789 // Seek to offset 4. 790 _, err = f.Seek(4, 0) 791 AssertEq(nil, err) 792 793 // Write the range [10, 14). 794 n, err = f.WriteAt([]byte("taco"), 2) 795 AssertEq(nil, err) 796 AssertEq(4, n) 797 798 // We should still be at offset 4. 799 offset, err := getFileOffset(f) 800 AssertEq(nil, err) 801 ExpectEq(4, offset) 802 } 803 804 func (t *MemFSTest) LargeFile() { 805 var err error 806 807 // Create a file. 808 f, err := os.Create(path.Join(t.Dir, "foo")) 809 t.ToClose = append(t.ToClose, f) 810 AssertEq(nil, err) 811 812 // Copy in large contents. 813 const size = 1 << 24 814 contents := bytes.Repeat([]byte{0x20}, size) 815 816 _, err = io.Copy(f, bytes.NewReader(contents)) 817 AssertEq(nil, err) 818 819 // Read the full contents of the file. 820 contents, err = ioutil.ReadFile(f.Name()) 821 AssertEq(nil, err) 822 ExpectEq(size, len(contents)) 823 } 824 825 func (t *MemFSTest) AppendMode() { 826 var err error 827 var n int 828 var off int64 829 buf := make([]byte, 1024) 830 831 // Create a file with some contents. 832 fileName := path.Join(t.Dir, "foo") 833 err = ioutil.WriteFile(fileName, []byte("Jello, "), 0600) 834 AssertEq(nil, err) 835 836 // Open the file in append mode. 837 f, err := os.OpenFile(fileName, os.O_RDWR|os.O_APPEND, 0600) 838 t.ToClose = append(t.ToClose, f) 839 AssertEq(nil, err) 840 841 // Seek to somewhere silly and then write. 842 off, err = f.Seek(2, 0) 843 AssertEq(nil, err) 844 AssertEq(2, off) 845 846 n, err = f.Write([]byte("world!")) 847 AssertEq(nil, err) 848 AssertEq(6, n) 849 850 // The offset should have been updated to point at the end of the file. 851 off, err = getFileOffset(f) 852 AssertEq(nil, err) 853 ExpectEq(13, off) 854 855 off, err = getFileOffset(f) 856 AssertEq(nil, err) 857 ExpectEq(13, off) 858 859 // Read back the contents of the file, which should be correct even though we 860 // seeked to a silly place before writing the world part. 861 // 862 // Linux's support for pwrite is buggy; the pwrite(2) man page says this: 863 // 864 // POSIX requires that opening a file with the O_APPEND flag should have 865 // no affect on the location at which pwrite() writes data. However, on 866 // Linux, if a file is opened with O_APPEND, pwrite() appends data to 867 // the end of the file, regardless of the value of offset. 868 // 869 // So we allow either the POSIX result or the Linux result. 870 n, err = f.ReadAt(buf, 0) 871 AssertEq(io.EOF, err) 872 ExpectThat(string(buf[:n]), AnyOf("Jello, world!", "Jello, world!H")) 873 } 874 875 func (t *MemFSTest) ReadsPastEndOfFile() { 876 var err error 877 var n int 878 buf := make([]byte, 1024) 879 880 // Create a file. 881 f, err := os.Create(path.Join(t.Dir, "foo")) 882 t.ToClose = append(t.ToClose, f) 883 AssertEq(nil, err) 884 885 // Give it some contents. 886 n, err = f.Write([]byte("taco")) 887 AssertEq(nil, err) 888 AssertEq(4, n) 889 890 // Read a range overlapping EOF. 891 n, err = f.ReadAt(buf[:4], 2) 892 AssertEq(io.EOF, err) 893 ExpectEq(2, n) 894 ExpectEq("co", string(buf[:n])) 895 896 // Read a range starting at EOF. 897 n, err = f.ReadAt(buf[:4], 4) 898 AssertEq(io.EOF, err) 899 ExpectEq(0, n) 900 ExpectEq("", string(buf[:n])) 901 902 // Read a range starting past EOF. 903 n, err = f.ReadAt(buf[:4], 100) 904 AssertEq(io.EOF, err) 905 ExpectEq(0, n) 906 ExpectEq("", string(buf[:n])) 907 } 908 909 func (t *MemFSTest) Truncate_Smaller() { 910 var err error 911 fileName := path.Join(t.Dir, "foo") 912 913 // Create a file. 914 err = ioutil.WriteFile(fileName, []byte("taco"), 0600) 915 AssertEq(nil, err) 916 917 // Open it for modification. 918 f, err := os.OpenFile(fileName, os.O_RDWR, 0) 919 t.ToClose = append(t.ToClose, f) 920 AssertEq(nil, err) 921 922 // Truncate it. 923 err = f.Truncate(2) 924 AssertEq(nil, err) 925 926 // Stat it. 927 fi, err := f.Stat() 928 AssertEq(nil, err) 929 ExpectEq(2, fi.Size()) 930 931 // Read the contents. 932 contents, err := ioutil.ReadFile(fileName) 933 AssertEq(nil, err) 934 ExpectEq("ta", string(contents)) 935 } 936 937 func (t *MemFSTest) Truncate_SameSize() { 938 var err error 939 fileName := path.Join(t.Dir, "foo") 940 941 // Create a file. 942 err = ioutil.WriteFile(fileName, []byte("taco"), 0600) 943 AssertEq(nil, err) 944 945 // Open it for modification. 946 f, err := os.OpenFile(fileName, os.O_RDWR, 0) 947 t.ToClose = append(t.ToClose, f) 948 AssertEq(nil, err) 949 950 // Truncate it. 951 err = f.Truncate(4) 952 AssertEq(nil, err) 953 954 // Stat it. 955 fi, err := f.Stat() 956 AssertEq(nil, err) 957 ExpectEq(4, fi.Size()) 958 959 // Read the contents. 960 contents, err := ioutil.ReadFile(fileName) 961 AssertEq(nil, err) 962 ExpectEq("taco", string(contents)) 963 } 964 965 func (t *MemFSTest) Truncate_Larger() { 966 var err error 967 fileName := path.Join(t.Dir, "foo") 968 969 // Create a file. 970 err = ioutil.WriteFile(fileName, []byte("taco"), 0600) 971 AssertEq(nil, err) 972 973 // Open it for modification. 974 f, err := os.OpenFile(fileName, os.O_RDWR, 0) 975 t.ToClose = append(t.ToClose, f) 976 AssertEq(nil, err) 977 978 // Truncate it. 979 err = f.Truncate(6) 980 AssertEq(nil, err) 981 982 // Stat it. 983 fi, err := f.Stat() 984 AssertEq(nil, err) 985 ExpectEq(6, fi.Size()) 986 987 // Read the contents. 988 contents, err := ioutil.ReadFile(fileName) 989 AssertEq(nil, err) 990 ExpectEq("taco\x00\x00", string(contents)) 991 } 992 993 func (t *MemFSTest) Chmod() { 994 var err error 995 fileName := path.Join(t.Dir, "foo") 996 997 // Create a file. 998 err = ioutil.WriteFile(fileName, []byte(""), 0600) 999 AssertEq(nil, err) 1000 1001 // Chmod it. 1002 err = os.Chmod(fileName, 0754) 1003 AssertEq(nil, err) 1004 1005 // Stat it. 1006 fi, err := os.Stat(fileName) 1007 AssertEq(nil, err) 1008 ExpectEq(0754, fi.Mode()) 1009 } 1010 1011 func (t *MemFSTest) Chtimes() { 1012 var err error 1013 fileName := path.Join(t.Dir, "foo") 1014 1015 // Create a file. 1016 err = ioutil.WriteFile(fileName, []byte(""), 0600) 1017 AssertEq(nil, err) 1018 1019 // Chtimes it. 1020 expectedMtime := time.Now().Add(123 * time.Second).Round(time.Second) 1021 err = os.Chtimes(fileName, time.Now(), expectedMtime) 1022 AssertEq(nil, err) 1023 1024 // Stat it. 1025 fi, err := os.Stat(fileName) 1026 AssertEq(nil, err) 1027 ExpectThat(fi, fusetesting.MtimeIsWithin(expectedMtime, timeSlop)) 1028 } 1029 1030 func (t *MemFSTest) ReadDirWhileModifying() { 1031 dirName := path.Join(t.Dir, "dir") 1032 createFile := func(name string) { 1033 AssertEq(nil, ioutil.WriteFile(path.Join(dirName, name), []byte{}, 0400)) 1034 } 1035 1036 // Create a directory. 1037 err := os.Mkdir(dirName, 0700) 1038 AssertEq(nil, err) 1039 1040 // Open the directory. 1041 d, err := os.Open(dirName) 1042 t.ToClose = append(t.ToClose, d) 1043 AssertEq(nil, err) 1044 1045 // Add four files. 1046 createFile("foo") 1047 createFile("bar") 1048 createFile("baz") 1049 createFile("qux") 1050 1051 // Read one entry from the directory. 1052 names, err := d.Readdirnames(1) 1053 AssertEq(nil, err) 1054 AssertThat(names, ElementsAre("foo")) 1055 1056 // Make two holes in the directory. 1057 AssertEq(nil, os.Remove(path.Join(dirName, "foo"))) 1058 AssertEq(nil, os.Remove(path.Join(dirName, "baz"))) 1059 1060 // Add a bunch of files to the directory. 1061 createFile("blah_0") 1062 createFile("blah_1") 1063 createFile("blah_2") 1064 createFile("blah_3") 1065 createFile("blah_4") 1066 1067 // Continue reading from the directory, noting the names we see. 1068 namesSeen := make(map[string]bool) 1069 for { 1070 names, err = d.Readdirnames(1) 1071 for _, n := range names { 1072 namesSeen[n] = true 1073 } 1074 1075 if err == io.EOF { 1076 break 1077 } 1078 1079 AssertEq(nil, err) 1080 } 1081 1082 // Posix requires that we should have seen bar and qux, which we didn't 1083 // delete. 1084 ExpectTrue(namesSeen["bar"]) 1085 ExpectTrue(namesSeen["qux"]) 1086 } 1087 1088 func (t *MemFSTest) CreateSymlink() { 1089 var fi os.FileInfo 1090 var err error 1091 1092 symlinkName := path.Join(t.Dir, "foo") 1093 target := "taco/burrito" 1094 1095 // Create the link. 1096 err = os.Symlink(target, symlinkName) 1097 AssertEq(nil, err) 1098 1099 // Stat the link. 1100 fi, err = os.Lstat(symlinkName) 1101 AssertEq(nil, err) 1102 1103 ExpectEq("foo", fi.Name()) 1104 ExpectEq(0444|os.ModeSymlink, fi.Mode()) 1105 1106 // Read the link. 1107 actual, err := os.Readlink(symlinkName) 1108 AssertEq(nil, err) 1109 ExpectEq(target, actual) 1110 1111 // Read the parent directory. 1112 entries, err := fusetesting.ReadDirPicky(t.Dir) 1113 AssertEq(nil, err) 1114 AssertEq(1, len(entries)) 1115 1116 fi = entries[0] 1117 ExpectEq("foo", fi.Name()) 1118 ExpectEq(0444|os.ModeSymlink, fi.Mode()) 1119 } 1120 1121 func (t *MemFSTest) CreateSymlink_AlreadyExists() { 1122 var err error 1123 1124 // Create a file and a directory. 1125 fileName := path.Join(t.Dir, "foo") 1126 err = ioutil.WriteFile(fileName, []byte{}, 0400) 1127 AssertEq(nil, err) 1128 1129 dirName := path.Join(t.Dir, "bar") 1130 err = os.Mkdir(dirName, 0700) 1131 AssertEq(nil, err) 1132 1133 // Create an existing symlink. 1134 symlinkName := path.Join(t.Dir, "baz") 1135 err = os.Symlink("blah", symlinkName) 1136 AssertEq(nil, err) 1137 1138 // Symlinking on top of any of them should fail. 1139 names := []string{ 1140 fileName, 1141 dirName, 1142 symlinkName, 1143 } 1144 1145 for _, n := range names { 1146 err = os.Symlink("blah", n) 1147 ExpectThat(err, Error(HasSubstr("exists"))) 1148 } 1149 } 1150 1151 func (t *MemFSTest) ReadLink_NonExistent() { 1152 _, err := os.Readlink(path.Join(t.Dir, "foo")) 1153 ExpectTrue(os.IsNotExist(err), "err: %v", err) 1154 } 1155 1156 func (t *MemFSTest) ReadLink_NotASymlink() { 1157 var err error 1158 1159 // Create a file and a directory. 1160 fileName := path.Join(t.Dir, "foo") 1161 err = ioutil.WriteFile(fileName, []byte{}, 0400) 1162 AssertEq(nil, err) 1163 1164 dirName := path.Join(t.Dir, "bar") 1165 err = os.Mkdir(dirName, 0700) 1166 AssertEq(nil, err) 1167 1168 // Reading either of them as a symlink should fail. 1169 names := []string{ 1170 fileName, 1171 dirName, 1172 } 1173 1174 for _, n := range names { 1175 _, err = os.Readlink(n) 1176 ExpectThat(err, Error(HasSubstr("invalid argument"))) 1177 } 1178 } 1179 1180 func (t *MemFSTest) DeleteSymlink() { 1181 var err error 1182 1183 symlinkName := path.Join(t.Dir, "foo") 1184 target := "taco/burrito" 1185 1186 // Create the link. 1187 err = os.Symlink(target, symlinkName) 1188 AssertEq(nil, err) 1189 1190 // Remove it. 1191 err = os.Remove(symlinkName) 1192 AssertEq(nil, err) 1193 1194 // Statting should now fail. 1195 _, err = os.Lstat(symlinkName) 1196 ExpectTrue(os.IsNotExist(err), "err: %v", err) 1197 1198 // Read the parent directory. 1199 entries, err := fusetesting.ReadDirPicky(t.Dir) 1200 1201 AssertEq(nil, err) 1202 ExpectThat(entries, ElementsAre()) 1203 } 1204 1205 func (t *MemFSTest) CreateHardlink() { 1206 var fi os.FileInfo 1207 var err error 1208 1209 // Create a file. 1210 fileName := path.Join(t.Dir, "regular_file") 1211 const contents = "Hello\x00world" 1212 1213 err = ioutil.WriteFile(fileName, []byte(contents), 0444) 1214 AssertEq(nil, err) 1215 1216 // Clean up the file at the end. 1217 defer func() { 1218 err := os.Remove(fileName) 1219 AssertEq(nil, err) 1220 }() 1221 1222 // Create a link to the file. 1223 linkName := path.Join(t.Dir, "foo") 1224 err = os.Link(fileName, linkName) 1225 AssertEq(nil, err) 1226 1227 // Clean up the file at the end. 1228 defer func() { 1229 err := os.Remove(linkName) 1230 AssertEq(nil, err) 1231 }() 1232 1233 // Stat the link. 1234 fi, err = os.Lstat(linkName) 1235 AssertEq(nil, err) 1236 1237 ExpectEq("foo", fi.Name()) 1238 ExpectEq(0444, fi.Mode()) 1239 1240 // Read the parent directory. 1241 entries, err := fusetesting.ReadDirPicky(t.Dir) 1242 AssertEq(nil, err) 1243 AssertEq(2, len(entries)) 1244 1245 fi = entries[0] 1246 ExpectEq("foo", fi.Name()) 1247 ExpectEq(0444, fi.Mode()) 1248 1249 fi = entries[1] 1250 ExpectEq("regular_file", fi.Name()) 1251 ExpectEq(0444, fi.Mode()) 1252 } 1253 1254 func (t *MemFSTest) CreateHardlink_AlreadyExists() { 1255 var err error 1256 1257 // Create a file and a directory. 1258 fileName := path.Join(t.Dir, "foo") 1259 err = ioutil.WriteFile(fileName, []byte{}, 0400) 1260 AssertEq(nil, err) 1261 1262 dirName := path.Join(t.Dir, "bar") 1263 err = os.Mkdir(dirName, 0700) 1264 AssertEq(nil, err) 1265 1266 // Create an existing symlink. 1267 symlinkName := path.Join(t.Dir, "baz") 1268 err = os.Symlink("blah", symlinkName) 1269 AssertEq(nil, err) 1270 1271 // Create another link to the file. 1272 hardlinkName := path.Join(t.Dir, "qux") 1273 err = os.Link(fileName, hardlinkName) 1274 AssertEq(nil, err) 1275 1276 // Symlinking on top of any of them should fail. 1277 names := []string{ 1278 fileName, 1279 dirName, 1280 symlinkName, 1281 hardlinkName, 1282 } 1283 1284 for _, n := range names { 1285 err = os.Link(fileName, n) 1286 ExpectThat(err, Error(HasSubstr("exists"))) 1287 } 1288 } 1289 1290 func (t *MemFSTest) DeleteHardlink() { 1291 var fi os.FileInfo 1292 var err error 1293 1294 // Create a file. 1295 fileName := path.Join(t.Dir, "regular_file") 1296 const contents = "Hello\x00world" 1297 1298 err = ioutil.WriteFile(fileName, []byte(contents), 0444) 1299 AssertEq(nil, err) 1300 1301 // Step #1: We will create and remove a link and verify that 1302 // after removal everything is as expected. 1303 1304 // Create a link to the file. 1305 linkName := path.Join(t.Dir, "foo") 1306 err = os.Link(fileName, linkName) 1307 AssertEq(nil, err) 1308 1309 // Remove the link. 1310 err = os.Remove(linkName) 1311 AssertEq(nil, err) 1312 1313 // Stat the link. 1314 fi, err = os.Lstat(linkName) 1315 AssertEq(nil, fi) 1316 ExpectThat(err, Error(HasSubstr("no such file"))) 1317 1318 // Read the parent directory. 1319 entries, err := fusetesting.ReadDirPicky(t.Dir) 1320 AssertEq(nil, err) 1321 AssertEq(1, len(entries)) 1322 1323 fi = entries[0] 1324 ExpectEq("regular_file", fi.Name()) 1325 ExpectEq(0444, fi.Mode()) 1326 1327 // Step #2: We will create a link and remove the original file subsequently 1328 // and verify that after removal everything is as expected. 1329 1330 // Create a link to the file. 1331 linkName = path.Join(t.Dir, "bar") 1332 err = os.Link(fileName, linkName) 1333 AssertEq(nil, err) 1334 1335 // Remove the original file. 1336 err = os.Remove(fileName) 1337 AssertEq(nil, err) 1338 1339 // Stat the link. 1340 fi, err = os.Lstat(linkName) 1341 AssertEq(nil, err) 1342 ExpectEq("bar", fi.Name()) 1343 ExpectEq(0444, fi.Mode()) 1344 1345 // Stat the original file. 1346 fi, err = os.Lstat(fileName) 1347 AssertEq(nil, fi) 1348 ExpectThat(err, Error(HasSubstr("no such file"))) 1349 1350 // Read the parent directory. 1351 entries, err = fusetesting.ReadDirPicky(t.Dir) 1352 AssertEq(nil, err) 1353 AssertEq(1, len(entries)) 1354 1355 fi = entries[0] 1356 ExpectEq("bar", fi.Name()) 1357 ExpectEq(0444, fi.Mode()) 1358 1359 // Cleanup. 1360 err = os.Remove(linkName) 1361 AssertEq(nil, err) 1362 } 1363 1364 func (t *MemFSTest) ReadHardlink() { 1365 var err error 1366 1367 // Create a file. 1368 fileName := path.Join(t.Dir, "regular_file") 1369 const contents = "Hello\x00world" 1370 1371 err = ioutil.WriteFile(fileName, []byte(contents), 0444) 1372 AssertEq(nil, err) 1373 1374 // Clean up the file at the end. 1375 defer func() { 1376 err := os.Remove(fileName) 1377 AssertEq(nil, err) 1378 }() 1379 1380 // Create a link to the file. 1381 linkName := path.Join(t.Dir, "foo") 1382 err = os.Link(fileName, linkName) 1383 AssertEq(nil, err) 1384 1385 // Clean up the file at the end. 1386 defer func() { 1387 err := os.Remove(linkName) 1388 AssertEq(nil, err) 1389 }() 1390 1391 // Read files. 1392 original, err := ioutil.ReadFile(fileName) 1393 AssertEq(nil, err) 1394 linked, err := ioutil.ReadFile(linkName) 1395 AssertEq(nil, err) 1396 1397 // Check if the bytes are the same. 1398 AssertEq(true, reflect.DeepEqual(original, linked)) 1399 } 1400 1401 func (t *MemFSTest) CreateInParallel_NoTruncate() { 1402 fusetesting.RunCreateInParallelTest_NoTruncate(t.Ctx, t.Dir) 1403 } 1404 1405 func (t *MemFSTest) CreateInParallel_Truncate() { 1406 fusetesting.RunCreateInParallelTest_Truncate(t.Ctx, t.Dir) 1407 } 1408 1409 func (t *MemFSTest) CreateInParallel_Exclusive() { 1410 fusetesting.RunCreateInParallelTest_Exclusive(t.Ctx, t.Dir) 1411 } 1412 1413 func (t *MemFSTest) MkdirInParallel() { 1414 fusetesting.RunMkdirInParallelTest(t.Ctx, t.Dir) 1415 } 1416 1417 func (t *MemFSTest) SymlinkInParallel() { 1418 fusetesting.RunSymlinkInParallelTest(t.Ctx, t.Dir) 1419 } 1420 1421 func (t *MemFSTest) HardlinkInParallel() { 1422 fusetesting.RunHardlinkInParallelTest(t.Ctx, t.Dir) 1423 } 1424 1425 func (t *MemFSTest) RenameWithinDir_File() { 1426 var err error 1427 1428 // Create a parent directory. 1429 parentPath := path.Join(t.Dir, "parent") 1430 1431 err = os.Mkdir(parentPath, 0700) 1432 AssertEq(nil, err) 1433 1434 // And a file within it. 1435 oldPath := path.Join(parentPath, "foo") 1436 1437 err = ioutil.WriteFile(oldPath, []byte("taco"), 0400) 1438 AssertEq(nil, err) 1439 1440 // Rename it. 1441 newPath := path.Join(parentPath, "bar") 1442 1443 err = os.Rename(oldPath, newPath) 1444 AssertEq(nil, err) 1445 1446 // The old name shouldn't work. 1447 _, err = os.Stat(oldPath) 1448 ExpectTrue(os.IsNotExist(err), "err: %v", err) 1449 1450 _, err = ioutil.ReadFile(oldPath) 1451 ExpectTrue(os.IsNotExist(err), "err: %v", err) 1452 1453 // The new name should. 1454 fi, err := os.Stat(newPath) 1455 AssertEq(nil, err) 1456 ExpectEq(len("taco"), fi.Size()) 1457 ExpectEq(os.FileMode(0400), fi.Mode()) 1458 1459 contents, err := ioutil.ReadFile(newPath) 1460 AssertEq(nil, err) 1461 ExpectEq("taco", string(contents)) 1462 1463 // There should only be the new entry in the directory. 1464 entries, err := fusetesting.ReadDirPicky(parentPath) 1465 AssertEq(nil, err) 1466 AssertEq(1, len(entries)) 1467 fi = entries[0] 1468 1469 ExpectEq(path.Base(newPath), fi.Name()) 1470 ExpectEq(os.FileMode(0400), fi.Mode()) 1471 } 1472 1473 func (t *MemFSTest) RenameWithinDir_Directory() { 1474 var err error 1475 1476 // Create a parent directory. 1477 parentPath := path.Join(t.Dir, "parent") 1478 1479 err = os.Mkdir(parentPath, 0700) 1480 AssertEq(nil, err) 1481 1482 // And a non-empty directory within it. 1483 oldPath := path.Join(parentPath, "foo") 1484 1485 err = os.MkdirAll(path.Join(oldPath, "child"), 0700) 1486 AssertEq(nil, err) 1487 1488 // Rename it. 1489 newPath := path.Join(parentPath, "bar") 1490 1491 err = os.Rename(oldPath, newPath) 1492 AssertEq(nil, err) 1493 1494 // The old name shouldn't work. 1495 _, err = os.Stat(oldPath) 1496 ExpectTrue(os.IsNotExist(err), "err: %v", err) 1497 1498 // The new name should. 1499 fi, err := os.Stat(newPath) 1500 AssertEq(nil, err) 1501 ExpectEq(os.FileMode(0700)|os.ModeDir, fi.Mode()) 1502 1503 // There should only be the new entry in the parent. 1504 entries, err := fusetesting.ReadDirPicky(parentPath) 1505 AssertEq(nil, err) 1506 AssertEq(1, len(entries)) 1507 fi = entries[0] 1508 1509 ExpectEq(path.Base(newPath), fi.Name()) 1510 ExpectEq(os.FileMode(0700)|os.ModeDir, fi.Mode()) 1511 1512 // And the child should still be present. 1513 entries, err = fusetesting.ReadDirPicky(newPath) 1514 AssertEq(nil, err) 1515 AssertEq(1, len(entries)) 1516 fi = entries[0] 1517 1518 ExpectEq("child", fi.Name()) 1519 ExpectEq(os.FileMode(0700)|os.ModeDir, fi.Mode()) 1520 } 1521 1522 func (t *MemFSTest) RenameWithinDir_SameName() { 1523 var err error 1524 1525 // Create a parent directory. 1526 parentPath := path.Join(t.Dir, "parent") 1527 1528 err = os.Mkdir(parentPath, 0700) 1529 AssertEq(nil, err) 1530 1531 // And a file within it. 1532 filePath := path.Join(parentPath, "foo") 1533 1534 err = ioutil.WriteFile(filePath, []byte("taco"), 0400) 1535 AssertEq(nil, err) 1536 1537 // Attempt to rename it. 1538 err = os.Rename(filePath, filePath) 1539 AssertEq(nil, err) 1540 1541 // The file should still exist. 1542 contents, err := ioutil.ReadFile(filePath) 1543 AssertEq(nil, err) 1544 ExpectEq("taco", string(contents)) 1545 1546 // There should only be the one entry in the directory. 1547 entries, err := fusetesting.ReadDirPicky(parentPath) 1548 AssertEq(nil, err) 1549 AssertEq(1, len(entries)) 1550 fi := entries[0] 1551 1552 ExpectEq(path.Base(filePath), fi.Name()) 1553 ExpectEq(os.FileMode(0400), fi.Mode()) 1554 } 1555 1556 func (t *MemFSTest) RenameAcrossDirs_File() { 1557 var err error 1558 1559 // Create two parent directories. 1560 oldParentPath := path.Join(t.Dir, "old") 1561 newParentPath := path.Join(t.Dir, "new") 1562 1563 err = os.Mkdir(oldParentPath, 0700) 1564 AssertEq(nil, err) 1565 1566 err = os.Mkdir(newParentPath, 0700) 1567 AssertEq(nil, err) 1568 1569 // And a file within the first. 1570 oldPath := path.Join(oldParentPath, "foo") 1571 1572 err = ioutil.WriteFile(oldPath, []byte("taco"), 0400) 1573 AssertEq(nil, err) 1574 1575 // Rename it. 1576 newPath := path.Join(newParentPath, "bar") 1577 1578 err = os.Rename(oldPath, newPath) 1579 AssertEq(nil, err) 1580 1581 // The old name shouldn't work. 1582 _, err = os.Stat(oldPath) 1583 ExpectTrue(os.IsNotExist(err), "err: %v", err) 1584 1585 _, err = ioutil.ReadFile(oldPath) 1586 ExpectTrue(os.IsNotExist(err), "err: %v", err) 1587 1588 // The new name should. 1589 fi, err := os.Stat(newPath) 1590 AssertEq(nil, err) 1591 ExpectEq(len("taco"), fi.Size()) 1592 ExpectEq(os.FileMode(0400), fi.Mode()) 1593 1594 contents, err := ioutil.ReadFile(newPath) 1595 AssertEq(nil, err) 1596 ExpectEq("taco", string(contents)) 1597 1598 // Check the old parent. 1599 entries, err := fusetesting.ReadDirPicky(oldParentPath) 1600 AssertEq(nil, err) 1601 AssertEq(0, len(entries)) 1602 1603 // And the new one. 1604 entries, err = fusetesting.ReadDirPicky(newParentPath) 1605 AssertEq(nil, err) 1606 AssertEq(1, len(entries)) 1607 fi = entries[0] 1608 1609 ExpectEq(path.Base(newPath), fi.Name()) 1610 ExpectEq(os.FileMode(0400), fi.Mode()) 1611 } 1612 1613 func (t *MemFSTest) RenameAcrossDirs_Directory() { 1614 var err error 1615 1616 // Create two parent directories. 1617 oldParentPath := path.Join(t.Dir, "old") 1618 newParentPath := path.Join(t.Dir, "new") 1619 1620 err = os.Mkdir(oldParentPath, 0700) 1621 AssertEq(nil, err) 1622 1623 err = os.Mkdir(newParentPath, 0700) 1624 AssertEq(nil, err) 1625 1626 // And a non-empty directory within the first. 1627 oldPath := path.Join(oldParentPath, "foo") 1628 1629 err = os.MkdirAll(path.Join(oldPath, "child"), 0700) 1630 AssertEq(nil, err) 1631 1632 // Rename it. 1633 newPath := path.Join(newParentPath, "bar") 1634 1635 err = os.Rename(oldPath, newPath) 1636 AssertEq(nil, err) 1637 1638 // The old name shouldn't work. 1639 _, err = os.Stat(oldPath) 1640 ExpectTrue(os.IsNotExist(err), "err: %v", err) 1641 1642 // The new name should. 1643 fi, err := os.Stat(newPath) 1644 AssertEq(nil, err) 1645 ExpectEq(os.FileMode(0700)|os.ModeDir, fi.Mode()) 1646 1647 // And the child should still be present. 1648 entries, err := fusetesting.ReadDirPicky(newPath) 1649 AssertEq(nil, err) 1650 AssertEq(1, len(entries)) 1651 fi = entries[0] 1652 1653 ExpectEq("child", fi.Name()) 1654 ExpectEq(os.FileMode(0700)|os.ModeDir, fi.Mode()) 1655 1656 // Check the old parent. 1657 entries, err = fusetesting.ReadDirPicky(oldParentPath) 1658 AssertEq(nil, err) 1659 AssertEq(0, len(entries)) 1660 1661 // And the new one. 1662 entries, err = fusetesting.ReadDirPicky(newParentPath) 1663 AssertEq(nil, err) 1664 AssertEq(1, len(entries)) 1665 fi = entries[0] 1666 1667 ExpectEq(path.Base(newPath), fi.Name()) 1668 ExpectEq(os.FileMode(0700)|os.ModeDir, fi.Mode()) 1669 } 1670 1671 func (t *MemFSTest) RenameOutOfFileSystem() { 1672 var err error 1673 1674 // Create a file. 1675 oldPath := path.Join(t.Dir, "foo") 1676 1677 err = ioutil.WriteFile(oldPath, []byte("taco"), 0400) 1678 AssertEq(nil, err) 1679 1680 // Attempt to move it out of the file system. 1681 tempDir, err := ioutil.TempDir("", "memfs_test") 1682 AssertEq(nil, err) 1683 defer os.RemoveAll(tempDir) 1684 1685 err = os.Rename(oldPath, path.Join(tempDir, "bar")) 1686 ExpectThat(err, Error(HasSubstr("cross-device"))) 1687 } 1688 1689 func (t *MemFSTest) RenameIntoFileSystem() { 1690 var err error 1691 1692 // Create a file outside of our file system. 1693 f, err := ioutil.TempFile("", "memfs_test") 1694 AssertEq(nil, err) 1695 defer f.Close() 1696 1697 oldPath := f.Name() 1698 defer os.Remove(oldPath) 1699 1700 // Attempt to move it into the file system. 1701 err = os.Rename(oldPath, path.Join(t.Dir, "bar")) 1702 ExpectThat(err, Error(HasSubstr("cross-device"))) 1703 } 1704 1705 func (t *MemFSTest) RenameOverExistingFile() { 1706 var err error 1707 1708 // Create two files. 1709 oldPath := path.Join(t.Dir, "foo") 1710 err = ioutil.WriteFile(oldPath, []byte("taco"), 0400) 1711 AssertEq(nil, err) 1712 1713 newPath := path.Join(t.Dir, "bar") 1714 err = ioutil.WriteFile(newPath, []byte("burrito"), 0600) 1715 AssertEq(nil, err) 1716 1717 // Rename one over the other. 1718 err = os.Rename(oldPath, newPath) 1719 AssertEq(nil, err) 1720 1721 // Check the file contents. 1722 contents, err := ioutil.ReadFile(newPath) 1723 AssertEq(nil, err) 1724 ExpectEq("taco", string(contents)) 1725 1726 // And the parent listing. 1727 entries, err := fusetesting.ReadDirPicky(t.Dir) 1728 AssertEq(nil, err) 1729 AssertEq(1, len(entries)) 1730 fi := entries[0] 1731 1732 ExpectEq(path.Base(newPath), fi.Name()) 1733 ExpectEq(os.FileMode(0400), fi.Mode()) 1734 ExpectEq(len("taco"), fi.Size()) 1735 } 1736 1737 func (t *MemFSTest) RenameOverExistingDirectory() { 1738 var err error 1739 1740 // Create two directories, the first non-empty. 1741 oldPath := path.Join(t.Dir, "foo") 1742 err = os.MkdirAll(path.Join(oldPath, "child"), 0700) 1743 AssertEq(nil, err) 1744 1745 newPath := path.Join(t.Dir, "bar") 1746 err = os.Mkdir(newPath, 0600) 1747 AssertEq(nil, err) 1748 1749 // Renaming over the non-empty directory shouldn't work. 1750 err = os.Rename(newPath, oldPath) 1751 ExpectThat(err, Error(MatchesRegexp("not empty|file exists"))) 1752 1753 // As of Go 1.8 this shouldn't work the other way around either (see 1754 // https://github.com/golang/go/commit/321c312). 1755 if atLeastGo18 { 1756 err = os.Rename(oldPath, newPath) 1757 ExpectThat(err, Error(HasSubstr("file exists"))) 1758 1759 // Both should still be present in the parent listing. 1760 entries, err := fusetesting.ReadDirPicky(t.Dir) 1761 AssertEq(nil, err) 1762 ExpectEq(2, len(entries)) 1763 } 1764 } 1765 1766 func (t *MemFSTest) RenameOverExisting_WrongType() { 1767 var err error 1768 1769 // Create a file and a directory. 1770 filePath := path.Join(t.Dir, "foo") 1771 err = ioutil.WriteFile(filePath, []byte("taco"), 0400) 1772 AssertEq(nil, err) 1773 1774 dirPath := path.Join(t.Dir, "bar") 1775 err = os.Mkdir(dirPath, 0700) 1776 AssertEq(nil, err) 1777 1778 // Renaming either over the other shouldn't work. 1779 err = os.Rename(filePath, dirPath) 1780 ExpectThat(err, Error(MatchesRegexp("is a directory|file exists"))) 1781 1782 err = os.Rename(dirPath, filePath) 1783 ExpectThat(err, Error(HasSubstr("not a directory"))) 1784 } 1785 1786 func (t *MemFSTest) RenameNonExistentFile() { 1787 var err error 1788 1789 err = os.Rename(path.Join(t.Dir, "foo"), path.Join(t.Dir, "bar")) 1790 ExpectThat(err, Error(HasSubstr("no such file"))) 1791 } 1792 1793 func (t *MemFSTest) NoXattrs() { 1794 var err error 1795 var sz int 1796 var smallBuf [1]byte 1797 1798 // Create a file. 1799 filePath := path.Join(t.Dir, "foo") 1800 err = ioutil.WriteFile(filePath, []byte("taco"), 0400) 1801 AssertEq(nil, err) 1802 1803 // List xattr names. 1804 sz, err = unix.Listxattr(filePath, nil) 1805 AssertEq(nil, err) 1806 AssertEq(0, sz) 1807 1808 // Attempt to read a non-existent xattr. 1809 _, err = unix.Getxattr(filePath, "foo", nil) 1810 ExpectEq(fuse.ENOATTR, err) 1811 1812 // Attempt to read a non-existent xattr with a buf. 1813 _, err = unix.Getxattr(filePath, "foo", smallBuf[:]) 1814 ExpectEq(fuse.ENOATTR, err) 1815 1816 // List xattr names with a buf. 1817 sz, err = unix.Listxattr(filePath, smallBuf[:]) 1818 AssertEq(nil, err) 1819 ExpectEq(0, sz) 1820 } 1821 1822 func (t *MemFSTest) SetXAttr() { 1823 var err error 1824 var sz int 1825 var buf [1024]byte 1826 1827 // Create a file. 1828 filePath := path.Join(t.Dir, "foo") 1829 err = ioutil.WriteFile(filePath, []byte("taco"), 0600) 1830 AssertEq(nil, err) 1831 1832 err = unix.Setxattr(filePath, "foo", []byte("bar"), unix.XATTR_REPLACE) 1833 AssertEq(fuse.ENOATTR, err) 1834 1835 err = unix.Setxattr(filePath, "foo", []byte("bar"), unix.XATTR_CREATE) 1836 AssertEq(nil, err) 1837 1838 // List xattr with a buf that is too small. 1839 _, err = unix.Listxattr(filePath, buf[:1]) 1840 ExpectEq(unix.ERANGE, err) 1841 1842 // List xattr to ask for name size. 1843 sz, err = unix.Listxattr(filePath, nil) 1844 AssertEq(nil, err) 1845 AssertEq(4, sz) 1846 1847 // List xattr names. 1848 sz, err = unix.Listxattr(filePath, buf[:sz]) 1849 AssertEq(nil, err) 1850 AssertEq(4, sz) 1851 AssertEq("foo\000", string(buf[:sz])) 1852 1853 // Read xattr with a buf that is too small. 1854 _, err = unix.Getxattr(filePath, "foo", buf[:1]) 1855 ExpectEq(unix.ERANGE, err) 1856 1857 // Read xattr to ask for value size. 1858 sz, err = unix.Getxattr(filePath, "foo", nil) 1859 AssertEq(nil, err) 1860 AssertEq(3, sz) 1861 1862 // Read xattr value. 1863 sz, err = unix.Getxattr(filePath, "foo", buf[:sz]) 1864 AssertEq(nil, err) 1865 AssertEq(3, sz) 1866 AssertEq("bar", string(buf[:sz])) 1867 } 1868 1869 func (t *MemFSTest) RemoveXAttr() { 1870 var err error 1871 1872 // Create a file 1873 filePath := path.Join(t.Dir, "foo") 1874 err = ioutil.WriteFile(filePath, []byte("taco"), 0600) 1875 AssertEq(nil, err) 1876 1877 err = unix.Removexattr(filePath, "foo") 1878 AssertEq(fuse.ENOATTR, err) 1879 1880 err = unix.Setxattr(filePath, "foo", []byte("bar"), unix.XATTR_CREATE) 1881 AssertEq(nil, err) 1882 1883 err = unix.Removexattr(filePath, "foo") 1884 AssertEq(nil, err) 1885 1886 _, err = unix.Getxattr(filePath, "foo", nil) 1887 AssertEq(fuse.ENOATTR, err) 1888 } 1889 1890 //////////////////////////////////////////////////////////////////////// 1891 // Mknod 1892 //////////////////////////////////////////////////////////////////////// 1893 1894 type MknodTest struct { 1895 memFSTest 1896 } 1897 1898 func init() { RegisterTestSuite(&MknodTest{}) } 1899 1900 func (t *MknodTest) File() { 1901 // mknod(2) only works for root on OS X. 1902 if runtime.GOOS == "darwin" { 1903 return 1904 } 1905 1906 var err error 1907 p := path.Join(t.Dir, "foo") 1908 1909 // Create 1910 err = syscall.Mknod(p, syscall.S_IFREG|0641, 0) 1911 AssertEq(nil, err) 1912 1913 // Stat 1914 fi, err := os.Stat(p) 1915 AssertEq(nil, err) 1916 1917 ExpectEq(path.Base(p), fi.Name()) 1918 ExpectEq(0, fi.Size()) 1919 ExpectEq(os.FileMode(0641), fi.Mode()) 1920 1921 // Read 1922 contents, err := ioutil.ReadFile(p) 1923 AssertEq(nil, err) 1924 ExpectEq("", string(contents)) 1925 } 1926 1927 func (t *MknodTest) Directory() { 1928 // mknod(2) only works for root on OS X. 1929 if runtime.GOOS == "darwin" { 1930 return 1931 } 1932 1933 var err error 1934 p := path.Join(t.Dir, "foo") 1935 1936 // Quoth `man 2 mknod`: "Under Linux, this call cannot be used to create 1937 // directories." 1938 err = syscall.Mknod(p, syscall.S_IFDIR|0700, 0) 1939 ExpectEq(syscall.EPERM, err) 1940 } 1941 1942 func (t *MknodTest) AlreadyExists() { 1943 // mknod(2) only works for root on OS X. 1944 if runtime.GOOS == "darwin" { 1945 return 1946 } 1947 1948 var err error 1949 p := path.Join(t.Dir, "foo") 1950 1951 // Create (first) 1952 err = ioutil.WriteFile(p, []byte("taco"), 0600) 1953 AssertEq(nil, err) 1954 1955 // Create (second) 1956 err = syscall.Mknod(p, syscall.S_IFREG|0600, 0) 1957 ExpectEq(syscall.EEXIST, err) 1958 1959 // Read 1960 contents, err := ioutil.ReadFile(p) 1961 AssertEq(nil, err) 1962 ExpectEq("taco", string(contents)) 1963 } 1964 1965 func (t *MknodTest) NonExistentParent() { 1966 // mknod(2) only works for root on OS X. 1967 if runtime.GOOS == "darwin" { 1968 return 1969 } 1970 1971 var err error 1972 p := path.Join(t.Dir, "foo/bar") 1973 1974 err = syscall.Mknod(p, syscall.S_IFREG|0600, 0) 1975 ExpectEq(syscall.ENOENT, err) 1976 } 1977 1978 func (t *MknodTest) Fallocate_Larger() { 1979 var err error 1980 fileName := path.Join(t.Dir, "foo") 1981 1982 // Create a file. 1983 err = ioutil.WriteFile(fileName, []byte("taco"), 0600) 1984 AssertEq(nil, err) 1985 1986 // Open it for modification. 1987 f, err := os.OpenFile(fileName, os.O_RDWR, 0) 1988 t.ToClose = append(t.ToClose, f) 1989 AssertEq(nil, err) 1990 1991 // Truncate it. 1992 err = fallocate.Fallocate(f, 5, 1) 1993 AssertEq(nil, err) 1994 1995 // Stat it. 1996 fi, err := f.Stat() 1997 AssertEq(nil, err) 1998 ExpectEq(6, fi.Size()) 1999 2000 // Read the contents. 2001 contents, err := ioutil.ReadFile(fileName) 2002 AssertEq(nil, err) 2003 ExpectEq("taco\x00\x00", string(contents)) 2004 }