Skip to content

Commit de34432

Browse files
anandgupta42claude
andcommitted
test: consolidated test coverage across 9 modules (133 new tests)
Merges 9 test PRs (#390, #394, #395, #396, #397, #398, #399, #401, #387) into a single PR, discarding 4 duplicates (#391, #392, #393, #400). **New test coverage:** - `id.test.ts` — 14 tests: Identifier generation, monotonic ordering, timestamp extraction, Zod schema - `shell.test.ts` — 9 tests: shell blacklist enforcement for fish/nu, cache reset, fallback - `path-traversal.test.ts` — 7 tests (new): `Protected.isSensitiveWrite` for .pem/.key, .gnupg, .env variants - `ignore.test.ts` — 7 tests (new): `FileIgnore.match` directory patterns, globs, whitelist overrides - `paths-parsetext.test.ts` — 16 tests: `ConfigPaths.parseText` env/file substitution, JSONC parsing - `finops-formatting.test.ts` — 14 tests: `formatBytes`/`truncateQuery` edge cases - `finops-role-access.test.ts` — 10 tests: RBAC `formatGrants`/`formatHierarchy`/`formatUserRoles` - `tool-lookup.test.ts` — 4 tests: Zod schema introspection for tool parameters - `summary-git-path.test.ts` — 10 tests: `unquoteGitPath` decoding for non-ASCII filenames - `tracing.test.ts` — 2 tests (added): Recap loop detection boundaries - `patch.test.ts` — 9 tests (added): `maybeParseApplyPatchVerified` entry point coverage - `instruction.test.ts` — 13 tests (new): `InstructionPrompt.loaded()` dedup guards - `message-v2.test.ts` — 23 tests (new): `MessageV2.filterCompacted()` boundary detection **Bug fixes (discovered during testing):** - `finops-formatting.ts`: fix `formatBytes` crash on negative/NaN/fractional inputs - `finops-formatting.ts`: fix `truncateQuery` returning empty for whitespace-only, exceeding `maxLen` when < 4 - `training-import.test.ts`: fix pre-existing typecheck errors (missing `context`/`rule` mock keys) - `instruction.test.ts`, `message-v2.test.ts`: fix `MessageV2.Part` cast and branded ID type errors Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 8eb13d4 commit de34432

15 files changed

Lines changed: 1732 additions & 4 deletions
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
export function formatBytes(bytes: number): string {
22
if (bytes === 0) return "0 B"
3+
if (!Number.isFinite(bytes)) return "0 B"
4+
const abs = Math.abs(bytes)
35
const units = ["B", "KB", "MB", "GB", "TB", "PB"]
4-
const i = Math.floor(Math.log(bytes) / Math.log(1024))
6+
const i = Math.max(0, Math.min(Math.floor(Math.log(abs) / Math.log(1024)), units.length - 1))
57
const value = bytes / Math.pow(1024, i)
68
return `${value.toFixed(i === 0 ? 0 : 2)} ${units[i]}`
79
}
810

911
export function truncateQuery(text: string, maxLen: number): string {
1012
if (!text) return "(empty)"
1113
const oneLine = text.replace(/\s+/g, " ").trim()
14+
if (!oneLine) return "(empty)"
15+
if (maxLen <= 0) return ""
16+
if (maxLen < 4) return oneLine.slice(0, maxLen)
1217
if (oneLine.length <= maxLen) return oneLine
1318
return oneLine.slice(0, maxLen - 3) + "..."
1419
}
Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
/**
2+
* Tests for finops role-access formatting functions:
3+
* formatGrants, formatHierarchy, formatUserRoles.
4+
*
5+
* These render RBAC data as markdown tables. Incorrect output
6+
* could cause data engineers to miss security issues during audits.
7+
* Tests use Dispatcher.call spying to supply known RBAC data.
8+
*/
9+
import { describe, test, expect, spyOn, afterAll, beforeEach } from "bun:test"
10+
import * as Dispatcher from "../../src/altimate/native/dispatcher"
11+
import {
12+
FinopsRoleGrantsTool,
13+
FinopsRoleHierarchyTool,
14+
FinopsUserRolesTool,
15+
} from "../../src/altimate/tools/finops-role-access"
16+
import { SessionID, MessageID } from "../../src/session/schema"
17+
18+
beforeEach(() => {
19+
process.env.ALTIMATE_TELEMETRY_DISABLED = "true"
20+
})
21+
afterAll(() => {
22+
delete process.env.ALTIMATE_TELEMETRY_DISABLED
23+
})
24+
25+
const ctx = {
26+
sessionID: SessionID.make("ses_test"),
27+
messageID: MessageID.make("msg_test"),
28+
callID: "call_test",
29+
agent: "build",
30+
abort: AbortSignal.any([]),
31+
messages: [],
32+
metadata: () => {},
33+
ask: async () => {},
34+
}
35+
36+
let dispatcherSpy: ReturnType<typeof spyOn>
37+
38+
function mockDispatcher(responses: Record<string, any>) {
39+
dispatcherSpy?.mockRestore()
40+
dispatcherSpy = spyOn(Dispatcher, "call").mockImplementation(async (method: string) => {
41+
if (responses[method]) return responses[method]
42+
throw new Error(`No mock for ${method}`)
43+
})
44+
}
45+
46+
afterAll(() => {
47+
dispatcherSpy?.mockRestore()
48+
})
49+
50+
describe("formatGrants: privilege summary and grant rows", () => {
51+
test("renders privilege summary and grant table with standard Snowflake fields", async () => {
52+
mockDispatcher({
53+
"finops.role_grants": {
54+
success: true,
55+
grant_count: 2,
56+
privilege_summary: { SELECT: 2, INSERT: 1 },
57+
grants: [
58+
{ grantee_name: "ANALYST", privilege: "SELECT", object_type: "TABLE", object_name: "orders" },
59+
{ grantee_name: "ADMIN", privilege: "INSERT", object_type: "TABLE", object_name: "users" },
60+
],
61+
},
62+
})
63+
64+
const tool = await FinopsRoleGrantsTool.init()
65+
const result = await tool.execute({ warehouse: "test_wh", limit: 100 }, ctx as any)
66+
67+
expect(result.title).toContain("2 found")
68+
expect(result.output).toContain("Privilege Summary")
69+
expect(result.output).toContain("SELECT: 2")
70+
expect(result.output).toContain("INSERT: 1")
71+
expect(result.output).toContain("ANALYST | SELECT | TABLE | orders")
72+
expect(result.output).toContain("ADMIN | INSERT | TABLE | users")
73+
})
74+
75+
test("uses fallback field aliases (role, granted_on, name)", async () => {
76+
mockDispatcher({
77+
"finops.role_grants": {
78+
success: true,
79+
grant_count: 1,
80+
privilege_summary: {},
81+
grants: [
82+
{ role: "DBA", privilege: "USAGE", granted_on: "WAREHOUSE", name: "compute_wh" },
83+
],
84+
},
85+
})
86+
87+
const tool = await FinopsRoleGrantsTool.init()
88+
const result = await tool.execute({ warehouse: "test_wh", limit: 100 }, ctx as any)
89+
90+
// formatGrants should fall back to r.role, r.granted_on, r.name
91+
expect(result.output).toContain("DBA | USAGE | WAREHOUSE | compute_wh")
92+
})
93+
94+
test("handles empty grants array", async () => {
95+
mockDispatcher({
96+
"finops.role_grants": {
97+
success: true,
98+
grant_count: 0,
99+
privilege_summary: {},
100+
grants: [],
101+
},
102+
})
103+
104+
const tool = await FinopsRoleGrantsTool.init()
105+
const result = await tool.execute({ warehouse: "test_wh", limit: 100 }, ctx as any)
106+
107+
expect(result.output).toContain("No grants found")
108+
})
109+
110+
test("returns error message on Dispatcher failure", async () => {
111+
mockDispatcher({
112+
"finops.role_grants": {
113+
success: false,
114+
error: "Connection refused",
115+
},
116+
})
117+
118+
const tool = await FinopsRoleGrantsTool.init()
119+
const result = await tool.execute({ warehouse: "test_wh", limit: 100 }, ctx as any)
120+
121+
expect(result.title).toContain("FAILED")
122+
expect(result.output).toContain("Connection refused")
123+
})
124+
})
125+
126+
describe("formatHierarchy: recursive role tree rendering", () => {
127+
test("renders two-level nested hierarchy with children key", async () => {
128+
mockDispatcher({
129+
"finops.role_hierarchy": {
130+
success: true,
131+
role_count: 3,
132+
hierarchy: [
133+
{
134+
name: "SYSADMIN",
135+
children: [
136+
{ name: "DBA", children: [] },
137+
{ name: "ANALYST", children: [] },
138+
],
139+
},
140+
],
141+
},
142+
})
143+
144+
const tool = await FinopsRoleHierarchyTool.init()
145+
const result = await tool.execute({ warehouse: "test_wh" }, ctx as any)
146+
147+
expect(result.title).toContain("3 roles")
148+
expect(result.output).toContain("Role Hierarchy")
149+
expect(result.output).toContain("SYSADMIN")
150+
expect(result.output).toContain("-> DBA")
151+
expect(result.output).toContain("-> ANALYST")
152+
})
153+
154+
test("uses granted_roles fallback alias for children", async () => {
155+
mockDispatcher({
156+
"finops.role_hierarchy": {
157+
success: true,
158+
role_count: 2,
159+
hierarchy: [
160+
{
161+
role: "ACCOUNTADMIN",
162+
granted_roles: [{ role: "SECURITYADMIN" }],
163+
},
164+
],
165+
},
166+
})
167+
168+
const tool = await FinopsRoleHierarchyTool.init()
169+
const result = await tool.execute({ warehouse: "test_wh" }, ctx as any)
170+
171+
// Should use r.role as name and r.granted_roles as children
172+
expect(result.output).toContain("ACCOUNTADMIN")
173+
expect(result.output).toContain("-> SECURITYADMIN")
174+
})
175+
176+
test("handles empty hierarchy", async () => {
177+
mockDispatcher({
178+
"finops.role_hierarchy": {
179+
success: true,
180+
role_count: 0,
181+
hierarchy: [],
182+
},
183+
})
184+
185+
const tool = await FinopsRoleHierarchyTool.init()
186+
const result = await tool.execute({ warehouse: "test_wh" }, ctx as any)
187+
188+
expect(result.output).toContain("Role Hierarchy")
189+
// No roles rendered but header is present
190+
expect(result.output).not.toContain("->")
191+
})
192+
})
193+
194+
describe("formatUserRoles: user-role assignment table", () => {
195+
test("renders user assignments with standard fields", async () => {
196+
mockDispatcher({
197+
"finops.user_roles": {
198+
success: true,
199+
assignment_count: 2,
200+
assignments: [
201+
{ grantee_name: "alice@corp.com", role: "ANALYST", granted_by: "SECURITYADMIN" },
202+
{ grantee_name: "bob@corp.com", role: "DBA", granted_by: "ACCOUNTADMIN" },
203+
],
204+
},
205+
})
206+
207+
const tool = await FinopsUserRolesTool.init()
208+
const result = await tool.execute({ warehouse: "test_wh", limit: 100 }, ctx as any)
209+
210+
expect(result.title).toContain("2 assignments")
211+
expect(result.output).toContain("User Role Assignments")
212+
expect(result.output).toContain("alice@corp.com | ANALYST | SECURITYADMIN")
213+
expect(result.output).toContain("bob@corp.com | DBA | ACCOUNTADMIN")
214+
})
215+
216+
test("uses fallback aliases (user_name, role_name, grantor)", async () => {
217+
mockDispatcher({
218+
"finops.user_roles": {
219+
success: true,
220+
assignment_count: 1,
221+
assignments: [
222+
{ user_name: "charlie", role_name: "READER", grantor: "ADMIN" },
223+
],
224+
},
225+
})
226+
227+
const tool = await FinopsUserRolesTool.init()
228+
const result = await tool.execute({ warehouse: "test_wh", limit: 100 }, ctx as any)
229+
230+
// Falls back to r.user_name (via user fallback chain), r.role_name, r.grantor
231+
expect(result.output).toContain("charlie | READER | ADMIN")
232+
})
233+
234+
test("handles empty assignments", async () => {
235+
mockDispatcher({
236+
"finops.user_roles": {
237+
success: true,
238+
assignment_count: 0,
239+
assignments: [],
240+
},
241+
})
242+
243+
const tool = await FinopsUserRolesTool.init()
244+
const result = await tool.execute({ warehouse: "test_wh", limit: 100 }, ctx as any)
245+
246+
expect(result.output).toContain("No user role assignments found")
247+
})
248+
})

0 commit comments

Comments
 (0)