quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

test_std.js (8197B)


      1 #! (shebang test)
      2 import * as std from "std";
      3 import * as os from "os";
      4 
      5 function assert(actual, expected, message) {
      6     if (arguments.length == 1)
      7         expected = true;
      8 
      9     if (Object.is(actual, expected))
     10         return;
     11 
     12     if (actual !== null && expected !== null
     13     &&  typeof actual == 'object' && typeof expected == 'object'
     14     &&  actual.toString() === expected.toString())
     15         return;
     16 
     17     throw Error("assertion failed: got |" + actual + "|" +
     18                 ", expected |" + expected + "|" +
     19                 (message ? " (" + message + ")" : ""));
     20 }
     21 
     22 // load more elaborate version of assert if available
     23 try { std.loadScript("test_assert.js"); } catch(e) {}
     24 
     25 /*----------------*/
     26 
     27 function test_printf()
     28 {
     29     assert(std.sprintf("a=%d s=%s", 123, "abc"), "a=123 s=abc");
     30     assert(std.sprintf("%010d", 123), "0000000123");
     31     assert(std.sprintf("%x", -2), "fffffffe");
     32     assert(std.sprintf("%lx", -2), "fffffffffffffffe");
     33     assert(std.sprintf("%10.1f", 2.1), "       2.1");
     34     assert(std.sprintf("%*.*f", 10, 2, -2.13), "     -2.13");
     35     assert(std.sprintf("%#lx", 0x7fffffffffffffffn), "0x7fffffffffffffff");
     36 }
     37 
     38 function test_file1()
     39 {
     40     var f, len, str, size, buf, ret, i, str1;
     41 
     42     f = std.tmpfile();
     43     str = "hello world\n";
     44     f.puts(str);
     45 
     46     f.seek(0, std.SEEK_SET);
     47     str1 = f.readAsString();
     48     assert(str1 === str);
     49 
     50     f.seek(0, std.SEEK_END);
     51     size = f.tell();
     52     assert(size === str.length);
     53 
     54     f.seek(0, std.SEEK_SET);
     55 
     56     buf = new Uint8Array(size);
     57     ret = f.read(buf.buffer, 0, size);
     58     assert(ret === size);
     59     for(i = 0; i < size; i++)
     60         assert(buf[i] === str.charCodeAt(i));
     61 
     62     f.close();
     63 }
     64 
     65 function test_file2()
     66 {
     67     var f, str, i, size;
     68     f = std.tmpfile();
     69     str = "hello world\n";
     70     size = str.length;
     71     for(i = 0; i < size; i++)
     72         f.putByte(str.charCodeAt(i));
     73     f.seek(0, std.SEEK_SET);
     74     for(i = 0; i < size; i++) {
     75         assert(str.charCodeAt(i) === f.getByte());
     76     }
     77     assert(f.getByte() === -1);
     78     f.close();
     79 }
     80 
     81 function test_getline()
     82 {
     83     var f, line, line_count, lines, i;
     84 
     85     lines = ["hello world", "line 1", "line 2" ];
     86     f = std.tmpfile();
     87     for(i = 0; i < lines.length; i++) {
     88         f.puts(lines[i], "\n");
     89     }
     90 
     91     f.seek(0, std.SEEK_SET);
     92     assert(!f.eof());
     93     line_count = 0;
     94     for(;;) {
     95         line = f.getline();
     96         if (line === null)
     97             break;
     98         assert(line == lines[line_count]);
     99         line_count++;
    100     }
    101     assert(f.eof());
    102     assert(line_count === lines.length);
    103 
    104     f.close();
    105 }
    106 
    107 function test_popen()
    108 {
    109     var str, f, fname = "tmp_file.txt";
    110     var content = "hello world";
    111 
    112     f = std.open(fname, "w");
    113     f.puts(content);
    114     f.close();
    115 
    116     /* test loadFile */
    117     assert(std.loadFile(fname), content);
    118 
    119     /* execute the 'cat' shell command */
    120     f = std.popen("cat " + fname, "r");
    121     str = f.readAsString();
    122     f.close();
    123 
    124     assert(str, content);
    125 
    126     os.remove(fname);
    127 }
    128 
    129 function test_ext_json()
    130 {
    131     var expected, input, obj;
    132     expected = '{"x":false,"y":true,"z2":null,"a":[1,8,160],"b":"abc\\u000bd","s":"str"}';
    133     input = `{ "x":false, /*comments are allowed */
    134                "y":true,  // also a comment
    135                z2:null, // unquoted property names
    136                "a":[+1,0o10,0xa0,], // plus prefix, octal, hexadecimal
    137                "b": "ab\
    138 c\\vd", // multi-line strings, '\v' escape
    139                "s":'str',} // trailing comma in objects and arrays, single quoted string
    140             `;
    141     obj = std.parseExtJSON(input);
    142     assert(JSON.stringify(obj), expected);
    143 
    144     obj = std.parseExtJSON('[Infinity, +Infinity, -Infinity, NaN, +NaN, -NaN, .1, -.2]');
    145     assert(obj[0], Infinity);
    146     assert(obj[1], Infinity);
    147     assert(obj[2], -Infinity);
    148     assert(obj[3], NaN);
    149     assert(obj[4], NaN);
    150     assert(obj[5], NaN);
    151     assert(obj[6], 0.1);
    152     assert(obj[7], -0.2);
    153 }
    154 
    155 function test_os()
    156 {
    157     var fd, fpath, fname, fdir, buf, buf2, i, files, err, fdate, st, link_path;
    158 
    159     const stdinIsTTY = !os.exec(["/bin/sh", "-c", "test -t 0"], { usePath: false });
    160 
    161     assert(os.isatty(0), stdinIsTTY, `isatty(STDIN)`);
    162 
    163     fdir = "test_tmp_dir";
    164     fname = "tmp_file.txt";
    165     fpath = fdir + "/" + fname;
    166     link_path = fdir + "/test_link";
    167 
    168     os.remove(link_path);
    169     os.remove(fpath);
    170     os.remove(fdir);
    171 
    172     err = os.mkdir(fdir, 0o755);
    173     assert(err === 0);
    174 
    175     fd = os.open(fpath, os.O_RDWR | os.O_CREAT | os.O_TRUNC);
    176     assert(fd >= 0);
    177 
    178     buf = new Uint8Array(10);
    179     for(i = 0; i < buf.length; i++)
    180         buf[i] = i;
    181     assert(os.write(fd, buf.buffer, 0, buf.length) === buf.length);
    182 
    183     assert(os.seek(fd, 0, std.SEEK_SET) === 0);
    184     buf2 = new Uint8Array(buf.length);
    185     assert(os.read(fd, buf2.buffer, 0, buf2.length) === buf2.length);
    186 
    187     for(i = 0; i < buf.length; i++)
    188         assert(buf[i] == buf2[i]);
    189 
    190     if (typeof BigInt !== "undefined") {
    191         assert(os.seek(fd, BigInt(6), std.SEEK_SET), BigInt(6));
    192         assert(os.read(fd, buf2.buffer, 0, 1) === 1);
    193         assert(buf[6] == buf2[0]);
    194     }
    195 
    196     assert(os.close(fd) === 0);
    197 
    198     [files, err] = os.readdir(fdir);
    199     assert(err, 0);
    200     assert(files.indexOf(fname) >= 0);
    201 
    202     fdate = 10000;
    203 
    204     err = os.utimes(fpath, fdate, fdate);
    205     assert(err, 0);
    206 
    207     [st, err] = os.stat(fpath);
    208     assert(err, 0);
    209     assert(st.mode & os.S_IFMT, os.S_IFREG);
    210     assert(st.mtime, fdate);
    211 
    212     err = os.symlink(fname, link_path);
    213     assert(err === 0);
    214 
    215     [st, err] = os.lstat(link_path);
    216     assert(err, 0);
    217     assert(st.mode & os.S_IFMT, os.S_IFLNK);
    218 
    219     [buf, err] = os.readlink(link_path);
    220     assert(err, 0);
    221     assert(buf, fname);
    222 
    223     assert(os.remove(link_path) === 0);
    224 
    225     [buf, err] = os.getcwd();
    226     assert(err, 0);
    227 
    228     [buf2, err] = os.realpath(".");
    229     assert(err, 0);
    230 
    231     assert(buf, buf2);
    232 
    233     assert(os.remove(fpath) === 0);
    234 
    235     fd = os.open(fpath, os.O_RDONLY);
    236     assert(fd < 0);
    237 
    238     assert(os.remove(fdir) === 0);
    239 }
    240 
    241 function test_os_exec()
    242 {
    243     var ret, fds, pid, f, status;
    244 
    245     ret = os.exec(["true"]);
    246     assert(ret, 0);
    247 
    248     ret = os.exec(["/bin/sh", "-c", "exit 1"], { usePath: false });
    249     assert(ret, 1);
    250 
    251     fds = os.pipe();
    252     pid = os.exec(["sh", "-c", "echo $FOO"], {
    253         stdout: fds[1],
    254         block: false,
    255         env: { FOO: "hello" },
    256     } );
    257     assert(pid >= 0);
    258     os.close(fds[1]); /* close the write end (as it is only in the child)  */
    259     f = std.fdopen(fds[0], "r");
    260     assert(f.getline(), "hello");
    261     assert(f.getline(), null);
    262     f.close();
    263     [ret, status] = os.waitpid(pid, 0);
    264     assert(ret, pid);
    265     assert(status & 0x7f, 0); /* exited */
    266     assert(status >> 8, 0); /* exit code */
    267 
    268     pid = os.exec(["cat"], { block: false } );
    269     assert(pid >= 0);
    270     os.kill(pid, os.SIGTERM);
    271     [ret, status] = os.waitpid(pid, 0);
    272     assert(ret, pid);
    273     assert(status !== 0, true, `expect nonzero exit code (got ${status})`);
    274     assert(status & 0x7f, os.SIGTERM);
    275 }
    276 
    277 function test_timer()
    278 {
    279     var th, i;
    280 
    281     /* just test that a timer can be inserted and removed */
    282     th = [];
    283     for(i = 0; i < 3; i++)
    284         th[i] = os.setTimeout(function () { }, 1000);
    285     for(i = 0; i < 3; i++)
    286         os.clearTimeout(th[i]);
    287 }
    288 
    289 /* test closure variable handling when freeing asynchronous
    290    function */
    291 function test_async_gc()
    292 {
    293     (async function run () {
    294         let obj = {}
    295 
    296         let done = () => {
    297             obj
    298             std.gc();
    299         }
    300 
    301         Promise.resolve().then(done)
    302 
    303         const p = new Promise(() => {})
    304 
    305         await p
    306     })();
    307 }
    308 
    309 /* check that the promise async rejection handler is not invoked when
    310    the rejection is handled not too late after the promise
    311    rejection. */
    312 function test_async_promise_rejection()
    313 {
    314     var counter = 0;
    315     var p1, p2, p3;
    316     p1 = Promise.reject();
    317     p2 = Promise.reject();
    318     p3 = Promise.resolve();
    319     p1.catch(() => counter++);
    320     p2.catch(() => counter++);
    321     p3.then(() => counter++)
    322     os.setTimeout(() => { assert(counter, 3) }, 10);
    323 }
    324 
    325 test_printf();
    326 test_file1();
    327 test_file2();
    328 test_getline();
    329 test_popen();
    330 test_os();
    331 test_os_exec();
    332 test_timer();
    333 test_ext_json();
    334 test_async_gc();
    335 test_async_promise_rejection();
    336