|
8 | 8 | import io |
9 | 9 | import os |
10 | 10 | from pathlib import Path |
| 11 | +import runpy |
11 | 12 | import shutil |
12 | 13 | import sys |
13 | 14 | from tempfile import NamedTemporaryFile |
@@ -228,6 +229,93 @@ def run_main(argv): |
228 | 229 | assert dash_h_stderr == dash_help_stderr |
229 | 230 |
|
230 | 231 |
|
| 232 | +def test_main_returns_zero_when_click_entrypoint_returns_none(monkeypatch: pytest.MonkeyPatch) -> None: |
| 233 | + monkeypatch.setattr(main, 'filtered_sys_argv', lambda: ['--help']) |
| 234 | + monkeypatch.setattr(main.click_entrypoint, 'main', lambda *args, **kwargs: None) |
| 235 | + |
| 236 | + assert main.main() == 0 |
| 237 | + |
| 238 | + |
| 239 | +def test_main_returns_click_entrypoint_integer_result(monkeypatch: pytest.MonkeyPatch) -> None: |
| 240 | + monkeypatch.setattr(main, 'filtered_sys_argv', lambda: ['--version']) |
| 241 | + monkeypatch.setattr(main.click_entrypoint, 'main', lambda *args, **kwargs: 7) |
| 242 | + |
| 243 | + assert main.main() == 7 |
| 244 | + |
| 245 | + |
| 246 | +def test_main_returns_one_for_unexpected_click_entrypoint_result(monkeypatch: pytest.MonkeyPatch) -> None: |
| 247 | + monkeypatch.setattr(main, 'filtered_sys_argv', list) |
| 248 | + monkeypatch.setattr(main.click_entrypoint, 'main', lambda *args, **kwargs: object()) |
| 249 | + |
| 250 | + assert main.main() == 1 |
| 251 | + |
| 252 | + |
| 253 | +def test_main_exits_one_on_click_abort(monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]) -> None: |
| 254 | + monkeypatch.setattr(main, 'filtered_sys_argv', list) |
| 255 | + monkeypatch.setattr(main.click_entrypoint, 'main', lambda *args, **kwargs: (_ for _ in ()).throw(click.Abort())) |
| 256 | + |
| 257 | + with pytest.raises(SystemExit) as excinfo: |
| 258 | + main.main() |
| 259 | + |
| 260 | + assert excinfo.value.code == 1 |
| 261 | + assert 'Aborted!' in capsys.readouterr().err |
| 262 | + |
| 263 | + |
| 264 | +def test_main_exits_one_on_broken_pipe(monkeypatch: pytest.MonkeyPatch) -> None: |
| 265 | + monkeypatch.setattr(main, 'filtered_sys_argv', list) |
| 266 | + monkeypatch.setattr(main.click_entrypoint, 'main', lambda *args, **kwargs: (_ for _ in ()).throw(BrokenPipeError())) |
| 267 | + |
| 268 | + with pytest.raises(SystemExit) as excinfo: |
| 269 | + main.main() |
| 270 | + |
| 271 | + assert excinfo.value.code == 1 |
| 272 | + |
| 273 | + |
| 274 | +def test_main_exits_with_click_exception_exit_code(monkeypatch: pytest.MonkeyPatch) -> None: |
| 275 | + exception = click.ClickException('bad option') |
| 276 | + exception.exit_code = 9 |
| 277 | + show_calls: list[bool] = [] |
| 278 | + monkeypatch.setattr(main, 'filtered_sys_argv', list) |
| 279 | + monkeypatch.setattr(exception, 'show', lambda *args, **kwargs: show_calls.append(True)) |
| 280 | + monkeypatch.setattr(main.click_entrypoint, 'main', lambda *args, **kwargs: (_ for _ in ()).throw(exception)) |
| 281 | + |
| 282 | + with pytest.raises(SystemExit) as excinfo: |
| 283 | + main.main() |
| 284 | + |
| 285 | + assert excinfo.value.code == 9 |
| 286 | + assert show_calls == [True] |
| 287 | + |
| 288 | + |
| 289 | +def test_main_exits_two_for_click_exception_without_exit_code(monkeypatch: pytest.MonkeyPatch) -> None: |
| 290 | + class NoExitCodeClickException(click.ClickException): |
| 291 | + def __getattribute__(self, name: str) -> Any: |
| 292 | + if name == 'exit_code': |
| 293 | + raise AttributeError(name) |
| 294 | + return super().__getattribute__(name) |
| 295 | + |
| 296 | + exception = NoExitCodeClickException('bad option') |
| 297 | + show_calls: list[bool] = [] |
| 298 | + monkeypatch.setattr(main, 'filtered_sys_argv', list) |
| 299 | + monkeypatch.setattr(exception, 'show', lambda *args, **kwargs: show_calls.append(True)) |
| 300 | + monkeypatch.setattr(main.click_entrypoint, 'main', lambda *args, **kwargs: (_ for _ in ()).throw(exception)) |
| 301 | + |
| 302 | + with pytest.raises(SystemExit) as excinfo: |
| 303 | + main.main() |
| 304 | + |
| 305 | + assert excinfo.value.code == 2 |
| 306 | + assert show_calls == [True] |
| 307 | + |
| 308 | + |
| 309 | +def test_module_main_guard_calls_sys_exit(monkeypatch: pytest.MonkeyPatch) -> None: |
| 310 | + exit_codes: list[int | None] = [] |
| 311 | + monkeypatch.setattr(click.core.Command, 'main', lambda self, *args, **kwargs: 11) |
| 312 | + monkeypatch.setattr(sys, 'exit', lambda code=0: exit_codes.append(code)) |
| 313 | + |
| 314 | + runpy.run_path(main.__file__, run_name='__main__') |
| 315 | + |
| 316 | + assert exit_codes == [11] |
| 317 | + |
| 318 | + |
231 | 319 | @dbtest |
232 | 320 | def test_ssl_mode_on(executor, capsys): |
233 | 321 | runner = CliRunner() |
|
0 commit comments