Skip to content

🐛 Bug: --timeout 0 with unref'd timers causes process exit #3817

Closed
@rolfl

Description

@rolfl

Background context - SSCCE to follow. Bear with me, this behaviour is somewhat bizarre, so explaining it is complicated....

When using WebStorm as an IDE, it can run the mocha tests in "run" mode or "debug" mode. If the tests are constructed in a particular way (specifically - using promises) In "run" mode, everything works fine. In debug mode, all the tests are ignored.... in WebStorm, it looks like:

image

It took me a lot of trial-and-error to identify the "root cause", but it boils down to the --timeout 0 that webstorm adds when doing the node --inspect-brk part of debugging. The timeout 0 is added to allow breakpoints to pause the code without causing the tests to time out.

The problem can be explained with the following test case:

'use strict';


function slowThing() {
  return new Promise(resolve => setTimeout(resolve, 10).unref());
}

describe('This has lots of 10ms tests', function() {
  it('10ms', () => slowThing());
});

Note, all the test does, is wait 10ms, and then succeed.

There are 2 key features in the above....

  1. it returns a promise in the it(...) test.
  2. it does an unref() on the setTimeout()

If you run the above normally, it succeeds node ./node_modules/mocha/bin/_mocha --ui bdd tests/sscce.spec.js:

  This has lots of 10ms tests
    ✓ 10ms

  1 passing (34ms)

If you add --timeout 0 it completes successfully, but does not actually run the test: node ./node_modules/mocha/bin/_mocha --timeout 0 --ui bdd tests/sscce.spec.js && echo pass gives:

  This has lots of 10ms tests
pass

The same is true (it also fails) if you run in debug mode (--inspect).

BUT, if you add a second --timeout 0 it will then work correctly: node ./node_modules/mocha/bin/_mocha --timeout 0 --timeout 0 --ui bdd tests/sscce.spec.js && echo pass

  This has lots of 10ms tests
    ✓ 10ms

  1 passing (18ms)
pass

My guess is that the code that waits for Promise-based tests to complete is not actively waiting on the promise, so the node system discovers there are no events to prevent system exit, so it exits...

But, for the life of me, I don't understand why adding multiple --timeout 0 flags makes it work.....

Oh, and, if you use WebStorm, you end up having to add 2 --timeout 0 flags in your configuration, so that when you run the tests it has 2 timeouts, and when you debug, it has 3.

Edited to add versions:

rolf@rolf-vb:~/bmix/debugsscce$ node --version
v8.15.1
rolf@rolf-vb:~/bmix/debugsscce$ npm list mocha
[email protected] /home/rolf/bmix/debugsscce
└── [email protected]

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: asyncrelated to asynchronous use of Mochaarea: node.jscommand-line-or-Node.js-specificstatus: accepting prsMocha can use your help with this one!type: buga defect, confirmed by a maintainer

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions