github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/kbfs/libfs/fs_test.go (about) 1 // Copyright 2017 Keybase Inc. All rights reserved. 2 // Use of this source code is governed by a BSD 3 // license that can be found in the LICENSE file. 4 5 package libfs 6 7 import ( 8 "bytes" 9 "context" 10 "os" 11 "path" 12 "testing" 13 "time" 14 15 "github.com/keybase/client/go/kbfs/data" 16 "github.com/keybase/client/go/kbfs/ioutil" 17 "github.com/keybase/client/go/kbfs/kbfsmd" 18 "github.com/keybase/client/go/kbfs/libcontext" 19 "github.com/keybase/client/go/kbfs/libkbfs" 20 "github.com/keybase/client/go/kbfs/test/clocktest" 21 "github.com/keybase/client/go/kbfs/tlf" 22 "github.com/keybase/client/go/kbfs/tlfhandle" 23 "github.com/keybase/client/go/protocol/keybase1" 24 "github.com/stretchr/testify/assert" 25 "github.com/stretchr/testify/require" 26 billy "gopkg.in/src-d/go-billy.v4" 27 ) 28 29 func makeFSWithBranch(t *testing.T, branch data.BranchName, subdir string) ( 30 context.Context, *tlfhandle.Handle, *FS) { 31 ctx := libcontext.BackgroundContextWithCancellationDelayer() 32 config := libkbfs.MakeTestConfigOrBust(t, "user1", "user2") 33 h, err := tlfhandle.ParseHandle( 34 ctx, config.KBPKI(), config.MDOps(), nil, "user1", tlf.Private) 35 require.NoError(t, err) 36 fs, err := NewFS( 37 ctx, config, h, branch, subdir, "", keybase1.MDPriorityNormal) 38 require.NoError(t, err) 39 return ctx, h, fs 40 } 41 42 func makeFS(t *testing.T, subdir string) ( 43 context.Context, *tlfhandle.Handle, *FS) { 44 return makeFSWithBranch(t, data.MasterBranch, subdir) 45 } 46 47 func makeFSWithJournal(t *testing.T, subdir string) ( 48 context.Context, *tlfhandle.Handle, *FS, func()) { 49 ctx := libcontext.BackgroundContextWithCancellationDelayer() 50 config := libkbfs.MakeTestConfigOrBustLoggedInWithMode( 51 t, 0, libkbfs.InitSingleOp, "user1") 52 53 tempdir, err := os.MkdirTemp(os.TempDir(), "journal_server") 54 require.NoError(t, err) 55 defer func() { 56 if err != nil { 57 os.RemoveAll(tempdir) 58 } 59 }() 60 err = config.EnableDiskLimiter(tempdir) 61 require.NoError(t, err) 62 err = config.EnableJournaling( 63 ctx, tempdir, libkbfs.TLFJournalSingleOpBackgroundWorkEnabled) 64 require.NoError(t, err) 65 shutdown := func() { 66 libkbfs.CheckConfigAndShutdown(ctx, t, config) 67 err := ioutil.RemoveAll(tempdir) 68 assert.NoError(t, err) 69 } 70 71 h, err := tlfhandle.ParseHandle( 72 ctx, config.KBPKI(), config.MDOps(), nil, "user1", tlf.Private) 73 require.NoError(t, err) 74 fs, err := NewFS( 75 ctx, config, h, data.MasterBranch, subdir, "", 76 keybase1.MDPriorityNormal) 77 require.NoError(t, err) 78 79 return ctx, h, fs, shutdown 80 } 81 82 func testCreateFile( 83 ctx context.Context, t *testing.T, fs *FS, file string, 84 parent libkbfs.Node) { 85 f, err := fs.Create(file) 86 require.NoError(t, err) 87 require.Equal(t, file, f.Name()) 88 89 children, err := fs.config.KBFSOps().GetDirChildren(ctx, parent) 90 require.NoError(t, err) 91 require.Contains(t, children, testPPS(path.Base(file))) 92 93 // Write to the file. 94 data := []byte{1} 95 n, err := f.Write(data) 96 require.NoError(t, err) 97 require.Equal(t, 1, n) 98 99 err = f.Close() 100 require.NoError(t, err) 101 102 // Re-open and read the file. 103 f, err = fs.Open(file) 104 require.NoError(t, err) 105 gotData := make([]byte, len(data)) 106 n, err = f.Read(gotData) 107 require.NoError(t, err) 108 require.Equal(t, len(data), n) 109 require.True(t, bytes.Equal(data, gotData)) 110 111 // Shouldn't be able to write to a read-only file. 112 _, err = f.Write(gotData) 113 require.NotNil(t, err) 114 115 err = f.Close() 116 require.NoError(t, err) 117 118 err = fs.SyncAll() 119 require.NoError(t, err) 120 } 121 122 func TestCreateFileInRoot(t *testing.T) { 123 ctx, h, fs := makeFS(t, "") 124 defer libkbfs.CheckConfigAndShutdown(ctx, t, fs.config) 125 126 rootNode, _, err := fs.config.KBFSOps().GetRootNode( 127 ctx, h, data.MasterBranch) 128 require.NoError(t, err) 129 130 testCreateFile(ctx, t, fs, "foo", rootNode) 131 testCreateFile(ctx, t, fs, "/bar", rootNode) 132 } 133 134 func testPPS(s string) data.PathPartString { 135 return data.NewPathPartString(s, nil) 136 } 137 138 func TestCreateFileInSubdir(t *testing.T) { 139 ctx, h, fs := makeFS(t, "") 140 defer libkbfs.CheckConfigAndShutdown(ctx, t, fs.config) 141 142 rootNode, _, err := fs.config.KBFSOps().GetRootNode( 143 ctx, h, data.MasterBranch) 144 require.NoError(t, err) 145 aNode, _, err := fs.config.KBFSOps().CreateDir(ctx, rootNode, testPPS("a")) 146 require.NoError(t, err) 147 bNode, _, err := fs.config.KBFSOps().CreateDir(ctx, aNode, testPPS("b")) 148 require.NoError(t, err) 149 150 testCreateFile(ctx, t, fs, "a/b/foo", bNode) 151 } 152 153 func TestCreateFileInMissingSubdir(t *testing.T) { 154 ctx, _, fs := makeFS(t, "") 155 defer libkbfs.CheckConfigAndShutdown(ctx, t, fs.config) 156 157 f, err := fs.Create("a/b/foo") 158 require.NoError(t, err) 159 require.Equal(t, "a/b/foo", f.Name()) 160 161 _, err = fs.Lstat("a") 162 require.NoError(t, err) 163 _, err = fs.Lstat("a/b") 164 require.NoError(t, err) 165 } 166 167 func TestAppendFile(t *testing.T) { 168 ctx, h, fs := makeFS(t, "") 169 defer libkbfs.CheckConfigAndShutdown(ctx, t, fs.config) 170 171 rootNode, _, err := fs.config.KBFSOps().GetRootNode( 172 ctx, h, data.MasterBranch) 173 require.NoError(t, err) 174 175 testCreateFile(ctx, t, fs, "foo", rootNode) 176 f, err := fs.OpenFile("foo", os.O_APPEND, 0600) 177 require.NoError(t, err) 178 179 // Append one byte to the file. 180 data := []byte{2} 181 n, err := f.Write(data) 182 require.NoError(t, err) 183 require.Equal(t, 1, n) 184 185 err = f.Close() 186 require.NoError(t, err) 187 188 // Re-open and read the file. 189 f, err = fs.Open("foo") 190 require.NoError(t, err) 191 gotData := make([]byte, 2) 192 n, err = f.Read(gotData) 193 require.NoError(t, err) 194 require.Equal(t, len(gotData), n) 195 196 err = f.Close() 197 require.NoError(t, err) 198 199 err = fs.SyncAll() 200 require.NoError(t, err) 201 } 202 203 func TestRecreateAndExcl(t *testing.T) { 204 ctx, h, fs := makeFS(t, "") 205 defer libkbfs.CheckConfigAndShutdown(ctx, t, fs.config) 206 207 rootNode, _, err := fs.config.KBFSOps().GetRootNode( 208 ctx, h, data.MasterBranch) 209 require.NoError(t, err) 210 211 testCreateFile(ctx, t, fs, "foo", rootNode) 212 213 // Re-create the same file. 214 f, err := fs.Create("foo") 215 require.NoError(t, err) 216 err = f.Close() 217 require.NoError(t, err) 218 219 // Try to create it with EXCL, and fail. 220 _, err = fs.OpenFile("foo", os.O_CREATE|os.O_EXCL, 0600) 221 require.NotNil(t, err) 222 223 // Creating a different file exclusively should work though. 224 f, err = fs.OpenFile("foo2", os.O_CREATE|os.O_EXCL, 0600) 225 require.NoError(t, err) 226 err = f.Close() 227 require.NoError(t, err) 228 err = fs.SyncAll() 229 require.NoError(t, err) 230 } 231 232 func TestStat(t *testing.T) { 233 ctx, h, fs := makeFS(t, "") 234 defer libkbfs.CheckConfigAndShutdown(ctx, t, fs.config) 235 236 clock := &clocktest.TestClock{} 237 clock.Set(time.Now()) 238 fs.config.SetClock(clock) 239 240 rootNode, _, err := fs.config.KBFSOps().GetRootNode( 241 ctx, h, data.MasterBranch) 242 require.NoError(t, err) 243 aNode, _, err := fs.config.KBFSOps().CreateDir(ctx, rootNode, testPPS("a")) 244 require.NoError(t, err) 245 testCreateFile(ctx, t, fs, "a/foo", aNode) 246 247 // Check the dir 248 fi, err := fs.Stat("a") 249 require.NoError(t, err) 250 checkDir := func(fi os.FileInfo, isWriter bool) { 251 require.Equal(t, "a", fi.Name()) 252 // Not sure exactly what the dir size should be. 253 require.True(t, fi.Size() > 0) 254 expectedMode := os.FileMode(0500) | os.ModeDir 255 if isWriter { 256 expectedMode |= 0200 257 } 258 require.Equal(t, expectedMode, fi.Mode()) 259 require.True(t, clock.Now().Equal(fi.ModTime())) 260 require.True(t, fi.IsDir()) 261 } 262 checkDir(fi, true) 263 264 // Check the file 265 fi, err = fs.Stat("a/foo") 266 require.NoError(t, err) 267 checkFile := func(fi os.FileInfo, isWriter bool) { 268 require.Equal(t, "foo", fi.Name()) 269 require.Equal(t, int64(1), fi.Size()) 270 expectedMode := os.FileMode(0400) 271 if isWriter { 272 expectedMode |= 0200 273 } 274 require.Equal(t, expectedMode, fi.Mode()) 275 require.True(t, clock.Now().Equal(fi.ModTime())) 276 require.False(t, fi.IsDir()) 277 } 278 checkFile(fi, true) 279 280 // Try a read-only file. 281 config2 := libkbfs.ConfigAsUser(fs.config.(*libkbfs.ConfigLocal), "user2") 282 defer libkbfs.CheckConfigAndShutdown(ctx, t, config2) 283 config2.SetClock(clock) 284 285 h2, err := tlfhandle.ParseHandle( 286 ctx, config2.KBPKI(), config2.MDOps(), nil, "user2#user1", tlf.Private) 287 require.NoError(t, err) 288 fs2U2, err := NewFS( 289 ctx, config2, h2, data.MasterBranch, "", "", 290 keybase1.MDPriorityNormal) 291 require.NoError(t, err) 292 rootNode2, _, err := fs2U2.config.KBFSOps().GetRootNode( 293 ctx, h2, data.MasterBranch) 294 require.NoError(t, err) 295 aNode2, _, err := fs2U2.config.KBFSOps().CreateDir( 296 ctx, rootNode2, testPPS("a")) 297 require.NoError(t, err) 298 testCreateFile(ctx, t, fs2U2, "a/foo", aNode2) 299 300 // Read as the reader. 301 fs2U1, err := NewFS( 302 ctx, fs.config, h2, data.MasterBranch, "", "", 303 keybase1.MDPriorityNormal) 304 require.NoError(t, err) 305 306 fi, err = fs2U1.Stat("a") 307 require.NoError(t, err) 308 checkDir(fi, false) 309 310 fi, err = fs2U1.Stat("a/foo") 311 require.NoError(t, err) 312 checkFile(fi, false) 313 } 314 315 func TestRename(t *testing.T) { 316 ctx, h, fs := makeFS(t, "") 317 defer libkbfs.CheckConfigAndShutdown(ctx, t, fs.config) 318 319 rootNode, _, err := fs.config.KBFSOps().GetRootNode( 320 ctx, h, data.MasterBranch) 321 require.NoError(t, err) 322 testCreateFile(ctx, t, fs, "foo", rootNode) 323 err = fs.MkdirAll("a/b", os.FileMode(0600)) 324 require.NoError(t, err) 325 326 f, err := fs.Open("foo") 327 require.NoError(t, err) 328 gotDataFoo := make([]byte, 1) 329 _, err = f.Read(gotDataFoo) 330 require.NoError(t, err) 331 err = f.Close() 332 require.NoError(t, err) 333 334 err = fs.Rename("foo", "a/b/bar") 335 require.NoError(t, err) 336 337 f, err = fs.Open("a/b/bar") 338 require.NoError(t, err) 339 gotDataBar := make([]byte, 1) 340 _, err = f.Read(gotDataBar) 341 require.NoError(t, err) 342 require.True(t, bytes.Equal(gotDataFoo, gotDataBar)) 343 err = f.Close() 344 require.NoError(t, err) 345 346 _, err = fs.Open("foo") 347 require.NotNil(t, err) 348 349 err = fs.SyncAll() 350 require.NoError(t, err) 351 } 352 353 func TestRemove(t *testing.T) { 354 ctx, h, fs := makeFS(t, "") 355 defer libkbfs.CheckConfigAndShutdown(ctx, t, fs.config) 356 357 rootNode, _, err := fs.config.KBFSOps().GetRootNode( 358 ctx, h, data.MasterBranch) 359 require.NoError(t, err) 360 testCreateFile(ctx, t, fs, "foo", rootNode) 361 err = fs.MkdirAll("a/b", os.FileMode(0600)) 362 require.NoError(t, err) 363 364 // Remove a file. 365 err = fs.Remove("foo") 366 require.NoError(t, err) 367 _, err = fs.Open("foo") 368 require.NotNil(t, err) 369 370 // Removing "a" should fail because it's not empty. 371 err = fs.Remove("a") 372 require.NotNil(t, err) 373 374 // Remove an empty dir and verify it's gone. 375 err = fs.Remove("a/b") 376 require.NoError(t, err) 377 _, err = fs.Lstat("a/b") 378 require.NotNil(t, err) 379 380 err = fs.SyncAll() 381 require.NoError(t, err) 382 } 383 384 func TestReadDir(t *testing.T) { 385 ctx, h, fs := makeFS(t, "") 386 defer libkbfs.CheckConfigAndShutdown(ctx, t, fs.config) 387 388 rootNode, _, err := fs.config.KBFSOps().GetRootNode( 389 ctx, h, data.MasterBranch) 390 require.NoError(t, err) 391 aNode, _, err := fs.config.KBFSOps().CreateDir(ctx, rootNode, testPPS("a")) 392 require.NoError(t, err) 393 testCreateFile(ctx, t, fs, "a/foo", aNode) 394 testCreateFile(ctx, t, fs, "a/bar", aNode) 395 expectedNames := map[string]bool{ 396 "foo": true, 397 "bar": true, 398 } 399 400 fis, err := fs.ReadDir("a") 401 require.NoError(t, err) 402 require.Len(t, fis, len(expectedNames)) 403 for _, fi := range fis { 404 require.True(t, expectedNames[fi.Name()]) 405 delete(expectedNames, fi.Name()) 406 } 407 require.Len(t, expectedNames, 0) 408 } 409 410 func TestMkdirAll(t *testing.T) { 411 ctx, _, fs := makeFS(t, "") 412 defer libkbfs.CheckConfigAndShutdown(ctx, t, fs.config) 413 414 err := fs.MkdirAll("a/b", os.FileMode(0600)) 415 require.NoError(t, err) 416 417 err = fs.MkdirAll("a/b/c/d", os.FileMode(0600)) 418 require.NoError(t, err) 419 420 f, err := fs.Create("a/b/c/d/foo") 421 require.NoError(t, err) 422 423 err = f.Close() 424 require.NoError(t, err) 425 } 426 427 func TestSymlink(t *testing.T) { 428 ctx, _, fs := makeFS(t, "") 429 defer libkbfs.CheckConfigAndShutdown(ctx, t, fs.config) 430 431 err := fs.MkdirAll("a/b/c", os.FileMode(0600)) 432 require.NoError(t, err) 433 434 foo, err := fs.Create("a/b/c/foo") 435 require.NoError(t, err) 436 437 data := []byte{1, 2, 3, 4} 438 n, err := foo.Write(data) 439 require.Equal(t, len(data), n) 440 require.NoError(t, err) 441 err = foo.Close() 442 require.NoError(t, err) 443 444 t.Log("Basic file symlink in same dir") 445 err = fs.Symlink("foo", "a/b/c/bar") 446 require.NoError(t, err) 447 448 _, err = fs.Open("a/b/c/bar") 449 require.NoError(t, err) 450 451 t.Log("Make sure Symlink creates parent directories as needed") 452 err = fs.Symlink("../../foo", "a/b/c/d/e/bar") 453 require.NoError(t, err) 454 455 bar, err := fs.Open("a/b/c/d/e/bar") 456 require.NoError(t, err) 457 458 checkData := func(f billy.File) { 459 gotData := make([]byte, len(data)) 460 n, err = f.Read(gotData) 461 require.Equal(t, len(data), n) 462 require.NoError(t, err) 463 require.True(t, bytes.Equal(data, gotData)) 464 } 465 checkData(bar) 466 467 err = bar.Close() 468 require.NoError(t, err) 469 470 t.Log("File symlink across to a lower dir") 471 err = fs.Symlink("b/c/foo", "a/bar") 472 require.NoError(t, err) 473 bar, err = fs.Open("a/bar") 474 require.NoError(t, err) 475 checkData(bar) 476 err = bar.Close() 477 require.NoError(t, err) 478 479 t.Log("File symlink across to a higher dir") 480 err = fs.MkdirAll("a/b/c/d/e/f", os.FileMode(0600)) 481 require.NoError(t, err) 482 err = fs.Symlink("../../../foo", "a/b/c/d/e/f/bar") 483 require.NoError(t, err) 484 bar, err = fs.Open("a/b/c/d/e/f/bar") 485 require.NoError(t, err) 486 checkData(bar) 487 err = bar.Close() 488 require.NoError(t, err) 489 490 t.Log("File across dir symlink") 491 err = fs.Symlink("b", "a/b2") 492 require.NoError(t, err) 493 bar, err = fs.Open("a/b2/c/bar") 494 require.NoError(t, err) 495 checkData(bar) 496 err = bar.Close() 497 require.NoError(t, err) 498 499 t.Log("Infinite symlink loop") 500 err = fs.Symlink("x", "y") 501 require.NoError(t, err) 502 err = fs.Symlink("y", "x") 503 require.NoError(t, err) 504 _, err = fs.Open("x") 505 require.NotNil(t, err) 506 507 t.Log("Symlink that tries to break chroot") 508 err = fs.Symlink("../../a", "a/breakout") 509 require.NoError(t, err) 510 _, err = fs.Open("a/breakout") 511 require.NotNil(t, err) 512 513 t.Log("Symlink to absolute path") 514 err = fs.Symlink("/etc/passwd", "absolute") 515 require.NoError(t, err) 516 _, err = fs.Open("absolute") 517 require.NotNil(t, err) 518 519 t.Log("Readlink") 520 link, err := fs.Readlink("a/bar") 521 require.NoError(t, err) 522 require.Equal(t, "b/c/foo", link) 523 524 fi, err := fs.Lstat("a/bar") 525 require.NoError(t, err) 526 require.Equal(t, "bar", fi.Name()) 527 528 err = fs.SyncAll() 529 require.NoError(t, err) 530 } 531 532 func TestChmod(t *testing.T) { 533 ctx, _, fs := makeFS(t, "") 534 defer libkbfs.CheckConfigAndShutdown(ctx, t, fs.config) 535 536 foo, err := fs.Create("foo") 537 require.NoError(t, err) 538 err = foo.Close() 539 require.NoError(t, err) 540 541 fi, err := fs.Stat("foo") 542 require.NoError(t, err) 543 require.True(t, fi.Mode()&0100 == 0) 544 545 err = fs.Chmod("foo", 0777) 546 require.NoError(t, err) 547 548 fi, err = fs.Stat("foo") 549 require.NoError(t, err) 550 require.True(t, fi.Mode()&0100 != 0) 551 } 552 553 func TestChtimes(t *testing.T) { 554 ctx, _, fs := makeFS(t, "") 555 defer libkbfs.CheckConfigAndShutdown(ctx, t, fs.config) 556 557 clock := &clocktest.TestClock{} 558 clock.Set(time.Now()) 559 fs.config.SetClock(clock) 560 561 foo, err := fs.Create("foo") 562 require.NoError(t, err) 563 err = foo.Close() 564 require.NoError(t, err) 565 566 fi, err := fs.Stat("foo") 567 require.NoError(t, err) 568 require.True(t, clock.Now().Equal(fi.ModTime())) 569 570 mtime := time.Date(2015, 1, 2, 3, 4, 5, 6, time.Local) 571 err = fs.Chtimes("foo", time.Now(), mtime) 572 require.NoError(t, err) 573 574 fi, err = fs.Stat("foo") 575 require.NoError(t, err) 576 require.Equal(t, mtime, fi.ModTime()) 577 } 578 579 func TestChroot(t *testing.T) { 580 ctx, _, fs := makeFS(t, "") 581 defer libkbfs.CheckConfigAndShutdown(ctx, t, fs.config) 582 583 require.Equal(t, "/keybase/private/user1", fs.Root()) 584 585 err := fs.MkdirAll("a/b/c", os.FileMode(0600)) 586 require.NoError(t, err) 587 588 foo, err := fs.Create("a/b/c/foo") 589 require.NoError(t, err) 590 591 data := []byte{1, 2, 3, 4} 592 n, err := foo.Write(data) 593 require.Equal(t, len(data), n) 594 require.NoError(t, err) 595 err = foo.Close() 596 require.NoError(t, err) 597 598 err = fs.SyncAll() 599 require.NoError(t, err) 600 601 t.Log("Make a new FS with a deeper root") 602 fs2, err := fs.Chroot("a/b") 603 require.NoError(t, err) 604 605 require.Equal(t, "/keybase/private/user1/a/b", fs2.Root()) 606 607 f, err := fs2.Open("c/foo") 608 require.NoError(t, err) 609 gotData := make([]byte, len(data)) 610 _, err = f.Read(gotData) 611 require.NoError(t, err) 612 require.True(t, bytes.Equal(data, gotData)) 613 err = f.Close() 614 require.NoError(t, err) 615 616 t.Log("Attempt a breakout") 617 _, err = fs.Chroot("../../../etc/passwd") 618 require.NotNil(t, err) 619 } 620 621 func TestFileLocking(t *testing.T) { 622 _, _, fs, shutdown := makeFSWithJournal(t, "") 623 defer shutdown() 624 625 // TODO: Write an integration tests where we also check to make sure lock 626 // namespace isn't empty. 627 f, err := fs.Create("a") 628 require.NoError(t, err) 629 630 err = f.Lock() 631 require.NoError(t, err) 632 633 err = f.Unlock() 634 require.NoError(t, err) 635 636 // The lock has been released, and we haven't made any changes. 637 // This should be a no-op. 638 err = f.Unlock() 639 require.NoError(t, err) 640 641 // Make some more change so next Unlock actually needs to write a MD. 642 _, err = fs.Create("c") 643 require.NoError(t, err) 644 645 // Now we do have some stuff that needs to flush, but we don't 646 // have the lock, so this should complete without flushing 647 // anything. 648 err = f.Unlock() 649 require.NoError(t, err) 650 651 // Make sure the journal didn't flush. 652 err = fs.SyncAll() 653 require.NoError(t, err) 654 jManager, err := libkbfs.GetJournalManager(fs.config) 655 require.NoError(t, err) 656 status, err := jManager.JournalStatus(fs.root.GetFolderBranch().Tlf) 657 require.NoError(t, err) 658 require.NotEqual(t, kbfsmd.RevisionUninitialized, status.RevisionStart) 659 660 // Now manually flush again so the journal is clean. 661 err = jManager.FinishSingleOp(fs.ctx, 662 fs.root.GetFolderBranch().Tlf, nil, keybase1.MDPriorityNormal) 663 require.NoError(t, err) 664 } 665 666 func TestFileLockingExpiration(t *testing.T) { 667 _, _, fs, shutdown := makeFSWithJournal(t, "") 668 defer shutdown() 669 670 clock := &clocktest.TestClock{} 671 clock.Set(time.Now()) 672 fs.config.SetClock(clock) 673 674 f, err := fs.Create("a") 675 require.NoError(t, err) 676 677 err = f.Lock() 678 require.NoError(t, err) 679 680 _, err = fs.Create("b") 681 require.NoError(t, err) 682 683 clock.Add(2 * time.Minute) 684 685 // Close/Unlock should fail because the clock expired. 686 err = f.Close() 687 require.Error(t, err) 688 689 // Shut down the MD server first to avoid state-checking, since 690 // the journal is in a weird state. 691 fs.config.MDServer().Shutdown() 692 } 693 694 func TestArchivedByRevision(t *testing.T) { 695 ctx, h, fs := makeFS(t, "") 696 defer libkbfs.CheckConfigAndShutdown(ctx, t, fs.config) 697 698 rootNode, _, err := fs.config.KBFSOps().GetRootNode( 699 ctx, h, data.MasterBranch) 700 require.NoError(t, err) 701 702 testCreateFile(ctx, t, fs, "foo", rootNode) 703 fis, err := fs.ReadDir("") 704 require.NoError(t, err) 705 require.Len(t, fis, 1) 706 707 _, _, fsArchived := makeFSWithBranch( 708 t, data.MakeRevBranchName(kbfsmd.Revision(1)), "") 709 defer libkbfs.CheckConfigAndShutdown(ctx, t, fsArchived.config) 710 fis, err = fsArchived.ReadDir("") 711 require.NoError(t, err) 712 require.Len(t, fis, 0) 713 } 714 715 func TestEmptyFS(t *testing.T) { 716 ctx := libcontext.BackgroundContextWithCancellationDelayer() 717 config := libkbfs.MakeTestConfigOrBust(t, "user1", "user2") 718 defer libkbfs.CheckConfigAndShutdown(ctx, t, config) 719 720 h, err := tlfhandle.ParseHandle( 721 ctx, config.KBPKI(), config.MDOps(), nil, "user1", tlf.Private) 722 require.NoError(t, err) 723 fs, err := NewFSIfExists( 724 ctx, config, h, data.MasterBranch, "", "", keybase1.MDPriorityNormal) 725 require.NoError(t, err) 726 727 require.True(t, fs.IsEmpty()) 728 729 fis, err := fs.ReadDir("") 730 require.NoError(t, err) 731 require.Len(t, fis, 0) 732 733 err = fs.MkdirAll("a", 0777) 734 require.Error(t, err) 735 }