Skip to content

Commit 4acb5c3

Browse files
refactor: Simplify AbstractExecutionService (#3396)
Remove the extra abstraction for "jobs" in the execution service. Instead, just map each Snap ID to one job. Additionally stop storing an RPC hook for each job as it is unnecessary. Also make all properties hash private and remove some dead branches that were untested and not reachable in practice
1 parent ab98e6f commit 4acb5c3

File tree

9 files changed

+210
-344
lines changed

9 files changed

+210
-344
lines changed
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"branches": 93.68,
3-
"functions": 98.17,
4-
"lines": 98.51,
5-
"statements": 98.35
2+
"branches": 94.41,
3+
"functions": 98.4,
4+
"lines": 98.68,
5+
"statements": 98.52
66
}

packages/snaps-controllers/src/services/AbstractExecutionService.test.ts

Lines changed: 28 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -16,95 +16,25 @@ class MockExecutionService extends NodeThreadExecutionService {
1616
initTimeout: inMilliseconds(5, Duration.Second),
1717
});
1818
}
19-
20-
getJobs() {
21-
return this.jobs;
22-
}
2319
}
2420

2521
describe('AbstractExecutionService', () => {
2622
afterEach(() => {
2723
jest.restoreAllMocks();
2824
});
2925

30-
it('logs error for unrecognized notifications', async () => {
31-
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
32-
33-
const { service } = createService(MockExecutionService);
34-
35-
await service.executeSnap({
36-
snapId: 'TestSnap',
37-
sourceCode: `
38-
module.exports.onRpcRequest = () => null;
39-
`,
40-
endowments: [],
41-
});
42-
43-
const { streams } = service.getJobs().values().next().value;
44-
streams.command.emit('data', {
45-
jsonrpc: '2.0',
46-
method: 'foo',
47-
});
48-
49-
await service.terminateAllSnaps();
50-
51-
expect(consoleErrorSpy).toHaveBeenCalledTimes(1);
52-
expect(consoleErrorSpy).toHaveBeenCalledWith(
53-
new Error(`Received unexpected command stream notification "foo".`),
54-
);
55-
});
56-
57-
it('logs error for malformed UnhandledError notification', async () => {
58-
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
59-
60-
const { service } = createService(MockExecutionService);
61-
62-
await service.executeSnap({
63-
snapId: 'TestSnap',
64-
sourceCode: `
65-
module.exports.onRpcRequest = () => null;
66-
`,
67-
endowments: [],
68-
});
69-
70-
const { streams } = service.getJobs().values().next().value;
71-
streams.command.emit('data', {
72-
jsonrpc: '2.0',
73-
method: 'UnhandledError',
74-
params: [2],
75-
});
76-
77-
streams.command.emit('data', {
78-
jsonrpc: '2.0',
79-
method: 'UnhandledError',
80-
params: { error: null },
81-
});
82-
83-
await service.terminateAllSnaps();
84-
85-
const expectedError = new Error(
86-
`Received malformed "UnhandledError" command stream notification.`,
87-
);
88-
expect(consoleErrorSpy).toHaveBeenCalledTimes(2);
89-
expect(consoleErrorSpy).toHaveBeenNthCalledWith(1, expectedError);
90-
expect(consoleErrorSpy).toHaveBeenNthCalledWith(2, expectedError);
91-
});
92-
9326
it('throws an error if RPC request handler is unavailable', async () => {
9427
const { service } = createService(MockExecutionService);
95-
const snapId = 'TestSnap';
9628
await expect(
97-
service.handleRpcRequest(snapId, {
29+
service.handleRpcRequest(MOCK_SNAP_ID, {
9830
origin: 'foo.com',
9931
handler: HandlerType.OnRpcRequest,
10032
request: {
10133
id: 6,
10234
method: 'bar',
10335
},
10436
}),
105-
).rejects.toThrow(
106-
`Snap execution service returned no RPC handler for running snap "${snapId}".`,
107-
);
37+
).rejects.toThrow(`"${MOCK_SNAP_ID}" is not currently running.`);
10838
});
10939

11040
it('throws an error if execution environment fails to respond to ping', async () => {
@@ -164,4 +94,30 @@ describe('AbstractExecutionService', () => {
16494
}),
16595
).rejects.toThrow(`${MOCK_SNAP_ID} failed to start.`);
16696
});
97+
98+
it('throws an error if the Snap is already running when trying to execute', async () => {
99+
const { service } = createService(MockExecutionService);
100+
101+
await service.executeSnap({
102+
snapId: MOCK_SNAP_ID,
103+
sourceCode: `module.exports.onRpcRequest = () => {};`,
104+
endowments: [],
105+
});
106+
107+
await expect(
108+
service.executeSnap({
109+
snapId: MOCK_SNAP_ID,
110+
sourceCode: `module.exports.onRpcRequest = () => {};`,
111+
endowments: [],
112+
}),
113+
).rejects.toThrow(`"${MOCK_SNAP_ID}" is already running.`);
114+
});
115+
116+
it('throws an error if the Snap is not running when attempted to be terminated', async () => {
117+
const { service } = createService(MockExecutionService);
118+
119+
await expect(service.terminateSnap(MOCK_SNAP_ID)).rejects.toThrow(
120+
`"${MOCK_SNAP_ID}" is not currently running.`,
121+
);
122+
});
167123
});

0 commit comments

Comments
 (0)