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 all do one conflict-free operation while a user is unstaged. 6 7package test 8 9import "testing" 10 11// alice writes a multi-block file, and bob reads it 12func TestWriteMultiblockFile(t *testing.T) { 13 test(t, 14 blockSize(20), users("alice", "bob"), 15 as(alice, 16 write("a/b", ntimesString(15, "0123456789")), 17 ), 18 as(bob, 19 read("a/b", ntimesString(15, "0123456789")), 20 ), 21 ) 22} 23 24func TestSwitchToMultiblockFile(t *testing.T) { 25 test(t, 26 blockSize(20), users("alice", "bob"), 27 as(alice, 28 // Fill up the first block (a desired encrypted block size 29 // of 20 ends up with a plaintext size of 12). 30 write("a/b", ntimesString(3, "0123")), 31 // Then append to the end of the file to force a split. 32 pwriteBS("a/b", []byte(ntimesString(3, "0123")), 12), 33 ), 34 as(bob, 35 read("a/b", ntimesString(6, "0123")), 36 ), 37 ) 38} 39 40// alice writes a file, and bob overwrites it with a multi-block file 41func TestOverwriteMultiblockFile(t *testing.T) { 42 test(t, 43 blockSize(20), users("alice", "bob"), 44 as(alice, 45 write("a/b", "hello"), 46 ), 47 as(bob, 48 write("a/b", ntimesString(15, "0123456789")), 49 ), 50 as(alice, 51 read("a/b", ntimesString(15, "0123456789")), 52 ), 53 as(bob, 54 read("a/b", ntimesString(15, "0123456789")), 55 ), 56 ) 57} 58 59// bob removes a multiblock file written by alice (checks that state 60// is cleaned up) 61func TestRmMultiblockFile(t *testing.T) { 62 test(t, 63 blockSize(20), users("alice", "bob"), 64 as(alice, 65 write("a/b", ntimesString(15, "0123456789")), 66 ), 67 as(bob, 68 read("a/b", ntimesString(15, "0123456789")), 69 rm("a/b"), 70 ), 71 as(alice, 72 lsdir("a/", m{}), 73 ), 74 ) 75} 76 77// bob renames something over a multiblock file written by alice 78// (checks that state is cleaned up) 79func TestRenameOverMultiblockFile(t *testing.T) { 80 test(t, 81 blockSize(20), users("alice", "bob"), 82 as(alice, 83 write("a/b", ntimesString(15, "0123456789")), 84 write("a/c", "hello"), 85 ), 86 as(bob, 87 read("a/b", ntimesString(15, "0123456789")), 88 read("a/c", "hello"), 89 rename("a/c", "a/b"), 90 ), 91 as(alice, 92 read("a/b", "hello"), 93 lsdir("a/", m{"b": "FILE"}), 94 ), 95 ) 96} 97 98// bob writes a second copy of a multiblock file written by alice 99// (tests dedupping, but hard to verify that precisely here). 100func TestCopyMultiblockFile(t *testing.T) { 101 test(t, 102 blockSize(20), users("alice", "bob"), 103 as(alice, 104 write("a/b", ntimesString(15, "0123456789")), 105 ), 106 as(bob, 107 read("a/b", ntimesString(15, "0123456789")), 108 write("a/c", ntimesString(15, "0123456789")), 109 ), 110 as(alice, 111 read("a/b", ntimesString(15, "0123456789")), 112 read("a/c", ntimesString(15, "0123456789")), 113 rm("a/b"), 114 ), 115 as(bob, 116 read("a/c", ntimesString(15, "0123456789")), 117 ), 118 ) 119} 120 121// Test that we can make a big file, delete it, then make it 122// again. Regression for KBFS-700. 123func TestMakeDeleteAndMakeMultiBlockFile(t *testing.T) { 124 test(t, 125 blockSize(20), users("alice", "bob"), 126 as(alice, 127 write("a/b", ntimesString(15, "0123456789")), 128 ), 129 as(bob, 130 read("a/b", ntimesString(15, "0123456789")), 131 rm("a/b"), 132 write("a/b2", ntimesString(15, "0123456789")), 133 ), 134 as(alice, 135 read("a/b2", ntimesString(15, "0123456789")), 136 ), 137 ) 138} 139 140// When block changes are unembedded, make sure other users can read 141// and apply them. 142func TestReadUnembeddedBlockChanges(t *testing.T) { 143 test(t, 144 blockChangeSize(5), users("alice", "bob"), 145 as(alice, 146 write("a/b", "hello"), 147 ), 148 as(bob, 149 read("a/b", "hello"), 150 write("a/c", "hello2"), 151 write("a/d", "hello3"), 152 write("a/e", "hello4"), 153 write("a/f", "hello5"), 154 ), 155 as(alice, 156 lsdir("a", m{"b": "FILE", "c": "FILE", "d": "FILE", "e": "FILE", "f": "FILE"}), 157 read("a/b", "hello"), 158 read("a/c", "hello2"), 159 read("a/d", "hello3"), 160 read("a/e", "hello4"), 161 read("a/f", "hello5"), 162 ), 163 ) 164} 165 166// alice writes a multi-block directory root dir, and bob reads it. 167func TestWriteMultiblockRootDir(t *testing.T) { 168 test(t, 169 blockSize(20), users("alice", "bob"), 170 as(alice, 171 mkfile("b", "b"), 172 mkfile("c", "c"), 173 mkfile("d", "d"), 174 mkfile("e", "e"), 175 mkfile("f", "f"), 176 ), 177 as(bob, 178 lsdir("", m{ 179 "b": "FILE", 180 "c": "FILE", 181 "d": "FILE", 182 "e": "FILE", 183 "f": "FILE", 184 }), 185 read("b", "b"), 186 read("c", "c"), 187 read("d", "d"), 188 read("e", "e"), 189 read("f", "f"), 190 ), 191 ) 192} 193 194// alice writes a multi-block directory in separate batches, and bob reads it. 195func TestWriteMultiblockDirBatches(t *testing.T) { 196 test(t, 197 blockSize(20), users("alice", "bob"), 198 as(alice, 199 mkfile("a/b", "b"), 200 mkfile("a/c", "c"), 201 mkfile("a/d", "d"), 202 mkfile("a/e", "e"), 203 mkfile("a/f", "f"), 204 ), 205 as(bob, 206 lsdir("a/", m{ 207 "b": "FILE", 208 "c": "FILE", 209 "d": "FILE", 210 "e": "FILE", 211 "f": "FILE", 212 }), 213 read("a/b", "b"), 214 read("a/c", "c"), 215 read("a/d", "d"), 216 read("a/e", "e"), 217 read("a/f", "f"), 218 ), 219 ) 220} 221 222// alice writes a multi-block directory in one batch, and bob reads it. 223func TestWriteMultiblockDirAtOnce(t *testing.T) { 224 test(t, 225 blockSize(20), users("alice", "bob"), 226 as(alice, 227 pwriteBSSync("a/b", []byte("b"), 0, false), 228 pwriteBSSync("a/c", []byte("c"), 0, false), 229 pwriteBSSync("a/d", []byte("d"), 0, false), 230 pwriteBSSync("a/e", []byte("e"), 0, false), 231 pwriteBSSync("a/f", []byte("f"), 0, false), 232 ), 233 as(bob, 234 lsdir("a/", m{ 235 "b": "FILE", 236 "c": "FILE", 237 "d": "FILE", 238 "e": "FILE", 239 "f": "FILE", 240 }), 241 read("a/b", "b"), 242 read("a/c", "c"), 243 read("a/d", "d"), 244 read("a/e", "e"), 245 read("a/f", "f"), 246 ), 247 ) 248} 249 250// alice writes a multi-block directory and removes one entry from it. 251func TestRemoveOneFromMultiblockDir(t *testing.T) { 252 test(t, 253 blockSize(20), users("alice", "bob"), 254 as(alice, 255 mkfile("a/b", "b"), 256 mkfile("a/c", "c"), 257 mkfile("a/d", "d"), 258 mkfile("a/e", "e"), 259 mkfile("a/f", "f"), 260 ), 261 as(alice, 262 rm("a/e"), 263 ), 264 as(bob, 265 lsdir("a/", m{ 266 "b": "FILE", 267 "c": "FILE", 268 "d": "FILE", 269 "f": "FILE", 270 }), 271 read("a/b", "b"), 272 read("a/c", "c"), 273 read("a/d", "d"), 274 read("a/f", "f"), 275 ), 276 ) 277} 278 279// alice writes a multi-level, multi-block directory structure. 280func TestRemoveMultilevelMultiblockDir(t *testing.T) { 281 test(t, 282 blockSize(20), users("alice", "bob"), 283 as(alice, 284 mkfile("a/b", "b"), 285 mkfile("a/c", "c"), 286 mkdir("a/d"), 287 mkfile("a/d/e", "e"), 288 mkfile("a/d/f", "f"), 289 mkdir("a/g"), 290 mkfile("a/g/h", "h"), 291 mkfile("a/g/i", "i"), 292 ), 293 as(bob, 294 lsdir("a/", m{ 295 "b": "FILE", 296 "c": "FILE", 297 "d": "DIR", 298 "g": "DIR", 299 }), 300 lsdir("a/d", m{ 301 "e": "FILE", 302 "f": "FILE", 303 }), 304 lsdir("a/g", m{ 305 "h": "FILE", 306 "i": "FILE", 307 }), 308 read("a/b", "b"), 309 read("a/c", "c"), 310 read("a/d/e", "e"), 311 read("a/d/f", "f"), 312 read("a/g/h", "h"), 313 read("a/g/i", "i"), 314 ), 315 as(alice, 316 rm("a/g/i"), 317 rm("a/g/h"), 318 rmdir("a/g"), 319 rm("a/d/f"), 320 rm("a/d/e"), 321 rmdir("a/d"), 322 rm("a/c"), 323 rm("a/b"), 324 rmdir("a"), 325 ), 326 as(bob, 327 lsdir("", m{}), 328 ), 329 ) 330} 331 332// alice renames within a multi-block directory. 333func TestRenameWithinMultiblockDir(t *testing.T) { 334 test(t, 335 blockSize(20), users("alice", "bob"), 336 as(alice, 337 mkfile("a/b", "b"), 338 mkfile("a/c", "c"), 339 mkfile("a/d", "d"), 340 mkfile("a/e", "e"), 341 mkfile("a/f", "f"), 342 ), 343 as(alice, 344 rename("a/f", "a/g"), 345 ), 346 as(bob, 347 lsdir("a/", m{ 348 "b": "FILE", 349 "c": "FILE", 350 "d": "FILE", 351 "e": "FILE", 352 "g": "FILE", 353 }), 354 read("a/b", "b"), 355 read("a/c", "c"), 356 read("a/d", "d"), 357 read("a/e", "e"), 358 read("a/g", "f"), 359 ), 360 ) 361} 362 363// alice renames, creating a multi-block directory. 364func TestRenameCreatesMultiblockDir(t *testing.T) { 365 test(t, 366 blockSize(20), users("alice", "bob"), 367 as(alice, 368 mkfile("a/b", "b"), 369 mkfile("a/c", "c"), 370 mkfile("d/e", "e"), 371 ), 372 as(alice, 373 rename("a/c", "d/c"), 374 ), 375 as(bob, 376 lsdir("a/", m{"b": "FILE"}), 377 lsdir("d/", m{"c": "FILE", "e": "FILE"}), 378 read("a/b", "b"), 379 read("d/c", "c"), 380 read("d/e", "e"), 381 ), 382 ) 383} 384