0.1.9
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { join } from "node:path";
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import { DiskRecordsCache, diskCacheKey } from "../out/indexer/diskCache.js";
|
||||
|
||||
const identity = {
|
||||
projectDir: "C:/proj",
|
||||
sdkDir: "C:/sdk",
|
||||
indexSageXml: true,
|
||||
additionalDataSearchPaths: [],
|
||||
builtmodsDirs: ["C:/sdk/builtmods"],
|
||||
};
|
||||
|
||||
const sampleRecords = {
|
||||
assets: [{ type: "GameObject", id: "TankA", line: 3 }],
|
||||
defines: [{ name: "HP", value: "100", line: 2 }],
|
||||
includes: [{ type: "all", source: "Units.xml", line: 4 }],
|
||||
rootXiIncludes: [],
|
||||
nestedXiIncludes: [],
|
||||
};
|
||||
|
||||
function stampOf(file) {
|
||||
const s = fs.statSync(file);
|
||||
return {
|
||||
mtimeMs: s.mtimeMs,
|
||||
size: s.size,
|
||||
birthtimeMs: s.birthtimeMs,
|
||||
ctimeMs: s.ctimeMs,
|
||||
};
|
||||
}
|
||||
|
||||
function makeTmp(t) {
|
||||
const tmp = fs.mkdtempSync(join(os.tmpdir(), "ra3-diskcache-"));
|
||||
t.after(() => fs.rmSync(tmp, { recursive: true, force: true }));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
test("disk cache roundtrip keeps records and leaves no temp file", async (t) => {
|
||||
const tmp = makeTmp(t);
|
||||
const file = join(tmp, "a.xml");
|
||||
fs.writeFileSync(file, "0123456789");
|
||||
const filePath = join(tmp, "index-records.json.gz");
|
||||
const cache = new DiskRecordsCache(filePath, identity);
|
||||
|
||||
await cache.save([
|
||||
[
|
||||
file.toLowerCase(),
|
||||
{ stat: stampOf(file), records: sampleRecords, kind: "full" },
|
||||
],
|
||||
]);
|
||||
assert.equal(fs.existsSync(`${filePath}.tmp`), false, "atomic write leaves no temp");
|
||||
|
||||
const { records, stats } = await cache.loadValidated();
|
||||
assert.equal(stats.fileExists, true);
|
||||
assert.equal(stats.keyMatched, true);
|
||||
assert.equal(stats.loaded, 1);
|
||||
assert.equal(stats.validated, 1);
|
||||
assert.equal(stats.dropped, 0);
|
||||
assert.equal(records.length, 1);
|
||||
assert.deepEqual(records[0].records, sampleRecords);
|
||||
});
|
||||
|
||||
test("stat mismatch drops the cached entry", async (t) => {
|
||||
const tmp = makeTmp(t);
|
||||
const file = join(tmp, "a.xml");
|
||||
fs.writeFileSync(file, "0123456789");
|
||||
const filePath = join(tmp, "index-records.json.gz");
|
||||
const cache = new DiskRecordsCache(filePath, identity);
|
||||
await cache.save([
|
||||
[file.toLowerCase(), { stat: stampOf(file), records: sampleRecords, kind: "full" }],
|
||||
]);
|
||||
|
||||
const past = new Date(Date.now() - 60000);
|
||||
fs.utimesSync(file, past, past);
|
||||
const { records, stats } = await cache.loadValidated();
|
||||
assert.equal(stats.validated, 0);
|
||||
assert.equal(stats.dropped, 1);
|
||||
assert.equal(records.length, 0);
|
||||
});
|
||||
|
||||
test("identity mismatch ignores the cache", async (t) => {
|
||||
const tmp = makeTmp(t);
|
||||
const file = join(tmp, "a.xml");
|
||||
fs.writeFileSync(file, "0123456789");
|
||||
const filePath = join(tmp, "index-records.json.gz");
|
||||
const cache = new DiskRecordsCache(filePath, identity);
|
||||
await cache.save([
|
||||
[file.toLowerCase(), { stat: stampOf(file), records: sampleRecords, kind: "full" }],
|
||||
]);
|
||||
|
||||
const other = new DiskRecordsCache(filePath, {
|
||||
...identity,
|
||||
sdkDir: "D:/other-sdk",
|
||||
});
|
||||
const { records, stats } = await other.loadValidated();
|
||||
assert.equal(stats.fileExists, true);
|
||||
assert.equal(stats.keyMatched, false);
|
||||
assert.equal(records.length, 0);
|
||||
});
|
||||
|
||||
test("corrupt cache file yields an empty result", async (t) => {
|
||||
const tmp = makeTmp(t);
|
||||
const filePath = join(tmp, "index-records.json.gz");
|
||||
fs.writeFileSync(filePath, "this is not gzip json");
|
||||
const cache = new DiskRecordsCache(filePath, identity);
|
||||
const { records, stats } = await cache.loadValidated();
|
||||
assert.equal(stats.fileExists, true);
|
||||
assert.equal(records.length, 0);
|
||||
});
|
||||
|
||||
test("clear removes the cache file", async (t) => {
|
||||
const tmp = makeTmp(t);
|
||||
const file = join(tmp, "a.xml");
|
||||
fs.writeFileSync(file, "0123456789");
|
||||
const filePath = join(tmp, "index-records.json.gz");
|
||||
const cache = new DiskRecordsCache(filePath, identity);
|
||||
await cache.save([
|
||||
[file.toLowerCase(), { stat: stampOf(file), records: sampleRecords, kind: "full" }],
|
||||
]);
|
||||
assert.ok(fs.existsSync(filePath));
|
||||
await cache.clear();
|
||||
assert.equal(fs.existsSync(filePath), false);
|
||||
});
|
||||
|
||||
test("diskCacheKey differs when the identity changes", () => {
|
||||
const a = diskCacheKey(identity);
|
||||
const b = diskCacheKey({ ...identity, indexSageXml: false });
|
||||
assert.notEqual(a, b);
|
||||
assert.equal(a, diskCacheKey(identity));
|
||||
});
|
||||
Reference in New Issue
Block a user