Skip to content

Commit e4f44e3

Browse files
committed
test: classifyToolCall unit tests — shell, file, browser, unknown tool classification
1 parent f7f101b commit e4f44e3

1 file changed

Lines changed: 93 additions & 0 deletions

File tree

internal/loop/loop_test.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1681,3 +1681,96 @@ func TestBatchApprovalSingleTool(t *testing.T) {
16811681
t.Logf("Single tool: batch gate not triggered ✓")
16821682
}
16831683

1684+
// ── classifyToolCall Tests ──────────────────────────────────────────────
1685+
1686+
func TestClassifyToolCall_ShellDestructive(t *testing.T) {
1687+
risk, resource := classifyToolCall("shell", `{"command":"rm -rf /etc/passwd"}`)
1688+
if risk != danger.Destructive {
1689+
t.Errorf("risk = %q, want %q", risk, danger.Destructive)
1690+
}
1691+
if resource != "rm -rf /etc/passwd" {
1692+
t.Errorf("resource = %q, want %q", resource, "rm -rf /etc/passwd")
1693+
}
1694+
}
1695+
1696+
func TestClassifyToolCall_ShellSafe(t *testing.T) {
1697+
risk, resource := classifyToolCall("shell", `{"command":"ls -la"}`)
1698+
if risk != danger.Safe {
1699+
t.Errorf("risk = %q, want %q", risk, danger.Safe)
1700+
}
1701+
if resource != "ls -la" {
1702+
t.Errorf("resource = %q, want %q", resource, "ls -la")
1703+
}
1704+
}
1705+
1706+
func TestClassifyToolCall_ShellInvalidJSON(t *testing.T) {
1707+
risk, resource := classifyToolCall("shell", `not-json`)
1708+
if risk != "" || resource != "" {
1709+
t.Errorf("expected empty for invalid JSON, got risk=%q resource=%q", risk, resource)
1710+
}
1711+
}
1712+
1713+
func TestClassifyToolCall_ReadFileSystemPath(t *testing.T) {
1714+
risk, resource := classifyToolCall("read_file", `{"path":"/etc/shadow"}`)
1715+
if risk != danger.SystemWrite {
1716+
t.Errorf("risk = %q, want %q", risk, danger.SystemWrite)
1717+
}
1718+
if resource != "/etc/shadow" {
1719+
t.Errorf("resource = %q, want %q", resource, "/etc/shadow")
1720+
}
1721+
}
1722+
1723+
func TestClassifyToolCall_ReadFileLocalPath(t *testing.T) {
1724+
risk, resource := classifyToolCall("read_file", `{"path":"/tmp/test.txt"}`)
1725+
if risk != danger.LocalWrite {
1726+
t.Errorf("risk = %q, want %q", risk, danger.LocalWrite)
1727+
}
1728+
if resource != "/tmp/test.txt" {
1729+
t.Errorf("resource = %q, want %q", resource, "/tmp/test.txt")
1730+
}
1731+
}
1732+
1733+
func TestClassifyToolCall_PatchSystemPath(t *testing.T) {
1734+
risk, resource := classifyToolCall("patch", `{"path":"/etc/nginx.conf"}`)
1735+
if risk != danger.SystemWrite {
1736+
t.Errorf("risk = %q, want %q", risk, danger.SystemWrite)
1737+
}
1738+
if resource != "/etc/nginx.conf" {
1739+
t.Errorf("resource = %q, want %q", resource, "/etc/nginx.conf")
1740+
}
1741+
}
1742+
1743+
func TestClassifyToolCall_WriteFileBadJSON(t *testing.T) {
1744+
risk, resource := classifyToolCall("write_file", `invalid`)
1745+
if risk != "" || resource != "" {
1746+
t.Errorf("expected empty for invalid JSON, got risk=%q resource=%q", risk, resource)
1747+
}
1748+
}
1749+
1750+
func TestClassifyToolCall_BrowserNavigate(t *testing.T) {
1751+
risk, resource := classifyToolCall("browser_navigate", `https://example.com`)
1752+
if risk != danger.NetworkEgress {
1753+
t.Errorf("risk = %q, want %q", risk, danger.NetworkEgress)
1754+
}
1755+
if resource != "https://example.com" {
1756+
t.Errorf("resource = %q, want %q", resource, "https://example.com")
1757+
}
1758+
}
1759+
1760+
func TestClassifyToolCall_UnknownTool(t *testing.T) {
1761+
risk, resource := classifyToolCall("unknown_tool", `{}`)
1762+
if risk != "" || resource != "" {
1763+
t.Errorf("expected empty for unknown tool, got risk=%q resource=%q", risk, resource)
1764+
}
1765+
}
1766+
1767+
func TestClassifyToolCall_Terminal(t *testing.T) {
1768+
risk, resource := classifyToolCall("terminal", `{"command":"whoami"}`)
1769+
if risk != danger.Safe {
1770+
t.Errorf("risk = %q, want %q", risk, danger.Safe)
1771+
}
1772+
if resource != "whoami" {
1773+
t.Errorf("resource = %q, want %q", resource, "whoami")
1774+
}
1775+
}
1776+

0 commit comments

Comments
 (0)