mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-29 12:11:09 +00:00
test(core): cache reset hooks + regression-guards from audit
Self-review pass on the previous two perf commits surfaced a few
follow-ups worth pinning down before they bite:
- Module-level caches (paths.isDirectoryCache, ripGrep dirIsDir/qwen-
Ignore, jsonl-utils.ensuredDirs) persisted across vitest cases
silently. Added underscore-prefixed `_reset*ForTest` exports and
wired one into the validatePath describe block so future cases
mutating the same absolute paths can't pass by accident.
- Documented the parentUuid-chain tradeoff on chatRecordingService
.appendRecord: when the async write rejects, lastRecordUuid was
already set sync, so subsequent records reference an absent
ancestor — readers like sessionService.reconstructHistory then
silently drop those descendants. Same observable failure mode as
the prior sync code's caught-and-logged throw.
- Documented the dir<->file mutation and mid-session .qwenignore
staleness windows for the validatePath / ripGrep caches.
- Added regression tests:
* validatePath does NOT cache ENOENT (Edit-then-Read works)
* validatePath skips re-stat on cache hit (perf assertion)
* flush() resolves immediately on a fresh service
* a rejected writeLine does not block the next record
Full core suite: 6061 pass, 2 skipped — no regressions.
This commit is contained in:
parent
8fa7f4c498
commit
d6485964c3
6 changed files with 121 additions and 4 deletions
|
|
@ -7,7 +7,15 @@
|
|||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { describe, it, expect, beforeAll, afterAll, vi } from 'vitest';
|
||||
import {
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeAll,
|
||||
beforeEach,
|
||||
afterAll,
|
||||
vi,
|
||||
} from 'vitest';
|
||||
import {
|
||||
escapePath,
|
||||
resolvePath,
|
||||
|
|
@ -18,6 +26,7 @@ import {
|
|||
shortenPath,
|
||||
tildeifyPath,
|
||||
getProjectHash,
|
||||
_resetValidatePathCacheForTest,
|
||||
} from './paths.js';
|
||||
import type { Config } from '../config/config.js';
|
||||
|
||||
|
|
@ -431,6 +440,14 @@ describe('validatePath', () => {
|
|||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// Module-level isDirectory cache persists across tests; tests here
|
||||
// mutate the same absolute paths between cases (create file, remove,
|
||||
// re-create as potentially-different type) so we reset to avoid stale
|
||||
// lookups masking regressions.
|
||||
_resetValidatePathCacheForTest();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
fs.rmSync(workspaceRoot, { recursive: true, force: true });
|
||||
});
|
||||
|
|
@ -482,6 +499,36 @@ describe('validatePath', () => {
|
|||
expect(() => validatePath(config, workspaceRoot)).not.toThrow();
|
||||
});
|
||||
|
||||
it('does not cache ENOENT — recreating the path between calls succeeds', () => {
|
||||
// Regression guard: a path that's missing at first-check, then created,
|
||||
// must NOT be rejected on the second call. Positive stats are cached;
|
||||
// ENOENT paths are not. This lets the model create a file with Edit
|
||||
// and then have the next tool call see it.
|
||||
const ephemeralDir = path.join(workspaceRoot, 'late-created');
|
||||
expect(() => validatePath(config, ephemeralDir)).toThrowError(
|
||||
/Path does not exist:/,
|
||||
);
|
||||
fs.mkdirSync(ephemeralDir);
|
||||
try {
|
||||
expect(() => validatePath(config, ephemeralDir)).not.toThrow();
|
||||
} finally {
|
||||
fs.rmSync(ephemeralDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it('caches positive isDirectory — repeat call does not re-stat', () => {
|
||||
const spy = vi.spyOn(fs, 'statSync');
|
||||
const dir = path.join(workspaceRoot, 'subdir');
|
||||
try {
|
||||
validatePath(config, dir);
|
||||
const afterFirst = spy.mock.calls.length;
|
||||
validatePath(config, dir);
|
||||
expect(spy.mock.calls.length).toBe(afterFirst);
|
||||
} finally {
|
||||
spy.mockRestore();
|
||||
}
|
||||
});
|
||||
|
||||
it('validates paths in allowed directories', () => {
|
||||
const extraDir = fs.mkdtempSync(path.join(os.tmpdir(), 'validate-extra-'));
|
||||
try {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue