1// Copyright Joyent, Inc. and other Node contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the
5// "Software"), to deal in the Software without restriction, including
6// without limitation the rights to use, copy, modify, merge, publish,
7// distribute, sublicense, and/or sell copies of the Software, and to permit
8// persons to whom the Software is furnished to do so, subject to the
9// following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22'use strict';
23const common = require('../common');
24const Countdown = require('../common/countdown');
25const assert = require('assert');
26const http = require('http');
27
28const N = 4;
29const M = 4;
30const server = http.Server(common.mustCall(function(req, res) {
31  res.writeHead(200);
32  res.end('hello world\n');
33}, (N * M))); // N * M = good requests (the errors will not be counted)
34
35function makeRequests(outCount, inCount, shouldFail) {
36  const countdown = new Countdown(
37    outCount * inCount,
38    common.mustCall(() => server.close())
39  );
40  let onRequest = common.mustNotCall(); // Temporary
41  const p = new Promise((resolve) => {
42    onRequest = common.mustCall((res) => {
43      if (countdown.dec() === 0) {
44        resolve();
45      }
46
47      if (!shouldFail)
48        res.resume();
49    }, outCount * inCount);
50  });
51
52  server.listen(0, () => {
53    const port = server.address().port;
54    for (let i = 0; i < outCount; i++) {
55      setTimeout(() => {
56        for (let j = 0; j < inCount; j++) {
57          const req = http.get({ port: port, path: '/' }, onRequest);
58          if (shouldFail)
59            req.on('error', common.mustCall(onRequest));
60          else
61            req.on('error', (e) => assert.fail(e));
62        }
63      }, i);
64    }
65  });
66  return p;
67}
68
69const test1 = makeRequests(N, M);
70
71const test2 = () => {
72  // Should not explode if can not create sockets.
73  // Ref: https://github.com/nodejs/node/issues/13045
74  // Ref: https://github.com/nodejs/node/issues/13831
75  http.Agent.prototype.createConnection = function createConnection(_, cb) {
76    process.nextTick(cb, new Error('nothing'));
77  };
78  return makeRequests(N, M, true);
79};
80
81test1
82  .then(test2)
83  .catch((e) => {
84    // This is currently the way to fail a test with a Promise.
85    console.error(e);
86    process.exit(1);
87  }
88  );
89