struct CliHttpResponse { u64 status = 0; String raw; String headers; String body; }; u64 cli_tests_passed = 0; u64 cli_tests_failed = 0; u64 cli_tests_skipped = 0; StringList cli_tests_failures; bool cli_contains(String haystack, String needle) { return(haystack.find(needle) != String::npos); } String cli_truncate(String value, u64 max_len = 240) { if(value.length() <= max_len) return(value); return(value.substr(0, max_len) + "..."); } CliHttpResponse cli_http_request(String host, u16 port, String path, String extra_headers = "") { CliHttpResponse res; u64 fd = socket_connect(host, port); if(fd == 0) { res.raw = "socket_connect failed"; return(res); } String host_header = host; if(host == "127.0.0.1" && port == 80) host_header = "uce.openfu.com"; else if(host == "127.0.0.1" && port == 8080) host_header = "localhost"; String request = "GET " + path + " HTTP/1.0\r\nHost: " + host_header + "\r\nConnection: close\r\n" + extra_headers + "\r\n"; socket_write(fd, request); for(u64 i = 0; i < 16; i++) { String chunk = socket_read(fd, 65536, 30); if(chunk == "") break; res.raw += chunk; } socket_close(fd); u64 line_end = res.raw.find("\r\n"); if(line_end != String::npos) { StringList parts = split(res.raw.substr(0, line_end), " "); if(parts.size() >= 2) res.status = int_val(parts[1]); } u64 split_at = res.raw.find("\r\n\r\n"); if(split_at != String::npos) { res.headers = res.raw.substr(0, split_at + 4); res.body = res.raw.substr(split_at + 4); } else { res.headers = res.raw; res.body = ""; } return(res); } CliHttpResponse cli_frontend(String path, String extra_headers = "") { return(cli_http_request("127.0.0.1", 80, path, extra_headers)); } CliHttpResponse cli_direct_http(String path, String extra_headers = "") { return(cli_http_request("127.0.0.1", 8080, path, extra_headers)); } void cli_test_case(String name, bool ok, String summary) { if(ok) { cli_tests_passed++; print("[PASS] ", name, " - ", summary, "\n"); } else { cli_tests_failed++; cli_tests_failures.push_back(name + ": " + summary); print("[FAIL] ", name, " - ", summary, "\n"); } } void cli_test_skip(String name, String summary) { cli_tests_skipped++; print("[SKIP] ", name, " - ", summary, "\n"); } bool cli_expect_http_once(CliHttpResponse& res, String path, u64 expected_status, String marker, StringList error_markers, String& summary) { bool ok = res.status == expected_status; summary = "HTTP " + std::to_string(res.status) + " for " + path; if(marker != "" && !cli_contains(res.body, marker)) { ok = false; summary += "; missing marker " + marker; } String lower = to_lower(res.body); for(String marker_text : error_markers) { if(cli_contains(lower, marker_text)) { ok = false; summary += "; body contained " + marker_text; } } return(ok); } bool cli_expect_http(String name, String path, u64 expected_status, String marker, StringList error_markers = {}) { CliHttpResponse res = cli_frontend(path); String summary; bool ok = cli_expect_http_once(res, path, expected_status, marker, error_markers, summary); if(!ok && expected_status != 500) { usleep(500000); res = cli_frontend(path); ok = cli_expect_http_once(res, path, expected_status, marker, error_markers, summary); } cli_test_case(name, ok, ok ? summary : summary + "; body=" + cli_truncate(res.body)); return(ok); } StringList cli_demo_error_markers() { StringList markers; markers.push_back(String("uce compile ") + "error"); markers.push_back(String("fatal signal during ") + "request"); markers.push_back(String("uncaught exception during ") + "request"); return(markers); } void cli_run_demo_smoke() { StringList files = split("call_file.uce\ncall_file_funcs.uce\ncollections.uce\ncomponents.uce\ncookie.uce\ndvalue.uce\nempty.uce\nerror-reporting.uce\nfile_append.uce\nfileio.uce\nheader.uce\nhello.uce\nindex.uce\njson.uce\nmarkdown.uce\nmemcached.uce\nmysql.uce\nonce-init.uce\nparse_time.uce\npost-multipart.uce\npost.uce\npreprocessor-comments.uce\nrandom.uce\nregex.uce\nscript.uce\nsession.uce\nsharedunit.uce\nshell.uce\nsqlite.uce\nstr_replace.uce\nstring.uce\ntask-status.uce\ntask.uce\ntask_repeat.uce\nunit-browser.uce\nunit-info.uce\nuri.uce\nutf8.uce\nwebsockets.ws.uce\nworking-dir.uce\nxml.uce\nyaml.uce\nzip.uce", "\n"); for(String file : files) cli_expect_http("uce_demo_smoke:demo page " + file, "/demo/" + file, 200, "", file == "unit-browser.uce" ? StringList() : cli_demo_error_markers()); } bool cli_doc_source_has_example(String source) { for(String line : split(source, "\n")) if(trim(line) == ":example") return(true); return(false); } // A real example must exercise the documented API and print a derived result. // These placeholder shapes (auto-generated stubs) are forbidden by the gate. bool cli_doc_example_is_placeholder(String source) { bool in_example = false; StringList body; for(String line : split(source, "\n")) { String t = trim(line); if(!in_example) { if(t == ":example") in_example = true; continue; } if(t.length() > 0 && t.substr(0, 1) == ":") break; body.push_back(line); } String joined = join(body, "\n"); if(cli_contains(joined, " example\\n\");")) return(true); if(cli_contains(joined, "is resource-bound; configure")) return(true); if(cli_contains(joined, "documents a UCE concept")) return(true); return(false); } void cli_run_doc_pages_gate() { StringList error_markers; error_markers.push_back("doc example error"); error_markers.push_back(String("uce compile ") + "error"); error_markers.push_back(String("wasm runtime error during ") + "request"); error_markers.push_back(String("fatal signal during ") + "request"); error_markers.push_back(String("uncaught exception during ") + "request"); error_markers.push_back("timed out acquiring compile lock"); for(String file_name : ls("../doc/pages/")) { String source = file_get_contents("../doc/pages/" + file_name); String page = nibble(file_name, "."); if(page == "") continue; bool has_example = cli_doc_source_has_example(source); String path = "/doc/index.uce?p=" + uri_encode(page); CliHttpResponse res = cli_frontend(path); String summary; bool ok = cli_expect_http_once(res, path, 200, "doc-detail", error_markers, summary); String lower = to_lower(res.body); if(has_example) { if(!cli_contains(res.body, "class=\"example-output\"") || !cli_contains(res.body, "example-output-label\">Output")) { ok = false; summary += "; missing example Output block"; } if(cli_contains(lower, "doc example error")) { ok = false; summary += "; example reported an error"; } if(cli_doc_example_is_placeholder(source)) { ok = false; summary += "; placeholder example (must exercise the API)"; } } cli_test_case("uce_doc_gate:doc page " + page, ok, ok ? summary : summary + "; body=" + cli_truncate(res.body)); } } void cli_run_http_smoke() { cli_expect_http("uce_http_smoke:doc index", "/doc/index.uce", 200, ""); // Regression guard: the index enumerates pages via ls("pages/"). When that // returned empty (wasm ls() was a stub), the page still rendered but // listed nothing — so assert the function grid is actually populated. cli_expect_http("uce_http_smoke:doc index lists functions", "/doc/index.uce", 200, "func-item"); cli_expect_http("uce_http_smoke:doc singlepage", "/doc/singlepage.uce", 200, ""); cli_expect_http("uce_http_smoke:doc component page", "/doc/index.uce?p=component", 200, "component()"); cli_expect_http("uce_http_smoke:doc regex page", "/doc/index.uce?p=regex_search", 200, "regex_search"); cli_expect_http("uce_http_smoke:doc xml page", "/doc/index.uce?p=xml_encode", 200, "xml_encode"); cli_expect_http("uce_http_smoke:doc yaml page", "/doc/index.uce?p=yaml_encode", 200, "yaml_encode"); cli_expect_http("uce_http_smoke:doc relative time page", "/doc/index.uce?p=time_format_relative", 200, "time_format_relative"); cli_expect_http("uce_http_smoke:starter home", "/examples/uce-starter/", 200, "Stunning Apps"); cli_expect_http("uce_http_smoke:starter dashboard", "/examples/uce-starter/?dashboard", 200, "Dashboard"); cli_expect_http("uce_http_smoke:starter dashboard ONCE assets reach head", "/examples/uce-starter/?dashboard", 200, "views/dashboard.css"); cli_expect_http("uce_http_smoke:starter workspace nested route", "/examples/uce-starter/?workspace/projects", 200, "Workspace"); cli_expect_http("uce_http_smoke:starter workspace ONCE assets reach head", "/examples/uce-starter/?workspace/projects", 200, "css/workspace.css"); cli_expect_http("uce_http_smoke:starter ajax section", "/examples/uce-starter/?page2-section1", 200, "UCE starter AJAX fragment response"); cli_expect_http("uce_http_smoke:starter route traversal blocked", "/examples/uce-starter/?../../../demo/index", 404, "The requested page does not exist."); // Configurable error page (page_runtime_error): a runtime fault must render the // developer-defined error-page unit with the real error info marshalled across // the membrane, at the error status. Asserts HTTP 500 AND that error["request_uri"] // reached the page (the "mode=trap" query is only shown if error_info crossed). cli_expect_http("uce_http_smoke:configurable error page 500 + error info", "/demo/error-reporting.uce?mode=trap", 500, "mode=trap"); } bool cli_site_body_reports_failure(String lower) { for(String digit : split("1 2 3 4 5 6 7 8 9", " ")) if(cli_contains(lower, ">failed " + digit)) return(true); return(false); } void cli_run_site_suite() { DValue manifest; for(String line : split(file_get_contents("manifest.txt"), "\n")) { line = trim(line); if(line == "" || line[0] == '#') continue; StringList parts = split(line, "|"); if(parts.size() < 7 || trim(parts[5]) != "1") continue; String file = trim(parts[0]); String title = trim(parts[1]); String expected = first(trim(parts[4]), title); CliHttpResponse res; String lower; bool ok = false; for(u64 attempt = 0; attempt < 3; attempt++) { if(attempt > 0) usleep(1000000); res = cli_frontend("/tests/" + file); lower = to_lower(res.body); ok = res.status == 200 && cli_contains(res.body, expected); for(String marker : { "compile error", "runtime error", "timed out acquiring compile lock", "near line" }) if(cli_contains(lower, marker)) ok = false; if(cli_contains(lower, "
") && cli_site_body_reports_failure(lower)) ok = false; if(ok) break; } String name = "uce_site_suite:site tests " + (file == "index.uce" ? "index" : file == "io.uce" ? "filesystem" : file == "websockets.ws.uce" ? "websockets page" : replace(replace(replace(file, ".uce", ""), ".ws", ""), "_", " ")); String fail_detail = "; status=" + std::to_string(res.status) + "; expected_marker=" + (cli_contains(res.body, expected) ? "yes" : "no") + "; summary=" + (cli_contains(lower, "
") ? "yes" : "no") + "; reports_failure=" + (cli_site_body_reports_failure(lower) ? "yes" : "no") + "; body=" + cli_truncate(res.body); cli_test_case(name, ok, (ok ? "HTTP 200 with suite page marker and no failed cases for /tests/" : "site suite failed for /tests/") + file + (ok ? "" : fail_detail)); } } void cli_run_security_smoke() { CliHttpResponse dotdot = cli_direct_http("/../site/demo/hello.uce"); cli_test_case("uce_security_smoke:direct HTTP rejects dot-dot script traversal", dotdot.status != 200 && !cli_contains(dotdot.body, "hello world"), "direct HTTP dot-dot traversal returned HTTP " + std::to_string(dotdot.status)); CliHttpResponse spoof = cli_direct_http("/no-such-script.uce", "Script-Filename: /Code/uce.openfu.com/uce/site/demo/hello.uce\r\n"); cli_test_case("uce_security_smoke:direct HTTP ignores Script-Filename header", spoof.status != 200 && !cli_contains(spoof.body, "hello world"), "direct HTTP Script-Filename override returned HTTP " + std::to_string(spoof.status)); CliHttpResponse sanitizer = cli_frontend("/tests/security_headers.uce"); String headers_lower = to_lower(sanitizer.headers); bool injected = false; for(String header : { "x-uce-injected", "x-uce-injected-name", "x-uce-cookie-injected", "x-uce-redirect-injected", "x-uce-status-injected" }) if(cli_contains(headers_lower, "\r\n" + to_lower(header) + ":")) injected = true; CliHttpResponse direct_sanitizer = cli_direct_http("/site/tests/security_headers.uce"); bool direct_ok = direct_sanitizer.status < 500 || cli_contains(direct_sanitizer.body, "security header sanitizer test"); cli_test_case("uce_security_smoke:response headers sanitize CRLF", !injected && direct_ok, "CRLF response header injection sanitized"); String attacker = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; CliHttpResponse session = cli_frontend("/tests/http.uce", "Cookie: uce-site-tests=" + attacker + "\r\n"); String session_headers = session.headers; bool adopted = cli_contains(session_headers, "Set-Cookie: uce-site-tests=" + attacker); bool hardened = cli_contains(session_headers, "Set-Cookie: uce-site-tests=") && cli_contains(session_headers, "HttpOnly") && cli_contains(session_headers, "SameSite=Lax"); cli_test_case("uce_security_smoke:unknown session ids are not adopted", !adopted && hardened, "unknown caller-supplied session id was replaced"); } void cli_run_starter_parity() { StringList markers = { "landing\t\tHome | UCE Starter", "dashboard\t?dashboard\tDashboard | UCE Starter", "gauges\t?gauges\tGauges | UCE Starter", "features\t?features\tFeatures | UCE Starter", "components\t?page1\tComponents | UCE Starter", "workspace\t?workspace\tWorkspace | UCE Starter" }; for(String row : markers) { StringList parts = split(row, "\t"); String name = parts[0]; String query = parts[1]; String title = parts[2]; cli_expect_http("uce_starter_parity:starter view " + name, "/examples/uce-starter/index.uce" + query, 200, "" + title + "", cli_demo_error_markers()); } cli_expect_http("uce_starter_parity:starter unknown route 404", "/examples/uce-starter/index.uce?does-not-exist", 404, "404 Not Found | UCE Starter", cli_demo_error_markers()); } void cli_run_task_lifetime_smoke() { String late_file = "/tmp/uce-site-tests-late-task.txt"; file_unlink(late_file); CliHttpResponse res = cli_frontend("/tests/tasks.uce?mode=late"); usleep(3000000); String observed = file_exists(late_file) ? file_get_contents(late_file) : ""; cli_test_case("uce_task_lifetime:delayed callback after request return", res.status == 200 && cli_contains(res.body, "late task scheduled") && cli_contains(observed, "late callback ran"), "status=" + std::to_string(res.status) + " observed=" + cli_truncate(observed)); } void cli_run_tcp_smoke() { u64 fd80 = socket_connect("127.0.0.1", 80); cli_test_case("uce_tcp_smoke:frontend port 80", fd80 != 0, "TCP connect " + String(fd80 != 0 ? "succeeded" : "failed") + " on port 80"); if(fd80 != 0) socket_close(fd80); u64 fd8080 = socket_connect("127.0.0.1", 8080); cli_test_case("uce_tcp_smoke:http websocket port 8080", fd8080 != 0, "TCP connect " + String(fd8080 != 0 ? "succeeded" : "failed") + " on port 8080"); if(fd8080 != 0) socket_close(fd8080); } void cli_run_wasm_kill(bool include_kill) { if(!include_kill) return; for(String row : { "wasm kill trap|/tests/wasm-kill/oob.uce|unreachable", "wasm kill loop|/tests/wasm-kill/loop.uce|interrupt", "wasm kill recurse|/tests/wasm-kill/recurse.uce|wasm_kill_recurse" }) { StringList parts = split(row, "|"); CliHttpResponse res = cli_frontend(parts[1]); CliHttpResponse health = cli_frontend("/demo/hello.uce"); bool ok = res.status == 500 && cli_contains(res.body, "wasm runtime error during request") && cli_contains(res.body, parts[2]) && health.status == 200 && cli_contains(health.body, "hello world"); cli_test_case("uce_wasm_kill:" + parts[0], ok, ok ? "clean wasm trap page and post-trap health check for " + parts[1] : "kill check failed; status=" + std::to_string(res.status) + " health=" + std::to_string(health.status)); } } void cli_print_list(bool include_kill) { print("UCE CLI test groups:\n"); print(" demo, http, site, security, starter, tcp"); if(include_kill) print(", wasm-kill"); print("\n"); } CLI(Request& context) { context.header["Content-Type"] = "text/plain; charset=utf-8"; DValue input = cli_input(context); String action = first(input["action"].to_string(), "run"); bool include_kill = input["include_kill"].to_bool() || input["include_wasm_kill"].to_bool(); if(action == "list") { cli_print_list(include_kill); return; } print("Running UCE CLI tests\n"); f64 group_start = time_precise(); cli_run_demo_smoke(); print("[GROUP] demo ", std::to_string((u64)((time_precise() - group_start) * 1000)), " ms\n"); group_start = time_precise(); cli_run_http_smoke(); print("[GROUP] http ", std::to_string((u64)((time_precise() - group_start) * 1000)), " ms\n"); group_start = time_precise(); cli_run_site_suite(); print("[GROUP] site ", std::to_string((u64)((time_precise() - group_start) * 1000)), " ms\n"); group_start = time_precise(); cli_run_doc_pages_gate(); print("[GROUP] doc-gate ", std::to_string((u64)((time_precise() - group_start) * 1000)), " ms\n"); group_start = time_precise(); cli_run_security_smoke(); print("[GROUP] security ", std::to_string((u64)((time_precise() - group_start) * 1000)), " ms\n"); group_start = time_precise(); cli_run_task_lifetime_smoke(); print("[GROUP] task-lifetime ", std::to_string((u64)((time_precise() - group_start) * 1000)), " ms\n"); group_start = time_precise(); cli_run_starter_parity(); print("[GROUP] starter ", std::to_string((u64)((time_precise() - group_start) * 1000)), " ms\n"); group_start = time_precise(); cli_run_tcp_smoke(); String repo_root = process_start_directory(); String cli_arg_out = shell_exec("cd " + shell_escape(repo_root) + " && bash scripts/uce-cli /tests/cli.uce action=arg message=hello-cli 2>&1"); cli_test_case("uce_cli_fixture:cli_arg", contains(cli_arg_out, "hello-cli") && contains(cli_arg_out, "fallback"), cli_truncate(cli_arg_out)); print("[GROUP] tcp ", std::to_string((u64)((time_precise() - group_start) * 1000)), " ms\n"); group_start = time_precise(); cli_run_wasm_kill(include_kill); print("[GROUP] wasm-kill ", std::to_string((u64)((time_precise() - group_start) * 1000)), " ms\n"); print("\nSummary: ", std::to_string(cli_tests_passed), " passed, ", std::to_string(cli_tests_failed), " failed, ", std::to_string(cli_tests_skipped), " skipped\n"); if(cli_tests_failed != 0) { context.set_status(500, "CLI Tests Failed"); print("Failures:\n"); for(String failure : cli_tests_failures) print("- ", failure, "\n"); } } RENDER(Request& context) { context.set_status(404, "Not Found"); context.header["Content-Type"] = "text/plain; charset=utf-8"; print("Invoke this test runner through the UCE CLI socket.\n"); }