import logging import pytest from threading import Event, Lock from appengine import Commands, AEErrs, AppEngineException from conftest import SampleModule class TestValToPrint: def test_string_passthrough(self, sample_module): assert sample_module.val_to_print("hello") == "hello" def test_float_default_one_decimal(self, sample_module): assert sample_module.val_to_print(3.14159) == "3.1" def test_float_custom_decimals(self, sample_module): assert sample_module.val_to_print(3.14159, dig=3) == "3.142" def test_integer_as_string(self, sample_module): assert sample_module.val_to_print(42) == "42" class TestLogging: def _bare_module(self): m = SampleModule(None, None) m.lock = Lock() return m def test_info_falls_back_to_print(self, capsys): self._bare_module().info("hello") assert "hello" in capsys.readouterr().out def test_debug_falls_back_to_print(self, capsys): self._bare_module().debug("dbg") assert "dbg" in capsys.readouterr().out def test_warning_falls_back_to_print(self, capsys): self._bare_module().warning("warn") assert "warn" in capsys.readouterr().out def test_error_falls_back_to_print(self, capsys): self._bare_module().error("err") assert "err" in capsys.readouterr().out def test_info_uses_logger(self, sample_module, caplog): with caplog.at_level(logging.INFO, logger="test"): sample_module.info("via logger") assert "via logger" in caplog.text class TestStop: def test_initial_state(self, sample_module): assert sample_module.stopped is False def test_stop_sets_flag(self, sample_module): sample_module.stop() assert sample_module.stopped is True def test_stop_all_without_event(self, sample_module): sample_module.stop_all_event = None sample_module.stop_all() # must not raise def test_stop_all_sets_event(self, sample_module): event = Event() sample_module.stop_all_event = event sample_module.stop_all() assert event.is_set() class TestFree: def test_free_is_noop(self, sample_module): sample_module.free() # must not raise class TestCmdHelp: def test_no_args_lists_commands(self, sample_module): result = sample_module.cmd_help() assert "add" in result assert "raise_ae" in result assert "raise_generic" in result def test_known_command_returns_docstring(self, sample_module): result = sample_module.cmd_help("add") assert "Add two numbers" in result def test_undocumented_command(self, log): class NoDoc(Commands): def cmd_nodoc(self): pass m = NoDoc(None, log) m.lock = Lock() assert "No documentation" in m.cmd_help("nodoc") def test_unknown_command(self, sample_module): assert "No command with this name" in sample_module.cmd_help("nonexistent") class TestListModules: def test_empty_cmods(self, sample_module): sample_module.cmods = {} success, result = sample_module.list_modules() assert success is True assert "List of modules" in result def test_with_modules(self, sample_module): sample_module.cmods = {"foo": None, "bar": None} _, result = sample_module.list_modules() assert "foo" in result assert "bar" in result class TestExecuteCommand: def test_success(self, sample_module): success, result = sample_module._execute_command("add", 1, 2) assert success is True assert result == 3.0 def test_method_not_found(self, sample_module): success, _ = sample_module._execute_command("nonexistent") assert success is False def test_wrong_params(self, sample_module): success, result = sample_module._execute_command("add") # missing a, b assert success is False assert result[0] == AEErrs.INVALID_PARAMS.value def test_app_engine_exception(self, sample_module): success, result = sample_module._execute_command("raise_ae") assert success is False assert result[0] == AEErrs.INVALID_PARAMS.value assert result[1] == "test error" def test_generic_exception(self, sample_module): success, result = sample_module._execute_command("raise_generic") assert success is False assert result[0] == AEErrs.INTERNAL_ERROR.value class TestDispatch: def test_module_not_found(self, sample_module): success, result = sample_module.execute_command("nonexistent", "add", 1, 2) assert success is False assert result[0] == AEErrs.INVALID_REQUEST.value def test_underscore_hyphen_alias(self, sample_module): sample_module.cmods = {"my-mod": sample_module} success, _ = sample_module.execute_command("my_mod", "add", 1, 2) assert success is True def test_help_no_args_lists_modules(self, sample_module): sample_module.cmods = {"sample": sample_module} success, result = sample_module.execute_command("", "help") assert success is True assert "sample" in result def test_help_with_module(self, sample_module): sample_module.cmods = {"sample": sample_module} success, result = sample_module.execute_command("", "help", "sample") assert success is True assert "add" in result def test_help_module_dot_function(self, sample_module): sample_module.cmods = {"sample": sample_module} success, result = sample_module.execute_command("", "help", "sample.add") assert success is True assert "Add two numbers" in result def test_no_module_uses_defmod(self, sample_module): Commands.defmod = "sample" sample_module.cmods = {"sample": sample_module} success, result = sample_module.execute_command("", "add", 1, 2) assert success is True assert result == 3.0