as-test 1.1.1 → 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 CHANGED
@@ -1,11 +1,16 @@
1
1
  # Change Log
2
2
 
3
- ## v1.1.1
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
4
9
 
5
10
  - add `ast clean` command to remove build outputs, coverage outputs, crash reports, and logs.
6
11
  - remove deps
7
12
 
8
- ## v1.1.0
13
+ ## 2026-05-12 -v1.1.0
9
14
 
10
15
  ### Upgrading to 1.1.0
11
16
 
@@ -46,7 +51,7 @@
46
51
 
47
52
  - feat: add per-mode `default: boolean` selection so modes can be included in implicit runs or kept manual-only.
48
53
  - feat: add `ast clean` to remove configured build outputs, coverage outputs, crash reports, and logs.
49
- - feat: make `ast clean` remove everything by default, prompt with `[Y/n]` before a full clean, and allow `-f` / `--force` to skip that confirmation.
54
+ - feat: make `ast clean` remove everything by default without prompting.
50
55
  - fix: restore unnamed root-config execution alongside named default modes when `--mode` is omitted.
51
56
  - fix: make `ast clean` ignore mode `default: false` flags and treat an omitted `--mode` as a full clean across every configured mode.
52
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.
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("hot path stays stable", (): void => {
257
- expect(1 + 1).toBe(2);
258
- }, 250);
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("ascii strings survive concatenation boundaries", (input: string): bool => {
265
- expect(input.length <= 40).toBe(true);
266
- return true;
267
- }).generate((seed: FuzzSeed, run: (input: string) => bool): void => {
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
- "outDir": {
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
- "enum": ["bindings"]
341
+ "description": "Mode-specific build output directory. If omitted, defaults to <outDir>/<mode-name>."
402
342
  },
403
- "corpusDir": {
404
- "type": "string"
343
+ "logs": {
344
+ "type": "string",
345
+ "description": "Mode-specific log output directory."
405
346
  },
406
- "crashDir": {
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 custom build command template."
349
+ "description": "Mode-specific coverage output directory."
418
350
  },
419
- "args": {
420
- "type": "array",
421
- "items": {
422
- "type": "string"
423
- }
351
+ "snapshotDir": {
352
+ "type": "string",
353
+ "description": "Mode-specific snapshot directory."
424
354
  },
425
- "target": {
355
+ "config": {
426
356
  "type": "string",
427
- "enum": ["wasi", "bindings", "web"]
357
+ "description": "Mode-specific asconfig path or \"none\"."
428
358
  },
429
- "env": {
430
- "description": "Mode-specific build environment overrides.",
359
+ "coverage": {
360
+ "description": "Mode-specific coverage settings.",
431
361
  "oneOf": [
432
362
  {
433
- "type": "string"
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": "object",
443
- "additionalProperties": {
444
- "type": "string"
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 runtime command."
417
+ "description": "Mode-specific custom build command template."
418
+ },
419
+ "args": {
420
+ "type": "array",
421
+ "items": {
422
+ "type": "string"
423
+ }
462
424
  },
463
- "browser": {
425
+ "target": {
464
426
  "type": "string",
465
- "description": "Mode-specific browser for web targets. Use chrome, chromium, firefox, webkit, or an executable path."
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
- "reporter": {
470
- "description": "Mode-specific reporter config.",
471
- "oneOf": [
472
- {
473
- "type": "string"
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
- "name": {
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
- "options": {
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
- "outDir": {
489
- "type": "string"
490
- },
491
- "outFile": {
492
- "type": "string"
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-specific runtime environment overrides.",
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
  },
@@ -8,21 +8,24 @@ fuzz("bounded integer addition", (left: i32, right: i32): bool => {
8
8
  run(seed.i32({ min: -1000, max: 1000 }), seed.i32({ min: -1000, max: 1000 }));
9
9
  });
10
10
 
11
- fuzz("numeric matchers stay consistent for bounded integers", (value: i32): bool => {
12
- expect(value).toBeNumber();
13
- expect(value).toBeInteger();
14
- expect(value).toBeFinite();
15
- expect(value).toBe(value);
16
- expect(value).toBeGreaterOrEqualTo(-1000);
17
- expect(value).toBeLessThanOrEqualTo(1000);
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);
18
20
 
19
- if (value != 0) {
20
- expect(value).toBeTruthy();
21
- } else {
22
- expect(value).toBeFalsy();
23
- }
21
+ if (value != 0) {
22
+ expect(value).toBeTruthy();
23
+ } else {
24
+ expect(value).toBeFalsy();
25
+ }
24
26
 
25
- return true;
26
- }).generate((seed: FuzzSeed, run: (value: i32) => bool): void => {
27
+ return true;
28
+ },
29
+ ).generate((seed: FuzzSeed, run: (value: i32) => bool): void => {
27
30
  run(seed.i32({ min: -1000, max: 1000 }));
28
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>((s) => s.i32({ min: -9, max: 9 }), PERF_ARRAY)
63
- .length;
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
  },
package/assembly/index.ts CHANGED
@@ -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());
@@ -354,7 +354,13 @@ export class Expectation<T> extends Tests {
354
354
  // @ts-ignore
355
355
  const passed = this._left.indexOf(value) >= 0;
356
356
  // @ts-ignore
357
- this._resolve(passed, "toMatch", q(this._left as string), q(value), message);
357
+ this._resolve(
358
+ passed,
359
+ "toMatch",
360
+ q(this._left as string),
361
+ q(value),
362
+ message,
363
+ );
358
364
  }
359
365
 
360
366
  /**
@@ -79,14 +79,24 @@ export class FuzzSeed {
79
79
 
80
80
  i8(options: IntegerOptions<i8> | null = null): i8 {
81
81
  if (options == null) {
82
- return this.nextI8InRange(i8.MIN_VALUE, i8.MAX_VALUE, EMPTY_I8_EXCLUDE, false);
82
+ return this.nextI8InRange(
83
+ i8.MIN_VALUE,
84
+ i8.MAX_VALUE,
85
+ EMPTY_I8_EXCLUDE,
86
+ false,
87
+ );
83
88
  }
84
89
  return this.nextI8InRange(options.min, options.max, options.exclude, true);
85
90
  }
86
91
 
87
92
  u8(options: IntegerOptions<u8> | null = null): u8 {
88
93
  if (options == null) {
89
- return this.nextU8InRange(u8.MIN_VALUE, u8.MAX_VALUE, EMPTY_U8_EXCLUDE, false);
94
+ return this.nextU8InRange(
95
+ u8.MIN_VALUE,
96
+ u8.MAX_VALUE,
97
+ EMPTY_U8_EXCLUDE,
98
+ false,
99
+ );
90
100
  }
91
101
  return this.nextU8InRange(options.min, options.max, options.exclude, true);
92
102
  }
@@ -186,7 +196,9 @@ export class FuzzSeed {
186
196
  if (!exclude.length) {
187
197
  for (let i = 0; i < length; i++) {
188
198
  unchecked(
189
- (out[i] = <u8>unchecked(include[this.nextRange(0, include.length - 1)])),
199
+ (out[i] = <u8>(
200
+ unchecked(include[this.nextRange(0, include.length - 1)])
201
+ )),
190
202
  );
191
203
  }
192
204
  return out;
@@ -299,7 +311,9 @@ export class FuzzSeed {
299
311
  return <i32>this.nextU32();
300
312
  }
301
313
  if (!exclude.length) {
302
- return max <= min ? min : min + <i32>(this.nextU32() % <u32>(max - min + 1));
314
+ return max <= min
315
+ ? min
316
+ : min + <i32>(this.nextU32() % <u32>(max - min + 1));
303
317
  }
304
318
  for (let attempts = 0; attempts < 1024; attempts++) {
305
319
  const value =
@@ -324,12 +338,16 @@ export class FuzzSeed {
324
338
  const right = <i32>max;
325
339
  if (!exclude.length) {
326
340
  return <i8>(
327
- right <= left ? left : left + <i32>(this.nextU32() % <u32>(right - left + 1))
341
+ (right <= left
342
+ ? left
343
+ : left + <i32>(this.nextU32() % <u32>(right - left + 1)))
328
344
  );
329
345
  }
330
346
  for (let attempts = 0; attempts < 1024; attempts++) {
331
347
  const value = <i8>(
332
- right <= left ? left : left + <i32>(this.nextU32() % <u32>(right - left + 1))
348
+ (right <= left
349
+ ? left
350
+ : left + <i32>(this.nextU32() % <u32>(right - left + 1)))
333
351
  );
334
352
  if (!containsValue<i8>(exclude, value)) return value;
335
353
  }
@@ -350,11 +368,13 @@ export class FuzzSeed {
350
368
  const left = <u32>min;
351
369
  const right = <u32>max;
352
370
  if (!exclude.length) {
353
- return <u8>(right <= left ? left : left + (this.nextU32() % (right - left + 1)));
371
+ return <u8>(
372
+ (right <= left ? left : left + (this.nextU32() % (right - left + 1)))
373
+ );
354
374
  }
355
375
  for (let attempts = 0; attempts < 1024; attempts++) {
356
376
  const value = <u8>(
357
- right <= left ? left : left + (this.nextU32() % (right - left + 1))
377
+ (right <= left ? left : left + (this.nextU32() % (right - left + 1)))
358
378
  );
359
379
  if (!containsValue<u8>(exclude, value)) return value;
360
380
  }
@@ -376,12 +396,16 @@ export class FuzzSeed {
376
396
  const right = <i32>max;
377
397
  if (!exclude.length) {
378
398
  return <i16>(
379
- right <= left ? left : left + <i32>(this.nextU32() % <u32>(right - left + 1))
399
+ (right <= left
400
+ ? left
401
+ : left + <i32>(this.nextU32() % <u32>(right - left + 1)))
380
402
  );
381
403
  }
382
404
  for (let attempts = 0; attempts < 1024; attempts++) {
383
405
  const value = <i16>(
384
- right <= left ? left : left + <i32>(this.nextU32() % <u32>(right - left + 1))
406
+ (right <= left
407
+ ? left
408
+ : left + <i32>(this.nextU32() % <u32>(right - left + 1)))
385
409
  );
386
410
  if (!containsValue<i16>(exclude, value)) return value;
387
411
  }
@@ -402,11 +426,13 @@ export class FuzzSeed {
402
426
  const left = <u32>min;
403
427
  const right = <u32>max;
404
428
  if (!exclude.length) {
405
- return <u16>(right <= left ? left : left + (this.nextU32() % (right - left + 1)));
429
+ return <u16>(
430
+ (right <= left ? left : left + (this.nextU32() % (right - left + 1)))
431
+ );
406
432
  }
407
433
  for (let attempts = 0; attempts < 1024; attempts++) {
408
434
  const value = <u16>(
409
- right <= left ? left : left + (this.nextU32() % (right - left + 1))
435
+ (right <= left ? left : left + (this.nextU32() % (right - left + 1)))
410
436
  );
411
437
  if (!containsValue<u16>(exclude, value)) return value;
412
438
  }
@@ -448,9 +474,7 @@ export class FuzzSeed {
448
474
  const left = this.toOrderedU64(min);
449
475
  const right = this.toOrderedU64(max);
450
476
  if (!exclude.length) {
451
- return this.fromOrderedU64(
452
- left + this.nextU64Offset(left, right),
453
- );
477
+ return this.fromOrderedU64(left + this.nextU64Offset(left, right));
454
478
  }
455
479
  for (let attempts = 0; attempts < 1024; attempts++) {
456
480
  const value = this.fromOrderedU64(left + this.nextU64Offset(left, right));
@@ -529,7 +553,7 @@ export class FuzzSeed {
529
553
  }
530
554
 
531
555
  private toOrderedU64(value: i64): u64 {
532
- return <u64>value ^ I64_SIGN_MASK;
556
+ return (<u64>value) ^ I64_SIGN_MASK;
533
557
  }
534
558
 
535
559
  private fromOrderedU64(value: u64): i64 {
@@ -543,13 +567,11 @@ const DIGIT_ALPHABET: i32[] = rangeChars(48, 57);
543
567
  const HEX_ALPHABET: i32[] = DIGIT_ALPHABET.concat(rangeChars(97, 102));
544
568
  const ALNUM_ALPHABET: i32[] = ALPHA_ALPHABET.concat(DIGIT_ALPHABET);
545
569
  const BASE64_ALPHABET: i32[] = ALPHA_ALPHABET.concat(DIGIT_ALPHABET).concat([
546
- 43,
547
- 47,
548
- 61,
570
+ 43, 47, 61,
549
571
  ]);
550
- const IDENTIFIER_ALPHABET: i32[] = [95].concat(ALPHA_ALPHABET).concat(
551
- DIGIT_ALPHABET,
552
- );
572
+ const IDENTIFIER_ALPHABET: i32[] = [95]
573
+ .concat(ALPHA_ALPHABET)
574
+ .concat(DIGIT_ALPHABET);
553
575
  const WHITESPACE_ALPHABET: i32[] = [9, 10, 13, 32];
554
576
 
555
577
  export abstract class FuzzerBase {
@@ -1113,7 +1135,6 @@ function removeFirst(values: i32[], needle: i32): void {
1113
1135
  if (index >= 0) values.splice(index, 1);
1114
1136
  }
1115
1137
 
1116
-
1117
1138
  function validateLengthRange(label: string, min: i32, max: i32): void {
1118
1139
  if (min < 0 || max < 0) panic();
1119
1140
  if (max < min) panic();