def test_symlink_roundtrip(self): meta = PathMeta(id='N:helloworld:123', size=10, checksum=b'1;o2j\x9912\xffo3ij\x01123,asdf.') path = self.test_path path._cache = SymlinkCache(path, meta=meta) path.cache.meta = meta new_meta = path.cache.meta path.unlink() msg = '\n'.join([f'{k!r} {v!r} {getattr(new_meta, k)!r}' for k, v in meta.items()]) assert meta == new_meta, msg
def mk_fldr_meta(fldr_path, ftype='collection', id=None): _meta = fldr_path.meta kwargs = {**_meta} kwargs['id'] = id if id is not None else f'N:{ftype}:' + fldr_path.as_posix() meta = PathMeta(**kwargs) # NOTE st_mtime -> modified time of the file contents (data) # NOTE st_ctime -> changed time of the file status (metadata) # linux does not have a unified way to bet st_btime aka st_crtime which is birth time or created time return meta.as_xattrs(prefix='bf') return {'bf.id': id if id is not None else f'N:{ftype}:' + fldr_path.as_posix(), 'bf.created': meta.created.isoformat().replace('.', ',') if meta.created is not None else None, 'bf.updated': meta.updated.isoformat().replace('.', ',')}
def setUp(self): self.dir = self._test_class(self.sandbox, 'some-dir', meta=PathMeta(id='0')) if self.dir.exists(): self.dir.rmtree(onerror=onerror) elif self.dir.is_symlink(): self.dir.unlink() self.dir.mkdir() self.file = self._test_class(self.sandbox, 'some-file', meta=PathMeta(id='1')) if self.file.exists() or self.file.is_symlink(): self.file.unlink() self.file.touch()
def _test_symlink_roundtrip_weird(self): path = LocalPathTest(test_base, 'testpath') # FIXME random needed ... meta = PathMeta(id='N:helloworld:123', size=10, checksum=b'1;o2j\x9912\xffo3ij\x01123,asdf.') pure_symlink = PurePosixPath(path.name) / meta.as_symlink() path.symlink_to(pure_symlink) try: cache = SymlinkCache(path) new_meta = cache.meta msg = '\n'.join([f'{k!r} {v!r} {getattr(new_meta, k)!r}' for k, v in meta.items()]) assert meta == new_meta, msg finally: path.unlink()
def mk_fldr_meta(fldr_path, ftype='collection', id=None): altid = f'N:{ftype}:' + fldr_path.as_posix() _id = id if id is not None else altid _id = _id.replace( '/', DIVISION_SLASH ) # ARGH there must be a way to ensure file system safe ids :/ _meta = fldr_path.meta kwargs = {**_meta} kwargs['id'] = _id meta = PathMeta(**kwargs) # NOTE st_mtime -> modified time of the file contents (data) # NOTE st_ctime -> changed time of the file status (metadata) # linux does not have a unified way to bet st_btime aka st_crtime which is birth time or created time return meta.as_xattrs(prefix='bf')
def test_metastore_roundtrip(self): pm = self.path.meta ms = pm.as_metastore(self.prefix) # FIXME actually write these to disk as well? new_pm = PathMeta.from_metastore(ms, self.prefix) assert new_pm == pm, '\n'.join([str((getattr(pm, field), getattr(new_pm, field))) for field in tuple()]) # TODO
def mk_fldr_meta(fldr_path, ftype='collection', id=None): #import uuid #altid = f'N:{ftype}:{uuid.uuid4()}' # sigh # XXX don't do this, because we need to be able to validate without that #altid = f'N:{ftype}:' + fldr_path.as_posix() # use L: to mark local instead of N: as the platform does altid = f'L:{ftype}:' + fldr_path.as_posix( ) # use L: to mark local instead of N: as the platform does _id = id if id is not None else altid _id = _id.replace( '/', DIVISION_SLASH ) # ARGH there must be a way to ensure file system safe ids :/ XXX evil _meta = fldr_path.meta kwargs = {**_meta} kwargs['id'] = _id meta = PathMeta(**kwargs) # NOTE st_mtime -> modified time of the file contents (data) # NOTE st_ctime -> changed time of the file status (metadata) # linux does not have a unified way to bet st_btime aka st_crtime which is birth time or created time return meta.as_xattrs(prefix='bf')
def test_xattrs_roundtrip(self): # TODO __kwargs ... pm = self.path.meta xattrs = pm.as_xattrs(self.prefix) log.debug(xattrs) # FIXME actually write these to disk as well? new_pm = PathMeta.from_xattrs(xattrs, self.prefix) msg = '\n'.join([f'{k!r} {v!r} {getattr(new_pm, k)!r}' for k, v in pm.items()]) assert new_pm == pm, msg
def meta(self): return PathMeta(size=self.size, created=self.created, updated=self.updated, checksum=self.checksum, etag=self.etag, chunksize=self.chunksize, id=self.id, file_id=self.file_id, old_id=None, gid=None, # needed to determine local writability user_id=self.owner_id, mode=None, errors=self.errors)
def test_parts_roundtrip(self): pmas = _PathMetaAsSymlink() lpm = self.path.meta bpm = PathMeta(id='N:helloworld:123', size=10, checksum=b'1;o2j\x9912\xffo3ij\x01123,asdf.') bads = [] for pm in (lpm, bpm): symlink = pm.as_symlink() log.debug(symlink) new_pm = pmas.from_parts(symlink.parts) #corrected_new_pm = PurePosixPath() if new_pm != pm: bads += ['\n'.join([str((getattr(pm, field), getattr(new_pm, field))) for field in ('id',) + _PathMetaAsSymlink.order if not (getattr(pm, field) is getattr(new_pm, field) is None)]), f'{pm.__reduce__()}\n{new_pm.__reduce__()}'] assert not bads, '\n===========\n'.join(bads)
def test_sparse(self): test_file = self._test_class(self.dir, 'more-test', meta=PathMeta(id='3')) test_file.unlink() # FIXME fix bad Cache constructor behavior already test_file.touch() assert not self.file.is_sparse() assert not self.dir.is_sparse() assert not test_file.is_sparse() self.dir._mark_sparse() assert not self.file.is_sparse() assert self.dir.is_sparse() assert test_file.is_sparse() self.dir._clear_sparse() assert not self.file.is_sparse() assert not self.dir.is_sparse() assert not test_file.is_sparse()
def test_2_create_dir(self): test_path.mkdir() wat = CachePathTest(test_path, meta=PathMeta(id='0')) log.debug(wat) assert wat.meta
def metaAtTime(self, time): # we are cheating in order to do this return PathMeta(id=self._cache_class._remote_class.invAtTime(self, time))
def meta(self): return PathMeta(id=self.id)
p = self.as_path() return f'{self.__class__.__name__} <{self.id!r} {p!r}>' # set up cache hierarchy LocalPathTest._cache_class = CachePathTest CachePathTest._local_class = LocalPathTest CachePathTest._remote_class = RemotePathTest RemotePathTest._cache_class = CachePathTest # set up testing anchor (must come after the hierarchy) CachePathTest.anchor = test_path # note: the this creates a symlink which the rests of the tests expect if test_path.exists(): test_path.rmtree(onerror=onerror) CachePathTest.anchor = CachePathTest(test_path, meta=PathMeta(id='0')) test_path.unlink() class TestPathHelper: @classmethod def setUpClass(cls): if cls.test_base.exists(): shutil.rmtree(cls.test_base, onerror=onerror) cls.test_base.mkdir() @classmethod def tearDownClass(cls): shutil.rmtree(cls.test_base, onerror=onerror)
def test_update(self): old = PathMeta(id='0', size=10, file_id=1) new = PathMeta(id='0', size=10, checksum='asdf') changed, merged = PrimaryCache._update_meta(old, new) test_value = PathMeta(id='0', size=10, file_id=1, checksum='asdf') assert merged == test_value, test_value.as_pretty_diff(merged)
def test(self): zt = LocalPathTest(test_path) / 'zero-test' cache = CachePathTest(zt, meta=PathMeta(id='0')) assert cache.meta
def _test_getattr_size_hr(self): pm = PathMeta(size=1000000000000000) woo = getattr(pm, 'size.hr')
def test_1_create(self): wat = CachePathTest(test_path, meta=PathMeta(id='0')) log.debug(wat) assert wat.meta
def test_neg__neg__(self): pm = PathMeta(id='lol') assert pm
def test___neg__(self): pm = PathMeta() assert not pm, set(pm.__dict__.values())