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