forked from code-dot-org/code-dot-org
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexecutionLog.js
More file actions
110 lines (104 loc) · 3.85 KB
/
Copy pathexecutionLog.js
File metadata and controls
110 lines (104 loc) · 3.85 KB
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
import {TestResults} from './constants';
var utils = require('./utils');
/**
* Get a testResult and message value based on an examination of the
* executionLog against the level's logConditions
*
* @param {Object[]} logConditions an array of logCondition objects
* @param {string[]} executionLog an array of function or statement names
* @returns {!Object}
*/
module.exports.getResultsFromLog = function(logConditions, executionLog) {
executionLog = executionLog || [];
var results = {
testResult: TestResults.ALL_PASS
};
logConditions.forEach(function(condition, index) {
var testResult = TestResults.LOG_CONDITION_FAIL;
var exact;
/*
* 'exact' or 'inexact' match will search a sequence. 'exact' requires that
* no other entries appear within the pattern.
*
* @param {!Object} condition
* @param {string} [condition.matchType] 'exact', 'inexact'
* @param {number} [condition.minTimes] number of matches required
* @param {number} [condition.maxTimes] maximum number of matches allowed
* @param {string[]} [condition.entries] function or statement names
* @param {string} [condition.message] message to display if condition fails
*/
condition.minTimes = condition.minTimes || 0;
condition.maxTimes = utils.valueOr(condition.maxTimes, Infinity);
switch (condition.matchType) {
case 'exact':
exact = true;
// Fall through
case 'inexact':
var entryIndex = 0,
matchedSequences = 0;
for (var i = 0; i < executionLog.length; i++) {
if (matchLogEntry(executionLog[i], condition.entries[entryIndex])) {
entryIndex++;
if (entryIndex >= condition.entries.length) {
entryIndex = 0;
matchedSequences++;
if (
(matchedSequences >= condition.minTimes &&
condition.maxTimes === Infinity) ||
matchedSequences > condition.maxTimes
) {
// Stop checking if we know we've succeeded for minTimes without
// a maxTimes or we know we've failed for maxTimes
break;
}
}
} else if (exact) {
// Start back at the beginning of the sequence if we didn't match
entryIndex = 0;
}
}
if (
matchedSequences >= condition.minTimes &&
matchedSequences <= condition.maxTimes
) {
testResult = TestResults.ALL_PASS;
}
break;
default:
testResult = TestResults.ALL_PASS;
break;
}
// We want to remember the lowest test result value and message (100 is
// ALL_PASS, all other errors are lower numbers)
if (testResult < results.testResult) {
results.testResult = testResult;
results.message = condition.message;
}
});
return results;
};
/**
* Match an executionLog entry (in the form 'function:2' or '[forInit]') with
* a conditionEntry (in the form 'function:1' or '[forInit]'), where argument
* counts are stored after the colon following the function name.
*
* The colon and argument count are optional in the conditionEntry. When present,
* the argument count in the conditionEntry represents the minimum number of
* arguments in order to consider this a match.
*
* @param {Object[]} logConditions an array of logCondition objects
* @param {string[]} executionLog an array of function or statement names
* @returns {!Object}
*/
function matchLogEntry(logEntry, conditionEntry) {
var logItems = logEntry.split(':');
if (logItems.length < 2) {
return logEntry === conditionEntry;
}
var conditionItems = conditionEntry.split(':');
var conditionMinArgs = Number(conditionItems[1]);
if (isNaN(conditionMinArgs)) {
conditionMinArgs = 0;
}
return logItems[0] === conditionItems[0] && logItems[1] >= conditionMinArgs;
}