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: use dynamic port in test-cluster-dgram-reuse #12426

Closed
wants to merge 4 commits into from

Conversation

orafaelfragoso
Copy link
Contributor

Use of common.PORT in parallel tests is not completely safe (because
the same port can be previously assigned to another test running in
parallel if that test uses port 0 to get an arbitrary available port).

Remove common.PORT from test-cluster-dgram-reuse.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • commit message follows commit guidelines
Affected core subsystem(s)

test cluster

@nodejs-github-bot nodejs-github-bot added the test Issues and PRs related to the tests. label Apr 15, 2017
@benjamingr
Copy link
Member

Thanks

Refs: #12376

I'm wondering, are both sockets guaranteed to be created on the same port in this case?

@orafaelfragoso
Copy link
Contributor Author

@benjamingr Great question.

I wonder if there's a way to dynamically get a port from the OS and assign it to a const for every test?

@addaleax
Copy link
Member

addaleax commented Apr 15, 2017

What you can do and what should work is creating the first socket, then using .address().port to get its port and use that for the second one. :)

Copy link
Member

@benjamingr benjamingr left a comment

Choose a reason for hiding this comment

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

I think we should do what @addaleax suggested then.

@orafaelfragoso
Copy link
Contributor Author

@addaleax What do you think of this?

// Creates the first socket
const socket = dgram.createSocket({ type: 'udp4', reuseAddr: true });
// Let the OS assign a random port using '0'
socket.bind(0, next);
// Creates the second socket using the same port from the previous one
dgram.createSocket({ type: 'udp4', reuseAddr: true }).bind(socket.address().port, next);

I'm sure I am missing something here. Could you shed me some light? The test is failing with:

=== release test-cluster-dgram-reuse ===                   
Path: parallel/test-cluster-dgram-reuse
dgram.js:489
    throw errnoException(err, 'getsockname');
    ^

Error: getsockname EINVAL
    at exports._errnoException (util.js:1042:11)
    at Socket.address (dgram.js:489:11)
    at Object.<anonymous> (/home/rafael/Development/node/test/parallel/test-cluster-dgram-reuse.js:43:40)
    at Module._compile (module.js:607:30)
    at Object.Module._extensions..js (module.js:618:10)
    at Module.load (module.js:516:32)
    at tryModuleLoad (module.js:466:12)
    at Function.Module._load (module.js:458:3)
    at Module.runMain (module.js:643:10)
    at run (bootstrap_node.js:443:7)

assert.js:86
  throw new assert.AssertionError({
  ^
AssertionError: 1 === 0
    at Worker.cluster.fork.on.common.mustCall (/home/rafael/Development/node/test/parallel/test-cluster-dgram-reuse.js:15:12)
    at Worker.<anonymous> (/home/rafael/Development/node/test/common.js:461:15)
    at emitTwo (events.js:125:13)
    at Worker.emit (events.js:213:7)
    at ChildProcess.worker.process.once (internal/cluster/master.js:188:12)
    at Object.onceWrapper (events.js:312:19)
    at emitTwo (events.js:125:13)
    at ChildProcess.emit (events.js:213:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:208:12)
Command: out/Release/node /home/rafael/Development/node/test/parallel/test-cluster-dgram-reuse.js

@benjamingr
Copy link
Member

benjamingr commented Apr 15, 2017

@rafaelfragosom I'm not sure port is available immediately, you might need to change it to something like:

// Creates the first socket
const socket = dgram.createSocket({ type: 'udp4', reuseAddr: true });
// Let the OS assign a random port using '0'
socket.bind(0, function() {
  // Creates the second socket using the same port from the previous one
  dgram.createSocket({ type: 'udp4', reuseAddr: true }).bind(socket.address().port, next);
  next.call(this);
});

Although I admit I never tested this.

Edit: tested, this appears to be the case, you can create a third socket if you'd like.

Here's a utility:

function getPort(cb) {
  const s = dgram.createSocket({ type: 'udp4', reuseAddr: true }).bind(0, () => {
    cb(null, s.address().port);
  });
}

You can do that to get the port and then keep the test (inside the callback) as it was just changing 0 to the port.

@orafaelfragoso
Copy link
Contributor Author

@benjamingr It does work. I'm sending the commit.

@benjamingr
Copy link
Member

technically the test is now slightly different, but it tests the same thing so I'm going to LGTM. We need to give it 72 hours anyway so if other people feel differently they can speak up :)

@orafaelfragoso
Copy link
Contributor Author

orafaelfragoso commented Apr 15, 2017

@benjamingr Thank you!

This is my first contribution to a big project like node and it's been good so far. I'll get better at it.

@benjamingr
Copy link
Member

You're doing great :) Thanks for taking the time to contribute.

@jkrems
Copy link
Contributor

jkrems commented Apr 15, 2017

@mscdex mscdex added cluster Issues and PRs related to the cluster subsystem. dgram Issues and PRs related to the dgram subsystem / UDP. labels Apr 15, 2017
// Creates the first socket
const socket = dgram.createSocket({ type: 'udp4', reuseAddr: true });
// Let the OS assign a random port to the first socket
socket.bind(0, function() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you add common.mustCall() to the callback here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. I'm still getting used to the tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@cjihrig done.

Remove common.PORT from test-cluster-dgram-reuse to eliminate possibility
that a dynamic port used in another test will collide with common.PORT.

Refs: nodejs#12376
…euse

Using the bind() callback to get the dynamically assigned port from the first socket and assigning it to the next cluster.
Fixes the wordwrap error of my last commit based on the guidelines
Adding the common.mustCall() to the callback as the test documentation
explains it.
@santigimeno
Copy link
Member

santigimeno commented Apr 16, 2017

I wonder if after the proposed changes, the next() machinery is needed at all. I think the sockets could be safely closed in the second socket bind callback.

@orafaelfragoso
Copy link
Contributor Author

@cjihrig Any updates on your request?

@orafaelfragoso
Copy link
Contributor Author

@benjamingr I'm gonna update this test with your suggestion. I was affraid of doing something like this, but since you suggested, I'm gonna do it.

Copy link
Contributor

@cjihrig cjihrig left a comment

Choose a reason for hiding this comment

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

LGTM. I'm not sure if the indentation on the second bind() is right or not though.

@lpinca
Copy link
Member

lpinca commented May 19, 2017

Ops, I just landed #12901 which was a dupe of this.

@lpinca
Copy link
Member

lpinca commented May 19, 2017

Closing this, sorry @rafaelfragosom.

@lpinca lpinca closed this May 19, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cluster Issues and PRs related to the cluster subsystem. dgram Issues and PRs related to the dgram subsystem / UDP. test Issues and PRs related to the tests.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants