uNetworking/uWebSockets.js

Error: read ECONNRESET with multiple test

Closed this issue · 4 comments

Each test pass if it's runned individually.
If all tests are runned, only first pass.

Reproduction

// /test/index.test.ts
import { strictEqual } from 'node:assert'
import http, { type RequestOptions } from 'node:http'
import { afterEach, beforeEach, describe, it } from 'node:test'
import { App, type TemplatedApp } from 'uWebSockets.js'

const port = 8080

let app: TemplatedApp

const req = (path: string, options: RequestOptions = {}): Promise<{ statusCode: number }> => {
  return new Promise((resolve) => {
    http.get(`http://localhost:${port}${path}`, options, (res) => {
      res.on('data', (_chunk) => { })
      res.on('end', () => {
        resolve({
          statusCode: res.statusCode!
        })
      })
    })
  })
}

describe('Test suites #1', () => {
  beforeEach(() => {
    app = App()
  })

  afterEach(() => {
    app.close()
  })

  it('Test #1', async () => {
    app
      .get('/', (res) => { res.end('Hi 1') })
      .listen(port, () => { })

    const res = await req('/')

    strictEqual(res.statusCode, 200)
  })

  it('Test #2', async () => {
    app
      .get('/', (res) => { res.end('Hi 2') })
      .listen(port, () => { })

    const res = await req('/')

    strictEqual(res.statusCode, 200)
  })
})

yarn tsx --test ./test/index.test.ts OR yarn tsx --test --test-concurrency=1 ./test/index.test.ts

Actual

▶ Test suites #1
  ✔ Test #1 (14.4993ms)
  ✖ Test #2 (1.8679ms)
    Error: read ECONNRESET
        at TCP.onStreamRead (node:internal/stream_base_commons:216:20) {
      errno: -4077,
      code: 'ECONNRESET',
      syscall: 'read'
    }

▶ Test suites #1 (18.9841ms)
ℹ tests 2
ℹ suites 1
ℹ pass 1
ℹ fail 1
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 22.2206

✖ failing tests:

test at test\index.test.ts:1:738
✖ Test #2 (1.8679ms)
  Error: read ECONNRESET
      at TCP.onStreamRead (node:internal/stream_base_commons:216:20) {
    errno: -4077,
    code: 'ECONNRESET',
    syscall: 'read'
  }

Epected

Both tests pass

Information

Node: 22.9.0
uWebSockets.js: 20.49.0
OS: Windows

You need to move the request inside the listen callback so it runs after listen, then test pass

.listen(port, s => {
    if (!s) throw 'listen failed'
    const res = await req('/')
    strictEqual(res.statusCode, 200)
})

Still not works

// /test/index.test.ts
import { strictEqual } from 'node:assert'
import http, { type RequestOptions } from 'node:http'
import { afterEach, beforeEach, describe, it } from 'node:test'
import { App, type TemplatedApp } from 'uWebSockets.js'

const port = 8080

let app: TemplatedApp

const req = (path: string, options: RequestOptions = {}): Promise<{ statusCode: number }> => {
  return new Promise((resolve) => {
    http.get(`http://localhost:${port}${path}`, options, (res) => {
      res.on('data', (_chunk) => { })
      res.on('end', () => {
        resolve({
          statusCode: res.statusCode!
        })
      })
    })
  })
}

describe('Test suites #1', () => {
  beforeEach(() => {
    app = App()
  })

  afterEach(() => {
    app.close()
  })

  it('Test #1', (_, done) => {
    app
      .get('/', (res) => { res.end('Hi 1') })
      .listen(port, async s => {
        if (!s) throw 'listen failed'
        const res = await req('/')
        strictEqual(res.statusCode, 200)
        done()
      })
  })

  it('Test #2', (_, done) => {
    app
      .get('/', (res) => { res.end('Hi 2') })
      .listen(port, async s => {
        if (!s) throw 'listen failed'
        const res = await req('/')
        strictEqual(res.statusCode, 200)
        done()
      })
  })
})

You have no error handler on http.request, you force close socket with app.close and http.request throws error. Why use http.request use fetch works fine

const req = (path, options = {}) => {
   return fetch(`http://localhost:${port}${path}`).then(res => ({ statusCode: res.status }));
}

Thanks, now it works