Skip to content

Commit 9867c98

Browse files
committed
test: cover --exit-code-on-api-error, truncation, and Buildkite formatting
tests/unit/test_cli_config.py - exit_code_on_api_error default 3 / custom / zero - commit-message truncation: passthrough under 200, truncate over 200, quote-strip-before-truncate tests/unit/test_socketcli.py - unexpected error exits 3 by default - --exit-code-on-api-error 100 remaps the failure exit code - --disable-blocking OVERRIDES --exit-code-on-api-error (-> 0): locks in the documented precedence so the soft_fail guidance can't silently regress - KeyboardInterrupt still exits 2 - _emit_infrastructure_error: BK markers + soft_fail hint only when IS_BUILDKITE; traceback gated on include_traceback Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>
1 parent 7aacf82 commit 9867c98

2 files changed

Lines changed: 135 additions & 0 deletions

File tree

tests/unit/test_cli_config.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,45 @@
11
import pytest
22
from socketsecurity.config import CliConfig
33

4+
5+
class TestExitCodeOnApiError:
6+
def test_default_is_3(self):
7+
config = CliConfig.from_args(["--api-token", "test"])
8+
assert config.exit_code_on_api_error == 3
9+
10+
def test_custom_value(self):
11+
config = CliConfig.from_args(
12+
["--api-token", "test", "--exit-code-on-api-error", "100"]
13+
)
14+
assert config.exit_code_on_api_error == 100
15+
16+
def test_zero_value(self):
17+
config = CliConfig.from_args(
18+
["--api-token", "test", "--exit-code-on-api-error", "0"]
19+
)
20+
assert config.exit_code_on_api_error == 0
21+
22+
23+
class TestCommitMessageTruncation:
24+
def test_passes_through_under_limit(self):
25+
msg = "a normal short commit message"
26+
config = CliConfig.from_args(["--api-token", "test", "--commit-message", msg])
27+
assert config.commit_message == msg
28+
29+
def test_truncated_above_limit(self):
30+
config = CliConfig.from_args(
31+
["--api-token", "test", "--commit-message", "a" * 250]
32+
)
33+
assert config.commit_message == "a" * 200
34+
35+
def test_quote_strip_runs_before_truncation(self):
36+
quoted = '"' + ("b" * 250) + '"'
37+
config = CliConfig.from_args(
38+
["--api-token", "test", "--commit-message", quoted]
39+
)
40+
assert config.commit_message == "b" * 200
41+
42+
443
class TestCliConfig:
544
def test_api_token_from_env(self, monkeypatch):
645
monkeypatch.setenv("SOCKET_SECURITY_API_KEY", "test-token")

tests/unit/test_socketcli.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,103 @@
1+
import sys
2+
3+
import pytest
4+
15
from socketsecurity.core.classes import Diff, Package
6+
from socketsecurity import socketcli
27
from socketsecurity.socketcli import build_license_artifact_payload
38

49

10+
# ---------------------------------------------------------------------------
11+
# Exit-code-on-api-error (flag-only, non-breaking for 2.3.x).
12+
#
13+
# Default behavior is unchanged from prior releases: unexpected errors exit 3,
14+
# and --disable-blocking forces exit 0 for everything. The flag only changes
15+
# the code when explicitly set, and --disable-blocking still takes precedence.
16+
# ---------------------------------------------------------------------------
17+
18+
19+
def _run_cli_expecting_exit(monkeypatch, argv, boom=None):
20+
def fail_main_code():
21+
raise (boom or RuntimeError("infra boom"))
22+
23+
monkeypatch.setattr(socketcli, "main_code", fail_main_code)
24+
monkeypatch.setattr(sys, "argv", argv)
25+
with pytest.raises(SystemExit) as exc_info:
26+
socketcli.cli()
27+
return exc_info.value.code
28+
29+
30+
def test_unexpected_error_exits_3_by_default(monkeypatch):
31+
code = _run_cli_expecting_exit(monkeypatch, ["socketcli", "--api-token", "test"])
32+
assert code == 3
33+
34+
35+
def test_exit_code_on_api_error_remaps_failure(monkeypatch):
36+
code = _run_cli_expecting_exit(
37+
monkeypatch,
38+
["socketcli", "--api-token", "test", "--exit-code-on-api-error", "100"],
39+
)
40+
assert code == 100
41+
42+
43+
def test_disable_blocking_overrides_exit_code_on_api_error(monkeypatch):
44+
# The documented interaction: --disable-blocking forces exit 0 for ALL
45+
# outcomes and therefore overrides --exit-code-on-api-error. A user who
46+
# sets both gets 0, NOT 100 -- this guards against silently regressing
47+
# that precedence (which would break the documented soft_fail guidance).
48+
code = _run_cli_expecting_exit(
49+
monkeypatch,
50+
[
51+
"socketcli", "--api-token", "test",
52+
"--exit-code-on-api-error", "100",
53+
"--disable-blocking",
54+
],
55+
)
56+
assert code == 0
57+
58+
59+
def test_keyboard_interrupt_still_exits_2(monkeypatch):
60+
code = _run_cli_expecting_exit(
61+
monkeypatch, ["socketcli", "--api-token", "test"], boom=KeyboardInterrupt()
62+
)
63+
assert code == 2
64+
65+
66+
# ---------------------------------------------------------------------------
67+
# Buildkite-aware infrastructure error formatting.
68+
# ---------------------------------------------------------------------------
69+
70+
71+
def test_emit_infra_error_no_buildkite_has_no_markers(monkeypatch, capsys, caplog):
72+
monkeypatch.setattr(socketcli, "IS_BUILDKITE", False)
73+
with caplog.at_level("ERROR", logger="socketcli"):
74+
socketcli._emit_infrastructure_error("something failed")
75+
out = capsys.readouterr().out
76+
assert "^^^ +++" not in out
77+
assert "--- :warning:" not in out
78+
assert "soft_fail" not in "\n".join(r.getMessage() for r in caplog.records)
79+
80+
81+
def test_emit_infra_error_buildkite_emits_markers(monkeypatch, capsys, caplog):
82+
monkeypatch.setattr(socketcli, "IS_BUILDKITE", True)
83+
with caplog.at_level("ERROR", logger="socketcli"):
84+
socketcli._emit_infrastructure_error("something failed")
85+
out = capsys.readouterr().out
86+
assert "^^^ +++" in out
87+
assert "--- :warning: Socket infrastructure error" in out
88+
assert "soft_fail" in "\n".join(r.getMessage() for r in caplog.records)
89+
90+
91+
def test_emit_infra_error_traceback_gated(monkeypatch, capsys):
92+
monkeypatch.setattr(socketcli, "IS_BUILDKITE", False)
93+
try:
94+
raise ValueError("boom")
95+
except ValueError:
96+
socketcli._emit_infrastructure_error("wrapped", include_traceback=True)
97+
err = capsys.readouterr().err
98+
assert "Traceback" in err and "ValueError: boom" in err
99+
100+
5101
def test_build_license_artifact_payload_without_packages_returns_empty_dict():
6102
diff = Diff()
7103

0 commit comments

Comments
 (0)