def test_rename(self): oldname = self.newname() newname = self.newname() inode = self.server.mkdir(ROOT_INODE, oldname, self.dir_mode(), some_ctx) inode_p_new = self.server.mkdir(ROOT_INODE, self.newname(), self.dir_mode(), some_ctx) inode_p_new_before = self.server.getattr(inode_p_new.st_ino, some_ctx) inode_p_old_before = self.server.getattr(ROOT_INODE, some_ctx) safe_sleep(CLOCK_GRANULARITY) self.server.rename(ROOT_INODE, oldname, inode_p_new.st_ino, newname, some_ctx) inode_p_old_after = self.server.getattr(ROOT_INODE, some_ctx) inode_p_new_after = self.server.getattr(inode_p_new.st_ino, some_ctx) self.assertFalse(self.db.has_val('SELECT inode FROM contents JOIN names ON names.id = name_id ' 'WHERE name=? AND parent_inode = ?', (oldname, ROOT_INODE))) id_ = self.db.get_val('SELECT inode FROM contents JOIN names ON names.id == name_id ' 'WHERE name=? AND parent_inode = ?', (newname, inode_p_new.st_ino)) self.assertEqual(inode.st_ino, id_) assert inode_p_new_before.st_mtime_ns < inode_p_new_after.st_mtime_ns assert inode_p_new_before.st_ctime_ns < inode_p_new_after.st_ctime_ns assert inode_p_old_before.st_mtime_ns < inode_p_old_after.st_mtime_ns assert inode_p_old_before.st_ctime_ns < inode_p_old_after.st_ctime_ns self.server.forget([(inode.st_ino, 1), (inode_p_new.st_ino, 1)]) self.fsck()
def test_create(ctx): fctx = Ctx() mode = dir_mode() name = newname(ctx) inode_p_old = ctx.server.getattr(ROOT_INODE, some_ctx) safe_sleep(CLOCK_GRANULARITY) ctx.server._create(ROOT_INODE, name, mode, fctx) id_ = ctx.db.get_val('SELECT inode FROM contents JOIN names ON name_id = names.id ' 'WHERE name=? AND parent_inode = ?', (name, ROOT_INODE)) inode = ctx.server.getattr(id_, some_ctx) assert inode.st_mode == mode assert inode.st_uid == fctx.uid assert inode.st_gid == fctx.gid assert inode.st_nlink == 1 assert inode.st_size == 0 inode_p_new = ctx.server.getattr(ROOT_INODE, some_ctx) assert inode_p_new.st_mtime_ns > inode_p_old.st_mtime_ns assert inode_p_new.st_ctime_ns > inode_p_old.st_ctime_ns ctx.server.forget([(id_, 1)]) fsck(ctx)
def test_link(self): name = self.newname() inode_p_new = self.server.mkdir(ROOT_INODE, self.newname(), self.dir_mode(), Ctx()) inode_p_new_before = self.server.getattr(inode_p_new.id).copy() (fh, inode) = self.server.create(ROOT_INODE, self.newname(), self.file_mode(), os.O_RDWR, Ctx()) self.server.release(fh) safe_sleep(CLOCK_GRANULARITY) inode_before = self.server.getattr(inode.id).copy() self.server.link(inode.id, inode_p_new.id, name) inode_after = self.server.lookup(inode_p_new.id, name) inode_p_new_after = self.server.getattr(inode_p_new.id) id_ = self.db.get_val('SELECT inode FROM contents JOIN names ON names.id = name_id ' 'WHERE name=? AND parent_inode = ?', (name, inode_p_new.id)) self.assertEqual(inode_before.id, id_) self.assertEqual(inode_after.refcount, 2) self.assertGreater(inode_after.ctime, inode_before.ctime) self.assertLess(inode_p_new_before.mtime, inode_p_new_after.mtime) self.assertLess(inode_p_new_before.ctime, inode_p_new_after.ctime) self.server.forget([(inode.id, 1), (inode_p_new.id, 1), (inode_after.id, 1)]) self.fsck()
def test_create(self): ctx = Ctx() mode = self.dir_mode() name = self.newname() inode_p_old = self.server.getattr(ROOT_INODE).copy() safe_sleep(CLOCK_GRANULARITY) self.server._create(ROOT_INODE, name, mode, ctx) id_ = self.db.get_val('SELECT inode FROM contents JOIN names ON name_id = names.id ' 'WHERE name=? AND parent_inode = ?', (name, ROOT_INODE)) inode = self.server.getattr(id_) self.assertEqual(inode.mode, mode) self.assertEqual(inode.uid, ctx.uid) self.assertEqual(inode.gid, ctx.gid) self.assertEqual(inode.refcount, 1) self.assertEqual(inode.size, 0) inode_p_new = self.server.getattr(ROOT_INODE) self.assertGreater(inode_p_new.mtime, inode_p_old.mtime) self.assertGreater(inode_p_new.ctime, inode_p_old.ctime) self.server.forget([(id_, 1)]) self.fsck()
def test_setattr(self): (fh, inode) = self.server.create(ROOT_INODE, self.newname(), 0o641, os.O_RDWR, Ctx()) self.server.release(fh) inode_old = self.server.getattr(inode.id).copy() attr = llfuse.EntryAttributes() attr.st_mode = self.file_mode() attr.st_uid = randint(0, 2 ** 32) attr.st_gid = None attr.st_atime = randint(0, 2 ** 32) / 10 ** 6 attr.st_mtime = randint(0, 2 ** 32) / 10 ** 6 safe_sleep(CLOCK_GRANULARITY) self.server.setattr(inode.id, attr) inode_new = self.server.getattr(inode.id) self.assertGreater(inode_new.ctime, inode_old.ctime) for key in attr.__slots__: if key in ('st_mode', 'st_uid', 'st_atime', 'st_mtime'): self.assertEqual(getattr(attr, key), getattr(inode_new, key), '%s mismatch' % key) elif key != 'st_ctime': self.assertEqual(getattr(inode_old, key), getattr(inode_new, key), '%s mismatch' % key) self.server.forget([(inode.id, 1)]) self.fsck()
def test_replace_dir(self): oldname = self.newname() newname = self.newname() inode = self.server.mkdir(ROOT_INODE, oldname, self.dir_mode(), Ctx()) inode_p_new = self.server.mkdir(ROOT_INODE, self.newname(), self.dir_mode(), Ctx()) inode_p_new_before = self.server.getattr(inode_p_new.id).copy() inode_p_old_before = self.server.getattr(ROOT_INODE).copy() inode2 = self.server.mkdir(inode_p_new.id, newname, self.dir_mode(), Ctx()) self.server.forget([(inode2.id, 1)]) safe_sleep(CLOCK_GRANULARITY) self.server.rename(ROOT_INODE, oldname, inode_p_new.id, newname) inode_p_old_after = self.server.getattr(ROOT_INODE) inode_p_new_after = self.server.getattr(inode_p_new.id) self.assertFalse(self.db.has_val('SELECT inode FROM contents JOIN names ON names.id = name_id ' 'WHERE name=? AND parent_inode = ?', (oldname, ROOT_INODE))) id_ = self.db.get_val('SELECT inode FROM contents JOIN names ON names.id = name_id ' 'WHERE name=? AND parent_inode = ?', (newname, inode_p_new.id)) self.assertEqual(inode.id, id_) self.assertLess(inode_p_new_before.mtime, inode_p_new_after.mtime) self.assertLess(inode_p_new_before.ctime, inode_p_new_after.ctime) self.assertLess(inode_p_old_before.mtime, inode_p_old_after.mtime) self.assertLess(inode_p_old_before.ctime, inode_p_old_after.ctime) self.server.forget([(inode.id, 1), (inode_p_new.id, 1)]) self.assertFalse(self.db.has_val('SELECT id FROM inodes WHERE id=?', (inode2.id,))) self.fsck()
def test_expire(self): inode = self.inode # Define the 4 most recently accessed ones most_recent = [7, 11, 10, 8] for i in most_recent: safe_sleep(0.2) with self.cache.get(inode, i) as fh: fh.write(('%d' % i).encode()) # And some others for i in range(20): if i in most_recent: continue with self.cache.get(inode, i) as fh: fh.write(('%d' % i).encode()) # Flush the 2 most recently accessed ones commit(self.cache, inode, most_recent[-2]) commit(self.cache, inode, most_recent[-3]) # We want to expire 4 entries, 2 of which are already flushed self.cache.cache.max_entries = 16 self.cache.backend_pool = TestBackendPool(self.backend_pool, no_write=2) self.cache.expire() self.cache.backend_pool.verify() self.assertEqual(len(self.cache.cache), 16) for i in range(20): if i in most_recent: self.assertTrue((inode, i) not in self.cache.cache) else: self.assertTrue((inode, i) in self.cache.cache)
def test_setattr_one(ctx): (fh, inode) = ctx.server.create(ROOT_INODE, newname(ctx), file_mode(), os.O_RDWR, some_ctx) ctx.server.release(fh) inode_old = ctx.server.getattr(inode.st_ino, some_ctx) attr = ctx.server.getattr(inode.st_ino, some_ctx) # this is a fresh instance attr.st_mode = file_mode() attr.st_uid = randint(0, 2 ** 32) attr.st_gid = randint(0, 2 ** 32) # should be ignored attr.st_atime_ns = randint(0, 2 ** 50) attr.st_mtime_ns = randint(0, 2 ** 50) safe_sleep(CLOCK_GRANULARITY) sf = SetattrFields(update_mode=True, update_uid=True, update_atime=True, update_mtime=True) ctx.server.setattr(inode.st_ino, attr, sf, None, some_ctx) inode_new = ctx.server.getattr(inode.st_ino, some_ctx) for name in ('st_mode', 'st_uid', 'st_atime_ns', 'st_mtime_ns'): assert getattr(attr, name) == getattr(inode_new, name) for name in ('st_gid', 'st_size', 'st_nlink', 'st_rdev', 'st_blocks', 'st_blksize'): assert getattr(inode_old, name) == getattr(inode_new, name) assert inode_old.st_ctime_ns < inode_new.st_ctime_ns ctx.server.forget([(inode.st_ino, 1)]) fsck(ctx)
def test_replace_dir(ctx): oldname = newname(ctx) newname_ = newname(ctx) inode = ctx.server.mkdir(ROOT_INODE, oldname, dir_mode(), some_ctx) inode_p_new = ctx.server.mkdir(ROOT_INODE, newname(ctx), dir_mode(), some_ctx) inode_p_new_before = ctx.server.getattr(inode_p_new.st_ino, some_ctx) inode_p_old_before = ctx.server.getattr(ROOT_INODE, some_ctx) inode2 = ctx.server.mkdir(inode_p_new.st_ino, newname_, dir_mode(), some_ctx) ctx.server.forget([(inode2.st_ino, 1)]) safe_sleep(CLOCK_GRANULARITY) ctx.server.rename(ROOT_INODE, oldname, inode_p_new.st_ino, newname_, some_ctx) inode_p_old_after = ctx.server.getattr(ROOT_INODE, some_ctx) inode_p_new_after = ctx.server.getattr(inode_p_new.st_ino, some_ctx) assert not ctx.db.has_val('SELECT inode FROM contents JOIN names ON names.id = name_id ' 'WHERE name=? AND parent_inode = ?', (oldname, ROOT_INODE)) id_ = ctx.db.get_val('SELECT inode FROM contents JOIN names ON names.id = name_id ' 'WHERE name=? AND parent_inode = ?', (newname_, inode_p_new.st_ino)) assert inode.st_ino == id_ assert inode_p_new_before.st_mtime_ns < inode_p_new_after.st_mtime_ns assert inode_p_new_before.st_ctime_ns < inode_p_new_after.st_ctime_ns assert inode_p_old_before.st_mtime_ns < inode_p_old_after.st_mtime_ns assert inode_p_old_before.st_ctime_ns < inode_p_old_after.st_ctime_ns ctx.server.forget([(inode.st_ino, 1), (inode_p_new.st_ino, 1)]) assert not ctx.db.has_val('SELECT id FROM inodes WHERE id=?', (inode2.st_ino,)) fsck(ctx)
def test_link(ctx): name = newname(ctx) inode_p_new = ctx.server.mkdir(ROOT_INODE, newname(ctx), dir_mode(), some_ctx) inode_p_new_before = ctx.server.getattr(inode_p_new.st_ino, some_ctx) (fh, inode) = ctx.server.create(ROOT_INODE, newname(ctx), file_mode(), os.O_RDWR, some_ctx) ctx.server.release(fh) safe_sleep(CLOCK_GRANULARITY) inode_before = ctx.server.getattr(inode.st_ino, some_ctx) ctx.server.link(inode.st_ino, inode_p_new.st_ino, name, some_ctx) inode_after = ctx.server.lookup(inode_p_new.st_ino, name, some_ctx) inode_p_new_after = ctx.server.getattr(inode_p_new.st_ino, some_ctx) id_ = ctx.db.get_val('SELECT inode FROM contents JOIN names ON names.id = name_id ' 'WHERE name=? AND parent_inode = ?', (name, inode_p_new.st_ino)) assert inode_before.st_ino == id_ assert inode_after.st_nlink == 2 assert inode_after.st_ctime_ns > inode_before.st_ctime_ns assert inode_p_new_before.st_mtime_ns < inode_p_new_after.st_mtime_ns assert inode_p_new_before.st_ctime_ns < inode_p_new_after.st_ctime_ns ctx.server.forget([(inode.st_ino, 1), (inode_p_new.st_ino, 1), (inode_after.st_ino, 1)]) fsck(ctx)
def test_setattr_two(self): (fh, inode_old) = self.server.create(ROOT_INODE, self.newname(), self.file_mode(), os.O_RDWR, some_ctx) attr = self.server.getattr(inode_old.st_ino, some_ctx) attr.st_mode = self.file_mode() attr.st_uid = randint(0, 2 ** 32) attr.st_gid = randint(0, 2 ** 32) attr.st_mtime_ns = randint(0, 2 ** 50) attr.st_ctime_ns = 5e9 safe_sleep(CLOCK_GRANULARITY) sf = SetattrFields(update_gid=True, update_mtime=True) self.server.setattr(inode_old.st_ino, attr, sf, None, some_ctx) inode_new = self.server.getattr(inode_old.st_ino, some_ctx) for name in ('st_gid', 'st_mtime_ns'): assert getattr(attr, name) == getattr(inode_new, name) for name in ('st_uid', 'st_size', 'st_nlink', 'st_rdev', 'st_blocks', 'st_blksize', 'st_mode', 'st_atime_ns'): assert getattr(inode_old, name) == getattr(inode_new, name) assert inode_old.st_ctime_ns < inode_new.st_ctime_ns self.server.release(fh) self.server.forget([(inode_old.st_ino, 1)]) self.fsck()
def test_rmdir(ctx): name = newname(ctx) inode = ctx.server.mkdir(ROOT_INODE, name, dir_mode(), some_ctx) ctx.server.forget([(inode.st_ino, 1)]) inode_p_before = ctx.server.getattr(ROOT_INODE, some_ctx) safe_sleep(CLOCK_GRANULARITY) ctx.server.rmdir(ROOT_INODE, name, some_ctx) inode_p_after = ctx.server.getattr(ROOT_INODE, some_ctx) assert inode_p_before.st_mtime_ns < inode_p_after.st_mtime_ns assert inode_p_before.st_ctime_ns < inode_p_after.st_ctime_ns assert not ctx.db.has_val('SELECT inode FROM contents JOIN names ON names.id = name_id ' 'WHERE name=? AND parent_inode = ?', (name, ROOT_INODE)) assert not ctx.db.has_val('SELECT id FROM inodes WHERE id=?', (inode.st_ino,)) fsck(ctx)
def test_rmdir(self): name = self.newname() inode = self.server.mkdir(ROOT_INODE, name, self.dir_mode(), Ctx()) self.server.forget([(inode.id, 1)]) inode_p_before = self.server.getattr(ROOT_INODE).copy() safe_sleep(CLOCK_GRANULARITY) self.server.rmdir(ROOT_INODE, name) inode_p_after = self.server.getattr(ROOT_INODE) self.assertLess(inode_p_before.mtime, inode_p_after.mtime) self.assertLess(inode_p_before.ctime, inode_p_after.ctime) self.assertFalse(self.db.has_val('SELECT inode FROM contents JOIN names ON names.id = name_id ' 'WHERE name=? AND parent_inode = ?', (name, ROOT_INODE))) self.assertFalse(self.db.has_val('SELECT id FROM inodes WHERE id=?', (inode.id,))) self.fsck()
def test_read(ctx): len_ = ctx.max_obj_size data = random_data(len_) off = ctx.max_obj_size // 2 (fh, inode) = ctx.server.create(ROOT_INODE, newname(ctx), file_mode(), os.O_RDWR, some_ctx) ctx.server.write(fh, off, data) inode_before = ctx.server.getattr(inode.st_ino, some_ctx) safe_sleep(CLOCK_GRANULARITY) assert ctx.server.read(fh, off, len_) == data inode_after = ctx.server.getattr(inode.st_ino, some_ctx) assert inode_after.st_atime_ns > inode_before.st_atime_ns assert ctx.server.read(fh, 0, len_) == b"\0" * off + data[:off] assert ctx.server.read(fh, ctx.max_obj_size, len_) == data[off:] ctx.server.release(fh) ctx.server.forget([(inode.st_ino, 1)]) fsck(ctx)
def test_read(self): len_ = self.max_obj_size data = self.random_data(len_) off = self.max_obj_size // 2 (fh, inode) = self.server.create(ROOT_INODE, self.newname(), self.file_mode(), os.O_RDWR, Ctx()) self.server.write(fh, off, data) inode_before = self.server.getattr(inode.id).copy() safe_sleep(CLOCK_GRANULARITY) self.assertTrue(self.server.read(fh, off, len_) == data) inode_after = self.server.getattr(inode.id) self.assertGreater(inode_after.atime, inode_before.atime) self.assertTrue(self.server.read(fh, 0, len_) == b"\0" * off + data[:off]) self.assertTrue(self.server.read(fh, self.max_obj_size, len_) == data[off:]) self.server.release(fh) self.server.forget([(inode.id, 1)]) self.fsck()
def test_symlink(self): target = self.newname() name = self.newname() inode_p_before = self.server.getattr(ROOT_INODE).copy() safe_sleep(CLOCK_GRANULARITY) inode = self.server.symlink(ROOT_INODE, name, target, Ctx()) inode_p_after = self.server.getattr(ROOT_INODE) self.assertEqual(target, self.server.readlink(inode.id)) id_ = self.db.get_val('SELECT inode FROM contents JOIN names ON names.id = name_id ' 'WHERE name=? AND parent_inode = ?', (name, ROOT_INODE)) self.assertEqual(inode.id, id_) self.assertLess(inode_p_before.mtime, inode_p_after.mtime) self.assertLess(inode_p_before.ctime, inode_p_after.ctime) self.server.forget([(inode.id, 1)]) self.fsck()
def test_symlink(ctx): target = newname(ctx) name = newname(ctx) inode_p_before = ctx.server.getattr(ROOT_INODE, some_ctx) safe_sleep(CLOCK_GRANULARITY) inode = ctx.server.symlink(ROOT_INODE, name, target, some_ctx) inode_p_after = ctx.server.getattr(ROOT_INODE, some_ctx) assert target, ctx.server.readlink(inode.st_ino == some_ctx) id_ = ctx.db.get_val('SELECT inode FROM contents JOIN names ON names.id = name_id ' 'WHERE name=? AND parent_inode = ?', (name, ROOT_INODE)) assert inode.st_ino == id_ assert inode_p_before.st_mtime_ns < inode_p_after.st_mtime_ns assert inode_p_before.st_ctime_ns < inode_p_after.st_ctime_ns ctx.server.forget([(inode.st_ino, 1)]) fsck(ctx)
def test_replace_file(self): oldname = self.newname() newname = self.newname() (fh, inode) = self.server.create(ROOT_INODE, oldname, self.file_mode(), os.O_RDWR, Ctx()) self.server.write(fh, 0, b'some data to deal with') self.server.release(fh) self.server.setxattr(inode.id, b'test_xattr', b'42*8') inode_p_new = self.server.mkdir(ROOT_INODE, self.newname(), self.dir_mode(), Ctx()) inode_p_new_before = self.server.getattr(inode_p_new.id).copy() inode_p_old_before = self.server.getattr(ROOT_INODE).copy() (fh, inode2) = self.server.create(inode_p_new.id, newname, self.file_mode(), os.O_RDWR, Ctx()) self.server.write(fh, 0, b'even more data to deal with') self.server.release(fh) self.server.setxattr(inode2.id, b'test_xattr', b'42*8') self.server.forget([(inode2.id, 1)]) safe_sleep(CLOCK_GRANULARITY) self.server.rename(ROOT_INODE, oldname, inode_p_new.id, newname) inode_p_old_after = self.server.getattr(ROOT_INODE) inode_p_new_after = self.server.getattr(inode_p_new.id) self.assertFalse(self.db.has_val('SELECT inode FROM contents JOIN names ON names.id = name_id ' 'WHERE name=? AND parent_inode = ?', (oldname, ROOT_INODE))) id_ = self.db.get_val('SELECT inode FROM contents JOIN names ON names.id = name_id ' 'WHERE name=? AND parent_inode = ?', (newname, inode_p_new.id)) self.assertEqual(inode.id, id_) self.assertLess(inode_p_new_before.mtime, inode_p_new_after.mtime) self.assertLess(inode_p_new_before.ctime, inode_p_new_after.ctime) self.assertLess(inode_p_old_before.mtime, inode_p_old_after.mtime) self.assertLess(inode_p_old_before.ctime, inode_p_old_after.ctime) self.assertFalse(self.db.has_val('SELECT id FROM inodes WHERE id=?', (inode2.id,))) self.server.forget([(inode.id, 1), (inode_p_new.id, 1)]) self.fsck()
def test_replace_file(ctx): oldname = newname(ctx) newname_ = newname(ctx) (fh, inode) = ctx.server.create(ROOT_INODE, oldname, file_mode(), os.O_RDWR, some_ctx) ctx.server.write(fh, 0, b'some data to deal with') ctx.server.release(fh) ctx.server.setxattr(inode.st_ino, b'test_xattr', b'42*8', some_ctx) inode_p_new = ctx.server.mkdir(ROOT_INODE, newname(ctx), dir_mode(), some_ctx) inode_p_new_before = ctx.server.getattr(inode_p_new.st_ino, some_ctx) inode_p_old_before = ctx.server.getattr(ROOT_INODE, some_ctx) (fh, inode2) = ctx.server.create(inode_p_new.st_ino, newname_, file_mode(), os.O_RDWR, some_ctx) ctx.server.write(fh, 0, b'even more data to deal with') ctx.server.release(fh) ctx.server.setxattr(inode2.st_ino, b'test_xattr', b'42*8', some_ctx) ctx.server.forget([(inode2.st_ino, 1)]) safe_sleep(CLOCK_GRANULARITY) ctx.server.rename(ROOT_INODE, oldname, inode_p_new.st_ino, newname_, some_ctx) inode_p_old_after = ctx.server.getattr(ROOT_INODE, some_ctx) inode_p_new_after = ctx.server.getattr(inode_p_new.st_ino, some_ctx) assert not ctx.db.has_val('SELECT inode FROM contents JOIN names ON names.id = name_id ' 'WHERE name=? AND parent_inode = ?', (oldname, ROOT_INODE)) id_ = ctx.db.get_val('SELECT inode FROM contents JOIN names ON names.id = name_id ' 'WHERE name=? AND parent_inode = ?', (newname_, inode_p_new.st_ino)) assert inode.st_ino == id_ assert inode_p_new_before.st_mtime_ns < inode_p_new_after.st_mtime_ns assert inode_p_new_before.st_ctime_ns < inode_p_new_after.st_ctime_ns assert inode_p_old_before.st_mtime_ns < inode_p_old_after.st_mtime_ns assert inode_p_old_before.st_ctime_ns < inode_p_old_after.st_ctime_ns assert not ctx.db.has_val('SELECT id FROM inodes WHERE id=?', (inode2.st_ino,)) ctx.server.forget([(inode.st_ino, 1), (inode_p_new.st_ino, 1)]) fsck(ctx)
async def test_replace_dir(ctx): oldname = newname(ctx) newname_ = newname(ctx) inode = await ctx.server.mkdir(ROOT_INODE, oldname, dir_mode(), some_ctx) inode_p_new = await ctx.server.mkdir(ROOT_INODE, newname(ctx), dir_mode(), some_ctx) inode_p_new_before = await ctx.server.getattr(inode_p_new.st_ino, some_ctx) inode_p_old_before = await ctx.server.getattr(ROOT_INODE, some_ctx) inode2 = await ctx.server.mkdir(inode_p_new.st_ino, newname_, dir_mode(), some_ctx) await ctx.server.forget([(inode2.st_ino, 1)]) safe_sleep(CLOCK_GRANULARITY) await ctx.server.rename(ROOT_INODE, oldname, inode_p_new.st_ino, newname_, 0, some_ctx) inode_p_old_after = await ctx.server.getattr(ROOT_INODE, some_ctx) inode_p_new_after = await ctx.server.getattr(inode_p_new.st_ino, some_ctx) assert not ctx.db.has_val( 'SELECT inode FROM contents JOIN names ON names.id = name_id ' 'WHERE name=? AND parent_inode = ?', (oldname, ROOT_INODE)) id_ = ctx.db.get_val( 'SELECT inode FROM contents JOIN names ON names.id = name_id ' 'WHERE name=? AND parent_inode = ?', (newname_, inode_p_new.st_ino)) assert inode.st_ino == id_ assert inode_p_new_before.st_mtime_ns < inode_p_new_after.st_mtime_ns assert inode_p_new_before.st_ctime_ns < inode_p_new_after.st_ctime_ns assert inode_p_old_before.st_mtime_ns < inode_p_old_after.st_mtime_ns assert inode_p_old_before.st_ctime_ns < inode_p_old_after.st_ctime_ns await ctx.server.forget([(inode.st_ino, 1), (inode_p_new.st_ino, 1)]) assert not ctx.db.has_val('SELECT id FROM inodes WHERE id=?', (inode2.st_ino, )) await fsck(ctx)
def test_write(self): len_ = self.max_obj_size data = self.random_data(len_) off = self.max_obj_size // 2 (fh, inode) = self.server.create(ROOT_INODE, self.newname(), self.file_mode(), os.O_RDWR, some_ctx) inode_before = self.server.getattr(inode.st_ino, some_ctx) safe_sleep(CLOCK_GRANULARITY) self.server.write(fh, off, data) inode_after = self.server.getattr(inode.st_ino, some_ctx) self.assertGreater(inode_after.st_mtime_ns, inode_before.st_mtime_ns) self.assertGreater(inode_after.st_ctime_ns, inode_before.st_ctime_ns) self.assertEqual(inode_after.st_size, off + len_) self.server.write(fh, 0, data) inode_after = self.server.getattr(inode.st_ino, some_ctx) self.assertEqual(inode_after.st_size, off + len_) self.server.release(fh) self.server.forget([(inode.st_ino, 1)]) self.fsck()
def test_write(ctx): len_ = ctx.max_obj_size data = random_data(len_) off = ctx.max_obj_size // 2 (fh, inode) = ctx.server.create(ROOT_INODE, newname(ctx), file_mode(), os.O_RDWR, some_ctx) inode_before = ctx.server.getattr(inode.st_ino, some_ctx) safe_sleep(CLOCK_GRANULARITY) ctx.server.write(fh, off, data) inode_after = ctx.server.getattr(inode.st_ino, some_ctx) assert inode_after.st_mtime_ns > inode_before.st_mtime_ns assert inode_after.st_ctime_ns > inode_before.st_ctime_ns assert inode_after.st_size == off + len_ ctx.server.write(fh, 0, data) inode_after = ctx.server.getattr(inode.st_ino, some_ctx) assert inode_after.st_size == off + len_ ctx.server.release(fh) ctx.server.forget([(inode.st_ino, 1)]) fsck(ctx)
def test_rename(self): oldname = self.newname() newname = self.newname() inode = self.server.mkdir(ROOT_INODE, oldname, self.dir_mode(), some_ctx) inode_p_new = self.server.mkdir(ROOT_INODE, self.newname(), self.dir_mode(), some_ctx) inode_p_new_before = self.server.getattr(inode_p_new.st_ino, some_ctx) inode_p_old_before = self.server.getattr(ROOT_INODE, some_ctx) safe_sleep(CLOCK_GRANULARITY) self.server.rename(ROOT_INODE, oldname, inode_p_new.st_ino, newname, some_ctx) inode_p_old_after = self.server.getattr(ROOT_INODE, some_ctx) inode_p_new_after = self.server.getattr(inode_p_new.st_ino, some_ctx) self.assertFalse( self.db.has_val( 'SELECT inode FROM contents JOIN names ON names.id = name_id ' 'WHERE name=? AND parent_inode = ?', (oldname, ROOT_INODE))) id_ = self.db.get_val( 'SELECT inode FROM contents JOIN names ON names.id == name_id ' 'WHERE name=? AND parent_inode = ?', (newname, inode_p_new.st_ino)) self.assertEqual(inode.st_ino, id_) self.assertLess(inode_p_new_before.st_mtime_ns, inode_p_new_after.st_mtime_ns) self.assertLess(inode_p_new_before.st_ctime_ns, inode_p_new_after.st_ctime_ns) self.assertLess(inode_p_old_before.st_mtime_ns, inode_p_old_after.st_mtime_ns) self.assertLess(inode_p_old_before.st_ctime_ns, inode_p_old_after.st_ctime_ns) self.server.forget([(inode.st_ino, 1), (inode_p_new.st_ino, 1)]) self.fsck()
async def test_write(ctx): len_ = ctx.max_obj_size data = random_data(len_) off = ctx.max_obj_size // 2 (fh, inode) = await ctx.server.create(ROOT_INODE, newname(ctx), file_mode(), os.O_RDWR, some_ctx) inode_before = await ctx.server.getattr(inode.st_ino, some_ctx) safe_sleep(CLOCK_GRANULARITY) await ctx.server.write(fh, off, data) inode_after = await ctx.server.getattr(inode.st_ino, some_ctx) assert inode_after.st_mtime_ns > inode_before.st_mtime_ns assert inode_after.st_ctime_ns > inode_before.st_ctime_ns assert inode_after.st_size == off + len_ await ctx.server.write(fh, 0, data) inode_after = await ctx.server.getattr(inode.st_ino, some_ctx) assert inode_after.st_size == off + len_ await ctx.server.release(fh) await ctx.server.forget([(inode.st_ino, 1)]) await fsck(ctx)
def test_expire_race(self): # Create element inode = self.inode blockno = 1 data1 = self.random_data(int(0.4 * self.max_obj_size)) with self.cache.get(inode, blockno) as fh: fh.seek(0) fh.write(data1) self.cache.upload(fh) # Make sure entry will be expired self.cache.cache.max_entries = 0 def e_w_l(): with llfuse.lock: self.cache.expire() # Lock it self.cache._lock_entry(inode, blockno, release_global=True) try: # Start expiration, will block on lock t1 = AsyncFn(e_w_l) t1.start() # Start second expiration, will block t2 = AsyncFn(e_w_l) t2.start() # Release lock with llfuse.lock_released: safe_sleep(0.1) self.cache._unlock_entry(inode, blockno) t1.join_and_raise() t2.join_and_raise() assert len(self.cache.cache) == 0 finally: self.cache._unlock_entry(inode, blockno, release_global=True, noerror=True)
def test_write(self): len_ = self.max_obj_size data = self.random_data(len_) off = self.max_obj_size // 2 (fh, inode) = self.server.create(ROOT_INODE, self.newname(), self.file_mode(), os.O_RDWR, Ctx()) inode_before = self.server.getattr(inode.id).copy() safe_sleep(CLOCK_GRANULARITY) self.server.write(fh, off, data) inode_after = self.server.getattr(inode.id) self.assertGreater(inode_after.mtime, inode_before.mtime) self.assertGreater(inode_after.ctime, inode_before.ctime) self.assertEqual(inode_after.size, off + len_) self.server.write(fh, 0, data) inode_after = self.server.getattr(inode.id) self.assertEqual(inode_after.size, off + len_) self.server.release(fh) self.server.forget([(inode.id, 1)]) self.fsck()
def test_parallel_expire(self): # Create elements inode = self.inode for i in range(5): data1 = self.random_data(int(0.4 * self.max_obj_size)) with self.cache.get(inode, i) as fh: fh.write(data1) # We want to expire just one element, but have # several threads running expire() simultaneously self.cache.cache.max_entries = 4 def e_w_l(): with llfuse.lock: self.cache.expire() # Lock first element so that we have time to start threads self.cache._lock_entry(inode, 0, release_global=True) try: # Start expiration, will block on lock t1 = AsyncFn(e_w_l) t1.start() # Start second expiration, will block t2 = AsyncFn(e_w_l) t2.start() # Release lock with llfuse.lock_released: safe_sleep(0.1) self.cache._unlock_entry(inode, 0) t1.join_and_raise() t2.join_and_raise() assert len(self.cache.cache) == 4 finally: self.cache._unlock_entry(inode, 0, release_global=True, noerror=True)
def test_setattr(self): (fh, inode) = self.server.create(ROOT_INODE, self.newname(), 0o641, os.O_RDWR, Ctx()) self.server.release(fh) inode_old = self.server.getattr(inode.id).copy() attr = llfuse.EntryAttributes() attr.st_mode = self.file_mode() attr.st_uid = randint(0, 2**32) attr.st_gid = randint(0, 2**32) attr.st_atime = randint(0, 2**32) / 10**6 attr.st_mtime = randint(0, 2**32) / 10**6 safe_sleep(CLOCK_GRANULARITY) self.server.setattr(inode.id, attr) inode_new = self.server.getattr(inode.id) self.assertGreater(inode_new.ctime, inode_old.ctime) for key in attr.__slots__: if getattr(attr, key) is not None: self.assertEqual(getattr(attr, key), getattr(inode_new, key)) self.server.forget([(inode.id, 1)]) self.fsck()
def test_unlink(ctx): name = newname(ctx) (fh, inode) = ctx.server.create(ROOT_INODE, name, file_mode(), os.O_RDWR, some_ctx) ctx.server.write(fh, 0, b'some data to deal with') ctx.server.release(fh) # Add extended attributes ctx.server.setxattr(inode.st_ino, b'test_xattr', b'42*8', some_ctx) ctx.server.forget([(inode.st_ino, 1)]) inode_p_before = ctx.server.getattr(ROOT_INODE, some_ctx) safe_sleep(CLOCK_GRANULARITY) ctx.server.unlink(ROOT_INODE, name, some_ctx) inode_p_after = ctx.server.getattr(ROOT_INODE, some_ctx) assert inode_p_before.st_mtime_ns < inode_p_after.st_mtime_ns assert inode_p_before.st_ctime_ns < inode_p_after.st_ctime_ns assert not ctx.db.has_val('SELECT inode FROM contents JOIN names ON names.id = name_id ' 'WHERE name=? AND parent_inode = ?', (name, ROOT_INODE)) assert not ctx.db.has_val('SELECT id FROM inodes WHERE id=?', (inode.st_ino,)) fsck(ctx)
def test_unlink(self): name = self.newname() (fh, inode) = self.server.create(ROOT_INODE, name, self.file_mode(), os.O_RDWR, Ctx()) self.server.write(fh, 0, b'some data to deal with') self.server.release(fh) # Add extended attributes self.server.setxattr(inode.id, b'test_xattr', b'42*8') self.server.forget([(inode.id, 1)]) inode_p_before = self.server.getattr(ROOT_INODE).copy() safe_sleep(CLOCK_GRANULARITY) self.server.unlink(ROOT_INODE, name) inode_p_after = self.server.getattr(ROOT_INODE) self.assertLess(inode_p_before.mtime, inode_p_after.mtime) self.assertLess(inode_p_before.ctime, inode_p_after.ctime) self.assertFalse(self.db.has_val('SELECT inode FROM contents JOIN names ON names.id = name_id ' 'WHERE name=? AND parent_inode = ?', (name, ROOT_INODE))) self.assertFalse(self.db.has_val('SELECT id FROM inodes WHERE id=?', (inode.id,))) self.fsck()
def test_unlink(self): name = self.newname() (fh, inode) = self.server.create(ROOT_INODE, name, self.file_mode(), os.O_RDWR, some_ctx) self.server.write(fh, 0, b'some data to deal with') self.server.release(fh) # Add extended attributes self.server.setxattr(inode.st_ino, b'test_xattr', b'42*8', some_ctx) self.server.forget([(inode.st_ino, 1)]) inode_p_before = self.server.getattr(ROOT_INODE, some_ctx) safe_sleep(CLOCK_GRANULARITY) self.server.unlink(ROOT_INODE, name, some_ctx) inode_p_after = self.server.getattr(ROOT_INODE, some_ctx) self.assertLess(inode_p_before.st_mtime_ns, inode_p_after.st_mtime_ns) self.assertLess(inode_p_before.st_ctime_ns, inode_p_after.st_ctime_ns) self.assertFalse(self.db.has_val('SELECT inode FROM contents JOIN names ON names.id = name_id ' 'WHERE name=? AND parent_inode = ?', (name, ROOT_INODE))) self.assertFalse(self.db.has_val('SELECT id FROM inodes WHERE id=?', (inode.st_ino,))) self.fsck()