test_std.js (7283B)
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 (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],"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 "s":"str",} // trailing comma in objects and arrays 138 `; 139 obj = std.parseExtJSON(input); 140 assert(JSON.stringify(obj), expected); 141 } 142 143 function test_os() 144 { 145 var fd, fpath, fname, fdir, buf, buf2, i, files, err, fdate, st, link_path; 146 147 const stdinIsTTY = !os.exec(["/bin/sh", "-c", "test -t 0"], { usePath: false }); 148 149 assert(os.isatty(0), stdinIsTTY, `isatty(STDIN)`); 150 151 fdir = "test_tmp_dir"; 152 fname = "tmp_file.txt"; 153 fpath = fdir + "/" + fname; 154 link_path = fdir + "/test_link"; 155 156 os.remove(link_path); 157 os.remove(fpath); 158 os.remove(fdir); 159 160 err = os.mkdir(fdir, 0o755); 161 assert(err === 0); 162 163 fd = os.open(fpath, os.O_RDWR | os.O_CREAT | os.O_TRUNC); 164 assert(fd >= 0); 165 166 buf = new Uint8Array(10); 167 for(i = 0; i < buf.length; i++) 168 buf[i] = i; 169 assert(os.write(fd, buf.buffer, 0, buf.length) === buf.length); 170 171 assert(os.seek(fd, 0, std.SEEK_SET) === 0); 172 buf2 = new Uint8Array(buf.length); 173 assert(os.read(fd, buf2.buffer, 0, buf2.length) === buf2.length); 174 175 for(i = 0; i < buf.length; i++) 176 assert(buf[i] == buf2[i]); 177 178 if (typeof BigInt !== "undefined") { 179 assert(os.seek(fd, BigInt(6), std.SEEK_SET), BigInt(6)); 180 assert(os.read(fd, buf2.buffer, 0, 1) === 1); 181 assert(buf[6] == buf2[0]); 182 } 183 184 assert(os.close(fd) === 0); 185 186 [files, err] = os.readdir(fdir); 187 assert(err, 0); 188 assert(files.indexOf(fname) >= 0); 189 190 fdate = 10000; 191 192 err = os.utimes(fpath, fdate, fdate); 193 assert(err, 0); 194 195 [st, err] = os.stat(fpath); 196 assert(err, 0); 197 assert(st.mode & os.S_IFMT, os.S_IFREG); 198 assert(st.mtime, fdate); 199 200 err = os.symlink(fname, link_path); 201 assert(err === 0); 202 203 [st, err] = os.lstat(link_path); 204 assert(err, 0); 205 assert(st.mode & os.S_IFMT, os.S_IFLNK); 206 207 [buf, err] = os.readlink(link_path); 208 assert(err, 0); 209 assert(buf, fname); 210 211 assert(os.remove(link_path) === 0); 212 213 [buf, err] = os.getcwd(); 214 assert(err, 0); 215 216 [buf2, err] = os.realpath("."); 217 assert(err, 0); 218 219 assert(buf, buf2); 220 221 assert(os.remove(fpath) === 0); 222 223 fd = os.open(fpath, os.O_RDONLY); 224 assert(fd < 0); 225 226 assert(os.remove(fdir) === 0); 227 } 228 229 function test_os_exec() 230 { 231 var ret, fds, pid, f, status; 232 233 ret = os.exec(["true"]); 234 assert(ret, 0); 235 236 ret = os.exec(["/bin/sh", "-c", "exit 1"], { usePath: false }); 237 assert(ret, 1); 238 239 fds = os.pipe(); 240 pid = os.exec(["sh", "-c", "echo $FOO"], { 241 stdout: fds[1], 242 block: false, 243 env: { FOO: "hello" }, 244 } ); 245 assert(pid >= 0); 246 os.close(fds[1]); /* close the write end (as it is only in the child) */ 247 f = std.fdopen(fds[0], "r"); 248 assert(f.getline(), "hello"); 249 assert(f.getline(), null); 250 f.close(); 251 [ret, status] = os.waitpid(pid, 0); 252 assert(ret, pid); 253 assert(status & 0x7f, 0); /* exited */ 254 assert(status >> 8, 0); /* exit code */ 255 256 pid = os.exec(["cat"], { block: false } ); 257 assert(pid >= 0); 258 os.kill(pid, os.SIGTERM); 259 [ret, status] = os.waitpid(pid, 0); 260 assert(ret, pid); 261 assert(status !== 0, true, `expect nonzero exit code (got ${status})`); 262 assert(status & 0x7f, os.SIGTERM); 263 } 264 265 function test_timer() 266 { 267 var th, i; 268 269 /* just test that a timer can be inserted and removed */ 270 th = []; 271 for(i = 0; i < 3; i++) 272 th[i] = os.setTimeout(function () { }, 1000); 273 for(i = 0; i < 3; i++) 274 os.clearTimeout(th[i]); 275 } 276 277 /* test closure variable handling when freeing asynchronous 278 function */ 279 function test_async_gc() 280 { 281 (async function run () { 282 let obj = {} 283 284 let done = () => { 285 obj 286 std.gc(); 287 } 288 289 Promise.resolve().then(done) 290 291 const p = new Promise(() => {}) 292 293 await p 294 })(); 295 } 296 297 test_printf(); 298 test_file1(); 299 test_file2(); 300 test_getline(); 301 test_popen(); 302 test_os(); 303 test_os_exec(); 304 test_timer(); 305 test_ext_json(); 306 test_async_gc(); 307