as-test 1.1.0 → 1.1.2
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/CHANGELOG.md +17 -3
- package/README.md +14 -7
- package/as-test.config.schema.json +142 -142
- package/assembly/__fuzz__/math.fuzz.ts +22 -0
- package/assembly/__fuzz__/seed-perf.fuzz.ts +4 -2
- package/assembly/__fuzz__/string.fuzz.ts +31 -0
- package/assembly/index.ts +6 -9
- package/assembly/src/expectation.ts +99 -42
- package/assembly/src/fuzz.ts +44 -23
- package/assembly/util/format.ts +113 -0
- package/assembly/util/helpers.ts +7 -13
- package/assembly/util/json.ts +2 -2
- package/assembly/util/wipc.ts +5 -3
- package/bin/build-worker-pool.js +7 -1
- package/bin/commands/build-core.js +6 -1
- package/bin/commands/build.js +1 -1
- package/bin/commands/clean-core.js +61 -16
- package/bin/commands/clean.js +11 -3
- package/bin/commands/fuzz-core.js +2 -2
- package/bin/commands/run-core.js +35 -24
- package/bin/commands/web-runner-source.js +14 -14
- package/bin/commands/web-session.js +6 -1
- package/bin/crash-store.js +3 -1
- package/bin/index.js +303 -124
- package/bin/reporters/default.js +175 -33
- package/bin/util.js +36 -11
- package/bin/wipc.js +7 -2
- package/lib/build/index.js +93 -25
- package/lib/src/index.ts +115 -36
- package/package.json +1 -3
- package/transform/lib/coverage.js +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 2026-05-13 - v1.1.2
|
|
4
|
+
|
|
5
|
+
- update build and run faliures to provide helpful error messages and reproduction commands and instructions
|
|
6
|
+
- remove confirmation from ast clean
|
|
7
|
+
|
|
8
|
+
## 2026-05-12 -v1.1.1
|
|
9
|
+
|
|
10
|
+
- add `ast clean` command to remove build outputs, coverage outputs, crash reports, and logs.
|
|
11
|
+
- remove deps
|
|
12
|
+
|
|
13
|
+
## 2026-05-12 -v1.1.0
|
|
4
14
|
|
|
5
15
|
### Upgrading to 1.1.0
|
|
6
16
|
|
|
@@ -40,9 +50,13 @@
|
|
|
40
50
|
### Modes & CLI
|
|
41
51
|
|
|
42
52
|
- feat: add per-mode `default: boolean` selection so modes can be included in implicit runs or kept manual-only.
|
|
43
|
-
- feat: add `ast clean` to remove configured build outputs, crash reports, and logs
|
|
53
|
+
- feat: add `ast clean` to remove configured build outputs, coverage outputs, crash reports, and logs.
|
|
54
|
+
- feat: make `ast clean` remove everything by default without prompting.
|
|
44
55
|
- fix: restore unnamed root-config execution alongside named default modes when `--mode` is omitted.
|
|
45
|
-
- fix: make `ast clean
|
|
56
|
+
- fix: make `ast clean` ignore mode `default: false` flags and treat an omitted `--mode` as a full clean across every configured mode.
|
|
57
|
+
- fix: make `ast clean --mode ...` stay scoped to the selected mode(s) and skip shared output paths that are still owned by unselected modes instead of deleting them.
|
|
58
|
+
- fix: make full `ast clean` remove the configured output roots directly so stale legacy build, coverage, and log directories are removed too.
|
|
59
|
+
- fix: simplify `ast clean` console output so it only prints removed paths plus a final summary.
|
|
46
60
|
|
|
47
61
|
### Tests
|
|
48
62
|
|
package/README.md
CHANGED
|
@@ -253,18 +253,25 @@ fuzz("bounded integer addition", (left: i32, right: i32): bool => {
|
|
|
253
253
|
Pass a third argument to override the operation count for one target without changing the global fuzz config:
|
|
254
254
|
|
|
255
255
|
```ts
|
|
256
|
-
fuzz(
|
|
257
|
-
|
|
258
|
-
|
|
256
|
+
fuzz(
|
|
257
|
+
"hot path stays stable",
|
|
258
|
+
(): void => {
|
|
259
|
+
expect(1 + 1).toBe(2);
|
|
260
|
+
},
|
|
261
|
+
250,
|
|
262
|
+
);
|
|
259
263
|
```
|
|
260
264
|
|
|
261
265
|
Or pass it as the second argument to `.generate(...)`:
|
|
262
266
|
|
|
263
267
|
```ts
|
|
264
|
-
fuzz(
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
+
fuzz(
|
|
269
|
+
"ascii strings survive concatenation boundaries",
|
|
270
|
+
(input: string): bool => {
|
|
271
|
+
expect(input.length <= 40).toBe(true);
|
|
272
|
+
return true;
|
|
273
|
+
},
|
|
274
|
+
).generate((seed: FuzzSeed, run: (input: string) => bool): void => {
|
|
268
275
|
run(seed.string({ charset: "ascii", min: 0, max: 40 }));
|
|
269
276
|
}, 250);
|
|
270
277
|
```
|
|
@@ -336,168 +336,190 @@
|
|
|
336
336
|
}
|
|
337
337
|
]
|
|
338
338
|
},
|
|
339
|
-
|
|
340
|
-
"type": "string",
|
|
341
|
-
"description": "Mode-specific build output directory. If omitted, defaults to <outDir>/<mode-name>."
|
|
342
|
-
},
|
|
343
|
-
"logs": {
|
|
344
|
-
"type": "string",
|
|
345
|
-
"description": "Mode-specific log output directory."
|
|
346
|
-
},
|
|
347
|
-
"coverageDir": {
|
|
348
|
-
"type": "string",
|
|
349
|
-
"description": "Mode-specific coverage output directory."
|
|
350
|
-
},
|
|
351
|
-
"snapshotDir": {
|
|
352
|
-
"type": "string",
|
|
353
|
-
"description": "Mode-specific snapshot directory."
|
|
354
|
-
},
|
|
355
|
-
"config": {
|
|
356
|
-
"type": "string",
|
|
357
|
-
"description": "Mode-specific asconfig path or \"none\"."
|
|
358
|
-
},
|
|
359
|
-
"coverage": {
|
|
360
|
-
"description": "Mode-specific coverage settings.",
|
|
361
|
-
"oneOf": [
|
|
362
|
-
{
|
|
363
|
-
"type": "boolean"
|
|
364
|
-
},
|
|
365
|
-
{
|
|
366
|
-
"type": "object",
|
|
367
|
-
"additionalProperties": true,
|
|
368
|
-
"properties": {
|
|
369
|
-
"enabled": {
|
|
370
|
-
"type": "boolean"
|
|
371
|
-
},
|
|
372
|
-
"includeSpecs": {
|
|
373
|
-
"type": "boolean"
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
]
|
|
378
|
-
},
|
|
379
|
-
"fuzz": {
|
|
380
|
-
"type": "object",
|
|
381
|
-
"additionalProperties": false,
|
|
382
|
-
"description": "Mode-specific fuzz overrides applied before running `ast fuzz` or `ast test --fuzz` in this mode.",
|
|
383
|
-
"properties": {
|
|
384
|
-
"input": {
|
|
385
|
-
"type": "array",
|
|
386
|
-
"items": {
|
|
387
|
-
"type": "string"
|
|
388
|
-
}
|
|
389
|
-
},
|
|
390
|
-
"runs": {
|
|
391
|
-
"type": "number"
|
|
392
|
-
},
|
|
393
|
-
"seed": {
|
|
394
|
-
"type": "number"
|
|
395
|
-
},
|
|
396
|
-
"maxInputBytes": {
|
|
397
|
-
"type": "number"
|
|
398
|
-
},
|
|
399
|
-
"target": {
|
|
339
|
+
"outDir": {
|
|
400
340
|
"type": "string",
|
|
401
|
-
"
|
|
341
|
+
"description": "Mode-specific build output directory. If omitted, defaults to <outDir>/<mode-name>."
|
|
402
342
|
},
|
|
403
|
-
"
|
|
404
|
-
"type": "string"
|
|
343
|
+
"logs": {
|
|
344
|
+
"type": "string",
|
|
345
|
+
"description": "Mode-specific log output directory."
|
|
405
346
|
},
|
|
406
|
-
"
|
|
407
|
-
"type": "string"
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
},
|
|
411
|
-
"buildOptions": {
|
|
412
|
-
"type": "object",
|
|
413
|
-
"additionalProperties": false,
|
|
414
|
-
"properties": {
|
|
415
|
-
"cmd": {
|
|
347
|
+
"coverageDir": {
|
|
416
348
|
"type": "string",
|
|
417
|
-
"description": "Mode-specific
|
|
349
|
+
"description": "Mode-specific coverage output directory."
|
|
418
350
|
},
|
|
419
|
-
"
|
|
420
|
-
"type": "
|
|
421
|
-
"
|
|
422
|
-
"type": "string"
|
|
423
|
-
}
|
|
351
|
+
"snapshotDir": {
|
|
352
|
+
"type": "string",
|
|
353
|
+
"description": "Mode-specific snapshot directory."
|
|
424
354
|
},
|
|
425
|
-
"
|
|
355
|
+
"config": {
|
|
426
356
|
"type": "string",
|
|
427
|
-
"
|
|
357
|
+
"description": "Mode-specific asconfig path or \"none\"."
|
|
428
358
|
},
|
|
429
|
-
"
|
|
430
|
-
"description": "Mode-specific
|
|
359
|
+
"coverage": {
|
|
360
|
+
"description": "Mode-specific coverage settings.",
|
|
431
361
|
"oneOf": [
|
|
432
362
|
{
|
|
433
|
-
"type": "
|
|
363
|
+
"type": "boolean"
|
|
434
364
|
},
|
|
435
365
|
{
|
|
366
|
+
"type": "object",
|
|
367
|
+
"additionalProperties": true,
|
|
368
|
+
"properties": {
|
|
369
|
+
"enabled": {
|
|
370
|
+
"type": "boolean"
|
|
371
|
+
},
|
|
372
|
+
"includeSpecs": {
|
|
373
|
+
"type": "boolean"
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
]
|
|
378
|
+
},
|
|
379
|
+
"fuzz": {
|
|
380
|
+
"type": "object",
|
|
381
|
+
"additionalProperties": false,
|
|
382
|
+
"description": "Mode-specific fuzz overrides applied before running `ast fuzz` or `ast test --fuzz` in this mode.",
|
|
383
|
+
"properties": {
|
|
384
|
+
"input": {
|
|
436
385
|
"type": "array",
|
|
437
386
|
"items": {
|
|
438
387
|
"type": "string"
|
|
439
388
|
}
|
|
440
389
|
},
|
|
441
|
-
{
|
|
442
|
-
"type": "
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
390
|
+
"runs": {
|
|
391
|
+
"type": "number"
|
|
392
|
+
},
|
|
393
|
+
"seed": {
|
|
394
|
+
"type": "number"
|
|
395
|
+
},
|
|
396
|
+
"maxInputBytes": {
|
|
397
|
+
"type": "number"
|
|
398
|
+
},
|
|
399
|
+
"target": {
|
|
400
|
+
"type": "string",
|
|
401
|
+
"enum": ["bindings"]
|
|
402
|
+
},
|
|
403
|
+
"corpusDir": {
|
|
404
|
+
"type": "string"
|
|
405
|
+
},
|
|
406
|
+
"crashDir": {
|
|
407
|
+
"type": "string"
|
|
446
408
|
}
|
|
447
|
-
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
},
|
|
451
|
-
"runOptions": {
|
|
452
|
-
"type": "object",
|
|
453
|
-
"additionalProperties": false,
|
|
454
|
-
"properties": {
|
|
455
|
-
"runtime": {
|
|
409
|
+
}
|
|
410
|
+
},
|
|
411
|
+
"buildOptions": {
|
|
456
412
|
"type": "object",
|
|
457
413
|
"additionalProperties": false,
|
|
458
414
|
"properties": {
|
|
459
415
|
"cmd": {
|
|
460
416
|
"type": "string",
|
|
461
|
-
"description": "Mode-specific
|
|
417
|
+
"description": "Mode-specific custom build command template."
|
|
418
|
+
},
|
|
419
|
+
"args": {
|
|
420
|
+
"type": "array",
|
|
421
|
+
"items": {
|
|
422
|
+
"type": "string"
|
|
423
|
+
}
|
|
462
424
|
},
|
|
463
|
-
"
|
|
425
|
+
"target": {
|
|
464
426
|
"type": "string",
|
|
465
|
-
"
|
|
427
|
+
"enum": ["wasi", "bindings", "web"]
|
|
428
|
+
},
|
|
429
|
+
"env": {
|
|
430
|
+
"description": "Mode-specific build environment overrides.",
|
|
431
|
+
"oneOf": [
|
|
432
|
+
{
|
|
433
|
+
"type": "string"
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
"type": "array",
|
|
437
|
+
"items": {
|
|
438
|
+
"type": "string"
|
|
439
|
+
}
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
"type": "object",
|
|
443
|
+
"additionalProperties": {
|
|
444
|
+
"type": "string"
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
]
|
|
466
448
|
}
|
|
467
449
|
}
|
|
468
450
|
},
|
|
469
|
-
"
|
|
470
|
-
"
|
|
471
|
-
"
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
},
|
|
475
|
-
{
|
|
451
|
+
"runOptions": {
|
|
452
|
+
"type": "object",
|
|
453
|
+
"additionalProperties": false,
|
|
454
|
+
"properties": {
|
|
455
|
+
"runtime": {
|
|
476
456
|
"type": "object",
|
|
477
457
|
"additionalProperties": false,
|
|
478
458
|
"properties": {
|
|
479
|
-
"
|
|
459
|
+
"cmd": {
|
|
460
|
+
"type": "string",
|
|
461
|
+
"description": "Mode-specific runtime command."
|
|
462
|
+
},
|
|
463
|
+
"browser": {
|
|
464
|
+
"type": "string",
|
|
465
|
+
"description": "Mode-specific browser for web targets. Use chrome, chromium, firefox, webkit, or an executable path."
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
},
|
|
469
|
+
"reporter": {
|
|
470
|
+
"description": "Mode-specific reporter config.",
|
|
471
|
+
"oneOf": [
|
|
472
|
+
{
|
|
480
473
|
"type": "string"
|
|
481
474
|
},
|
|
482
|
-
|
|
475
|
+
{
|
|
476
|
+
"type": "object",
|
|
477
|
+
"additionalProperties": false,
|
|
478
|
+
"properties": {
|
|
479
|
+
"name": {
|
|
480
|
+
"type": "string"
|
|
481
|
+
},
|
|
482
|
+
"options": {
|
|
483
|
+
"type": "array",
|
|
484
|
+
"items": {
|
|
485
|
+
"type": "string"
|
|
486
|
+
}
|
|
487
|
+
},
|
|
488
|
+
"outDir": {
|
|
489
|
+
"type": "string"
|
|
490
|
+
},
|
|
491
|
+
"outFile": {
|
|
492
|
+
"type": "string"
|
|
493
|
+
}
|
|
494
|
+
},
|
|
495
|
+
"required": ["name"]
|
|
496
|
+
}
|
|
497
|
+
]
|
|
498
|
+
},
|
|
499
|
+
"env": {
|
|
500
|
+
"description": "Mode-specific runtime environment overrides.",
|
|
501
|
+
"oneOf": [
|
|
502
|
+
{
|
|
503
|
+
"type": "string"
|
|
504
|
+
},
|
|
505
|
+
{
|
|
483
506
|
"type": "array",
|
|
484
507
|
"items": {
|
|
485
508
|
"type": "string"
|
|
486
509
|
}
|
|
487
510
|
},
|
|
488
|
-
|
|
489
|
-
"type": "
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
511
|
+
{
|
|
512
|
+
"type": "object",
|
|
513
|
+
"additionalProperties": {
|
|
514
|
+
"type": "string"
|
|
515
|
+
}
|
|
493
516
|
}
|
|
494
|
-
|
|
495
|
-
"required": ["name"]
|
|
517
|
+
]
|
|
496
518
|
}
|
|
497
|
-
|
|
519
|
+
}
|
|
498
520
|
},
|
|
499
521
|
"env": {
|
|
500
|
-
"description": "Mode-
|
|
522
|
+
"description": "Mode-wide environment variables merged before build/run-specific env.",
|
|
501
523
|
"oneOf": [
|
|
502
524
|
{
|
|
503
525
|
"type": "string"
|
|
@@ -517,28 +539,6 @@
|
|
|
517
539
|
]
|
|
518
540
|
}
|
|
519
541
|
}
|
|
520
|
-
},
|
|
521
|
-
"env": {
|
|
522
|
-
"description": "Mode-wide environment variables merged before build/run-specific env.",
|
|
523
|
-
"oneOf": [
|
|
524
|
-
{
|
|
525
|
-
"type": "string"
|
|
526
|
-
},
|
|
527
|
-
{
|
|
528
|
-
"type": "array",
|
|
529
|
-
"items": {
|
|
530
|
-
"type": "string"
|
|
531
|
-
}
|
|
532
|
-
},
|
|
533
|
-
{
|
|
534
|
-
"type": "object",
|
|
535
|
-
"additionalProperties": {
|
|
536
|
-
"type": "string"
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
]
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
542
|
}
|
|
543
543
|
]
|
|
544
544
|
},
|
|
@@ -7,3 +7,25 @@ fuzz("bounded integer addition", (left: i32, right: i32): bool => {
|
|
|
7
7
|
}).generate((seed: FuzzSeed, run: (left: i32, right: i32) => bool): void => {
|
|
8
8
|
run(seed.i32({ min: -1000, max: 1000 }), seed.i32({ min: -1000, max: 1000 }));
|
|
9
9
|
});
|
|
10
|
+
|
|
11
|
+
fuzz(
|
|
12
|
+
"numeric matchers stay consistent for bounded integers",
|
|
13
|
+
(value: i32): bool => {
|
|
14
|
+
expect(value).toBeNumber();
|
|
15
|
+
expect(value).toBeInteger();
|
|
16
|
+
expect(value).toBeFinite();
|
|
17
|
+
expect(value).toBe(value);
|
|
18
|
+
expect(value).toBeGreaterOrEqualTo(-1000);
|
|
19
|
+
expect(value).toBeLessThanOrEqualTo(1000);
|
|
20
|
+
|
|
21
|
+
if (value != 0) {
|
|
22
|
+
expect(value).toBeTruthy();
|
|
23
|
+
} else {
|
|
24
|
+
expect(value).toBeFalsy();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return true;
|
|
28
|
+
},
|
|
29
|
+
).generate((seed: FuzzSeed, run: (value: i32) => bool): void => {
|
|
30
|
+
run(seed.i32({ min: -1000, max: 1000 }));
|
|
31
|
+
}, 250);
|
|
@@ -59,8 +59,10 @@ fuzz("seed perf bytes/array", (_n: i32): bool => true).generate(
|
|
|
59
59
|
let score = 0;
|
|
60
60
|
for (let i = 0; i < 64; i++) {
|
|
61
61
|
score += seed.bytes(PERF_BYTES).length;
|
|
62
|
-
score += seed.array<i32>(
|
|
63
|
-
.
|
|
62
|
+
score += seed.array<i32>(
|
|
63
|
+
(s) => s.i32({ min: -9, max: 9 }),
|
|
64
|
+
PERF_ARRAY,
|
|
65
|
+
).length;
|
|
64
66
|
}
|
|
65
67
|
run(score);
|
|
66
68
|
},
|
|
@@ -19,3 +19,34 @@ fuzz(
|
|
|
19
19
|
}),
|
|
20
20
|
);
|
|
21
21
|
}, 250);
|
|
22
|
+
|
|
23
|
+
fuzz(
|
|
24
|
+
"string matchers stay consistent on derived slices",
|
|
25
|
+
(input: string): bool => {
|
|
26
|
+
const split = input.length >> 1;
|
|
27
|
+
const prefix = input.substr(0, split);
|
|
28
|
+
const suffix = input.substr(split);
|
|
29
|
+
|
|
30
|
+
expect(input).toBeString();
|
|
31
|
+
expect(input).toContain(prefix);
|
|
32
|
+
expect(input).toMatch(suffix);
|
|
33
|
+
|
|
34
|
+
if (input.length > 0) {
|
|
35
|
+
expect(input).toBeTruthy();
|
|
36
|
+
expect(input).toContain(input.charAt(input.length - 1));
|
|
37
|
+
} else {
|
|
38
|
+
expect(input).toBeFalsy();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return true;
|
|
42
|
+
},
|
|
43
|
+
).generate((seed: FuzzSeed, run: (input: string) => bool): void => {
|
|
44
|
+
run(
|
|
45
|
+
seed.string({
|
|
46
|
+
charset: "ascii",
|
|
47
|
+
min: 0,
|
|
48
|
+
max: 40,
|
|
49
|
+
exclude: [0x00, 0x0a, 0x0d],
|
|
50
|
+
}),
|
|
51
|
+
);
|
|
52
|
+
}, 250);
|
package/assembly/index.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Suite } from "./src/suite";
|
|
2
2
|
import { Expectation } from "./src/expectation";
|
|
3
|
-
import { stringify } from "as-console/stringify";
|
|
4
3
|
import {
|
|
5
4
|
__COVER,
|
|
6
5
|
__POINTS,
|
|
@@ -16,6 +15,7 @@ import {
|
|
|
16
15
|
sendReport,
|
|
17
16
|
} from "./util/wipc";
|
|
18
17
|
import { quote } from "./util/json";
|
|
18
|
+
import { bold, formatValue, green, red } from "./util/format";
|
|
19
19
|
import {
|
|
20
20
|
createFuzzer,
|
|
21
21
|
FuzzerBase,
|
|
@@ -245,7 +245,7 @@ export function log<T>(data: T): void {
|
|
|
245
245
|
}
|
|
246
246
|
|
|
247
247
|
export function __as_test_log_default<T>(data: T): string {
|
|
248
|
-
return
|
|
248
|
+
return formatValue(data);
|
|
249
249
|
}
|
|
250
250
|
|
|
251
251
|
export function __as_test_log_is_enabled(): bool {
|
|
@@ -445,10 +445,7 @@ function runFuzzers(): void {
|
|
|
445
445
|
for (let i = 0; i < entryFuzzers.length; i++) {
|
|
446
446
|
const fuzzer = unchecked(entryFuzzers[i]);
|
|
447
447
|
prepareFuzzIteration();
|
|
448
|
-
const result = fuzzer.run(
|
|
449
|
-
config.seed,
|
|
450
|
-
resolveFuzzerRuns(fuzzer, config),
|
|
451
|
-
);
|
|
448
|
+
const result = fuzzer.run(config.seed, resolveFuzzerRuns(fuzzer, config));
|
|
452
449
|
report.fuzzers.push(result);
|
|
453
450
|
}
|
|
454
451
|
sendReport(report.serialize());
|
|
@@ -673,11 +670,11 @@ export class Result {
|
|
|
673
670
|
}
|
|
674
671
|
display(): string {
|
|
675
672
|
let out = "";
|
|
676
|
-
out += `${
|
|
673
|
+
out += `${bold(this.name)} `;
|
|
677
674
|
if (this.arg1) {
|
|
678
|
-
out += `${
|
|
675
|
+
out += `${bold(red(this.arg1.toString() + " failed"))}`;
|
|
679
676
|
} else {
|
|
680
|
-
out += `${
|
|
677
|
+
out += `${bold(green("0 failed"))}`;
|
|
681
678
|
}
|
|
682
679
|
out += ` ${this.arg1 + this.arg2} total\n`;
|
|
683
680
|
return out;
|