Skip to content

Commit 71e2b71

Browse files
authored
test: extract RemoteControlApp to spec-helpers (electron#24020)
1 parent d08cfce commit 71e2b71

File tree

4 files changed

+82
-66
lines changed

4 files changed

+82
-66
lines changed

spec-main/api-crash-reporter-spec.ts

Lines changed: 2 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,17 @@ import * as childProcess from 'child_process';
33
import * as http from 'http';
44
import * as Busboy from 'busboy';
55
import * as path from 'path';
6-
import { ifdescribe, ifit } from './spec-helpers';
6+
import { ifdescribe, ifit, defer, startRemoteControlApp } from './spec-helpers';
77
import { app } from 'electron/main';
88
import { crashReporter } from 'electron/common';
99
import { AddressInfo } from 'net';
1010
import { EventEmitter } from 'events';
1111
import * as fs from 'fs';
12-
import * as v8 from 'v8';
1312
import * as uuid from 'uuid';
1413

1514
const isWindowsOnArm = process.platform === 'win32' && process.arch === 'arm64';
1615
const isLinuxOnArm = process.platform === 'linux' && process.arch.includes('arm');
1716

18-
const afterTest: ((() => void) | (() => Promise<void>))[] = [];
19-
async function cleanup () {
20-
for (const cleanup of afterTest) {
21-
const r = cleanup();
22-
if (r instanceof Promise) { await r; }
23-
}
24-
afterTest.length = 0;
25-
}
26-
2717
type CrashInfo = {
2818
prod: string
2919
ver: string
@@ -57,49 +47,6 @@ function checkCrash (expectedProcessType: string, fields: CrashInfo) {
5747
}
5848
}
5949

60-
const startRemoteControlApp = async () => {
61-
const appPath = path.join(__dirname, 'fixtures', 'apps', 'remote-control');
62-
const appProcess = childProcess.spawn(process.execPath, [appPath]);
63-
appProcess.stderr.on('data', d => {
64-
process.stderr.write(d);
65-
});
66-
const port = await new Promise<number>(resolve => {
67-
appProcess.stdout.on('data', d => {
68-
const m = /Listening: (\d+)/.exec(d.toString());
69-
if (m && m[1] != null) {
70-
resolve(Number(m[1]));
71-
}
72-
});
73-
});
74-
function remoteEval (js: string): any {
75-
return new Promise((resolve, reject) => {
76-
const req = http.request({
77-
host: '127.0.0.1',
78-
port,
79-
method: 'POST'
80-
}, res => {
81-
const chunks = [] as Buffer[];
82-
res.on('data', chunk => { chunks.push(chunk); });
83-
res.on('end', () => {
84-
const ret = v8.deserialize(Buffer.concat(chunks));
85-
if (Object.prototype.hasOwnProperty.call(ret, 'error')) {
86-
reject(new Error(`remote error: ${ret.error}\n\nTriggered at:`));
87-
} else {
88-
resolve(ret.result);
89-
}
90-
});
91-
});
92-
req.write(js);
93-
req.end();
94-
});
95-
}
96-
function remotely (script: Function, ...args: any[]): Promise<any> {
97-
return remoteEval(`(${script})(...${JSON.stringify(args)})`);
98-
}
99-
afterTest.push(() => { appProcess.kill('SIGINT'); });
100-
return { remoteEval, remotely };
101-
};
102-
10350
const startServer = async () => {
10451
const crashes: CrashInfo[] = [];
10552
function getCrashes () { return crashes; }
@@ -145,7 +92,7 @@ const startServer = async () => {
14592

14693
const port = (server.address() as AddressInfo).port;
14794

148-
afterTest.push(() => { server.close(); });
95+
defer(() => { server.close(); });
14996

15097
return { getCrashes, port, waitForCrash };
15198
};
@@ -188,8 +135,6 @@ function waitForNewFileInDir (dir: string): Promise<string[]> {
188135

189136
// TODO(nornagon): Fix tests on linux/arm.
190137
ifdescribe(!isLinuxOnArm && !process.mas && !process.env.DISABLE_CRASH_REPORTER_TESTS)('crashReporter module', function () {
191-
afterEach(cleanup);
192-
193138
describe('should send minidump', () => {
194139
it('when renderer crashes', async () => {
195140
const { port, waitForCrash } = await startServer();

spec-main/api-net-spec.ts

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as http from 'http';
44
import * as url from 'url';
55
import { AddressInfo, Socket } from 'net';
66
import { emittedOnce } from './events-helpers';
7+
import { defer } from './spec-helpers';
78

89
const kOneKiloByte = 1024;
910
const kOneMegaByte = kOneKiloByte * kOneKiloByte;
@@ -22,13 +23,6 @@ function randomString (length: number) {
2223
return buffer.toString();
2324
}
2425

25-
const cleanupTasks: (() => void)[] = [];
26-
27-
function cleanUp () {
28-
cleanupTasks.forEach(t => t());
29-
cleanupTasks.length = 0;
30-
}
31-
3226
async function getResponse (urlRequest: Electron.ClientRequest) {
3327
return new Promise<Electron.IncomingMessage>((resolve, reject) => {
3428
urlRequest.on('error', reject);
@@ -70,7 +64,7 @@ function respondNTimes (fn: http.RequestListener, n: number): Promise<string> {
7064
});
7165
const sockets: Socket[] = [];
7266
server.on('connection', s => sockets.push(s));
73-
cleanupTasks.push(() => {
67+
defer(() => {
7468
server.close();
7569
sockets.forEach(s => s.destroy());
7670
});
@@ -118,7 +112,6 @@ describe('net module', () => {
118112
beforeEach(() => {
119113
routeFailure = false;
120114
});
121-
afterEach(cleanUp);
122115
afterEach(async function () {
123116
await session.defaultSession.clearCache();
124117
if (routeFailure && this.test) {

spec-main/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,8 @@ app.whenReady().then(async () => {
110110
chai.use(require('dirty-chai'));
111111

112112
const runner = mocha.run(cb);
113+
const { runCleanupFunctions } = require('./spec-helpers');
114+
runner.on('test end', () => {
115+
runCleanupFunctions();
116+
});
113117
});

spec-main/spec-helpers.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,78 @@
1+
import * as childProcess from 'child_process';
2+
import * as path from 'path';
3+
import * as http from 'http';
4+
import * as v8 from 'v8';
5+
16
export const ifit = (condition: boolean) => (condition ? it : it.skip);
27
export const ifdescribe = (condition: boolean) => (condition ? describe : describe.skip);
38

49
export const delay = (time: number) => new Promise(resolve => setTimeout(resolve, time));
10+
11+
type CleanupFunction = (() => void) | (() => Promise<void>)
12+
const cleanupFunctions: CleanupFunction[] = [];
13+
export async function runCleanupFunctions () {
14+
for (const cleanup of cleanupFunctions) {
15+
const r = cleanup();
16+
if (r instanceof Promise) { await r; }
17+
}
18+
cleanupFunctions.length = 0;
19+
}
20+
21+
export function defer (f: CleanupFunction) {
22+
cleanupFunctions.push(f);
23+
}
24+
25+
class RemoteControlApp {
26+
process: childProcess.ChildProcess;
27+
port: number;
28+
29+
constructor (proc: childProcess.ChildProcess, port: number) {
30+
this.process = proc;
31+
this.port = port;
32+
}
33+
34+
remoteEval = (js: string): Promise<any> => {
35+
return new Promise((resolve, reject) => {
36+
const req = http.request({
37+
host: '127.0.0.1',
38+
port: this.port,
39+
method: 'POST'
40+
}, res => {
41+
const chunks = [] as Buffer[];
42+
res.on('data', chunk => { chunks.push(chunk); });
43+
res.on('end', () => {
44+
const ret = v8.deserialize(Buffer.concat(chunks));
45+
if (Object.prototype.hasOwnProperty.call(ret, 'error')) {
46+
reject(new Error(`remote error: ${ret.error}\n\nTriggered at:`));
47+
} else {
48+
resolve(ret.result);
49+
}
50+
});
51+
});
52+
req.write(js);
53+
req.end();
54+
});
55+
}
56+
57+
remotely = (script: Function, ...args: any[]): Promise<any> => {
58+
return this.remoteEval(`(${script})(...${JSON.stringify(args)})`);
59+
}
60+
}
61+
62+
export async function startRemoteControlApp () {
63+
const appPath = path.join(__dirname, 'fixtures', 'apps', 'remote-control');
64+
const appProcess = childProcess.spawn(process.execPath, [appPath]);
65+
appProcess.stderr.on('data', d => {
66+
process.stderr.write(d);
67+
});
68+
const port = await new Promise<number>(resolve => {
69+
appProcess.stdout.on('data', d => {
70+
const m = /Listening: (\d+)/.exec(d.toString());
71+
if (m && m[1] != null) {
72+
resolve(Number(m[1]));
73+
}
74+
});
75+
});
76+
defer(() => { appProcess.kill('SIGINT'); });
77+
return new RemoteControlApp(appProcess, port);
78+
}

0 commit comments

Comments
 (0)