From 78f57c7547516d6ae9bb57e83e36f5cda43f6c43 Mon Sep 17 00:00:00 2001 From: Jan Lindemann Date: Thu, 25 Jun 2026 19:37:34 +0200 Subject: [PATCH] jw.pkg.lib.Result: Add unit test Add a unit test for the Result class covering: - stdout/stderr property access with various status values - None output handling and exception behavior - Encoding and strip_output property setters - cmd and wd setters - summary, summarize, and __repr__ behavior - matches_error pattern matching Signed-off-by: Jan Lindemann --- test/unit/python/jw/pkg/lib/Result/Makefile | 8 + test/unit/python/jw/pkg/lib/Result/test.py | 159 ++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 test/unit/python/jw/pkg/lib/Result/Makefile create mode 100644 test/unit/python/jw/pkg/lib/Result/test.py diff --git a/test/unit/python/jw/pkg/lib/Result/Makefile b/test/unit/python/jw/pkg/lib/Result/Makefile new file mode 100644 index 00000000..3d3138c5 --- /dev/null +++ b/test/unit/python/jw/pkg/lib/Result/Makefile @@ -0,0 +1,8 @@ +TOPDIR = ../../../../../../.. + +include $(TOPDIR)/make/proj.mk +include $(JWBDIR)/make/py-run.mk + +all: + +test: run diff --git a/test/unit/python/jw/pkg/lib/Result/test.py b/test/unit/python/jw/pkg/lib/Result/test.py new file mode 100644 index 00000000..b8f25aa9 --- /dev/null +++ b/test/unit/python/jw/pkg/lib/Result/test.py @@ -0,0 +1,159 @@ +from jw.pkg.lib.Result import Result + +# -- Basic construction -- + +r = Result(stdout=b'hello', stderr=b'world', status=0) +assert r.status == 0 +assert r.stdout == b'hello' +assert r.stderr == b'world' + +# -- stdout property -- + +r = Result(stdout=b'test', status=0) +assert r.stdout == b'test' + +# stdout_or_none returns raw value +r = Result(stdout=b'test', status=0) +assert r.stdout_or_none == b'test' + +# stdout_str_or_none returns decoded string +r = Result(stdout=b'test', status=0) +assert r.stdout_str_or_none == 'test' + +# stdout_str returns decoded string +r = Result(stdout=b'test', status=0) +assert r.stdout_str == 'test' + +# stdout returns b'' when stdout is None and status == 0 +r = Result(stdout=None, status=0) +assert r.stdout == b'' + +# stdout raises when stdout is None and status != 0 +r = Result(stdout=None, status=1) +try: + _ = r.stdout + assert False, 'Should have raised' +except Exception: + pass + +# -- stderr property -- + +r = Result(stderr=b'error', status=1) +assert r.stderr == b'error' + +# stderr_or_none returns raw value +r = Result(stderr=b'err', status=1) +assert r.stderr_or_none == b'err' + +# stderr_str_or_none returns decoded string +r = Result(stderr=b'err', status=1) +assert r.stderr_str_or_none == 'err' + +# stderr_str returns decoded string +r = Result(stderr=b'err', status=1) +assert r.stderr_str == 'err' + +# stderr returns b'' when stderr is None and status != 0 (error case) +r = Result(stderr=None, status=1) +assert r.stderr == b'' + +# stderr raises when stderr is None and status == 0 (success case) +r = Result(stderr=None, status=0) +try: + _ = r.stderr + assert False, 'Should have raised' +except Exception: + pass + +# -- None outputs -- + +r = Result(stdout=None, stderr=None, status=1) +assert r.stdout_or_none is None +assert r.stderr_or_none is None +assert r.stdout_str_or_none is None +assert r.stderr_str_or_none is None + +# -- encoding -- + +r = Result(stdout=b'caf\xc3\xa9', encoding='UTF-8') +assert r.encoding == 'UTF-8' +assert r.stdout_str == 'café' + +r = Result(stdout=b'test', encoding='UTF-8') +r.encoding = 'ASCII' +assert r.encoding == 'ASCII' + +# -- strip_output -- + +r = Result(stdout=b' spaces ', status=0) +assert r.stdout_str_or_none == ' spaces ' + +r = Result(stdout=b' spaces ', status=0, strip_output=True) +assert r.stdout_str_or_none == 'spaces' + +r = Result(stdout=b' lines \n', status=0, strip_output=True) +assert r.stdout_str_or_none == 'lines' + +# -- cmd and wd setters -- + +r = Result(cmd=['echo', 'hello'], wd='/tmp') +assert r.cmd == ['echo', 'hello'] +assert r.wd == '/tmp' + +r.cmd = ['ls', '-la'] +r.wd = '/home' +assert r.cmd == ['ls', '-la'] +assert r.wd == '/home' + +# -- summary -- + +r = Result(stdout=b'output', status=0) +assert 'status 0' in r.summary + +r = Result(stderr=b'error', status=1) +assert 'status 1' in r.summary +assert 'stderr' in r.summary + +# -- matches_error -- + +r = Result(stderr=b'fatal error: missing file', status=128) +assert r.matches_error('fatal error') + +r = Result(stderr=b'fatal error: missing file', status=128) +assert not r.matches_error('success') + +r = Result(stdout=b'ok', stderr=b'', status=0) +assert not r.matches_error('.*') + +r = Result(stdout=b'ok', stderr=None, status=0) +assert not r.matches_error('.*') + +# -- summarize with custom cmd/wd -- + +r = Result(stdout=b'out', status=0, cmd=['echo', 'test'], wd='/tmp') +assert 'echo' in r.summary or 'status 0' in r.summary + +# -- __repr__ -- + +r = Result(stdout=b'repr test', status=0) +s = repr(r) +assert '0' in s # verbose=False uses numeric status +assert 'repr test' in s + +# -- encoding setter -- + +r = Result(stdout=b'test', status=0, encoding='UTF-8') +assert r.encoding == 'UTF-8' +r.encoding = 'ASCII' +assert r.encoding == 'ASCII' + +# -- strip_output setter -- + +r = Result(stdout=b' x ', status=0, strip_output=False) +assert r.stdout_str_or_none == ' x ' +r.strip_output = True +# strip_output is a property setter, the value is stored +# But __decode is called at property access time using current strip_output +assert r.stdout_str_or_none == 'x' + +print('All Result tests passed')