diff --git a/test/unit/python/jw/pkg/lib/TarIo/Makefile b/test/unit/python/jw/pkg/lib/TarIo/Makefile new file mode 100644 index 00000000..de693650 --- /dev/null +++ b/test/unit/python/jw/pkg/lib/TarIo/Makefile @@ -0,0 +1,7 @@ +TOPDIR = ../../../../../../.. + +include $(TOPDIR)/make/proj.mk +include $(JWBDIR)/make/py-run.mk + +all: +test: run diff --git a/test/unit/python/jw/pkg/lib/TarIo/test.py b/test/unit/python/jw/pkg/lib/TarIo/test.py new file mode 100644 index 00000000..56db44df --- /dev/null +++ b/test/unit/python/jw/pkg/lib/TarIo/test.py @@ -0,0 +1,53 @@ +import io +import tarfile + +from jw.pkg.lib.TarIo import TarIoTarFile + +def make_tar(files: dict[str, bytes]) -> bytes: + buf = io.BytesIO() + with tarfile.open(fileobj = buf, mode = 'w') as tf: + for name, content in files.items(): + info = tarfile.TarInfo(name) + info.size = len(content) + tf.addfile(info, io.BytesIO(content)) + return buf.getvalue() + +def members(blob: bytes) -> dict[str, bytes | None]: + ret = {} + with tarfile.open(fileobj = io.BytesIO(blob)) as tf: + for info in tf.getmembers(): + f = tf.extractfile(info) + ret[info.name] = f.read() if f is not None else None + return ret + +# -- Bypass the constructor: _filter_tar_file() and _match() do not use +# the copy contexts, so a bare instance is sufficient +tar = object.__new__(TarIoTarFile) + +files = { + 'a.txt': b'AAA', + 'dir/b.txt': b'BBB', + 'c.txt': b'CCC', +} +blob = make_tar(files) + +# -- _match is exact matching +assert tar._match('a.txt', ['a.txt', 'c.txt']) +assert not tar._match('a.txt', ['x.txt']) +assert not tar._match('a.txt', []) + +# -- _filter_tar_file without a filter is a round trip +ret = tar._filter_tar_file(blob) +assert members(ret) == files + +# -- With a filter, only the exact paths survive +matched: list[str] = [] +ret = tar._filter_tar_file(blob, ['a.txt', 'c.txt'], matched = matched) +assert members(ret) == {'a.txt': b'AAA', 'c.txt': b'CCC'} +assert sorted(matched) == ['a.txt', 'c.txt'] + +# -- A filter without hits yields an empty tar +ret = tar._filter_tar_file(blob, ['nope.txt']) +assert members(ret) == {} + +print('All TarIo tests passed')