@stacks/rendezvous 0.7.4 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/app.js +13 -7
- package/dist/heatstroke.js +112 -1
- package/dist/invariant.js +34 -8
- package/dist/package.json +1 -1
- package/dist/property.js +25 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -56,6 +56,7 @@ npx rv <path-to-clarinet-project> <contract-name> <type>
|
|
|
56
56
|
- `--path` – The path to use for the replay functionality.
|
|
57
57
|
- `--runs` – The number of test iterations to use for exercising the contracts.
|
|
58
58
|
(default: `100`)
|
|
59
|
+
- `--bail` – Stop after the first failure.
|
|
59
60
|
- `--dial` – The path to a JavaScript file containing custom pre- and
|
|
60
61
|
post-execution functions (dialers).
|
|
61
62
|
|
package/dist/app.js
CHANGED
|
@@ -94,10 +94,12 @@ const helpMessage = `
|
|
|
94
94
|
--seed - The seed to use for the replay functionality.
|
|
95
95
|
--path - The path to use for the replay functionality.
|
|
96
96
|
--runs - The runs to use for iterating over the tests. Default: 100.
|
|
97
|
+
--bail - Stop after the first failure.
|
|
97
98
|
--dial – The path to a JavaScript file containing custom pre- and post-execution functions (dialers).
|
|
98
99
|
--help - Show the help message.
|
|
99
100
|
`;
|
|
100
|
-
const
|
|
101
|
+
const parseBooleanOption = (argName) => process.argv.slice(4).includes(`--${argName}`);
|
|
102
|
+
const parseOption = (argName) => {
|
|
101
103
|
var _a;
|
|
102
104
|
return (_a = process.argv
|
|
103
105
|
.find((arg, idx) => idx >= 4 && arg.toLowerCase().startsWith(`--${argName}`))) === null || _a === void 0 ? void 0 : _a.split("=")[1];
|
|
@@ -140,24 +142,28 @@ function main() {
|
|
|
140
142
|
const manifestPath = (0, path_1.join)(manifestDir, (0, exports.getManifestFileName)(manifestDir, sutContractName));
|
|
141
143
|
radio.emit("logMessage", `Using manifest path: ${manifestPath}`);
|
|
142
144
|
radio.emit("logMessage", `Target contract: ${sutContractName}`);
|
|
143
|
-
const seed = parseInt(
|
|
145
|
+
const seed = parseInt(parseOption("seed"), 10) || undefined;
|
|
144
146
|
if (seed !== undefined) {
|
|
145
147
|
radio.emit("logMessage", `Using seed: ${seed}`);
|
|
146
148
|
}
|
|
147
|
-
const path =
|
|
149
|
+
const path = parseOption("path") || undefined;
|
|
148
150
|
if (path !== undefined) {
|
|
149
151
|
radio.emit("logMessage", `Using path: ${path}`);
|
|
150
152
|
}
|
|
151
|
-
const runs = parseInt(
|
|
153
|
+
const runs = parseInt(parseOption("runs"), 10) || undefined;
|
|
152
154
|
if (runs !== undefined) {
|
|
153
155
|
radio.emit("logMessage", `Using runs: ${runs}`);
|
|
154
156
|
}
|
|
157
|
+
const bail = parseBooleanOption("bail");
|
|
158
|
+
if (bail) {
|
|
159
|
+
radio.emit("logMessage", `Bailing on first failure.`);
|
|
160
|
+
}
|
|
155
161
|
/**
|
|
156
162
|
* The path to the dialer file. The dialer file allows the user to register
|
|
157
163
|
* custom pre and post-execution JavaScript functions to be executed before
|
|
158
164
|
* and after the public function calls during invariant testing.
|
|
159
165
|
*/
|
|
160
|
-
const dialPath =
|
|
166
|
+
const dialPath = parseOption("dial") || undefined;
|
|
161
167
|
if (dialPath !== undefined) {
|
|
162
168
|
radio.emit("logMessage", `Using dial path: ${dialPath}`);
|
|
163
169
|
}
|
|
@@ -181,11 +187,11 @@ function main() {
|
|
|
181
187
|
// If "test", call `checkProperties` for property-based testing.
|
|
182
188
|
switch (type) {
|
|
183
189
|
case "invariant": {
|
|
184
|
-
yield (0, invariant_1.checkInvariants)(simnet, sutContractName, rendezvousList, rendezvousAllFunctions, seed, path, runs, dialerRegistry, radio);
|
|
190
|
+
yield (0, invariant_1.checkInvariants)(simnet, sutContractName, rendezvousList, rendezvousAllFunctions, seed, path, runs, bail, dialerRegistry, radio);
|
|
185
191
|
break;
|
|
186
192
|
}
|
|
187
193
|
case "test": {
|
|
188
|
-
(0, property_1.checkProperties)(simnet, sutContractName, rendezvousList, rendezvousAllFunctions, seed, path, runs, radio);
|
|
194
|
+
(0, property_1.checkProperties)(simnet, sutContractName, rendezvousList, rendezvousAllFunctions, seed, path, runs, bail, radio);
|
|
189
195
|
break;
|
|
190
196
|
}
|
|
191
197
|
}
|
package/dist/heatstroke.js
CHANGED
|
@@ -20,7 +20,7 @@ const shared_1 = require("./shared");
|
|
|
20
20
|
* @param type The type of test that failed: invariant or property.
|
|
21
21
|
* @returns void
|
|
22
22
|
*/
|
|
23
|
-
function reporter(runDetails, radio, type) {
|
|
23
|
+
function reporter(runDetails, radio, type, statistics) {
|
|
24
24
|
var _a, _b;
|
|
25
25
|
if (runDetails.failed) {
|
|
26
26
|
// Report general run data.
|
|
@@ -79,4 +79,115 @@ function reporter(runDetails, radio, type) {
|
|
|
79
79
|
else {
|
|
80
80
|
radio.emit("logMessage", (0, ansicolor_1.green)(`\nOK, ${type === "invariant" ? "invariants" : "properties"} passed after ${runDetails.numRuns} runs.\n`));
|
|
81
81
|
}
|
|
82
|
+
reportStatistics(statistics, type, radio);
|
|
83
|
+
radio.emit("logMessage", "\n");
|
|
82
84
|
}
|
|
85
|
+
const ARROW = "->";
|
|
86
|
+
const SUCCESS_SYMBOL = "+";
|
|
87
|
+
const FAIL_SYMBOL = "-";
|
|
88
|
+
const WARN_SYMBOL = "!";
|
|
89
|
+
/**
|
|
90
|
+
* Reports execution statistics in a tree-like format.
|
|
91
|
+
* @param statistics The statistics object containing test execution data.
|
|
92
|
+
* @param type The type of test being reported.
|
|
93
|
+
* @param radio The event emitter for logging messages.
|
|
94
|
+
*/
|
|
95
|
+
function reportStatistics(statistics, type, radio) {
|
|
96
|
+
if ((type === "invariant" && (!statistics.invariant || !statistics.sut)) ||
|
|
97
|
+
(type === "test" && !statistics.test)) {
|
|
98
|
+
radio.emit("logMessage", "No statistics available for this run");
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
radio.emit("logMessage", `\nEXECUTION STATISTICS\n`);
|
|
102
|
+
switch (type) {
|
|
103
|
+
case "invariant": {
|
|
104
|
+
radio.emit("logMessage", "│ PUBLIC FUNCTION CALLS");
|
|
105
|
+
radio.emit("logMessage", "│");
|
|
106
|
+
radio.emit("logMessage", `├─ ${SUCCESS_SYMBOL} SUCCESSFUL`);
|
|
107
|
+
logAsTree(Object.fromEntries(statistics.sut.successful), radio);
|
|
108
|
+
radio.emit("logMessage", "│");
|
|
109
|
+
radio.emit("logMessage", `├─ ${FAIL_SYMBOL} IGNORED`);
|
|
110
|
+
logAsTree(Object.fromEntries(statistics.sut.failed), radio);
|
|
111
|
+
radio.emit("logMessage", "│");
|
|
112
|
+
radio.emit("logMessage", "│ INVARIANT CHECKS");
|
|
113
|
+
radio.emit("logMessage", "│");
|
|
114
|
+
radio.emit("logMessage", `├─ ${SUCCESS_SYMBOL} PASSED`);
|
|
115
|
+
logAsTree(Object.fromEntries(statistics.invariant.successful), radio);
|
|
116
|
+
radio.emit("logMessage", "│");
|
|
117
|
+
radio.emit("logMessage", `└─ ${FAIL_SYMBOL} FAILED`);
|
|
118
|
+
logAsTree(Object.fromEntries(statistics.invariant.failed), radio, {
|
|
119
|
+
isLastSection: true,
|
|
120
|
+
});
|
|
121
|
+
radio.emit("logMessage", "\nLEGEND:\n");
|
|
122
|
+
radio.emit("logMessage", " SUCCESSFUL calls executed and advanced the test");
|
|
123
|
+
radio.emit("logMessage", " IGNORED calls failed but did not affect the test");
|
|
124
|
+
radio.emit("logMessage", " PASSED invariants maintained system integrity");
|
|
125
|
+
radio.emit("logMessage", " FAILED invariants indicate contract vulnerabilities");
|
|
126
|
+
if (computeTotalCount(statistics.invariant.failed) > 0) {
|
|
127
|
+
radio.emit("logFailure", "\n! FAILED invariants require immediate attention as they indicate that your contract can enter an invalid state under certain conditions.");
|
|
128
|
+
}
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
case "test": {
|
|
132
|
+
radio.emit("logMessage", "│ PROPERTY TEST CALLS");
|
|
133
|
+
radio.emit("logMessage", "│");
|
|
134
|
+
radio.emit("logMessage", `├─ ${SUCCESS_SYMBOL} PASSED`);
|
|
135
|
+
logAsTree(Object.fromEntries(statistics.test.successful), radio);
|
|
136
|
+
radio.emit("logMessage", "│");
|
|
137
|
+
radio.emit("logMessage", `├─ ${WARN_SYMBOL} DISCARDED`);
|
|
138
|
+
logAsTree(Object.fromEntries(statistics.test.discarded), radio);
|
|
139
|
+
radio.emit("logMessage", "│");
|
|
140
|
+
radio.emit("logMessage", `└─ ${FAIL_SYMBOL} FAILED`);
|
|
141
|
+
logAsTree(Object.fromEntries(statistics.test.failed), radio, {
|
|
142
|
+
isLastSection: true,
|
|
143
|
+
});
|
|
144
|
+
radio.emit("logMessage", "\nLEGEND:\n");
|
|
145
|
+
radio.emit("logMessage", " PASSED properties verified for given inputs");
|
|
146
|
+
radio.emit("logMessage", " DISCARDED skipped due to invalid preconditions");
|
|
147
|
+
radio.emit("logMessage", " FAILED property violations or unexpected behavior");
|
|
148
|
+
if (computeTotalCount(statistics.test.failed) > 0) {
|
|
149
|
+
radio.emit("logFailure", "\n! FAILED tests indicate that your function properties don't hold for all inputs. Review the counterexamples above for debugging.");
|
|
150
|
+
}
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Displays a tree structure of data.
|
|
157
|
+
* @param tree The object to display as a tree.
|
|
158
|
+
* @param radio The event emitter for logging messages.
|
|
159
|
+
* @param options Configuration options for tree display.
|
|
160
|
+
*/
|
|
161
|
+
function logAsTree(tree, radio, options = {}) {
|
|
162
|
+
const { isLastSection = false, baseIndent = " " } = options;
|
|
163
|
+
const printTree = (node, indent = baseIndent, isLastParent = true, radio) => {
|
|
164
|
+
const keys = Object.keys(node);
|
|
165
|
+
keys.forEach((key, index) => {
|
|
166
|
+
const isLast = index === keys.length - 1;
|
|
167
|
+
const connector = isLast ? "└─" : "├─";
|
|
168
|
+
const nextIndent = indent + (isLastParent ? " " : "│ ");
|
|
169
|
+
const leadingChar = isLastSection ? " " : "│";
|
|
170
|
+
if (typeof node[key] === "object" && node[key] !== null) {
|
|
171
|
+
radio.emit("logMessage", `${leadingChar} ${indent}${connector} ${ARROW} ${key}`);
|
|
172
|
+
printTree(node[key], nextIndent, isLast, radio);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
const count = node[key];
|
|
176
|
+
radio.emit("logMessage", `${leadingChar} ${indent}${connector} ${key}: x${count}`);
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
printTree(tree, baseIndent, true, radio);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Computes the total number of failures from a failure map.
|
|
184
|
+
* @param failedMap Map containing failure counts by test name
|
|
185
|
+
* @returns The sum of all failure counts
|
|
186
|
+
*/
|
|
187
|
+
const computeTotalCount = (failedMap) => {
|
|
188
|
+
let totalFailures = 0;
|
|
189
|
+
for (const count of failedMap.values()) {
|
|
190
|
+
totalFailures += count;
|
|
191
|
+
}
|
|
192
|
+
return totalFailures;
|
|
193
|
+
};
|
package/dist/invariant.js
CHANGED
|
@@ -31,22 +31,42 @@ const dialer_1 = require("./dialer");
|
|
|
31
31
|
* @param seed The seed for reproducible invariant testing.
|
|
32
32
|
* @param path The path for reproducible invariant testing.
|
|
33
33
|
* @param runs The number of test runs.
|
|
34
|
+
* @param bail Stop execution after the first failure and prevent further
|
|
35
|
+
* shrinking.
|
|
34
36
|
* @param dialerRegistry The custom dialer registry.
|
|
35
37
|
* @param radio The custom logging event emitter.
|
|
36
38
|
* @returns void
|
|
37
39
|
*/
|
|
38
|
-
const checkInvariants = (simnet, targetContractName, rendezvousList, rendezvousAllFunctions, seed, path, runs, dialerRegistry, radio) => __awaiter(void 0, void 0, void 0, function* () {
|
|
40
|
+
const checkInvariants = (simnet, targetContractName, rendezvousList, rendezvousAllFunctions, seed, path, runs, bail, dialerRegistry, radio) => __awaiter(void 0, void 0, void 0, function* () {
|
|
41
|
+
const statistics = {
|
|
42
|
+
sut: {
|
|
43
|
+
successful: new Map(),
|
|
44
|
+
failed: new Map(),
|
|
45
|
+
},
|
|
46
|
+
invariant: {
|
|
47
|
+
successful: new Map(),
|
|
48
|
+
failed: new Map(),
|
|
49
|
+
},
|
|
50
|
+
};
|
|
39
51
|
// A map where the keys are the Rendezvous identifiers and the values are
|
|
40
52
|
// arrays of their SUT (System Under Test) functions. This map will be used
|
|
41
53
|
// to access the SUT functions for each Rendezvous contract afterwards.
|
|
42
54
|
const rendezvousSutFunctions = filterSutFunctions(rendezvousAllFunctions);
|
|
55
|
+
// The Rendezvous identifier is the first one in the list. Only one contract
|
|
56
|
+
// can be fuzzed at a time.
|
|
57
|
+
const rendezvousContractId = rendezvousList[0];
|
|
58
|
+
for (const functionInterface of rendezvousSutFunctions.get(rendezvousContractId)) {
|
|
59
|
+
statistics.sut.successful.set(functionInterface.name, 0);
|
|
60
|
+
statistics.sut.failed.set(functionInterface.name, 0);
|
|
61
|
+
}
|
|
43
62
|
// A map where the keys are the Rendezvous identifiers and the values are
|
|
44
63
|
// arrays of their invariant functions. This map will be used to access the
|
|
45
64
|
// invariant functions for each Rendezvous contract afterwards.
|
|
46
65
|
const rendezvousInvariantFunctions = filterInvariantFunctions(rendezvousAllFunctions);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
66
|
+
for (const functionInterface of rendezvousInvariantFunctions.get(rendezvousContractId)) {
|
|
67
|
+
statistics.invariant.successful.set(functionInterface.name, 0);
|
|
68
|
+
statistics.invariant.failed.set(functionInterface.name, 0);
|
|
69
|
+
}
|
|
50
70
|
const traitReferenceSutFunctions = rendezvousSutFunctions
|
|
51
71
|
.get(rendezvousContractId)
|
|
52
72
|
.filter((fn) => (0, traits_1.isTraitReferenceFunction)(fn));
|
|
@@ -93,7 +113,7 @@ const checkInvariants = (simnet, targetContractName, rendezvousList, rendezvousA
|
|
|
93
113
|
return;
|
|
94
114
|
}
|
|
95
115
|
const radioReporter = (runDetails) => {
|
|
96
|
-
(0, heatstroke_1.reporter)(runDetails, radio, "invariant");
|
|
116
|
+
(0, heatstroke_1.reporter)(runDetails, radio, "invariant", statistics);
|
|
97
117
|
};
|
|
98
118
|
yield fast_check_1.default.assert(fast_check_1.default.asyncProperty(fast_check_1.default
|
|
99
119
|
.record({
|
|
@@ -176,6 +196,7 @@ const checkInvariants = (simnet, targetContractName, rendezvousList, rendezvousA
|
|
|
176
196
|
// call during the run.
|
|
177
197
|
const selectedFunctionClarityResult = (0, transactions_1.cvToString)(functionCall.result);
|
|
178
198
|
if (functionCallResultJson.success) {
|
|
199
|
+
statistics.sut.successful.set(selectedFunction.name, statistics.sut.successful.get(selectedFunction.name) + 1);
|
|
179
200
|
localContext[r.rendezvousContractId][selectedFunction.name]++;
|
|
180
201
|
simnet.callPublicFn(r.rendezvousContractId, "update-context", [
|
|
181
202
|
transactions_1.Cl.stringAscii(selectedFunction.name),
|
|
@@ -204,6 +225,7 @@ const checkInvariants = (simnet, targetContractName, rendezvousList, rendezvousA
|
|
|
204
225
|
}
|
|
205
226
|
else {
|
|
206
227
|
// Function call failed.
|
|
228
|
+
statistics.sut.failed.set(selectedFunction.name, statistics.sut.failed.get(selectedFunction.name) + 1);
|
|
207
229
|
radio.emit("logMessage", (0, ansicolor_1.dim)(`₿ ${simnet.burnBlockHeight.toString().padStart(8)} ` +
|
|
208
230
|
`Ӿ ${simnet.blockHeight.toString().padStart(8)} ` +
|
|
209
231
|
`${sutCallerWallet} ` +
|
|
@@ -255,6 +277,8 @@ const checkInvariants = (simnet, targetContractName, rendezvousList, rendezvousA
|
|
|
255
277
|
const invariantCallResultJson = (0, transactions_1.cvToJSON)(invariantCallResult);
|
|
256
278
|
const invariantCallClarityResult = (0, transactions_1.cvToString)(invariantCallResult);
|
|
257
279
|
if (invariantCallResultJson.value === true) {
|
|
280
|
+
statistics.invariant.successful.set(r.selectedInvariant.name, statistics.invariant.successful.get(r.selectedInvariant.name) +
|
|
281
|
+
1);
|
|
258
282
|
radio.emit("logMessage", `₿ ${simnet.burnBlockHeight.toString().padStart(8)} ` +
|
|
259
283
|
`Ӿ ${simnet.blockHeight.toString().padStart(8)} ` +
|
|
260
284
|
`${(0, ansicolor_1.dim)(invariantCallerWallet)} ` +
|
|
@@ -265,6 +289,7 @@ const checkInvariants = (simnet, targetContractName, rendezvousList, rendezvousA
|
|
|
265
289
|
(0, ansicolor_1.green)(invariantCallClarityResult));
|
|
266
290
|
}
|
|
267
291
|
else {
|
|
292
|
+
statistics.invariant.failed.set(r.selectedInvariant.name, statistics.invariant.failed.get(r.selectedInvariant.name) + 1);
|
|
268
293
|
radio.emit("logMessage", (0, ansicolor_1.red)(`₿ ${simnet.burnBlockHeight.toString().padStart(8)} ` +
|
|
269
294
|
`Ӿ ${simnet.blockHeight.toString().padStart(8)} ` +
|
|
270
295
|
`${invariantCallerWallet} ` +
|
|
@@ -298,11 +323,12 @@ const checkInvariants = (simnet, targetContractName, rendezvousList, rendezvousA
|
|
|
298
323
|
simnet.mineEmptyBurnBlocks(r.burnBlocks);
|
|
299
324
|
}
|
|
300
325
|
})), {
|
|
301
|
-
|
|
326
|
+
endOnFailure: bail,
|
|
327
|
+
numRuns: runs,
|
|
328
|
+
path: path,
|
|
302
329
|
reporter: radioReporter,
|
|
303
330
|
seed: seed,
|
|
304
|
-
|
|
305
|
-
numRuns: runs,
|
|
331
|
+
verbose: true,
|
|
306
332
|
});
|
|
307
333
|
});
|
|
308
334
|
exports.checkInvariants = checkInvariants;
|
package/dist/package.json
CHANGED
package/dist/property.js
CHANGED
|
@@ -21,15 +21,29 @@ const traits_1 = require("./traits");
|
|
|
21
21
|
* @param seed The seed for reproducible property-based tests.
|
|
22
22
|
* @param path The path for reproducible property-based tests.
|
|
23
23
|
* @param runs The number of test runs.
|
|
24
|
+
* @param bail Stop execution after the first failure and prevent further
|
|
25
|
+
* shrinking.
|
|
24
26
|
* @param radio The custom logging event emitter.
|
|
25
27
|
* @returns void
|
|
26
28
|
*/
|
|
27
|
-
const checkProperties = (simnet, targetContractName, rendezvousList, rendezvousAllFunctions, seed, path, runs, radio) => {
|
|
29
|
+
const checkProperties = (simnet, targetContractName, rendezvousList, rendezvousAllFunctions, seed, path, runs, bail, radio) => {
|
|
30
|
+
const statistics = {
|
|
31
|
+
test: {
|
|
32
|
+
successful: new Map(),
|
|
33
|
+
discarded: new Map(),
|
|
34
|
+
failed: new Map(),
|
|
35
|
+
},
|
|
36
|
+
};
|
|
28
37
|
const testContractId = rendezvousList[0];
|
|
29
38
|
// A map where the keys are the test contract identifiers and the values are
|
|
30
39
|
// arrays of their test functions. This map will be used to access the test
|
|
31
40
|
// functions for each test contract in the property-based testing routine.
|
|
32
41
|
const testContractsTestFunctions = filterTestFunctions(rendezvousAllFunctions);
|
|
42
|
+
for (const functionInterface of testContractsTestFunctions.get(testContractId)) {
|
|
43
|
+
statistics.test.successful.set(functionInterface.name, 0);
|
|
44
|
+
statistics.test.discarded.set(functionInterface.name, 0);
|
|
45
|
+
statistics.test.failed.set(functionInterface.name, 0);
|
|
46
|
+
}
|
|
33
47
|
const traitReferenceFunctions = testContractsTestFunctions
|
|
34
48
|
.get(testContractId)
|
|
35
49
|
.filter((fn) => (0, traits_1.isTraitReferenceFunction)(fn));
|
|
@@ -79,7 +93,7 @@ const checkProperties = (simnet, targetContractName, rendezvousList, rendezvousA
|
|
|
79
93
|
return;
|
|
80
94
|
}
|
|
81
95
|
const radioReporter = (runDetails) => {
|
|
82
|
-
(0, heatstroke_1.reporter)(runDetails, radio, "test");
|
|
96
|
+
(0, heatstroke_1.reporter)(runDetails, radio, "test", statistics);
|
|
83
97
|
};
|
|
84
98
|
fast_check_1.default.assert(fast_check_1.default.property(fast_check_1.default
|
|
85
99
|
.record({
|
|
@@ -132,6 +146,7 @@ const checkProperties = (simnet, targetContractName, rendezvousList, rendezvousA
|
|
|
132
146
|
.get(r.selectedTestFunction.name);
|
|
133
147
|
const discarded = isTestDiscarded(discardFunctionName, selectedTestFunctionArgs, r.testContractId, simnet, testCallerAddress);
|
|
134
148
|
if (discarded) {
|
|
149
|
+
statistics.test.discarded.set(r.selectedTestFunction.name, statistics.test.discarded.get(r.selectedTestFunction.name) + 1);
|
|
135
150
|
radio.emit("logMessage", `₿ ${simnet.burnBlockHeight.toString().padStart(8)} ` +
|
|
136
151
|
`Ӿ ${simnet.blockHeight.toString().padStart(8)} ` +
|
|
137
152
|
`${(0, ansicolor_1.dim)(testCallerWallet)} ` +
|
|
@@ -149,6 +164,7 @@ const checkProperties = (simnet, targetContractName, rendezvousList, rendezvousA
|
|
|
149
164
|
const discardedInPlace = (0, exports.isTestDiscardedInPlace)(testFunctionCallResultJson);
|
|
150
165
|
const testFunctionCallClarityResult = (0, transactions_1.cvToString)(testFunctionCallResult);
|
|
151
166
|
if (discardedInPlace) {
|
|
167
|
+
statistics.test.discarded.set(r.selectedTestFunction.name, statistics.test.discarded.get(r.selectedTestFunction.name) + 1);
|
|
152
168
|
radio.emit("logMessage", `₿ ${simnet.burnBlockHeight.toString().padStart(8)} ` +
|
|
153
169
|
`Ӿ ${simnet.blockHeight.toString().padStart(8)} ` +
|
|
154
170
|
`${(0, ansicolor_1.dim)(testCallerWallet)} ` +
|
|
@@ -161,6 +177,8 @@ const checkProperties = (simnet, targetContractName, rendezvousList, rendezvousA
|
|
|
161
177
|
else if (!discardedInPlace &&
|
|
162
178
|
testFunctionCallResultJson.success &&
|
|
163
179
|
testFunctionCallResultJson.value.value === true) {
|
|
180
|
+
statistics.test.successful.set(r.selectedTestFunction.name, statistics.test.successful.get(r.selectedTestFunction.name) +
|
|
181
|
+
1);
|
|
164
182
|
radio.emit("logMessage", `₿ ${simnet.burnBlockHeight.toString().padStart(8)} ` +
|
|
165
183
|
`Ӿ ${simnet.blockHeight.toString().padStart(8)} ` +
|
|
166
184
|
`${(0, ansicolor_1.dim)(testCallerWallet)} ` +
|
|
@@ -174,6 +192,7 @@ const checkProperties = (simnet, targetContractName, rendezvousList, rendezvousA
|
|
|
174
192
|
}
|
|
175
193
|
}
|
|
176
194
|
else {
|
|
195
|
+
statistics.test.failed.set(r.selectedTestFunction.name, statistics.test.failed.get(r.selectedTestFunction.name) + 1);
|
|
177
196
|
// The function call did not result in (ok true) or (ok false).
|
|
178
197
|
// Either the test failed or the test function returned an
|
|
179
198
|
// unexpected value i.e. `(ok 1)`.
|
|
@@ -202,11 +221,12 @@ const checkProperties = (simnet, targetContractName, rendezvousList, rendezvousA
|
|
|
202
221
|
}
|
|
203
222
|
}
|
|
204
223
|
}), {
|
|
205
|
-
|
|
224
|
+
endOnFailure: bail,
|
|
225
|
+
numRuns: runs,
|
|
226
|
+
path: path,
|
|
206
227
|
reporter: radioReporter,
|
|
207
228
|
seed: seed,
|
|
208
|
-
|
|
209
|
-
numRuns: runs,
|
|
229
|
+
verbose: true,
|
|
210
230
|
});
|
|
211
231
|
};
|
|
212
232
|
exports.checkProperties = checkProperties;
|