From 92bfafa0778af90c9cdcbf90620cba3c7676beb0 Mon Sep 17 00:00:00 2001 From: John-Mark Gurney Date: Tue, 13 Sep 2022 22:49:59 -0700 Subject: [PATCH] make tests pass on FreeBSD.. implement hostuuid for it... Hard code stat results so that the tests pass on a different checkout w/ different mtimes.. --- ui/medashare/cli.py | 27 +++++++++++- ui/medashare/hostid.py | 93 ++++++++++++++++++++++++++++++------------ 2 files changed, 94 insertions(+), 26 deletions(-) diff --git a/ui/medashare/cli.py b/ui/medashare/cli.py index 3cf8801..38ff52a 100644 --- a/ui/medashare/cli.py +++ b/ui/medashare/cli.py @@ -1,5 +1,6 @@ #!/usr/bin/env python +import stat import sys import logging @@ -1686,7 +1687,31 @@ class _TestCases(unittest.TestCase): self.assertEqual(ObjectStore.makehash('cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e', strict=False), 'sha512:cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e') self.assertEqual(ObjectStore.makehash('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', strict=False), 'sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855') - def test_enumeratedir(self): + @staticmethod + def statmock(fname): + fname = pathlib.Path(fname) + fnameparts = fname.parts + subdiridx = fnameparts.index('subdir') + + _stats = { + # repr on os.stat_result doesn't work + # (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime) + + 'test.txt': os.stat_result((stat.S_IROTH|stat.S_IRGRP|stat.S_IWUSR|stat.S_IRUSR|stat.S_IFREG, 10, 100, 1, 100, 100, 15, 1654166365, 1558388856.000000, 1663133775)), + 'newfile.txt': os.stat_result((stat.S_IROTH|stat.S_IRGRP|stat.S_IWUSR|stat.S_IRUSR|stat.S_IFREG, 10, 100, 1, 100, 100, 19, 1659652579, 1658982768.041291, 1663133775)), + 'sample.data.sqlite3': os.stat_result((stat.S_IROTH|stat.S_IRGRP|stat.S_IWUSR|stat.S_IRUSR|stat.S_IFREG, 10, 100, 1, 100, 100, 57344, 1663133777, 1663133777.529757, 1663133777)), + 't': os.stat_result((stat.S_IFDIR, 0, 0, 0, 0, 0, 0, 0, 0, 0)), + 'z.jpg': os.stat_result((stat.S_IROTH|stat.S_IRGRP|stat.S_IWUSR|stat.S_IRUSR|stat.S_IFREG, 10, 100, 1, 100, 100, 332, 1661553878, 1661551130.361235, 1663134325)), + + } + + subpath = '/'.join(fnameparts[subdiridx + 1:]) + return _stats[subpath] + + @mock.patch('os.stat') + def test_enumeratedir(self, statmock): + statmock.side_effect = self.statmock + files = enumeratedir(self.tempdir, self.created_by_ref) ftest = [ x for x in files if x.filename == 'test.txt' ][0] fname = 'test.txt' diff --git a/ui/medashare/hostid.py b/ui/medashare/hostid.py index 3806dd8..8130a73 100644 --- a/ui/medashare/hostid.py +++ b/ui/medashare/hostid.py @@ -1,38 +1,81 @@ +import errno import uuid +import sys -from ctypes import CDLL, Structure, POINTER -from ctypes import c_uint8, c_int, c_long, c_int64 +from ctypes import CDLL, Structure, POINTER, pointer +from ctypes import c_char, c_uint8, c_int, c_long, c_int64, c_char_p +from ctypes import c_void_p, c_size_t -uuid_t = c_uint8 * 16 +__all__ = [ 'hostuuid'] _clib = CDLL(None) -__all__ = [ 'hostuuid'] +if False: + # XXX doesn't work on FreeBSD + errnov = c_int.in_dll(_clib, 'errno') + + def raiseerrno(): + v = errnov.value + raise OSError(v, errno.errorcode[v]) + +if sys.platform == 'darwin': + uuid_t = c_uint8 * 16 + + class timespec(Structure): + _fields_ = [ + ('tv_sec', c_int64), + ('tv_nsec', c_long), + ] + pass + + timespec_p = POINTER(timespec) + + def hostuuid(): + ts = timespec() + hid = uuid_t() + + r = _clib.gethostuuid(hid, ts) + + if r: + raise OSErrorException() + + return uuid.UUID(bytes=bytes(hid)) -class timespec(Structure): - _fields_ = [ - ('tv_sec', c_int64), - ('tv_nsec', c_long), - ] - pass + for r, f, a in ( + (c_int, 'gethostuuid', (uuid_t, timespec_p)), + ): + fun = getattr(_clib, f) + setattr(fun, 'restype', r) + setattr(fun, 'argtypes', a) + locals()[f] = fun -timespec_p = POINTER(timespec) +elif sys.platform.startswith('freebsd'): + def hostuuid(): + uuidstr = (c_char * 37)() + uuidstrpointer = pointer(uuidstr) + oldsize = c_size_t(len(uuidstr)) -def hostuuid(): - ts = timespec() - hid = uuid_t() + r = _clib.sysctlbyname('kern.hostuuid'.encode('us-ascii'), + uuidstrpointer, pointer(oldsize), None, 0) - r = _clib.gethostuuid(hid, ts) + if r: + raise OSError() - if r: - raise OSErrorException() + v = uuid.UUID(uuidstr.value.decode('us-ascii')) + if v == uuid.UUID(int=0): + raise RuntimeError( + 'uuid from kern.hostuuid is all zeros') - return uuid.UUID(bytes=bytes(hid)) + return v -for r, f, a in ( - (c_int, 'gethostuuid', (uuid_t, timespec_p)), - ): - fun = getattr(_clib, f) - setattr(fun, 'restype', r) - setattr(fun, 'argtypes', a) - locals()[f] = fun + for r, f, a in ( + (c_int, 'sysctlbyname', (c_char_p, c_void_p, POINTER(c_size_t), + c_void_p, c_size_t)), + ): + fun = getattr(_clib, f) + setattr(fun, 'restype', r) + setattr(fun, 'argtypes', a) + locals()[f] = fun +else: + raise RuntimeError('no hostuuid defined for platform: %s' % + repr(sys.platform))