0
0
mirror of https://github.com/nodejs/node.git synced 2024-12-01 16:10:02 +01:00

test: make common.js mandatory via linting rule

test/common.js contains code that detects global variable leaks.

This eslint rule checks that a module named `common` is loaded. It is
only applicable to files in the test directory. Tests that intentionally
leak variables can opt out with an eslint-disable comment.

PR-URL: https://github.com/nodejs/node/pull/3157
Reviewed-By: Rod Vagg <rod@vagg.org>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
This commit is contained in:
Rich Trott 2015-10-01 21:38:16 -07:00
parent c78091d689
commit 3de353b554
6 changed files with 110 additions and 2 deletions

View File

@ -5,6 +5,8 @@ rules:
no-undef: 0
## allow global Buffer usage
require-buffer: 0
## common module is mandatory in tests
required-modules: [2, "common"]
globals:
gc: false

View File

@ -1,3 +1,4 @@
/* eslint-disable required-modules */
'use strict';
var path = require('path');
var fs = require('fs');

View File

@ -1,4 +1,4 @@
/* eslint-disable strict */
/* eslint-disable strict, required-modules */
try {
var crypto = require('crypto');
} catch (e) {

View File

@ -1,5 +1,5 @@
/* eslint-disable required-modules */
'use strict';
//console.log('puts before');
Object.prototype.xadsadsdasasdxx = function() {
};

View File

@ -1,3 +1,4 @@
/* eslint-disable required-modules */
'use strict';
var assert = require('assert');
var util = require('util');

View File

@ -0,0 +1,104 @@
/**
* @fileoverview Require usage of specified node modules.
* @author Rich Trott
*/
'use strict';
var path = require('path');
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
// trim required module names
var requiredModules = context.options;
var foundModules = [];
// if no modules are required we don't need to check the CallExpressions
if (requiredModules.length === 0) {
return {};
}
/**
* Function to check if a node is a string literal.
* @param {ASTNode} node The node to check.
* @returns {boolean} If the node is a string literal.
*/
function isString(node) {
return node && node.type === 'Literal' && typeof node.value === 'string';
}
/**
* Function to check if a node is a require call.
* @param {ASTNode} node The node to check.
* @returns {boolean} If the node is a require call.
*/
function isRequireCall(node) {
return node.callee.type === 'Identifier' && node.callee.name === 'require';
}
/**
* Function to check if a node has an argument that is a required module and
* return its name.
* @param {ASTNode} node The node to check
* @returns {undefined|String} required module name or undefined
*/
function getRequiredModuleName(node) {
var moduleName;
// node has arguments and first argument is string
if (node.arguments.length && isString(node.arguments[0])) {
var argValue = path.basename(node.arguments[0].value.trim());
// check if value is in required modules array
if (requiredModules.indexOf(argValue) !== -1) {
moduleName = argValue;
}
}
return moduleName;
}
return {
'CallExpression': function(node) {
if (isRequireCall(node)) {
var requiredModuleName = getRequiredModuleName(node);
if (requiredModuleName) {
foundModules.push(requiredModuleName);
}
}
},
'Program:exit': function(node) {
if (foundModules.length < requiredModules.length) {
var missingModules = requiredModules.filter(
function(module) {
return foundModules.indexOf(module === -1);
}
);
missingModules.forEach(function(moduleName) {
context.report(
node,
'Mandatory module "{{moduleName}}" must be loaded.',
{ moduleName: moduleName }
);
});
}
}
};
};
module.exports.schema = {
'type': 'array',
'items': [
{
'enum': [0, 1, 2]
}
],
'additionalItems': {
'type': 'string'
},
'uniqueItems': true
};