-
Notifications
You must be signed in to change notification settings - Fork 785
/
helper.js
129 lines (111 loc) · 4.6 KB
/
helper.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*jslint nomen: true */
var Instrumenter = require('../lib/instrumenter'),
vm = require('vm'),
NO_OP = function () {},
utils = require('../lib/object-utils');
function Verifier(opts) {
this.file = opts.file;
this.fn = opts.fn;
this.code = opts.code;
this.generatedCode = opts.generatedCode;
this.err = opts.err;
this.debug = opts.debug;
this.coverageVariable = opts.coverageVariable || '__coverage__';
}
function pad(str, len) {
var blanks = ' ';
if (str.length >= len) {
return str;
}
return blanks.substring(0, len - str.length) + str;
}
function annotatedCode(code) {
var line = 0,
annotated = code.map(function (str) { line += 1; return pad(line, 6) + ': ' + str; });
return annotated.join('\n');
}
Verifier.prototype = {
verify: function (test, args, expectedOutput, expectedCoverage) {
if (this.err) {
test.ok(false, "Cannot call verify when errors present");
return;
} else if (this.fn === NO_OP) {
test.ok(false, "Cannot call verify for noop");
return;
}
var actualOutput = this.fn(args),
fullCov = global[this.coverageVariable],
cov = fullCov[Object.keys(fullCov)[0]];
utils.addDerivedInfo(global[this.coverageVariable]);
test.ok(cov && typeof cov === 'object', 'No coverage found for [' + this.file + ']');
test.deepEqual(expectedOutput, actualOutput, 'Output mismatch');
test.deepEqual(expectedCoverage.lines, cov.l, 'Line coverage mismatch');
test.deepEqual(expectedCoverage.functions, cov.f, 'Function coverage mismatch');
test.deepEqual(expectedCoverage.branches, cov.b, 'Branch coverage mismatch');
test.deepEqual(expectedCoverage.statements, cov.s, 'Statement coverage mismatch');
},
getCoverage: function () {
return global[this.coverageVariable];
},
getFileCoverage: function () {
var cov = this.getCoverage();
return cov[Object.keys(cov)[0]];
},
verifyError: function (test) {
test.ok(this.err && typeof this.err === 'object', 'Error should be an object');
},
verifyNoError: function (test) {
test.ok(!(this.err && typeof this.err === 'object'), 'Error should not be present');
}
};
function setup(file, codeArray, opts) {
opts = opts || {};
opts.file = file;
opts.debug = opts.debug || process.env.DEBUG;
var expectError = opts.expectError,
//exercise the case where RE substitutions for the preamble have $ signs
coverageVariable = typeof opts.coverageVariable === 'undefined' ? '$$coverage$$' : opts.coverageVariable,
ps = opts.embedSource || false,
pc = opts.preserveComments || false,
verifier,
cover = new Instrumenter({
debug: opts.debug,
walkDebug: opts.walkDebug,
noAutoWrap: opts.noAutoWrap,
coverageVariable: coverageVariable,
embedSource: ps,
preserveComments: pc
}),
args = [ codeArray.join("\n")],
callback = function (err, generated) {
if (err) {
if (expectError) {
verifier = new Verifier({ debug: opts.debug, file: file, fn: NO_OP, code: codeArray });
} else {
console.error(err);
console.error(err.stack);
verifier = new Verifier({ debug: opts.debug, file: file, err: err, code: codeArray });
}
return;
}
var wrappedCode = '(function (args) { var output;\n' + generated + '\nreturn output;\n})',
fn;
global[coverageVariable] = undefined;
fn = vm.runInThisContext(wrappedCode, __filename);
verifier = new Verifier({ debug: opts.debug, file: file, fn: fn, code: codeArray,
generatedCode: generated, coverageVariable: coverageVariable });
if (opts.debug) {
console.log('================== Original ============================================');
console.log(annotatedCode(codeArray));
console.log('================== Generated ===========================================');
console.log(generated);
console.log('========================================================================');
}
};
if (file) { args.push(file); }
args.push(callback);
delete opts.expectError;
cover.instrument.apply(cover, args);
return verifier;
}
exports.verifier = setup;