github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/test/qr_test.go (about) 1 // Copyright 2016 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 // These tests exercise quota reclamation. 6 7 package test 8 9 import ( 10 "fmt" 11 "testing" 12 "time" 13 ) 14 15 // Check that simple quota reclamation works 16 func TestQRSimple(t *testing.T) { 17 test(t, 18 users("alice"), 19 as(alice, 20 addTime(1*time.Minute), 21 mkfile("a", "hello"), 22 rm("a"), 23 addTime(2*time.Minute), 24 forceQuotaReclamation(), 25 ), 26 ) 27 } 28 29 // Check that quota reclamation works, eventually, after enough iterations. 30 func TestQRLargePointerSet(t *testing.T) { 31 var busyWork []fileOp 32 iters := 100 33 for i := 0; i < iters; i++ { 34 name := fmt.Sprintf("a%d", i) 35 busyWork = append(busyWork, mkfile(name, "hello"), rm(name)) 36 } 37 // 5 unreferenced pointers per iteration -- 3 updates to the root 38 // block, one empty file written to, and one non-empty file 39 // deleted. 40 ptrsPerIter := 5 41 var qrOps []optionOp 42 // Each reclamation needs a sync after it (e.g., a new "as" 43 // clause) to ensure it completes before the next force 44 // reclamation. 45 for i := 0; i < ptrsPerIter*iters/100; i++ { 46 qrOps = append(qrOps, as(alice, 47 addTime(2*time.Minute), 48 forceQuotaReclamation(), 49 )) 50 } 51 totalOps := []optionOp{users("alice"), as(alice, busyWork...)} 52 totalOps = append(totalOps, qrOps...) 53 test(t, totalOps...) 54 } 55 56 // Test that quota reclamation handles conflict resolution correctly. 57 func TestQRAfterCR(t *testing.T) { 58 test(t, 59 users("alice", "bob"), 60 as(alice, 61 mkfile("a/b", "hello"), 62 ), 63 as(bob, 64 disableUpdates(), 65 ), 66 as(alice, 67 write("a/c", "world"), 68 ), 69 as(bob, noSync(), 70 rm("a/b"), 71 reenableUpdates(), 72 ), 73 as(alice, 74 addTime(2*time.Minute), 75 forceQuotaReclamation(), 76 ), 77 ) 78 } 79 80 // Check that quota reclamation after two syncOps CR leaves the TLF in 81 // a readable state. Regression test for KBFS-1562. 82 func TestQRAfterCRWithTwoSyncOps(t *testing.T) { 83 test(t, 84 users("alice", "bob"), 85 as(alice, 86 mkfile("a/b", "hello"), 87 ), 88 as(bob, 89 disableUpdates(), 90 ), 91 as(alice, 92 write("a/c", "hello2"), 93 ), 94 as(bob, noSync(), 95 write("a/b", "hello world"), 96 write("a/b", "hello world etc"), 97 reenableUpdates(), 98 ), 99 as(alice, 100 addTime(2*time.Minute), 101 forceQuotaReclamation(), 102 read("a/b", "hello world etc"), 103 read("a/c", "hello2"), 104 ), 105 ) 106 } 107 108 // Check that quota reclamation works on multi-block files 109 func TestQRWithMultiBlockFiles(t *testing.T) { 110 test(t, 111 blockSize(20), users("alice"), 112 as(alice, 113 addTime(1*time.Minute), 114 mkfile("a", ntimesString(15, "0123456789")), 115 rm("a"), 116 addTime(2*time.Minute), 117 forceQuotaReclamation(), 118 ), 119 ) 120 } 121 122 // Test that conflict resolution works gracefully after quota 123 // reclamation deletes a modified+deleted directory from the merged 124 // branch. Regression for KBFS-1202. 125 func TestCRAfterRmdirAndQR(t *testing.T) { 126 test(t, 127 users("alice", "bob"), 128 as(alice, 129 mkdir("a/b"), 130 mkfile("a/b/c", "world"), 131 ), 132 as(bob, 133 disableUpdates(), 134 ), 135 as(alice, 136 mkfile("a/b/d", "world2"), 137 rm("a/b/c"), 138 rm("a/b/d"), 139 rmdir("a/b"), 140 ), 141 as(bob, noSync(), 142 setmtime("a/b/c", time.Now().Add(1*time.Minute)), 143 rm("a/b/c"), 144 rmdir("a/b"), 145 ), 146 as(alice, 147 addTime(2*time.Minute), 148 // Force rmd.data.Dir.MTime to something recent. TODO: remove me. 149 mkfile("c", "test"), 150 forceQuotaReclamation(), 151 ), 152 as(bob, noSync(), 153 reenableUpdates(), 154 lsdir("a/", m{}), 155 ), 156 as(alice, 157 lsdir("a/", m{}), 158 ), 159 ) 160 }