test: id — Identifier generation, ordering, and timestamp extraction#400
test: id — Identifier generation, ordering, and timestamp extraction#400anandgupta42 wants to merge 1 commit intomainfrom
Conversation
The Identifier module generates monotonic IDs for every session, message, part, and permission. Zero tests existed. Covers ascending/descending ordering, prefix validation, and documents the 48-bit timestamp overflow behavior. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> https://claude.ai/code/session_012maTw3RYyvmA13VfxTeYpJ
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review to trigger a review.
Tip: disable this comment in your organization's Code Review settings.
📝 WalkthroughWalkthroughA new test suite for the Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
packages/opencode/test/id/id.test.ts (2)
39-51: Consider adding passthrough test for descending.The ascending tests include coverage for the given ID passthrough behavior (lines 19-36), but descending tests don't cover this scenario. Since both use the same underlying
generateIDfunction, adding a similar test would ensure consistent behavior.📝 Optional: Add passthrough test
test("generates monotonically decreasing IDs", () => { const ids = Array.from({ length: 100 }, () => Identifier.descending("session")) for (let i = 1; i < ids.length; i++) { expect(ids[i] < ids[i - 1]).toBe(true) } }) + + test("returns given ID when prefix matches", () => { + const given = "ses_abc123" + const id = Identifier.descending("session", given) + expect(id).toBe(given) + }) })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/opencode/test/id/id.test.ts` around lines 39 - 51, Add a passthrough test for Identifier.descending similar to the ascending passthrough coverage: call Identifier.descending with an already-formed ID string (e.g., one that matches the "ses_" prefix used elsewhere) and assert it returns the input unchanged; target the Identifier.descending function (which delegates to generateID) to ensure the same passthrough behavior is exercised as in the ascending tests.
84-89: Consider improving type safety in the loop.The
as anycast works but loses type safety. The type can be improved by explicitly typing the array elements.📝 Optional: Improve typing
- const prefixes = [ + const prefixes: Array<[keyof typeof import("../../src/id/id").Identifier extends { ascending: (k: infer K) => any } ? K : never, string]> = [ ["session", "ses_"], ... ] as const for (const [key, prefix] of prefixes) { - test(`${key} generates IDs starting with ${prefix}`, () => { - const id = Identifier.ascending(key as any) + test(`${key} generates IDs starting with ${prefix}`, () => { + const id = Identifier.ascending(key) expect(id).toStartWith(prefix) }) }Alternatively, a simpler approach using type assertion at the array level:
type PrefixKey = Parameters<typeof Identifier.ascending>[0] const prefixes: [PrefixKey, string][] = [ ["session", "ses_"], // ... ]🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/opencode/test/id/id.test.ts` around lines 84 - 89, The test loop uses an unsafe cast `key as any` when calling Identifier.ascending; instead, tighten types by declaring the prefixes array with an explicit tuple element type that matches Identifier.ascending's first parameter (e.g., create a type alias like PrefixKey = Parameters<typeof Identifier.ascending>[0] and type prefixes as [PrefixKey, string][] or otherwise type each array element), then remove the `as any` cast and pass the properly typed `key` to Identifier.ascending.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@packages/opencode/test/id/id.test.ts`:
- Around line 39-51: Add a passthrough test for Identifier.descending similar to
the ascending passthrough coverage: call Identifier.descending with an
already-formed ID string (e.g., one that matches the "ses_" prefix used
elsewhere) and assert it returns the input unchanged; target the
Identifier.descending function (which delegates to generateID) to ensure the
same passthrough behavior is exercised as in the ascending tests.
- Around line 84-89: The test loop uses an unsafe cast `key as any` when calling
Identifier.ascending; instead, tighten types by declaring the prefixes array
with an explicit tuple element type that matches Identifier.ascending's first
parameter (e.g., create a type alias like PrefixKey = Parameters<typeof
Identifier.ascending>[0] and type prefixes as [PrefixKey, string][] or otherwise
type each array element), then remove the `as any` cast and pass the properly
typed `key` to Identifier.ascending.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 148e5749-5d05-4bd2-95ed-d426504be1ce
📒 Files selected for processing (1)
packages/opencode/test/id/id.test.ts
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>
|
Consolidated into #403 |
* 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> * fix: address code review findings — test artifact leakage and cleanup - summary-git-path.test.ts: use tmpdir() instead of projectRoot to prevent Storage.write() from polluting the developer's .opencode/storage/ directory - finops-role-access.test.ts: consolidate duplicate afterAll hooks to ensure ALTIMATE_TELEMETRY_DISABLED env var is cleaned up after tests Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
What does this PR do?
Adds the first test coverage for the
Identifiermodule (src/id/id.ts), which is the core ID generation system used by every session, message, part, permission, and workspace in altimate-code. Previously had zero tests.1.
Identifier.ascendingandIdentifier.descending—src/id/id.ts(7 new tests)This module generates monotonic, lexicographically-sortable IDs that power message ordering, session listing, and data integrity throughout the system. Zero tests existed. New coverage includes:
2.
Identifier.timestamp—src/id/id.ts(2 new tests)The
timestamp()function extracts creation time from ascending IDs, used intool/truncation.tsfor age-based cleanup. Testing revealed that absolute timestamp extraction overflows for modern timestamps (the 6-byte / 48-bit encoding can't holdDate.now() * 0x1000), but relative comparisons between IDs created in the same era work correctly — which is exactly how the codebase uses it. Tests document this behavior:Discovery: 48-bit timestamp overflow
During testing, discovered that
Identifier.timestamp()silently overflows for current-era timestamps. The encoding storests * 0x1000in 48 bits, but modern timestamps exceed 2^36 ms (~1972). This doesn't affect production because the only caller (tool/truncation.ts) uses it for relative age comparisons where both sides overflow identically. Filed as a known behavior, not a blocking bug.Type of change
Issue for this PR
N/A — proactive test coverage for core infrastructure
How did you verify your code works?
Checklist
https://claude.ai/code/session_012maTw3RYyvmA13VfxTeYpJ
Summary by CodeRabbit