Files

100 lines
4.2 KiB
C

// Console-service smoke test. Verifies RSSRV publication, query, write, and cursor operations.
#include <ntlite/console_service.h>
#include <ntlite/port.h>
#include <ntlite/resource.h>
#include <ntlite/syscall.h>
#include <string.h>
static void exit_test(int code) {
for (;;) SysExitProcess(code);
}
static void print(const char* text) {
SYS_WRITE_CONSOLE_REQUEST request = { sizeof(request), SysSvFromCstr(text) };
(void)SysWriteConsole(&request);
}
static void print_status(KSTATUS status) {
static const char digits[] = "0123456789ABCDEF";
char buffer[11] = "0x00000000";
for (uint32_t i = 0; i < 8u; ++i)
buffer[2u + i] = digits[(status >> ((7u - i) * 4u)) & 0xFu];
print(buffer);
}
// Reports one failed console-service operation with its native status.
static void fail_status(const char* operation, KSTATUS status, int code) {
print("console_service_smoke: ");
print(operation);
print(" failed status=");
print_status(status);
print("\n");
exit_test(code);
}
// Reports one failed console-service invariant.
static void fail(const char* message, int code) {
print("console_service_smoke: ");
print(message);
print("\n");
exit_test(code);
}
// Runs the console-service smoke contract.
int main(void) {
SYS_HANDLE resources = SYS_HANDLE_INVALID;
KSTATUS status = NtlResourceConnect(&resources);
if (!KSUCCESS(status)) fail_status("connect resource service", status, 1);
uint32_t kind = NTL_RESOURCE_KIND_INVALID;
status = NtlResourceQuery(resources, SYS_SV_LITERAL("/Sessions/0"), &kind);
if (!KSUCCESS(status)) fail_status("query /Sessions/0", status, 2);
if (kind != NTL_RESOURCE_KIND_NAMESPACE_DIRECTORY) fail("/Sessions/0 has wrong resource kind", 2);
// DWM is noncritical, so the console contract must not depend on the desktop endpoint being published.
status = NtlResourceQuery(resources, SYS_SV_LITERAL("/Sessions/0/Console"), &kind);
if (!KSUCCESS(status)) fail_status("query /Sessions/0/Console", status, 3);
if (kind != NTL_RESOURCE_KIND_CAPABILITY) fail("/Sessions/0/Console has wrong resource kind", 3);
status = NtlResourceQuery(resources, SYS_SV_LITERAL("/Console"), &kind);
if (!KSUCCESS(status)) fail_status("query /Console", status, 4);
if (kind != NTL_RESOURCE_KIND_SYMBOLIC_LINK) fail("/Console has wrong resource kind", 4);
SYS_HANDLE alias = SYS_HANDLE_INVALID;
status = NtlResourceLookup(resources, SYS_SV_LITERAL("/Console"),
SYS_RIGHT_QUERY | SYS_PORT_RIGHT_CONNECT, &alias);
if (!KSUCCESS(status)) fail_status("lookup /Console", status, 5);
if (alias == SYS_HANDLE_INVALID) fail("lookup /Console returned invalid handle", 5);
(void)SysCloseHandle(alias);
(void)NtlResourceClose(resources);
SYS_HANDLE session = SYS_HANDLE_INVALID;
status = NtlConsoleConnect(&session);
if (!KSUCCESS(status)) fail_status("connect console", status, 6);
NTL_CONSOLE_INFO before;
memset(&before, 0, sizeof(before));
status = NtlConsoleQueryInfo(session, &before);
if (!KSUCCESS(status)) fail_status("query console info", status, 7);
if (before.Size != sizeof(before) || before.Flags != NTL_CONSOLE_FLAG_NONE ||
before.Columns == 0 || before.Rows == 0 || before.PixelWidth == 0 || before.PixelHeight == 0)
fail("initial console info is invalid", 7);
static const char message[] = "[console_service_smoke] PASS\n";
size_t written = 0;
status = NtlConsoleWrite(session, message, sizeof(message) - 1u, &written);
if (!KSUCCESS(status)) fail_status("write console", status, 8);
if (written != sizeof(message) - 1u) fail("console write returned short byte count", 8);
NTL_CONSOLE_INFO after;
memset(&after, 0, sizeof(after));
status = NtlConsoleQueryInfo(session, &after);
if (!KSUCCESS(status)) fail_status("query console info after write", status, 9);
if (after.Generation <= before.Generation) fail("console generation did not advance", 9);
status = NtlConsoleSetCursor(session, (int)after.CursorX, (int)after.CursorY);
if (!KSUCCESS(status)) fail_status("set console cursor", status, 10);
(void)NtlConsoleClose(session);
exit_test(0);
return 0;
}