release-macos-lifecycle.test.mjs
78 lines 2.8 KB
Raw
sha256:bd1eb24434d281fe65142038c1bf217493421f5a86880c22dff7e6037d2d4700 feat(companion): add production macOS distribution path Human minor ⚠ breaking 24 days ago
1 import assert from 'node:assert/strict';
2 import { EventEmitter } from 'node:events';
3 import fs from 'node:fs/promises';
4 import os from 'node:os';
5 import path from 'node:path';
6 import test from 'node:test';
7
8 import { startAppRuntime } from '../companion/runtime/app-runtime.mjs';
9
10 function fakeWorker() {
11 const worker = new EventEmitter();
12 worker.killedWith = null;
13 worker.kill = (signal) => { worker.killedWith = signal; };
14 worker.send = () => {};
15 worker.once('newListener', (event) => {
16 if (event === 'message') queueMicrotask(() => worker.emit('message', { ready: true }));
17 });
18 return worker;
19 }
20
21 test('app runtime publishes state and removes capability and state on close', async () => {
22 const stateDirectory = await fs.mkdtemp(path.join(os.tmpdir(), 'knowtation-lifecycle-'));
23 const store = new Map();
24 const custody = {
25 set: async (key, value) => store.set(key, value),
26 delete: async (key) => store.delete(key),
27 };
28 const worker = fakeWorker();
29 let listenerClosed = false;
30 const runtime = await startAppRuntime({
31 custody,
32 runtimeRoot: '/fixed/runtime',
33 stateDirectory,
34 spawnWorker: () => worker,
35 listenerFactory: ({ expectedToken }) => ({
36 start: async () => {
37 assert.equal(expectedToken, store.get('knowtation.companion.loopbackToken'));
38 return { host: '127.0.0.1', port: 43123 };
39 },
40 close: async () => { listenerClosed = true; },
41 }),
42 });
43 const stateFile = path.join(stateDirectory, 'companion.json');
44 const state = JSON.parse(await fs.readFile(stateFile, 'utf8'));
45 assert.deepEqual({ host: state.host, port: state.port }, { host: '127.0.0.1', port: 43123 });
46 assert.ok(store.has('knowtation.companion.loopbackToken'));
47
48 await runtime.close();
49 await runtime.close();
50 assert.equal(listenerClosed, true);
51 assert.equal(worker.killedWith, 'SIGTERM');
52 assert.equal(store.has('knowtation.companion.loopbackToken'), false);
53 await assert.rejects(fs.access(stateFile));
54 await fs.rm(stateDirectory, { recursive: true, force: true });
55 });
56
57 test('failed startup revokes the capability and terminates the worker', async () => {
58 const stateDirectory = await fs.mkdtemp(path.join(os.tmpdir(), 'knowtation-lifecycle-fail-'));
59 const store = new Map();
60 const custody = {
61 set: async (key, value) => store.set(key, value),
62 delete: async (key) => store.delete(key),
63 };
64 const worker = fakeWorker();
65 await assert.rejects(startAppRuntime({
66 custody,
67 runtimeRoot: '/fixed/runtime',
68 stateDirectory,
69 spawnWorker: () => worker,
70 listenerFactory: () => ({
71 start: async () => { throw new Error('listener_failed'); },
72 close: async () => {},
73 }),
74 }), /listener_failed/);
75 assert.equal(worker.killedWith, 'SIGTERM');
76 assert.equal(store.has('knowtation.companion.loopbackToken'), false);
77 await fs.rm(stateDirectory, { recursive: true, force: true });
78 });
File History 1 commit
sha256:bd1eb24434d281fe65142038c1bf217493421f5a86880c22dff7e6037d2d4700 feat(companion): add production macOS distribution path Human minor ⚠ 24 days ago