1'use strict';
2// Flags: --expose-gc
3
4// Tests that memoryUsage().external doesn't go negative
5// when a lot tls connections are opened and closed
6
7const common = require('../common');
8if (!common.hasCrypto)
9  common.skip('missing crypto');
10
11const makeDuplexPair = require('../common/duplexpair');
12const onGC = require('../common/ongc');
13const assert = require('assert');
14const tls = require('tls');
15
16// Payload doesn't matter. We just need to have the tls
17// connection try and connect somewhere.
18const dummyPayload = Buffer.alloc(10000, 'yolo');
19
20let runs = 0;
21
22// Count garbage-collected TLS sockets.
23let gced = 0;
24function ongc() { gced++; }
25
26connect();
27
28function connect() {
29  if (runs % 64 === 0)
30    global.gc();
31  const externalMemoryUsage = process.memoryUsage().external;
32  assert(externalMemoryUsage >= 0, `${externalMemoryUsage} < 0`);
33  if (runs++ === 512) {
34    // Make sure at least half the TLS sockets have been garbage collected
35    // (so that this test can actually check what it's testing):
36    assert(gced >= 256, `${gced} < 256`);
37    return;
38  }
39
40  const { clientSide, serverSide } = makeDuplexPair();
41
42  const tlsSocket = tls.connect({ socket: clientSide });
43  tlsSocket.on('error', common.mustCall(connect));
44  onGC(tlsSocket, { ongc });
45
46  // Use setImmediate so that we don't trigger the error within the same
47  // event loop tick.
48  setImmediate(() => serverSide.write(dummyPayload));
49}
50