// Dynamic test runner for every executable in the runner directory. #include #include #include #include #include #include #include #define ALL_TESTS_INITIAL_CAPACITY 32u typedef struct TEST_ENTRY { char Name[SYS_DIR_NAME_MAX]; } TEST_ENTRY; static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } static void print_u64(uint64_t v) { char buf[32]; int i = 0; if (v == 0) { print("0"); return; } while (v && i < (int)sizeof(buf)) { buf[i++] = (char)('0' + (v % 10)); v /= 10; } while (i--) { char c[2] = { buf[i], 0 }; print(c); } } static void print_i32(int32_t v) { if (v < 0) { print("-"); print_u64((uint32_t)(-(v + 1)) + 1u); return; } print_u64((uint32_t)v); } static void print_hex32(uint32_t v) { static const char hex[] = "0123456789abcdef"; for (int i = 7; i >= 0; i--) { char c[2] = { hex[(v >> (i * 4)) & 0xfu], 0 }; print(c); } } // Exits the process without returning to the runtime. static void exit_now(int code) { while (true) SysExitProcess(code); } // Converts ASCII to lowercase for stable case-insensitive comparisons. static char ascii_lower(char c) { if (c >= 'A' && c <= 'Z') return (char)(c - 'A' + 'a'); return c; } // Compares two names case-insensitively, with a case-sensitive tie-breaker. static int compare_names(const char* a, const char* b) { size_t i = 0; while (true) { char ca = ascii_lower(a[i]); char cb = ascii_lower(b[i]); if (ca != cb) return (unsigned char)ca < (unsigned char)cb ? -1 : 1; if (ca == '\0') break; i++; } return strcmp(a, b); } // Returns whether one character is a path separator. static bool is_separator(char c) { return c == '/' || c == '\\'; } // Copies a SYS_STRING_VIEW into a NUL-terminated fixed buffer. static bool copy_view(char* out, size_t outSize, SYS_STRING_VIEW view) { if (!out || outSize == 0 || !view.Data || view.Length + 1 > outSize) return false; memcpy(out, view.Data, view.Length); out[view.Length] = '\0'; return true; } // Splits an executable path into its directory and basename components. static bool split_self_path(const char* path, char* dir, size_t dirSize, char* name, size_t nameSize) { if (!path || !dir || !name || dirSize == 0 || nameSize == 0) return false; size_t len = strlen(path); size_t last = (size_t)-1; for (size_t i = 0; i < len; i++) { if (is_separator(path[i])) last = i; } const char* base = path; size_t dirLen = 1; if (last == (size_t)-1) { if (dirSize < 2) return false; dir[0] = '.'; dir[1] = '\0'; } else { dirLen = last; if (last == 0) dirLen = 1; if (last >= 2 && path[1] == ':' && is_separator(path[2])) dirLen = last + 1; if (dirLen + 1 > dirSize) return false; memcpy(dir, path, dirLen); dir[dirLen] = '\0'; base = path + last + 1; } size_t baseLen = strlen(base); if (baseLen + 1 > nameSize) return false; memcpy(name, base, baseLen + 1); return true; } // Returns whether one filename ends in .exe, case-insensitively. static bool has_exe_suffix(const char* name) { size_t len = strlen(name); if (len < 4) return false; const char* ext = name + len - 4; return ascii_lower(ext[0]) == '.' && ascii_lower(ext[1]) == 'e' && ascii_lower(ext[2]) == 'x' && ascii_lower(ext[3]) == 'e'; } // Allocates a test-entry array from user VM. static uint32_t alloc_entries(uint32_t capacity, TEST_ENTRY** entriesOut) { void* base = 0; size_t bytes = (size_t)capacity * sizeof(TEST_ENTRY); size_t pages = (bytes + 4095u) / 4096u; if (pages == 0) pages = 1; SYS_ALLOC_VM_REQUEST req; memset(&req, 0, sizeof(req)); req.Size = sizeof(req); req.Protect = SYS_VM_READWRITE; req.Flags = SYS_VM_FLAG_NONE; req.PageCount = pages; req.BaseOut = &base; KSTATUS status = SysAllocVm(&req); if (status != NTLSTATUS_SUCCESS || !base) { *entriesOut = 0; return status ? status : NTLSTATUS_NO_MEMORY; } *entriesOut = (TEST_ENTRY*)base; return NTLSTATUS_SUCCESS; } // Grows the test-entry array. static uint32_t grow_entries(TEST_ENTRY** entries, uint32_t* capacity, uint32_t count) { uint32_t oldCapacity = *capacity; uint32_t newCapacity = oldCapacity ? oldCapacity * 2u : ALL_TESTS_INITIAL_CAPACITY; TEST_ENTRY* next = 0; KSTATUS status = alloc_entries(newCapacity, &next); if (status != NTLSTATUS_SUCCESS) return status; if (*entries && count) memcpy(next, *entries, (size_t)count * sizeof(TEST_ENTRY)); if (*entries) SysFreeVm(*entries); *entries = next; *capacity = newCapacity; return NTLSTATUS_SUCCESS; } // Sorts test entries in deterministic execution order. static void sort_entries(TEST_ENTRY* entries, uint32_t count) { for (uint32_t i = 1; i < count; i++) { TEST_ENTRY current = entries[i]; uint32_t j = i; while (j > 0 && compare_names(current.Name, entries[j - 1].Name) < 0) { entries[j] = entries[j - 1]; j--; } entries[j] = current; } } // Builds one child path from the runner directory and test filename. static bool build_child_path(const char* dir, const char* name, char* out, size_t outSize) { if (!dir || !name || !out || outSize == 0) return false; size_t dirLen = strlen(dir); size_t nameLen = strlen(name); bool needSep = dirLen > 0 && !is_separator(dir[dirLen - 1]); size_t total = dirLen + (needSep ? 1u : 0u) + nameLen; if (total + 1 > outSize) return false; memcpy(out, dir, dirLen); size_t pos = dirLen; if (needSep) out[pos++] = '/'; memcpy(out + pos, name, nameLen); out[total] = '\0'; return true; } // Collects executable tests from the runner directory. static uint32_t collect_tests(const char* dir, const char* selfName, TEST_ENTRY** entriesOut, uint32_t* countOut) { *entriesOut = 0; *countOut = 0; uint32_t hDir = 0; KSTATUS status = NtlOpenDir(SysSvFromCstr(dir), SYS_DIR_ACCESS_ENUMERATE | SYS_DIR_ACCESS_OPEN, SYS_DIR_FLAG_NONE, &hDir); if (status != NTLSTATUS_SUCCESS) return status; TEST_ENTRY* entries = 0; uint32_t count = 0; uint32_t capacity = 0; while (true) { SYS_DIR_ENTRY entry; status = SysReadDir(hDir, &entry); if (status != NTLSTATUS_SUCCESS) break; if (!entry.Name[0]) continue; if ((entry.Attr & 0x10u) != 0) continue; if (!has_exe_suffix(entry.Name)) continue; if (compare_names(entry.Name, selfName) == 0) continue; if (count == capacity) { status = grow_entries(&entries, &capacity, count); if (status != NTLSTATUS_SUCCESS) { SysCloseHandle(hDir); if (entries) SysFreeVm(entries); return status; } } strncpy(entries[count].Name, entry.Name, sizeof(entries[count].Name) - 1); entries[count].Name[sizeof(entries[count].Name) - 1] = '\0'; count++; } SysCloseHandle(hDir); sort_entries(entries, count); *entriesOut = entries; *countOut = count; return NTLSTATUS_SUCCESS; } // Runs one test process and returns the child's exit code through exitCodeOut. static uint32_t run_test(const char* path, int32_t* exitCodeOut) { uint32_t imageFile = SYS_HANDLE_INVALID; KSTATUS status = NtlOpenFile(SysSvFromCstr(path), SYS_FILE_ACCESS_READ | SYS_FILE_ACCESS_QUERY, SYS_FILE_OPEN_EXISTING, SYS_FILE_FLAG_NONE, &imageFile); if (status != NTLSTATUS_SUCCESS) return status; uint32_t process = 0; NTL_CREATE_SYSTEM_PROCESS_REQUEST req; memset(&req, 0, sizeof(req)); req.Size = sizeof(req); req.Flags = NTL_PROCESS_LOAD_FLAG_NONE; req.ImageFile = imageFile; req.Path = SysSvFromCstr(path); req.CommandLine = SysSvFromCstr(path); req.SecurityContext = SYS_SECURITY_CONTEXT_CURRENT; req.ResolveModuleName = NtlResolveSystemModuleName; req.ProcessHandleOut = &process; status = NtlCreateSystemProcess(&req); (void)SysCloseHandle(imageFile); if (status != NTLSTATUS_SUCCESS) return status; status = SysWait(process, SYS_WAIT_FLAG_NONE); if (status != NTLSTATUS_SUCCESS) { SysCloseHandle(process); return status; } int32_t exitCode = 1; status = SysGetProcessExitCode(process, &exitCode); SysCloseHandle(process); if (status != NTLSTATUS_SUCCESS) return status; *exitCodeOut = exitCode; return NTLSTATUS_SUCCESS; } int main(void) { print("all_tests: start\n"); char selfPath[SYS_PATH_MAX]; char selfDir[SYS_PATH_MAX]; char selfName[SYS_DIR_NAME_MAX]; SYS_PEB* peb = SysGetPeb(); if (!peb || peb->Magic != SYS_PEB_MAGIC || peb->Version != SYS_ENV_VERSION || !copy_view(selfPath, sizeof(selfPath), peb->ImagePath) || !split_self_path(selfPath, selfDir, sizeof(selfDir), selfName, sizeof(selfName))) { print("all_tests: failed to resolve runner path\n"); exit_now(1); } TEST_ENTRY* entries = 0; uint32_t count = 0; KSTATUS status = collect_tests(selfDir, selfName, &entries, &count); if (status != NTLSTATUS_SUCCESS) { print("all_tests: failed to enumerate tests status=0x"); print_hex32(status); print("\n"); exit_now(1); } if (count == 0) { print("all_tests: no test executables found\n"); if (entries) SysFreeVm(entries); exit_now(1); } for (uint32_t i = 0; i < count; i++) { char childPath[SYS_PATH_MAX]; if (!build_child_path(selfDir, entries[i].Name, childPath, sizeof(childPath))) { print("all_tests: child path too long: "); print(entries[i].Name); print("\n"); SysFreeVm(entries); exit_now(1); } print("all_tests: RUN "); print(childPath); print("\n"); int32_t exitCode = 1; status = run_test(childPath, &exitCode); if (status != NTLSTATUS_SUCCESS) { print("all_tests: FAIL "); print(childPath); print(" launch/wait status=0x"); print_hex32(status); print("\n"); SysFreeVm(entries); exit_now(1); } if (exitCode != 0) { print("all_tests: FAIL "); print(childPath); print(" exit="); print_i32(exitCode); print("\n"); SysFreeVm(entries); exit_now(exitCode ? exitCode : 1); } print("all_tests: PASS "); print(childPath); print("\n"); } print("all_tests: PASS count="); print_u64(count); print("\n"); SysFreeVm(entries); exit_now(0); return 0; }