details: https://hg.nginx.org/njs/rev/3b035831f64a branches: changeset: 1753:3b035831f64a user: Dmitry Volyntsev <xei...@nginx.com> date: Mon Nov 29 16:50:41 2021 +0000 description: 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. diffstat: auto/make | 6 +- test/finalize | 11 + test/fs/methods.js | 599 ------------------------- test/fs/methods.t.js | 610 ++++++++++++++++++++++++++ test/fs/promises_01.t.js | 42 + test/fs/promises_02.t.js | 78 +++ test/fs/promises_03.t.js | 104 ++++ test/fs/promises_04.t.js | 196 ++++++++ test/fs/promises_05.t.js | 141 ++++++ test/fs/promises_06.t.js | 105 ++++ test/fs/promises_07.t.js | 239 ++++++++++ test/fs/promises_08.t.js | 86 +++ test/fs/promises_09.t.js | 109 ++++ 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 + test/js/async_await_for.js | 23 - test/js/async_await_for.t.js | 31 + test/js/async_await_inline.js | 11 - test/js/async_await_inline.t.js | 18 + test/js/async_await_many_call.js | 30 - test/js/async_await_many_call.t.js | 35 + test/js/async_await_reject.js | 5 - test/js/async_await_reject.t.js | 15 + test/js/async_await_stages.js | 28 - test/js/async_await_stages.t.js | 36 + test/js/async_await_throw.js | 12 - test/js/async_await_throw.t.js | 22 + test/js/async_await_throw_async.js | 15 - test/js/async_await_throw_async.t.js | 25 + test/js/async_await_throw_catch.js | 12 - test/js/async_await_throw_catch.t.js | 20 + test/js/async_await_throw_catch_async.js | 15 - test/js/async_await_throw_catch_async.t.js | 25 + test/js/async_await_try_catch.js | 19 - test/js/async_await_try_catch.t.js | 30 + test/js/async_await_try_finally.js | 20 - test/js/async_await_try_finally.t.js | 32 + test/js/async_await_try_resolve.js | 15 - test/js/async_await_try_resolve.t.js | 23 + 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/fs_promises_002.js | 72 --- test/js/fs_promises_003.js | 108 ---- test/js/fs_promises_004.js | 200 -------- test/js/fs_promises_005.js | 143 ------ test/js/fs_promises_006.js | 104 ---- test/js/fs_promises_007.js | 241 ---------- test/js/fs_promises_008.js | 79 --- test/js/fs_promises_009.js | 106 ---- test/js/promise_all.js | 9 - test/js/promise_all.t.js | 16 + test/js/promise_allSettled.js | 20 - test/js/promise_allSettled.t.js | 26 + test/js/promise_allSettled_string.js | 10 - test/js/promise_allSettled_string.t.js | 16 + test/js/promise_all_throw.js | 9 - test/js/promise_all_throw.t.js | 15 + test/js/promise_any.js | 8 - test/js/promise_any.t.js | 14 + 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 + test/js/promise_race.js | 12 - test/js/promise_race.t.js | 18 + test/js/promise_race_throw.js | 12 - test/js/promise_race_throw.t.js | 18 + 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 | 23 - test/js/promise_s18.t.js | 32 + 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 | 30 - test/js/promise_s21.t.js | 32 + 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 | 13 - test/js/promise_s24.t.js | 18 + 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 - test/js/promise_set_timeout.js | 17 - test/js/promise_set_timeout.t.js | 21 + 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 + test/js/promise_two_first_then_throw.js | 6 - test/js/promise_two_first_then_throw.t.js | 13 + 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 | 125 ----- test/webcrypto/aes.t.js | 96 ++++ test/webcrypto/aes_decoding.js | 118 ----- test/webcrypto/aes_decoding.t.js | 81 +++ test/webcrypto/derive.js | 151 ------ test/webcrypto/derive.t.js | 100 ++++ test/webcrypto/digest.js | 90 --- test/webcrypto/digest.t.js | 60 ++ test/webcrypto/rsa.js | 108 ---- test/webcrypto/rsa.t.js | 68 ++ test/webcrypto/rsa_decoding.js | 83 --- test/webcrypto/rsa_decoding.t.js | 41 + test/webcrypto/sign.js | 290 ------------ test/webcrypto/sign.t.js | 232 +++++++++ test/webcrypto/verify.js | 215 --------- test/webcrypto/verify.t.js | 155 ++++++ 186 files changed, 4544 insertions(+), 4238 deletions(-) diffs (truncated from 9574 to 1000 lines): diff -r 144e430d0ed5 -r 3b035831f64a auto/make --- a/auto/make Mon Nov 29 14:41:09 2021 +0000 +++ b/auto/make Mon Nov 29 16:50:41 2021 +0000 @@ -209,12 +209,16 @@ lib_test: $NJS_BUILD_DIR/njs_auto_config $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 -r 144e430d0ed5 -r 3b035831f64a test/finalize --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/finalize Mon Nov 29 16:50:41 2021 +0000 @@ -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 -r 144e430d0ed5 -r 3b035831f64a test/fs/methods.js --- a/test/fs/methods.js Mon Nov 29 14:41:09 2021 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,599 +0,0 @@ -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}`); - } - }) - } -} - -function p(args, default_opts) { - let params = Object.assign({}, default_opts, args); - - let fname = params.args[0]; - - if (fname[0] == '@') { - let gen = `build/test/fs_test_${Math.round(Math.random() * 1000000)}`; - params.args = params.args.map(v => v); - params.args[0] = gen + fname.slice(1); - } - - return params; -} - -function promisify(f) { - return function (...args) { - return new Promise((resolve, reject) => { - function callback(err, result) { - if (err) { - return reject(err); - } else { - resolve(result); - } - } - - args.push(callback); - f.apply(this, args); - }); - }; -} - -async function method(name, params) { - let data = null; - - 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)); - } - - 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)); - }); - - 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)); - }); - - break; - } - - return data; -} - -async function read_test(params) { - let data = await method("readFile", params); - - if (params.slice) { - data = data.slice.apply(data, params.slice); - } - - 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`); - } - - return 'SUCCESS'; -} - -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/non_utf8", "utf8"], expected: "��" }, - { args: ["test/fs/non_utf8", {encoding: "hex"}], expected: "8080" }, - { args: ["test/fs/non_utf8", "base64"], expected: "gIA=" }, - { args: ["test/fs/ascii", "utf8"], expected: "x".repeat(600) }, - { args: ["test/fs/ascii", { encoding:"utf8", flags: "r+"}], expected: "x".repeat(600) }, - - { 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 }, -]; - -let readFile_tsuite = { - name: "fs readFile", - T: read_test, - prepare_args: p, - opts: { type: "callback" }, - tests: read_tests, -}; - -let readFileSync_tsuite = { - name: "fs readFileSync", - T: read_test, - prepare_args: p, - opts: { type: "sync" }, - tests: read_tests, -}; - -let readFileP_tsuite = { - name: "fsp readFile", - T: read_test, - prepare_args: p, - opts: { type: "promise" }, - tests: read_tests, -}; - -async function write_test(params) { - let fname = params.args[0]; - - try { fs.unlinkSync(fname); } catch (e) {} - - let data = await method("writeFile", params).catch(e => ({error:e})); - - if (!data) { - data = fs.readFileSync(fname); - } - - try { fs.unlinkSync(fname); } catch (e) {} - - if (params.check) { - if (!params.check(data, params)) { - throw Error(`writeFile failed check`); - } - - } else if (params.exception) { - throw data.error; - - } else { - if (data.compare(params.expected) != 0) { - throw Error(`writeFile unexpected data`); - } - } - - return 'SUCCESS'; -} - -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") }, - { args: ["@", Buffer.from("XYZ"), {encoding: "utf8", mode: 0o666}], - expected: Buffer.from("XYZ") }, - { args: ["@", new DataView(Buffer.alloc(3).fill(66).buffer)], - expected: Buffer.from("BBB") }, - { args: ["@", new Uint8Array(Buffer.from("ABCD"))], - expected: Buffer.from("ABCD")}, - { args: ["@", "XYZ"], expected: Buffer.from("XYZ")}, - { args: ["@", "78797a", "hex"], expected: Buffer.from("xyz") }, - { args: ["@", "eHl6", "base64"], expected: Buffer.from("xyz") }, - { args: ["@", "eHl6", {encoding: "base64url"}], expected: Buffer.from("xyz"), - optional: true }, - { args: ["@", Symbol("XYZ")], exception: "TypeError: Cannot convert a Symbol value to a string"}, - { args: ["/invalid_path", "XYZ"], - check: (err, params) => { - let e = err.error; - - if (e.syscall != 'open') { - throw Error(`${e.syscall} unexpected syscall`); - } - - if (e.code != "EACCES" && e.code != "EROFS") { - throw Error(`${e.code} unexpected code`); - } - - return true; - } }, -]; - -let writeFile_tsuite = { - name: "fs writeFile", - T: write_test, - prepare_args: p, - opts: { type: "callback" }, - tests: write_tests, -}; - -let writeFileSync_tsuite = { - name: "fs writeFileSync", - T: write_test, - prepare_args: p, - opts: { type: "sync" }, - tests: write_tests, -}; - -let writeFileP_tsuite = { - name: "fsp writeFile", - T: write_test, - prepare_args: p, - opts: { type: "promise" }, - tests: write_tests, -}; - -async function append_test(params) { - let fname = params.args[0]; - - try { fs.unlinkSync(fname); } catch (e) {} - - let data = await method("appendFile", params).catch(e => ({error:e})); - data = await method("appendFile", params).catch(e => ({error:e})); - - if (!data) { - data = fs.readFileSync(fname); - } - - try { fs.unlinkSync(fname); } catch (e) {} - - if (params.check) { - if (!params.check(data, params)) { - throw Error(`appendFile failed check`); - } - - } else if (params.exception) { - throw data.error; - - } else { - if (data.compare(params.expected) != 0) { - throw Error(`appendFile unexpected data`); - } - } - - return 'SUCCESS'; -} - -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") }, - { args: ["@", Buffer.from("XYZ"), {encoding: "utf8", mode: 0o666}], - expected: Buffer.from("XYZXYZ") }, - { args: ["@", new DataView(Buffer.alloc(3).fill(66).buffer)], - expected: Buffer.from("BBBBBB") }, - { args: ["@", new Uint8Array(Buffer.from("ABCD"))], - expected: Buffer.from("ABCDABCD")}, - { args: ["@", "XYZ"], expected: Buffer.from("XYZXYZ")}, - { args: ["@", "78797a", "hex"], expected: Buffer.from("xyzxyz") }, - { args: ["@", "eHl6", "base64"], expected: Buffer.from("xyzxyz") }, - { args: ["@", "eHl6", {encoding: "base64url"}], expected: Buffer.from("xyzxyz"), - optional: true }, - { args: ["@", Symbol("XYZ")], exception: "TypeError: Cannot convert a Symbol value to a string"}, - { args: ["/invalid_path", "XYZ"], - check: (err, params) => { - let e = err.error; - - if (e.syscall != 'open') { - throw Error(`${e.syscall} unexpected syscall`); - } - - if (e.code != "EACCES" && e.code != "EROFS") { - throw Error(`${e.code} unexpected code`); - } - - return true; - } }, -]; - -let appendFile_tsuite = { - name: "fs appendFile", - T: append_test, - prepare_args: p, - opts: { type: "callback" }, - tests: append_tests, -}; - -let appendFileSync_tsuite = { - name: "fs appendFileSync", - T: append_test, - prepare_args: p, - opts: { type: "sync" }, - tests: append_tests, -}; - -let appendFileP_tsuite = { - name: "fsp appendFile", - T: append_test, - prepare_args: p, - opts: { type: "promise" }, - tests: append_tests, -}; - -async function realpath_test(params) { - let data = await method("realpath", params); - - if (!params.check(data)) { - throw Error(`realpath failed check`); - } - - return 'SUCCESS'; -} - -let realpath_tests = [ - { args: ["./build/test/.."], - check: (data) => data.endsWith("build") }, - { args: ["./build/test/", {encoding:'buffer'}], - check: (data) => data instanceof Buffer }, -]; - -let realpath_tsuite = { - name: "fs realpath", - T: realpath_test, - prepare_args: p, - opts: { type: "callback" }, - tests: realpath_tests, -}; - -let realpathSync_tsuite = { - name: "fs realpathSync", - T: realpath_test, - prepare_args: p, - opts: { type: "sync" }, - tests: realpath_tests, -}; - -let realpathP_tsuite = { - name: "fsp realpath", - T: realpath_test, - prepare_args: p, - opts: { type: "promise" }, - tests: realpath_tests, -}; - -async function stat_test(params) { - if (params.init) { - params.init(params); - } - - let stat = await method(params.method, params).catch(e => ({error:e})); - - if (params.check && !params.check(stat, params)) { - throw Error(`${params.method} failed check`); - } - - return 'SUCCESS'; -} - -function contains(arr, elts) { - return elts.every(el => { - let r = arr.some(v => el == v); - - if (!r) { - throw Error(`${el} is not found`); - } - - return r; - }); -} - -let stat_tests = [ - { args: ["/invalid_path"], - check: (err, params) => { - let e = err.error; - - if (e.syscall != params.method) { - throw Error(`${e.syscall} unexpected syscall`); - } - - if (e.code != "ENOENT") { - throw Error(`${e.code} unexpected code`); - } - - return true; - } }, - - { args: ["@_link"], - init: (params) => { - let lname = params.args[0]; - let fname = lname.slice(0, -5); - - /* making symbolic link. */ - - try { fs.unlinkSync(fname); fs.unlinkSync(lname); } catch (e) {} - - fs.writeFileSync(fname, fname); - - fname = fs.realpathSync(fname); - fs.symlinkSync(fname, lname); - }, - - check: (st, params) => { - switch (params.method) { - case "stat": - if (!st.isFile()) { - throw Error(`${params.args[0]} is not a file`); - } - - break; - - case "lstat": - if (!st.isSymbolicLink()) { - throw Error(`${params.args[0]} is not a link`); - } - - break; - } - - return true; - } }, - - { 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/"], - check: (st) => Object.keys(st).every(p => { - let v = st[p]; - if (p == 'atime' || p == 'ctime' || p == 'mtime' || p == 'birthtime') { - if (!(v instanceof Date)) { - throw Error(`${p} is not an instance of Date`); - } - - return true; - } - - if ((typeof v) != 'number') { - throw Error(`${p} is not an instance of Number`); - } - - return true; - }) }, - - { args: ["./build/"], - check: (st) => ['atime', 'birthtime', 'ctime', 'mtime'].every(p => { - let date = st[p].valueOf(); - let num = st[p + 'Ms']; - - if (Math.abs(date - num) > 1) { - throw Error(`${p}:${date} != ${p+'Ms'}:${num}`); - } - - return true; - }) }, - - { args: ["./build/"], - check: (st) => ['isBlockDevice', - 'isCharacterDevice', - 'isDirectory', - 'isFIFO', - 'isFile', - 'isSocket', - 'isSymbolicLink'].every(m => { - - let r = st[m](); - if (!(r == (m == 'isDirectory'))) { - throw Error(`${m} is ${r}`); - } - - return true; - }) }, -]; - -let stat_tsuite = { - name: "fs stat", - T: stat_test, - prepare_args: p, - opts: { type: "callback", method: "stat" }, - tests: stat_tests, -}; - -let statSync_tsuite = { - name: "fs statSync", - T: stat_test, - prepare_args: p, - opts: { type: "sync", method: "stat" }, - tests: stat_tests, -}; - -let statP_tsuite = { - name: "fsp stat", - T: stat_test, - prepare_args: p, - opts: { type: "promise", method: "stat" }, - tests: stat_tests, -}; - -let lstat_tsuite = { - name: "fs lstat", - T: stat_test, - prepare_args: p, - opts: { type: "callback", method: "lstat" }, - tests: stat_tests, -}; - -let lstatSync_tsuite = { - name: "fs lstatSync", - T: stat_test, - prepare_args: p, - opts: { type: "sync", method: "lstat" }, - tests: stat_tests, -}; - -let lstatP_tsuite = { - name: "fsp lstat", - T: stat_test, - prepare_args: p, - opts: { type: "promise", method: "lstat" }, - tests: stat_tests, -}; - -run([ - readFile_tsuite, - readFileSync_tsuite, - readFileP_tsuite, - writeFile_tsuite, - writeFileSync_tsuite, - writeFileP_tsuite, - appendFile_tsuite, - appendFileSync_tsuite, - appendFileP_tsuite, - realpath_tsuite, - realpathSync_tsuite, - realpathP_tsuite, - stat_tsuite, - statSync_tsuite, - statP_tsuite, - lstat_tsuite, - lstatSync_tsuite, - lstatP_tsuite, -]); diff -r 144e430d0ed5 -r 3b035831f64a test/fs/methods.t.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/fs/methods.t.js Mon Nov 29 16:50:41 2021 +0000 @@ -0,0 +1,610 @@ +/*--- +includes: [compatFs.js, compatBuffer.js, runTsuite.js] +flags: [async] +---*/ + +function p(args, default_opts) { + let params = Object.assign({}, default_opts, args); + + let fname = params.args[0]; + + if (fname[0] == '@') { + let gen = `build/test/fs_test_${Math.round(Math.random() * 1000000)}`; + params.args = params.args.map(v => v); + params.args[0] = gen + fname.slice(1); + } + + return params; +} + +function promisify(f) { + return function (...args) { + return new Promise((resolve, reject) => { + function callback(err, result) { + if (err) { + return reject(err); + } else { + resolve(result); + } + } + + args.push(callback); + f.apply(this, args); + }); + }; +} + +async function method(name, params) { + let data = null; + + switch (params.type) { + case "sync": + data = fs[name + "Sync"].apply(null, params.args); + break; + + case "callback": + data = await promisify(fs[name]).apply(null, params.args); + break; + + case "promise": + data = await fs.promises[name].apply(null, params.args); + break; + } + + return data; +} + +async function read_test(params) { + let data = await method("readFile", params).catch(e => ({error:e})); + + if (params.slice && !data.error) { + data = data.slice.apply(data, params.slice); + } + + if (params.check) { + if (!params.check(data, params)) { + throw Error(`readFile failed check`); + } + + } 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`); + } + } + + return 'SUCCESS'; +} + +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"], + 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=" }, + { args: ["test/fs/ascii", "utf8"], expected: "x".repeat(600) }, + { args: ["test/fs/ascii", { encoding:"utf8", flags: "r+"}], expected: "x".repeat(600) }, + + { 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"), + 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" }, + 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" }, + 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" }, + get tests() { return read_tests() }, +}; + +async function write_test(params) { + let fname = params.args[0]; + + try { fs.unlinkSync(fname); } catch (e) {} + + let data = await method("writeFile", params).catch(e => ({error:e})); + + if (!data) { + data = fs.readFileSync(fname); + } + + try { fs.unlinkSync(fname); } catch (e) {} + + if (params.check) { + if (!params.check(data, params)) { + throw Error(`writeFile failed check`); + } + + } else if (params.exception) { + throw data.error; + + } else { + if (data.compare(params.expected) != 0) { + throw Error(`writeFile unexpected data`); + } + } + + return 'SUCCESS'; +} + +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") }, + { args: ["@", Buffer.from("XYZ"), {encoding: "utf8", mode: 0o666}], + expected: Buffer.from("XYZ") }, + { args: ["@", new DataView(Buffer.alloc(3).fill(66).buffer)], + expected: Buffer.from("BBB") }, + { args: ["@", new Uint8Array(Buffer.from("ABCD"))], + expected: Buffer.from("ABCD")}, + { args: ["@", "XYZ"], expected: Buffer.from("XYZ")}, + { args: ["@", "78797a", "hex"], expected: Buffer.from("xyz") }, + { args: ["@", "eHl6", "base64"], expected: Buffer.from("xyz") }, + { args: ["@", "eHl6", {encoding: "base64url"}], expected: Buffer.from("xyz"), + optional: true }, + { args: ["@", Symbol("XYZ")], exception: "TypeError: Cannot convert a Symbol value to a string"}, + { args: ["/invalid_path", "XYZ"], + check: (err, params) => { + let e = err.error; + + if (e.syscall != 'open') { + throw Error(`${e.syscall} unexpected syscall`); + } + + if (e.code != "EACCES" && e.code != "EROFS") { + throw Error(`${e.code} unexpected code`); + } + + return true; + } }, +]; + +let writeFile_tsuite = { + name: "fs writeFile", + skip: () => (!has_fs() || !has_buffer()), + T: write_test, + prepare_args: p, + opts: { type: "callback" }, + 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" }, + 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" }, + get tests() { return write_tests() }, +}; + +async function append_test(params) { + let fname = params.args[0]; + + try { fs.unlinkSync(fname); } catch (e) {} + + let data = await method("appendFile", params).catch(e => ({error:e})); + data = await method("appendFile", params).catch(e => ({error:e})); + + if (!data) { + data = fs.readFileSync(fname); + } + + try { fs.unlinkSync(fname); } catch (e) {} + + if (params.check) { + if (!params.check(data, params)) { + throw Error(`appendFile failed check`); + } + + } else if (params.exception) { + throw data.error; + + } else { + if (data.compare(params.expected) != 0) { + throw Error(`appendFile unexpected data`); + } + } + + return 'SUCCESS'; +} + +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") }, + { args: ["@", Buffer.from("XYZ"), {encoding: "utf8", mode: 0o666}], + expected: Buffer.from("XYZXYZ") }, + { args: ["@", new DataView(Buffer.alloc(3).fill(66).buffer)], + expected: Buffer.from("BBBBBB") }, + { args: ["@", new Uint8Array(Buffer.from("ABCD"))], + expected: Buffer.from("ABCDABCD")}, + { args: ["@", "XYZ"], expected: Buffer.from("XYZXYZ")}, + { args: ["@", "78797a", "hex"], expected: Buffer.from("xyzxyz") }, + { args: ["@", "eHl6", "base64"], expected: Buffer.from("xyzxyz") }, + { args: ["@", "eHl6", {encoding: "base64url"}], expected: Buffer.from("xyzxyz"), + optional: true }, + { args: ["@", Symbol("XYZ")], exception: "TypeError: Cannot convert a Symbol value to a string"}, + { args: ["/invalid_path", "XYZ"], + check: (err, params) => { + let e = err.error; + + if (e.syscall != 'open') { + throw Error(`${e.syscall} unexpected syscall`); + } + + if (e.code != "EACCES" && e.code != "EROFS") { + throw Error(`${e.code} unexpected code`); + } + + return true; + } }, +]; + +let appendFile_tsuite = { + name: "fs appendFile", + skip: () => (!has_fs() || !has_buffer()), + T: append_test, + prepare_args: p, + opts: { type: "callback" }, + 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" }, + 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" }, + get tests() { return append_tests() }, _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel