diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 96f90c98..0a7b2969 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -38,7 +38,6 @@ jobs: build-essential debhelper dh-python dh-apparmor git config --global --add safe.directory "$GITHUB_WORKSPACE" - uses: actions/checkout@v4 - - name: Test build run: | dpkg-buildpackage -b -i -us -uc @@ -47,3 +46,5 @@ jobs: run: | set -o xtrace ./run-tests + git clone https://github.com/nickboucher/trojan-source + ./unicode-testscript diff --git a/pyproject.toml b/pyproject.toml index 66ae5607..010fdd41 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,6 +2,8 @@ line-length = 79 [tool.mypy] strict="yes" +[tool.pylint.'SIMILARITIES'] +min-similarity-lines=10 [tool.pylint.'FORMAT'] expected-line-ending-format="LF" max-line-length=79 diff --git a/run-tests b/run-tests index 1ad52aa1..e9accb5c 100755 --- a/run-tests +++ b/run-tests @@ -5,13 +5,14 @@ pyrc="${git_toplevel}/pyproject.toml" pythonpath="${git_toplevel}/usr/lib/python3/dist-packages" export PYTHONPATH="${pythonpath}${PYTHONPATH+":${PYTHONPATH}"}" -pytest=(python3 -m pytest -o 'python_files=*.py') +pytest=(python3 -m pytest -o 'python_files=tests/*.py') black=(black --config="${pyrc}" --color --diff --check) pylint=(pylint --rcfile="${pyrc}") mypy=(mypy --config-file="${pyrc}") cd "${pythonpath}/stdisplay/" -"${pytest[@]}" "${@}" +# Ideally, these variables should be ignored by the tests... +NO_COLOR="" COLORTERM="" TERM="xterm-direct" "${pytest[@]}" "${@}" "${black[@]}" . find . -type f -name "*.py" -print0 | xargs -0 "${pylint[@]}" "${mypy[@]}" . diff --git a/unicode-testscript b/unicode-testscript index da92c304..4f952e8e 100755 --- a/unicode-testscript +++ b/unicode-testscript @@ -3,23 +3,15 @@ ## Copyright (C) 2025 - 2025 ENCRYPTED SUPPORT LLC ## See the file COPYING for copying conditions. -## NOTE: -## Assumes folder 'trojan-source' in the home folder. -## -## cd ~ -## git clone git@github.com:nickboucher/trojan-source.git - -## TODO: Convert into proper unit test and/or CI. - #set -x set -e set -o nounset set -o pipefail set -o errtrace -if [ "$(id -u)" = 0 ]; then - printf "%s\n" "$0: ERROR: No need to run as root!" >&2 - exit 1 +if [ "$(id -u)" = 0 ] && [ -z "${GITHUB_WORKSPACE:-}" ]; then + printf "%s\n" "$0: ERROR: No need to run as root!" >&2 + exit 1 fi folder_list="Assembly Bash C C# C++ Go Java JavaScript Python RegEx Rust Solidity" diff --git a/usr/bin/stcat b/usr/bin/stcat index da0cd351..54b7f924 100755 --- a/usr/bin/stcat +++ b/usr/bin/stcat @@ -1,25 +1,12 @@ #!/usr/bin/env python3 +# pylint: disable=missing-module-docstring ## SPDX-FileCopyrightText: 2025 Benjamin Grande M. S. ## SPDX-FileCopyrightText: 2025 ENCRYPTED SUPPORT LLC ## ## SPDX-License-Identifier: AGPL-3.0-or-later -"""Safely print stdin or file to stdout.""" - -from fileinput import input as file_input -from sys import stdin, stdout -from stdisplay.stdisplay import stdisplay - - -def main() -> None: - """Safely print stdin or file to stdout.""" - stdin.reconfigure(errors="ignore") # type: ignore - ## File input reads stdin when no file is provided or file is '-'. - for untrusted_text in file_input(encoding="ascii", errors="replace"): - stdout.write(stdisplay(untrusted_text)) - stdout.flush() - +from stdisplay.stcat import main if __name__ == "__main__": main() diff --git a/usr/bin/stcatn b/usr/bin/stcatn index e649339e..a04f9fb9 100755 --- a/usr/bin/stcatn +++ b/usr/bin/stcatn @@ -1,31 +1,12 @@ #!/usr/bin/env python3 +# pylint: disable=missing-module-docstring ## SPDX-FileCopyrightText: 2025 Benjamin Grande M. S. ## SPDX-FileCopyrightText: 2025 ENCRYPTED SUPPORT LLC ## ## SPDX-License-Identifier: AGPL-3.0-or-later -""" -Safely print stdin or file to stdout with tweaks -(trim trailing whitespace, ensure final newline). -""" - -from fileinput import input as file_input -from sys import stdin, stdout -from stdisplay.stdisplay import stdisplay - - -def main() -> None: - """ - main - """ - stdin.reconfigure(errors="ignore") # type: ignore - - for line in file_input(encoding="ascii", errors="replace"): - stdout.write(stdisplay(line).rstrip() + "\n") - - stdout.flush() - +from stdisplay.stcatn import main if __name__ == "__main__": main() diff --git a/usr/bin/stecho b/usr/bin/stecho index 4f3c02de..d9820854 100755 --- a/usr/bin/stecho +++ b/usr/bin/stecho @@ -1,24 +1,12 @@ #!/usr/bin/env python3 +# pylint: disable=missing-module-docstring ## SPDX-FileCopyrightText: 2025 Benjamin Grande M. S. ## SPDX-FileCopyrightText: 2025 ENCRYPTED SUPPORT LLC ## ## SPDX-License-Identifier: AGPL-3.0-or-later -"""Safely print argument to stdout with echo's formatting.""" - -from sys import argv, stdout -from stdisplay.stdisplay import stdisplay - - -def main() -> None: - """Safely print argument to stdout with echo's formatting.""" - if len(argv) > 1: - untrusted_text = " ".join(argv[1:]) - stdout.write(stdisplay(untrusted_text)) - stdout.write("\n") - stdout.flush() - +from stdisplay.stecho import main if __name__ == "__main__": main() diff --git a/usr/bin/stprint b/usr/bin/stprint index 6a2cc0dc..7f8c6d13 100755 --- a/usr/bin/stprint +++ b/usr/bin/stprint @@ -1,23 +1,12 @@ #!/usr/bin/env python3 +# pylint: disable=missing-module-docstring ## SPDX-FileCopyrightText: 2025 Benjamin Grande M. S. ## SPDX-FileCopyrightText: 2025 ENCRYPTED SUPPORT LLC ## ## SPDX-License-Identifier: AGPL-3.0-or-later -"""Safely print argument to stdout.""" - -from sys import argv, stdout -from stdisplay.stdisplay import stdisplay - - -def main() -> None: - """Safely print argument to stdout.""" - if len(argv) > 1: - untrusted_text = "".join(argv[1:]) - stdout.write(stdisplay(untrusted_text)) - stdout.flush() - +from stdisplay.stprint import main if __name__ == "__main__": main() diff --git a/usr/bin/stsponge b/usr/bin/stsponge index efb4d250..0af27420 100755 --- a/usr/bin/stsponge +++ b/usr/bin/stsponge @@ -1,35 +1,12 @@ #!/usr/bin/env python3 +# pylint: disable=missing-module-docstring ## SPDX-FileCopyrightText: 2025 Benjamin Grande M. S. ## SPDX-FileCopyrightText: 2025 ENCRYPTED SUPPORT LLC ## ## SPDX-License-Identifier: AGPL-3.0-or-later -"""Safely print stdin to stdout or file.""" - -from sys import argv, stdin, stdout -import shutil -from tempfile import NamedTemporaryFile -from stdisplay.stdisplay import stdisplay - - -def main() -> None: - """Safely print stdin to stdout or file.""" - untrusted_text_list = [] - stdin.reconfigure(errors="ignore") # type: ignore - for untrusted_text in stdin: - untrusted_text_list.append(untrusted_text) - if len(argv) == 1: - stdout.write(stdisplay("".join(untrusted_text_list))) - stdout.flush() - else: - with NamedTemporaryFile(mode="w", delete=False) as temp_file: - temp_file.write(stdisplay("".join(untrusted_text_list))) - temp_file.flush() - for file in argv[1:]: - shutil.copy2(temp_file.name, file) - temp_file.close() - +from stdisplay.stsponge import main if __name__ == "__main__": main() diff --git a/usr/bin/sttee b/usr/bin/sttee index 585ef224..8628a648 100755 --- a/usr/bin/sttee +++ b/usr/bin/sttee @@ -1,28 +1,12 @@ #!/usr/bin/env python3 +# pylint: disable=missing-module-docstring ## SPDX-FileCopyrightText: 2025 Benjamin Grande M. S. ## SPDX-FileCopyrightText: 2025 ENCRYPTED SUPPORT LLC ## ## SPDX-License-Identifier: AGPL-3.0-or-later -"""Safely print stdin to stdout and file.""" -from sys import argv, stdin, stdout -from stdisplay.stdisplay import stdisplay - - -def main() -> None: - """Safely print stdin to stdout and file.""" - untrusted_text_list = [] - stdin.reconfigure(errors="ignore") # type: ignore - for untrusted_text in stdin: - untrusted_text_list.append(untrusted_text) - stdout.write(stdisplay(untrusted_text)) - stdout.flush() - if len(argv) > 1: - for file_arg in argv[1:]: - with open(file_arg, mode="w", encoding="ascii") as file: - file.write(stdisplay("".join(untrusted_text_list))) - +from stdisplay.sttee import main if __name__ == "__main__": main() diff --git a/usr/lib/python3/dist-packages/stdisplay/stcat.py b/usr/lib/python3/dist-packages/stdisplay/stcat.py new file mode 100755 index 00000000..9163d97a --- /dev/null +++ b/usr/lib/python3/dist-packages/stdisplay/stcat.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 + +## SPDX-FileCopyrightText: 2025 Benjamin Grande M. S. +## SPDX-FileCopyrightText: 2025 ENCRYPTED SUPPORT LLC +## +## SPDX-License-Identifier: AGPL-3.0-or-later + +"""Safely print stdin or file to stdout.""" + +from fileinput import input as file_input +from sys import stdin, stdout, modules +from stdisplay.stdisplay import stdisplay + + +def main() -> None: + """Safely print stdin or file to stdout.""" + # https://github.com/pytest-dev/pytest/issues/4843 + if "pytest" not in modules: + stdin.reconfigure(errors="ignore") # type: ignore + ## File input reads stdin when no file is provided or file is '-'. + for untrusted_text in file_input(encoding="ascii", errors="replace"): + stdout.write(stdisplay(untrusted_text)) + stdout.flush() + + +if __name__ == "__main__": + main() diff --git a/usr/lib/python3/dist-packages/stdisplay/stcatn.py b/usr/lib/python3/dist-packages/stdisplay/stcatn.py new file mode 100755 index 00000000..3abf9397 --- /dev/null +++ b/usr/lib/python3/dist-packages/stdisplay/stcatn.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 + +## SPDX-FileCopyrightText: 2025 Benjamin Grande M. S. +## SPDX-FileCopyrightText: 2025 ENCRYPTED SUPPORT LLC +## +## SPDX-License-Identifier: AGPL-3.0-or-later + +""" +Safely print stdin or file to stdout with tweaks +(trim trailing whitespace, ensure final newline). +""" + +from fileinput import input as file_input +from sys import stdin, stdout, modules +from stdisplay.stdisplay import stdisplay + + +def main() -> None: + """ + main + """ + # https://github.com/pytest-dev/pytest/issues/4843 + if "pytest" not in modules: + stdin.reconfigure(errors="ignore") # type: ignore + + for line in file_input(encoding="ascii", errors="replace"): + stdout.write(stdisplay(line).rstrip() + "\n") + + stdout.flush() + + +if __name__ == "__main__": + main() diff --git a/usr/lib/python3/dist-packages/stdisplay/stecho.py b/usr/lib/python3/dist-packages/stdisplay/stecho.py new file mode 100755 index 00000000..4f3c02de --- /dev/null +++ b/usr/lib/python3/dist-packages/stdisplay/stecho.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 + +## SPDX-FileCopyrightText: 2025 Benjamin Grande M. S. +## SPDX-FileCopyrightText: 2025 ENCRYPTED SUPPORT LLC +## +## SPDX-License-Identifier: AGPL-3.0-or-later + +"""Safely print argument to stdout with echo's formatting.""" + +from sys import argv, stdout +from stdisplay.stdisplay import stdisplay + + +def main() -> None: + """Safely print argument to stdout with echo's formatting.""" + if len(argv) > 1: + untrusted_text = " ".join(argv[1:]) + stdout.write(stdisplay(untrusted_text)) + stdout.write("\n") + stdout.flush() + + +if __name__ == "__main__": + main() diff --git a/usr/lib/python3/dist-packages/stdisplay/stprint.py b/usr/lib/python3/dist-packages/stdisplay/stprint.py new file mode 100755 index 00000000..6a2cc0dc --- /dev/null +++ b/usr/lib/python3/dist-packages/stdisplay/stprint.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 + +## SPDX-FileCopyrightText: 2025 Benjamin Grande M. S. +## SPDX-FileCopyrightText: 2025 ENCRYPTED SUPPORT LLC +## +## SPDX-License-Identifier: AGPL-3.0-or-later + +"""Safely print argument to stdout.""" + +from sys import argv, stdout +from stdisplay.stdisplay import stdisplay + + +def main() -> None: + """Safely print argument to stdout.""" + if len(argv) > 1: + untrusted_text = "".join(argv[1:]) + stdout.write(stdisplay(untrusted_text)) + stdout.flush() + + +if __name__ == "__main__": + main() diff --git a/usr/lib/python3/dist-packages/stdisplay/stsponge.py b/usr/lib/python3/dist-packages/stdisplay/stsponge.py new file mode 100755 index 00000000..9bcc97e2 --- /dev/null +++ b/usr/lib/python3/dist-packages/stdisplay/stsponge.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 + +## SPDX-FileCopyrightText: 2025 Benjamin Grande M. S. +## SPDX-FileCopyrightText: 2025 ENCRYPTED SUPPORT LLC +## +## SPDX-License-Identifier: AGPL-3.0-or-later + +"""Safely print stdin to stdout or file.""" + +from sys import argv, stdin, stdout, modules +import shutil +from tempfile import NamedTemporaryFile +from stdisplay.stdisplay import stdisplay + + +def main() -> None: + """Safely print stdin to stdout or file.""" + # https://github.com/pytest-dev/pytest/issues/4843 + if "pytest" not in modules: + stdin.reconfigure(errors="ignore") # type: ignore + untrusted_text_list = [] + for untrusted_text in stdin: + untrusted_text_list.append(untrusted_text) + if len(argv) == 1: + stdout.write(stdisplay("".join(untrusted_text_list))) + stdout.flush() + else: + with NamedTemporaryFile(mode="w", delete=False) as temp_file: + temp_file.write(stdisplay("".join(untrusted_text_list))) + temp_file.flush() + for file in argv[1:]: + shutil.copy2(temp_file.name, file) + temp_file.close() + + +if __name__ == "__main__": + main() diff --git a/usr/lib/python3/dist-packages/stdisplay/sttee.py b/usr/lib/python3/dist-packages/stdisplay/sttee.py new file mode 100755 index 00000000..ec1218fa --- /dev/null +++ b/usr/lib/python3/dist-packages/stdisplay/sttee.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 + +## SPDX-FileCopyrightText: 2025 Benjamin Grande M. S. +## SPDX-FileCopyrightText: 2025 ENCRYPTED SUPPORT LLC +## +## SPDX-License-Identifier: AGPL-3.0-or-later + +"""Safely print stdin to stdout and file.""" +from sys import argv, stdin, stdout, modules +from stdisplay.stdisplay import stdisplay + + +def main() -> None: + """Safely print stdin to stdout and file.""" + # https://github.com/pytest-dev/pytest/issues/4843 + if "pytest" not in modules: + stdin.reconfigure(errors="ignore") # type: ignore + untrusted_text_list = [] + for untrusted_text in stdin: + untrusted_text_list.append(untrusted_text) + stdout.write(stdisplay(untrusted_text)) + stdout.flush() + if len(argv) > 1: + for file_arg in argv[1:]: + with open(file_arg, mode="w", encoding="ascii") as file: + file.write(stdisplay("".join(untrusted_text_list))) + + +if __name__ == "__main__": + main() diff --git a/usr/lib/python3/dist-packages/stdisplay/tests/__init__.py b/usr/lib/python3/dist-packages/stdisplay/tests/__init__.py old mode 100755 new mode 100644 index e5a0d9b4..0c7cf256 --- a/usr/lib/python3/dist-packages/stdisplay/tests/__init__.py +++ b/usr/lib/python3/dist-packages/stdisplay/tests/__init__.py @@ -1 +1,99 @@ #!/usr/bin/env python3 +# pylint: disable=missing-module-docstring + +## SPDX-FileCopyrightText: 2025 Benjamin Grande M. S. +## SPDX-FileCopyrightText: 2025 ENCRYPTED SUPPORT LLC +## +## SPDX-License-Identifier: AGPL-3.0-or-later + +import importlib +import os +import shutil +import sys +import tempfile +import unittest +from typing import Optional, Any +from test.support import captured_stdout, captured_stdin # type: ignore +from unittest.mock import patch +from stdisplay.stdisplay import get_sgr_support + + +class TestSTBase(unittest.TestCase): + """ + Base class for testing safe terminal utilities. + + Assign "self.module" to the module you want to try on the "setup()" using + "super()": + + >>> class TestSTCat(stdisplay.tests.TestSTBase): + >>> def setUp(self) -> None: + >>> self.module = "stcat" + >>> super().setUp() + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + self.text_dirty = "\x1b[0mTest\x1b[2Kor\x1b]1;is\x1b\n[m" + self.text_dirty_sanitized = "\x1b[0mTest_[2Kor_]1;is_\n[m" + super().__init__(*args, **kwargs) + + def setUp(self) -> None: + self.tmpfiles_list = [] + contents = ["a b\n", "c d"] + self.tmpdir = tempfile.mkdtemp() + for i in range(0, 6): + self.tmpfiles_list.append(os.path.join(self.tmpdir, str(i))) + with open(self.tmpfiles_list[i], "w", encoding="utf-8") as file: + if i == 0: + file.write("") + elif i == 1: + file.write("".join(contents)) + elif i == 2: + file.write("".join(contents) + "\n") + elif i == 3: + file.write(self.text_dirty) + elif i in [4, 5]: + pass + file.flush() + file.close() + self.tmpfiles = { + "empty": self.tmpfiles_list[0], + "raw": self.tmpfiles_list[1], + "newline": self.tmpfiles_list[2], + "dirty": self.tmpfiles_list[3], + "fill": self.tmpfiles_list[4], + "fill2": self.tmpfiles_list[5], + } + + def tearDown(self) -> None: + shutil.rmtree(self.tmpdir) + + def _del_module(self) -> None: + for module in ["stdisplay." + self.module]: # type: ignore # pylint: disable=no-member + if module in sys.modules: + del sys.modules[module] + globals().pop(module, None) + + # pylint: disable=too-many-arguments + def _test_util( + self, + argv: Optional[list[str]] = None, + stdin: Optional[str] = None, + ) -> str: + """ + Helper function to pass stdin. + """ + self._del_module() + if argv is None: + argv = [self.module + ".py"] # type: ignore # pylint: disable=no-member + else: + argv = [self.module + ".py"] + argv # type: ignore # pylint: disable=no-member + with patch.object( + sys, "argv", argv + ), captured_stdout() as stdout, captured_stdin() as stdin_patch: + module = importlib.import_module("stdisplay." + self.module) # type: ignore # pylint: disable=no-member + if stdin is not None: + stdin_patch.write(stdin) + stdin_patch.seek(0) + module.main() + result = str(stdout.getvalue()) # pylint: disable=no-member + return result diff --git a/usr/lib/python3/dist-packages/stdisplay/tests/stcat.py b/usr/lib/python3/dist-packages/stdisplay/tests/stcat.py new file mode 100644 index 00000000..df7293db --- /dev/null +++ b/usr/lib/python3/dist-packages/stdisplay/tests/stcat.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 +# pylint: disable=missing-module-docstring + +## SPDX-FileCopyrightText: 2025 Benjamin Grande M. S. +## SPDX-FileCopyrightText: 2025 ENCRYPTED SUPPORT LLC +## +## SPDX-License-Identifier: AGPL-3.0-or-later + +import unittest +import stdisplay.tests + + +class TestSTCat(stdisplay.tests.TestSTBase): + """ + Test stcat. + """ + + def setUp(self) -> None: + self.module = "stcat" + super().setUp() + + def test_stcat_stdin(self) -> None: + """ + Test passing stdin. + """ + self.assertEqual("", self._test_util()) + self.assertEqual("", self._test_util(stdin="")) + self.assertEqual("", self._test_util(argv=["-"])) + self.assertEqual("a b", self._test_util(stdin="a b")) + self.assertEqual( + "a b", + self._test_util(argv=["-"], stdin="a b"), + ) + self.assertEqual( + self.text_dirty_sanitized, + self._test_util(stdin=self.text_dirty), + ) + + def test_stcat_file(self) -> None: + """ + Test passing files. + """ + cases = [ + ("", [self.tmpfiles["empty"], self.tmpfiles["empty"]]), + ("a b\nc d", [self.tmpfiles["empty"], self.tmpfiles["raw"]]), + ( + "a b\nc d\n", + [self.tmpfiles["empty"], self.tmpfiles["newline"]], + ), + ( + "a b\nc da b\nc d\n", + [self.tmpfiles["raw"], self.tmpfiles["newline"]], + ), + (self.text_dirty_sanitized, [self.tmpfiles["dirty"]]), + ] + for text, argv in cases: + with self.subTest(text=text, argv=argv): + self.assertEqual(text, self._test_util(argv=argv)) + + self.assertEqual( + "a b\nc d", + self._test_util(stdin="is ignored", argv=[self.tmpfiles["raw"]]), + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/usr/lib/python3/dist-packages/stdisplay/tests/stcatn.py b/usr/lib/python3/dist-packages/stdisplay/tests/stcatn.py new file mode 100644 index 00000000..b330bd28 --- /dev/null +++ b/usr/lib/python3/dist-packages/stdisplay/tests/stcatn.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +# pylint: disable=missing-module-docstring + +## SPDX-FileCopyrightText: 2025 Benjamin Grande M. S. +## SPDX-FileCopyrightText: 2025 ENCRYPTED SUPPORT LLC +## +## SPDX-License-Identifier: AGPL-3.0-or-later + +import unittest +import stdisplay.tests + + +class TestSTCatn(stdisplay.tests.TestSTBase): + """ + Test stcatn. + """ + + def setUp(self) -> None: + self.module = "stcatn" + super().setUp() + + def test_stcatn_file(self) -> None: + """ + Test passing files. + """ + cases = [ + ("a b\nc d\n", [self.tmpfiles["raw"]]), + ( + "a b\nc d\na b\nc d\n", + [self.tmpfiles["raw"], self.tmpfiles["raw"]], + ), + (self.text_dirty_sanitized + "\n", [self.tmpfiles["dirty"]]), + ] + for text, argv in cases: + with self.subTest(text=text, argv=argv): + self.assertEqual(text, self._test_util(argv=argv)) + + self.assertEqual( + "a b\nc d\n", + self._test_util(stdin="is ignored", argv=[self.tmpfiles["raw"]]), + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/usr/lib/python3/dist-packages/stdisplay/tests/stdisplay.py b/usr/lib/python3/dist-packages/stdisplay/tests/stdisplay.py old mode 100755 new mode 100644 index 9d609d72..d6a61638 --- a/usr/lib/python3/dist-packages/stdisplay/tests/stdisplay.py +++ b/usr/lib/python3/dist-packages/stdisplay/tests/stdisplay.py @@ -1,5 +1,10 @@ #!/usr/bin/env python3 +## SPDX-FileCopyrightText: 2025 Benjamin Grande M. S. +## SPDX-FileCopyrightText: 2025 ENCRYPTED SUPPORT LLC +## +## SPDX-License-Identifier: AGPL-3.0-or-later + """ Test the stdisplay module. """ diff --git a/usr/lib/python3/dist-packages/stdisplay/tests/stecho.py b/usr/lib/python3/dist-packages/stdisplay/tests/stecho.py new file mode 100644 index 00000000..f943ce38 --- /dev/null +++ b/usr/lib/python3/dist-packages/stdisplay/tests/stecho.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +# pylint: disable=missing-module-docstring + +## SPDX-FileCopyrightText: 2025 Benjamin Grande M. S. +## SPDX-FileCopyrightText: 2025 ENCRYPTED SUPPORT LLC +## +## SPDX-License-Identifier: AGPL-3.0-or-later + +import unittest +import stdisplay.tests + + +class TestSTEcho(stdisplay.tests.TestSTBase): + """ + Test stecho. + """ + + def setUp(self) -> None: + self.module = "stecho" + super().setUp() + + def test_stecho(self) -> None: + """ + Test stecho. + """ + self.assertEqual("\n", self._test_util()) + self.assertEqual("\n", self._test_util(argv=[""])) + self.assertEqual("\n", self._test_util(stdin="no stdin")) + self.assertEqual("a b\n", self._test_util(argv=["a b"])) + self.assertEqual("a b\n", self._test_util(argv=["a", "b"])) + self.assertEqual( + self.text_dirty_sanitized + "\n", + self._test_util(argv=[self.text_dirty]), + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/usr/lib/python3/dist-packages/stdisplay/tests/stprint.py b/usr/lib/python3/dist-packages/stdisplay/tests/stprint.py index 7c07d3c3..1ce9ebcd 100755 --- a/usr/lib/python3/dist-packages/stdisplay/tests/stprint.py +++ b/usr/lib/python3/dist-packages/stdisplay/tests/stprint.py @@ -1,20 +1,51 @@ #!/usr/bin/env python3 +# pylint: disable=missing-module-docstring -""" -Test the stprint module. -""" +## SPDX-FileCopyrightText: 2025 Benjamin Grande M. S. +## SPDX-FileCopyrightText: 2025 ENCRYPTED SUPPORT LLC +## +## SPDX-License-Identifier: AGPL-3.0-or-later import os -import unittest import subprocess +import unittest from stdisplay.stdisplay import ( get_sgr_support, ) +import stdisplay.tests -class TestSTPrint(unittest.TestCase): +class TestSTPrint(stdisplay.tests.TestSTBase): """ - Test stprint + Test stprint. + """ + + def setUp(self) -> None: + self.module = "stprint" + super().setUp() + + def test_stprint(self) -> None: + """ + Test without argument. + """ + self.assertEqual("", self._test_util()) + self.assertEqual("", self._test_util(argv=[""])) + self.assertEqual("", self._test_util(stdin="no stdin")) + self.assertEqual( + "a b", self._test_util(stdin="no stdin", argv=["a b"]) + ) + self.assertEqual("ab", self._test_util(argv=["a", "b"])) + self.assertEqual( + self.text_dirty_sanitized, self._test_util(argv=[self.text_dirty]) + ) + + +class TestSTPrintShell(unittest.TestCase): + """ + Test stdisplay with environment variables using stprint. + + This class only exists because the developer could not find a way to patch + the environment variables correctly on the base class functions. """ # pylint: disable=too-many-arguments diff --git a/usr/lib/python3/dist-packages/stdisplay/tests/stsponge.py b/usr/lib/python3/dist-packages/stdisplay/tests/stsponge.py new file mode 100644 index 00000000..354b11ca --- /dev/null +++ b/usr/lib/python3/dist-packages/stdisplay/tests/stsponge.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +# pylint: disable=missing-module-docstring disable=duplicate-code + +## SPDX-FileCopyrightText: 2025 Benjamin Grande M. S. +## SPDX-FileCopyrightText: 2025 ENCRYPTED SUPPORT LLC +## +## SPDX-License-Identifier: AGPL-3.0-or-later + +import unittest +from pathlib import Path +import stdisplay.tests + + +class TestSTSponge(stdisplay.tests.TestSTBase): + """ + Test stsponge. + """ + + def setUp(self) -> None: + self.module = "stsponge" + super().setUp() + + def test_stsponge(self) -> None: + """ + Test stsponge. + """ + self.assertEqual("", self._test_util()) + self.assertEqual("", self._test_util(stdin="")) + self.assertEqual("stdin", self._test_util(stdin="stdin")) + # Empty stdin with file argument produces empty stdout and file. + self.assertEqual("", self._test_util(argv=[self.tmpfiles["fill"]])) + self.assertEqual( + "", + Path(self.tmpfiles["fill"]).read_text(encoding="utf-8"), + ) + # Empty stdout when writing to file and file sanitization. + self.assertEqual( + "", + self._test_util( + stdin=self.text_dirty, argv=[self.tmpfiles["fill"]] + ), + ) + self.assertEqual( + self.text_dirty_sanitized, + Path(self.tmpfiles["fill"]).read_text(encoding="utf-8"), + ) + # Empty stdout when writing to multiple files and its sanitization. + self.assertEqual( + "", + self._test_util( + stdin=self.text_dirty, + argv=[self.tmpfiles["fill"], self.tmpfiles["fill2"]], + ), + ) + self.assertEqual( + self.text_dirty_sanitized, + Path(self.tmpfiles["fill"]).read_text(encoding="utf-8"), + ) + self.assertEqual( + self.text_dirty_sanitized, + Path(self.tmpfiles["fill2"]).read_text(encoding="utf-8"), + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/usr/lib/python3/dist-packages/stdisplay/tests/sttee.py b/usr/lib/python3/dist-packages/stdisplay/tests/sttee.py new file mode 100644 index 00000000..c931bd25 --- /dev/null +++ b/usr/lib/python3/dist-packages/stdisplay/tests/sttee.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +# pylint: disable=missing-module-docstring + +## SPDX-FileCopyrightText: 2025 Benjamin Grande M. S. +## SPDX-FileCopyrightText: 2025 ENCRYPTED SUPPORT LLC +## +## SPDX-License-Identifier: AGPL-3.0-or-later + +import unittest +from pathlib import Path +import stdisplay.tests + + +class TestSTTee(stdisplay.tests.TestSTBase): + """ + Test sttee + """ + + def setUp(self) -> None: + self.module = "sttee" + super().setUp() + + def test_sttee(self) -> None: + """ + Test sttee. + """ + self.assertEqual("", self._test_util()) + self.assertEqual("", self._test_util(stdin="")) + self.assertEqual("stdin", self._test_util(stdin="stdin")) + # Empty stdin with file argument. + self.assertEqual("", self._test_util(argv=[self.tmpfiles["fill"]])) + self.assertEqual( + "", + Path(self.tmpfiles["fill"]).read_text(encoding="utf-8"), + ) + # Stdin sanitization and writing to file. + self.assertEqual( + self.text_dirty_sanitized, + self._test_util( + stdin=self.text_dirty, argv=[self.tmpfiles["fill"]] + ), + ) + self.assertEqual( + self.text_dirty_sanitized, + Path(self.tmpfiles["fill"]).read_text(encoding="utf-8"), + ) + # Stdin sanitization and writing to multiple files. + self.assertEqual( + self.text_dirty_sanitized, + self._test_util( + stdin=self.text_dirty, + argv=[self.tmpfiles["fill"], self.tmpfiles["fill2"]], + ), + ) + self.assertEqual( + self.text_dirty_sanitized, + Path(self.tmpfiles["fill"]).read_text(encoding="utf-8"), + ) + self.assertEqual( + self.text_dirty_sanitized, + Path(self.tmpfiles["fill2"]).read_text(encoding="utf-8"), + ) + + +if __name__ == "__main__": + unittest.main()