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

test: fix flaky test-net-socket-local-address #4644

Closed
wants to merge 1 commit into from

Conversation

Trott
Copy link
Member

@Trott Trott commented Jan 12, 2016

The close event can fire twice if close is called twice. Move checks
to exit event for process instead.

Ref: #4476

The close event can fire twice if close is called twice. Move checks
to exit event for process instead.

Ref: nodejs#4476
@Trott Trott added the test Issues and PRs related to the tests. label Jan 12, 2016
@Trott
Copy link
Member Author

Trott commented Jan 12, 2016

@jbergstroem
Copy link
Member

LGTM

@mscdex mscdex added the net Issues and PRs related to the net subsystem. label Jan 12, 2016
assert.deepEqual(clientLocalPorts, serverRemotePorts,
'client and server should agree on the ports used');
assert.equal(2, conns);
}));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't this be changed to common.mustCall(fn, 2) instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not as the test was written. Most of the times, it would run once, but every once in a while on Windows (and possibly elsewhere, but definitely on Windows), it would run twice.

In a stress test run, the test ran 9999 times on Windows. 9988 times, the function ran once. But 11 times, the test failed because it ran twice.

@cjihrig
Copy link
Contributor

cjihrig commented Jan 12, 2016

Changes LGTM, but shouldn't we be able to reliably determine how many times the close event occurs?

@Trott
Copy link
Member Author

Trott commented Jan 12, 2016

@cjihrig My original fix for this was to put in a boolean that indicated whether or not server.close() had been called yet and to check that boolean right before calling server.close(). This way, we could avoid the infrequent (but still occurring from time to time) situation where server.close() gets called by two different invocations of testConnect().

I refactored it to process.on('exit',...) because the resulting code is simpler this way and the change set is more straightforward as well.

The race condition exists because the client connection callback calls testConnect() (where server.close() happens) asynchronously (in the callback to client.close()) while the server calls it synchronously in its connection callback. If, at the end of the test, the client close callback manages to invoke testConnect() after the server has done so but before the program actually exits, then the close callback will fire twice. At least, that was my theory which appears to be borne out by the stress test results above.

@cjihrig
Copy link
Contributor

cjihrig commented Jan 12, 2016

@Trott would you mind taking a look at #4650. IMO, this test is overly complicated. It's calling testConnect() from everywhere, including multiple server events. I tried to simplify it in #4650.

@Trott
Copy link
Member Author

Trott commented Jan 13, 2016

@cjihrig Took a look. It looked good, but when I tried to confirm that it still triggered an assertion in Node 3.0.0 (by converting ES6 stuff to ES5), the test passed instead. So it no longer tests for the bug it was written to find.

Then it occurred to me that I didn't do a similar thing for this version of the test in this PR. So I've done that now and I can report that it still triggers the error:

$ node test/parallel/test-net-socket-local-address.js 

assert.js:89
  throw new assert.AssertionError({
  ^
AssertionError: client and server should agree on the ports used
    at process.<anonymous> (/Users/trott/io.js/test/parallel/test-net-socket-local-address.js:43:10)
    at emitOne (events.js:77:13)
    at process.emit (events.js:169:7)

So that's good. For the record, here's the version of the test in this PR with unsupported-in-3.0.0 features rewritten or commented out:

'use strict';
// const common = require('../common');
const assert = require('assert');
const net = require('net');

// skip test in FreeBSD jails
// if (common.inFreeBSDJail) {
//   console.log('1..0 # Skipped: In a FreeBSD jail');
//   return;
// }

var conns = 0;
var clientLocalPorts = [];
var serverRemotePorts = [];

const server = net.createServer(function(socket) {
  serverRemotePorts.push(socket.remotePort);
  testConnect();
});

const client = new net.Socket();

server.listen(12346, '127.0.0.1', testConnect);

function testConnect() {
  if (conns > serverRemotePorts.length || conns > clientLocalPorts.length) {
    // We're waiting for a callback to fire.
    return;
  }

  if (conns === 2) {
    return server.close();
  }
  client.connect(12346, '127.0.0.1', function() {
    clientLocalPorts.push(this.localPort);
    this.once('close', testConnect);
    this.destroy();
  });
  conns++;
}

process.on('exit', function() {
  assert.deepEqual(clientLocalPorts, serverRemotePorts,
                   'client and server should agree on the ports used');
  assert.equal(2, conns);
});

If you can come up with a simpler test in that other PR that still finds the bug the test was written for, I'm happy to go with that instead of this PR, of course.

cjihrig added a commit that referenced this pull request Jan 13, 2016
Prior to this commit, the test was flaky because it was
executing the majority of its logic in a function called from
the client and multiple events on the server. This commit
simplifies the test by separating the server's connection and
listening events, and isolating the client logic.

Refs: #4476
Refs: #4644
PR-URL: #4650
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
@cjihrig
Copy link
Contributor

cjihrig commented Jan 13, 2016

Closing in favor of #4650.

@cjihrig cjihrig closed this Jan 13, 2016
rvagg pushed a commit that referenced this pull request Jan 14, 2016
Prior to this commit, the test was flaky because it was
executing the majority of its logic in a function called from
the client and multiple events on the server. This commit
simplifies the test by separating the server's connection and
listening events, and isolating the client logic.

Refs: #4476
Refs: #4644
PR-URL: #4650
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
@MylesBorins MylesBorins added test Issues and PRs related to the tests. and removed lts-watch-v4.x test Issues and PRs related to the tests. labels Jan 28, 2016
MylesBorins pushed a commit that referenced this pull request Jan 28, 2016
Prior to this commit, the test was flaky because it was
executing the majority of its logic in a function called from
the client and multiple events on the server. This commit
simplifies the test by separating the server's connection and
listening events, and isolating the client logic.

Refs: #4476
Refs: #4644
PR-URL: #4650
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
MylesBorins pushed a commit that referenced this pull request Feb 11, 2016
Prior to this commit, the test was flaky because it was
executing the majority of its logic in a function called from
the client and multiple events on the server. This commit
simplifies the test by separating the server's connection and
listening events, and isolating the client logic.

Refs: #4476
Refs: #4644
PR-URL: #4650
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
MylesBorins pushed a commit to MylesBorins/node that referenced this pull request Feb 11, 2016
Prior to this commit, the test was flaky because it was
executing the majority of its logic in a function called from
the client and multiple events on the server. This commit
simplifies the test by separating the server's connection and
listening events, and isolating the client logic.

Refs: nodejs#4476
Refs: nodejs#4644
PR-URL: nodejs#4650
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
MylesBorins pushed a commit to MylesBorins/node that referenced this pull request Feb 15, 2016
Prior to this commit, the test was flaky because it was
executing the majority of its logic in a function called from
the client and multiple events on the server. This commit
simplifies the test by separating the server's connection and
listening events, and isolating the client logic.

Refs: nodejs#4476
Refs: nodejs#4644
PR-URL: nodejs#4650
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
scovetta pushed a commit to scovetta/node that referenced this pull request Apr 2, 2016
Prior to this commit, the test was flaky because it was
executing the majority of its logic in a function called from
the client and multiple events on the server. This commit
simplifies the test by separating the server's connection and
listening events, and isolating the client logic.

Refs: nodejs#4476
Refs: nodejs#4644
PR-URL: nodejs#4650
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
@Trott Trott deleted the fix-net-socket-local-address branch January 13, 2022 22:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
net Issues and PRs related to the net subsystem. test Issues and PRs related to the tests.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants