diff --git a/test/common.js b/test/common.js index 6301db9eb3..23048bff66 100644 --- a/test/common.js +++ b/test/common.js @@ -226,3 +226,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(process.env.SystemRoot, '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 read file: ', etcServicesFileName); + return undefined; + } + + return serviceName; +} diff --git a/test/internet/test-dns.js b/test/internet/test-dns.js index 902545c175..202f08e8dd 100644 --- a/test/internet/test-dns.js +++ b/test/internet/test-dns.js @@ -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(); }); @@ -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(); });