from __future__ import annotations import unittest from types import SimpleNamespace from unittest.mock import patch from uvm.errors import CommandError from uvm.system import CommandRunner class CommandRunnerTests(unittest.TestCase): def test_passes_sensitive_input_over_stdin_without_logging_it(self) -> None: emitted: list[str] = [] completed = SimpleNamespace(returncode=0, stdout="result\n", stderr="") with patch("uvm.system.subprocess.run", return_value=completed) as run: result = CommandRunner(emit=emitted.append).run( ("credential-tool", "--stdin"), capture=True, input_text="secret-value\n", sensitive=True, ) self.assertEqual(result.stdout, "result\n") self.assertEqual(run.call_args.kwargs["input"], "secret-value\n") self.assertNotIn("secret-value", emitted[0]) def test_redacts_sensitive_command_output_from_errors(self) -> None: completed = SimpleNamespace( returncode=1, stdout="", stderr="failure mentioning secret-value", ) with ( patch("uvm.system.subprocess.run", return_value=completed), self.assertRaises(CommandError) as raised, ): CommandRunner(emit=None).run( ("credential-tool", "--stdin"), capture=True, input_text="secret-value\n", sensitive=True, ) self.assertNotIn("secret-value", str(raised.exception))