-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconnect.test.js
192 lines (173 loc) · 6.93 KB
/
connect.test.js
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
const http = require('http');
const connect = require('./connect');
const { PassThrough, Transform } = require('stream');
let prosyServers = [];
afterEach(() => {
prosyServers.forEach(prosyServer => prosyServer.close());
prosyServers = [];
});
/**
* @param {string} requestString
* @returns Response String
*/
function generateResponse(requestString) {
return `Response: ${requestString}`;
}
function createProxyServer() {
return new Promise(resolve => {
const server = http.createServer();
const connectRequestUrlPromise = new Promise(connectRequestUrlResolve => {
server.on('connect', (request, socket) => {
socket.write('HTTP/1.0 200 Connection established\r\n\r\n');
connectRequestUrlResolve(request.url);
socket.pipe(new Transform({
transform(chunk, encoding, callback) {
callback(null, generateResponse(chunk.toString()));
},
})).pipe(socket);
});
});
server.listen({
host: '127.0.0.1',
port: 0,
});
server.on('listening', () => {
const hostname = server.address().address;
const port = server.address().port;
resolve({
proxyServerHost: `${hostname}:${port}`,
connectRequestUrlPromise,
});
});
prosyServers.push(server);
});
}
expect.extend({
/**
* promise が resolve も reject もしないことをチェック
* @param {Promise<any>} received
* @param {number} timeoutMs
* @returns
*/
willNotSettle(received, timeoutMs = 1000) {
const timeout = Symbol('timeout');
return Promise.race([
received,
new Promise(resolve => setTimeout(() => resolve(timeout), timeoutMs)),
]).then(result => {
return {
message: () => `The subject is not Promise or settled within ${timeoutMs} milliseconds.`,
pass: result === timeout,
};
});
},
});
test('proxyServerHost が指定されていない場合例外が投げられる', () => {
const proxyServerHost = undefined;
const destHostname = 'localhost';
const destPort = '80';
const inputStream = new PassThrough();
const outputStream = new PassThrough();
expect(() => {
connect(proxyServerHost, destHostname, destPort, inputStream, outputStream);
}).toThrowError('http-proxy-server arg ("hostname:port") required.');
});
test('destHostname が指定されていない場合例外が投げられる', () => {
const proxyServerHost = 'localhost:8080';
const destHostname = undefined;
const destPort = '80';
const inputStream = new PassThrough();
const outputStream = new PassThrough();
expect(() => {
connect(proxyServerHost, destHostname, destPort, inputStream, outputStream);
}).toThrowError('destination-server hostname arg required.');
});
test('destPort が指定されていない場合例外が投げられる', () => {
const proxyServerHost = 'localhost:8080';
const destHostname = 'localhost';
const destPort = undefined;
const inputStream = new PassThrough();
const outputStream = new PassThrough();
expect(() => {
connect(proxyServerHost, destHostname, destPort, inputStream, outputStream);
}).toThrowError('destination-server port arg required.');
});
test('options.timeoutMs が Integer ではない場合例外が投げられる', () => {
const proxyServerHost = 'localhost:8080';
const destHostname = 'localhost';
const destPort = '12345';
const inputStream = new PassThrough();
const outputStream = new PassThrough();
const timeoutMs = 'aaa';
expect(() => {
connect(proxyServerHost, destHostname, destPort, inputStream, outputStream, {
timeoutMs,
});
}).toThrowError('timeoutMs must be Integer.');
});
test('Proxy server へ接続する', () => {
return createProxyServer().then(({
proxyServerHost,
connectRequestUrlPromise,
}) => {
const destHostname = '127.1.2.3';
const destPort = '12345';
const inputStream = new PassThrough();
const outputStream = new PassThrough();
const responsePromise = new Promise(resolve => {
outputStream.once('data', chunk => resolve(chunk.toString()));
});
connect(proxyServerHost, destHostname, destPort, inputStream, outputStream);
inputStream.end('test_input');
return Promise.all([
expect(responsePromise).resolves.toBe(generateResponse('test_input')),
expect(connectRequestUrlPromise).resolves.toBe(`${destHostname}:${destPort}`),
]);
});
});
test('Proxy server が複数指定されている場合、1番目へのconnectに失敗したら2番目へ接続する', () => {
return createProxyServer().then(({
proxyServerHost,
connectRequestUrlPromise,
}) => {
const dummyProxyServerHost = '192.0.2.0:8080'; // 192.0.2.0/24 は test 用のため誰も使用していない
const destHostname = '127.1.2.3';
const destPort = '12345';
const inputStream = new PassThrough();
const outputStream = new PassThrough();
const responsePromise = new Promise(resolve => {
outputStream.once('data', chunk => resolve(chunk.toString()));
});
connect(`${dummyProxyServerHost},${proxyServerHost}`, destHostname, destPort, inputStream, outputStream);
inputStream.end('test_input');
return Promise.all([
expect(responsePromise).resolves.toBe(generateResponse('test_input')),
expect(connectRequestUrlPromise).resolves.toBe(`${destHostname}:${destPort}`),
]);
});
});
test('Proxy server が複数指定されている場合、1番目へのconnectに成功したら2番目へ接続しない', () => {
return Promise.all([
createProxyServer(),
createProxyServer(),
]).then(([server1, server2]) => {
const proxyServerHost = `${server1.proxyServerHost},${server2.proxyServerHost}`;
const destHostname = '127.1.2.3';
const destPort = '12345';
const inputStream = new PassThrough();
const outputStream = new PassThrough();
const timeoutMs = 500;
const responsePromise = new Promise(resolve => {
outputStream.once('data', chunk => resolve(chunk.toString()));
});
connect(proxyServerHost, destHostname, destPort, inputStream, outputStream, {
timeoutMs,
});
inputStream.end('test_input');
return Promise.all([
expect(responsePromise).resolves.toBe(generateResponse('test_input')),
expect(server1.connectRequestUrlPromise).resolves.toBe(`${destHostname}:${destPort}`),
expect(server2.connectRequestUrlPromise).willNotSettle(timeoutMs + 300 /* ms */),
]);
});
});