Skip to content

Long task with synchronous pieces does not time out #2920

Closed
@bensaufley

Description

@bensaufley

Describe the bug

Basically I've got a synchronous function that I want to test is reasonably fast with a large amount of data. I understand the issue of not being able to interrupt the process for the synchronous task, and saw for example another issue mentioning the problem with an infinite loop—but this function does eventually resolve. If I've set a timeout for 150ms and it takes 5 seconds to resolve, I would expect the test to fail as timed out, but it doesn't, no matter how long it takes.

I suppose this may be "behaving as expected" as timeout is only intended to interrupt asynchronous tasks if it can and does nothing if it can't interrupt, but it's definitely unintuitive to me that a test with a 150ms timeout that resolves in 5 seconds is considered to have passed.

For my particular use case I did a const start = Date.now(); … expect(Date.now() - start).toBeLessThan(150); and I'm sure that will probably be the response here, but I think it's unintuitive that the distinction between synchronous and asynchronous code (even synchronous code within a promise) will change whether the same behavior is considered to have timed out.

Reproduction

Times out as I'd expect, because (as far as I understand, and I admit I'm a little fuzzy) setTimeout does not monopolize ticks and allows the test process to intervene:

it('times out', async () => {
  await new Promise((resolve) => {
    setTimeout(resolve, 5_000);
  });
}, 150);

Does not time out, and does not fail once completed:

it('does not time out', async () => {
  const start = Date.now();
  await new Promise((resolve) => {
    while (Date.now() - start < 5_000) {}
    resolve();
  });
}, 150);

Even this, which occurred to me while writing this issue, does not result in a timeout:

it('does not time out even with a promise after completion allowing the test runner to intervene', async () => {
  const start = Date.now();
  while (Date.now() - start < 5_000) {}
  await new Promise((resolve) => {
    setImmediate(resolve); // setTimeout(resolve, 0 or even 10) has no effect either
  });
}, 150);

System Info

System:
    OS: macOS 13.1
    CPU: (10) arm64 Apple M1 Pro
    Memory: 85.13 MB / 16.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 18.10.0 - ~/.nodenv/versions/18.10.0/bin/node
    npm: 8.19.2 - ~/.nodenv/versions/18.10.0/bin/npm
  Browsers:
    Firefox: 109.0.1
    Safari: 16.2
  npmPackages:
    @vitest/coverage-c8: ^0.24.5 => 0.24.5 
    vite: ^3.2.4 => 3.2.4 
    vitest: ^0.24.5 => 0.24.5

Used Package Manager

npm

Validations

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedExtra attention is needed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions