testcontainers-node icon indicating copy to clipboard operation
testcontainers-node copied to clipboard

`jest --detectLeaks` is detecting leaks on the getting started example

Open felipecrs opened this issue 9 months ago • 7 comments

PS: I have read https://github.com/testcontainers/testcontainers-node/issues/383, but I'm reopening since no solution was provided there.

Expected Behaviour Not to leak anything. Deno's test runner won't allow tests to pass if leaks are detected, for example.

Actual Behaviour Leaks are reported. When using TESTCONTAINERS_RYUK_DISABLED=true, less leaks are reported, though.

Testcontainer Logs

❯ npx jest --detectLeaks
 FAIL  ./customer-repository.test.js
  ● Test suite failed to run

    EXPERIMENTAL FEATURE!
    Your test suite is leaking memory. Please ensure all references are cleaned.

    There is a number of things that can leak memory:
      - Async operations that have not finished (e.g. fs.readFile).
      - Timers not properly mocked (e.g. setInterval, setTimeout).
      - Keeping references to the global scope.

      at onResult (node_modules/@jest/core/build/TestScheduler.js:150:18)
      at node_modules/@jest/core/build/TestScheduler.js:254:19
      at node_modules/emittery/index.js:363:13
          at Array.map (<anonymous>)
      at Emittery.emit (node_modules/emittery/index.js:361:23)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        5.484 s, estimated 17 s
Ran all test suites.

Steps to Reproduce

  1. Setup the getting started example: https://testcontainers.com/guides/getting-started-with-testcontainers-for-nodejs/
  2. npx jest --detectLeaks

Environment Information

  • Operating System: Ubuntu 24.04.2 LTS
  • Docker Version: 28.0.4
  • Node version: 22.14.0
  • Testcontainers version: 10.23.0
  • Jest: 29.7.0

felipecrs avatar Apr 01 '25 21:04 felipecrs

To do: run with --logHeapUsage and assess the impact. I'm aware in some places we might add a UUID to an array or something and not clear it up, but I'm not too concerned about that. Running with --detectOpenHandles returns OK.

For example run a single test, record the heap usage. Run the entire test suite, record the heap usage, compare.

cristianrgreco avatar Apr 02 '25 11:04 cristianrgreco

@cristianrgreco, just to be sure, is that "to do" on me or on you?

felipecrs avatar Apr 02 '25 17:04 felipecrs

Haha sorry I could've been more clear. It's on anyone really. If you'd like do it that'd be amazing. If not I'm sure I'll get round to it eventually.

cristianrgreco avatar Apr 02 '25 17:04 cristianrgreco

FWIW, in a simpler example I could get rid of the leaks as long as TESTCONTAINERS_RYUK_DISABLED=true. With ryuk enabled, the socket connection initiated here is never closed and there is no simple way around that I can see.

const socket = await connectToReaperSocket(host, reaperPort, reaperContainer.Id);

Here is deno reporting on it:

TestContainers hello world with local socat proxy => ./utils/tcproxy.e2e.ts:5:6
error: Leaks detected:
  - A TCP connection was opened/accepted during the test, but not closed during the test. Close the TCP connection by calling `tcpConn.close()`.

(notice testing in deno requires working around https://github.com/denoland/deno/issues/20255 as well)

bonitao avatar Apr 05 '25 11:04 bonitao

In a simpler example I could get rid of the leaks as long as TESTCONTAINERS_RYUK_DISABLED=true

Hi @bonitao, I have this example:

const { GenericContainer } = require("testcontainers");

it("should return first mapped port", async () => {
  const container = await new GenericContainer("cristianrgreco/testcontainer:1.1.14")
    .withExposedPorts(8080)
    .start();

  expect(container.getFirstMappedPort()).toBe(container.getMappedPort(8080));

  await container.stop();
});

When I run:

TESTCONTAINERS_RYUK_DISABLED=true npx jest --detectLeaks simple.test.js

It still fails with:

  ● Test suite failed to run

    EXPERIMENTAL FEATURE!
    Your test suite is leaking memory. Please ensure all references are cleaned.

    There is a number of things that can leak memory:
      - Async operations that have not finished (e.g. fs.readFile).
      - Timers not properly mocked (e.g. setInterval, setTimeout).
      - Keeping references to the global scope.

      at onResult (node_modules/@jest/core/build/TestScheduler.js:150:18)
      at node_modules/@jest/core/build/TestScheduler.js:254:19
      at node_modules/emittery/index.js:363:13
          at Array.map (<anonymous>)
      at Emittery.emit (node_modules/emittery/index.js:361:23)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        3.372 s
Ran all test suites matching /simple.test.js/i.

This is with NodeJS instead of Deno.

cristianrgreco avatar Apr 05 '25 13:04 cristianrgreco