[njs] Tests: refactored JavaScript tests.

Dmitry Volyntsev xeioex at nginx.com
Mon Nov 29 16:52:08 UTC 2021


details:   https://hg.nginx.org/njs/rev/3b035831f64a
branches:  
changeset: 1753:3b035831f64a
user:      Dmitry Volyntsev <xeioex at 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() },


More information about the nginx-devel mailing list