fetch_network.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. #!/usr/bin/env node
  2. "use strict";
  3. process.on("unhandledRejection", exn => { throw exn; });
  4. const TEST_RELEASE_BUILD = +process.env.TEST_RELEASE_BUILD;
  5. const V86 = require(`../../build/${TEST_RELEASE_BUILD ? "libv86" : "libv86-debug"}.js`).V86;
  6. const assert = require("assert").strict;
  7. const SHOW_LOGS = false;
  8. const STOP_ON_FIRST_FAILURE = false;
  9. function log_pass(msg, ...args)
  10. {
  11. console.log(`\x1b[92m[+] ${msg}\x1b[0m`, ...args);
  12. }
  13. function log_warn(msg, ...args)
  14. {
  15. console.error(`\x1b[93m[!] ${msg}\x1b[0m`, ...args);
  16. }
  17. function log_fail(msg, ...args)
  18. {
  19. console.error(`\x1b[91m[-] ${msg}\x1b[0m`, ...args);
  20. }
  21. const tests =
  22. [
  23. {
  24. name: "DHCP",
  25. timeout: 60,
  26. start: () =>
  27. {
  28. emulator.serial0_send("udhcpc\n");
  29. emulator.serial0_send("echo -e done\\\\tudhcpc\n");
  30. },
  31. end_trigger: "done\tudhcpc",
  32. end: (capture) =>
  33. {
  34. assert(/lease of 192.168.86.100 obtained/.test(capture), "lease of 192.168.86.100 obtained");
  35. },
  36. },
  37. {
  38. name: "ifconfig",
  39. timeout: 60,
  40. start: () =>
  41. {
  42. emulator.serial0_send("ifconfig\n");
  43. emulator.serial0_send("echo -e done\\\\tifconfig\n");
  44. },
  45. end_trigger: "done\tifconfig",
  46. end: (capture) =>
  47. {
  48. assert(/192.168.86.100/.test(capture), "192.168.86.100");
  49. },
  50. },
  51. {
  52. name: "route",
  53. timeout: 60,
  54. start: () =>
  55. {
  56. emulator.serial0_send("ip route\n");
  57. emulator.serial0_send("echo -e done\\\\troute\n");
  58. },
  59. end_trigger: "done\troute",
  60. end: (capture) =>
  61. {
  62. assert(/192.168.86.1/.test(capture), "192.168.86.100");
  63. },
  64. },
  65. {
  66. name: "ping 1.2.3.4",
  67. timeout: 60,
  68. start: () =>
  69. {
  70. emulator.serial0_send("ping -c 2 1.2.3.4\n");
  71. emulator.serial0_send("echo -e done\\\\tping\n");
  72. },
  73. end_trigger: "done\tping",
  74. end: (capture) =>
  75. {
  76. assert(/2 packets transmitted, 2 packets received, 0% packet loss/.test(capture), "2 packets transmitted, 2 packets received, 0% packet loss");
  77. },
  78. },
  79. {
  80. name: "arp -a",
  81. timeout: 60,
  82. start: () =>
  83. {
  84. emulator.serial0_send("arp -a\n");
  85. emulator.serial0_send("echo -e done\\\\tarp\n");
  86. },
  87. end_trigger: "done\tarp",
  88. end: (capture) =>
  89. {
  90. assert(/.192.168.86.1. at 52:54:00:01:02:03 \[ether\] {2}on eth0/.test(capture), "(192.168.86.1) at 52:54:00:01:02:03 [ether] on eth0");
  91. },
  92. },
  93. {
  94. name: "Curl mocked.example.org",
  95. timeout: 60,
  96. allow_failure: true,
  97. start: () =>
  98. {
  99. emulator.serial0_send("wget -T 10 -O - mocked.example.org\n");
  100. emulator.serial0_send("echo -e done\\\\tmocked.example.org\n");
  101. },
  102. end_trigger: "done\tmocked.example.org",
  103. end: (capture) =>
  104. {
  105. assert(/This text is from the mock/.test(capture), "got mocked.example.org text");
  106. },
  107. },
  108. {
  109. name: "Curl example.org",
  110. timeout: 60,
  111. allow_failure: true,
  112. start: () =>
  113. {
  114. emulator.serial0_send("wget -T 10 -O - example.org\n");
  115. emulator.serial0_send("echo -e done\\\\texample.org\n");
  116. },
  117. end_trigger: "done\texample.org",
  118. end: (capture) =>
  119. {
  120. assert(/This domain is for use in illustrative examples in documents/.test(capture), "got example.org text");
  121. },
  122. },
  123. ];
  124. let test_num = 0;
  125. let test_timeout = 0;
  126. const failed_tests = [];
  127. const emulator = new V86({
  128. bios: { url: __dirname + "/../../bios/seabios.bin" },
  129. vga_bios: { url: __dirname + "/../../bios/vgabios.bin" },
  130. cdrom: { url: __dirname + "/../../images/linux4.iso" },
  131. autostart: true,
  132. memory_size: 64 * 1024 * 1024,
  133. disable_jit: +process.env.DISABLE_JIT,
  134. network_relay_url: "fetch",
  135. log_level: SHOW_LOGS ? 0x400000 : 0,
  136. });
  137. emulator.add_listener("emulator-ready", function () {
  138. let network_adapter = emulator.network_adapter;
  139. let original_fetch = network_adapter.fetch;
  140. network_adapter.fetch = (url, opts) => {
  141. if(/^http:\/\/mocked.example.org\/?/.test(url)) {
  142. let contents = new TextEncoder().encode("This text is from the mock");
  143. let headers = new Headers();
  144. return new Promise(res => setTimeout(() => res([
  145. {status: 200, statusText: "OK", headers: headers},
  146. contents.buffer
  147. ]), 50));
  148. }
  149. return original_fetch.call(network_adapter, url, opts);
  150. };
  151. });
  152. let ran_command = false;
  153. let line = "";
  154. let capturing = false;
  155. let capture = "";
  156. let next_trigger;
  157. let next_trigger_handler;
  158. function start_timeout()
  159. {
  160. if(tests[test_num].timeout)
  161. {
  162. test_timeout = setTimeout(() =>
  163. {
  164. log_fail("Test #%d (%s) took longer than %s sec. Timing out and terminating.", test_num, tests[test_num].name, tests[test_num].timeout);
  165. process.exit(1);
  166. }, tests[test_num].timeout * 1000);
  167. }
  168. }
  169. function begin()
  170. {
  171. start_timeout();
  172. console.log("\nPreparing test #%d: %s", test_num, tests[test_num].name);
  173. start_test();
  174. }
  175. function start_test()
  176. {
  177. console.log("Starting test #%d: %s", test_num, tests[test_num].name);
  178. capture = "";
  179. tests[test_num].start();
  180. if(tests[test_num].capture_trigger)
  181. {
  182. next_trigger = tests[test_num].capture_trigger;
  183. next_trigger_handler = start_capture;
  184. }
  185. else
  186. {
  187. next_trigger = tests[test_num].end_trigger;
  188. next_trigger_handler = end_test;
  189. }
  190. start_capture();
  191. }
  192. function start_capture()
  193. {
  194. console.log("Capturing...");
  195. capture = "";
  196. capturing = true;
  197. next_trigger = tests[test_num].end_trigger;
  198. next_trigger_handler = end_test;
  199. }
  200. function end_test()
  201. {
  202. capturing = false;
  203. if(tests[test_num].timeout)
  204. {
  205. clearTimeout(test_timeout);
  206. }
  207. let test_has_failed = false;
  208. try {
  209. tests[test_num].end(capture);
  210. } catch(e) {
  211. console.log(e);
  212. test_has_failed = true;
  213. }
  214. if(!test_has_failed)
  215. {
  216. log_pass("Test #%d passed: %s", test_num, tests[test_num].name);
  217. }
  218. else
  219. {
  220. if(tests[test_num].allow_failure)
  221. {
  222. log_warn("Test #%d failed: %s (failure allowed)", test_num, tests[test_num].name);
  223. }
  224. else
  225. {
  226. log_fail("Test #%d failed: %s", test_num, tests[test_num].name);
  227. if(STOP_ON_FIRST_FAILURE)
  228. {
  229. finish_tests();
  230. }
  231. }
  232. test_has_failed = false;
  233. }
  234. test_num++;
  235. if(test_num < tests.length)
  236. {
  237. begin();
  238. }
  239. else
  240. {
  241. finish_tests();
  242. }
  243. }
  244. function finish_tests()
  245. {
  246. emulator.stop();
  247. console.log("\nTests finished.");
  248. if(failed_tests.length === 0)
  249. {
  250. console.log("All tests passed");
  251. }
  252. else
  253. {
  254. let unallowed_failure = false;
  255. console.error("Failed %d out of %d tests:", failed_tests.length, tests.length);
  256. for(const num of failed_tests)
  257. {
  258. if(tests[num].allow_failure)
  259. {
  260. log_warn("#%d %s (failure allowed)", num, tests[num].name);
  261. }
  262. else
  263. {
  264. unallowed_failure = true;
  265. log_fail("#%d %s", num, tests[num].name);
  266. }
  267. }
  268. if(unallowed_failure)
  269. {
  270. process.exit(1);
  271. }
  272. }
  273. }
  274. emulator.bus.register("emulator-started", function()
  275. {
  276. console.error("Booting now, please stand by");
  277. });
  278. emulator.add_listener("serial0-output-byte", function(byte)
  279. {
  280. const chr = String.fromCharCode(byte);
  281. if(chr < " " && chr !== "\n" && chr !== "\t" || chr > "~")
  282. {
  283. return;
  284. }
  285. let new_line = "";
  286. let is_new_line = false;
  287. if(chr === "\n")
  288. {
  289. is_new_line = true;
  290. new_line = line;
  291. line = "";
  292. }
  293. else
  294. {
  295. line += chr;
  296. }
  297. if(!ran_command && line.endsWith("~% "))
  298. {
  299. ran_command = true;
  300. begin();
  301. }
  302. else if(new_line === next_trigger)
  303. {
  304. next_trigger_handler();
  305. }
  306. else if(is_new_line && capturing)
  307. {
  308. capture += new_line + "\n";
  309. console.log(" Captured: %s", new_line);
  310. }
  311. else if(is_new_line)
  312. {
  313. console.log(" Serial: %s", new_line);
  314. }
  315. });