mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-08-17 12:18:31 -07:00
test(dictionary): pin concurrent snapshot writers to one surviving snapshot
Give each concurrent writer a distinct title, length, and term text so the assertion identifies which writer's snapshot survived instead of only checking that the file parses with the expected entry count.
This commit is contained in:
@@ -3,6 +3,7 @@ import * as fs from 'fs';
|
|||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import test from 'node:test';
|
import test from 'node:test';
|
||||||
|
import { isDeepStrictEqual } from 'node:util';
|
||||||
import { getSnapshotPath, readSnapshot, writeSnapshot } from './cache';
|
import { getSnapshotPath, readSnapshot, writeSnapshot } from './cache';
|
||||||
import { CHARACTER_DICTIONARY_FORMAT_VERSION } from './constants';
|
import { CHARACTER_DICTIONARY_FORMAT_VERSION } from './constants';
|
||||||
import type { CharacterDictionarySnapshot } from './types';
|
import type { CharacterDictionarySnapshot } from './types';
|
||||||
@@ -46,31 +47,46 @@ test('concurrent writeSnapshot calls for the same media leave one complete snaps
|
|||||||
const outputDir = makeTempDir();
|
const outputDir = makeTempDir();
|
||||||
const snapshotPath = getSnapshotPath(outputDir, 130298);
|
const snapshotPath = getSnapshotPath(outputDir, 130298);
|
||||||
const base = createSnapshot();
|
const base = createSnapshot();
|
||||||
const wide: CharacterDictionarySnapshot = {
|
// Distinct titles, lengths, and term text so the surviving file can be pinned to exactly one
|
||||||
...base,
|
// writer rather than merely "a snapshot that parses". A shared temp file is caught by the
|
||||||
entryCount: 400,
|
// losing writers failing to rename; interleaved content is only caught when the timing happens
|
||||||
termEntries: Array.from({ length: 400 }, (_entry, index) => [
|
// to leave a mix, which is why the assertion checks identity rather than shape.
|
||||||
`名前${index}`,
|
const variants: CharacterDictionarySnapshot[] = ['alpha', 'beta', 'gamma'].map((label, index) => {
|
||||||
'なまえ',
|
const entryCount = 400 + index * 100;
|
||||||
'name primary',
|
return {
|
||||||
'',
|
...base,
|
||||||
75,
|
mediaTitle: `${base.mediaTitle} ${label}`,
|
||||||
[`Character ${index}`.repeat(200)],
|
entryCount,
|
||||||
0,
|
termEntries: Array.from({ length: entryCount }, (_entry, entryIndex) => [
|
||||||
'',
|
`${label}${entryIndex}`,
|
||||||
]) as CharacterDictionarySnapshot['termEntries'],
|
'なまえ',
|
||||||
};
|
'name primary',
|
||||||
|
'',
|
||||||
|
75,
|
||||||
|
[`${label} character ${entryIndex} `.repeat(600)],
|
||||||
|
0,
|
||||||
|
'',
|
||||||
|
]) as CharacterDictionarySnapshot['termEntries'],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all(variants.map((variant) => writeSnapshot(snapshotPath, variant)));
|
||||||
writeSnapshot(snapshotPath, wide),
|
|
||||||
writeSnapshot(snapshotPath, wide),
|
|
||||||
writeSnapshot(snapshotPath, wide),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const restored = await readSnapshot(snapshotPath);
|
const restored = await readSnapshot(snapshotPath);
|
||||||
assert.equal(restored?.entryCount, 400);
|
const expected = variants.map((variant) => ({
|
||||||
assert.equal(restored?.termEntries.length, 400);
|
...variant,
|
||||||
assert.deepEqual(restored, { ...wide, nameSplitSource: 'heuristic' });
|
nameSplitSource: 'heuristic' as const,
|
||||||
|
}));
|
||||||
|
const matches = expected.filter((candidate) => isDeepStrictEqual(restored, candidate));
|
||||||
|
assert.equal(
|
||||||
|
matches.length,
|
||||||
|
1,
|
||||||
|
`expected exactly one writer's complete snapshot to survive, got ${
|
||||||
|
restored === null
|
||||||
|
? 'an unreadable file'
|
||||||
|
: `entryCount=${restored.entryCount}, terms=${restored.termEntries.length}, title=${restored.mediaTitle}`
|
||||||
|
}`,
|
||||||
|
);
|
||||||
|
|
||||||
// Every writer cleaned up after itself, so no temp files are left behind.
|
// Every writer cleaned up after itself, so no temp files are left behind.
|
||||||
const leftovers = fs
|
const leftovers = fs
|
||||||
|
|||||||
Reference in New Issue
Block a user