KyleJune
KyleJune•14mo ago

Leaking resources from inbound HTTP connections in tests

Anyone have any ideas why I would be getting the following error. I'm using an oak server that is started before all the tests and closed after they all finish.
error: Leaking resources:
- An inbound HTTP connection (rid 7) was accepted before the test started, but was closed during the test. Do not close resources in a test that were not created during that test.
- An inbound HTTP connection (rid 21) was accepted during the test, but not closed during the test. Close the inbound HTTP connection by calling `httpConn.close()`.
error: Leaking resources:
- An inbound HTTP connection (rid 7) was accepted before the test started, but was closed during the test. Do not close resources in a test that were not created during that test.
- An inbound HTTP connection (rid 21) was accepted during the test, but not closed during the test. Close the inbound HTTP connection by calling `httpConn.close()`.
It happens in all test cases after the first. I await the response, so I'm not sure why the connection is still considered open when the test ends. All the assertions pass, the only thing that causes failure is the leaking resource. In oak I don't see an option to close the response.
it(notFoundTests, "without extension", async () => {
const response = await fetch("http://localhost:9001/api/invalid");
const body = await response.json();
assertEquals(response.status, 404);
assertEquals(
response.headers.get("Content-Type"),
"application/json; charset=UTF-8",
);
assert(response.headers.has("X-Response-Time"));
assert(!response.headers.has("etag"));
assertEquals(body, {
error: { name: "NotFoundError", message: "Not found", status: 404 },
});
});

it(notFoundTests, "with json extension", async () => {
const response = await fetch("http://localhost:9001/api/invalid.json");
const body = await response.text();
assertEquals(response.status, 404);
assertEquals(response.headers.get("Content-Type"), null);
assert(response.headers.has("X-Response-Time"));
assert(!response.headers.has("etag"));
assertEquals(body, "");
});
it(notFoundTests, "without extension", async () => {
const response = await fetch("http://localhost:9001/api/invalid");
const body = await response.json();
assertEquals(response.status, 404);
assertEquals(
response.headers.get("Content-Type"),
"application/json; charset=UTF-8",
);
assert(response.headers.has("X-Response-Time"));
assert(!response.headers.has("etag"));
assertEquals(body, {
error: { name: "NotFoundError", message: "Not found", status: 404 },
});
});

it(notFoundTests, "with json extension", async () => {
const response = await fetch("http://localhost:9001/api/invalid.json");
const body = await response.text();
assertEquals(response.status, 404);
assertEquals(response.headers.get("Content-Type"), null);
assert(response.headers.has("X-Response-Time"));
assert(!response.headers.has("etag"));
assertEquals(body, "");
});
7 Replies
KyleJune
KyleJuneOP•14mo ago
I tried adding await delay(1000) to the end of each test, even with that delay, the problem still happens. I don't have an issue with Deno v1.36.4, I'm going to try seeing if I can find the version this issue starts in. Looks like the last working version is v1.37.0, then it breaks in v1.37.1 and beyond. Same version of oak and all other dependencies. So the issue appears to be in Deno.
Deno AI Helper
Deno AI Helper•14mo ago
Based on the documentation, the error message you're seeing is related to resource sanitization in Deno's test runner. This feature checks that all resources created during a test are also closed during the same test. In your case, it seems that HTTP connections are being left open after the tests finish. The error message suggests two issues: 1. An inbound HTTP connection (rid 7) was accepted before the test started, but was closed during the test. This suggests that a connection was established before the test began and was closed within the test. The test runner expects that resources created outside of a test are not closed within the test. 2. An inbound HTTP connection (rid 21) was accepted during the test, but not closed during the test. This suggests that a connection was established during the test but was not closed before the test ended. The fetch function you're using to make HTTP requests in your tests does not automatically close the connection. Even though you're awaiting the response, the underlying connection is still open. In the Oak framework, the connection is typically closed automatically after the response is sent. However, in your tests, you're not directly interacting with the Oak application, but rather sending HTTP requests to the server. This means that the connection's lifecycle isn't managed by your test code, but by the server and the client (the fetch function). Unfortunately, the Deno documentation does not provide a clear solution for this issue. You might need to look for a way to ensure that the HTTP connections are closed after each test. This could involve some changes to how you're structuring your tests or how you're managing your Oak server.
Deno AI Helper
Deno AI Helper•14mo ago
🦕 Oops! Can you pinpoint where I went wrong to help me improve? 📈
KyleJune
KyleJuneOP•14mo ago
I think it's this PR that caused the issue. It seems to be the only one related to HTTP and it says it's for ensuring that resources are closed. https://github.com/denoland/deno/pull/20641
KyleJune
KyleJuneOP•14mo ago
I just tried that one by doing the following and it seems like that isn't what caused the issue. hmm. deno upgrade --canary --version a27ee8f368dbac33141fdcb9a17d0e4ea907b8ef
KyleJune
KyleJuneOP•14mo ago
This is the last working version.
deno 1.37.0+6f87962 (canary, x86_64-unknown-linux-gnu)
v8 11.8.172.6
typescript 5.2.2
deno 1.37.0+6f87962 (canary, x86_64-unknown-linux-gnu)
v8 11.8.172.6
typescript 5.2.2
The issue starts in the next canary build.
deno 1.37.0+c68650d (canary, x86_64-unknown-linux-gnu)
v8 11.8.172.6
typescript 5.2.2
deno 1.37.0+c68650d (canary, x86_64-unknown-linux-gnu)
v8 11.8.172.6
typescript 5.2.2
This is the PR that causes the issue. https://github.com/denoland/deno/pull/20680
GitHub
fix(cli/test): clear connection pool after tests by lucacasonato · ...
This helps reduce flakes where a test starts an HTTP server and makes a request using fetch, then shuts down the server, then starting a new test with a new server, but the connection pool still ha...
KyleJune
KyleJuneOP•14mo ago
I created an issue for the problem on github. https://github.com/denoland/deno/issues/21256
GitHub
Race condition in Deno.serve() and fetch() · Issue #21256 · denolan...
The following code sample is from one of my private repositories. The beforeAll starts an oak server and the afterAll closes it. So all test cases are making API calls to the same oak server. These...