Skip to content

Commit

Permalink
tests: do not hardcode service name in test-dns.
Browse files Browse the repository at this point in the history
Instead of hard-coding http service name in test-dns, retrieve it from
/etc/services. This is not ideal, but it's still better than hard-coding
it.

Fixes nodejs#8047.
  • Loading branch information
Julien Gilli committed Aug 12, 2014
1 parent 63a4268 commit d5ff830
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 2 deletions.
55 changes: 55 additions & 0 deletions test/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,58 @@ exports.checkSpawnSyncRet = function(ret) {
assert.strictEqual(ret.status, 0);
assert.strictEqual(ret.error, undefined);
};

var etcServicesFileName = path.join('/etc', 'services');
if (process.platform === 'win32') {
etcServicesFileName = path.join('/Windows', 'System32', 'drivers', 'etc',
'services');
}

/*
* Returns a string that represents the service name associated
* to the service bound to port "port" and using protocol "protocol".
*
* If the service is not defined in the services file, it returns
* the port number as a string.
*
* Returns undefined if /etc/services (or its equivalent on non-UNIX
* platforms) can't be read.
*/
exports.getServiceName = function getServiceName(port, protocol) {
if (port == null) {
throw new Error("Missing port number");
}

if (typeof protocol !== 'string') {
throw new Error("Protocol must be a string");
}

/*
* By default, if a service can't be found in /etc/services,
* its name is considered to be its port number.
*/
var serviceName = port.toString();

try {
/*
* I'm not a big fan of readFileSync, but reading /etc/services asynchronously
* here would require implementing a simple line parser, which seems overkill
* for a simple utility function that is not running concurrently with any
* other one.
*/
var servicesContent = fs.readFileSync(etcServicesFileName,
{ encoding: 'utf8'});
var regexp = util.format('^(\\w+)\\s+\\s%d/%s\\s', port, protocol);
var re = new RegExp(regexp, 'm');

var matches = re.exec(servicesContent);
if (matches && matches.length > 1) {
serviceName = matches[1];
}
} catch(e) {
console.error('Cannot find /etc/services file!');
return undefined;
}

return serviceName;
}
36 changes: 34 additions & 2 deletions test/internet/test-dns.js
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,23 @@ TEST(function test_lookupservice_ip_ipv4(done) {
var req = dns.lookupService('127.0.0.1', 80, function(err, host, service) {
if (err) throw err;
assert.strictEqual(host, 'localhost');
assert.strictEqual(service, 'http');

/*
* Retrieve the actual HTTP service name as setup on the host currently
* running the test by reading it from /etc/services. This is not ideal,
* as the service name lookup could use another mechanism (e.g nscd), but
* it's already better than hardcoding it.
*/
var httpServiceName = common.getServiceName(80, 'tcp');
if (!httpServiceName) {
/*
* Couldn't find service name, reverting to the most sensible default
* for port 80.
*/
httpServiceName = 'http';
}

assert.strictEqual(service, httpServiceName);

done();
});
Expand All @@ -515,7 +531,23 @@ TEST(function test_lookupservice_ip_ipv6(done) {
* that most sane platforms use either one of these two by default.
*/
assert(host === 'localhost' || host === 'ip6-localhost');
assert.strictEqual(service, 'http');

/*
* Retrieve the actual HTTP service name as setup on the host currently
* running the test by reading it from /etc/services. This is not ideal,
* as the service name lookup could use another mechanism (e.g nscd), but
* it's already better than hardcoding it.
*/
var httpServiceName = common.getServiceName(80, 'tcp');
if (!httpServiceName) {
/*
* Couldn't find service name, reverting to the most sensible default
* for port 80.
*/
httpServiceName = 'http';
}

assert.strictEqual(service, httpServiceName);

done();
});
Expand Down

0 comments on commit d5ff830

Please sign in to comment.