From fefd7a1bc782b90a305923bfa2b8f04eca3a5ed4 Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Mon, 29 Nov 2021 16:50:41 +0000 Subject: [PATCH] Tests: refactored JavaScript tests. A generic runner test/run is introduced. It runs all available tests in test/ directory. JavaScript files are expected to be compliant with Test262. --- auto/make | 6 +- test/finalize | 11 + test/fs/{methods.js => methods.t.js} | 237 ++++++----- test/fs/promises_01.t.js | 42 ++ .../promises_02.t.js} | 46 +- .../promises_03.t.js} | 26 +- .../promises_04.t.js} | 36 +- .../promises_05.t.js} | 34 +- .../promises_06.t.js} | 29 +- .../promises_07.t.js} | 36 +- .../promises_08.t.js} | 17 +- .../promises_09.t.js} | 23 +- test/harness/assert.js | 118 +++++ test/harness/compareArray.js | 42 ++ test/harness/compatBuffer.js | 3 + test/harness/compatFs.js | 11 + test/harness/compatPrint.js | 3 + test/harness/compatWebcrypto.js | 8 + test/harness/doneprintHandle.js | 22 + test/harness/runTsuite.js | 54 +++ test/harness/sta.js | 27 ++ test/harness/webCryptoUtils.js | 13 + test/js/async_await_add.js | 7 - test/js/async_await_add.t.js | 15 + test/js/async_await_blank.js | 5 - test/js/async_await_blank.t.js | 13 + test/js/async_await_catch.js | 5 - test/js/async_await_catch.t.js | 13 + test/js/async_await_finally.js | 6 - test/js/async_await_finally.t.js | 15 + ...sync_await_for.js => async_await_for.t.js} | 10 +- ...wait_inline.js => async_await_inline.t.js} | 11 +- ...any_call.js => async_await_many_call.t.js} | 9 +- test/js/async_await_reject.js | 5 - test/js/async_await_reject.t.js | 15 + ...wait_stages.js => async_await_stages.t.js} | 10 +- ..._await_throw.js => async_await_throw.t.js} | 12 +- ..._async.js => async_await_throw_async.t.js} | 12 +- ..._catch.js => async_await_throw_catch.t.js} | 10 +- ....js => async_await_throw_catch_async.t.js} | 12 +- test/js/async_await_try_catch.js | 19 - test/js/async_await_try_catch.t.js | 30 ++ ...inally.js => async_await_try_finally.t.js} | 18 +- ...esolve.js => async_await_try_resolve.t.js} | 10 +- test/js/async_await_try_throw.js | 14 - test/js/async_await_try_throw.t.js | 27 ++ test/js/async_await_try_throw_catch.js | 17 - test/js/async_await_try_throw_catch.t.js | 27 ++ test/js/fs_promises_001.js | 55 --- test/js/promise_all.js | 9 - test/js/promise_all.t.js | 16 + ..._allSettled.js => promise_allSettled.t.js} | 12 +- ...ring.js => promise_allSettled_string.t.js} | 12 +- ...se_all_throw.js => promise_all_throw.t.js} | 12 +- test/js/{promise_any.js => promise_any.t.js} | 12 +- test/js/promise_any_all_rejected.js | 7 - test/js/promise_any_all_rejected.t.js | 13 + test/js/promise_catch_then_throw_catch.js | 5 - test/js/promise_catch_then_throw_catch.t.js | 14 + test/js/promise_catch_throw.js | 3 - test/js/promise_catch_throw.t.js | 10 + test/js/promise_finally.js | 7 - test/js/promise_finally.t.js | 14 + test/js/promise_finally_throw.js | 2 - test/js/promise_finally_throw.t.js | 9 + test/js/promise_finally_throw_catch.js | 3 - test/js/promise_finally_throw_catch.t.js | 9 + .../js/{promise_race.js => promise_race.t.js} | 12 +- ..._race_throw.js => promise_race_throw.t.js} | 12 +- test/js/promise_reject_catch.js | 1 - test/js/promise_reject_catch.t.js | 8 + test/js/promise_reject_post_catch.js | 2 - test/js/promise_reject_post_catch.t.js | 9 + test/js/promise_rejection_tracker.js | 1 - test/js/promise_rejection_tracker.t.js | 9 + test/js/promise_s01.t.js | 22 + test/js/promise_s02.t.js | 23 + test/js/promise_s03.t.js | 21 + test/js/promise_s04.t.js | 12 + test/js/promise_s05.t.js | 18 + test/js/promise_s06.t.js | 10 + test/js/promise_s07.t.js | 15 + test/js/promise_s08.t.js | 22 + test/js/promise_s09.t.js | 15 + test/js/promise_s1.js | 15 - test/js/promise_s10.js | 11 - test/js/promise_s10.t.js | 20 + test/js/promise_s11.js | 13 - test/js/promise_s11.t.js | 22 + test/js/promise_s12.js | 10 - test/js/promise_s12.t.js | 19 + test/js/promise_s13.js | 21 - test/js/promise_s13.t.js | 23 + test/js/promise_s14.js | 9 - test/js/promise_s14.t.js | 21 + test/js/promise_s15.js | 10 - test/js/promise_s15.t.js | 16 + test/js/promise_s16.js | 10 - test/js/promise_s16.t.js | 16 + test/js/promise_s17.js | 10 - test/js/promise_s17.t.js | 18 + test/js/{promise_s18.js => promise_s18.t.js} | 21 +- test/js/promise_s19.js | 33 -- test/js/promise_s19.t.js | 34 ++ test/js/promise_s2.js | 14 - test/js/promise_s20.js | 23 - test/js/promise_s20.t.js | 25 ++ test/js/{promise_s21.js => promise_s21.t.js} | 24 +- test/js/promise_s22.js | 32 -- test/js/promise_s22.t.js | 32 ++ test/js/promise_s23.js | 28 -- test/js/promise_s23.t.js | 25 ++ test/js/{promise_s24.js => promise_s24.t.js} | 9 +- test/js/promise_s25.js | 29 -- test/js/promise_s25.t.js | 24 ++ test/js/promise_s26.js | 144 ------- test/js/promise_s26.t.js | 211 +++++++++ test/js/promise_s3.js | 11 - test/js/promise_s4.js | 6 - test/js/promise_s5.js | 7 - test/js/promise_s6.js | 4 - test/js/promise_s7.js | 12 - test/js/promise_s8.js | 13 - test/js/promise_s9.js | 10 - ...et_timeout.js => promise_set_timeout.t.js} | 12 +- test/js/promise_then_throw.js | 2 - test/js/promise_then_throw.t.js | 9 + test/js/promise_then_throw_catch.js | 3 - test/js/promise_then_throw_catch.t.js | 12 + test/js/promise_then_throw_finally_catch.js | 4 - test/js/promise_then_throw_finally_catch.t.js | 13 + ...w.js => promise_two_first_then_throw.t.js} | 7 + test/js/promise_two_then_throw.js | 5 - test/js/promise_two_then_throw.t.js | 12 + test/njs_expect_test.exp | 402 ------------------ test/options | 61 +++ test/prepare | 36 ++ test/report | 18 + test/setup | 39 ++ test/test262 | 64 +++ test/webcrypto/{aes.js => aes.t.js} | 69 +-- .../{aes_decoding.js => aes_decoding.t.js} | 71 +--- test/webcrypto/{derive.js => derive.t.js} | 87 +--- test/webcrypto/{digest.js => digest.t.js} | 56 +-- test/webcrypto/{rsa.js => rsa.t.js} | 72 +--- test/webcrypto/rsa_decoding.js | 83 ---- test/webcrypto/rsa_decoding.t.js | 41 ++ test/webcrypto/{sign.js => sign.t.js} | 152 ++----- test/webcrypto/{verify.js => verify.t.js} | 102 +---- 149 files changed, 2200 insertions(+), 1894 deletions(-) create mode 100644 test/finalize rename test/fs/{methods.js => methods.t.js} (76%) create mode 100644 test/fs/promises_01.t.js rename test/{js/fs_promises_002.js => fs/promises_02.t.js} (63%) rename test/{js/fs_promises_003.js => fs/promises_03.t.js} (84%) rename test/{js/fs_promises_004.js => fs/promises_04.t.js} (87%) rename test/{js/fs_promises_005.js => fs/promises_05.t.js} (83%) rename test/{js/fs_promises_006.js => fs/promises_06.t.js} (81%) rename test/{js/fs_promises_007.js => fs/promises_07.t.js} (90%) rename test/{js/fs_promises_008.js => fs/promises_08.t.js} (87%) rename test/{js/fs_promises_009.js => fs/promises_09.t.js} (88%) create mode 100644 test/harness/assert.js create mode 100644 test/harness/compareArray.js create mode 100644 test/harness/compatBuffer.js create mode 100644 test/harness/compatFs.js create mode 100644 test/harness/compatPrint.js create mode 100644 test/harness/compatWebcrypto.js create mode 100644 test/harness/doneprintHandle.js create mode 100644 test/harness/runTsuite.js create mode 100644 test/harness/sta.js create mode 100644 test/harness/webCryptoUtils.js delete mode 100644 test/js/async_await_add.js create mode 100644 test/js/async_await_add.t.js delete mode 100644 test/js/async_await_blank.js create mode 100644 test/js/async_await_blank.t.js delete mode 100644 test/js/async_await_catch.js create mode 100644 test/js/async_await_catch.t.js delete mode 100644 test/js/async_await_finally.js create mode 100644 test/js/async_await_finally.t.js rename test/js/{async_await_for.js => async_await_for.t.js} (57%) rename test/js/{async_await_inline.js => async_await_inline.t.js} (52%) rename test/js/{async_await_many_call.js => async_await_many_call.t.js} (78%) delete mode 100644 test/js/async_await_reject.js create mode 100644 test/js/async_await_reject.t.js rename test/js/{async_await_stages.js => async_await_stages.t.js} (66%) rename test/js/{async_await_throw.js => async_await_throw.t.js} (56%) rename test/js/{async_await_throw_catch_async.js => async_await_throw_async.t.js} (57%) rename test/js/{async_await_throw_catch.js => async_await_throw_catch.t.js} (64%) rename test/js/{async_await_throw_async.js => async_await_throw_catch_async.t.js} (57%) delete mode 100644 test/js/async_await_try_catch.js create mode 100644 test/js/async_await_try_catch.t.js rename test/js/{async_await_try_finally.js => async_await_try_finally.t.js} (57%) rename test/js/{async_await_try_resolve.js => async_await_try_resolve.t.js} (61%) delete mode 100644 test/js/async_await_try_throw.js create mode 100644 test/js/async_await_try_throw.t.js delete mode 100644 test/js/async_await_try_throw_catch.js create mode 100644 test/js/async_await_try_throw_catch.t.js delete mode 100644 test/js/fs_promises_001.js delete mode 100644 test/js/promise_all.js create mode 100644 test/js/promise_all.t.js rename test/js/{promise_allSettled.js => promise_allSettled.t.js} (81%) rename test/js/{promise_allSettled_string.js => promise_allSettled_string.t.js} (64%) rename test/js/{promise_all_throw.js => promise_all_throw.t.js} (65%) rename test/js/{promise_any.js => promise_any.t.js} (59%) delete mode 100644 test/js/promise_any_all_rejected.js create mode 100644 test/js/promise_any_all_rejected.t.js delete mode 100644 test/js/promise_catch_then_throw_catch.js create mode 100644 test/js/promise_catch_then_throw_catch.t.js delete mode 100644 test/js/promise_catch_throw.js create mode 100644 test/js/promise_catch_throw.t.js delete mode 100644 test/js/promise_finally.js create mode 100644 test/js/promise_finally.t.js delete mode 100644 test/js/promise_finally_throw.js create mode 100644 test/js/promise_finally_throw.t.js delete mode 100644 test/js/promise_finally_throw_catch.js create mode 100644 test/js/promise_finally_throw_catch.t.js rename test/js/{promise_race.js => promise_race.t.js} (60%) rename test/js/{promise_race_throw.js => promise_race_throw.t.js} (58%) delete mode 100644 test/js/promise_reject_catch.js create mode 100644 test/js/promise_reject_catch.t.js delete mode 100644 test/js/promise_reject_post_catch.js create mode 100644 test/js/promise_reject_post_catch.t.js delete mode 100644 test/js/promise_rejection_tracker.js create mode 100644 test/js/promise_rejection_tracker.t.js create mode 100644 test/js/promise_s01.t.js create mode 100644 test/js/promise_s02.t.js create mode 100644 test/js/promise_s03.t.js create mode 100644 test/js/promise_s04.t.js create mode 100644 test/js/promise_s05.t.js create mode 100644 test/js/promise_s06.t.js create mode 100644 test/js/promise_s07.t.js create mode 100644 test/js/promise_s08.t.js create mode 100644 test/js/promise_s09.t.js delete mode 100644 test/js/promise_s1.js delete mode 100644 test/js/promise_s10.js create mode 100644 test/js/promise_s10.t.js delete mode 100644 test/js/promise_s11.js create mode 100644 test/js/promise_s11.t.js delete mode 100644 test/js/promise_s12.js create mode 100644 test/js/promise_s12.t.js delete mode 100644 test/js/promise_s13.js create mode 100644 test/js/promise_s13.t.js delete mode 100644 test/js/promise_s14.js create mode 100644 test/js/promise_s14.t.js delete mode 100644 test/js/promise_s15.js create mode 100644 test/js/promise_s15.t.js delete mode 100644 test/js/promise_s16.js create mode 100644 test/js/promise_s16.t.js delete mode 100644 test/js/promise_s17.js create mode 100644 test/js/promise_s17.t.js rename test/js/{promise_s18.js => promise_s18.t.js} (50%) delete mode 100644 test/js/promise_s19.js create mode 100644 test/js/promise_s19.t.js delete mode 100644 test/js/promise_s2.js delete mode 100644 test/js/promise_s20.js create mode 100644 test/js/promise_s20.t.js rename test/js/{promise_s21.js => promise_s21.t.js} (51%) delete mode 100644 test/js/promise_s22.js create mode 100644 test/js/promise_s22.t.js delete mode 100644 test/js/promise_s23.js create mode 100644 test/js/promise_s23.t.js rename test/js/{promise_s24.js => promise_s24.t.js} (65%) delete mode 100644 test/js/promise_s25.js create mode 100644 test/js/promise_s25.t.js delete mode 100644 test/js/promise_s26.js create mode 100644 test/js/promise_s26.t.js delete mode 100644 test/js/promise_s3.js delete mode 100644 test/js/promise_s4.js delete mode 100644 test/js/promise_s5.js delete mode 100644 test/js/promise_s6.js delete mode 100644 test/js/promise_s7.js delete mode 100644 test/js/promise_s8.js delete mode 100644 test/js/promise_s9.js rename test/js/{promise_set_timeout.js => promise_set_timeout.t.js} (63%) delete mode 100644 test/js/promise_then_throw.js create mode 100644 test/js/promise_then_throw.t.js delete mode 100644 test/js/promise_then_throw_catch.js create mode 100644 test/js/promise_then_throw_catch.t.js delete mode 100644 test/js/promise_then_throw_finally_catch.js create mode 100644 test/js/promise_then_throw_finally_catch.t.js rename test/js/{promise_two_first_then_throw.js => promise_two_first_then_throw.t.js} (65%) delete mode 100644 test/js/promise_two_then_throw.js create mode 100644 test/js/promise_two_then_throw.t.js create mode 100644 test/options create mode 100644 test/prepare create mode 100644 test/report create mode 100644 test/setup create mode 100755 test/test262 rename test/webcrypto/{aes.js => aes.t.js} (77%) rename test/webcrypto/{aes_decoding.js => aes_decoding.t.js} (69%) rename test/webcrypto/{derive.js => derive.t.js} (70%) rename test/webcrypto/{digest.js => digest.t.js} (69%) rename test/webcrypto/{rsa.js => rsa.t.js} (61%) delete mode 100644 test/webcrypto/rsa_decoding.js create mode 100644 test/webcrypto/rsa_decoding.t.js rename test/webcrypto/{sign.js => sign.t.js} (81%) rename test/webcrypto/{verify.js => verify.t.js} (70%) diff --git a/auto/make b/auto/make index 9a807a8f..2aaafeac 100644 --- a/auto/make +++ b/auto/make @@ -209,12 +209,16 @@ lib_test: $NJS_BUILD_DIR/njs_auto_config.h \\ $NJS_BUILD_DIR/lvlhsh_unit_test $NJS_BUILD_DIR/unicode_unit_test +test262: njs + + test/test262 + unit_test: $NJS_BUILD_DIR/njs_auto_config.h \\ $NJS_BUILD_DIR/njs_unit_test $NJS_BUILD_DIR/njs_unit_test -test: expect_test unit_test +test: expect_test unit_test test262 benchmark: $NJS_BUILD_DIR/njs_auto_config.h \\ $NJS_BUILD_DIR/njs_benchmark diff --git a/test/finalize b/test/finalize new file mode 100644 index 00000000..59d8d094 --- /dev/null +++ b/test/finalize @@ -0,0 +1,11 @@ +#!/bin/sh + +# Copyright (C) Dmitry Volyntsev +# Copyright (C) NGINX, Inc. + +if [ -z "$NJS_TEST_VERBOSE" ]; then + verbose "Removing dir: $NJS_TEST_DIR\n" + verbose "\n" + + rm -fr $NJS_TEST_DIR +fi diff --git a/test/fs/methods.js b/test/fs/methods.t.js similarity index 76% rename from test/fs/methods.js rename to test/fs/methods.t.js index 2769bc74..64aa809b 100644 --- a/test/fs/methods.js +++ b/test/fs/methods.t.js @@ -1,41 +1,7 @@ -var fs = require('fs'); - -async function run(tlist) { - function validate(t, r, i) { - if (r.status == "fulfilled") { - return r.value === "SUCCESS"; - } - - if (r.status == "rejected" && t[i].exception) { - if (process.argv[2] === '--match-exception-text') { - /* is not compatible with node.js format */ - return r.reason.toString().startsWith(t[i].exception); - } - - return true; - } - - if (r.status == "rejected" && t[i].optional) { - return r.reason.toString().startsWith("Error: No such file or directory"); - } - - return false; - } - - for (let k = 0; k < tlist.length; k++) { - let ts = tlist[k]; - let results = await Promise.allSettled(ts.tests.map(t => ts.T(ts.prepare_args(t, ts.opts)))); - let r = results.map((r, i) => validate(ts.tests, r, i)); - - console.log(`${ts.name} ${r.every(v=>v == true) ? "SUCCESS" : "FAILED"}`); - - r.forEach((v, i) => { - if (!v) { - console.log(`FAILED ${i}: ${JSON.stringify(ts.tests[i])}\n with reason: ${results[i].reason}`); - } - }) - } -} +/*--- +includes: [compatFs.js, compatBuffer.js, runTsuite.js] +flags: [async] +---*/ function p(args, default_opts) { let params = Object.assign({}, default_opts, args); @@ -73,41 +39,15 @@ async function method(name, params) { switch (params.type) { case "sync": - try { - data = fs[name + "Sync"].apply(null, params.args); - - } catch (e) { - if (!params.stringify) { - throw e; - } - - data = Buffer.from(JSON.stringify(e)); - } - + data = fs[name + "Sync"].apply(null, params.args); break; case "callback": - data = await promisify(fs[name]).apply(null, params.args) - .catch(e => { - if (!params.stringify) { - throw e; - } - - return Buffer.from(JSON.stringify(e)); - }); - + data = await promisify(fs[name]).apply(null, params.args); break; case "promise": - data = await fs.promises[name].apply(null, params.args) - .catch(e => { - if (!params.stringify) { - throw e; - } - - return Buffer.from(JSON.stringify(e)); - }); - + data = await fs.promises[name].apply(null, params.args); break; } @@ -115,37 +55,63 @@ async function method(name, params) { } async function read_test(params) { - let data = await method("readFile", params); + let data = await method("readFile", params).catch(e => ({error:e})); - if (params.slice) { + if (params.slice && !data.error) { data = data.slice.apply(data, params.slice); } - let success = true; - if (data instanceof Buffer) { - if (data.compare(params.expected) != 0) { - success = false; + if (params.check) { + if (!params.check(data, params)) { + throw Error(`readFile failed check`); } - } else if (data != params.expected) { - success = false; - } + } else if (params.exception) { + throw data.error; + + } else { + let success = true; + if (data instanceof Buffer) { + if (data.compare(params.expected) != 0) { + success = false; + } + + } else if (data != params.expected) { + success = false; + } - if (!success) { - throw Error(`readFile unexpected data`); + if (!success) { + throw Error(`readFile unexpected data`); + } } return 'SUCCESS'; } -let read_tests = [ +let read_tests = () => [ { args: ["test/fs/utf8"], expected: Buffer.from("αβZγ") }, { args: [Buffer.from("@test/fs/utf8").slice(1)], expected: Buffer.from("αβZγ") }, { args: ["test/fs/utf8", "utf8"], expected: "αβZγ" }, { args: ["test/fs/utf8", {encoding: "utf8", flags:"r+"}], expected: "αβZγ" }, - { args: ["test/fs/nonexistent"], stringify: true, - expected: Buffer.from('{"errno":2,"code":"ENOENT","path":"test/fs/nonexistent","syscall":"open"}'), - exception: "Error: No such file or directory" }, + { args: ["test/fs/nonexistent"], + check: (err, params) => { + let e = err.error; + + if (e.syscall != 'open') { + throw Error(`${e.syscall} unexpected syscall`); + } + + if (e.code != "ENOENT") { + throw Error(`${e.code} unexpected code`); + } + + if (e.path != "test/fs/nonexistent") { + throw Error(`${e.path} unexpected path`); + } + + return true; + } }, + { args: ["test/fs/non_utf8", "utf8"], expected: "��" }, { args: ["test/fs/non_utf8", {encoding: "hex"}], expected: "8080" }, { args: ["test/fs/non_utf8", "base64"], expected: "gIA=" }, @@ -155,32 +121,61 @@ let read_tests = [ { args: [Buffer.from([0x80, 0x80])], exception: "Error: No such file or directory" }, { args: ['x'.repeat(8192)], exception: "TypeError: \"path\" is too long" }, - { args: ["/proc/version"], slice:[0,5], expected: Buffer.from("Linux"), optional: true }, - { args: ["/proc/cpuinfo"], slice:[0,9], expected: Buffer.from("processor"), optional: true }, + { args: ["/proc/version"], slice:[0,5], expected: Buffer.from("Linux"), + check: (data, params) => { + + if (data.error) { + let e = data.error; + if (e.syscall != 'open') { + throw Error(`${e.syscall} unexpected syscall`); + } + + return true; + } + + return data.compare(params.expected) == 0; + } }, + { args: ["/proc/cpuinfo"], slice:[0,9], expected: Buffer.from("processor"), + check: (data, params) => { + + if (data.error) { + let e = data.error; + if (e.syscall != 'open') { + throw Error(`${e.syscall} unexpected syscall`); + } + + return true; + } + + return data.compare(params.expected) == 0; + } }, ]; let readFile_tsuite = { name: "fs readFile", + skip: () => (!has_fs() || !has_buffer()), T: read_test, prepare_args: p, opts: { type: "callback" }, - tests: read_tests, + get tests() { return read_tests() }, }; let readFileSync_tsuite = { name: "fs readFileSync", + skip: () => (!has_fs() || !has_buffer()), T: read_test, prepare_args: p, opts: { type: "sync" }, - tests: read_tests, + get tests() { return read_tests() }, }; let readFileP_tsuite = { name: "fsp readFile", + skip: () => (!has_fs() || !has_buffer()), T: read_test, prepare_args: p, opts: { type: "promise" }, - tests: read_tests, + get tests() { return read_tests() }, }; async function write_test(params) { @@ -213,7 +208,7 @@ async function write_test(params) { return 'SUCCESS'; } -let write_tests = [ +let write_tests = () => [ { args: ["@", Buffer.from(Buffer.alloc(4).fill(65).buffer, 1)], expected: Buffer.from("AAA") }, { args: ["@", Buffer.from("XYZ"), "utf8"], expected: Buffer.from("XYZ") }, @@ -247,26 +242,29 @@ let write_tests = [ let writeFile_tsuite = { name: "fs writeFile", + skip: () => (!has_fs() || !has_buffer()), T: write_test, prepare_args: p, opts: { type: "callback" }, - tests: write_tests, + get tests() { return write_tests() }, }; let writeFileSync_tsuite = { name: "fs writeFileSync", + skip: () => (!has_fs() || !has_buffer()), T: write_test, prepare_args: p, opts: { type: "sync" }, - tests: write_tests, + get tests() { return write_tests() }, }; let writeFileP_tsuite = { name: "fsp writeFile", + skip: () => (!has_fs() || !has_buffer()), T: write_test, prepare_args: p, opts: { type: "promise" }, - tests: write_tests, + get tests() { return write_tests() }, }; async function append_test(params) { @@ -300,7 +298,7 @@ async function append_test(params) { return 'SUCCESS'; } -let append_tests = [ +let append_tests = () => [ { args: ["@", Buffer.from(Buffer.alloc(4).fill(65).buffer, 1)], expected: Buffer.from("AAAAAA") }, { args: ["@", Buffer.from("XYZ"), "utf8"], expected: Buffer.from("XYZXYZ") }, @@ -334,26 +332,29 @@ let append_tests = [ let appendFile_tsuite = { name: "fs appendFile", + skip: () => (!has_fs() || !has_buffer()), T: append_test, prepare_args: p, opts: { type: "callback" }, - tests: append_tests, + get tests() { return append_tests() }, }; let appendFileSync_tsuite = { name: "fs appendFileSync", + skip: () => (!has_fs() || !has_buffer()), T: append_test, prepare_args: p, opts: { type: "sync" }, - tests: append_tests, + get tests() { return append_tests() }, }; let appendFileP_tsuite = { name: "fsp appendFile", + skip: () => (!has_fs() || !has_buffer()), T: append_test, prepare_args: p, opts: { type: "promise" }, - tests: append_tests, + get tests() { return append_tests() }, }; async function realpath_test(params) { @@ -366,35 +367,38 @@ async function realpath_test(params) { return 'SUCCESS'; } -let realpath_tests = [ - { args: ["./build/test/.."], +let realpath_tests = () => [ + { args: ["build/test/.."], check: (data) => data.endsWith("build") }, - { args: ["./build/test/", {encoding:'buffer'}], + { args: ["build/test/", {encoding:'buffer'}], check: (data) => data instanceof Buffer }, ]; let realpath_tsuite = { name: "fs realpath", + skip: () => (!has_fs() || !has_buffer()), T: realpath_test, prepare_args: p, opts: { type: "callback" }, - tests: realpath_tests, + get tests() { return realpath_tests() }, }; let realpathSync_tsuite = { name: "fs realpathSync", + skip: () => (!has_fs() || !has_buffer()), T: realpath_test, prepare_args: p, opts: { type: "sync" }, - tests: realpath_tests, + get tests() { return realpath_tests() }, }; let realpathP_tsuite = { name: "fsp realpath", + skip: () => (!has_fs() || !has_buffer()), T: realpath_test, prepare_args: p, opts: { type: "promise" }, - tests: realpath_tests, + get tests() { return realpath_tests() }, }; async function stat_test(params) { @@ -423,7 +427,7 @@ function contains(arr, elts) { }); } -let stat_tests = [ +let stat_tests = () => [ { args: ["/invalid_path"], check: (err, params) => { let e = err.error; @@ -474,14 +478,14 @@ let stat_tests = [ return true; } }, - { args: ["./build/"], + { args: ["build/"], check: (st) => contains(Object.keys(st), [ "atime", "atimeMs", "birthtime", "birthtimeMs", "blksize", "blocks", "ctime", "ctimeMs", "dev", "gid", "ino", "mode", "mtime", "mtimeMs","nlink", "rdev", "size", "uid" ]) }, - { args: ["./build/"], + { args: ["build/"], check: (st) => Object.keys(st).every(p => { let v = st[p]; if (p == 'atime' || p == 'ctime' || p == 'mtime' || p == 'birthtime') { @@ -499,7 +503,7 @@ let stat_tests = [ return true; }) }, - { args: ["./build/"], + { args: ["build/"], check: (st) => ['atime', 'birthtime', 'ctime', 'mtime'].every(p => { let date = st[p].valueOf(); let num = st[p + 'Ms']; @@ -511,7 +515,7 @@ let stat_tests = [ return true; }) }, - { args: ["./build/"], + { args: ["build/"], check: (st) => ['isBlockDevice', 'isCharacterDevice', 'isDirectory', @@ -531,50 +535,56 @@ let stat_tests = [ let stat_tsuite = { name: "fs stat", + skip: () => (!has_fs() || !has_buffer()), T: stat_test, prepare_args: p, opts: { type: "callback", method: "stat" }, - tests: stat_tests, + get tests() { return stat_tests() }, }; let statSync_tsuite = { name: "fs statSync", + skip: () => (!has_fs() || !has_buffer()), T: stat_test, prepare_args: p, opts: { type: "sync", method: "stat" }, - tests: stat_tests, + get tests() { return stat_tests() }, }; let statP_tsuite = { name: "fsp stat", + skip: () => (!has_fs() || !has_buffer()), T: stat_test, prepare_args: p, opts: { type: "promise", method: "stat" }, - tests: stat_tests, + get tests() { return stat_tests() }, }; let lstat_tsuite = { name: "fs lstat", + skip: () => (!has_fs() || !has_buffer()), T: stat_test, prepare_args: p, opts: { type: "callback", method: "lstat" }, - tests: stat_tests, + get tests() { return stat_tests() }, }; let lstatSync_tsuite = { name: "fs lstatSync", + skip: () => (!has_fs() || !has_buffer()), T: stat_test, prepare_args: p, opts: { type: "sync", method: "lstat" }, - tests: stat_tests, + get tests() { return stat_tests() }, }; let lstatP_tsuite = { name: "fsp lstat", + skip: () => (!has_fs() || !has_buffer()), T: stat_test, prepare_args: p, opts: { type: "promise", method: "lstat" }, - tests: stat_tests, + get tests() { return stat_tests() }, }; run([ @@ -596,4 +606,5 @@ run([ lstat_tsuite, lstatSync_tsuite, lstatP_tsuite, -]); +]) +.then($DONE, $DONE); diff --git a/test/fs/promises_01.t.js b/test/fs/promises_01.t.js new file mode 100644 index 00000000..22193153 --- /dev/null +++ b/test/fs/promises_01.t.js @@ -0,0 +1,42 @@ +/*--- +includes: [compareArray.js, compatFs.js] +flags: [async] +---*/ + +var fname = 'build/test/fs_promises_01'; + +let stages = []; + +Promise.resolve() +.then(() => { + return fsp.writeFile(fname, fname); +}) +.then(data => { + stages.push('init'); + assert.sameValue(data, undefined, 'init'); +}) +.then(() => { + return fsp.readFile(fname).then(fsp.readFile); +}) +.then(data => { + stages.push('short circut'); + assert.sameValue(data.toString(), fname, 'short circut'); +}) +.then(() => { + var read = fsp.readFile.bind(fsp, fname, 'utf8'); + var write = fsp.writeFile.bind(fsp, fname); + var append = fsp.appendFile.bind(fsp, fname); + + return write(fname).then(read).then(append).then(read); +}) +.then(data => { + stages.push('chain'); + assert.sameValue(data, fname + fname, 'chain'); +}) +.then(() => { + stages.push('errors ok'); +}) +.then(() => { + assert.compareArray(stages, ["init", "short circut", "chain", "errors ok"]); +}) +.then($DONE, $DONE); diff --git a/test/js/fs_promises_002.js b/test/fs/promises_02.t.js similarity index 63% rename from test/js/fs_promises_002.js rename to test/fs/promises_02.t.js index 8345ca40..a07f7412 100644 --- a/test/js/fs_promises_002.js +++ b/test/fs/promises_02.t.js @@ -1,6 +1,9 @@ -var fs = require('fs'); -var fsp = fs.promises; -var fname = './build/test/fs_promises_002'; +/*--- +includes: [compareArray.js, compatFs.js] +flags: [async] +---*/ + +var fname = 'build/test/fs_promises_02'; var testSync = new Promise((resolve, reject) => { var failed = false; @@ -16,7 +19,7 @@ var testSync = new Promise((resolve, reject) => { } catch(e) { failed = (e.syscall != 'access') || e.code != 'ENOENT'; } - resolve(failed); + resolve(Boolean(failed)); } catch (e) { reject(e); } @@ -34,26 +37,24 @@ var testCallback = new Promise((resolve, reject) => { fs.access(fname + '___', (err) => { failed |= ((err === undefined) || (err.syscall != 'access') || err.code != 'ENOENT'); - resolve(failed); + resolve(Boolean(failed)); }); }); }); }); +let stages = []; + Promise.resolve() .then(() => testSync) -.then((failed) => { - console.log('testSync ok', !failed); -}) -.catch((e) => { - console.log('testSync failed', e); +.then(failed => { + stages.push('testSync'); + assert.sameValue(failed, false, 'testSync'); }) .then(() => testCallback) -.then((failed) => { - console.log('testCallback ok', !failed); -}) -.catch((e) => { - console.log('testCallback failed', e); +.then(failed => { + stages.push('testCallback'); + assert.sameValue(failed, false, 'testCallback'); }) .then(() => { fs.writeFileSync(fname, fname); @@ -63,10 +64,15 @@ Promise.resolve() .then(() => fsp.access(fname + '___')); }) .then(() => { - console.log('testPromise failed'); + $DONOTEVALUATE(); +}) +.catch(e => { + stages.push('testPromise'); + assert.sameValue(e.syscall, 'access', 'testPromise'); + assert.sameValue(e.path, fname + '___', 'testPromise'); + assert.sameValue(e.code, 'ENOENT', 'testPromise'); }) -.catch((e) => { - console.log('testPromise ok', (e.syscall == 'access') && (e.path == fname + '___') - && e.code == 'ENOENT'); +.then(() => { + assert.compareArray(stages, ["testSync", "testCallback", "testPromise"]); }) -; +.then($DONE, $DONE); diff --git a/test/js/fs_promises_003.js b/test/fs/promises_03.t.js similarity index 84% rename from test/js/fs_promises_003.js rename to test/fs/promises_03.t.js index 671a97e9..1c7d94c8 100644 --- a/test/js/fs_promises_003.js +++ b/test/fs/promises_03.t.js @@ -1,7 +1,9 @@ -var fs = require('fs'); -var fsp = fs.promises; -var fname = './build/test/fs_promises_003'; +/*--- +includes: [compareArray.js, compatFs.js] +flags: [async] +---*/ +var fname = 'build/test/fs_promises_03'; var testSync = () => new Promise((resolve, reject) => { try { @@ -68,22 +70,17 @@ var testCallback = () => new Promise((resolve, reject) => { }); }); +let stages = []; Promise.resolve() .then(testSync) .then(() => { - console.log('test fs.unlinkSync'); -}) -.catch((e) => { - console.log('test fs.unlinkSync failed', e); + stages.push("unlinkSync"); }) .then(testCallback) .then(() => { - console.log('test fs.unlink'); -}) -.catch((e) => { - console.log('test fs.unlink failed', e); + stages.push("unlink"); }) .then(() => fsp.unlink(fname) @@ -101,8 +98,7 @@ Promise.resolve() .catch((e) => { if (e.syscall != 'access') { throw e; } }) .then(() => { - console.log('test fsp.unlink'); + stages.push("fsp.unlink"); }) -.catch((e) => { - console.log('test fsp.unlink failed', e); -}); +.then(() => assert.compareArray(stages, ['unlinkSync', 'unlink', 'fsp.unlink'])) +.then($DONE, $DONE); diff --git a/test/js/fs_promises_004.js b/test/fs/promises_04.t.js similarity index 87% rename from test/js/fs_promises_004.js rename to test/fs/promises_04.t.js index 873e787c..d6e61ae2 100644 --- a/test/js/fs_promises_004.js +++ b/test/fs/promises_04.t.js @@ -1,10 +1,12 @@ -var fs = require('fs'); -var fsp = fs.promises; -var dname = './build/test/'; -var fname = dname + 'fs_promises_004'; -var fname_utf8 = dname + 'fs_promises_αβγ_004'; -var lname = dname + 'fs_promises_004_lnk'; +/*--- +includes: [compareArray.js, compatFs.js] +flags: [async] +---*/ +var dname = 'build/test/'; +var fname = dname + 'fs_promises_04'; +var fname_utf8 = dname + 'fs_promises_αβγ_04'; +var lname = dname + 'fs_promises_04_lnk'; var testSync = () => new Promise((resolve, reject) => { try { @@ -44,7 +46,7 @@ var testSync = () => new Promise((resolve, reject) => { } var rname_utf8 = fs.realpathSync(fname_utf8); - if (rname_utf8.slice(-7,-4) != 'αβγ') { + if (rname_utf8.slice(-6,-3) != 'αβγ') { throw new Error('fs.realpathSync error 2'); } @@ -140,22 +142,17 @@ var testCallback = () => new Promise((resolve, reject) => { } }); +let stages = []; Promise.resolve() .then(testSync) .then(() => { - console.log('test fs.symlinkSync'); -}) -.catch((e) => { - console.log('test fs.symlinkSync failed', e); + stages.push("symlinkSync"); }) .then(testCallback) .then(() => { - console.log('test fs.symlink'); -}) -.catch((e) => { - console.log('test fs.symlink failed', e); + stages.push("symlink"); }) .then(() => fsp.unlink(fname) @@ -179,7 +176,7 @@ Promise.resolve() .then((rname) => fsp.realpath(lname) .then((xname) => { if (rname != xname) { - throw new Error('fsp.symlink error 2'); + throw new Error(`fsp.symlink error 2`); } })) .then(() => { @@ -193,8 +190,7 @@ Promise.resolve() }) .then(() => { - console.log('test fsp.symlink'); + stages.push("fsp.symlink"); }) -.catch((e) => { - console.log('test fsp.symlink failed', e); -}); +.then(() => assert.compareArray(stages, ['symlinkSync', 'symlink', 'fsp.symlink'])) +.then($DONE, $DONE); diff --git a/test/js/fs_promises_005.js b/test/fs/promises_05.t.js similarity index 83% rename from test/js/fs_promises_005.js rename to test/fs/promises_05.t.js index 544e2047..f957d776 100644 --- a/test/js/fs_promises_005.js +++ b/test/fs/promises_05.t.js @@ -1,10 +1,12 @@ -var fs = require('fs'); -var fsp = fs.promises; -var rname = './build/test/'; -var dname = rname + 'fs_promises_005'; -var dname_utf8 = rname + 'fs_promises_αβγ_005'; -var fname = (d) => d + '/fs_promises_005_file'; +/*--- +includes: [compareArray.js, compatFs.js] +flags: [async] +---*/ +var rname = 'build/test/'; +var dname = rname + 'fs_promises_05'; +var dname_utf8 = rname + 'fs_promises_αβγ_05'; +var fname = (d) => d + '/fs_promises_05_file'; var testSync = () => new Promise((resolve, reject) => { try { @@ -104,21 +106,18 @@ var testCallback = () => new Promise((resolve, reject) => { }); +let stages = []; + Promise.resolve() .then(testSync) .then(() => { - console.log('test fs.mkdirSync'); -}) -.catch((e) => { - console.log('test fs.mkdirSync failed', JSON.stringify(e)); + stages.push("mkdirSync"); }) + .then(testCallback) .then(() => { - console.log('test fs.mkdir'); -}) -.catch((e) => { - console.log('test fs.mkdir failed', JSON.stringify(e)); + stages.push("mkdir"); }) .then(() => { @@ -136,8 +135,7 @@ Promise.resolve() }) .then(() => fsp.rmdir(dname)) .then(() => { - console.log('test fsp.mkdir'); + stages.push("fsp.mkdir"); }) -.catch((e) => { - console.log('test fsp.mkdir failed', JSON.stringify(e)); -}); +.then(() => assert.compareArray(stages, ['mkdirSync', 'mkdir', 'fsp.mkdir'])) +.then($DONE, $DONE); diff --git a/test/js/fs_promises_006.js b/test/fs/promises_06.t.js similarity index 81% rename from test/js/fs_promises_006.js rename to test/fs/promises_06.t.js index a5794f92..9a5186c2 100644 --- a/test/js/fs_promises_006.js +++ b/test/fs/promises_06.t.js @@ -1,8 +1,11 @@ -var fs = require('fs'); -var fsp = fs.promises; -var dname = './build/test/'; -var fname = (d) => d + '/fs_promises_006_file'; -var fname_utf8 = (d) => d + '/fs_promises_αβγ_006'; +/*--- +includes: [compareArray.js, compatFs.js] +flags: [async] +---*/ + +var dname = 'build/test/'; +var fname = (d) => d + '/fs_promises_06_file'; +var fname_utf8 = (d) => d + '/fs_promises_αβγ_06'; var testSync = new Promise((resolve, reject) => { try { @@ -63,18 +66,17 @@ var testCallback = new Promise((resolve, reject) => { } }); +let stages = []; + Promise.resolve() .then(() => testSync) .then(() => { - console.log('test fs.renameSync'); -}) -.catch((e) => { - console.log('test fs.renameSync failed', JSON.stringify(e)); + stages.push("renameSync"); }) .then(testCallback) .then(() => { - console.log('test fs.rename'); + stages.push("rename"); }) .catch((e) => { console.log('test fs.rename failed', JSON.stringify(e)); @@ -97,8 +99,7 @@ Promise.resolve() } }) .then(() => { - console.log('test fsp.rename'); + stages.push("fsp.rename"); }) -.catch((e) => { - console.log('test fsp.rename failed', JSON.stringify(e)); -}); +.then(() => assert.compareArray(stages, ["renameSync", "rename", "fsp.rename"])) +.then($DONE, $DONE); diff --git a/test/js/fs_promises_007.js b/test/fs/promises_07.t.js similarity index 90% rename from test/js/fs_promises_007.js rename to test/fs/promises_07.t.js index e02796cb..e4fcb42c 100644 --- a/test/js/fs_promises_007.js +++ b/test/fs/promises_07.t.js @@ -1,10 +1,13 @@ -var fs = require('fs'); -var fsp = fs.promises; -var dname = './build/test/fs_promises_007'; -var dname_utf8 = './build/test/fs_promises_αβγ_007'; -var fname = (d) => d + '/fs_promises_007_file'; -var lname = (d) => d + '/fs_promises_007_link'; -var cname = (d) => d + '/fs_promises_αβγ_007_dir'; +/*--- +includes: [compareArray.js, compatFs.js] +flags: [async] +---*/ + +var dname = 'build/test/fs_promises_07'; +var dname_utf8 = 'build/test/fs_promises_αβγ_07'; +var fname = (d) => d + '/fs_promises_07_file'; +var lname = (d) => d + '/fs_promises_07_link'; +var cname = (d) => d + '/fs_promises_αβγ_07_dir'; var dir_test = [cname(''), lname(''), fname('')].map((x) => x.substring(1)); @@ -175,21 +178,17 @@ var testCallback = () => new Promise((resolve, reject) => { }); +let stages = []; + Promise.resolve() .then(testSync) .then(() => { - console.log('test fs.readdirSync'); -}) -.catch((e) => { - console.log('test fs.readdirSync failed', e, JSON.stringify(e)); + stages.push("readdirSync"); }) .then(testCallback) .then(() => { - console.log('test fs.readdir'); -}) -.catch((e) => { - console.log('test fs.readdir failed', e, JSON.stringify(e)); + stages.push("readdir"); }) .then(() => { @@ -234,8 +233,7 @@ Promise.resolve() } }) .then(() => { - console.log('test fsp.readdir'); + stages.push("fsp.readdir"); }) -.catch((e) => { - console.log('test fsp.readdir failed', e, JSON.stringify(e)); -}); +.then(() => assert.compareArray(stages, ["readdirSync", "readdir", "fsp.readdir"])) +.then($DONE, $DONE); diff --git a/test/js/fs_promises_008.js b/test/fs/promises_08.t.js similarity index 87% rename from test/js/fs_promises_008.js rename to test/fs/promises_08.t.js index 8e83c307..f0b393b7 100644 --- a/test/js/fs_promises_008.js +++ b/test/fs/promises_08.t.js @@ -1,6 +1,9 @@ -var fs = require('fs'); -var fsp = fs.promises; -var dname = './build/test/fs_promises_αβγ_008/'; +/*--- +includes: [compareArray.js, compatFs.js] +flags: [async] +---*/ + +var dname = 'build/test/fs_promises_αβγ_08/'; var path = 'one/two/three/αβγ'; var wipePath = (root, path, nofail) => { @@ -69,11 +72,15 @@ var testSync = () => new Promise((resolve, reject) => { } }); +let stages = []; + Promise.resolve() .then(testSync) .then(() => { - console.log('test recursive fs.mkdirSync'); + stages.push("mkdirSync"); }) .catch((e) => { - console.log('test failed recursive fs.mkdirSync', JSON.stringify(e)); + $DONOTEVALUATE(); }) +.then(() => assert.compareArray(stages, ["mkdirSync"])) +.then($DONE, $DONE); diff --git a/test/js/fs_promises_009.js b/test/fs/promises_09.t.js similarity index 88% rename from test/js/fs_promises_009.js rename to test/fs/promises_09.t.js index 90b6df99..7ca0b8c5 100644 --- a/test/js/fs_promises_009.js +++ b/test/fs/promises_09.t.js @@ -1,11 +1,13 @@ -var fs = require('fs'); -var fsp = fs.promises; -var root = './build/test/'; -var dname = 'fs_promises_αβγ_009/'; -var lname = 'fs_promises_αβγ_009_lnk'; +/*--- +includes: [compareArray.js, compatFs.js] +flags: [async] +---*/ + +var root = 'build/test/'; +var dname = 'fs_promises_αβγ_09/'; +var lname = 'fs_promises_αβγ_09_lnk'; var path = 'one/two/three/αβγ'; - var setContent = (root, path) => { fs.mkdirSync(root + path, { recursive: true }); path @@ -96,11 +98,12 @@ var testSync = () => new Promise((resolve, reject) => { }); +let stages = []; + Promise.resolve() .then(testSync) .then(() => { - console.log('test recursive fs.rmdirSync()'); + stages.push("rmdirSync"); }) -.catch((e) => { - console.log('test failed recursive fs.rmdirSync()', e.message, JSON.stringify(e)); -}); +.then(() => assert.compareArray(stages, ["rmdirSync"])) +.then($DONE, $DONE); diff --git a/test/harness/assert.js b/test/harness/assert.js new file mode 100644 index 00000000..34eed55e --- /dev/null +++ b/test/harness/assert.js @@ -0,0 +1,118 @@ +// Copyright (C) 2017 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Collection of assertion functions used throughout test262 +defines: [assert] +---*/ + + +function assert(mustBeTrue, message) { + if (mustBeTrue === true) { + return; + } + + if (message === undefined) { + message = 'Expected true but got ' + assert._toString(mustBeTrue); + } + throw new Test262Error(message); +} + +assert._isSameValue = function (a, b) { + if (a === b) { + // Handle +/-0 vs. -/+0 + return a !== 0 || 1 / a === 1 / b; + } + + // Handle NaN vs. NaN + return a !== a && b !== b; +}; + +assert.sameValue = function (actual, expected, message) { + try { + if (assert._isSameValue(actual, expected)) { + return; + } + } catch (error) { + throw new Test262Error(message + ' (_isSameValue operation threw) ' + error); + return; + } + + if (message === undefined) { + message = ''; + } else { + message += ' '; + } + + message += 'Expected SameValue(«' + assert._toString(actual) + '», «' + assert._toString(expected) + '») to be true'; + + throw new Test262Error(message); +}; + +assert.notSameValue = function (actual, unexpected, message) { + if (!assert._isSameValue(actual, unexpected)) { + return; + } + + if (message === undefined) { + message = ''; + } else { + message += ' '; + } + + message += 'Expected SameValue(«' + assert._toString(actual) + '», «' + assert._toString(unexpected) + '») to be false'; + + throw new Test262Error(message); +}; + +assert.throws = function (expectedErrorConstructor, func, message) { + var expectedName, actualName; + if (typeof func !== "function") { + throw new Test262Error('assert.throws requires two arguments: the error constructor ' + + 'and a function to run'); + return; + } + if (message === undefined) { + message = ''; + } else { + message += ' '; + } + + try { + func(); + } catch (thrown) { + if (typeof thrown !== 'object' || thrown === null) { + message += 'Thrown value was not an object!'; + throw new Test262Error(message); + } else if (thrown.constructor !== expectedErrorConstructor) { + expectedName = expectedErrorConstructor.name; + actualName = thrown.constructor.name; + if (expectedName === actualName) { + message += 'Expected a ' + expectedName + ' but got a different error constructor with the same name'; + } else { + message += 'Expected a ' + expectedName + ' but got a ' + actualName; + } + throw new Test262Error(message); + } + return; + } + + message += 'Expected a ' + expectedErrorConstructor.name + ' to be thrown but no exception was thrown at all'; + throw new Test262Error(message); +}; + +assert._toString = function (value) { + try { + if (value === 0 && 1 / value === -Infinity) { + return '-0'; + } + + return String(value); + } catch (err) { + if (err.name === 'TypeError') { + return Object.prototype.toString.call(value); + } + + throw err; + } +}; diff --git a/test/harness/compareArray.js b/test/harness/compareArray.js new file mode 100644 index 00000000..adf294b5 --- /dev/null +++ b/test/harness/compareArray.js @@ -0,0 +1,42 @@ +// Copyright (C) 2017 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Compare the contents of two arrays +defines: [compareArray] +---*/ + +function compareArray(a, b) { + if (b.length !== a.length) { + return false; + } + + for (var i = 0; i < a.length; i++) { + if (!compareArray.isSameValue(b[i], a[i])) { + return false; + } + } + return true; +} + +compareArray.isSameValue = function(a, b) { + if (a === 0 && b === 0) return 1 / a === 1 / b; + if (a !== a && b !== b) return true; + + return a === b; +}; + +compareArray.format = function(array) { + return `[${array.map(String).join(', ')}]`; +}; + +assert.compareArray = function(actual, expected, message) { + message = message === undefined ? '' : message; + assert(actual != null, `First argument shouldn't be nullish. ${message}`); + assert(expected != null, `Second argument shouldn't be nullish. ${message}`); + var format = compareArray.format; + assert( + compareArray(actual, expected), + `Expected ${format(actual)} and ${format(expected)} to have the same contents. ${message}` + ); +}; diff --git a/test/harness/compatBuffer.js b/test/harness/compatBuffer.js new file mode 100644 index 00000000..5b82aa3c --- /dev/null +++ b/test/harness/compatBuffer.js @@ -0,0 +1,3 @@ +function has_buffer() { + return (typeof Buffer === 'function') && Buffer.from; +} diff --git a/test/harness/compatFs.js b/test/harness/compatFs.js new file mode 100644 index 00000000..e4732c96 --- /dev/null +++ b/test/harness/compatFs.js @@ -0,0 +1,11 @@ +let fs = null; +let fsp = null; + +if (typeof require == 'function') { + fs = require('fs'); + fsp = fs.promises; +} + +function has_fs() { + return fs; +} diff --git a/test/harness/compatPrint.js b/test/harness/compatPrint.js new file mode 100644 index 00000000..db33030e --- /dev/null +++ b/test/harness/compatPrint.js @@ -0,0 +1,3 @@ +if (typeof print !== 'function') { + print = console.log; +} diff --git a/test/harness/compatWebcrypto.js b/test/harness/compatWebcrypto.js new file mode 100644 index 00000000..be757e17 --- /dev/null +++ b/test/harness/compatWebcrypto.js @@ -0,0 +1,8 @@ +if (typeof crypto == 'undefined' && typeof require == 'function') { + crypto = require('crypto').webcrypto; +} + +function has_webcrypto() { + return (typeof crypto != 'undefied') ? crypto : null; +} + diff --git a/test/harness/doneprintHandle.js b/test/harness/doneprintHandle.js new file mode 100644 index 00000000..e9681240 --- /dev/null +++ b/test/harness/doneprintHandle.js @@ -0,0 +1,22 @@ +// Copyright (C) 2017 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | +defines: [$DONE] +---*/ + +function __consolePrintHandle__(msg) { + print(msg); +} + +function $DONE(error) { + if (error) { + if(typeof error === 'object' && error !== null && 'name' in error) { + __consolePrintHandle__('Test262:AsyncTestFailure:' + error.name + ': ' + error.message); + } else { + __consolePrintHandle__('Test262:AsyncTestFailure:Test262Error: ' + error); + } + } else { + __consolePrintHandle__('Test262:AsyncTestComplete'); + } +} diff --git a/test/harness/runTsuite.js b/test/harness/runTsuite.js new file mode 100644 index 00000000..51b335ac --- /dev/null +++ b/test/harness/runTsuite.js @@ -0,0 +1,54 @@ +async function run(tlist) { + function validate(t, r, i) { + if (r.status == "fulfilled" && r.value === "SKIPPED") { + return true; + } + + if (r.status == "fulfilled" && !t[i].exception) { + return r.value === "SUCCESS"; + } + + if (r.status == "rejected" && t[i].exception) { + return true; + } + + if (r.status == "rejected" && t[i].optional) { + return r.reason.toString().startsWith("InternalError: not implemented"); + } + + return false; + } + + for (let k = 0; k < tlist.length; k++) { + let ts = tlist[k]; + + if (ts.skip && ts.skip()) { + continue; + } + + let results = await Promise.allSettled(ts.tests.map(t => ts.T(ts.prepare_args(t, ts.opts)))); + let r = results.map((r, i) => validate(ts.tests, r, i)); + + r.forEach((v, i) => { + assert.sameValue(v, true, `FAILED ${i}: ${JSON.stringify(ts.tests[i])}\n with reason: ${results[i].reason}`); + }) + } +} + +function merge(to, from) { + let r = Object.assign({}, to); + Object.keys(from).forEach(v => { + if (typeof r[v] == 'object' && typeof from[v] == 'object') { + r[v] = merge(r[v], from[v]); + + } else if (typeof from[v] == 'object') { + r[v] = Object.assign({}, from[v]); + + } else { + r[v] = from[v]; + } + }) + + return r; +} + diff --git a/test/harness/sta.js b/test/harness/sta.js new file mode 100644 index 00000000..b249ee45 --- /dev/null +++ b/test/harness/sta.js @@ -0,0 +1,27 @@ +// Copyright (c) 2012 Ecma International. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + Provides both: + + - An error class to avoid false positives when testing for thrown exceptions + - A function to explicitly throw an exception using the Test262Error class +defines: [Test262Error, $DONOTEVALUATE] +---*/ + + +function Test262Error(message) { + this.message = message || ""; +} + +Test262Error.prototype.toString = function () { + return "Test262Error: " + this.message; +}; + +Test262Error.thrower = (message) => { + throw new Test262Error(message); +}; + +function $DONOTEVALUATE() { + throw "Test262: This statement should not be evaluated."; +} diff --git a/test/harness/webCryptoUtils.js b/test/harness/webCryptoUtils.js new file mode 100644 index 00000000..243098ef --- /dev/null +++ b/test/harness/webCryptoUtils.js @@ -0,0 +1,13 @@ +function pem_to_der(pem, type) { + const pemJoined = pem.toString().split('\n').join(''); + const pemHeader = `-----BEGIN ${type} KEY-----`; + const pemFooter = `-----END ${type} KEY-----`; + const pemContents = pemJoined.substring(pemHeader.length, pemJoined.length - pemFooter.length); + return Buffer.from(pemContents, 'base64'); +} + +function base64decode(b64) { + const joined = b64.toString().split('\n').join(''); + return Buffer.from(joined, 'base64'); +} + diff --git a/test/js/async_await_add.js b/test/js/async_await_add.js deleted file mode 100644 index 62d46e7e..00000000 --- a/test/js/async_await_add.js +++ /dev/null @@ -1,7 +0,0 @@ -async function af(x) { - const y = await new Promise(resolve => {resolve(x + 10)}); - - return x + y; -} - -af(50).then(v => console.log(v)); diff --git a/test/js/async_await_add.t.js b/test/js/async_await_add.t.js new file mode 100644 index 00000000..5c7eef2c --- /dev/null +++ b/test/js/async_await_add.t.js @@ -0,0 +1,15 @@ +/*--- +includes: [] +flags: [async] +---*/ + +async function af(x) { + const y = await new Promise(resolve => {resolve(x + 10)}); + + return x + y; +} + +af(50).then(v => { + assert.sameValue(v, 110); +}) +.then($DONE, $DONE); diff --git a/test/js/async_await_blank.js b/test/js/async_await_blank.js deleted file mode 100644 index deaa8cfd..00000000 --- a/test/js/async_await_blank.js +++ /dev/null @@ -1,5 +0,0 @@ -async function af(x) { - return x; -} - -af(12345).then(v => console.log(v)); diff --git a/test/js/async_await_blank.t.js b/test/js/async_await_blank.t.js new file mode 100644 index 00000000..9399f56f --- /dev/null +++ b/test/js/async_await_blank.t.js @@ -0,0 +1,13 @@ +/*--- +includes: [] +flags: [async] +---*/ + +async function af(x) { + return x; +} + +af(12345).then(v => { + assert.sameValue(v, 12345) +}) +.then($DONE, $DONE); diff --git a/test/js/async_await_catch.js b/test/js/async_await_catch.js deleted file mode 100644 index c47a512b..00000000 --- a/test/js/async_await_catch.js +++ /dev/null @@ -1,5 +0,0 @@ -async function add(x) { - return await new Promise((resolve, reject) => {reject(x)}).catch(v => v + 1); -} - -add(50).then(v => {console.log(v)}); diff --git a/test/js/async_await_catch.t.js b/test/js/async_await_catch.t.js new file mode 100644 index 00000000..db85b16e --- /dev/null +++ b/test/js/async_await_catch.t.js @@ -0,0 +1,13 @@ +/*--- +includes: [] +flags: [async] +---*/ + +async function add(x) { + return await new Promise((resolve, reject) => {reject(x)}).catch(v => v + 1); +} + +add(50).then(v => { + assert.sameValue(v, 51); +}) +.then($DONE, $DONE); diff --git a/test/js/async_await_finally.js b/test/js/async_await_finally.js deleted file mode 100644 index 5c2ae73c..00000000 --- a/test/js/async_await_finally.js +++ /dev/null @@ -1,6 +0,0 @@ -async function add(x) { - return await new Promise((resolve, reject) => {reject(x)}) - .finally(() => console.log(x + 1)); -} - -add(50).then(v => {console.log(v)}); diff --git a/test/js/async_await_finally.t.js b/test/js/async_await_finally.t.js new file mode 100644 index 00000000..999c66d7 --- /dev/null +++ b/test/js/async_await_finally.t.js @@ -0,0 +1,15 @@ +/*--- +includes: [] +flags: [async] +---*/ + +let called = false; +async function add(x) { + return await new Promise((resolve, reject) => {reject(x + 1)}) + .finally(() => {called = true}); +} + +add(50).catch(e => { + assert.sameValue(e, 51); + assert.sameValue(called, true, "finally was not invoked"); +}).then($DONE, $DONE); diff --git a/test/js/async_await_for.js b/test/js/async_await_for.t.js similarity index 57% rename from test/js/async_await_for.js rename to test/js/async_await_for.t.js index 1256a068..24cea598 100644 --- a/test/js/async_await_for.js +++ b/test/js/async_await_for.t.js @@ -1,3 +1,8 @@ +/*--- +includes: [compareArray.js] +flags: [async] +---*/ + let stage = []; async function f() { @@ -18,6 +23,9 @@ async function f() { stage.push(1); -f().then(v => {console.log(v, stage.join(", "))}) +f().then(v => { + assert.sameValue(v, 85); + assert.compareArray(stage, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, "end"]); +}).then($DONE, $DONE); stage.push(3); diff --git a/test/js/async_await_inline.js b/test/js/async_await_inline.t.js similarity index 52% rename from test/js/async_await_inline.js rename to test/js/async_await_inline.t.js index 2901738b..a20b7710 100644 --- a/test/js/async_await_inline.js +++ b/test/js/async_await_inline.t.js @@ -1,11 +1,18 @@ +/*--- +includes: [] +flags: [async] +---*/ + function pr(x) { return new Promise(resolve => {resolve(x)}); } -async function add(x) { +async function add() { const a = pr(20); const b = pr(50); return await a + await b; } -add(50).then(v => {console.log(v)}); +add().then(v => { + assert.sameValue(v, 70); +}).then($DONE, $DONE); diff --git a/test/js/async_await_many_call.js b/test/js/async_await_many_call.t.js similarity index 78% rename from test/js/async_await_many_call.js rename to test/js/async_await_many_call.t.js index 52f24ac7..43cfee55 100644 --- a/test/js/async_await_many_call.js +++ b/test/js/async_await_many_call.t.js @@ -1,3 +1,8 @@ +/*--- +includes: [compareArray.js] +flags: [async] +---*/ + async function test(name) { let k1, k2; @@ -26,5 +31,5 @@ async function test(name) { Promise.all(['First', 'Second', 'Third'].map(v => test(v))) .then(results => { - console.log(results) -}) + assert.compareArray(results, ['First: SUN MOON','Second: CAT MOUSE','Third: MAN WOMAN']); +}).then($DONE, $DONE); diff --git a/test/js/async_await_reject.js b/test/js/async_await_reject.js deleted file mode 100644 index eeaec34d..00000000 --- a/test/js/async_await_reject.js +++ /dev/null @@ -1,5 +0,0 @@ -async function add(x) { - return await new Promise((resolve, reject) => {reject(x)}); -} - -add(50).then(v => {console.log(v)}); diff --git a/test/js/async_await_reject.t.js b/test/js/async_await_reject.t.js new file mode 100644 index 00000000..f2faf9fe --- /dev/null +++ b/test/js/async_await_reject.t.js @@ -0,0 +1,15 @@ +/*--- +includes: [] +flags: [async] +---*/ + +async function add(x) { + return await new Promise((resolve, reject) => {reject(x)}); +} + +add(50) +.then(v => $DONOTEVALUATE()) +.catch(v => { + assert.sameValue(v, 50); +}) +.then($DONE, $DONE); diff --git a/test/js/async_await_stages.js b/test/js/async_await_stages.t.js similarity index 66% rename from test/js/async_await_stages.js rename to test/js/async_await_stages.t.js index e3ff18e4..164c1e45 100644 --- a/test/js/async_await_stages.js +++ b/test/js/async_await_stages.t.js @@ -1,3 +1,8 @@ +/*--- +includes: [compareArray.js] +flags: [async] +---*/ + function pr(x) { return new Promise(resolve => {resolve(x)}) .then(v => v).then(v => v); @@ -23,6 +28,9 @@ async function f() { stage.push(1); -f().then(v => {console.log(v, stage.join(", "))}) +f().then(v => { + stage.push(v); + assert.compareArray(stage, [1, 2, 3, 4, 5, 30]); +}).then($DONE, $DONE); stage.push(3); diff --git a/test/js/async_await_throw.js b/test/js/async_await_throw.t.js similarity index 56% rename from test/js/async_await_throw.js rename to test/js/async_await_throw.t.js index 8923e5d4..b872080c 100644 --- a/test/js/async_await_throw.js +++ b/test/js/async_await_throw.t.js @@ -1,3 +1,8 @@ +/*--- +includes: [] +flags: [async] +---*/ + function pr(x) { return new Promise(resolve => {resolve(x)}).then(v => {throw v}); } @@ -9,4 +14,9 @@ async function add(x) { return a + b; } -add(50).then(v => {console.log(v)}); +add(50) +.then(v => $DONOTEVALUATE()) +.catch(v => { + assert.sameValue(v, 50); +}) +.then($DONE, $DONE); diff --git a/test/js/async_await_throw_catch_async.js b/test/js/async_await_throw_async.t.js similarity index 57% rename from test/js/async_await_throw_catch_async.js rename to test/js/async_await_throw_async.t.js index e7c51031..e59d68f6 100644 --- a/test/js/async_await_throw_catch_async.js +++ b/test/js/async_await_throw_async.t.js @@ -1,3 +1,8 @@ +/*--- +includes: [] +flags: [async] +---*/ + function pr(x) { return new Promise(resolve => {resolve(x)}); } @@ -12,4 +17,9 @@ async function add(x) { return a + b; } -add(50).then(v => {console.log(v - 1)}).catch(v => console.log(v)); +add(50) +.then(v => $DONOTEVALUATE()) +.catch(v => { + assert.sameValue(v, 51); +}) +.then($DONE, $DONE); diff --git a/test/js/async_await_throw_catch.js b/test/js/async_await_throw_catch.t.js similarity index 64% rename from test/js/async_await_throw_catch.js rename to test/js/async_await_throw_catch.t.js index 5e9025f3..cafcab4c 100644 --- a/test/js/async_await_throw_catch.js +++ b/test/js/async_await_throw_catch.t.js @@ -1,3 +1,8 @@ +/*--- +includes: [] +flags: [async] +---*/ + function pr(x) { return new Promise(resolve => {resolve(x)}).then(v => {throw v}).catch(v => v); } @@ -9,4 +14,7 @@ async function add(x) { return a + b; } -add(50).then(v => {console.log(v)}); +add(50).then(v => { + assert.sameValue(v, 110); +}) +.then($DONE, $DONE); diff --git a/test/js/async_await_throw_async.js b/test/js/async_await_throw_catch_async.t.js similarity index 57% rename from test/js/async_await_throw_async.js rename to test/js/async_await_throw_catch_async.t.js index b5b6bb27..e59d68f6 100644 --- a/test/js/async_await_throw_async.js +++ b/test/js/async_await_throw_catch_async.t.js @@ -1,3 +1,8 @@ +/*--- +includes: [] +flags: [async] +---*/ + function pr(x) { return new Promise(resolve => {resolve(x)}); } @@ -12,4 +17,9 @@ async function add(x) { return a + b; } -add(50).then(v => {console.log(v)}); +add(50) +.then(v => $DONOTEVALUATE()) +.catch(v => { + assert.sameValue(v, 51); +}) +.then($DONE, $DONE); diff --git a/test/js/async_await_try_catch.js b/test/js/async_await_try_catch.js deleted file mode 100644 index 5c11ec51..00000000 --- a/test/js/async_await_try_catch.js +++ /dev/null @@ -1,19 +0,0 @@ -async function af() { - try { - await new Promise(function(resolve, reject) { - reject("reject"); - }); - - console.log("shouldn't happen"); - } - catch (v) { - console.log(v); - } - finally { - console.log("finally"); - } - - return "end"; -}; - -af().then(v => console.log(v)); diff --git a/test/js/async_await_try_catch.t.js b/test/js/async_await_try_catch.t.js new file mode 100644 index 00000000..abb57864 --- /dev/null +++ b/test/js/async_await_try_catch.t.js @@ -0,0 +1,30 @@ +/*--- +includes: [compareArray.js] +flags: [async] +---*/ + +let stages = []; + +async function af() { + try { + await new Promise(function(resolve, reject) { + reject("reject"); + }); + + $DONOTEVALUATE(); + } + catch (v) { + stages.push(v); + } + finally { + stages.push('finally'); + } + + return "end"; +}; + +af().then(v => { + stages.push(v); + assert.compareArray(stages, ['reject', 'finally', 'end']); +}) +.then($DONE, $DONE) diff --git a/test/js/async_await_try_finally.js b/test/js/async_await_try_finally.t.js similarity index 57% rename from test/js/async_await_try_finally.js rename to test/js/async_await_try_finally.t.js index 9feb1b5f..c7869714 100644 --- a/test/js/async_await_try_finally.js +++ b/test/js/async_await_try_finally.t.js @@ -1,20 +1,32 @@ +/*--- +includes: [] +flags: [async] +---*/ + +let stages = []; + async function af() { try { await new Promise(function(resolve, reject) { reject("reject"); }); - console.log("shouldn't happen: try"); + $DONOTEVALUATE(); } finally { await new Promise(function(resolve, reject) { reject("finally reject"); }); - console.log("shouldn't happen: finally"); + $DONOTEVALUATE(); } return "shouldn't happen: end"; }; -af().then(v => console.log(v)); +af() +.then(v => $DONOTEVALUATE()) +.catch(v => { + assert.sameValue(v, "finally reject"); +}) +.then($DONE, $DONE); diff --git a/test/js/async_await_try_resolve.js b/test/js/async_await_try_resolve.t.js similarity index 61% rename from test/js/async_await_try_resolve.js rename to test/js/async_await_try_resolve.t.js index b041de15..02ef9899 100644 --- a/test/js/async_await_try_resolve.js +++ b/test/js/async_await_try_resolve.t.js @@ -1,3 +1,8 @@ +/*--- +includes: [] +flags: [async] +---*/ + async function af() { let key; @@ -12,4 +17,7 @@ async function af() { return key; }; -af().then(v => console.log(v)); +af().then(v => { + assert.sameValue(v, "key: resolve"); +}) +.then($DONE, $DONE); diff --git a/test/js/async_await_try_throw.js b/test/js/async_await_try_throw.js deleted file mode 100644 index d5f51e53..00000000 --- a/test/js/async_await_try_throw.js +++ /dev/null @@ -1,14 +0,0 @@ -async function af() { - try { - throw "try"; - - console.log("shouldn't happen: try"); - } - finally { - console.log("finally"); - } - - return "shouldn't happen: end"; -}; - -af().then(v => console.log(v)); diff --git a/test/js/async_await_try_throw.t.js b/test/js/async_await_try_throw.t.js new file mode 100644 index 00000000..13742141 --- /dev/null +++ b/test/js/async_await_try_throw.t.js @@ -0,0 +1,27 @@ +/*--- +includes: [compareArray.js] +flags: [async] +---*/ + +let stages = []; + +async function af() { + try { + throw "try"; + + $DONOTEVALUATE(); + } + finally { + stages.push("finally"); + } + + return "shouldn't happen: end"; +}; + +af() +.then(v => $DONOTEVALUATE()) +.catch(v => { + stages.push(v); + assert.compareArray(stages, ['finally', 'try']); +}) +.then($DONE, $DONE) diff --git a/test/js/async_await_try_throw_catch.js b/test/js/async_await_try_throw_catch.js deleted file mode 100644 index d4bd5b3e..00000000 --- a/test/js/async_await_try_throw_catch.js +++ /dev/null @@ -1,17 +0,0 @@ -async function af() { - try { - throw "try"; - - console.log("shouldn't happen: try"); - } - catch (v) { - console.log(v); - } - finally { - console.log("finally"); - } - - return "end"; -}; - -af().then(v => console.log(v)); diff --git a/test/js/async_await_try_throw_catch.t.js b/test/js/async_await_try_throw_catch.t.js new file mode 100644 index 00000000..0417c439 --- /dev/null +++ b/test/js/async_await_try_throw_catch.t.js @@ -0,0 +1,27 @@ +/*--- +includes: [compareArray.js] +flags: [async] +---*/ + +let stage = []; + +async function af() { + try { + throw "try"; + + $DONOTEVALUATE(); + } + catch (v) { + stage.push(v); + } + finally { + stage.push("finally"); + } + + return "end"; +}; + +af().then(v => { + stage.push(v); + assert.compareArray(stage, ['try', 'finally', 'end']) +}).then($DONE, $DONE); diff --git a/test/js/fs_promises_001.js b/test/js/fs_promises_001.js deleted file mode 100644 index 22a1efc5..00000000 --- a/test/js/fs_promises_001.js +++ /dev/null @@ -1,55 +0,0 @@ -var fs = require('fs').promises; -var fname = './build/test/fs_promises_001'; - -Promise.resolve() -.then(() => { - return fs.writeFile(fname, fname); -}) -.then((data) => { - console.log('init ok', data === undefined); -}) -.catch((e) => { - console.log('init failed', e); -}) -.then(() => { - return fs.readFile(fname).then(fs.readFile); -}) -.then((data) => { - console.log('short circut ok', data == fname); -}) -.catch((e) => { - console.log('short circut failed', e); -}) -.then(() => { - var read = fs.readFile.bind(fs, fname, 'utf8'); - var write = fs.writeFile.bind(fs, fname); - var append = fs.appendFile.bind(fs, fname); - - return write(fname).then(read).then(append).then(read); -}) -.then((data) => { - console.log('chain ok', data == (fname + fname)); -}) -.catch((e) => { - console.log('chain failed', e); -}) -.then(() => { - // nodejs incompatible - try { - return fs.readFile(); - } catch (e) { - console.log('error 1 ok', e instanceof TypeError) - } - try { - return fs.writeFile(); - } catch (e) { - console.log('error 2 ok', e instanceof TypeError) - } -}) -.then((data) => { - console.log('errors ok'); -}) -.catch((e) => { - console.log('errors failed - reject on bad args'); -}) -; diff --git a/test/js/promise_all.js b/test/js/promise_all.js deleted file mode 100644 index afe885f8..00000000 --- a/test/js/promise_all.js +++ /dev/null @@ -1,9 +0,0 @@ -function resolve(value) { - return new Promise(resolve => setTimeout(() => resolve(value), 0)); -} - -Promise.all([resolve(['one', 'two']), resolve(['three', 'four'])]) -.then( - (v) => {console.log(`resolved:${njs.dump(v)}`)}, - (v) => {console.log(`rejected:${njs.dump(v)}`)} -); diff --git a/test/js/promise_all.t.js b/test/js/promise_all.t.js new file mode 100644 index 00000000..7f8b25d5 --- /dev/null +++ b/test/js/promise_all.t.js @@ -0,0 +1,16 @@ +/*--- +includes: [compareArray.js] +flags: [async] +---*/ + +function resolve(value) { + return new Promise(resolve => setTimeout(() => resolve(value), 0)); +} + +Promise.all([resolve(['one', 'two']), resolve(['three', 'four'])]) +.then( + v => { assert.compareArray(v[0], ['one', 'two']); + assert.compareArray(v[1], ['three', 'four']); }, + v => $DONOTEVALUATE(), +) +.then($DONE, $DONE); diff --git a/test/js/promise_allSettled.js b/test/js/promise_allSettled.t.js similarity index 81% rename from test/js/promise_allSettled.js rename to test/js/promise_allSettled.t.js index bf997121..a4e49807 100644 --- a/test/js/promise_allSettled.js +++ b/test/js/promise_allSettled.t.js @@ -1,3 +1,8 @@ +/*--- +includes: [] +flags: [async] +---*/ + var p0 = Promise.resolve(2).then(v => v + 1); var p1 = Promise.reject(21).catch(v => v * 2); var p2 = Promise.resolve('nope').then(() => { throw 'foo' }); @@ -15,6 +20,7 @@ function dump(v) { } Promise.allSettled([p0, p1, p2, p3, p4, p5, p6, p7, p8]).then( - (v) => {console.log(`resolved:${dump(v)}`)}, - (v) => {console.log(`rejected:${dump(v)}`)} -); + v => assert.sameValue(dump(v), "F:0,3,42,here|R:finally,finally after rejected,foo,here too,yes"), + v => $DONOTEVALUATE(), +) +.then($DONE, $DONE); diff --git a/test/js/promise_allSettled_string.js b/test/js/promise_allSettled_string.t.js similarity index 64% rename from test/js/promise_allSettled_string.js rename to test/js/promise_allSettled_string.t.js index fc47a7db..e99792d7 100644 --- a/test/js/promise_allSettled_string.js +++ b/test/js/promise_allSettled_string.t.js @@ -1,3 +1,8 @@ +/*--- +includes: [] +flags: [async] +---*/ + function dump(v) { var fulfilled = v.filter(v=>v.status == 'fulfilled').map(v=>v.value).sort(); var rejected = v.filter(v=>v.status == 'rejected').map(v=>v.reason).sort(); @@ -5,6 +10,7 @@ function dump(v) { } Promise.allSettled("abc").then( - (v) => {console.log(`resolved:${dump(v)}`)}, - (v) => {console.log(`rejected:${dump(v)}`)} -); + v => assert.sameValue(dump(v), "F:a,b,c|R:"), + v => $DONOTEVALUATE(), +) +.then($DONE, $DONE); diff --git a/test/js/promise_all_throw.js b/test/js/promise_all_throw.t.js similarity index 65% rename from test/js/promise_all_throw.js rename to test/js/promise_all_throw.t.js index 1994b37e..008952a1 100644 --- a/test/js/promise_all_throw.js +++ b/test/js/promise_all_throw.t.js @@ -1,9 +1,15 @@ +/*--- +includes: [] +flags: [async] +---*/ + var p0 = Promise.resolve(1).then(v => v + 1); var p1 = Promise.reject(2).catch(v => v * 2); var p2 = Promise.resolve().then(() => { throw 'foo' }); var p3 = Promise.reject().then(() => { throw 'oof'; }); Promise.all([p0, p1, p2, p3]).then( - (v) => {console.log(`resolved:${v}`)}, - (v) => {console.log(`rejected:${v}`)} -); + v => $DONOTEVALUATE(), + v => assert.sameValue(v, 'foo') +) +.then($DONE, $DONE); diff --git a/test/js/promise_any.js b/test/js/promise_any.t.js similarity index 59% rename from test/js/promise_any.js rename to test/js/promise_any.t.js index 3ea4b545..fb287ba9 100644 --- a/test/js/promise_any.js +++ b/test/js/promise_any.t.js @@ -1,8 +1,14 @@ +/*--- +includes: [] +flags: [async] +---*/ + var p0 = Promise.resolve().then(() => { throw 'foo' }); var p1 = Promise.reject(2).catch(v => v * 2); var p2 = Promise.resolve(1).then(v => v + 1); Promise.any([p0, p1, p2]).then( - (v) => {console.log(`resolved:${v}`)}, - (v) => {console.log(`rejected:${v}`)} -); + v => assert.sameValue(v, 4), + v => $DONOTEVALUATE(), +) +.then($DONE, $DONE); diff --git a/test/js/promise_any_all_rejected.js b/test/js/promise_any_all_rejected.js deleted file mode 100644 index f008fe38..00000000 --- a/test/js/promise_any_all_rejected.js +++ /dev/null @@ -1,7 +0,0 @@ -var p0 = Promise.reject(1); -var p1 = Promise.reject(2); - -Promise.any([p0, p1]).then( - (v) => {console.log(`resolve:${v}`)}, - (v) => {console.log(`reject:${v}`)} -); diff --git a/test/js/promise_any_all_rejected.t.js b/test/js/promise_any_all_rejected.t.js new file mode 100644 index 00000000..c6a7254a --- /dev/null +++ b/test/js/promise_any_all_rejected.t.js @@ -0,0 +1,13 @@ +/*--- +includes: [] +flags: [async] +---*/ + +var p0 = Promise.reject(1); +var p1 = Promise.reject(2); + +Promise.any([p0, p1]).then( + v => $DONOTEVALUATE(), + v => assert.sameValue(v.constructor, AggregateError), +) +.then($DONE, $DONE); diff --git a/test/js/promise_catch_then_throw_catch.js b/test/js/promise_catch_then_throw_catch.js deleted file mode 100644 index b4f99e89..00000000 --- a/test/js/promise_catch_then_throw_catch.js +++ /dev/null @@ -1,5 +0,0 @@ -Promise.resolve() -.then(() => {}) -.catch(() => {}) -.then(() => {nonExsisting()}) -.catch(() => {console.log("Done")}); \ No newline at end of file diff --git a/test/js/promise_catch_then_throw_catch.t.js b/test/js/promise_catch_then_throw_catch.t.js new file mode 100644 index 00000000..bbe6b591 --- /dev/null +++ b/test/js/promise_catch_then_throw_catch.t.js @@ -0,0 +1,14 @@ +/*--- +includes: [] +flags: [async] +---*/ + +let called = false; + +Promise.resolve() +.then(() => {}) +.catch(() => {}) +.then(() => {nonExsisting()}) +.catch(() => { called = true; }) +.then(() => assert.sameValue(called, true)) +.then($DONE, $DONE); diff --git a/test/js/promise_catch_throw.js b/test/js/promise_catch_throw.js deleted file mode 100644 index 9c246eb2..00000000 --- a/test/js/promise_catch_throw.js +++ /dev/null @@ -1,3 +0,0 @@ -Promise.resolve() -.then(() => {nonExsisting()}) -.catch(() => {nonExsistingInCatch()}); \ No newline at end of file diff --git a/test/js/promise_catch_throw.t.js b/test/js/promise_catch_throw.t.js new file mode 100644 index 00000000..9bf99da5 --- /dev/null +++ b/test/js/promise_catch_throw.t.js @@ -0,0 +1,10 @@ +/*--- +includes: [] +flags: [async] +---*/ + +Promise.resolve() +.then(() => {nonExsisting()}) +.catch(() => {nonExsistingInCatch()}) +.catch(v => assert.sameValue(v.constructor, ReferenceError)) +.then($DONE, $DONE); diff --git a/test/js/promise_finally.js b/test/js/promise_finally.js deleted file mode 100644 index b6286889..00000000 --- a/test/js/promise_finally.js +++ /dev/null @@ -1,7 +0,0 @@ -Promise.resolve('here') -.finally(() => {'nope'}) -.then(v => {console.log(v)}); - -Promise.resolve('here') -.finally(() => {throw 'nope'}) -.then(v => {console.log(v)}); diff --git a/test/js/promise_finally.t.js b/test/js/promise_finally.t.js new file mode 100644 index 00000000..bd12bdfc --- /dev/null +++ b/test/js/promise_finally.t.js @@ -0,0 +1,14 @@ +/*--- +includes: [] +flags: [async] +---*/ + +Promise.resolve('here') +.finally(() => {'nope'}) +.then(v => assert.sameValue(v, 'here')); + +Promise.resolve('here') +.finally(() => {throw 'nope'}) +.then(v => $DONOTEVALUATE()) +.catch(v => assert.sameValue(v, 'nope')) +.then($DONE, $DONE); diff --git a/test/js/promise_finally_throw.js b/test/js/promise_finally_throw.js deleted file mode 100644 index 7ae947e5..00000000 --- a/test/js/promise_finally_throw.js +++ /dev/null @@ -1,2 +0,0 @@ -Promise.resolve() -.finally(() => {nonExsistingInFinally()}); \ No newline at end of file diff --git a/test/js/promise_finally_throw.t.js b/test/js/promise_finally_throw.t.js new file mode 100644 index 00000000..74fe0d9f --- /dev/null +++ b/test/js/promise_finally_throw.t.js @@ -0,0 +1,9 @@ +/*--- +includes: [] +flags: [] +negative: + phase: runtime +---*/ + +Promise.resolve() +.finally(() => {nonExsistingInFinally()}); diff --git a/test/js/promise_finally_throw_catch.js b/test/js/promise_finally_throw_catch.js deleted file mode 100644 index 03301be2..00000000 --- a/test/js/promise_finally_throw_catch.js +++ /dev/null @@ -1,3 +0,0 @@ -Promise.resolve() -.finally(() => {nonExsistingInFinally()}) -.catch(() => {console.log("Done")}); \ No newline at end of file diff --git a/test/js/promise_finally_throw_catch.t.js b/test/js/promise_finally_throw_catch.t.js new file mode 100644 index 00000000..2d5ae3dc --- /dev/null +++ b/test/js/promise_finally_throw_catch.t.js @@ -0,0 +1,9 @@ +/*--- +includes: [] +flags: [async] +---*/ + +Promise.resolve() +.finally(() => {nonExsistingInFinally()}) +.catch(e => {}) +.then($DONE, $DONE); diff --git a/test/js/promise_race.js b/test/js/promise_race.t.js similarity index 60% rename from test/js/promise_race.js rename to test/js/promise_race.t.js index 81a6d572..eb34dd7f 100644 --- a/test/js/promise_race.js +++ b/test/js/promise_race.t.js @@ -1,3 +1,8 @@ +/*--- +includes: [] +flags: [async] +---*/ + var p1 = new Promise((resolve, reject) => { setTimeout(resolve, 0, 'one'); }); @@ -7,6 +12,7 @@ var p2 = new Promise((resolve, reject) => { }); Promise.race([p1, p2]).then( - (v) => {console.log(`resolved:${v}`)}, - (v) => {console.log(`rejected:${v}`)} -); + v => assert.sameValue(v, 'one'), + v => $DONOTEVALUATE(), +) +.then($DONE, $DONE); diff --git a/test/js/promise_race_throw.js b/test/js/promise_race_throw.t.js similarity index 58% rename from test/js/promise_race_throw.js rename to test/js/promise_race_throw.t.js index 0fc9145b..f53cb6d5 100644 --- a/test/js/promise_race_throw.js +++ b/test/js/promise_race_throw.t.js @@ -1,3 +1,8 @@ +/*--- +includes: [] +flags: [async] +---*/ + var p1 = new Promise((resolve, reject) => { throw 'one'; }); @@ -7,6 +12,7 @@ var p2 = new Promise((resolve, reject) => { }); Promise.race([p1, p2]).then( - (v) => {console.log(`resolved:${v}`)}, - (v) => {console.log(`rejected:${v}`)} -); + v => $DONOTEVALUATE(), + v => assert.sameValue(v, 'one'), +) +.then($DONE, $DONE); diff --git a/test/js/promise_reject_catch.js b/test/js/promise_reject_catch.js deleted file mode 100644 index 81dff1f5..00000000 --- a/test/js/promise_reject_catch.js +++ /dev/null @@ -1 +0,0 @@ -Promise.reject("test").catch((x) => console.log('rejected', x)); \ No newline at end of file diff --git a/test/js/promise_reject_catch.t.js b/test/js/promise_reject_catch.t.js new file mode 100644 index 00000000..727bf773 --- /dev/null +++ b/test/js/promise_reject_catch.t.js @@ -0,0 +1,8 @@ +/*--- +includes: [] +flags: [async] +---*/ + +Promise.reject("test") +.catch(v => assert.sameValue(v, "test")) +.then($DONE, $DONE); diff --git a/test/js/promise_reject_post_catch.js b/test/js/promise_reject_post_catch.js deleted file mode 100644 index b2e617b7..00000000 --- a/test/js/promise_reject_post_catch.js +++ /dev/null @@ -1,2 +0,0 @@ -var p = Promise.reject(); -setImmediate(() => {p.catch(() => {})}); \ No newline at end of file diff --git a/test/js/promise_reject_post_catch.t.js b/test/js/promise_reject_post_catch.t.js new file mode 100644 index 00000000..0061cbcf --- /dev/null +++ b/test/js/promise_reject_post_catch.t.js @@ -0,0 +1,9 @@ +/*--- +includes: [] +flags: [] +negative: + phase: runtime +---*/ + +var p = Promise.reject(); +setImmediate(() => {p.catch(() => {})}); diff --git a/test/js/promise_rejection_tracker.js b/test/js/promise_rejection_tracker.js deleted file mode 100644 index db06e222..00000000 --- a/test/js/promise_rejection_tracker.js +++ /dev/null @@ -1 +0,0 @@ -Promise.reject(1); \ No newline at end of file diff --git a/test/js/promise_rejection_tracker.t.js b/test/js/promise_rejection_tracker.t.js new file mode 100644 index 00000000..865b7445 --- /dev/null +++ b/test/js/promise_rejection_tracker.t.js @@ -0,0 +1,9 @@ +/*--- +includes: [] +flags: [] +negative: + phase: runtime +---*/ + +Promise.reject(1); + diff --git a/test/js/promise_s01.t.js b/test/js/promise_s01.t.js new file mode 100644 index 00000000..acd98d00 --- /dev/null +++ b/test/js/promise_s01.t.js @@ -0,0 +1,22 @@ +/*--- +includes: [compareArray.js] +flags: [async] +---*/ + +let stages = []; + +var promise = new Promise(function(resolve, reject) { + stages.push('One'); + + reject(123); +}).catch((v) => {stages.push(v)}); + +stages.push('Two'); + +promise.then(() => {stages.push('Four'); return {num: 'Five'}}) +.then(obj => {stages.push(obj.num); return {num: 'Six'}}) +.then(obj => {stages.push(obj.num)}) +.then(() => assert.compareArray(stages, ["One", "Two", "Three", 123, "Four", "Five", "Six"])) +.then($DONE, $DONE); + +stages.push('Three'); diff --git a/test/js/promise_s02.t.js b/test/js/promise_s02.t.js new file mode 100644 index 00000000..3e89abf0 --- /dev/null +++ b/test/js/promise_s02.t.js @@ -0,0 +1,23 @@ +/*--- +includes: [compareArray.js] +flags: [async] +---*/ + +let stages = []; + +var promise = new Promise(function(resolve, reject) { + stages.push('One'); + + reject(123); +}) + +stages.push('Two'); + +promise.then(() => {stages.push('Four'); return {num: 'Five'}}) +.then(obj => {stages.push(obj.num); return {num: 'Six'}}) +.then(obj => {stages.push(obj.num)}) +.catch(v => assert.sameValue(v, 123)) +.then(() => assert.compareArray(stages, ["One", "Two", "Three"])) +.then($DONE, $DONE); + +stages.push('Three'); diff --git a/test/js/promise_s03.t.js b/test/js/promise_s03.t.js new file mode 100644 index 00000000..9492dd65 --- /dev/null +++ b/test/js/promise_s03.t.js @@ -0,0 +1,21 @@ +/*--- +includes: [compareArray.js] +flags: [async] +---*/ + +let stages = []; + +var promise = new Promise(function(resolve, reject) { + stages.push('One'); + reject(42); +}); + +stages.push('Two'); + +promise.then( + v => $DONOTEVALUATE(), + v => assert.sameValue(v, 42)) +.then(() => assert.compareArray(stages, ['One', 'Two', 'Three'])) +.then($DONE, $DONE); + +stages.push('Three'); diff --git a/test/js/promise_s04.t.js b/test/js/promise_s04.t.js new file mode 100644 index 00000000..02303561 --- /dev/null +++ b/test/js/promise_s04.t.js @@ -0,0 +1,12 @@ +/*--- +includes: [] +flags: [] +negative: + phase: runtime +---*/ + +Promise.reject(new Error('Oh my')) +.then( + function(success) {}, + function(error) { throw error;} +); diff --git a/test/js/promise_s05.t.js b/test/js/promise_s05.t.js new file mode 100644 index 00000000..2cb4981c --- /dev/null +++ b/test/js/promise_s05.t.js @@ -0,0 +1,18 @@ +/*--- +includes: [] +flags: [async] +---*/ + +let called = false; + +Promise.resolve('Success') +.then( + function(value) { + assert.sameValue(value, 'Success'); + called = true; + }, + function(value) { + $DONOTEVALUATE() +}) +.then(() => assert.sameValue(called, true)) +.then($DONE, $DONE); diff --git a/test/js/promise_s06.t.js b/test/js/promise_s06.t.js new file mode 100644 index 00000000..45627148 --- /dev/null +++ b/test/js/promise_s06.t.js @@ -0,0 +1,10 @@ +/*--- +includes: [] +flags: [async] +---*/ + +var p = Promise.resolve([1,2,3]); +p.then(function(v) { + assert.sameValue(v[0], 1); +}) +.then($DONE, $DONE); diff --git a/test/js/promise_s07.t.js b/test/js/promise_s07.t.js new file mode 100644 index 00000000..35b3ee6c --- /dev/null +++ b/test/js/promise_s07.t.js @@ -0,0 +1,15 @@ +/*--- +includes: [] +flags: [async] +---*/ + +var p1 = Promise.resolve({ + then: function(onFulfill, onReject) { onFulfill('fulfilled!'); } +}); + +p1.then( + function(v) { assert.sameValue(v, 'fulfilled!'); }, + function(e) { $DONOTEVALUATE() }, +) +.then(() => assert.sameValue(p1 instanceof Promise, true)) +.then($DONE, $DONE); diff --git a/test/js/promise_s08.t.js b/test/js/promise_s08.t.js new file mode 100644 index 00000000..83f3730c --- /dev/null +++ b/test/js/promise_s08.t.js @@ -0,0 +1,22 @@ +/*--- +includes: [] +flags: [async] +---*/ + +let called = false; + +var thenable = { + then: function(resolve) { + called = true; + resolve(); + } +}; + +function executor(resolve, reject) { + resolve(thenable); + throw new Error('ignored'); +} + +new Promise(executor) +.then(() => assert.sameValue(called, true)) +.then($DONE, $DONE); diff --git a/test/js/promise_s09.t.js b/test/js/promise_s09.t.js new file mode 100644 index 00000000..ff410023 --- /dev/null +++ b/test/js/promise_s09.t.js @@ -0,0 +1,15 @@ +/*--- +includes: [compareArray.js] +flags: [] +---*/ + +let calls = []; + +function NotPromise(executor) { + assert.sameValue(Object.isExtensible(executor), true); + executor(function() {calls.push('S')}, function() {calls.push('R')}); +} + +Promise.resolve.call(NotPromise); + +assert.compareArray(calls, ['S']); diff --git a/test/js/promise_s1.js b/test/js/promise_s1.js deleted file mode 100644 index 308dbe2d..00000000 --- a/test/js/promise_s1.js +++ /dev/null @@ -1,15 +0,0 @@ -var promise = new Promise(function(resolve, reject) { - console.log('One'); - - reject(123); -}).catch((v) => {console.log(v)}); - -console.log('Two'); - -promise.then(() => {console.log('Four'); return {num: 'Five'}}) -.then((obj) => {console.log(obj.num); return {num: 'Six'}}) -.then((obj) => {console.log(obj.num); return {num: 'Seven'}}) -.then((obj) => {console.log(obj.num); return {num: 'Eight'}}) -.then((obj) => {console.log(obj.num)}); - -console.log('Three'); \ No newline at end of file diff --git a/test/js/promise_s10.js b/test/js/promise_s10.js deleted file mode 100644 index 6fd1d6b2..00000000 --- a/test/js/promise_s10.js +++ /dev/null @@ -1,11 +0,0 @@ -var promise = new Promise(function(resolve, reject) { - console.log('One'); - reject('Oh no'); -}); - -console.log('Two'); - -promise.then(() => {console.log('Three')}) -.catch((v) => {console.log(v)}); - -console.log('Three'); \ No newline at end of file diff --git a/test/js/promise_s10.t.js b/test/js/promise_s10.t.js new file mode 100644 index 00000000..a3e155f3 --- /dev/null +++ b/test/js/promise_s10.t.js @@ -0,0 +1,20 @@ +/*--- +includes: [compareArray.js] +flags: [async] +---*/ + +let stages = []; + +var promise = new Promise(function(resolve, reject) { + stages.push('One'); + reject('Oh no'); +}); + +stages.push('Two'); + +promise.then(() => {stages.push('Three')}) +.catch((v) => {stages.push(v)}) +.then(() => assert.compareArray(stages, ['One', 'Two', 'Three', 'Oh no'])) +.then($DONE, $DONE); + +stages.push('Three'); diff --git a/test/js/promise_s11.js b/test/js/promise_s11.js deleted file mode 100644 index ecffccca..00000000 --- a/test/js/promise_s11.js +++ /dev/null @@ -1,13 +0,0 @@ -var promise = new Promise((resolve, reject) => resolve('all')); - -promise.then( function f1(result) { - console.log('S: ' + result); - return 'f1'; -}); - -promise.then( function f2(result) { - console.log('R: ' + result); - return 'f2'; -}); - -console.log('end') \ No newline at end of file diff --git a/test/js/promise_s11.t.js b/test/js/promise_s11.t.js new file mode 100644 index 00000000..d37bfb68 --- /dev/null +++ b/test/js/promise_s11.t.js @@ -0,0 +1,22 @@ +/*--- +includes: [compareArray.js] +flags: [async] +---*/ + +let stages = []; + +var promise = new Promise((resolve, reject) => resolve('all')); + +promise.then( function f1(result) { + stages.push('S: ' + result); + return 'f1'; +}); + +promise.then( function f2(result) { + stages.push('R: ' + result); + return 'f2'; +}) +.then(() => assert.compareArray(stages, ['end', 'S: all', 'R: all'])) +.then($DONE, $DONE); + +stages.push('end'); diff --git a/test/js/promise_s12.js b/test/js/promise_s12.js deleted file mode 100644 index e157b472..00000000 --- a/test/js/promise_s12.js +++ /dev/null @@ -1,10 +0,0 @@ -var thenable = new Promise(function() {}); - -var p = new Promise(function(resolve) { - resolve(); - throw thenable; -}); - -p.then(function() { - console.log('Done'); -}); \ No newline at end of file diff --git a/test/js/promise_s12.t.js b/test/js/promise_s12.t.js new file mode 100644 index 00000000..dec5ca7e --- /dev/null +++ b/test/js/promise_s12.t.js @@ -0,0 +1,19 @@ +/*--- +includes: [] +flags: [async] +---*/ + +let called = false; + +var thenable = new Promise(function() {}); + +var p = new Promise(function(resolve) { + resolve(); + throw thenable; +}); + +p.then(function() { + called = true; +}) +.then(() => assert.sameValue(called, true)) +.then($DONE, $DONE); diff --git a/test/js/promise_s13.js b/test/js/promise_s13.js deleted file mode 100644 index 4ace323e..00000000 --- a/test/js/promise_s13.js +++ /dev/null @@ -1,21 +0,0 @@ -var thenable = Promise.resolve(); -var p = new Promise(function(a,b) { - throw thenable; -}); - -p.then(function() { - console.log('The promise should not be fulfilled.'); -}) -.then( - function() { - console.log('The promise should not be fulfilled.'); - }, - function(x) { - if (x !== thenable) { - console.log('The promise should be rejected with the resolution value.'); - return; - } - - console.log('Done'); - } -); \ No newline at end of file diff --git a/test/js/promise_s13.t.js b/test/js/promise_s13.t.js new file mode 100644 index 00000000..fe4bb017 --- /dev/null +++ b/test/js/promise_s13.t.js @@ -0,0 +1,23 @@ +/*--- +includes: [] +flags: [async] +---*/ + +let called = false; + +var thenable = Promise.resolve(); +var p = new Promise(function(a,b) { + throw thenable; +}); + +p +.then(v => $DONOTEVALUATE()) +.then( + v => $DONOTEVALUATE(), + function(x) { + assert.sameValue(x, thenable, 'The promise should be rejected with the resolution value.'); + called = true; + } +) +.then(() => assert.sameValue(called, true)) +.then($DONE, $DONE); diff --git a/test/js/promise_s14.js b/test/js/promise_s14.js deleted file mode 100644 index 63494eea..00000000 --- a/test/js/promise_s14.js +++ /dev/null @@ -1,9 +0,0 @@ -var isLoading = true; -var promise = new Promise((a, b) => {a()} ); - -promise.then(function(response) { - throw new TypeError('oops'); -}) -.then(function(json) { }) -.catch(function(error) { console.log(error); }) -.finally(function() { console.log('Done') }); \ No newline at end of file diff --git a/test/js/promise_s14.t.js b/test/js/promise_s14.t.js new file mode 100644 index 00000000..a6e81d4a --- /dev/null +++ b/test/js/promise_s14.t.js @@ -0,0 +1,21 @@ +/*--- +includes: [] +flags: [async] +---*/ + +let stages = []; + +var isLoading = true; +var promise = new Promise((a, b) => {a()} ); + +promise.then(function(response) { + throw new TypeError('oops'); +}) +.then(function(json) { }) +.catch(e => stages.push(e)) +.finally(() => stages.push('Done')) +.then(() => { + assert.sameValue(stages[0] instanceof TypeError, true); + assert.sameValue(stages[1], 'Done'); +}) +.then($DONE, $DONE); diff --git a/test/js/promise_s15.js b/test/js/promise_s15.js deleted file mode 100644 index 5b134bdb..00000000 --- a/test/js/promise_s15.js +++ /dev/null @@ -1,10 +0,0 @@ -var obj = {}; -var p = Promise.resolve(obj); - -p.then(undefined, undefined) -.then(function(arg) { - if (arg !== obj) { - console.log('Expected resolution object to be passed through, got ' + arg); - } -}) -.then(() => {console.log('Done')}, () => {console.log('Error')}); \ No newline at end of file diff --git a/test/js/promise_s15.t.js b/test/js/promise_s15.t.js new file mode 100644 index 00000000..df5c82ee --- /dev/null +++ b/test/js/promise_s15.t.js @@ -0,0 +1,16 @@ +/*--- +includes: [] +flags: [async] +---*/ + +var obj = {}; +var p = Promise.resolve(obj); + +p.then(undefined, undefined) +.then( + v => { + assert.sameValue(v, obj, + 'Expected resolution object to be passed through, got ' + v); + }, + e => $DONOTEVALUATE()) +.then($DONE, $DONE); diff --git a/test/js/promise_s16.js b/test/js/promise_s16.js deleted file mode 100644 index 769d38a6..00000000 --- a/test/js/promise_s16.js +++ /dev/null @@ -1,10 +0,0 @@ -var obj = {}; -var p = Promise.reject(obj); - -p.then(undefined, undefined).then(function() { - console.log('Should not be called -- promise was rejected.'); -}, function(arg) { - if (arg !== obj) { - console.log('Expected resolution object to be passed through, got ' + arg); - } -}).then(() => {console.log('Done')}, () => {console.log('Error')}); diff --git a/test/js/promise_s16.t.js b/test/js/promise_s16.t.js new file mode 100644 index 00000000..b4924884 --- /dev/null +++ b/test/js/promise_s16.t.js @@ -0,0 +1,16 @@ +/*--- +includes: [] +flags: [async] +---*/ + +var obj = {}; +var p = Promise.reject(obj); + +p.then(undefined, undefined) +.then( + v => DONOTEVALUATE(), + e => { + assert.sameValue(e, obj, + 'Expected resolution object to be passed through, got ' + e); +}) +.then($DONE, $DONE); diff --git a/test/js/promise_s17.js b/test/js/promise_s17.js deleted file mode 100644 index 769d38a6..00000000 --- a/test/js/promise_s17.js +++ /dev/null @@ -1,10 +0,0 @@ -var obj = {}; -var p = Promise.reject(obj); - -p.then(undefined, undefined).then(function() { - console.log('Should not be called -- promise was rejected.'); -}, function(arg) { - if (arg !== obj) { - console.log('Expected resolution object to be passed through, got ' + arg); - } -}).then(() => {console.log('Done')}, () => {console.log('Error')}); diff --git a/test/js/promise_s17.t.js b/test/js/promise_s17.t.js new file mode 100644 index 00000000..b5bc8690 --- /dev/null +++ b/test/js/promise_s17.t.js @@ -0,0 +1,18 @@ +/*--- +includes: [] +flags: [async] +---*/ + +/* Duplicate of s16. */ + +var obj = {}; +var p = Promise.reject(obj); + +p.then(undefined, undefined) +.then( + v => DONOTEVALUATE(), + e => { + assert.sameValue(e, obj, + 'Expected resolution object to be passed through, got ' + e); +}) +.then($DONE, $DONE); diff --git a/test/js/promise_s18.js b/test/js/promise_s18.t.js similarity index 50% rename from test/js/promise_s18.js rename to test/js/promise_s18.t.js index 10d10641..ce0da2fe 100644 --- a/test/js/promise_s18.js +++ b/test/js/promise_s18.t.js @@ -1,23 +1,32 @@ +/*--- +includes: [compareArray.js] +flags: [async] +---*/ + +let stages = []; + var thenable = { then: function(resolve) { resolve(); - console.log('State 5'); + stages.push(5); } }; var thenableWithError = { then: function(resolve) { - console.log('State 3'); + stages.push(3); resolve(thenable); - console.log('State 4'); + stages.push(4); throw new Error('ignored exception'); } }; function executor(resolve, reject) { - console.log('State 1'); + stages.push(1); resolve(thenableWithError); - console.log('State 2'); + stages.push(2); } -new Promise(executor).then(() => {console.log('Done')}, () => {console.log('Error')}); \ No newline at end of file +new Promise(executor) +.then(() => assert.compareArray(stages, [1, 2, 3, 4, 5])) +.then($DONE, $DONE); diff --git a/test/js/promise_s19.js b/test/js/promise_s19.js deleted file mode 100644 index 451f710e..00000000 --- a/test/js/promise_s19.js +++ /dev/null @@ -1,33 +0,0 @@ -var returnValue = null; -var value = {}; -var resolve; - -var poisonedThen = Object.defineProperty({}, 'then', { - get: function() { - console.log('Throw!'); - throw value; - } -}); - -var promise = new Promise(function(_resolve) { - resolve = _resolve; -}); - -promise.then( -function() { - console.log('Resolve!'); - console.log('The promise should not be fulfilled.'); -}, -function(val) { - console.log('Reject!'); - if (val !== value) { - console.log('The promise should be fulfilled with the provided value.'); - return; - } - - console.log('Done'); -}); - -returnValue = resolve(poisonedThen); - -console.log(returnValue); \ No newline at end of file diff --git a/test/js/promise_s19.t.js b/test/js/promise_s19.t.js new file mode 100644 index 00000000..d339b3f6 --- /dev/null +++ b/test/js/promise_s19.t.js @@ -0,0 +1,34 @@ +/*--- +includes: [compareArray.js] +flags: [async] +---*/ + +let stages = []; + +var returnValue = null; +var value = {}; +var resolve; + +var poisonedThen = Object.defineProperty({}, 'then', { + get: function() { + stages.push('Throw!'); + throw value; + } +}); + +var promise = new Promise(function(_resolve) { + resolve = _resolve; +}); + +promise.then( + v => $DONOTEVALUATE(), + e => { + stages.push('Reject!'); + assert.sameValue(e, value, 'The promise should be fulfilled with the provided value.'); +}) +.then(() => assert.compareArray(stages, ['Throw!', undefined, 'Reject!'])) +.then($DONE, $DONE); + +returnValue = resolve(poisonedThen); + +stages.push(returnValue); diff --git a/test/js/promise_s2.js b/test/js/promise_s2.js deleted file mode 100644 index 92d92dd0..00000000 --- a/test/js/promise_s2.js +++ /dev/null @@ -1,14 +0,0 @@ -var promise = new Promise(function(resolve, reject) { - console.log('One'); - reject(123); -}); - -console.log('Two'); - -promise.then(() => {console.log('Four'); return {num: 'Five'}}) -.then((obj) => {console.log(obj.num); return {num: 'Six'}}) -.then((obj) => {console.log(obj.num); return {num: 'Seven'}}) -.then((obj) => {console.log(obj.num); return {num: 'Eight'}}) -.then((obj) => {console.log(obj.num)}); - -console.log('Three'); \ No newline at end of file diff --git a/test/js/promise_s20.js b/test/js/promise_s20.js deleted file mode 100644 index 0934bba0..00000000 --- a/test/js/promise_s20.js +++ /dev/null @@ -1,23 +0,0 @@ -var returnValue = null; -var value = {}; -var poisonedThen = Object.defineProperty({}, 'then', { - get: function() { - throw value; - } -}); -var promise = new Promise(function(resolve) { - returnValue = resolve(poisonedThen); -}); - -console.log(returnValue == undefined); - -promise.then(function() { - console.log('The promise should not be fulfilled.'); -}, function(val) { - if (val !== value) { - console.log('The promise should be fulfilled with the provided value.'); - return; - } - - console.log('Done'); -}); \ No newline at end of file diff --git a/test/js/promise_s20.t.js b/test/js/promise_s20.t.js new file mode 100644 index 00000000..4c6a151d --- /dev/null +++ b/test/js/promise_s20.t.js @@ -0,0 +1,25 @@ +/*--- +includes: [] +flags: [async] +---*/ + +var returnValue = null; +var value = {}; +var poisonedThen = Object.defineProperty({}, 'then', { + get: function() { + throw value; + } +}); +var promise = new Promise(function(resolve) { + returnValue = resolve(poisonedThen); +}); + +assert.sameValue(returnValue, undefined); + +promise +.then( + v => $DONOTEVALUATE(), + e => { + assert.sameValue(e, value, 'The promise should be fulfilled with the provided value.'); +}) +.then($DONE, $DONE); diff --git a/test/js/promise_s21.js b/test/js/promise_s21.t.js similarity index 51% rename from test/js/promise_s21.js rename to test/js/promise_s21.t.js index aad00cca..77689f6f 100644 --- a/test/js/promise_s21.js +++ b/test/js/promise_s21.t.js @@ -1,3 +1,8 @@ +/*--- +includes: [] +flags: [async] +---*/ + var value = {}; var resolve; var poisonedThen = Object.defineProperty({}, 'then', { @@ -16,15 +21,12 @@ p2 = p1.then(function() { return poisonedThen; }); -p2.then(function(x) { - console.log('The promise should not be fulfilled.'); -}, function(x) { - if (x !== value) { - console.log('The promise should be rejected with the thrown exception.'); - return; - } - - console.log('Done'); -}); +p2 +.then( + v => $DONOTEVALUATE(), + e => { + assert.sameValue(e, value, 'The promise should be rejected with the thrown exception.'); +}) +.then($DONE, $DONE); -resolve(); \ No newline at end of file +resolve(); diff --git a/test/js/promise_s22.js b/test/js/promise_s22.js deleted file mode 100644 index 9dee7c17..00000000 --- a/test/js/promise_s22.js +++ /dev/null @@ -1,32 +0,0 @@ -var returnValue = null; -var value = {}; -var resolve; - -var thenable = new Promise(function(resolve) { - resolve(); -}); - -var promise = new Promise(function(_resolve) { - resolve = _resolve; -}); - -thenable.then = function(resolve) { - resolve(value); -}; - -promise.then( -function(val) { - if (val !== value) { - console.log('The promise should be fulfilled with the provided value.'); - return; - } - - console.log('Done'); -}, -function() { - console.log('The promise should not be rejected.'); -}); - -returnValue = resolve(thenable); - -console.log(returnValue == undefined); \ No newline at end of file diff --git a/test/js/promise_s22.t.js b/test/js/promise_s22.t.js new file mode 100644 index 00000000..a5907264 --- /dev/null +++ b/test/js/promise_s22.t.js @@ -0,0 +1,32 @@ +/*--- +includes: [] +flags: [async] +---*/ + +var returnValue = null; +var value = {}; +var resolve; + +var thenable = new Promise(function(resolve) { + resolve(); +}); + +var promise = new Promise(function(_resolve) { + resolve = _resolve; +}); + +thenable.then = function(resolve) { + resolve(value); +}; + +promise +.then( + v => { + assert.sameValue(v, value, 'The promise should be fulfilled with the provided value.'); + }, + e => $DONOTEVALUATE) +.then($DONE, $DONE); + +returnValue = resolve(thenable); + +assert.sameValue(returnValue, undefined); diff --git a/test/js/promise_s23.js b/test/js/promise_s23.js deleted file mode 100644 index 8525cdea..00000000 --- a/test/js/promise_s23.js +++ /dev/null @@ -1,28 +0,0 @@ -var returnValue = null; -var resolve; - -var promise = new Promise(function(_resolve) { - resolve = _resolve; -}); - -promise.then( -function() { - console.log('The promise should not be fulfilled.'); -}, -function(reason) { - if (!reason) { - console.log('The promise should be rejected with a value.'); - return; - } - - if (reason.constructor !== TypeError) { - console.log('The promise should be rejected with a TypeError instance.'); - return; - } - - console.log('Done'); -}); - -returnValue = resolve(promise); - -console.log(returnValue == undefined) \ No newline at end of file diff --git a/test/js/promise_s23.t.js b/test/js/promise_s23.t.js new file mode 100644 index 00000000..c9befa1f --- /dev/null +++ b/test/js/promise_s23.t.js @@ -0,0 +1,25 @@ +/*--- +includes: [] +flags: [async] +---*/ + +var returnValue = null; +var resolve; + +var promise = new Promise(function(_resolve) { + resolve = _resolve; +}); + +promise +.then( + v => $DONOTEVALUATE(), + e => { + + assert.sameValue(e.constructor, TypeError, + 'The promise should be rejected with a TypeError instance.'); +}) +.then($DONE, $DONE); + +returnValue = resolve(promise); + +assert.sameValue(returnValue, undefined); diff --git a/test/js/promise_s24.js b/test/js/promise_s24.t.js similarity index 65% rename from test/js/promise_s24.js rename to test/js/promise_s24.t.js index bb3dddff..f1e4a4ad 100644 --- a/test/js/promise_s24.js +++ b/test/js/promise_s24.t.js @@ -1,4 +1,9 @@ -var checkPoint = ''; +/*--- +includes: [] +flags: [] +---*/ + +let checkPoint = ''; Promise.reject.call(function(executor) { checkPoint += 'a'; @@ -10,4 +15,4 @@ Promise.reject.call(function(executor) { checkPoint += 'c'; }, {}); -console.log(checkPoint == 'abc'); \ No newline at end of file +assert.sameValue(checkPoint, 'abc'); diff --git a/test/js/promise_s25.js b/test/js/promise_s25.js deleted file mode 100644 index 3b70e46d..00000000 --- a/test/js/promise_s25.js +++ /dev/null @@ -1,29 +0,0 @@ -var resolve, reject; -var promise = new Promise(function(_resolve, _reject) { - resolve = _resolve; - reject = _reject; -}); - -var P = function(executor) { - executor(resolve, reject); - return promise; -}; - -Promise.resolve.call(P, promise) -.then( -function() { - console.log('The promise should not be fulfilled.'); -}, -function(value) { - if (!value) { - console.log('The promise should be rejected with a value.'); - return; - } - - if (value.constructor !== TypeError) { - console.log('The promise should be rejected with a TypeError instance.'); - return; - } - - console.log('Done'); -}); \ No newline at end of file diff --git a/test/js/promise_s25.t.js b/test/js/promise_s25.t.js new file mode 100644 index 00000000..8fe8b74e --- /dev/null +++ b/test/js/promise_s25.t.js @@ -0,0 +1,24 @@ +/*--- +includes: [] +flags: [async] +---*/ + +var resolve, reject; +var promise = new Promise(function(_resolve, _reject) { + resolve = _resolve; + reject = _reject; +}); + +var P = function(executor) { + executor(resolve, reject); + return promise; +}; + +Promise.resolve.call(P, promise) +.then( + v => $DONOTEVALUATE(), + e => { + assert.sameValue(e.constructor, TypeError, + 'The promise should be rejected with a TypeError instance.'); +}) +.then($DONE, $DONE); diff --git a/test/js/promise_s26.js b/test/js/promise_s26.js deleted file mode 100644 index f5244d33..00000000 --- a/test/js/promise_s26.js +++ /dev/null @@ -1,144 +0,0 @@ -var inherits = (child, parent) => { - child.prototype = Object.create(parent.prototype, { - constructor: { - value: child, - enumerable: false, - writable: true, - configurable: true - } - }); - Object.setPrototypeOf(child, parent); -}; - - -var BoxedPromise = (() => { - function BoxedPromise(executor) { - console.log('BoxedPromise.constructor'); - - if (!(this instanceof BoxedPromise)) { - return Promise(executor); - } - - if (typeof executor !== 'function') { - return new Promise(executor); - } - - var context, args; - var promise = new Promise(wrappedExecutor); - this.boxed = promise; - - try { - executor.apply(context, args); - - } catch (e) { - args[1](e); - } - - function wrappedExecutor(resolve, reject) { - context = this; - args = [wrappedResolve, wrappedReject]; - function wrappedResolve(val) { - return resolve(val); - } - function wrappedReject(val) { - return reject(val); - } - } - } - - inherits(BoxedPromise, Promise); - - BoxedPromise.prototype.then = function(res, rej) { - console.log('BoxedPromise.prototype.then'); - var rs = Object.create(Object.getPrototypeOf(this)); - rs.boxed = this.boxed.then(res, rej); - return rs; - }; - - return BoxedPromise; -})(); - - -var PatchedPromise = (() => { - function PatchedPromise(executor) { - console.log('PatchedPromise.constructor'); - - if (!(this instanceof PatchedPromise)) { - return Promise(executor); - } - - if (typeof executor !== 'function') { - return new Promise(executor); - } - - var context, args; - var promise = new Promise(wrappedExecutor); - Object.setPrototypeOf(promise, PatchedPromise.prototype); - - try { - executor.apply(context, args); - - } catch (e) { - args[1](e); - } - - return promise; - - function wrappedExecutor(resolve, reject) { - context = this; - args = [wrappedResolve, wrappedReject]; - function wrappedResolve(val) { - return resolve(val); - } - function wrappedReject(val) { - return reject(val); - } - } - } - - inherits(PatchedPromise, Promise); - - return PatchedPromise; -})(); - - -var testSubclass = (Class, name) => { - return new Promise((resolve) => { - var resolved = Class.resolve(name) - .then((x) => console.log('resolved', name)); - - console.log(name, 'resolve', resolved instanceof Class ? 'OK' : 'failed'); - - - var rejected = Class.reject(name) - .catch((x) => console.log('rejected', name)); - - console.log(name, 'reject', rejected instanceof Class ? 'OK' : 'failed'); - - - var instance = new Class((resolve) => { - setImmediate(() => resolve(name)); - }); - - var chain = instance - .then((x) => { console.log('then', x); return x; }) - .then((x) => { console.log('then', x); return x; }); - - console.log(name, 'chain', chain instanceof Class ? 'OK' : 'failed'); - - var fin = chain - .finally(() => console.log('finally', name)); - - console.log(name, 'finally', fin instanceof Class ? 'OK' : 'failed'); - - console.log(name, 'sync done\n'); - - fin - .then(() => console.log(name, 'async done\n')) - .then(resolve); - }); -}; - -Promise.resolve() - .then(() => testSubclass(BoxedPromise, 'BoxedPromise')) - .then(() => testSubclass(PatchedPromise, 'PatchedPromise')); diff --git a/test/js/promise_s26.t.js b/test/js/promise_s26.t.js new file mode 100644 index 00000000..499e520c --- /dev/null +++ b/test/js/promise_s26.t.js @@ -0,0 +1,211 @@ +/*--- +includes: [compareArray.js] +flags: [async] +---*/ + +let stages = []; + +var inherits = (child, parent) => { + child.prototype = Object.create(parent.prototype, { + constructor: { + value: child, + enumerable: false, + writable: true, + configurable: true + } + }); + Object.setPrototypeOf(child, parent); +}; + + +var BoxedPromise = (() => { + function BoxedPromise(executor) { + stages.push('BoxedPromise.constructor'); + + if (!(this instanceof BoxedPromise)) { + return Promise(executor); + } + + if (typeof executor !== 'function') { + return new Promise(executor); + } + + var context, args; + var promise = new Promise(wrappedExecutor); + this.boxed = promise; + + try { + executor.apply(context, args); + + } catch (e) { + args[1](e); + } + + function wrappedExecutor(resolve, reject) { + context = this; + args = [wrappedResolve, wrappedReject]; + function wrappedResolve(val) { + return resolve(val); + } + function wrappedReject(val) { + return reject(val); + } + } + } + + inherits(BoxedPromise, Promise); + + BoxedPromise.prototype.then = function(res, rej) { + stages.push('BoxedPromise.prototype.then'); + var rs = Object.create(Object.getPrototypeOf(this)); + rs.boxed = this.boxed.then(res, rej); + return rs; + }; + + return BoxedPromise; +})(); + + +var PatchedPromise = (() => { + function PatchedPromise(executor) { + stages.push('PatchedPromise.constructor'); + + if (!(this instanceof PatchedPromise)) { + return Promise(executor); + } + + if (typeof executor !== 'function') { + return new Promise(executor); + } + + var context, args; + var promise = new Promise(wrappedExecutor); + Object.setPrototypeOf(promise, PatchedPromise.prototype); + + try { + executor.apply(context, args); + + } catch (e) { + args[1](e); + } + + return promise; + + function wrappedExecutor(resolve, reject) { + context = this; + args = [wrappedResolve, wrappedReject]; + function wrappedResolve(val) { + return resolve(val); + } + function wrappedReject(val) { + return reject(val); + } + } + } + + inherits(PatchedPromise, Promise); + + return PatchedPromise; +})(); + + +var testSubclass = (Class, name) => { + return new Promise((resolve) => { + var resolved = Class.resolve(name) + .then((x) => stages.push(`resolved ${name}`)); + + stages.push(`${name} resolve ${resolved instanceof Class ? 'OK' : 'failed'}`); + + + var rejected = Class.reject(name) + .catch((x) => stages.push(`rejected ${name}`)); + + stages.push(`${name} reject ${rejected instanceof Class ? 'OK' : 'failed'}`); + + var instance = new Class((resolve) => { + setImmediate(() => resolve(name)); + }); + + var chain = instance + .then((x) => { stages.push(`then ${x}`); return x; }) + .then((x) => { stages.push(`then ${x}`); return x; }); + + stages.push(`${name} chain ${chain instanceof Class ? 'OK' : 'failed'}`); + + var fin = chain + .finally(() => stages.push(`finally ${name}`)); + + stages.push(`${name} finally ${fin instanceof Class ? 'OK' : 'failed'}`); + + stages.push(`${name} sync done`); + + fin + .then(() => stages.push(`${name} async done`)) + .then(resolve); + }); +}; + +Promise.resolve() +.then(() => testSubclass(BoxedPromise, 'BoxedPromise')) +.then(() => { + assert.compareArray(stages, [ + "BoxedPromise.constructor", + "BoxedPromise.prototype.then", + "BoxedPromise resolve OK", + "BoxedPromise.constructor", + "BoxedPromise.prototype.then", + "BoxedPromise reject OK", + "BoxedPromise.constructor", + "BoxedPromise.prototype.then", + "BoxedPromise.prototype.then", + "BoxedPromise chain OK", + "BoxedPromise.prototype.then", + "BoxedPromise finally OK", + "BoxedPromise sync done", + + "BoxedPromise.prototype.then", + "BoxedPromise.prototype.then", + "resolved BoxedPromise", + "rejected BoxedPromise", + "then BoxedPromise", + "then BoxedPromise", + "finally BoxedPromise", + "BoxedPromise.constructor", + "BoxedPromise.prototype.then", + "BoxedPromise.prototype.then", + "BoxedPromise async done", + ]); + stages = []; +}) +.then(() => testSubclass(PatchedPromise, 'PatchedPromise')) +.then(() => { + assert.compareArray(stages, [ + "PatchedPromise.constructor", + "PatchedPromise.constructor", + "PatchedPromise resolve OK", + "PatchedPromise.constructor", + "PatchedPromise.constructor", + "PatchedPromise reject OK", + "PatchedPromise.constructor", + "PatchedPromise.constructor", + "PatchedPromise.constructor", + "PatchedPromise chain OK", + "PatchedPromise.constructor", + "PatchedPromise finally OK", + "PatchedPromise sync done", + + "PatchedPromise.constructor", + "PatchedPromise.constructor", + "resolved PatchedPromise", + "rejected PatchedPromise", + "then PatchedPromise", + "then PatchedPromise", + "finally PatchedPromise", + "PatchedPromise.constructor", + "PatchedPromise.constructor", + "PatchedPromise.constructor", + "PatchedPromise async done", + ]); + stages = []; +}) +.then($DONE, $DONE); diff --git a/test/js/promise_s3.js b/test/js/promise_s3.js deleted file mode 100644 index 8e71fe3e..00000000 --- a/test/js/promise_s3.js +++ /dev/null @@ -1,11 +0,0 @@ - -var promise = new Promise(function(resolve, reject) { - console.log('One'); - reject(new Error('Blah')); -}); - -console.log('Two'); - -promise.then((response) => console.log(`Fulfilled: ${response}`), (error) => console.log(`Rejected: ${error}`)); - -console.log('Three'); \ No newline at end of file diff --git a/test/js/promise_s4.js b/test/js/promise_s4.js deleted file mode 100644 index ce52e6bd..00000000 --- a/test/js/promise_s4.js +++ /dev/null @@ -1,6 +0,0 @@ -Promise.reject(new Error('Oh my')).then(function(success) { -}, -function(error) { - console.log(error); - throw error; -}); \ No newline at end of file diff --git a/test/js/promise_s5.js b/test/js/promise_s5.js deleted file mode 100644 index 91995f94..00000000 --- a/test/js/promise_s5.js +++ /dev/null @@ -1,7 +0,0 @@ - -Promise.resolve('Success').then(function(value) { - console.log(value); -}, -function(value) { - console.log('ignored'); -}); \ No newline at end of file diff --git a/test/js/promise_s6.js b/test/js/promise_s6.js deleted file mode 100644 index 9451c6ec..00000000 --- a/test/js/promise_s6.js +++ /dev/null @@ -1,4 +0,0 @@ -var p = Promise.resolve([1,2,3]); -p.then(function(v) { - console.log(v[0]); -}); \ No newline at end of file diff --git a/test/js/promise_s7.js b/test/js/promise_s7.js deleted file mode 100644 index 5ecc378e..00000000 --- a/test/js/promise_s7.js +++ /dev/null @@ -1,12 +0,0 @@ -var p1 = Promise.resolve({ - then: function(onFulfill, onReject) { onFulfill('fulfilled!'); } -}); - -console.log(p1 instanceof Promise); - -p1.then(function(v) { - console.log(v); -}, -function(e) { - console.log('ignored'); -}); \ No newline at end of file diff --git a/test/js/promise_s8.js b/test/js/promise_s8.js deleted file mode 100644 index da87ff7c..00000000 --- a/test/js/promise_s8.js +++ /dev/null @@ -1,13 +0,0 @@ -var thenable = { - then: function(resolve) { - console.log('Ok') - resolve(); - } -}; - -function executor(resolve, reject) { - resolve(thenable); - throw new Error('ignored'); -} - -new Promise(executor).then(() => {}); \ No newline at end of file diff --git a/test/js/promise_s9.js b/test/js/promise_s9.js deleted file mode 100644 index 4c014bbe..00000000 --- a/test/js/promise_s9.js +++ /dev/null @@ -1,10 +0,0 @@ -var executorFunction; - -function NotPromise(executor) { - executorFunction = executor; - executor(function() {console.log('S')}, function() {console.log('R')}); -} - -Promise.resolve.call(NotPromise); - -console.log(Object.isExtensible(executorFunction)); \ No newline at end of file diff --git a/test/js/promise_set_timeout.js b/test/js/promise_set_timeout.t.js similarity index 63% rename from test/js/promise_set_timeout.js rename to test/js/promise_set_timeout.t.js index c0d365bd..fe908f13 100644 --- a/test/js/promise_set_timeout.js +++ b/test/js/promise_set_timeout.t.js @@ -1,3 +1,8 @@ +/*--- +includes: [compareArray.js] +flags: [] +---*/ + var res = []; function abc() { var promise = new Promise(function(resolve, reject) { @@ -7,11 +12,10 @@ function abc() { res.push('Two'); promise.then(() => {res.push('Four'); return {num: 'Five'}}) .then((obj) => {res.push(obj.num); return {num: 'Six'}}) - .then((obj) => {res.push(obj.num); return {num: 'Seven'}}) - .then((obj) => {res.push(obj.num); return {num: 'Eight'}}) .then((obj) => {res.push(obj.num)}); res.push('Three'); } + abc(); -console.log(res.join(',')); -setTimeout(() => console.log(res.join(',')), 0); +assert.compareArray(res, ['One', 'Two', 'Three']); +setTimeout(() => assert.compareArray(res, ['One', 'Two', 'Three', 'Four', 'Five', 'Six']), 0); diff --git a/test/js/promise_then_throw.js b/test/js/promise_then_throw.js deleted file mode 100644 index 0a14dfde..00000000 --- a/test/js/promise_then_throw.js +++ /dev/null @@ -1,2 +0,0 @@ -Promise.resolve() -.then(() => {nonExsisting()}); \ No newline at end of file diff --git a/test/js/promise_then_throw.t.js b/test/js/promise_then_throw.t.js new file mode 100644 index 00000000..a2e5761a --- /dev/null +++ b/test/js/promise_then_throw.t.js @@ -0,0 +1,9 @@ +/*--- +includes: [] +flags: [] +negative: + phase: runtime +---*/ + +Promise.resolve() +.then(() => {nonExsisting()}); diff --git a/test/js/promise_then_throw_catch.js b/test/js/promise_then_throw_catch.js deleted file mode 100644 index eee458bc..00000000 --- a/test/js/promise_then_throw_catch.js +++ /dev/null @@ -1,3 +0,0 @@ -Promise.resolve() -.then(() => {nonExsisting()}) -.catch(() => {console.log("Done")}); \ No newline at end of file diff --git a/test/js/promise_then_throw_catch.t.js b/test/js/promise_then_throw_catch.t.js new file mode 100644 index 00000000..afa1ca76 --- /dev/null +++ b/test/js/promise_then_throw_catch.t.js @@ -0,0 +1,12 @@ +/*--- +includes: [] +flags: [async] +---*/ + +let called = false; + +Promise.resolve() +.then(() => {nonExsisting()}) +.catch(() => {called = true;}) +.then(v => assert.sameValue(called, true)) +.then($DONE, $DONE); diff --git a/test/js/promise_then_throw_finally_catch.js b/test/js/promise_then_throw_finally_catch.js deleted file mode 100644 index 534154c2..00000000 --- a/test/js/promise_then_throw_finally_catch.js +++ /dev/null @@ -1,4 +0,0 @@ -Promise.resolve() -.then(() => {nonExsisting()}) -.finally(() => {}) -.catch(() => {console.log("Done")}); \ No newline at end of file diff --git a/test/js/promise_then_throw_finally_catch.t.js b/test/js/promise_then_throw_finally_catch.t.js new file mode 100644 index 00000000..4f00a398 --- /dev/null +++ b/test/js/promise_then_throw_finally_catch.t.js @@ -0,0 +1,13 @@ +/*--- +includes: [] +flags: [async] +---*/ + +let called = false; + +Promise.resolve() +.then(() => {nonExsisting()}) +.finally(() => {}) +.catch(() => {called = true;}) +.then(v => assert.sameValue(called, true)) +.then($DONE, $DONE); diff --git a/test/js/promise_two_first_then_throw.js b/test/js/promise_two_first_then_throw.t.js similarity index 65% rename from test/js/promise_two_first_then_throw.js rename to test/js/promise_two_first_then_throw.t.js index 2752287b..e2406c11 100644 --- a/test/js/promise_two_first_then_throw.js +++ b/test/js/promise_two_first_then_throw.t.js @@ -1,3 +1,10 @@ +/*--- +includes: [] +flags: [] +negative: + phase: runtime +---*/ + Promise.resolve() .then(() => {nonExsistingOne()}); diff --git a/test/js/promise_two_then_throw.js b/test/js/promise_two_then_throw.js deleted file mode 100644 index af0a00b3..00000000 --- a/test/js/promise_two_then_throw.js +++ /dev/null @@ -1,5 +0,0 @@ -Promise.resolve() -.then(() => {nonExsistingOne()}); - -Promise.resolve() -.then(() => {nonExsistingTwo()}); \ No newline at end of file diff --git a/test/js/promise_two_then_throw.t.js b/test/js/promise_two_then_throw.t.js new file mode 100644 index 00000000..f29bf1b9 --- /dev/null +++ b/test/js/promise_two_then_throw.t.js @@ -0,0 +1,12 @@ +/*--- +includes: [] +flags: [] +negative: + phase: runtime +---*/ + +Promise.resolve() +.then(() => {nonExsistingOne()}); + +Promise.resolve() +.then(() => {nonExsistingTwo()}); diff --git a/test/njs_expect_test.exp b/test/njs_expect_test.exp index 8d0a4a37..69d9cc8d 100644 --- a/test/njs_expect_test.exp +++ b/test/njs_expect_test.exp @@ -648,405 +648,3 @@ njs_test { # version njs_run {"-v"} "\\d+\.\\d+\.\\d+" - -# Promise - -njs_run {"./test/js/promise_set_timeout.js"} \ -"One,Two,Three -One,Two,Three,Four,Five,Six,Seven,Eight" - -njs_run {"./test/js/promise_s1.js"} \ -"One -Two -Three -123 -Four -Five -Six -Seven -Eight" - -njs_run {"./test/js/promise_s2.js"} \ -"One -Two -Three" - -njs_run {"./test/js/promise_s3.js"} \ -"One -Two -Three -Rejected: Error: Blah" - -njs_run {"./test/js/promise_s4.js"} \ -"Error: Oh my" - -njs_run {"./test/js/promise_s5.js"} \ -"Success" - -njs_run {"./test/js/promise_s6.js"} \ -"1" - -njs_run {"./test/js/promise_s7.js"} \ -"true -fulfilled!" - -njs_run {"./test/js/promise_s8.js"} \ -"Ok" - -njs_run {"./test/js/promise_s9.js"} \ -"S -true" - -njs_run {"./test/js/promise_s10.js"} \ -"One -Two -Three -Oh no" - -njs_run {"./test/js/promise_s11.js"} \ -"end -S: all -R: all" - -njs_run {"./test/js/promise_s12.js"} \ -"Done" - -njs_run {"./test/js/promise_s13.js"} \ -"Done" - -njs_run {"./test/js/promise_s14.js"} \ -"TypeError: oops - at anonymous \\\(promise_s14.js:5\\\) - at native \\\(native\\\) - at main \\\(promise_s14.js:9\\\) - -Done" - -njs_run {"./test/js/promise_s15.js"} \ -"Done" - -njs_run {"./test/js/promise_s16.js"} \ -"Done" - -njs_run {"./test/js/promise_s17.js"} \ -"Done" - -njs_run {"./test/js/promise_s18.js"} \ -"State 1 -State 2 -State 3 -State 4 -State 5 -Done" - -njs_run {"./test/js/promise_s19.js"} \ -"Throw! -undefined -Reject! -Done" - -njs_run {"./test/js/promise_s20.js"} \ -"true -Done" - -njs_run {"./test/js/promise_s21.js"} \ -"Done" - -njs_run {"./test/js/promise_s22.js"} \ -"true -Done" - -njs_run {"./test/js/promise_s23.js"} \ -"true -Done" - -njs_run {"./test/js/promise_s24.js"} \ -"true" - -njs_run {"./test/js/promise_s25.js"} \ -"Done" - -njs_run {"./test/js/promise_s26.js"} \ -"BoxedPromise.constructor -BoxedPromise.prototype.then -BoxedPromise resolve OK -BoxedPromise.constructor -BoxedPromise.prototype.then -BoxedPromise reject OK -BoxedPromise.constructor -BoxedPromise.prototype.then -BoxedPromise.prototype.then -BoxedPromise chain OK -BoxedPromise.prototype.then -BoxedPromise finally OK -BoxedPromise sync done - -BoxedPromise.prototype.then -BoxedPromise.prototype.then -resolved BoxedPromise -rejected BoxedPromise -then BoxedPromise -then BoxedPromise -finally BoxedPromise -BoxedPromise.constructor -BoxedPromise.prototype.then -BoxedPromise.prototype.then -BoxedPromise async done - -PatchedPromise.constructor -PatchedPromise.constructor -PatchedPromise resolve OK -PatchedPromise.constructor -PatchedPromise.constructor -PatchedPromise reject OK -PatchedPromise.constructor -PatchedPromise.constructor -PatchedPromise.constructor -PatchedPromise chain OK -PatchedPromise.constructor -PatchedPromise finally OK -PatchedPromise sync done - -PatchedPromise.constructor -PatchedPromise.constructor -resolved PatchedPromise -rejected PatchedPromise -then PatchedPromise -then PatchedPromise -finally PatchedPromise -PatchedPromise.constructor -PatchedPromise.constructor -PatchedPromise.constructor -PatchedPromise async done" - -# fs - -njs_run {"./test/fs/methods.js" "--match-exception-text"} \ -"fs readFile SUCCESS -fs readFileSync SUCCESS -fsp readFile SUCCESS -fs writeFile SUCCESS -fs writeFileSync SUCCESS -fsp writeFile SUCCESS -fs appendFile SUCCESS -fs appendFileSync SUCCESS -fsp appendFile SUCCESS -fs realpath SUCCESS -fs realpathSync SUCCESS -fsp realpath SUCCESS -fs stat SUCCESS -fs statSync SUCCESS -fsp stat SUCCESS -fs lstat SUCCESS -fs lstatSync SUCCESS -fsp lstat SUCCESS" - -njs_run {"./test/js/fs_promises_001.js"} \ -"init ok true -short circut ok true -chain ok true -error 1 ok true -error 2 ok true -errors ok" - -njs_run {"./test/js/fs_promises_002.js"} \ -"testSync ok true -testCallback ok true -testPromise ok true" - -njs_run {"./test/js/fs_promises_003.js"} \ -"test fs.unlinkSync -test fs.unlink -test fsp.unlink" - -njs_run {"./test/js/fs_promises_004.js"} \ -"test fs.symlinkSync -test fs.symlink -test fsp.symlink" - -njs_run {"./test/js/fs_promises_005.js"} \ -"test fs.mkdirSync -test fs.mkdir -test fsp.mkdir" - -njs_run {"./test/js/fs_promises_006.js"} \ -"test fs.renameSync -test fs.rename -test fsp.rename" - -njs_run {"./test/js/fs_promises_007.js"} \ -"test fs.readdirSync -test fs.readdir -test fsp.readdir" - -njs_run {"./test/js/fs_promises_008.js"} \ -"test recursive fs.mkdirSync" - -njs_run {"./test/js/fs_promises_009.js"} \ -"test recursive fs.rmdirSync" - -njs_run {"./test/js/promise_then_throw_finally_catch.js"} \ -"Done" - -njs_run {"./test/js/promise_catch_throw.js"} \ -"Error: unhandled promise rejection: ReferenceError: \"nonExsistingInCatch\" is not defined" - -njs_run {"./test/js/promise_then_throw.js"} \ -"Error: unhandled promise rejection: ReferenceError: \"nonExsisting\" is not defined" - -njs_run {"./test/js/promise_then_throw_catch.js"} \ -"Done" - -njs_run {"./test/js/promise_catch_then_throw_catch.js"} \ -"Done" - -njs_run {"./test/js/promise_finally.js"} \ -"here -Thrown: -Error: unhandled promise rejection: nope" - -njs_run {"./test/js/promise_finally_throw.js"} \ -"Error: unhandled promise rejection: ReferenceError: \"nonExsistingInFinally\" is not defined" - -njs_run {"./test/js/promise_finally_throw_catch.js"} \ -"Done" - -njs_run {"./test/js/promise_two_then_throw.js"} \ -"Error: unhandled promise rejection: ReferenceError: \"nonExsistingOne\" is not defined" - -njs_run {"./test/js/promise_two_first_then_throw.js"} \ -"Error: unhandled promise rejection: ReferenceError: \"nonExsistingOne\" is not defined" - -njs_run {"./test/js/promise_reject_catch.js"} \ -"rejected test" - -njs_run {"./test/js/promise_reject_post_catch.js"} \ -"Error: unhandled promise rejection: undefined" - -njs_run {"./test/js/promise_rejection_tracker.js"} \ -"Thrown: -Error: unhandled promise rejection: 1" - -njs_run {"./test/js/promise_all.js"} \ -"resolved:\\\[\\\['one','two'],\\\['three','four']]" - -njs_run {"./test/js/promise_all_throw.js"} \ -"rejected:foo" - -njs_run {"./test/js/promise_allSettled.js"} \ -"resolved:resolved:F:0,3,42,here|R:finally,finally after rejected,foo,here too,yes" - -njs_run {"./test/js/promise_allSettled_string.js"} \ -"resolved:F:a,b,c|R:" - -njs_run {"./test/js/promise_any.js"} \ -"resolved:4" - -njs_run {"./test/js/promise_any_all_rejected.js"} \ -"reject:AggregateError: All promises were rejected" - -njs_run {"./test/js/promise_race.js"} \ -"resolved:one" - -njs_run {"./test/js/promise_race_throw.js"} \ -"rejected:one" - -# Webcrypto - -njs_run {"./test/webcrypto/rsa_decoding.js" "--match-exception-text"} \ -"RSA-OAEP decoding SUCCESS" - -njs_run {"./test/webcrypto/rsa.js" "--match-exception-text"} \ -"RSA-OAEP encoding/decoding SUCCESS" - -njs_run {"./test/webcrypto/aes_decoding.js" "--match-exception-text"} \ -"AES decoding SUCCESS" - -njs_run {"./test/webcrypto/aes.js" "--match-exception-text"} \ -"AES encoding/decoding SUCCESS" - -njs_run {"./test/webcrypto/derive.js" "--match-exception-text"} \ -"derive SUCCESS" - -njs_run {"./test/webcrypto/digest.js" "--match-exception-text"} \ -"SHA digest SUCCESS" - -njs_run {"./test/webcrypto/sign.js" "--match-exception-text"} \ -"HMAC sign SUCCESS -RSASSA-PKCS1-v1_5 sign SUCCESS -RSA-PSS sign SUCCESS -ECDSA sign SUCCESS" - -njs_run {"./test/webcrypto/verify.js" "--match-exception-text"} \ -"HMAC verify SUCCESS -RSASSA-PKCS1-v1_5 verify SUCCESS -RSA-PSS verify SUCCESS -ECDSA verify SUCCESS" - -# Async/Await - -njs_run {"./test/js/async_await_inline.js"} \ -"70" - -njs_run {"./test/js/async_await_add.js"} \ -"110" - -njs_run {"./test/js/async_await_stages.js"} \ -"30 1, 2, 3, 4, 5" - -njs_run {"./test/js/async_await_for.js"} \ -"85 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, end" - -njs_run {"./test/js/async_await_blank.js"} \ -"12345" - -njs_run {"./test/js/async_await_reject.js"} \ -"Thrown: -Error: unhandled promise rejection: 50" - -njs_run {"./test/js/async_await_catch.js"} \ -"51" - -njs_run {"./test/js/async_await_finally.js"} \ -"51 -Thrown: -Error: unhandled promise rejection: 50" - -njs_run {"./test/js/async_await_throw.js"} \ -"Thrown: -Error: unhandled promise rejection: 50" - -njs_run {"./test/js/async_await_throw_catch.js"} \ -"110" - -njs_run {"./test/js/async_await_throw_async.js"} \ -"Thrown: -Error: unhandled promise rejection: 51" - -njs_run {"./test/js/async_await_throw_catch_async.js"} \ -"51" - -njs_run {"./test/js/async_await_try_catch.js"} \ -"reject -finally -end" - -njs_run {"./test/js/async_await_try_finally.js"} \ -"Thrown: -Error: unhandled promise rejection: finally reject" - -njs_run {"./test/js/async_await_try_throw.js"} \ -"finally -Thrown: -Error: unhandled promise rejection: try" - -njs_run {"./test/js/async_await_try_throw_catch.js"} \ -"try -finally -end" - -njs_run {"./test/js/async_await_try_resolve.js"} \ -"key: resolve" - -njs_run {"./test/js/async_await_many_call.js"} \ -"\\\['First: SUN MOON','Second: CAT MOUSE','Third: MAN WOMAN']" diff --git a/test/options b/test/options new file mode 100644 index 00000000..023fde0a --- /dev/null +++ b/test/options @@ -0,0 +1,61 @@ +#!/bin/sh + +# Copyright (C) Dmitry Volyntsev +# Copyright (C) NGINX, Inc. + +NJS_TEST_DIR=`mktemp -d /tmp/njs_test.XXX` +NJS_TEST_LOG_DEFAULT="$NJS_TEST_DIR/log.log" + +NJS_TEST_VERBOSE=${NJS_TEST_VERBOSE:-} +NJS_TEST_BINARY=${NJS_TEST_BINARY:-build/njs} +NJS_TEST_LOG=${NJS_TEST_LOG:-${NJS_TEST_LOG_DEFAULT}} + +for njs_option +do + case "$njs_option" in + -*=*) value=`echo "$njs_option" | sed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) value="" ;; + esac + + case "$njs_option" in + --binary=*) + NJS_TEST_BINARY="$value" + shift + ;; + + --log=*) + NJS_TEST_LOG="$value" + shift + ;; + + --test-dir=*) + NJS_TEST_DIR="$value" + shift + ;; + + --verbose=*) + NJS_TEST_VERBOSE="$value" + shift + ;; + + --help) + . test/help + exit 0 + ;; + + --*) + echo + echo $0: error: invalid option \"$njs_option\". + echo Run \"$0 --help\" to see available options. + echo + exit 1 + ;; + + *) + break + ;; + esac + +done + +NJS_TEST_PATHS=${@:-test} diff --git a/test/prepare b/test/prepare new file mode 100644 index 00000000..45adcfbd --- /dev/null +++ b/test/prepare @@ -0,0 +1,36 @@ +#!/bin/sh + +# Copyright (C) Dmitry Volyntsev +# Copyright (C) NGINX, Inc. + +njs_includes=`grep 'includes: \[[^]]*]' $njs_test \ + | sed -e 's/includes: \[//' | sed -e 's/,/ /g' | sed -e 's/\]//'` +njs_includes="assert.js sta.js $njs_includes" + +njs_flags=`grep 'flags: \[[^]]*]' $njs_test \ + | sed -e 's/flags: \[//' | sed -e 's/,/ /g' | sed -e 's/\]//'` + +njs_negative=`grep 'negative:' $njs_test > /dev/null \ + && grep 'phase: ' $njs_test | sed -e 's/ *phase: //' || true` + +njs_async=no +for flag in $njs_flags; do + case $flag in + async) + njs_async=yes + njs_includes="compatPrint.js doneprintHandle.js $njs_includes" + + ;; + esac +done + +njs_inc= +for file in $njs_includes; do + njs_inc="$njs_inc test/harness/$file" +done + +mkdir -p `dirname $NJS_TEST_DIR/$njs_test` + +cat $njs_inc $njs_test > $NJS_TEST_DIR/$njs_test + +njs_total=$((njs_total+1)) diff --git a/test/report b/test/report new file mode 100644 index 00000000..6aafe59b --- /dev/null +++ b/test/report @@ -0,0 +1,18 @@ +#!/bin/sh + +# Copyright (C) Dmitry Volyntsev +# Copyright (C) NGINX, Inc. + +NJS_STATUS="PASSED" +if [ $njs_passed -ne $njs_total ]; then + NJS_STATUS="FAILED" +fi + +if [ -n "$njs_failed_list" ]; then + for t in $njs_failed_list; do + printf "$t FAILED\n" + done +fi + +printf "TOTAL: $NJS_STATUS [$njs_passed/$njs_total]\n" +exit $(($njs_passed != $njs_total)) diff --git a/test/setup b/test/setup new file mode 100644 index 00000000..5760a9ff --- /dev/null +++ b/test/setup @@ -0,0 +1,39 @@ +#!/bin/sh + +# Copyright (C) Dmitry Volyntsev +# Copyright (C) NGINX, Inc. + +verbose() { + if [ -n "$NJS_TEST_VERBOSE" ]; then + printf "$1" + fi +} + +passed() { + verbose " PASSED\n" + njs_passed=$((njs_passed+1)) +} + +failed() { + njs_failed_list="$njs_failed_list $1" + verbose " FAILED\n" +} + +verbose "Test dir: $NJS_TEST_DIR\n" +verbose "Log file: $NJS_TEST_LOG\n" +verbose "\n" + +njs_passed=0 +njs_total=0 +njs_failed_list="" + +NJS_TESTS="" +for arg in $NJS_TEST_PATHS; do + if [ -d $arg ]; then + NJS_TESTS="$NJS_TESTS $(find $arg -name '*\.t\.js')" + else + NJS_TESTS="$NJS_TESTS $arg" + fi +done + +NJS_TESTS=`printf "%s\n" $NJS_TESTS | sort` diff --git a/test/test262 b/test/test262 new file mode 100755 index 00000000..56e16df1 --- /dev/null +++ b/test/test262 @@ -0,0 +1,64 @@ +#!/bin/sh + +# Copyright (C) Dmitry Volyntsev +# Copyright (C) NGINX, Inc. + +set -e + +. test/options +. test/setup + +for njs_test in $NJS_TESTS; do + . test/prepare + + njs_log="$NJS_TEST_DIR/${njs_test%.*}.log" + + verbose "$njs_test $njs_log" + cat << END >> $NJS_TEST_LOG +---------------------------------------- +running $njs_test $njs_log +END + + if /bin/sh -c "($NJS_TEST_BINARY $NJS_TEST_DIR/$njs_test)" > $njs_log 2>&1; then + njs_success=yes + else + njs_success=no + fi + + cat $njs_log >> $NJS_TEST_LOG + njs_out=`cat $njs_log` + + if [ $njs_success = yes ]; then + if [ -n "$njs_negative" ]; then + failed $njs_test + + elif [ $njs_async = yes ]; then + if [ "$njs_out" != 'Test262:AsyncTestComplete' ]; then + failed $njs_test + + else + passed $njs_test + fi + + else + if [ -n "$njs_out" ]; then + failed $njs_test + + else + passed $njs_test + fi + fi + + else + if [ -n "$njs_negative" ]; then + passed $njs_test + + else + failed $njs_test + fi + fi + +done + +. test/finalize +. test/report diff --git a/test/webcrypto/aes.js b/test/webcrypto/aes.t.js similarity index 77% rename from test/webcrypto/aes.js rename to test/webcrypto/aes.t.js index 85577fc9..ad08e35b 100644 --- a/test/webcrypto/aes.js +++ b/test/webcrypto/aes.t.js @@ -1,38 +1,26 @@ -if (typeof crypto == 'undefined') { - crypto = require('crypto').webcrypto; -} +/*--- +includes: [compatFs.js, compatBuffer.js, compatWebcrypto.js, runTsuite.js, webCryptoUtils.js] +flags: [async] +---*/ -async function run(tlist) { - function validate(t, r, i) { - if (r.status == "fulfilled" && !t[i].exception) { - return r.value === "SUCCESS"; - } +async function test(params) { + let dkey = await crypto.subtle.importKey("raw", params.key, + {name: params.name}, + false, ["decrypt"]); - if (r.status == "rejected" && t[i].exception) { - if (process.argv[2] === '--match-exception-text') { - /* is not compatible with node.js format */ - return r.reason.toString().startsWith(t[i].exception); - } + let ekey = await crypto.subtle.importKey("raw", params.key, + {name: params.name}, + false, ["encrypt"]); - return true; - } + let enc = await crypto.subtle.encrypt(params, ekey, params.data); + let plaintext = await crypto.subtle.decrypt(params, dkey, enc); + plaintext = Buffer.from(plaintext); - return false; + if (params.data.compare(plaintext) != 0) { + throw Error(`${params.name} encoding/decoding failed length ${data.length}`); } - for (let k = 0; k < tlist.length; k++) { - let ts = tlist[k]; - let results = await Promise.allSettled(ts.tests.map(t => ts.T(ts.prepare_args(t, ts.opts)))); - let r = results.map((r, i) => validate(ts.tests, r, i)); - - console.log(`${ts.name} ${r.every(v=>v == true) ? "SUCCESS" : "FAILED"}`); - - r.forEach((v, i) => { - if (!v) { - console.log(`FAILED ${i}: ${JSON.stringify(ts.tests[i])}\n with reason: ${results[i].reason}`); - } - }) - } + return 'SUCCESS'; } function p(args, default_opts) { @@ -55,28 +43,10 @@ function p(args, default_opts) { return params; } -async function test(params) { - let dkey = await crypto.subtle.importKey("raw", params.key, - {name: params.name}, - false, ["decrypt"]); - - let ekey = await crypto.subtle.importKey("raw", params.key, - {name: params.name}, - false, ["encrypt"]); - - let enc = await crypto.subtle.encrypt(params, ekey, params.data); - let plaintext = await crypto.subtle.decrypt(params, dkey, enc); - plaintext = Buffer.from(plaintext); - - if (params.data.compare(plaintext) != 0) { - throw Error(`${params.name} encoding/decoding failed length ${data.length}`); - } - - return 'SUCCESS'; -} let aes_tsuite = { name: "AES encoding/decoding", + skip: () => (!has_fs() || !has_buffer() || !has_webcrypto()), T: test, prepare_args: p, opts: { @@ -122,4 +92,5 @@ let aes_tsuite = { { name: "AES-CBC", data: "aabbccdd".repeat(5), iv: "ffffffffffffffffffffffffffffffff" }, ]}; -run([aes_tsuite]); +run([aes_tsuite]) +.then($DONE, $DONE); diff --git a/test/webcrypto/aes_decoding.js b/test/webcrypto/aes_decoding.t.js similarity index 69% rename from test/webcrypto/aes_decoding.js rename to test/webcrypto/aes_decoding.t.js index d518856a..c1aff369 100644 --- a/test/webcrypto/aes_decoding.js +++ b/test/webcrypto/aes_decoding.t.js @@ -1,45 +1,22 @@ -const fs = require('fs'); +/*--- +includes: [compatFs.js, compatBuffer.js, compatWebcrypto.js, runTsuite.js, webCryptoUtils.js] +flags: [async] +---*/ -if (typeof crypto == 'undefined') { - crypto = require('crypto').webcrypto; -} - -async function run(tlist) { - function validate(t, r, i) { - if (r.status == "fulfilled" && !t[i].exception) { - return r.value === "SUCCESS"; - } - - if (r.status == "rejected" && t[i].exception) { - if (process.argv[2] === '--match-exception-text') { - /* is not compatible with node.js format */ - return r.reason.toString().startsWith(t[i].exception); - } - - return true; - } - - return false; - } - - for (let k = 0; k < tlist.length; k++) { - let ts = tlist[k]; - let results = await Promise.allSettled(ts.tests.map(t => ts.T(ts.prepare_args(t, ts.opts)))); - let r = results.map((r, i) => validate(ts.tests, r, i)); +async function test(params) { + let enc = base64decode(fs.readFileSync(`test/webcrypto/${params.file}`)); + let key = await crypto.subtle.importKey("raw", params.key, + {name: params.name}, + false, ["decrypt"]); - console.log(`${ts.name} ${r.every(v=>v == true) ? "SUCCESS" : "FAILED"}`); + let plaintext = await crypto.subtle.decrypt(params, key, enc); + plaintext = new TextDecoder().decode(plaintext); - r.forEach((v, i) => { - if (!v) { - console.log(`FAILED ${i}: ${JSON.stringify(ts.tests[i])}\n with reason: ${results[i].reason}`); - } - }) + if (params.expected != plaintext) { + throw Error(`${params.name} decoding failed expected: "${params.expected}" vs "${plaintext}"`); } -} -function base64decode(b64) { - const joined = b64.toString().split('\n').join(''); - return Buffer.from(joined, 'base64'); + return 'SUCCESS'; } function p(args, default_opts) { @@ -61,24 +38,9 @@ function p(args, default_opts) { return params; } -async function test(params) { - let enc = base64decode(fs.readFileSync(`test/webcrypto/${params.file}`)); - let key = await crypto.subtle.importKey("raw", params.key, - {name: params.name}, - false, ["decrypt"]); - - let plaintext = await crypto.subtle.decrypt(params, key, enc); - plaintext = new TextDecoder().decode(plaintext); - - if (params.expected != plaintext) { - throw Error(`${params.name} decoding failed expected: "${params.expected}" vs "${plaintext}"`); - } - - return 'SUCCESS'; -} - let aes_tsuite = { name: "AES decoding", + skip: () => (!has_fs() || !has_buffer() || !has_webcrypto()), T: test, prepare_args: p, opts: { @@ -115,4 +77,5 @@ let aes_tsuite = { expected: "AES-CBC-256-SECRET-TEXT" }, ]}; -run([aes_tsuite]); +run([aes_tsuite]) +.then($DONE, $DONE); diff --git a/test/webcrypto/derive.js b/test/webcrypto/derive.t.js similarity index 70% rename from test/webcrypto/derive.js rename to test/webcrypto/derive.t.js index 8c87c013..60a21889 100644 --- a/test/webcrypto/derive.js +++ b/test/webcrypto/derive.t.js @@ -1,71 +1,7 @@ -if (typeof crypto == 'undefined') { - crypto = require('crypto').webcrypto; -} - -async function run(tlist) { - function validate(t, r, i) { - if (r.status == "fulfilled" && !t[i].exception) { - return r.value === "SUCCESS"; - } - - if (r.status == "rejected" && t[i].exception) { - if (process.argv[2] === '--match-exception-text') { - /* is not compatible with node.js format */ - return r.reason.toString().startsWith(t[i].exception); - } - - return true; - } - - if (r.status == "rejected" && t[i].optional) { - return r.reason.toString().startsWith("InternalError: not implemented"); - } - - return false; - } - - for (let k = 0; k < tlist.length; k++) { - let ts = tlist[k]; - let results = await Promise.allSettled(ts.tests.map(t => ts.T(ts.prepare_args(t, ts.opts)))); - let r = results.map((r, i) => validate(ts.tests, r, i)); - - console.log(`${ts.name} ${r.every(v=>v == true) ? "SUCCESS" : "FAILED"}`); - - r.forEach((v, i) => { - if (!v) { - console.log(`FAILED ${i}: ${JSON.stringify(ts.tests[i])}\n with reason: ${results[i].reason}`); - } - }) - } -} - -function merge(to, from) { - let r = Object.assign({}, to); - Object.keys(from).forEach(v => { - if (typeof r[v] == 'object' && typeof from[v] == 'object') { - r[v] = merge(r[v], from[v]); - - } else if (typeof from[v] == 'object') { - r[v] = Object.assign({}, from[v]); - - } else { - r[v] = from[v]; - } - }) - - return r; -}; - -function p(args, default_opts) { - let params = Object.assign({}, default_opts); - params = merge(params, args); - - params.algorithm.salt = Buffer.from(params.algorithm.salt, "hex"); - params.algorithm.info = Buffer.from(params.algorithm.info, "hex"); - params.derivedAlgorithm.iv = Buffer.from(params.derivedAlgorithm.iv, "hex"); - - return params; -} +/*--- +includes: [compatFs.js, compatBuffer.js, compatWebcrypto.js, runTsuite.js, webCryptoUtils.js] +flags: [async] +---*/ async function test(params) { let r; @@ -94,8 +30,20 @@ async function test(params) { return "SUCCESS"; } +function p(args, default_opts) { + let params = Object.assign({}, default_opts); + params = merge(params, args); + + params.algorithm.salt = Buffer.from(params.algorithm.salt, "hex"); + params.algorithm.info = Buffer.from(params.algorithm.info, "hex"); + params.derivedAlgorithm.iv = Buffer.from(params.derivedAlgorithm.iv, "hex"); + + return params; +} + let derive_tsuite = { name: "derive", + skip: () => (!has_fs() || !has_buffer() || !has_webcrypto()), T: test, prepare_args: p, opts: { @@ -148,4 +96,5 @@ let derive_tsuite = { expected: "e089c7491711306c69e077aa19fae6bfd2d4a6d240b0d37317d50472d7291a3e" }, ]}; -run([derive_tsuite]); +run([derive_tsuite]) +.then($DONE, $DONE); diff --git a/test/webcrypto/digest.js b/test/webcrypto/digest.t.js similarity index 69% rename from test/webcrypto/digest.js rename to test/webcrypto/digest.t.js index 77d6ad14..f6413348 100644 --- a/test/webcrypto/digest.js +++ b/test/webcrypto/digest.t.js @@ -1,45 +1,7 @@ -if (typeof crypto == 'undefined') { - crypto = require('crypto').webcrypto; -} - -async function run(tlist) { - function validate(t, r, i) { - if (r.status == "fulfilled" && !t[i].exception) { - return r.value === "SUCCESS"; - } - - if (r.status == "rejected" && t[i].exception) { - if (process.argv[2] === '--match-exception-text') { - /* is not compatible with node.js format */ - return r.reason.toString().startsWith(t[i].exception); - } - - return true; - } - - return false; - } - - for (let k = 0; k < tlist.length; k++) { - let ts = tlist[k]; - let results = await Promise.allSettled(ts.tests.map(t => ts.T(ts.prepare_args(t, ts.opts)))); - let r = results.map((r, i) => validate(ts.tests, r, i)); - - console.log(`${ts.name} ${r.every(v=>v == true) ? "SUCCESS" : "FAILED"}`); - - r.forEach((v, i) => { - if (!v) { - console.log(`FAILED ${i}: ${JSON.stringify(ts.tests[i])}\n with reason: ${results[i].reason}`); - } - }) - } -} - -function p(args) { - let params = Object.assign({}, args); - params.data = Buffer.from(params.data, "hex"); - return params; -} +/*--- +includes: [compatFs.js, compatBuffer.js, compatWebcrypto.js, runTsuite.js, webCryptoUtils.js] +flags: [async] +---*/ async function test(params) { let digest = await crypto.subtle.digest(params.name, params.data); @@ -52,8 +14,15 @@ async function test(params) { return 'SUCCESS'; } +function p(args) { + let params = Object.assign({}, args); + params.data = Buffer.from(params.data, "hex"); + return params; +} + let digest_tsuite = { name: "SHA digest", + skip: () => (!has_fs() || !has_buffer() || !has_webcrypto()), T: test, prepare_args: p, opts: { }, @@ -87,4 +56,5 @@ let digest_tsuite = { expected: "cdea58919606ea9ae078f7595b192b84446f2189" }, ]}; -run([digest_tsuite]); +run([digest_tsuite]) +.then($DONE, $DONE); diff --git a/test/webcrypto/rsa.js b/test/webcrypto/rsa.t.js similarity index 61% rename from test/webcrypto/rsa.js rename to test/webcrypto/rsa.t.js index 42d68d02..1e4c5409 100644 --- a/test/webcrypto/rsa.js +++ b/test/webcrypto/rsa.t.js @@ -1,57 +1,7 @@ -const fs = require('fs'); - -if (typeof crypto == 'undefined') { - crypto = require('crypto').webcrypto; -} - -async function run(tlist) { - function validate(t, r, i) { - if (r.status == "fulfilled" && !t[i].exception) { - return r.value === "SUCCESS"; - } - - if (r.status == "rejected" && t[i].exception) { - if (process.argv[2] === '--match-exception-text') { - /* is not compatible with node.js format */ - return r.reason.toString().startsWith(t[i].exception); - } - - return true; - } - - return false; - } - - for (let k = 0; k < tlist.length; k++) { - let ts = tlist[k]; - let results = await Promise.allSettled(ts.tests.map(t => ts.T(ts.prepare_args(t, ts.opts)))); - let r = results.map((r, i) => validate(ts.tests, r, i)); - - console.log(`${ts.name} ${r.every(v=>v == true) ? "SUCCESS" : "FAILED"}`); - - r.forEach((v, i) => { - if (!v) { - console.log(`FAILED ${i}: ${JSON.stringify(ts.tests[i])}\n with reason: ${results[i].reason}`); - } - }) - } -} - -function pem_to_der(pem, type) { - const pemJoined = pem.toString().split('\n').join(''); - const pemHeader = `-----BEGIN ${type} KEY-----`; - const pemFooter = `-----END ${type} KEY-----`; - const pemContents = pemJoined.substring(pemHeader.length, pemJoined.length - pemFooter.length); - return Buffer.from(pemContents, 'base64'); -} - -function p(args, default_opts) { - let params = Object.assign({}, default_opts, args); - - params.data = Buffer.from(params.data, "hex"); - - return params; -} +/*--- +includes: [compatFs.js, compatBuffer.js, compatWebcrypto.js, runTsuite.js, webCryptoUtils.js] +flags: [async] +---*/ async function test(params) { let spki = await crypto.subtle.importKey("spki", @@ -75,10 +25,19 @@ async function test(params) { } return 'SUCCESS'; -}; +} + +function p(args, default_opts) { + let params = Object.assign({}, default_opts, args); + + params.data = Buffer.from(params.data, "hex"); + + return params; +} let rsa_tsuite = { name: "RSA-OAEP encoding/decoding", + skip: () => (!has_fs() || !has_buffer() || !has_webcrypto()), T: test, prepare_args: p, opts: { @@ -105,4 +64,5 @@ let rsa_tsuite = { { data: "aabbcc", spki: "rsa2.spki", exception: "Error: EVP_PKEY_decrypt() failed" }, ]}; -run([rsa_tsuite]); +run([rsa_tsuite]) +.then($DONE, $DONE); diff --git a/test/webcrypto/rsa_decoding.js b/test/webcrypto/rsa_decoding.js deleted file mode 100644 index 4ebdd0fc..00000000 --- a/test/webcrypto/rsa_decoding.js +++ /dev/null @@ -1,83 +0,0 @@ -const fs = require('fs'); - -if (typeof crypto == 'undefined') { - crypto = require('crypto').webcrypto; -} - -async function run(tlist) { - function validate(t, r, i) { - if (r.status == "fulfilled" && !t[i].exception) { - return r.value === "SUCCESS"; - } - - if (r.status == "rejected" && t[i].exception) { - if (process.argv[2] === '--match-exception-text') { - /* is not compatible with node.js format */ - return r.reason.toString().startsWith(t[i].exception); - } - - return true; - } - - return false; - } - - for (let k = 0; k < tlist.length; k++) { - let ts = tlist[k]; - let results = await Promise.allSettled(ts.tests.map(t => ts.T(ts.prepare_args(t, ts.opts)))); - let r = results.map((r, i) => validate(ts.tests, r, i)); - - console.log(`${ts.name} ${r.every(v=>v == true) ? "SUCCESS" : "FAILED"}`); - - r.forEach((v, i) => { - if (!v) { - console.log(`FAILED ${i}: ${JSON.stringify(ts.tests[i])}\n with reason: ${results[i].reason}`); - } - }) - } -} - -function pem_to_der(pem) { - const pemJoined = pem.toString().split('\n').join(''); - const pemHeader = '-----BEGIN PRIVATE KEY-----'; - const pemFooter = '-----END PRIVATE KEY-----'; - const pemContents = pemJoined.substring(pemHeader.length, pemJoined.length - pemFooter.length); - return Buffer.from(pemContents, 'base64'); -} - -function base64decode(b64) { - const joined = b64.toString().split('\n').join(''); - return Buffer.from(joined, 'base64'); -} - -async function test(params) { - let pem = fs.readFileSync(`test/webcrypto/${params.pem}`); - let enc = base64decode(fs.readFileSync(`test/webcrypto/${params.src}`)); - - let key = await crypto.subtle.importKey("pkcs8", pem_to_der(pem), - {name:"RSA-OAEP", hash:"SHA-1"}, - false, ["decrypt"]); - - let plaintext = await crypto.subtle.decrypt({name: "RSA-OAEP"}, key, enc); - plaintext = new TextDecoder().decode(plaintext); - - if (params.expected != plaintext) { - throw Error(`RSA-OAEP decoding failed expected: "${params.expected}" vs "${plaintext}"`); - } - - return "SUCCESS"; -} - -let rsa_tsuite = { - name: "RSA-OAEP decoding", - T: test, - prepare_args: (v) => v, - opts: { }, - - tests: [ - { pem: "rsa.pkcs8", src: "text.base64.rsa-oaep.enc", expected: "WAKAWAKA" }, - { pem: "ec.pkcs8", src: "text.base64.rsa-oaep.enc", exception: "Error: RSA key is not found" }, - { pem: "rsa.pkcs8.broken", src: "text.base64.rsa-oaep.enc", exception: "Error: d2i_PKCS8_PRIV_KEY_INFO_bio() failed" }, -]}; - -run([rsa_tsuite]); diff --git a/test/webcrypto/rsa_decoding.t.js b/test/webcrypto/rsa_decoding.t.js new file mode 100644 index 00000000..3253daba --- /dev/null +++ b/test/webcrypto/rsa_decoding.t.js @@ -0,0 +1,41 @@ +/*--- +includes: [compatFs.js, compatBuffer.js, compatWebcrypto.js, runTsuite.js, webCryptoUtils.js] +flags: [async] +---*/ + +async function test(params) { + if (!has_fs() || !has_buffer() || !has_webcrypto()) { + return 'SKIPPED'; + } + + let pem = fs.readFileSync(`test/webcrypto/${params.pem}`); + let enc = base64decode(fs.readFileSync(`test/webcrypto/${params.src}`)); + + let key = await crypto.subtle.importKey("pkcs8", pem_to_der(pem, "PRIVATE"), + {name:"RSA-OAEP", hash:"SHA-1"}, + false, ["decrypt"]); + + let plaintext = await crypto.subtle.decrypt({name: "RSA-OAEP"}, key, enc); + plaintext = new TextDecoder().decode(plaintext); + + if (params.expected != plaintext) { + throw Error(`RSA-OAEP decoding failed expected: "${params.expected}" vs "${plaintext}"`); + } + + return "SUCCESS"; +} + +let rsa_tsuite = { + name: "RSA-OAEP decoding", + T: test, + prepare_args: (v) => v, + opts: { }, + + tests: [ + { pem: "rsa.pkcs8", src: "text.base64.rsa-oaep.enc", expected: "WAKAWAKA" }, + { pem: "ec.pkcs8", src: "text.base64.rsa-oaep.enc", exception: "Error: RSA key is not found" }, + { pem: "rsa.pkcs8.broken", src: "text.base64.rsa-oaep.enc", exception: "Error: d2i_PKCS8_PRIV_KEY_INFO_bio() failed" }, +]}; + +run([rsa_tsuite]) +.then($DONE, $DONE); diff --git a/test/webcrypto/sign.js b/test/webcrypto/sign.t.js similarity index 81% rename from test/webcrypto/sign.js rename to test/webcrypto/sign.t.js index 60f5fa77..d9eb3dc7 100644 --- a/test/webcrypto/sign.js +++ b/test/webcrypto/sign.t.js @@ -1,107 +1,7 @@ -const fs = require('fs'); -if (typeof crypto == 'undefined') { - crypto = require('crypto').webcrypto; -} - -async function run(tlist) { - function validate(t, r, i) { - if (r.status == "fulfilled" && !t[i].exception) { - return r.value === "SUCCESS"; - } - - if (r.status == "rejected" && t[i].exception) { - if (process.argv[2] === '--match-exception-text') { - /* is not compatible with node.js format */ - return r.reason.toString().startsWith(t[i].exception); - } - - return true; - } - - return false; - } - - for (let k = 0; k < tlist.length; k++) { - let ts = tlist[k]; - let results = await Promise.allSettled(ts.tests.map(t => ts.T(ts.prepare_args(t, ts.opts)))); - let r = results.map((r, i) => validate(ts.tests, r, i)); - - console.log(`${ts.name} ${r.every(v=>v == true) ? "SUCCESS" : "FAILED"}`); - - r.forEach((v, i) => { - if (!v) { - console.log(`FAILED ${i}: ${JSON.stringify(ts.tests[i])}\n with reason: ${results[i].reason}`); - } - }) - } -} - -function merge(to, from) { - let r = Object.assign({}, to); - Object.keys(from).forEach(v => { - if (typeof r[v] == 'object' && typeof from[v] == 'object') { - r[v] = merge(r[v], from[v]); - - } else if (typeof from[v] == 'object') { - r[v] = Object.assign({}, from[v]); - - } else { - r[v] = from[v]; - } - }) - - return r; -}; - -function pem_to_der(pem, type) { - const pemJoined = pem.toString().split('\n').join(''); - const pemHeader = `-----BEGIN ${type} KEY-----`; - const pemFooter = `-----END ${type} KEY-----`; - const pemContents = pemJoined.substring(pemHeader.length, pemJoined.length - pemFooter.length); - return Buffer.from(pemContents, 'base64'); -} - -function base64decode(b64) { - const joined = b64.toString().split('\n').join(''); - return Buffer.from(joined, 'base64'); -} - -function p(args, default_opts) { - let key; - let encoder = new TextEncoder(); - let params = merge({}, default_opts); - params = merge(params, args); - - switch (params.sign_key.fmt) { - case "pkcs8": - let pem = fs.readFileSync(`test/webcrypto/${params.sign_key.key}`); - key = pem_to_der(pem, "PRIVATE"); - break; - case "raw": - key = encoder.encode(params.sign_key.key); - break; - default: - throw Error("Unknown sign key format"); - } - - params.sign_key.key = key; - - switch (params.verify_key.fmt) { - case "spki": - let pem = fs.readFileSync(`test/webcrypto/${params.verify_key.key}`); - key = pem_to_der(pem, "PUBLIC"); - break; - case "raw": - key = encoder.encode(params.verify_key.key); - break; - default: - throw Error("Unknown verify key format"); - } - - params.verify_key.key = key; - - return params; -} +/*--- +includes: [compatFs.js, compatBuffer.js, compatWebcrypto.js, runTsuite.js, webCryptoUtils.js] +flags: [async] +---*/ async function test(params) { let encoder = new TextEncoder(); @@ -158,8 +58,46 @@ async function test(params) { return "SUCCESS"; } +function p(args, default_opts) { + let key; + let encoder = new TextEncoder(); + let params = merge({}, default_opts); + params = merge(params, args); + + switch (params.sign_key.fmt) { + case "pkcs8": + let pem = fs.readFileSync(`test/webcrypto/${params.sign_key.key}`); + key = pem_to_der(pem, "PRIVATE"); + break; + case "raw": + key = encoder.encode(params.sign_key.key); + break; + default: + throw Error("Unknown sign key format"); + } + + params.sign_key.key = key; + + switch (params.verify_key.fmt) { + case "spki": + let pem = fs.readFileSync(`test/webcrypto/${params.verify_key.key}`); + key = pem_to_der(pem, "PUBLIC"); + break; + case "raw": + key = encoder.encode(params.verify_key.key); + break; + default: + throw Error("Unknown verify key format"); + } + + params.verify_key.key = key; + + return params; +} + let hmac_tsuite = { name: "HMAC sign", + skip: () => (!has_fs() || !has_buffer() || !has_webcrypto()), T: test, prepare_args: p, opts: { @@ -195,6 +133,7 @@ let hmac_tsuite = { let rsassa_pkcs1_v1_5_tsuite = { name: "RSASSA-PKCS1-v1_5 sign", + skip: () => (!has_fs() || !has_buffer() || !has_webcrypto()), T: test, prepare_args: p, opts: { @@ -225,6 +164,7 @@ let rsassa_pkcs1_v1_5_tsuite = { let rsa_pss_tsuite = { name: "RSA-PSS sign", + skip: () => (!has_fs() || !has_buffer() || !has_webcrypto()), T: test, prepare_args: p, opts: { @@ -256,6 +196,7 @@ let rsa_pss_tsuite = { let ecdsa_tsuite = { name: "ECDSA sign", + skip: () => (!has_fs() || !has_buffer() || !has_webcrypto()), T: test, prepare_args: p, opts: { @@ -287,4 +228,5 @@ run([ rsassa_pkcs1_v1_5_tsuite, rsa_pss_tsuite, ecdsa_tsuite -]); +]) +.then($DONE, $DONE); diff --git a/test/webcrypto/verify.js b/test/webcrypto/verify.t.js similarity index 70% rename from test/webcrypto/verify.js rename to test/webcrypto/verify.t.js index 6ae24d02..b77f5c16 100644 --- a/test/webcrypto/verify.js +++ b/test/webcrypto/verify.t.js @@ -1,70 +1,23 @@ -const fs = require('fs'); +/*--- +includes: [compatFs.js, compatBuffer.js, compatWebcrypto.js, runTsuite.js, webCryptoUtils.js] +flags: [async] +---*/ -if (typeof crypto == 'undefined') { - crypto = require('crypto').webcrypto; -} - -async function run(tlist) { - function validate(t, r, i) { - if (r.status == "fulfilled" && !t[i].exception) { - return r.value === "SUCCESS"; - } - - if (r.status == "rejected" && t[i].exception) { - if (process.argv[2] === '--match-exception-text') { - /* is not compatible with node.js format */ - return r.reason.toString().startsWith(t[i].exception); - } - - return true; - } - - return false; - } - - for (let k = 0; k < tlist.length; k++) { - let ts = tlist[k]; - let results = await Promise.allSettled(ts.tests.map(t => ts.T(ts.prepare_args(t, ts.opts)))); - let r = results.map((r, i) => validate(ts.tests, r, i)); +async function test(params) { + let key = await crypto.subtle.importKey(params.key.fmt, + params.key.file, + params.import_alg, + false, ["verify"]); - console.log(`${ts.name} ${r.every(v=>v == true) ? "SUCCESS" : "FAILED"}`); + let r = await crypto.subtle.verify(params.verify_alg, + key, params.signature, + params.text); - r.forEach((v, i) => { - if (!v) { - console.log(`FAILED ${i}: ${JSON.stringify(ts.tests[i])}\n with reason: ${results[i].reason}`); - } - }) + if (params.expected !== r) { + throw Error(`${params.import_alg.name} failed expected: "${params.expected}" vs "${r}"`); } -} - -function merge(to, from) { - let r = Object.assign({}, to); - Object.keys(from).forEach(v => { - if (typeof r[v] == 'object' && typeof from[v] == 'object') { - r[v] = merge(r[v], from[v]); - - } else if (typeof from[v] == 'object') { - r[v] = Object.assign({}, from[v]); - - } else { - r[v] = from[v]; - } - }) - - return r; -}; -function base64decode(b64) { - const joined = b64.toString().split('\n').join(''); - return Buffer.from(joined, 'base64'); -} - -function pem_to_der(pem, type) { - const pemJoined = pem.toString().split('\n').join(''); - const pemHeader = `-----BEGIN ${type} KEY-----`; - const pemFooter = `-----END ${type} KEY-----`; - const pemContents = pemJoined.substring(pemHeader.length, pemJoined.length - pemFooter.length); - return Buffer.from(pemContents, 'base64'); + return 'SUCCESS'; } function p(args, default_opts) { @@ -88,26 +41,9 @@ function p(args, default_opts) { return params; } - -async function test(params) { - let key = await crypto.subtle.importKey(params.key.fmt, - params.key.file, - params.import_alg, - false, ["verify"]); - - let r = await crypto.subtle.verify(params.verify_alg, - key, params.signature, - params.text); - - if (params.expected !== r) { - throw Error(`${params.import_alg.name} failed expected: "${params.expected}" vs "${r}"`); - } - - return 'SUCCESS'; -} - let hmac_tsuite = { name: "HMAC verify", + skip: () => (!has_fs() || !has_buffer() || !has_webcrypto()), T: test, prepare_args: p, opts: { @@ -132,6 +68,7 @@ let hmac_tsuite = { let rsassa_pkcs1_v1_5_tsuite = { name: "RSASSA-PKCS1-v1_5 verify", + skip: () => (!has_fs() || !has_buffer() || !has_webcrypto()), T: test, prepare_args: p, opts: { @@ -156,6 +93,7 @@ let rsassa_pkcs1_v1_5_tsuite = { let rsa_pss_tsuite = { name: "RSA-PSS verify", + skip: () => (!has_fs() || !has_buffer() || !has_webcrypto()), T: test, prepare_args: p, opts: { @@ -185,6 +123,7 @@ let rsa_pss_tsuite = { let ecdsa_tsuite = { name: "ECDSA verify", + skip: () => (!has_fs() || !has_buffer() || !has_webcrypto()), T: test, prepare_args: p, opts: { @@ -212,4 +151,5 @@ run([ rsassa_pkcs1_v1_5_tsuite, rsa_pss_tsuite, ecdsa_tsuite, -]); +]) +.then($DONE, $DONE); -- 2.47.3