Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing with mocha times out on failed assert #1676

Closed
mrfitz42 opened this issue May 29, 2024 · 9 comments
Closed

Testing with mocha times out on failed assert #1676

mrfitz42 opened this issue May 29, 2024 · 9 comments

Comments

@mrfitz42
Copy link

mrfitz42 commented May 29, 2024

While unit testing legacy code which uses async and callbacks, no ESM or Promises, I noticed that many tests that failed an assert would hang and timeout rather that displaying the failure. Code has been upgraded to use the latest non-ESM-only package versions. I narrowed down the issue to tests that open a database connection.

I am not sure if this is a oracledb issue or a mocha issue, but I thought I would start here since the assert failure generates the following error message in node:

node:internal/process/promises:289
            triggerUncaughtException(err, true /* fromPromise */);
            ^

While mocha's timeout mentions:

     Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (oracledb-mocha.test.js)
  1. What versions are you using?

database version: Oracle 19c Enterprise edition version 19.21.0.0.0
process.platform: 'linux'
process.version: 'v20.11.0'
process.arch: 'x64'
require('oracledb').versionString: '6.5.1'
require('oracledb').oracleClientVersionString: undefined

  1. Is it an error or a hang or a crash?

Hangs on failed assert()

  1. What error(s) or behavior you are seeing?
$ mocha oracledb-mocha.test.js
Running in thick mode


  investigating
    when opening a connection
Obtained connection
Releasing connection - no error
connection: Connection {
  _events: [Object: null prototype] {},
  _eventsCount: 0,
  _maxListeners: undefined,
  _dbObjectClasses: Map(0) {},
  _closing: false,
  [Symbol(shapeMode)]: false,
  [Symbol(kCapture)]: false
}
      1) should fail an assert without hanging


  0 passing (2s)
  1 failing

  1) investigating
       when opening a connection
         should fail an assert without hanging:
     Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/home/mikef/APEX/spoccode-apex/oracledb-mocha.test.js)
      at listOnTimeout (node:internal/timers:573:17)
      at process.processTimers (node:internal/timers:514:7)
$ node oracledb-mocha.test.js 
Running in thick mode
Obtained connection
Releasing connection - no error
connection: Connection {
  _events: [Object: null prototype] {},
  _eventsCount: 0,
  _maxListeners: undefined,
  _dbObjectClasses: Map(0) {},
  _closing: false,
  [Symbol(shapeMode)]: false,
  [Symbol(kCapture)]: false
}
node:internal/process/promises:289
            triggerUncaughtException(err, true /* fromPromise */);
            ^

AssertionError [ERR_ASSERTION]: expected failed assert
    at /home/mikef/APEX/spoccode-apex/oracledb-mocha.test.js:29:7
    at /home/mikef/APEX/spoccode-apex/node_modules/oracledb/lib/util.js:136:7 {
  generatedMessage: false,
  code: 'ERR_ASSERTION',
  actual: false,
  expected: true,
  operator: '=='
}

Node.js v20.11.0
  1. Include a runnable Node.js script that shows the problem.
var oracledb = require('oracledb');
var assert   = require('assert');

// Optionally run in node-oracledb Thick mode
if (process.env.NODE_ORACLEDB_DRIVER_MODE === 'thick') {
  oracledb.initOracleClient();  // enable node-oracledb Thick mode
}

console.log(oracledb.thin ? 'Running in thin mode' : 'Running in thick mode');

var test_function = function(next) {
  var connAttrs = {
    user: process.env.NODE_ORACLEDB_USER,
    password: process.env.NODE_ORACLEDB_PASSWORD,
    connectString: process.env.NODE_ORACLEDB_CONNECTIONSTRING,
  };

  oracledb.getConnection(connAttrs, function(err, conn) {
    if (err) {
      console.log('Error from getConnection:', err);
      return next(err);
    }
    console.log('Obtained connection');

    conn.close(function(err) {
      console.log('Releasing connection', err || '- no error');
      assert(!err, 'threw an error');
      console.log('connection:', conn);
      assert(!conn, 'expected failed assert');

      next();
    });
  });
};


if (require.main === module) {
      test_function(() => process.exit());
}
else {
  describe('investigating', function() {
    context('when opening a connection', function() {
      it('should fail an assert without hanging', function(done) {
        test_function(done);
      });
    });
  });
}
@mrfitz42 mrfitz42 added the bug label May 29, 2024
@sharadraju
Copy link
Member

sharadraju commented May 30, 2024

@mrfitz42 This is a mocha error.

To run a mocha test with any node-oracledb functionality, we usually use mocha <testfilename> --t 0, to ensure that there are no timeouts.

Please check our https://github.com/oracle/node-oracledb/blob/main/test/opts/.mocharc.yaml file to check the test configuration settings in mocha for the node-oracledb tests provided in this repo.

The reason that hang might be happening, is because the connection is not explicitly closed, after the error is thrown and the program takes its time to close the connections.

@mrfitz42
Copy link
Author

Running mocha oracledb-mocha.test.js --t 0 doesn't hang, but it also does not show the failed assert ... it exits mocha without any test status.

What do you mean by "the connection is not explicitly closed" when the test calls conn.close(function(err) { ... }); with the assert in the callback function?

@sharadraju
Copy link
Member

@mrfitz42 My apologies. On second look, I realise that connection.close function is called and the assert fail is in the callback function.

We will look at it and let you know.

@sudarshan12s
Copy link

sudarshan12s commented May 31, 2024

I can see the assert hangs or abnormally terminates.

As a workaround, can you use try/catch something like this? or just an if stmts

try {
      assert(!conn, 'expected failed assert');
    } catch (err) {
      return next(err);
    }

It still needs to be investigated if this is something related to mocha and async functions returning a promise..

@anthony-tuininga
Copy link
Member

If you are using old-style callbacks you cannot throw exceptions. You must always call the done function when you are finished. If you want to throw exceptions you will have to catch them yourself as @sudarshan12s demonstrated. This is a "feature" and has nothing to do with the driver!

@mrfitz42
Copy link
Author

Well that's annoying. Is there any way of resolving the pending promise in the callback rather than wrapping try-catch around the asserts? If wrapping the asserts is the only way, I'll have to change about 1500 unit tests.

@sudarshan12s
Copy link

I see some workarounds like this might help

let unhandledRejectionExitCode = 0;

process.on("unhandledRejection", (reason) => {
    console.log("unhandled rejection:", reason);
    unhandledRejectionExitCode = 1;
    throw reason;
});

or

mocha --unhandled-rejections=strict test/checkconnhang.js --t 0

@mrfitz42
Copy link
Author

Thank you very much. Adding --unhandled-rejections=strict to the mocha command line did the trick.
I appreciate all your help in solving what turned out to be a mostly mocha issue.

@sharadraju
Copy link
Member

Closing this as this is not a node-oracledb issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants