1 | "use strict";
|
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
4 | };
|
5 | var __importStar = (this && this.__importStar) || function (mod) {
|
6 | if (mod && mod.__esModule) return mod;
|
7 | var result = {};
|
8 | if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
9 | result["default"] = mod;
|
10 | return result;
|
11 | };
|
12 | Object.defineProperty(exports, "__esModule", { value: true });
|
13 | var async_1 = __importDefault(require("async"));
|
14 | var changeCase = __importStar(require("change-case"));
|
15 | var web3_1 = __importDefault(require("web3"));
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 | function getFunctionFullName(signature, methodIdentifiers) {
|
22 | for (var method in methodIdentifiers) {
|
23 | if (signature.replace('0x', '') === methodIdentifiers[method].replace('0x', '')) {
|
24 | return method;
|
25 | }
|
26 | }
|
27 | return null;
|
28 | }
|
29 |
|
30 |
|
31 |
|
32 |
|
33 | function isConstant(funcABI) {
|
34 | return (funcABI.constant || funcABI.stateMutability === 'view' || funcABI.stateMutability === 'pure');
|
35 | }
|
36 |
|
37 |
|
38 |
|
39 |
|
40 | function isPayable(funcABI) {
|
41 | return (funcABI.payable || funcABI.stateMutability === 'payable');
|
42 | }
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 | function getOverridedSender(userdoc, signature, methodIdentifiers) {
|
50 | var fullName = getFunctionFullName(signature, methodIdentifiers);
|
51 | var senderRegex = /#sender: account-+(\d)/g;
|
52 | var accountIndex = fullName && userdoc.methods[fullName] ? senderRegex.exec(userdoc.methods[fullName].notice) : null;
|
53 | return fullName && accountIndex ? accountIndex[1] : null;
|
54 | }
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 | function getProvidedValue(userdoc, signature, methodIdentifiers) {
|
62 | var fullName = getFunctionFullName(signature, methodIdentifiers);
|
63 | var valueRegex = /#value: (\d+)/g;
|
64 | var value = fullName && userdoc.methods[fullName] ? valueRegex.exec(userdoc.methods[fullName].notice) : null;
|
65 | return fullName && value ? value[1] : null;
|
66 | }
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 | function getAvailableFunctions(fileAST, testContractName) {
|
73 | var funcList = [];
|
74 | if (fileAST.nodes && fileAST.nodes.length > 0) {
|
75 | var contractAST = fileAST.nodes.filter(function (node) { return node.name === testContractName && node.nodeType === 'ContractDefinition'; });
|
76 | if (contractAST.length > 0 && contractAST[0].nodes) {
|
77 | var funcNodes = contractAST[0].nodes.filter(function (node) { return ((node.kind === "function" && node.nodeType === "FunctionDefinition") || (node.nodeType === "FunctionDefinition")); });
|
78 | funcList = funcNodes.map(function (node) { return node.name; });
|
79 | }
|
80 | }
|
81 | return funcList;
|
82 | }
|
83 |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 | function getTestFunctionsInterface(jsonInterface, funcList) {
|
89 | var functionsInterface = [];
|
90 | var specialFunctions = ['beforeAll', 'beforeEach', 'afterAll', 'afterEach'];
|
91 | var _loop_1 = function (func) {
|
92 | if (!specialFunctions.includes(func)) {
|
93 | var funcInterface = jsonInterface.find(function (node) { return node.type === 'function' && node.name === func; });
|
94 | if (funcInterface)
|
95 | functionsInterface.push(funcInterface);
|
96 | }
|
97 | };
|
98 | for (var _i = 0, funcList_1 = funcList; _i < funcList_1.length; _i++) {
|
99 | var func = funcList_1[_i];
|
100 | _loop_1(func);
|
101 | }
|
102 | return functionsInterface;
|
103 | }
|
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 | function createRunList(jsonInterface, fileAST, testContractName) {
|
111 | var availableFunctions = getAvailableFunctions(fileAST, testContractName);
|
112 | var testFunctionsInterface = getTestFunctionsInterface(jsonInterface, availableFunctions);
|
113 | var runList = [];
|
114 | if (availableFunctions.indexOf('beforeAll') >= 0) {
|
115 | runList.push({ name: 'beforeAll', type: 'internal', constant: false, payable: false });
|
116 | }
|
117 | for (var _i = 0, testFunctionsInterface_1 = testFunctionsInterface; _i < testFunctionsInterface_1.length; _i++) {
|
118 | var func = testFunctionsInterface_1[_i];
|
119 | if (availableFunctions.indexOf('beforeEach') >= 0) {
|
120 | runList.push({ name: 'beforeEach', type: 'internal', constant: false, payable: false });
|
121 | }
|
122 | if (func.name)
|
123 | runList.push({ name: func.name, signature: func.signature, type: 'test', constant: isConstant(func), payable: isPayable(func) });
|
124 | if (availableFunctions.indexOf('afterEach') >= 0) {
|
125 | runList.push({ name: 'afterEach', type: 'internal', constant: false, payable: false });
|
126 | }
|
127 | }
|
128 | if (availableFunctions.indexOf('afterAll') >= 0) {
|
129 | runList.push({ name: 'afterAll', type: 'internal', constant: false, payable: false });
|
130 | }
|
131 | return runList;
|
132 | }
|
133 | function runTest(testName, testObject, contractDetails, fileAST, opts, testCallback, resultsCallback) {
|
134 | var passingNum = 0;
|
135 | var failureNum = 0;
|
136 | var timePassed = 0;
|
137 | var isJSONInterfaceAvailable = testObject && testObject.options && testObject.options.jsonInterface;
|
138 | if (!isJSONInterfaceAvailable)
|
139 | return resultsCallback(new Error('Contract interface not available'), { passingNum: passingNum, failureNum: failureNum, timePassed: timePassed });
|
140 | var runList = createRunList(testObject.options.jsonInterface, fileAST, testName);
|
141 | var web3 = new web3_1.default();
|
142 | var accts = {
|
143 | type: 'accountList',
|
144 | value: opts.accounts
|
145 | };
|
146 | testCallback(undefined, accts);
|
147 | var resp = {
|
148 | type: 'contract',
|
149 | value: testName,
|
150 | filename: testObject.filename
|
151 | };
|
152 | testCallback(undefined, resp);
|
153 | async_1.default.eachOfLimit(runList, 1, function (func, index, next) {
|
154 | var sender = null;
|
155 | if (func.signature) {
|
156 | sender = getOverridedSender(contractDetails.userdoc, func.signature, contractDetails.evm.methodIdentifiers);
|
157 | if (opts.accounts && sender) {
|
158 | sender = opts.accounts[sender];
|
159 | }
|
160 | }
|
161 | var sendParams = null;
|
162 | if (sender)
|
163 | sendParams = { from: sender };
|
164 | var method = testObject.methods[func.name].apply(testObject.methods[func.name], []);
|
165 | var startTime = Date.now();
|
166 | if (func.constant) {
|
167 | method.call(sendParams).then(function (result) {
|
168 | var time = (Date.now() - startTime) / 1000.0;
|
169 | if (result) {
|
170 | var resp_1 = {
|
171 | type: 'testPass',
|
172 | value: changeCase.sentenceCase(func.name),
|
173 | time: time,
|
174 | context: testName
|
175 | };
|
176 | testCallback(undefined, resp_1);
|
177 | passingNum += 1;
|
178 | timePassed += time;
|
179 | }
|
180 | else {
|
181 | var resp_2 = {
|
182 | type: 'testFailure',
|
183 | value: changeCase.sentenceCase(func.name),
|
184 | time: time,
|
185 | errMsg: 'function returned false',
|
186 | context: testName
|
187 | };
|
188 | testCallback(undefined, resp_2);
|
189 | failureNum += 1;
|
190 | }
|
191 | next();
|
192 | });
|
193 | }
|
194 | else {
|
195 | if (func.payable) {
|
196 | var value = getProvidedValue(contractDetails.userdoc, func.signature, contractDetails.evm.methodIdentifiers);
|
197 | if (value) {
|
198 | if (sendParams)
|
199 | sendParams.value = value;
|
200 | else
|
201 | sendParams = { value: value };
|
202 | }
|
203 | }
|
204 | method.send(sendParams).on('receipt', function (receipt) {
|
205 | try {
|
206 | var time = (Date.now() - startTime) / 1000.0;
|
207 | var topic = web3_1.default.utils.sha3('AssertionEvent(bool,string)');
|
208 | var testPassed = false;
|
209 | for (var i in receipt.events) {
|
210 | var event_1 = receipt.events[i];
|
211 | if (event_1.raw.topics.indexOf(topic) >= 0) {
|
212 | var testEvent = web3.eth.abi.decodeParameters(['bool', 'string'], event_1.raw.data);
|
213 | if (!testEvent[0]) {
|
214 | var resp_3 = {
|
215 | type: 'testFailure',
|
216 | value: changeCase.sentenceCase(func.name),
|
217 | time: time,
|
218 | errMsg: testEvent[1],
|
219 | context: testName
|
220 | };
|
221 | testCallback(undefined, resp_3);
|
222 | failureNum += 1;
|
223 | return next();
|
224 | }
|
225 | testPassed = true;
|
226 | }
|
227 | }
|
228 | if (testPassed) {
|
229 | var resp_4 = {
|
230 | type: 'testPass',
|
231 | value: changeCase.sentenceCase(func.name),
|
232 | time: time,
|
233 | context: testName
|
234 | };
|
235 | testCallback(undefined, resp_4);
|
236 | passingNum += 1;
|
237 | }
|
238 | return next();
|
239 | }
|
240 | catch (err) {
|
241 | console.error(err);
|
242 | return next(err);
|
243 | }
|
244 | }).on('error', function (err) {
|
245 | console.error(err);
|
246 | var time = (Date.now() - startTime) / 1000.0;
|
247 | var resp = {
|
248 | type: 'testFailure',
|
249 | value: changeCase.sentenceCase(func.name),
|
250 | time: time,
|
251 | errMsg: err.message,
|
252 | context: testName
|
253 | };
|
254 | testCallback(undefined, resp);
|
255 | failureNum += 1;
|
256 | return next();
|
257 | });
|
258 | }
|
259 | }, function (error) {
|
260 | resultsCallback(error, { passingNum: passingNum, failureNum: failureNum, timePassed: timePassed });
|
261 | });
|
262 | }
|
263 | exports.runTest = runTest;
|
264 |
|
\ | No newline at end of file |