From 2181828dcae1d833eec5fb333478ff06bf972dde Mon Sep 17 00:00:00 2001 From: tolauwae Date: Fri, 6 Dec 2024 17:31:50 +0100 Subject: [PATCH 01/16] Get 100% coverage for util --- src/util/retry.ts | 2 +- src/util/util.ts | 4 ++-- tests/unit/util.test.ts | 46 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/util/retry.ts b/src/util/retry.ts index 4670bc3..0ccd533 100644 --- a/src/util/retry.ts +++ b/src/util/retry.ts @@ -11,6 +11,6 @@ export function retry(promise: () => Promise, retries: number): Promise trying = ++attempt < retries; } } - reject(`exhausted number of retries (${retries})`); + reject(new Error(`exhausted number of retries (${retries})`)); }); } \ No newline at end of file diff --git a/src/util/util.ts b/src/util/util.ts index e55dd23..066c94f 100644 --- a/src/util/util.ts +++ b/src/util/util.ts @@ -1,7 +1,7 @@ export function getFileExtension(file: string): string { const result = /(?:\.([^.]+))?$/.exec(file) - if (result === null || result.length < 1) { - throw Error('Could not determine file type'); + if (result === null || result.length < 1 || result[1] === undefined) { + throw new Error('Could not determine file type'); } return result[1]; } diff --git a/tests/unit/util.test.ts b/tests/unit/util.test.ts index 9708fc4..c200943 100644 --- a/tests/unit/util.test.ts +++ b/tests/unit/util.test.ts @@ -1,5 +1,7 @@ import test from 'ava'; -import {getFileExtension} from '../../src/util/util'; +import {find, getFileExtension} from '../../src/util/util'; +import {indent} from '../../src/util/printing'; +import {retry} from '../../src/util/retry'; test('[internal] test util/getFileExtension', t => { t.is(getFileExtension('test.wast'), 'wast'); @@ -7,3 +9,45 @@ test('[internal] test util/getFileExtension', t => { t.is(getFileExtension('float_misc.asserts.wast'), 'wast'); t.is(getFileExtension('simd_i16x8_extadd_pairwise_i8x16.wast'), 'wast'); }); + +test('[internal] test errors in util/getFileExtension', t => { + const error = t.throws(() => { + getFileExtension('impossible') + }, {instanceOf: Error}); + t.is(error.message, 'Could not determine file type'); +}); + +test('[internal] test util/find', t => { + t.is(find(/(wast)/, 'test.wast'), 'wast'); + t.is(find(/(.wast)/, 'impossible'), ''); + t.is(find(/—(.*)—/, 'Jeeves—my man, you know—is really a most extraordinary chap.'), 'my man, you know'); + t.is(find(/^(?:[^,]*,){2}\s*([a-zA-Z]+)/, 'liberty, equality, fraternity'), 'fraternity'); + t.is(find(/^(?:[^,]*,){2}\s*([a-zA-Z]+)/, 'The unanimous Declaration of the thirteen united States of America, When in the Course of human events, it becomes necessary for one people to dissolve the political bands which have connected them with another, and to assume among the powers of the earth, the separate and equal station to which the Laws of Nature and of Nature\'s God entitle them, a decent respect to the opinions of mankind requires that they should declare the causes which impel them to the separation.'), 'it'); + t.is(find(/([a-zA-Z]{11,})/, 'The unanimous Declaration of the thirteen united States of America, When in the Course of human events, it becomes necessary for one people to dissolve the political bands which have connected them with another, and to assume among the powers of the earth, the separate and equal station to which the Laws of Nature and of Nature\'s God entitle them, a decent respect to the opinions of mankind requires that they should declare the causes which impel them to the separation.'), 'Declaration'); +}); + +test('[internal] test printing/indent', t => { + t.is(indent(4), ' '); + t.is(indent(4, 1), ' '); + t.is(indent(1, 4), ' '); +}); + +const attempt = (count: number, n: number) => retry(async () => { + return new Promise((resolve, reject) => { + count--; + if (count === 0) { + resolve(0); + } else { + reject() + } + }) +}, n); + +test('[internal] test retry/retry', async t => { + t.is(await attempt(2, 2), 0); + t.is(await attempt(2, 4), 0); + t.is(await attempt(8, 9), 0); + + const error = await t.throwsAsync(attempt(2, 1)); + t.is(error.message, `exhausted number of retries (${1})`); +}); \ No newline at end of file From 790464c1c508032ba9a8ba46d0e729138907884e Mon Sep 17 00:00:00 2001 From: tolauwae Date: Sat, 7 Dec 2024 01:13:03 +0100 Subject: [PATCH 02/16] Add sourcemap tests --- package.json | 3 ++- tests/unit/sourcemap.test.ts | 12 ++++++++++++ tests/unit/util.test.ts | 10 +++++----- 3 files changed, 19 insertions(+), 6 deletions(-) create mode 100644 tests/unit/sourcemap.test.ts diff --git a/package.json b/package.json index 4a9cdeb..7fccec2 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,8 @@ }, "ava": { "files": [ - "out/tests/unit/util.test.js" + "out/tests/unit/util.test.js", + "out/tests/unit/sourcemap.test.js" ], "typescript": { "compile": false, diff --git a/tests/unit/sourcemap.test.ts b/tests/unit/sourcemap.test.ts new file mode 100644 index 0000000..8a6369f --- /dev/null +++ b/tests/unit/sourcemap.test.ts @@ -0,0 +1,12 @@ +import test from 'ava'; +import {WASM} from '../../src/sourcemap/Wasm'; + +test('test wasm/leb128', t => { + t.is(WASM.leb128(0), '00'); + t.is(WASM.leb128(1), '01'); + t.is(WASM.leb128(8), '08'); + t.is(WASM.leb128(32), '20'); + // t.is(WASM.leb128(64), '40'); + t.is(WASM.leb128(128), '8001'); + // t.is(WASM.leb128(1202), 'b209'); +}); \ No newline at end of file diff --git a/tests/unit/util.test.ts b/tests/unit/util.test.ts index c200943..72765d8 100644 --- a/tests/unit/util.test.ts +++ b/tests/unit/util.test.ts @@ -3,21 +3,21 @@ import {find, getFileExtension} from '../../src/util/util'; import {indent} from '../../src/util/printing'; import {retry} from '../../src/util/retry'; -test('[internal] test util/getFileExtension', t => { +test('test util/getFileExtension', t => { t.is(getFileExtension('test.wast'), 'wast'); t.is(getFileExtension('util.test.js'), 'js'); t.is(getFileExtension('float_misc.asserts.wast'), 'wast'); t.is(getFileExtension('simd_i16x8_extadd_pairwise_i8x16.wast'), 'wast'); }); -test('[internal] test errors in util/getFileExtension', t => { +test('test errors in util/getFileExtension', t => { const error = t.throws(() => { getFileExtension('impossible') }, {instanceOf: Error}); t.is(error.message, 'Could not determine file type'); }); -test('[internal] test util/find', t => { +test('test util/find', t => { t.is(find(/(wast)/, 'test.wast'), 'wast'); t.is(find(/(.wast)/, 'impossible'), ''); t.is(find(/—(.*)—/, 'Jeeves—my man, you know—is really a most extraordinary chap.'), 'my man, you know'); @@ -26,7 +26,7 @@ test('[internal] test util/find', t => { t.is(find(/([a-zA-Z]{11,})/, 'The unanimous Declaration of the thirteen united States of America, When in the Course of human events, it becomes necessary for one people to dissolve the political bands which have connected them with another, and to assume among the powers of the earth, the separate and equal station to which the Laws of Nature and of Nature\'s God entitle them, a decent respect to the opinions of mankind requires that they should declare the causes which impel them to the separation.'), 'Declaration'); }); -test('[internal] test printing/indent', t => { +test('test printing/indent', t => { t.is(indent(4), ' '); t.is(indent(4, 1), ' '); t.is(indent(1, 4), ' '); @@ -43,7 +43,7 @@ const attempt = (count: number, n: number) => retry(async () => { }) }, n); -test('[internal] test retry/retry', async t => { +test('test retry/retry', async t => { t.is(await attempt(2, 2), 0); t.is(await attempt(2, 4), 0); t.is(await attempt(8, 9), 0); From fedcdbcc2653612f46b4921644b11272661ab148 Mon Sep 17 00:00:00 2001 From: tolauwae Date: Sat, 7 Dec 2024 21:00:28 +0100 Subject: [PATCH 03/16] Add basic sourcemap test --- tests/unit/artifacts/compile.output | 233 ++++++++++++++++++++++++++++ tests/unit/artifacts/dump | 100 ++++++++++++ tests/unit/artifacts/upload.wasm | Bin 0 -> 389 bytes tests/unit/sourcemap.test.ts | 19 +++ 4 files changed, 352 insertions(+) create mode 100644 tests/unit/artifacts/compile.output create mode 100644 tests/unit/artifacts/dump create mode 100644 tests/unit/artifacts/upload.wasm diff --git a/tests/unit/artifacts/compile.output b/tests/unit/artifacts/compile.output new file mode 100644 index 0000000..e98befe --- /dev/null +++ b/tests/unit/artifacts/compile.output @@ -0,0 +1,233 @@ +;; SOURCE MAP INFO +0000000: 0061 736d ; WASM_BINARY_MAGIC +0000004: 0100 0000 ; WASM_BINARY_VERSION +; section "Type" (1) +0000008: 01 ; section code +0000009: 0000 0000 00 ; section size (guess) +000000e: 03 ; num types +; func type 0 +000000f: 60 ; func +0000010: 02 ; num params +0000011: 7f ; i32 +0000012: 7f ; i32 +0000013: 00 ; num results +; func type 1 +0000014: 60 ; func +0000015: 01 ; num params +0000016: 7f ; i32 +0000017: 00 ; num results +; func type 2 +0000018: 60 ; func +0000019: 00 ; num params +000001a: 00 ; num results +0000009: 8d80 8080 00 ; FIXUP section size +; section "Import" (2) +000001b: 02 ; section code +000001c: 0000 0000 00 ; section size (guess) +0000021: 03 ; num imports +; import header 0 +0000022: 03 ; string length +0000023: 656e 76 env ; import module name +0000026: 0a ; string length +0000027: 6368 6970 5f64 656c 6179 chip_delay ; import field name +0000031: 00 ; import kind +0000032: 01 ; import signature index +; import header 1 +0000033: 03 ; string length +0000034: 656e 76 env ; import module name +0000037: 0d ; string length +0000038: 6368 6970 5f70 696e 5f6d 6f64 65 chip_pin_mode ; import field name +0000045: 00 ; import kind +0000046: 00 ; import signature index +; import header 2 +0000047: 03 ; string length +0000048: 656e 76 env ; import module name +000004b: 12 ; string length +000004c: 6368 6970 5f64 6967 6974 616c 5f77 7269 chip_digital_wri +000005c: 7465 te ; import field name +000005e: 00 ; import kind +000005f: 00 ; import signature index +000001c: bf80 8080 00 ; FIXUP section size +; section "Function" (3) +0000060: 03 ; section code +0000061: 0000 0000 00 ; section size (guess) +0000066: 02 ; num functions +0000067: 02 ; function 0 signature index +0000068: 02 ; function 1 signature index +0000061: 8380 8080 00 ; FIXUP section size +; section "Global" (6) +0000069: 06 ; section code +000006a: 0000 0000 00 ; section size (guess) +000006f: 03 ; num globals +0000070: 7f ; i32 +0000071: 00 ; global mutability +@ { "line": 13, "col_start": 21, "col_end": 30 } +0000072: 41 ; i32.const +0000073: 17 ; i32 literal +0000074: 0b ; end +0000075: 7f ; i32 +0000076: 00 ; global mutability +@ { "line": 14, "col_start": 20, "col_end": 29 } +0000077: 41 ; i32.const +0000078: 01 ; i32 literal +0000079: 0b ; end +000007a: 7f ; i32 +000007b: 00 ; global mutability +@ { "line": 15, "col_start": 21, "col_end": 30 } +000007c: 41 ; i32.const +000007d: 00 ; i32 literal +000007e: 0b ; end +000006a: 9080 8080 00 ; FIXUP section size +; section "Export" (7) +000007f: 07 ; section code +0000080: 0000 0000 00 ; section size (guess) +0000085: 01 ; num exports +0000086: 04 ; string length +0000087: 6d61 696e main ; export name +000008b: 00 ; export kind +000008c: 04 ; export func index +0000080: 8880 8080 00 ; FIXUP section size +; section "Code" (10) +000008d: 0a ; section code +000008e: 0000 0000 00 ; section size (guess) +0000093: 02 ; num functions +; function body 0 +0000094: 0000 0000 00 ; func body size (guess) +0000099: 00 ; local decl count +@ { "line": 20, "col_start": 5, "col_end": 15 } +000009a: 23 ; global.get +000009b: 00 ; global index +@ { "line": 21, "col_start": 5, "col_end": 14 } +000009c: 41 ; i32.const +000009d: 02 ; i32 literal +@ { "line": 22, "col_start": 5, "col_end": 9 } +000009e: 10 ; call +000009f: 01 ; function index +00000a0: 0b ; end +0000094: 8880 8080 00 ; FIXUP func body size +; function body 1 +00000a1: 0000 0000 00 ; func body size (guess) +00000a6: 01 ; local decl count +00000a7: 01 ; local type count +00000a8: 7f ; i32 +@ { "line": 28, "col_start": 5, "col_end": 14 } +00000a9: 41 ; i32.const +00000aa: e807 ; i32 literal +@ { "line": 29, "col_start": 5, "col_end": 14 } +00000ac: 21 ; local.set +00000ad: 00 ; local index +@ { "line": 32, "col_start": 5, "col_end": 9 } +00000ae: 10 ; call +00000af: 03 ; function index +@ { "line": 35, "col_start": 5, "col_end": 9 } +00000b0: 03 ; loop +00000b1: 40 ; void +@ { "line": 36, "col_start": 7, "col_end": 17 } +00000b2: 23 ; global.get +00000b3: 00 ; global index +@ { "line": 37, "col_start": 7, "col_end": 17 } +00000b4: 23 ; global.get +00000b5: 01 ; global index +@ { "line": 38, "col_start": 7, "col_end": 11 } +00000b6: 10 ; call +00000b7: 02 ; function index +@ { "line": 39, "col_start": 7, "col_end": 16 } +00000b8: 20 ; local.get +00000b9: 00 ; local index +@ { "line": 40, "col_start": 7, "col_end": 11 } +00000ba: 10 ; call +00000bb: 00 ; function index +@ { "line": 41, "col_start": 7, "col_end": 17 } +00000bc: 23 ; global.get +00000bd: 00 ; global index +@ { "line": 42, "col_start": 7, "col_end": 17 } +00000be: 23 ; global.get +00000bf: 02 ; global index +@ { "line": 43, "col_start": 7, "col_end": 11 } +00000c0: 10 ; call +00000c1: 02 ; function index +@ { "line": 44, "col_start": 7, "col_end": 16 } +00000c2: 20 ; local.get +00000c3: 00 ; local index +@ { "line": 45, "col_start": 7, "col_end": 11 } +00000c4: 10 ; call +00000c5: 00 ; function index +@ { "line": 46, "col_start": 7, "col_end": 9 } +00000c6: 0c ; br +00000c7: 00 ; break depth +00000c8: 0b ; end +00000c9: 0b ; end +00000a1: a480 8080 00 ; FIXUP func body size +000008e: b780 8080 00 ; FIXUP section size +; section "name" +00000ca: 00 ; section code +00000cb: 0000 0000 00 ; section size (guess) +00000d0: 04 ; string length +00000d1: 6e61 6d65 name ; custom section name +00000d5: 01 ; name subsection type +00000d6: 0000 0000 00 ; subsection size (guess) +00000db: 05 ; num names +00000dc: 00 ; elem index +00000dd: 0e ; string length +00000de: 656e 762e 6368 6970 5f64 656c 6179 env.chip_delay ; elem name 0 +00000ec: 01 ; elem index +00000ed: 11 ; string length +00000ee: 656e 762e 6368 6970 5f70 696e 5f6d 6f64 env.chip_pin_mod +00000fe: 65 e ; elem name 1 +00000ff: 02 ; elem index +0000100: 16 ; string length +0000101: 656e 762e 6368 6970 5f64 6967 6974 616c env.chip_digital +0000111: 5f77 7269 7465 _write ; elem name 2 +0000117: 03 ; elem index +0000118: 04 ; string length +0000119: 696e 6974 init ; elem name 3 +000011d: 04 ; elem index +000011e: 05 ; string length +000011f: 626c 696e 6b blink ; elem name 4 +00000d6: c980 8080 00 ; FIXUP subsection size +0000124: 02 ; local name type +0000125: 0000 0000 00 ; subsection size (guess) +000012a: 05 ; num functions +000012b: 00 ; function index +000012c: 00 ; num locals +000012d: 01 ; function index +000012e: 00 ; num locals +000012f: 02 ; function index +0000130: 00 ; num locals +0000131: 03 ; function index +0000132: 00 ; num locals +0000133: 04 ; function index +0000134: 01 ; num locals +0000135: 00 ; local index +0000136: 05 ; string length +0000137: 6465 6c61 79 delay ; local name 0 +0000125: 9280 8080 00 ; FIXUP subsection size +000013c: 04 ; name subsection type +000013d: 0000 0000 00 ; subsection size (guess) +0000142: 03 ; num names +0000143: 00 ; elem index +0000144: 12 ; string length +0000145: 696e 7433 322d 3e69 6e74 3332 2d3e 766f int32->int32->vo +0000155: 6964 id ; elem name 0 +0000157: 01 ; elem index +0000158: 0b ; string length +0000159: 696e 7433 322d 3e76 6f69 64 int32->void ; elem name 1 +0000164: 02 ; elem index +0000165: 0a ; string length +0000166: 766f 6964 2d3e 766f 6964 void->void ; elem name 2 +000013d: ae80 8080 00 ; FIXUP subsection size +0000170: 07 ; name subsection type +0000171: 0000 0000 00 ; subsection size (guess) +0000176: 03 ; num names +0000177: 00 ; elem index +0000178: 03 ; string length +0000179: 6c65 64 led ; elem name 0 +000017c: 01 ; elem index +000017d: 02 ; string length +000017e: 6f6e on ; elem name 1 +0000180: 02 ; elem index +0000181: 03 ; string length +0000182: 6f66 66 off ; elem name 2 +0000171: 8f80 8080 00 ; FIXUP subsection size +00000cb: b581 8080 00 ; FIXUP section size + diff --git a/tests/unit/artifacts/dump b/tests/unit/artifacts/dump new file mode 100644 index 0000000..9baf762 --- /dev/null +++ b/tests/unit/artifacts/dump @@ -0,0 +1,100 @@ + +blink.wasm: file format wasm 0x1 +, , , , , +Section Details: + +Type[4]: + - type[0] (i32, i32) -> nil + - type[1] (i32) -> i32 + - type[2] (i32) -> nil + - type[3] () -> nil +Import[4]: + - func[0] sig=2 <- env.chip_delay + - func[1] sig=0 <- env.chip_pin_mode + - func[2] sig=1 <- env.chip_digital_read + - func[3] sig=0 <- env.chip_digital_write +Function[2]: + - func[4] sig=3 + - func[5] sig=3 +Global[3]: + - global[0] i32 mutable=0 - init i32=23 + - global[1] i32 mutable=0 - init i32=1 + - global[2] i32 mutable=0 - init i32=0 +Export[1]: + - func[5] -> "main" +Code[2]: + - func[4] size=8 + - func[5] size=44 +Custom: + - name: "name" + - func[0] +, - func[1] +, - func[2] +, - func[3] +, - func[4] +, - func[5] + - func[5] local[0] + - type[0] int32->void> + - type[1] int32> + - type[2] void> + - type[3] void> + - global[0] + - global[1] + - global[2] + +Code Disassembly: + +0000b6 func[4] : + 0000b7: 23 00 | global.get 0 + 0000b9: 41 02 | i32.const 2 + 0000bb: 10 01 | call 1 + 0000bd: 0b | end +0000c3 func[5] : + 0000c4: 01 7f | local[0] type=i32 + 0000c6: 41 e8 07 | i32.const 1000 + 0000c9: 21 00 | local.set 0 + 0000cb: 10 04 | call 4 + 0000cd: 03 40 | loop + 0000cf: 23 00 | global.get 0 + 0000d1: 23 01 | global.get 1 + 0000d3: 10 03 | call 3 + 0000d5: 20 00 | local.get 0 + 0000d7: 10 00 | call 0 + 0000d9: 23 00 | global.get 0 + 0000db: 10 02 | call 2 + 0000dd: 23 00 | global.get 0 + 0000df: 23 02 | global.get 2 + 0000e1: 10 03 | call 3 + 0000e3: 20 00 | local.get 0 + 0000e5: 10 00 | call 0 + 0000e7: 23 00 | global.get 0 + 0000e9: 10 02 | call 2 + 0000eb: 0c 00 | br 0 + 0000ed: 0b | end + 0000ee: 0b | end +, , , , , +Sourcemap JSON: + +{ + "Functions": [ + {"name": "env.chip_delay", + "locals": [] + }, + {"name": "env.chip_pin_mode", + "locals": [] + }, + {"name": "env.chip_digital_read", + "locals": [] + }, + {"name": "env.chip_digital_write", + "locals": [] + }, + {"name": "init", + "locals": [] + }, + {"name": "blink", + "locals": [{"name": "delay","idx":0}] + } + ] +} + diff --git a/tests/unit/artifacts/upload.wasm b/tests/unit/artifacts/upload.wasm new file mode 100644 index 0000000000000000000000000000000000000000..312589a62e88a5c4b2377e438d5e10896f989458 GIT binary patch literal 389 zcmYk2u};G<5QhIdJ4A{Bg$}TSGM54NiatpiND3zsr-G=6DM2hO2*fimvmr)i-h{^> zcA#|d`R?<7zkV6nbwvQ^vFkdh8MiHF)E|I9JyL~TMrRkYNb{o1Zb1%gd9VCKfi?&02EFM}Nj3 { t.is(WASM.leb128(0), '00'); @@ -9,4 +15,17 @@ test('test wasm/leb128', t => { // t.is(WASM.leb128(64), '40'); t.is(WASM.leb128(128), '8001'); // t.is(WASM.leb128(1202), 'b209'); +}); + +function initialize(): string { + const tmp: string = mkdtempSync(''); + copyFileSync(`${artifacts}/upload.wasm`, `${tmp}/upload.wasm`); + return tmp; +} + +test('test WatMapper/extractLineInfo', async t => { + const dummy = readFileSync(`${artifacts}/compile.output`).toString(); + const mapper: WatMapper = new WatMapper(dummy, initialize(), WABT); + const mapping: SourceMap.Mapping = await mapper.mapping(); + t.true(mapping.lines.length > 0); }); \ No newline at end of file From 3a64145cc2e938daad8c5342d8ac2be617921651 Mon Sep 17 00:00:00 2001 From: tolauwae Date: Sat, 7 Dec 2024 21:01:30 +0100 Subject: [PATCH 04/16] Report coverage in CI run --- .github/workflows/test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 09c1edb..6ba920a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -37,6 +37,9 @@ jobs: run: | echo "LINE_COVERAGE=$(npm run coverage:test:ava | grep -E '^\s*Lines\s*:\s*[0-9]+(\.[0-9]+)?%' | awk '{print $3}' | tr -d '%')" >> $GITHUB_ENV + - name: Report coverage + run: npx c8 report + - name: Update coverage badge uses: schneegans/dynamic-badges-action@v1.7.0 with: From 71946665fb26ed43048e2c11bcf6f2ca9ee36da8 Mon Sep 17 00:00:00 2001 From: tolauwae Date: Sun, 8 Dec 2024 18:21:20 +0100 Subject: [PATCH 05/16] Build WAT tools --- .github/workflows/test.yml | 65 ++++++++++++++++++++++++++++++++++++++ .gitmodules | 5 ++- tests/unit/artifacts/wabt | 1 + 3 files changed, 70 insertions(+), 1 deletion(-) create mode 160000 tests/unit/artifacts/wabt diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6ba920a..3f28fc6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,9 +2,45 @@ name: Tests on: [ push ] jobs: + build: + name: Build WAT tools + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Get WABT commit ID + working-directory: tests/unit/artifacts/wabt + run: echo "WABT_VERSION=$(git rev-parse HEAD)" >> $GITHUB_ENV + + - name: Cache wabt + uses: actions/cache@v4 + id: cache-wabt + with: + key: ${{ runner.os }}-wabt-${{ env.WABT_VERSION }} + path: tests/unit/artifacts/wabt + restore-keys: | + ${{ runner.os }}-wabt- + + - name: Build WABT # Build latest version + if: steps.cache-wabt.outputs.cache-hit == false + working-directory: tests/unit/artifacts/wabt + run: | + mkdir build; cd build + cmake .. + cmake --build . + + - name: Upload built tools + uses: actions/upload-artifact@v4 + with: + name: wabt-build-${{ github.run_id }} + path: tests/unit/artifacts/wabt/build + unit: name: Unit tests runs-on: ubuntu-latest + needs: build strategy: fail-fast: false if: github.event.pull_request.draft == false @@ -16,12 +52,27 @@ jobs: - name: Prebuild files run: npm run test:prebuild + - name: Download WAT tools + uses: actions/download-artifact@v4 + with: + name: wabt-build-${{ github.run_id }} + path: .tools + + - name: Verify tools + run: | + chmod u+x $GITHUB_WORKSPACE/.tools/* + $GITHUB_WORKSPACE/.tools/wasm-objdump --version + + - name: Add .tools to PATH + run: echo "$GITHUB_WORKSPACE/.tools" >> $GITHUB_PATH + - name: Run ava unit tests run: npm run test:ava coverage: name: Code coverage runs-on: ubuntu-latest + needs: build strategy: fail-fast: true if: github.event.pull_request.draft == false @@ -33,6 +84,20 @@ jobs: - name: Prebuild files run: npm run test:prebuild + - name: Download WAT tools + uses: actions/download-artifact@v4 + with: + name: wabt-build-${{ github.run_id }} + path: .tools + + - name: Verify tools + run: | + chmod u+x $GITHUB_WORKSPACE/.tools/* + $GITHUB_WORKSPACE/.tools/wasm-objdump --version + + - name: Add .tools to PATH + run: echo "$GITHUB_WORKSPACE/.tools" >> $GITHUB_PATH + - name: Run c8 coverage run: | echo "LINE_COVERAGE=$(npm run coverage:test:ava | grep -E '^\s*Lines\s*:\s*[0-9]+(\.[0-9]+)?%' | awk '{print $3}' | tr -d '%')" >> $GITHUB_ENV diff --git a/.gitmodules b/.gitmodules index 70c311a..df1bd02 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "WABT"] path = WABT - url = git@github.com:TOPLLab/wabt.git \ No newline at end of file + url = git@github.com:TOPLLab/wabt.git +[submodule "tests/unit/artifacts/wabt"] + path = tests/unit/artifacts/wabt + url = git@github.com:TOPLLab/wabt.git diff --git a/tests/unit/artifacts/wabt b/tests/unit/artifacts/wabt new file mode 160000 index 0000000..09d542f --- /dev/null +++ b/tests/unit/artifacts/wabt @@ -0,0 +1 @@ +Subproject commit 09d542f48e03a55b73be47b981edff0793b3a6f1 From 196b962995780df0435235f10f3c9b00480e2c8b Mon Sep 17 00:00:00 2001 From: tolauwae Date: Thu, 12 Dec 2024 16:45:32 +0100 Subject: [PATCH 06/16] fixup! Build WAT tools --- .github/workflows/test.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3f28fc6..50eca12 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -63,11 +63,10 @@ jobs: chmod u+x $GITHUB_WORKSPACE/.tools/* $GITHUB_WORKSPACE/.tools/wasm-objdump --version - - name: Add .tools to PATH - run: echo "$GITHUB_WORKSPACE/.tools" >> $GITHUB_PATH - - name: Run ava unit tests run: npm run test:ava + env: + WABT: ${GITHUB_WORKSPACE}/.tools coverage: name: Code coverage From d58e568be07b2ac03d0f068d02692cf241d59cad Mon Sep 17 00:00:00 2001 From: tolauwae Date: Thu, 12 Dec 2024 21:13:17 +0100 Subject: [PATCH 07/16] Add example warduino test to CI --- .github/workflows/test.yml | 83 ++++++++++++++++++++++-- .gitmodules | 3 + tests/examples/example.ts | 116 +--------------------------------- tests/unit/artifacts/warduino | 1 + 4 files changed, 84 insertions(+), 119 deletions(-) create mode 160000 tests/unit/artifacts/warduino diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 50eca12..4f59cc6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,7 +2,7 @@ name: Tests on: [ push ] jobs: - build: + build-wabt: name: Build WAT tools runs-on: ubuntu-latest steps: @@ -37,10 +37,45 @@ jobs: name: wabt-build-${{ github.run_id }} path: tests/unit/artifacts/wabt/build + build-wdcli: + name: Build WARDuino CLI + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Get WDCLI commit ID + working-directory: tests/unit/artifacts/warduino + run: echo "WDCLI_VERSION=$(git rev-parse HEAD)" >> $GITHUB_ENV + + - name: Cache WARDuino CLI + uses: actions/cache@v4 + id: cache-warduino + with: + key: ${{ runner.os }}-warduino-${{ env.WDCLI_VERSION }} + path: tests/unit/artifacts/warduino + restore-keys: | + ${{ runner.os }}-warduino- + + - name: Build WARDuino CLI # Build latest version + if: steps.cache-warduino.outputs.cache-hit == false + working-directory: tests/unit/artifacts/warduino + run: | + mkdir build; cd build + cmake .. -D BUILD_EMULATOR=ON + cmake --build . + + - name: Upload built tools + uses: actions/upload-artifact@v4 + with: + name: warduino-build-${{ github.run_id }} + path: tests/unit/artifacts/warduino/build + unit: name: Unit tests runs-on: ubuntu-latest - needs: build + needs: build-wabt strategy: fail-fast: false if: github.event.pull_request.draft == false @@ -68,10 +103,50 @@ jobs: env: WABT: ${GITHUB_WORKSPACE}/.tools + warduino: + name: WARDuino test + runs-on: ubuntu-latest + needs: [build-wabt, build-wdcli] + strategy: + fail-fast: false + if: github.event.pull_request.draft == false + steps: + - uses: actions/checkout@v4 + + - run: npm i + + - name: Prebuild files + run: npm run test:prebuild + + - name: Download WAT tools + uses: actions/download-artifact@v4 + with: + name: wabt-build-${{ github.run_id }} + path: .tools + + - name: Download WARDuino + uses: actions/download-artifact@v4 + with: + name: warduino-build-${{ github.run_id }} + path: .warduino + + - name: Verify + run: | + chmod u+x $GITHUB_WORKSPACE/.tools/* + chmod u+x $GITHUB_WORKSPACE/.warduino/wdcli + $GITHUB_WORKSPACE/.tools/wasm-objdump --version + #$GITHUB_WORKSPACE/.warduino/wdcli --version + + - name: Run example WARDuino test + run: npm run test:example + env: + WABT: ${{ github.workspace }}/.tools + EMULATOR: ${{ github.workspace }}/.warduino/wdcli + coverage: name: Code coverage runs-on: ubuntu-latest - needs: build + needs: build-wabt strategy: fail-fast: true if: github.event.pull_request.draft == false @@ -99,7 +174,7 @@ jobs: - name: Run c8 coverage run: | - echo "LINE_COVERAGE=$(npm run coverage:test:ava | grep -E '^\s*Lines\s*:\s*[0-9]+(\.[0-9]+)?%' | awk '{print $3}' | tr -d '%')" >> $GITHUB_ENV + echo "LINE_COVERAGE=$(npm run coverage:test:ava | grep -E 'Lines\s*:\s*[0-9]+(\.[0-9]+)?%' | awk '{print $3}' | tr -d '%')" >> $GITHUB_ENV - name: Report coverage run: npx c8 report diff --git a/.gitmodules b/.gitmodules index df1bd02..0a5efa2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "tests/unit/artifacts/wabt"] path = tests/unit/artifacts/wabt url = git@github.com:TOPLLab/wabt.git +[submodule "tests/unit/artifacts/warduino"] + path = tests/unit/artifacts/warduino + url = git@github.com:TOPLLab/WARDuino.git diff --git a/tests/examples/example.ts b/tests/examples/example.ts index 71c690d..35d4222 100644 --- a/tests/examples/example.ts +++ b/tests/examples/example.ts @@ -17,120 +17,6 @@ import step = Message.step; const framework = Framework.getImplementation(); -const spec = framework.suite('Test Wasm spec'); // must be called first - -spec.testee('emulator[:8500]', new EmulatorSpecification(8500)); - -const steps: Step[] = []; - -// ✔ ((invoke "8u_good1" (i32.const 0)) (i32.const 97)) -steps.push(new Invoker('8u_good1', [WASM.i32(0)], WASM.i32(97))); - -// ✔ ((invoke "8u_good3" (i32.const 0)) (i32.const 98)) -steps.push(new Invoker('8u_good3', [WASM.i32(0)], WASM.i32(98))); - -// ✔ ((invoke "func-unwind-by-br")) -steps.push(new Invoker('func-unwind-by-br', [], undefined)); - -spec.test({ - title: `Test with address_0.wast`, - program: 'tests/examples/address.wast', - dependencies: [], - steps: steps -}); - -const debug = framework.suite('Test Debugger interface'); -debug.testee('emulator[:8520]', new EmulatorSpecification(8520)); -debug.testee('emulator[:8522]', new EmulatorSpecification(8522)); -// debug.testee('esp wrover', new ArduinoSpecification('/dev/ttyUSB0', 'esp32:esp32:esp32wrover'), new HybridScheduler(), {connectionTimout: 0}); - -debug.test({ - title: 'Test STEP OVER', - program: 'tests/examples/call.wast', - steps: [{ - title: 'Send DUMP command', - instruction: {kind: Kind.Request, value: dump} - }, { - title: 'Send STEP OVER command', - instruction: {kind: Kind.Request, value: stepOver} - }, { - title: 'CHECK: execution stepped over direct call', - instruction: {kind: Kind.Request, value: dump}, - expected: [{'pc': {kind: 'primitive', value: 169} as Expected}] - }, { - title: 'Send STEP OVER command', - instruction: {kind: Kind.Request, value: stepOver} - }, { - title: 'CHECK: execution took one step', - instruction: {kind: Kind.Request, value: dump}, - expected: [{'pc': {kind: 'primitive', value: 171} as Expected}] - }, { - title: 'Send STEP OVER command', - instruction: {kind: Kind.Request, value: stepOver} - }, { - title: 'CHECK: execution stepped over indirect call', - instruction: {kind: Kind.Request, value: dump}, - expected: [{'pc': {kind: 'primitive', value: 174} as Expected}] - }] -}); - -const DUMP: Step = { - title: 'Send DUMP command', - instruction: {kind: Kind.Request, value: Message.dump}, - expected: [ - {'pc': {kind: 'description', value: Description.defined} as Expected}, - { - 'breakpoints': { - kind: 'comparison', value: (state: Object, value: Array) => { - return value.length === 0; - }, message: 'list of breakpoints should be empty' - } as Expected> - }, - {'callstack[0].sp': {kind: 'primitive', value: -1} as Expected}, - {'callstack[0].fp': {kind: 'primitive', value: -1} as Expected}] -}; - -debug.test({ - title: 'Test DUMP blink', - program: `tests/examples/blink.wast`, - steps: [DUMP] -}); - -const primitives = framework.suite('Test primitives'); - -primitives.testee('debug[:8700]', new EmulatorSpecification(8700)); - -primitives.test({ - title: `Test store primitive`, - program: 'tests/examples/dummy.wast', - dependencies: [], - steps: [{ - title: 'CHECK: execution at start of main', - instruction: {kind: Kind.Request, value: dump}, - expected: [{'pc': {kind: 'primitive', value: 129} as Expected}] - }, - - new Invoker('load', [WASM.i32(32)], WASM.i32(0)), - - { - title: 'Send STEP command', - instruction: {kind: Kind.Request, value: step} - }, - - { - title: 'Send STEP command', - instruction: {kind: Kind.Request, value: step} - }, - - { - title: 'Send STEP command', - instruction: {kind: Kind.Request, value: step} - }, - - new Invoker('load', [WASM.i32(32)], WASM.i32(42)) - ] -}) - const oop = framework.suite('Test Out-of-place primitives'); oop.testee('supervisor[:8100] - proxy[:8150]', new OutofPlaceSpecification(8100, 8150)); @@ -183,4 +69,4 @@ oop.test({ }); -framework.run([spec, debug, primitives, oop]).then(() => process.exit(0)); +framework.run([oop]).then(() => process.exit(0)); diff --git a/tests/unit/artifacts/warduino b/tests/unit/artifacts/warduino new file mode 160000 index 0000000..3e97e4f --- /dev/null +++ b/tests/unit/artifacts/warduino @@ -0,0 +1 @@ +Subproject commit 3e97e4f43f12b01c65fd4ad2f9f418010852c486 From 0cef76c7c68f1a74a16a649626a0c7fc33c1615b Mon Sep 17 00:00:00 2001 From: tolauwae Date: Fri, 13 Dec 2024 08:19:27 +0100 Subject: [PATCH 08/16] fixup! Add example warduino test to CI --- src/reporter/describers/SuiteDescribers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reporter/describers/SuiteDescribers.ts b/src/reporter/describers/SuiteDescribers.ts index 73c7e4e..47f2dd6 100644 --- a/src/reporter/describers/SuiteDescribers.ts +++ b/src/reporter/describers/SuiteDescribers.ts @@ -62,7 +62,7 @@ export class NormalSuiteDescriber extends ShortSuiteDescriber { }); if (this.item.outcome === Outcome.error) { - report.push(' '.repeat(2) + red(this.item.clarification.toString())); + report.push(' '.repeat(2) + red(this.item.clarification)); } return report; From eee9de19ff6f19bb28c3137afb0476430ff3cd0c Mon Sep 17 00:00:00 2001 From: tolauwae Date: Fri, 13 Dec 2024 08:22:19 +0100 Subject: [PATCH 09/16] Change example test --- tests/examples/example.ts | 109 ++++++++++++++++++++++++-------------- 1 file changed, 68 insertions(+), 41 deletions(-) diff --git a/tests/examples/example.ts b/tests/examples/example.ts index 35d4222..adf59cf 100644 --- a/tests/examples/example.ts +++ b/tests/examples/example.ts @@ -17,56 +17,83 @@ import step = Message.step; const framework = Framework.getImplementation(); -const oop = framework.suite('Test Out-of-place primitives'); +const spec = framework.suite('Test Wasm spec'); // must be called first -oop.testee('supervisor[:8100] - proxy[:8150]', new OutofPlaceSpecification(8100, 8150)); +spec.testee('emulator[:8500]', new EmulatorSpecification(8500)); -oop.test({ - title: `Test store primitive`, - program: 'tests/examples/dummy.wast', - dependencies: [], - steps: [ - { - title: '[supervisor] CHECK: execution at start of main', - instruction: {kind: Kind.Request, value: dump}, - expected: [{'pc': {kind: 'primitive', value: 129} as Expected}] - }, +const steps: Step[] = []; - { - title: '[proxy] CHECK: execution at start of main', - instruction: {kind: Kind.Request, value: dump}, - expected: [{'pc': {kind: 'primitive', value: 129} as Expected}], - target: Target.proxy - }, +// ✔ ((invoke "8u_good1" (i32.const 0)) (i32.const 97)) +steps.push(new Invoker('8u_good1', [WASM.i32(0)], WASM.i32(97))); - new Invoker('load', [WASM.i32(32)], WASM.i32(0), Target.proxy), +// ✔ ((invoke "8u_good3" (i32.const 0)) (i32.const 98)) +steps.push(new Invoker('8u_good3', [WASM.i32(0)], WASM.i32(98))); - { - title: '[supervisor] Send STEP command', - instruction: {kind: Kind.Request, value: step} - }, +// ✔ ((invoke "func-unwind-by-br")) +steps.push(new Invoker('func-unwind-by-br', [], undefined)); - { - title: '[supervisor] Send STEP command', - instruction: {kind: Kind.Request, value: step} - }, +spec.test({ + title: `Test with address_0.wast`, + program: 'tests/examples/address.wast', + dependencies: [], + steps: steps +}); - { - title: '[supervisor] Send STEP command', - instruction: {kind: Kind.Request, value: step} - }, +const debug = framework.suite('Test Debugger interface'); +debug.testee('emulator[:8520]', new EmulatorSpecification(8520)); +debug.testee('emulator[:8522]', new EmulatorSpecification(8522)); +// debug.testee('esp wrover', new ArduinoSpecification('/dev/ttyUSB0', 'esp32:esp32:esp32wrover'), new HybridScheduler(), {connectionTimout: 0}); - { - title: '[supervisor] CHECK: execution took three steps', - instruction: {kind: Kind.Request, value: dump}, - expected: [{'pc': {kind: 'primitive', value: 136} as Expected}] - }, +debug.test({ + title: 'Test STEP OVER', + program: 'tests/examples/call.wast', + steps: [{ + title: 'Send DUMP command', + instruction: {kind: Kind.Request, value: dump} + }, { + title: 'Send STEP OVER command', + instruction: {kind: Kind.Request, value: stepOver} + }, { + title: 'CHECK: execution stepped over direct call', + instruction: {kind: Kind.Request, value: dump}, + expected: [{'pc': {kind: 'primitive', value: 169} as Expected}] + }, { + title: 'Send STEP OVER command', + instruction: {kind: Kind.Request, value: stepOver} + }, { + title: 'CHECK: execution took one step', + instruction: {kind: Kind.Request, value: dump}, + expected: [{'pc': {kind: 'primitive', value: 171} as Expected}] + }, { + title: 'Send STEP OVER command', + instruction: {kind: Kind.Request, value: stepOver} + }, { + title: 'CHECK: execution stepped over indirect call', + instruction: {kind: Kind.Request, value: dump}, + expected: [{'pc': {kind: 'primitive', value: 174} as Expected}] + }] +}); - new Invoker('load', [WASM.i32(32)], WASM.i32(42), Target.proxy), +const DUMP: Step = { + title: 'Send DUMP command', + instruction: {kind: Kind.Request, value: Message.dump}, + expected: [ + {'pc': {kind: 'description', value: Description.defined} as Expected}, + { + 'breakpoints': { + kind: 'comparison', value: (state: Object, value: Array) => { + return value.length === 0; + }, message: 'list of breakpoints should be empty' + } as Expected> + }, + {'callstack[0].sp': {kind: 'primitive', value: -1} as Expected}, + {'callstack[0].fp': {kind: 'primitive', value: -1} as Expected}] +}; - new Invoker('load', [WASM.i32(32)], WASM.i32(42), Target.supervisor) - ] +debug.test({ + title: 'Test DUMP blink', + program: `tests/examples/blink.wast`, + steps: [DUMP] }); - -framework.run([oop]).then(() => process.exit(0)); +framework.run([spec, debug]).then(() => process.exit(0)); From a2bfd2230fd92055d152310ff879cf07a74ca32b Mon Sep 17 00:00:00 2001 From: tolauwae Date: Fri, 13 Dec 2024 08:25:13 +0100 Subject: [PATCH 10/16] fixup! Change example test --- tests/examples/example.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/examples/example.ts b/tests/examples/example.ts index adf59cf..d2827d7 100644 --- a/tests/examples/example.ts +++ b/tests/examples/example.ts @@ -19,7 +19,7 @@ const framework = Framework.getImplementation(); const spec = framework.suite('Test Wasm spec'); // must be called first -spec.testee('emulator[:8500]', new EmulatorSpecification(8500)); +spec.testee('emulator[:8100]', new EmulatorSpecification(8100)); const steps: Step[] = []; @@ -40,9 +40,7 @@ spec.test({ }); const debug = framework.suite('Test Debugger interface'); -debug.testee('emulator[:8520]', new EmulatorSpecification(8520)); -debug.testee('emulator[:8522]', new EmulatorSpecification(8522)); -// debug.testee('esp wrover', new ArduinoSpecification('/dev/ttyUSB0', 'esp32:esp32:esp32wrover'), new HybridScheduler(), {connectionTimout: 0}); +debug.testee('emulator[:8150]', new EmulatorSpecification(8150)); debug.test({ title: 'Test STEP OVER', From 3c47de9c17b17ee2902346e5379c2355a50400fd Mon Sep 17 00:00:00 2001 From: tolauwae Date: Fri, 13 Dec 2024 08:39:59 +0100 Subject: [PATCH 11/16] Move submodules --- .github/workflows/test.yml | 18 +++++++++--------- .gitmodules | 7 ++----- tests/{unit => }/artifacts/compile.output | 0 tests/{unit => }/artifacts/dump | 0 tests/{unit => }/artifacts/upload.wasm | Bin tests/{unit => }/artifacts/wabt | 0 tests/{unit => }/artifacts/warduino | 0 tests/unit/sourcemap.test.ts | 4 ++-- tsconfig.json | 5 +++-- 9 files changed, 16 insertions(+), 18 deletions(-) rename tests/{unit => }/artifacts/compile.output (100%) rename tests/{unit => }/artifacts/dump (100%) rename tests/{unit => }/artifacts/upload.wasm (100%) rename tests/{unit => }/artifacts/wabt (100%) rename tests/{unit => }/artifacts/warduino (100%) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4f59cc6..a52084b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,7 +11,7 @@ jobs: submodules: recursive - name: Get WABT commit ID - working-directory: tests/unit/artifacts/wabt + working-directory: tests/artifacts/wabt run: echo "WABT_VERSION=$(git rev-parse HEAD)" >> $GITHUB_ENV - name: Cache wabt @@ -19,13 +19,13 @@ jobs: id: cache-wabt with: key: ${{ runner.os }}-wabt-${{ env.WABT_VERSION }} - path: tests/unit/artifacts/wabt + path: tests/artifacts/wabt restore-keys: | ${{ runner.os }}-wabt- - name: Build WABT # Build latest version if: steps.cache-wabt.outputs.cache-hit == false - working-directory: tests/unit/artifacts/wabt + working-directory: tests/artifacts/wabt run: | mkdir build; cd build cmake .. @@ -35,7 +35,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: wabt-build-${{ github.run_id }} - path: tests/unit/artifacts/wabt/build + path: tests/artifacts/wabt/build build-wdcli: name: Build WARDuino CLI @@ -46,7 +46,7 @@ jobs: submodules: recursive - name: Get WDCLI commit ID - working-directory: tests/unit/artifacts/warduino + working-directory: tests/artifacts/warduino run: echo "WDCLI_VERSION=$(git rev-parse HEAD)" >> $GITHUB_ENV - name: Cache WARDuino CLI @@ -54,13 +54,13 @@ jobs: id: cache-warduino with: key: ${{ runner.os }}-warduino-${{ env.WDCLI_VERSION }} - path: tests/unit/artifacts/warduino + path: tests/artifacts/warduino restore-keys: | ${{ runner.os }}-warduino- - name: Build WARDuino CLI # Build latest version if: steps.cache-warduino.outputs.cache-hit == false - working-directory: tests/unit/artifacts/warduino + working-directory: tests/artifacts/warduino run: | mkdir build; cd build cmake .. -D BUILD_EMULATOR=ON @@ -70,7 +70,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: warduino-build-${{ github.run_id }} - path: tests/unit/artifacts/warduino/build + path: tests/artifacts/warduino/build unit: name: Unit tests @@ -177,7 +177,7 @@ jobs: echo "LINE_COVERAGE=$(npm run coverage:test:ava | grep -E 'Lines\s*:\s*[0-9]+(\.[0-9]+)?%' | awk '{print $3}' | tr -d '%')" >> $GITHUB_ENV - name: Report coverage - run: npx c8 report + run: npx c8 report --all - name: Update coverage badge uses: schneegans/dynamic-badges-action@v1.7.0 diff --git a/.gitmodules b/.gitmodules index 0a5efa2..463c443 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,6 @@ -[submodule "WABT"] - path = WABT - url = git@github.com:TOPLLab/wabt.git [submodule "tests/unit/artifacts/wabt"] - path = tests/unit/artifacts/wabt + path = tests/artifacts/wabt url = git@github.com:TOPLLab/wabt.git [submodule "tests/unit/artifacts/warduino"] - path = tests/unit/artifacts/warduino + path = tests/artifacts/warduino url = git@github.com:TOPLLab/WARDuino.git diff --git a/tests/unit/artifacts/compile.output b/tests/artifacts/compile.output similarity index 100% rename from tests/unit/artifacts/compile.output rename to tests/artifacts/compile.output diff --git a/tests/unit/artifacts/dump b/tests/artifacts/dump similarity index 100% rename from tests/unit/artifacts/dump rename to tests/artifacts/dump diff --git a/tests/unit/artifacts/upload.wasm b/tests/artifacts/upload.wasm similarity index 100% rename from tests/unit/artifacts/upload.wasm rename to tests/artifacts/upload.wasm diff --git a/tests/unit/artifacts/wabt b/tests/artifacts/wabt similarity index 100% rename from tests/unit/artifacts/wabt rename to tests/artifacts/wabt diff --git a/tests/unit/artifacts/warduino b/tests/artifacts/warduino similarity index 100% rename from tests/unit/artifacts/warduino rename to tests/artifacts/warduino diff --git a/tests/unit/sourcemap.test.ts b/tests/unit/sourcemap.test.ts index 8592b2d..2e46b01 100644 --- a/tests/unit/sourcemap.test.ts +++ b/tests/unit/sourcemap.test.ts @@ -5,7 +5,7 @@ import {SourceMap} from '../../src/sourcemap/SourceMap'; import {WABT} from '../../src/util/env'; import {mkdtempSync, readFileSync, copyFileSync} from 'fs'; -const artifacts = `${__dirname}/../../../tests/unit/artifacts`; +const artifacts = `${__dirname}/../../../tests/artifacts`; test('test wasm/leb128', t => { t.is(WASM.leb128(0), '00'); @@ -28,4 +28,4 @@ test('test WatMapper/extractLineInfo', async t => { const mapper: WatMapper = new WatMapper(dummy, initialize(), WABT); const mapping: SourceMap.Mapping = await mapper.mapping(); t.true(mapping.lines.length > 0); -}); \ No newline at end of file +}); diff --git a/tsconfig.json b/tsconfig.json index e01c580..99b39c1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,9 +16,10 @@ "allowJs": true }, "exclude": [ - "WABT", + "wabt", "node_modules", "dist", - "tests/examples" + "tests/examples", + "warduino" ] } From bf18bf2be1909a0d4b6c4ae3736abfc5c090f009 Mon Sep 17 00:00:00 2001 From: tolauwae Date: Mon, 30 Dec 2024 14:24:12 +0100 Subject: [PATCH 12/16] Run only unit tests in CI --- .github/workflows/test.yml | 44 -------------------------------------- 1 file changed, 44 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a52084b..aff8049 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -76,8 +76,6 @@ jobs: name: Unit tests runs-on: ubuntu-latest needs: build-wabt - strategy: - fail-fast: false if: github.event.pull_request.draft == false steps: - uses: actions/checkout@v4 @@ -103,52 +101,10 @@ jobs: env: WABT: ${GITHUB_WORKSPACE}/.tools - warduino: - name: WARDuino test - runs-on: ubuntu-latest - needs: [build-wabt, build-wdcli] - strategy: - fail-fast: false - if: github.event.pull_request.draft == false - steps: - - uses: actions/checkout@v4 - - - run: npm i - - - name: Prebuild files - run: npm run test:prebuild - - - name: Download WAT tools - uses: actions/download-artifact@v4 - with: - name: wabt-build-${{ github.run_id }} - path: .tools - - - name: Download WARDuino - uses: actions/download-artifact@v4 - with: - name: warduino-build-${{ github.run_id }} - path: .warduino - - - name: Verify - run: | - chmod u+x $GITHUB_WORKSPACE/.tools/* - chmod u+x $GITHUB_WORKSPACE/.warduino/wdcli - $GITHUB_WORKSPACE/.tools/wasm-objdump --version - #$GITHUB_WORKSPACE/.warduino/wdcli --version - - - name: Run example WARDuino test - run: npm run test:example - env: - WABT: ${{ github.workspace }}/.tools - EMULATOR: ${{ github.workspace }}/.warduino/wdcli - coverage: name: Code coverage runs-on: ubuntu-latest needs: build-wabt - strategy: - fail-fast: true if: github.event.pull_request.draft == false steps: - uses: actions/checkout@v4 From 46e7bb78e166151d0d30014a87e41b77834f52ce Mon Sep 17 00:00:00 2001 From: tolauwae Date: Tue, 31 Dec 2024 14:35:53 +0100 Subject: [PATCH 13/16] Remove tmp dir in tests --- tests/unit/sourcemap.test.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/unit/sourcemap.test.ts b/tests/unit/sourcemap.test.ts index 2e46b01..a54ce4a 100644 --- a/tests/unit/sourcemap.test.ts +++ b/tests/unit/sourcemap.test.ts @@ -3,7 +3,7 @@ import {WASM} from '../../src/sourcemap/Wasm'; import {WatMapper} from '../../src/sourcemap/SourceMapper'; import {SourceMap} from '../../src/sourcemap/SourceMap'; import {WABT} from '../../src/util/env'; -import {mkdtempSync, readFileSync, copyFileSync} from 'fs'; +import {copyFileSync, mkdtempSync, readFileSync, rmdirSync} from 'fs'; const artifacts = `${__dirname}/../../../tests/artifacts`; @@ -18,14 +18,16 @@ test('test wasm/leb128', t => { }); function initialize(): string { - const tmp: string = mkdtempSync(''); + const tmp: string = mkdtempSync('test'); copyFileSync(`${artifacts}/upload.wasm`, `${tmp}/upload.wasm`); return tmp; } test('test WatMapper/extractLineInfo', async t => { const dummy = readFileSync(`${artifacts}/compile.output`).toString(); - const mapper: WatMapper = new WatMapper(dummy, initialize(), WABT); + const path = initialize(); + const mapper: WatMapper = new WatMapper(dummy, path, WABT); const mapping: SourceMap.Mapping = await mapper.mapping(); t.true(mapping.lines.length > 0); + rmdirSync(path, {recursive: true}); }); From 4b319bc5f8d3e7bbc7b1f36864e6d57e954d6d1d Mon Sep 17 00:00:00 2001 From: tolauwae Date: Wed, 1 Jan 2025 13:43:40 +0100 Subject: [PATCH 14/16] Test wasm mapper --- tests/unit/sourcemap.test.ts | 77 ++++++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 13 deletions(-) diff --git a/tests/unit/sourcemap.test.ts b/tests/unit/sourcemap.test.ts index a54ce4a..2103a72 100644 --- a/tests/unit/sourcemap.test.ts +++ b/tests/unit/sourcemap.test.ts @@ -3,31 +3,82 @@ import {WASM} from '../../src/sourcemap/Wasm'; import {WatMapper} from '../../src/sourcemap/SourceMapper'; import {SourceMap} from '../../src/sourcemap/SourceMap'; import {WABT} from '../../src/util/env'; -import {copyFileSync, mkdtempSync, readFileSync, rmdirSync} from 'fs'; +import {copyFileSync, mkdtempSync, readFileSync, rmSync} from 'fs'; const artifacts = `${__dirname}/../../../tests/artifacts`; +/** + * Check LEB 128 encoding + */ test('test wasm/leb128', t => { t.is(WASM.leb128(0), '00'); t.is(WASM.leb128(1), '01'); t.is(WASM.leb128(8), '08'); t.is(WASM.leb128(32), '20'); - // t.is(WASM.leb128(64), '40'); + t.is(WASM.leb128(64), 'C000'); t.is(WASM.leb128(128), '8001'); - // t.is(WASM.leb128(1202), 'b209'); + t.is(WASM.leb128(1202), 'B209'); }); -function initialize(): string { - const tmp: string = mkdtempSync('test'); - copyFileSync(`${artifacts}/upload.wasm`, `${tmp}/upload.wasm`); - return tmp; -} - test('test WatMapper/extractLineInfo', async t => { - const dummy = readFileSync(`${artifacts}/compile.output`).toString(); + await check(`${artifacts}/compile.output`, (mapping: SourceMap.Mapping) => { + // check line information + t.true(mapping.lines.some((entry) => + entry.line === 13 && + // entry.columnStart === 21 && + entry.columnEnd === 30 && + entry.instructions.some((entry) => + entry.address === 114))); + + t.true(mapping.lines.some((entry) => + entry.line === 22 && + // entry.columnStart === 5 && + entry.columnEnd === 9 && + entry.instructions.some((entry) => + entry.address === 158))); + }); +}) +; + +test('test WatMapper/extractImportInfo', async t => { + await check(`${artifacts}/compile.output`, (mapping: SourceMap.Mapping) => { + // check imports + t.true(mapping.imports.some((entry) => entry.name.includes('chip_delay') && entry.index === 0)); + t.true(mapping.imports.some((entry) => entry.name.includes('chip_pin_mod') && entry.index === 1)); + t.true(mapping.imports.some((entry) => entry.name.includes('chip_digital') && entry.index === 2)); + }); +}); + +test('test WatMapper/extractGlobalInfo', async t => { + await check(`${artifacts}/compile.output`, (mapping: SourceMap.Mapping) => { + // check globals + t.true(mapping.globals.some((entry) => entry.name.includes('led') && entry.index === 0)); + t.true(mapping.globals.some((entry) => entry.name.includes('on') && entry.index === 1)); + t.true(mapping.globals.some((entry) => entry.name.includes('off') && entry.index === 2)); + }); +}); + +test('test WatMapper/getFunctionInfos', async t => { + await check(`${artifacts}/compile.output`, (mapping: SourceMap.Mapping) => { + // check functions + t.true(mapping.functions.some((entry) => entry.name.includes('blink') && entry.index === 4)); + }); +}); + +// run a set of _checks_ against the source mapping for a given _filename_ +async function check(filename: string, checks: (mapping: SourceMap.Mapping) => void) { + const dummy = readFileSync(filename).toString(); const path = initialize(); const mapper: WatMapper = new WatMapper(dummy, path, WABT); const mapping: SourceMap.Mapping = await mapper.mapping(); - t.true(mapping.lines.length > 0); - rmdirSync(path, {recursive: true}); -}); + + checks(mapping); + + rmSync(path, {recursive: true}); +} + +function initialize(): string { + const tmp: string = mkdtempSync('test'); + copyFileSync(`${artifacts}/upload.wasm`, `${tmp}/upload.wasm`); + return tmp; +} \ No newline at end of file From ee918f3bf9340a556240cedfd2d722cecc56b11f Mon Sep 17 00:00:00 2001 From: tolauwae Date: Wed, 8 Jan 2025 12:01:30 +0100 Subject: [PATCH 15/16] Add scenario describer tests --- package.json | 1 + src/reporter/Reporter.ts | 12 ------ src/reporter/describers/SuiteDescribers.ts | 1 - tests/unit/describers.test.ts | 46 ++++++++++++++++++++++ 4 files changed, 47 insertions(+), 13 deletions(-) create mode 100644 tests/unit/describers.test.ts diff --git a/package.json b/package.json index 7fccec2..1bc4134 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ }, "ava": { "files": [ + "out/tests/unit/describers.test.js", "out/tests/unit/util.test.js", "out/tests/unit/sourcemap.test.js" ], diff --git a/src/reporter/Reporter.ts b/src/reporter/Reporter.ts index f1cdbd7..c88c643 100644 --- a/src/reporter/Reporter.ts +++ b/src/reporter/Reporter.ts @@ -119,19 +119,7 @@ export class Reporter { this.archiver.write(); } - info(text: string) { - this.output += `info: ${text}\n`; - } - error(text: string) { this.output += `error: ${text}\n`; } - - suite(title: string) { - this.output += `suite: ${title}\n`; - } - - test(title: string) { - this.output += ` test: ${title}\n`; - } } \ No newline at end of file diff --git a/src/reporter/describers/SuiteDescribers.ts b/src/reporter/describers/SuiteDescribers.ts index 47f2dd6..3d52609 100644 --- a/src/reporter/describers/SuiteDescribers.ts +++ b/src/reporter/describers/SuiteDescribers.ts @@ -67,5 +67,4 @@ export class NormalSuiteDescriber extends ShortSuiteDescriber { return report; } - } diff --git a/tests/unit/describers.test.ts b/tests/unit/describers.test.ts new file mode 100644 index 0000000..18d9c70 --- /dev/null +++ b/tests/unit/describers.test.ts @@ -0,0 +1,46 @@ +import test from 'ava'; +import { + MinimalScenarioDescriber, + NormalScenarioDescriber, + ShortScenarioDescriber +} from '../../src/reporter/describers/ScenarioDescribers'; +import {ScenarioResult, StepOutcome, SuiteResult} from '../../src/reporter/Results'; +import {Kind, Message, Step} from '../../src'; +import {Outcome} from '../../src/reporter/describers/Describer'; +import {Plain} from '../../src/reporter/Style'; + +const steps: Step[] = [ + { + title: 'Send DUMP command', + instruction: {kind: Kind.Request, value: Message.dump}, + expected: [{'pc': {kind: 'comparison', value: (_: Object, value: number) => value > 0}}] + }, { + title: 'Send STEP OVER command', + instruction: {kind: Kind.Request, value: Message.stepOver} + } +]; +const dummy = new ScenarioResult({ + title: 'Scenario title', program: 'artifacts/blink.wat', steps: steps +}); + +test('Test MinimalScenarioDescriber', t => { + const describer = new MinimalScenarioDescriber(dummy); + dummy.aggregate([new StepOutcome(steps[0]).update(Outcome.succeeded), new StepOutcome(steps[1]).update(Outcome.succeeded)]); + t.is(describer.describe(new Plain()).join('\n'), '\x1B[1m\x1B[34mscenario.\x1B[39m\x1B[22m \x1B[1mScenario title\x1B[22m \n'); +}); + +test('Test ShortScenarioDescriber', t => { + const describer = new ShortScenarioDescriber(dummy); + const output = describer.describe(new Plain()).join('\n'); + t.is(output, '\x1B[1m\x1B[34mscenario.\x1B[39m\x1B[22m \x1B[1mScenario title\x1B[22m \n'); + t.false(['Send DUMP command', 'Send STEP OVER command'].some((element) => output.includes(element))); +}); + +test('Test NormalScenarioDescriber', t => { + let output = new NormalScenarioDescriber(dummy).describe(new Plain()).join('\n'); + t.true(['PASS', 'Send DUMP command', 'Send STEP OVER command'].every((element) => output.includes(element))); + t.false(['FAIL'].some((element) => output.includes(element))); + dummy.aggregate([new StepOutcome(steps[0]).update(Outcome.failed), new StepOutcome(steps[1]).update(Outcome.succeeded)]); + output = new NormalScenarioDescriber(dummy).describe(new Plain()).join('\n'); + t.true(['FAIL', 'Send DUMP command', 'PASS', 'Send STEP OVER command'].every((element) => output.includes(element))); +}); From 679c636966da2ca392d2d7bc7c9aef69c4ce4995 Mon Sep 17 00:00:00 2001 From: tolauwae Date: Wed, 8 Jan 2025 15:36:18 +0100 Subject: [PATCH 16/16] Add MessageQueue tests --- package.json | 131 +++++++++++++++++----------------- src/messaging/MessageQueue.ts | 3 + tests/unit/describers.test.ts | 6 +- tests/unit/messaging.test.ts | 78 ++++++++++++++++++++ tests/unit/sourcemap.test.ts | 10 +-- tests/unit/util.test.ts | 12 ++-- 6 files changed, 162 insertions(+), 78 deletions(-) create mode 100644 tests/unit/messaging.test.ts diff --git a/package.json b/package.json index 1bc4134..6dfb99a 100644 --- a/package.json +++ b/package.json @@ -1,70 +1,71 @@ { - "name": "latch", - "description": "A testing language for constraint environments", - "version": "0.3.1", - "type": "commonjs", - "exports": { - "types": "./dist/types/index.d.ts", - "require": "./dist/cjs/index.cjs" - }, - "main": "dist/cjs/index.cjs", - "types": "dist/types/index.d.ts", + "name": "latch", + "description": "A testing language for constraint environments", + "version": "0.3.1", + "type": "commonjs", + "exports": { + "types": "./dist/types/index.d.ts", + "require": "./dist/cjs/index.cjs" + }, + "main": "dist/cjs/index.cjs", + "types": "dist/types/index.d.ts", + "files": [ + "dist", + "bin" + ], + "scripts": { + "clean": "rm -rf dist", + "build": "npm run build:cjs", + "build:cjs": "tsc --project tsconfig.build.json", + "build:tests": "tsc --outDir out --project tsconfig.tests.json", + "watch": "tsc -watch -p ./", + "lint": "eslint src/**/* --config .eslint.config.mjs", + "test:prebuild": "npm run build && npm run build:tests", + "test:all": "npm run test:prebuild && npm run test:ava", + "test:ava": "ava", + "test:example": "npx ts-node ./tests/examples/example.ts", + "coverage:test:ava": "c8 --src src/ --all ava" + }, + "dependencies": { + "ansi-colors": "^4.1.3", + "ieee754": "^1.2.1", + "ora": "^8.0.1", + "source-map": "^0.7.4", + "ts-node": "^10.5.0", + "tslib": "^2.8.1" + }, + "devDependencies": { + "@ava/typescript": "^5.0.0", + "@eslint/js": "^9.16.0", + "@stylistic/eslint-plugin-js": "^2.11.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.1.0", + "@types/node": "^20.10.4", + "@types/uuid": "^9.0.0", + "@types/ws": "^8.5.4", + "@typescript-eslint/eslint-plugin": "^8.17.0", + "ava": "^6.2.0", + "c8": "^10.1.2", + "convert-extension": "^0.3.0", + "eslint": "^9.16.0", + "globals": "^15.13.0", + "mqtt": "^4.3.7", + "serialport": "^10.4.0", + "typescript": "^5.2.0", + "typescript-eslint": "^8.17.0" + }, + "ava": { "files": [ - "dist", - "bin" + "out/tests/unit/describers.test.js", + "out/tests/unit/messaging.test.js", + "out/tests/unit/sourcemap.test.js", + "out/tests/unit/util.test.js" ], - "scripts": { - "clean": "rm -rf dist", - "build": "npm run build:cjs", - "build:cjs": "tsc --project tsconfig.build.json", - "build:tests": "tsc --outDir out --project tsconfig.tests.json", - "watch": "tsc -watch -p ./", - "lint": "eslint src/**/* --config .eslint.config.mjs", - "test:prebuild": "npm run build && npm run build:tests", - "test:all": "npm run test:prebuild && npm run test:ava", - "test:ava": "ava", - "test:example": "npx ts-node ./tests/examples/example.ts", - "coverage:test:ava": "c8 --src src/ --all ava" - }, - "dependencies": { - "ansi-colors": "^4.1.3", - "ieee754": "^1.2.1", - "ora": "^8.0.1", - "source-map": "^0.7.4", - "ts-node": "^10.5.0", - "tslib": "^2.8.1" - }, - "devDependencies": { - "@ava/typescript": "^5.0.0", - "@eslint/js": "^9.16.0", - "@stylistic/eslint-plugin-js": "^2.11.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.1.0", - "@types/node": "^20.10.4", - "@types/uuid": "^9.0.0", - "@types/ws": "^8.5.4", - "@typescript-eslint/eslint-plugin": "^8.17.0", - "ava": "^6.2.0", - "c8": "^10.1.2", - "convert-extension": "^0.3.0", - "eslint": "^9.16.0", - "globals": "^15.13.0", - "mqtt": "^4.3.7", - "serialport": "^10.4.0", - "typescript": "^5.2.0", - "typescript-eslint": "^8.17.0" - }, - "ava": { - "files": [ - "out/tests/unit/describers.test.js", - "out/tests/unit/util.test.js", - "out/tests/unit/sourcemap.test.js" - ], - "typescript": { - "compile": false, - "rewritePaths": { - "src/": "dist/" - } - } + "typescript": { + "compile": false, + "rewritePaths": { + "src/": "dist/" + } } + } } diff --git a/src/messaging/MessageQueue.ts b/src/messaging/MessageQueue.ts index ecb37b8..1da95fb 100644 --- a/src/messaging/MessageQueue.ts +++ b/src/messaging/MessageQueue.ts @@ -2,6 +2,9 @@ export class MessageQueue implements Iterable { private readonly delimiter: string; private queue: string[]; + /** + * @param delimiter the EOM (end-of-message) token + */ constructor(delimiter: string) { this.delimiter = delimiter; this.queue = []; diff --git a/tests/unit/describers.test.ts b/tests/unit/describers.test.ts index 18d9c70..6b0d94b 100644 --- a/tests/unit/describers.test.ts +++ b/tests/unit/describers.test.ts @@ -23,20 +23,20 @@ const dummy = new ScenarioResult({ title: 'Scenario title', program: 'artifacts/blink.wat', steps: steps }); -test('Test MinimalScenarioDescriber', t => { +test('[MinimalScenarioDescriber] : test printing', t => { const describer = new MinimalScenarioDescriber(dummy); dummy.aggregate([new StepOutcome(steps[0]).update(Outcome.succeeded), new StepOutcome(steps[1]).update(Outcome.succeeded)]); t.is(describer.describe(new Plain()).join('\n'), '\x1B[1m\x1B[34mscenario.\x1B[39m\x1B[22m \x1B[1mScenario title\x1B[22m \n'); }); -test('Test ShortScenarioDescriber', t => { +test('[ShortScenarioDescriber] : test printing', t => { const describer = new ShortScenarioDescriber(dummy); const output = describer.describe(new Plain()).join('\n'); t.is(output, '\x1B[1m\x1B[34mscenario.\x1B[39m\x1B[22m \x1B[1mScenario title\x1B[22m \n'); t.false(['Send DUMP command', 'Send STEP OVER command'].some((element) => output.includes(element))); }); -test('Test NormalScenarioDescriber', t => { +test('[NormalScenarioDescriber] : test printing', t => { let output = new NormalScenarioDescriber(dummy).describe(new Plain()).join('\n'); t.true(['PASS', 'Send DUMP command', 'Send STEP OVER command'].every((element) => output.includes(element))); t.false(['FAIL'].some((element) => output.includes(element))); diff --git a/tests/unit/messaging.test.ts b/tests/unit/messaging.test.ts new file mode 100644 index 0000000..9f64070 --- /dev/null +++ b/tests/unit/messaging.test.ts @@ -0,0 +1,78 @@ +import test from 'ava'; +import {MessageQueue} from '../../src/messaging/MessageQueue'; + +const alphanumerical = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.split(''); + +test('[MessageQueue] : test EOM detection', t => { + const fuzzer = fuzzy(alphanumerical); + const newline = new MessageQueue('\n'); + newline.push(fuzzer(9)); + t.false(newline.hasCompleteMessage()); + for (let i = 0; i < 5; i++) { + newline.push(fuzzer(20)); + } + t.false(newline.hasCompleteMessage()); + newline.push('\n'); + t.true(newline.hasCompleteMessage()); + + const semicolon = new MessageQueue(';'); + t.false(semicolon.hasCompleteMessage()); + semicolon.push(fuzzer(38) + ';' + fuzzer(3)); + t.true(newline.hasCompleteMessage()); + + const longer = new MessageQueue(' | '); + t.false(longer.hasCompleteMessage()); + longer.push(fuzzer(38) + ' | ' + fuzzer(3)); + t.true(longer.hasCompleteMessage()); +}); + +test('[MessageQueue] : test message retrieval', t => { + const fuzzer = fuzzy(alphanumerical); + + const message = fuzzy(alphanumerical)(30) + ';' + + const queue = new MessageQueue(';'); + queue.push(message); + queue.push(fuzzy(alphanumerical.concat([';']))(1028)); + t.is(queue.pop(), message); +}); + +test('[MessageQueue] : test iterator', t => { + const fuzzer = fuzzy(alphanumerical); + const queue = new MessageQueue(';'); + queue.push(fuzzer(16) + ';' + fuzzer(16) + ';' + fuzzer(16) + ';' + fuzzer(16)); + + let count = 0; + for (const message of queue) { + count++; + t.true(message.includes(';')); + t.is(message.length, 17); + } + t.true(count === 3); +}); + +test('[MessageQueue] : fuzz iterator', t => { + const EOM = ';' + const fuzzer = fuzzy(alphanumerical.concat([EOM])); + + for (let i = 0; i < 4096; i++) { + const input = fuzzer(2048); + const count = (input.match(new RegExp(`${EOM}`, 'g')) || []).length; + + const queue = new MessageQueue(EOM); + queue.push(input); + t.is([...queue].length, count); + } +}); + + +const fuzzy = (characters: string[]): (n: number) => string => { + const options = characters.length; + return (length: number) => { + let result = ''; + for (let counter = 0; counter < length; counter++) { + result += characters[Math.floor(Math.random() * options)]; + } + return result; + }; +} \ No newline at end of file diff --git a/tests/unit/sourcemap.test.ts b/tests/unit/sourcemap.test.ts index 2103a72..6e21d96 100644 --- a/tests/unit/sourcemap.test.ts +++ b/tests/unit/sourcemap.test.ts @@ -10,7 +10,7 @@ const artifacts = `${__dirname}/../../../tests/artifacts`; /** * Check LEB 128 encoding */ -test('test wasm/leb128', t => { +test('[leb128] : test encoding', t => { t.is(WASM.leb128(0), '00'); t.is(WASM.leb128(1), '01'); t.is(WASM.leb128(8), '08'); @@ -20,7 +20,7 @@ test('test wasm/leb128', t => { t.is(WASM.leb128(1202), 'B209'); }); -test('test WatMapper/extractLineInfo', async t => { +test('[extractLineInfo] : test against artifacts (1)', async t => { await check(`${artifacts}/compile.output`, (mapping: SourceMap.Mapping) => { // check line information t.true(mapping.lines.some((entry) => @@ -40,7 +40,7 @@ test('test WatMapper/extractLineInfo', async t => { }) ; -test('test WatMapper/extractImportInfo', async t => { +test('[extractImportInfo] : test against artifacts (1)', async t => { await check(`${artifacts}/compile.output`, (mapping: SourceMap.Mapping) => { // check imports t.true(mapping.imports.some((entry) => entry.name.includes('chip_delay') && entry.index === 0)); @@ -49,7 +49,7 @@ test('test WatMapper/extractImportInfo', async t => { }); }); -test('test WatMapper/extractGlobalInfo', async t => { +test('[extractGlobalInfo] : test against artifacts (1)', async t => { await check(`${artifacts}/compile.output`, (mapping: SourceMap.Mapping) => { // check globals t.true(mapping.globals.some((entry) => entry.name.includes('led') && entry.index === 0)); @@ -58,7 +58,7 @@ test('test WatMapper/extractGlobalInfo', async t => { }); }); -test('test WatMapper/getFunctionInfos', async t => { +test('[getFunctionInfos] : test against artifacts (1)', async t => { await check(`${artifacts}/compile.output`, (mapping: SourceMap.Mapping) => { // check functions t.true(mapping.functions.some((entry) => entry.name.includes('blink') && entry.index === 4)); diff --git a/tests/unit/util.test.ts b/tests/unit/util.test.ts index 72765d8..a0bbbee 100644 --- a/tests/unit/util.test.ts +++ b/tests/unit/util.test.ts @@ -3,21 +3,21 @@ import {find, getFileExtension} from '../../src/util/util'; import {indent} from '../../src/util/printing'; import {retry} from '../../src/util/retry'; -test('test util/getFileExtension', t => { +test('[getFileExtension] : test core functionality', t => { t.is(getFileExtension('test.wast'), 'wast'); t.is(getFileExtension('util.test.js'), 'js'); t.is(getFileExtension('float_misc.asserts.wast'), 'wast'); t.is(getFileExtension('simd_i16x8_extadd_pairwise_i8x16.wast'), 'wast'); }); -test('test errors in util/getFileExtension', t => { +test('[getFileExtension] : test error throwing', t => { const error = t.throws(() => { getFileExtension('impossible') }, {instanceOf: Error}); t.is(error.message, 'Could not determine file type'); }); -test('test util/find', t => { +test('[find] : test core functionality', t => { t.is(find(/(wast)/, 'test.wast'), 'wast'); t.is(find(/(.wast)/, 'impossible'), ''); t.is(find(/—(.*)—/, 'Jeeves—my man, you know—is really a most extraordinary chap.'), 'my man, you know'); @@ -26,7 +26,7 @@ test('test util/find', t => { t.is(find(/([a-zA-Z]{11,})/, 'The unanimous Declaration of the thirteen united States of America, When in the Course of human events, it becomes necessary for one people to dissolve the political bands which have connected them with another, and to assume among the powers of the earth, the separate and equal station to which the Laws of Nature and of Nature\'s God entitle them, a decent respect to the opinions of mankind requires that they should declare the causes which impel them to the separation.'), 'Declaration'); }); -test('test printing/indent', t => { +test('[indent] : test printing', t => { t.is(indent(4), ' '); t.is(indent(4, 1), ' '); t.is(indent(1, 4), ' '); @@ -43,11 +43,13 @@ const attempt = (count: number, n: number) => retry(async () => { }) }, n); -test('test retry/retry', async t => { +test('[retry] : test core functionality', async t => { t.is(await attempt(2, 2), 0); t.is(await attempt(2, 4), 0); t.is(await attempt(8, 9), 0); +}); +test('[retry] : test error throwing', async t => { const error = await t.throwsAsync(attempt(2, 1)); t.is(error.message, `exhausted number of retries (${1})`); }); \ No newline at end of file