| import * as std from "std"; |
| import * as os from "os"; |
| |
| function assert(actual, expected, message) { |
| if (arguments.length == 1) |
| expected = true; |
| |
| if (actual === expected) |
| return; |
| |
| if (actual !== null && expected !== null |
| && typeof actual == 'object' && typeof expected == 'object' |
| && actual.toString() === expected.toString()) |
| return; |
| |
| throw Error("assertion failed: got |" + actual + "|" + |
| ", expected |" + expected + "|" + |
| (message ? " (" + message + ")" : "")); |
| } |
| |
| // load more elaborate version of assert if available |
| try { std.loadScript("test_assert.js"); } catch(e) {} |
| |
| /*----------------*/ |
| |
| function test_printf() |
| { |
| assert(std.sprintf("a=%d s=%s", 123, "abc"), "a=123 s=abc"); |
| assert(std.sprintf("%010d", 123), "0000000123"); |
| assert(std.sprintf("%x", -2), "fffffffe"); |
| assert(std.sprintf("%lx", -2), "fffffffffffffffe"); |
| assert(std.sprintf("%10.1f", 2.1), " 2.1"); |
| assert(std.sprintf("%*.*f", 10, 2, -2.13), " -2.13"); |
| assert(std.sprintf("%#lx", 0x7fffffffffffffffn), "0x7fffffffffffffff"); |
| } |
| |
| function test_file1() |
| { |
| var f, len, str, size, buf, ret, i, str1; |
| |
| f = std.tmpfile(); |
| str = "hello world\n"; |
| f.puts(str); |
| |
| f.seek(0, std.SEEK_SET); |
| str1 = f.readAsString(); |
| assert(str1 === str); |
| |
| f.seek(0, std.SEEK_END); |
| size = f.tell(); |
| assert(size === str.length); |
| |
| f.seek(0, std.SEEK_SET); |
| |
| buf = new Uint8Array(size); |
| ret = f.read(buf.buffer, 0, size); |
| assert(ret === size); |
| for(i = 0; i < size; i++) |
| assert(buf[i] === str.charCodeAt(i)); |
| |
| f.close(); |
| } |
| |
| function test_file2() |
| { |
| var f, str, i, size; |
| f = std.tmpfile(); |
| str = "hello world\n"; |
| size = str.length; |
| for(i = 0; i < size; i++) |
| f.putByte(str.charCodeAt(i)); |
| f.seek(0, std.SEEK_SET); |
| for(i = 0; i < size; i++) { |
| assert(str.charCodeAt(i) === f.getByte()); |
| } |
| assert(f.getByte() === -1); |
| f.close(); |
| } |
| |
| function test_getline() |
| { |
| var f, line, line_count, lines, i; |
| |
| lines = ["hello world", "line 1", "line 2" ]; |
| f = std.tmpfile(); |
| for(i = 0; i < lines.length; i++) { |
| f.puts(lines[i], "\n"); |
| } |
| |
| f.seek(0, std.SEEK_SET); |
| assert(!f.eof()); |
| line_count = 0; |
| for(;;) { |
| line = f.getline(); |
| if (line === null) |
| break; |
| assert(line == lines[line_count]); |
| line_count++; |
| } |
| assert(f.eof()); |
| assert(line_count === lines.length); |
| |
| f.close(); |
| } |
| |
| function test_popen() |
| { |
| var str, f, fname = "tmp_file.txt"; |
| var content = "hello world"; |
| |
| f = std.open(fname, "w"); |
| f.puts(content); |
| f.close(); |
| |
| /* test loadFile */ |
| assert(std.loadFile(fname), content); |
| |
| /* execute the 'cat' shell command */ |
| f = std.popen("cat " + fname, "r"); |
| str = f.readAsString(); |
| f.close(); |
| |
| assert(str, content); |
| |
| os.remove(fname); |
| } |
| |
| function test_ext_json() |
| { |
| var expected, input, obj; |
| expected = '{"x":false,"y":true,"z2":null,"a":[1,8,160],"s":"str"}'; |
| input = `{ "x":false, /*comments are allowed */ |
| "y":true, // also a comment |
| z2:null, // unquoted property names |
| "a":[+1,0o10,0xa0,], // plus prefix, octal, hexadecimal |
| "s":"str",} // trailing comma in objects and arrays |
| `; |
| obj = std.parseExtJSON(input); |
| assert(JSON.stringify(obj), expected); |
| } |
| |
| function test_os() |
| { |
| var fd, fpath, fname, fdir, buf, buf2, i, files, err, fdate, st, link_path; |
| |
| assert(os.isatty(0)); |
| |
| fdir = "test_tmp_dir"; |
| fname = "tmp_file.txt"; |
| fpath = fdir + "/" + fname; |
| link_path = fdir + "/test_link"; |
| |
| os.remove(link_path); |
| os.remove(fpath); |
| os.remove(fdir); |
| |
| err = os.mkdir(fdir, 0o755); |
| assert(err === 0); |
| |
| fd = os.open(fpath, os.O_RDWR | os.O_CREAT | os.O_TRUNC); |
| assert(fd >= 0); |
| |
| buf = new Uint8Array(10); |
| for(i = 0; i < buf.length; i++) |
| buf[i] = i; |
| assert(os.write(fd, buf.buffer, 0, buf.length) === buf.length); |
| |
| assert(os.seek(fd, 0, std.SEEK_SET) === 0); |
| buf2 = new Uint8Array(buf.length); |
| assert(os.read(fd, buf2.buffer, 0, buf2.length) === buf2.length); |
| |
| for(i = 0; i < buf.length; i++) |
| assert(buf[i] == buf2[i]); |
| |
| if (typeof BigInt !== "undefined") { |
| assert(os.seek(fd, BigInt(6), std.SEEK_SET), BigInt(6)); |
| assert(os.read(fd, buf2.buffer, 0, 1) === 1); |
| assert(buf[6] == buf2[0]); |
| } |
| |
| assert(os.close(fd) === 0); |
| |
| [files, err] = os.readdir(fdir); |
| assert(err, 0); |
| assert(files.indexOf(fname) >= 0); |
| |
| fdate = 10000; |
| |
| err = os.utimes(fpath, fdate, fdate); |
| assert(err, 0); |
| |
| [st, err] = os.stat(fpath); |
| assert(err, 0); |
| assert(st.mode & os.S_IFMT, os.S_IFREG); |
| assert(st.mtime, fdate); |
| |
| err = os.symlink(fname, link_path); |
| assert(err === 0); |
| |
| [st, err] = os.lstat(link_path); |
| assert(err, 0); |
| assert(st.mode & os.S_IFMT, os.S_IFLNK); |
| |
| [buf, err] = os.readlink(link_path); |
| assert(err, 0); |
| assert(buf, fname); |
| |
| assert(os.remove(link_path) === 0); |
| |
| [buf, err] = os.getcwd(); |
| assert(err, 0); |
| |
| [buf2, err] = os.realpath("."); |
| assert(err, 0); |
| |
| assert(buf, buf2); |
| |
| assert(os.remove(fpath) === 0); |
| |
| fd = os.open(fpath, os.O_RDONLY); |
| assert(fd < 0); |
| |
| assert(os.remove(fdir) === 0); |
| } |
| |
| function test_os_exec() |
| { |
| var ret, fds, pid, f, status; |
| |
| ret = os.exec(["true"]); |
| assert(ret, 0); |
| |
| ret = os.exec(["/bin/sh", "-c", "exit 1"], { usePath: false }); |
| assert(ret, 1); |
| |
| fds = os.pipe(); |
| pid = os.exec(["sh", "-c", "echo $FOO"], { |
| stdout: fds[1], |
| block: false, |
| env: { FOO: "hello" }, |
| } ); |
| assert(pid >= 0); |
| os.close(fds[1]); /* close the write end (as it is only in the child) */ |
| f = std.fdopen(fds[0], "r"); |
| assert(f.getline(), "hello"); |
| assert(f.getline(), null); |
| f.close(); |
| [ret, status] = os.waitpid(pid, 0); |
| assert(ret, pid); |
| assert(status & 0x7f, 0); /* exited */ |
| assert(status >> 8, 0); /* exit code */ |
| |
| pid = os.exec(["cat"], { block: false } ); |
| assert(pid >= 0); |
| os.kill(pid, os.SIGQUIT); |
| [ret, status] = os.waitpid(pid, 0); |
| assert(ret, pid); |
| assert(status & 0x7f, os.SIGQUIT); |
| } |
| |
| function test_timer() |
| { |
| var th, i; |
| |
| /* just test that a timer can be inserted and removed */ |
| th = []; |
| for(i = 0; i < 3; i++) |
| th[i] = os.setTimeout(function () { }, 1000); |
| for(i = 0; i < 3; i++) |
| os.clearTimeout(th[i]); |
| } |
| |
| test_printf(); |
| test_file1(); |
| test_file2(); |
| test_getline(); |
| test_popen(); |
| test_os(); |
| test_os_exec(); |
| test_timer(); |
| test_ext_json(); |