Skip to content

test(utils): add tests for misc, MemCache, and DiskCache#502

Merged
marcoscaceres merged 8 commits into
mainfrom
test/core-utils
May 4, 2026
Merged

test(utils): add tests for misc, MemCache, and DiskCache#502
marcoscaceres merged 8 commits into
mainfrom
test/core-utils

Conversation

@marcoscaceres

Copy link
Copy Markdown
Collaborator

Summary

  • 19 specs for env(), seconds(), ms(), HTTPError
  • 24 specs for MemCache (TTL, stale reads, getOr, invalidate)
  • 11 specs for DiskCache (persistence, path traversal guard)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds comprehensive Jasmine coverage for utility helpers and both cache implementations, strengthening regression protection around TTL behavior, persistence, and input validation.

Changes:

  • Add unit tests for env(), seconds(), ms(), and HTTPError.
  • Add behavioral tests for MemCache (TTL expiry, stale reads, getOr(), invalidate(), etc.).
  • Add integration-style tests for DiskCache (persistence across instances, TTL expiry/invalidation, and path traversal key rejection).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
tests/utils/misc.test.js New specs for misc utility helpers and HTTPError.
tests/utils/mem-cache.test.js New specs validating MemCache correctness across key behaviors.
tests/utils/disk-cache.test.js New specs validating DiskCache persistence, TTL behavior, and key/path safety checks.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/utils/disk-cache.test.js Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/utils/mem-cache.test.js Outdated
Comment thread tests/utils/disk-cache.test.js Outdated
Comment on lines +66 to +72
const cache = new DiskCache({ ttl: 1, path: "test-cache" });
await cache.set("key", "value");

// Wait briefly to ensure TTL expires
await new Promise(resolve => setTimeout(resolve, 10));
expect(await cache.get("key")).toBeUndefined();
});

Copilot AI Apr 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These TTL tests use real setTimeout sleeps to force expiry, which slows the suite and can be timing-sensitive. Consider stubbing Date.now() (or using a fake clock) to advance time deterministically and avoid waiting in tests.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid suggestion. The DiskCache TTL tests use real setTimeout(10ms) which is timing-dependent. Stubbing Date.now() would be more deterministic. However, with 10ms waits the flakiness risk is very low in practice, and DiskCache reads file mtimes from disk which adds complexity to mocking. Keeping as-is for now — can refactor to fake clocks as a follow-up if flakiness is observed.

Comment thread tests/utils/disk-cache.test.js Outdated
Comment on lines +85 to +94
const cache = new DiskCache({ ttl: 1, path: "test-cache" });
await cache.set("a", 1);
await cache.set("b", 2);

await new Promise(resolve => setTimeout(resolve, 10));
await cache.invalidate();

expect(await cache.get("a", true)).toBeUndefined();
expect(await cache.get("b", true)).toBeUndefined();
});

Copilot AI Apr 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above: relying on setTimeout(..., 10) to age entries makes the test slower and more timing-dependent than necessary. Stubbing Date.now()/using a fake clock would let you test invalidate() behavior without sleeping.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid suggestion. The DiskCache TTL tests use real setTimeout(10ms) which is timing-dependent. Stubbing Date.now() would be more deterministic. However, with 10ms waits the flakiness risk is very low in practice, and DiskCache reads file mtimes from disk which adds complexity to mocking. Keeping as-is for now — can refactor to fake clocks as a follow-up if flakiness is observed.

Comment thread tests/utils/disk-cache.test.js Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/utils/disk-cache.test.js Outdated
Comment on lines +88 to +90

await new Promise(resolve => setTimeout(resolve, 10));
await cache.invalidate();

Copilot AI Apr 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the TTL expiry tests, this setTimeout-based wait can introduce timing flakiness. Prefer stubbing Date.now() to move time forward, which keeps the test deterministic and avoids adding real delays to CI runs.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid suggestion. The DiskCache TTL tests use real setTimeout(10ms) which is timing-dependent. Stubbing Date.now() would be more deterministic. However, with 10ms waits the flakiness risk is very low in practice, and DiskCache reads file mtimes from disk which adds complexity to mocking. Keeping as-is for now — can refactor to fake clocks as a follow-up if flakiness is observed.

Comment thread tests/utils/disk-cache.test.js Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/utils/misc.test.js

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/utils/disk-cache.test.js Outdated
Comment thread tests/utils/disk-cache.test.js Outdated
Comment thread tests/utils/disk-cache.test.js

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/utils/disk-cache.test.js Outdated
Comment thread tests/utils/misc.test.js Outdated
Comment thread tests/utils/misc.test.js Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/utils/disk-cache.test.js
Comment thread tests/utils/misc.test.js

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/utils/disk-cache.test.js Outdated
Comment thread tests/utils/misc.test.js

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/utils/misc.test.js Outdated
Adds 54 new specs covering the three core utility modules:

- misc: env(), seconds(), ms(), HTTPError (19 specs)
- MemCache: set/get, TTL expiry, has, getOr, delete, clear,
  expires, invalidate (24 specs)
- DiskCache: set/get round-trip, TTL expiry, persistence across
  instances, invalidate, path traversal prevention (11 specs)
…shot

env() throws raw strings, not Error instances, so toThrow() can't
reliably match messages. Switch to try/catch with exact string assertion.
Reset savedEnv in beforeEach so each test tracks only its own keys.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

marcoscaceres and others added 2 commits April 27, 2026 18:13
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@marcoscaceres

Copy link
Copy Markdown
Collaborator Author

@copilot can you address any unaddressed concerns? O

marcoscaceres and others added 2 commits April 27, 2026 18:16
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…versal prefix bypass

- Remove orphaned describe("TTL expiry") + it() block (lines 65-75) that was
  never closed, causing "Unexpected end of input" syntax error at test load time
- Fix path-traversal prefix-bypass in DiskCache.keyToFilePath(): use
  `baseDir + path.sep` instead of bare `baseDir` so a key like
  `../test-cache-evil/pwn` cannot escape the cache directory
- Add test for the prefix-bypass scenario

Agent-Logs-Url: https://github.com/speced/respec-web-services/sessions/505fff65-5d3f-41b9-8488-88bfebd453bb

Co-authored-by: marcoscaceres <870154+marcoscaceres@users.noreply.github.com>

Copilot AI commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

@copilot can you address any unaddressed concerns? O

Addressed the remaining unresolved concerns in commit 7dbbe88:

  1. Syntax error in disk-cache.test.js — Removed the orphaned describe("TTL expiry") + it() block (lines 65-75) that was never closed, which caused an "Unexpected end of input" error and prevented the test suite from loading at all.

  2. Path-traversal prefix-bypass vulnerability — Fixed DiskCache.keyToFilePath() to use result.startsWith(baseDir + path.sep) instead of bare result.startsWith(baseDir). Without the separator, a key like ../test-cache-evil/pwn resolves to /tmp/test-cache-evil/pwn.json which falsely passes the old check (since "test-cache-evil" starts with "test-cache").

  3. Added prefix-bypass test — New spec "rejects prefix-bypass traversal (../test-cache-evil)" covers the exact scenario described in the review.

All 55 specs pass.

@marcoscaceres

Copy link
Copy Markdown
Collaborator Author

@copilot can you review this and fix any issues that come up?

- Set `tempDir = undefined` at the top of `beforeEach` so that a
  `mkdtemp` failure on a later run cannot accidentally reuse the
  previous test's directory in `afterEach`
- Wrap env-var restoration in `try { } finally { rm... }` so the
  temp directory is always cleaned up even if the env restoration
  step throws

Agent-Logs-Url: https://github.com/speced/respec-web-services/sessions/3c3383f4-458d-4aaf-8fc6-091cdefd4390

Co-authored-by: marcoscaceres <870154+marcoscaceres@users.noreply.github.com>
@marcoscaceres

Copy link
Copy Markdown
Collaborator Author

@copilot Can you confirm all your feedback has been addressed? Please resolve the threads that have been addressed and fix anything outstanding.

Copilot AI commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

@copilot Can you confirm all your feedback has been addressed? Please resolve the threads that have been addressed and fix anything outstanding.

All feedback has been addressed. Here's a summary of each open thread:

  • setTimeout vs fake clock (disk-cache threads on lines 66–72, 69–71, 75–79, 85–94, 88–90): The current code already uses spyOn(Date, "now").and.callFake(() => now) in a beforeEach — no real sleeps anywhere in TTL tests.
  • env var isolation (misc.test.js:18–44, 18–22): savedEnv = {} is reset in beforeEach and restored in afterEach; each test saves its own keys before mutating.
  • try/finally + tempDir guard (disk-cache.test.js:17–29): Fixed in 4a0bcd6tempDir = undefined at top of beforeEach, afterEach uses try/finally so cleanup always runs.
  • prefix-bypass path traversal (disk-cache.test.js:111–145): Fixed in 7dbbe88 — implementation uses startsWith(baseDir + path.sep) and a dedicated test covers the ../test-cache-evil bypass case.

All 55 specs pass. I can't resolve GitHub threads via these tools, but every concern in the open threads is addressed in the code.

@marcoscaceres
marcoscaceres marked this pull request as ready for review April 29, 2026 03:14
@marcoscaceres

Copy link
Copy Markdown
Collaborator Author

@copilot can you resolve the merge conflicts?

Copilot AI commented May 4, 2026

Copy link
Copy Markdown
Contributor

@copilot can you resolve the merge conflicts?

Resolved in commit b3f97d1. The only conflict was in tests/utils/misc.test.js — merged our env(), seconds(), ms(), and HTTPError tests with main's new getErrnoCode tests, and updated the import to include getErrnoCode. utils/disk-cache.ts auto-merged cleanly (main switched it to use getErrnoCode() instead of error.code). All 63 specs pass.

@marcoscaceres
marcoscaceres merged commit 3abb21d into main May 4, 2026
3 checks passed
@marcoscaceres
marcoscaceres deleted the test/core-utils branch May 4, 2026 13:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants