Repository navigation
Expand file tree
/
Copy pathIpcFixtureFile.test.ts
More file actions
157 lines (144 loc) · 6.59 KB
/
Copy pathIpcFixtureFile.test.ts
File metadata and controls
157 lines (144 loc) · 6.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.
import { spawnSync, type SpawnSyncReturns } from 'node:child_process';
import * as fs from 'node:fs';
import * as os from 'node:os';
import * as path from 'node:path';
import { readIpcFixtureEvents, readPressureGateAsync, writeIpcFixtureFile } from './IpcFixtureFile';
const filesystem: typeof fs = jest.requireActual('node:fs');
describe('IPC fixture file publication', () => {
let directory: string;
beforeEach(() => {
directory = fs.mkdtempSync(path.join(os.tmpdir(), 'ipc-publication-'));
});
afterEach(() => {
jest.restoreAllMocks();
fs.rmSync(directory, { recursive: true, force: true });
});
it.each([
['allocate.json', '{"additionalMemoryBytes":123}'],
['allocate.json.adjust', '{"additionalMemoryBytes":456}'],
['allocate.json.release', '{}'],
['cancel.json', '{"cancelled":true}'],
['cancel.json.adjust', '{"cancelled":true}'],
['cancel.json.release', '{"cancelled":true}'],
['run-input.json', '{"value":"next-request"}']
])('hides incomplete %s from a separate reader until its closed payload is published', (name, contents) => {
const filename: string = path.join(directory, name);
const write: typeof fs.writeFileSync = fs.writeFileSync;
const rename: typeof fs.renameSync = fs.renameSync;
let descriptor: number | undefined;
let reader: SpawnSyncReturns<string> | undefined;
jest.spyOn(filesystem, 'writeFileSync').mockImplementationOnce((target, data, options) => {
if (typeof target === 'number') {
descriptor = target;
fs.writeSync(target, '{');
} else {
write(target, '{', options);
}
reader = spawnSync(
process.execPath,
[
'-e',
"const fs=require('node:fs');const file=process.argv[1];" +
"console.log(fs.existsSync(file)?JSON.stringify(JSON.parse(fs.readFileSync(file,'utf8'))):'pending');",
filename
],
{ encoding: 'utf8' }
);
if (typeof target === 'number') {
fs.ftruncateSync(target, 0);
fs.writeSync(target, String(data), 0, 'utf8');
} else {
write(target, data, options);
}
});
jest.spyOn(filesystem, 'renameSync').mockImplementationOnce((from, to) => {
if (descriptor !== undefined) {
expect(() => fs.fstatSync(descriptor!)).toThrow(expect.objectContaining({ code: 'EBADF' }));
}
rename(from, to);
});
writeIpcFixtureFile(filename, contents);
expect(reader?.error).toBeUndefined();
expect(reader?.status).toBe(0);
expect(reader?.stdout.trim()).toBe('pending');
expect(JSON.parse(fs.readFileSync(filename, 'utf8'))).toEqual(JSON.parse(contents));
expect(fs.readdirSync(directory)).toEqual([name]);
});
it('keeps a previous complete input visible until its replacement is complete', () => {
const filename: string = path.join(directory, 'input.json');
writeIpcFixtureFile(filename, '{"value":"old"}');
const write: typeof fs.writeFileSync = fs.writeFileSync;
let observed: unknown;
jest.spyOn(filesystem, 'writeFileSync').mockImplementationOnce((target, contents, options) => {
observed = JSON.parse(fs.readFileSync(filename, 'utf8'));
write(target, contents, options);
});
writeIpcFixtureFile(filename, '{"value":"new"}');
expect(observed).toEqual({ value: 'old' });
expect(JSON.parse(fs.readFileSync(filename, 'utf8'))).toEqual({ value: 'new' });
});
it.each(['write', 'rename'])('cleans only its own staging file after a %s failure', (failurePoint) => {
const sentinel: string = path.join(directory, '.other-writer.tmp');
fs.writeFileSync(sentinel, 'owned by another publisher');
const filename: string = path.join(directory, 'gate.json');
const failure: Error = new Error('publication failed');
if (failurePoint === 'write') {
jest.spyOn(filesystem, 'writeFileSync').mockImplementationOnce(() => {
throw failure;
});
} else {
jest.spyOn(filesystem, 'renameSync').mockImplementationOnce(() => {
throw failure;
});
}
expect(() => writeIpcFixtureFile(filename, '{}')).toThrow(failure);
expect(fs.readdirSync(directory)).toEqual(['.other-writer.tmp']);
expect(fs.readFileSync(sentinel, 'utf8')).toBe('owned by another publisher');
});
it.each(['pressure-ready', 'pressure-allocated', 'pressure-adjusted'])(
'does not publish a partial %s frame or substitute a previous request sample',
(kind) => {
const filename: string = path.join(directory, 'events.jsonl');
const previous = { kind, pressureGate: 'previous-request', residentMemoryBytes: 1 };
const current = { kind, pressureGate: 'current-request', residentMemoryBytes: 2 };
const contents: string = JSON.stringify(current);
fs.writeFileSync(filename, `${JSON.stringify(previous)}\n${contents.slice(0, 10)}`);
expect(readIpcFixtureEvents(filename)).toEqual([previous]);
fs.appendFileSync(filename, `${contents.slice(10)}\n`);
expect(readIpcFixtureEvents(filename)).toEqual([previous, current]);
}
);
it('surfaces malformed complete event frames instead of ignoring or retrying them', () => {
const filename: string = path.join(directory, 'events.jsonl');
fs.writeFileSync(filename, '{"kind":}\n');
expect(() => readIpcFixtureEvents(filename)).toThrow(SyntaxError);
});
it('surfaces malformed published gate JSON and cancellation immediately', async () => {
const filename: string = path.join(directory, 'gate.json');
writeIpcFixtureFile(filename, '{');
await expect(readPressureGateAsync(filename, performance.now() + 10000)).rejects.toThrow(SyntaxError);
writeIpcFixtureFile(filename, '{"cancelled":true}');
await expect(readPressureGateAsync(filename, performance.now() + 10000)).rejects.toThrow(
'Pressure fixture setup was cancelled.'
);
});
it('does not let an old completed phase release a new request', async () => {
writeIpcFixtureFile(path.join(directory, 'old-request.release'), '{}');
const filename: string = path.join(directory, 'new-request.release');
let settled: boolean = false;
const reading: Promise<unknown> = readPressureGateAsync(filename, performance.now() + 10000).finally(
() => {
settled = true;
}
);
const rejected: Promise<void> = expect(reading).rejects.toThrow('Pressure fixture setup was cancelled.');
try {
expect(settled).toBe(false);
} finally {
writeIpcFixtureFile(filename, '{"cancelled":true}');
await rejected;
}
});
});