add new posix subsystem tests

This commit is contained in:
nakst 2022-01-19 23:26:46 +00:00
parent fefa668d0d
commit d49ca458e2
2 changed files with 85 additions and 63 deletions

View File

@ -1132,26 +1132,8 @@ bool PipeTests() {
#define vfork() EsPOSIXSystemCall(SYS_vfork, 0, 0, 0, 0, 0, 0)
#define wait4(x, y, z, w) EsPOSIXSystemCall(SYS_wait4, (intptr_t) x, (intptr_t) y, (intptr_t) z, (intptr_t) w, 0, 0)
bool POSIXSubsystemTest() {
const char *executeEnvironment[] = {
"PATH=/Applications/POSIX/bin",
"TMPDIR=/Applications/POSIX/tmp",
NULL,
};
const char *executable = "/Applications/POSIX/bin/busybox";
const char *argv[] = {
(char *) "busybox",
(char *) "echo",
(char *) "hello",
NULL,
};
int _argc;
char **_argv;
EsPOSIXInitialise(&_argc, &_argv);
bool POSIXSubsystemRunCommandAndCheckOutput(const char **executeEnvironment, const char **argv,
const char *executable, const char *expectedOutput) {
int stdoutPipe[2];
pipe(stdoutPipe);
@ -1166,7 +1148,7 @@ bool POSIXSubsystemTest() {
return false;
} else if (pid > 0) {
close(stdoutPipe[1]);
char readData[10];
char readData[4096];
int readPosition = 0;
while (true) {
@ -1179,7 +1161,8 @@ bool POSIXSubsystemTest() {
}
}
if (readPosition != 6 || EsMemoryCompare(readData, "hello\n", 6)) {
if (readPosition != (int) EsCStringLength(expectedOutput)
|| EsMemoryCompare(readData, expectedOutput, readPosition)) {
EsPrint("Incorrect output: '%s'.\n", readPosition, readData);
return false;
}
@ -1196,6 +1179,33 @@ bool POSIXSubsystemTest() {
return false;
}
close(stdoutPipe[0]);
return true;
}
bool POSIXSubsystemTest() {
int checkIndex = 0;
const char *executeEnvironment[] = {
"PATH=/Applications/POSIX/bin",
"TMPDIR=/Applications/POSIX/tmp",
NULL,
};
int _argc;
char **_argv;
EsPOSIXInitialise(&_argc, &_argv);
const char *executable = "/Applications/POSIX/bin/busybox";
const char *argv[] = { "busybox", "sh", "test.sh", NULL, };
EsFileWriteAll(EsLiteral("0:/test.sh"), EsLiteral("echo hello"));
CHECK(POSIXSubsystemRunCommandAndCheckOutput(executeEnvironment, argv, executable, "hello\n"));
EsFileWriteAll(EsLiteral("0:/test.sh"), EsLiteral("echo world"));
CHECK(POSIXSubsystemRunCommandAndCheckOutput(executeEnvironment, argv, executable, "world\n"));
EsFileWriteAll(EsLiteral("0:/test.sh"), EsLiteral("find . | grep Kernel.esx"));
CHECK(POSIXSubsystemRunCommandAndCheckOutput(executeEnvironment, argv, executable, "./Essence/Kernel.esx\n"));
return true;
}

View File

@ -1263,6 +1263,56 @@ void GetSource(const char *parameters, const char *checksum) {
if (CallSystemF("mv %.*s bin/source", (int) (url - folder), folder)) exit(1);
}
void RunTests(int singleTest) {
// TODO Capture (and compress) emulator memory dump if a test causes a KernelPanic or EsPanic.
// TODO Using SMP/KVM if available in the optimised test runs.
int successCount = 0, failureCount = 0;
CallSystem("mkdir -p root/Essence/Settings/API\\ Tests");
FILE *testFailures = fopen("bin/Logs/Test Failures.txt", "wb");
for (int optimisations = 0; optimisations <= 1; optimisations++) {
for (uint32_t index = 0; index < sizeof(tests) / sizeof(tests[0]); index++) {
if (singleTest != -1) {
if ((int) index != singleTest || optimisations) {
continue;
}
}
CallSystem("rm -f bin/Logs/qemu_serial1.txt");
FILE *f = fopen("root/Essence/Settings/API Tests/test.dat", "wb");
fwrite(&index, 1, sizeof(uint32_t), f);
uint32_t mode = 1;
fwrite(&mode, 1, sizeof(uint32_t), f);
fclose(f);
emulatorTimeout = tests[index].timeoutSeconds;
if (optimisations) BuildAndRun(OPTIMISE_FULL, true, DEBUG_LATER, EMULATOR_QEMU_NO_GUI, LOG_NORMAL);
else BuildAndRun(OPTIMISE_OFF, true, DEBUG_LATER, EMULATOR_QEMU_NO_GUI, LOG_NORMAL);
emulatorTimeout = 0;
if (emulatorDidTimeout) encounteredErrors = false;
if (encounteredErrors) { fprintf(stderr, "Compile errors, stopping tests.\n"); goto stopTests; }
char *log = (char *) LoadFile("bin/Logs/qemu_serial1.txt", NULL);
if (!log) { fprintf(stderr, "No log file, stopping tests.\n"); goto stopTests; }
bool success = strstr(log, "[APITests-Success]\n") && !emulatorDidTimeout;
bool failure = strstr(log, "[APITests-Failure]\n");
if (emulatorDidTimeout) fprintf(stderr, "'%s' (%d/%d): " ColorError "timeout" ColorNormal ".\n", tests[index].cName, optimisations, index);
else if (success) fprintf(stderr, "'%s' (%d/%d): success.\n", tests[index].cName, optimisations, index);
else if (failure) fprintf(stderr, "'%s' (%d/%d): " ColorError "failure" ColorNormal ".\n", tests[index].cName, optimisations, index);
else fprintf(stderr, "'%s' (%d/%d): " ColorError "no response" ColorNormal ".\n", tests[index].cName, optimisations, index);
if (success) successCount++;
else failureCount++;
free(log);
if (!success) CallSystemF("mv bin/Logs/qemu_serial1.txt bin/Logs/test_%d_%d.txt", optimisations, index);
if (!success) fprintf(testFailures, "%d/%d %s\n", optimisations, index, tests[index].cName);
}
}
stopTests:;
fprintf(stderr, ColorHighlight "%d/%d tests succeeded." ColorNormal "\n", successCount, successCount + failureCount);
fclose(testFailures);
if (failureCount && automatedBuild) exit(1);
}
void DoCommand(const char *l) {
while (l && (*l == ' ' || *l == '\t')) l++;
@ -1700,47 +1750,9 @@ void DoCommand(const char *l) {
strcat(cwd, "/crash-report.tar.gz");
fprintf(stderr, "Crash report made at " ColorHighlight "%s" ColorNormal ".\n", cwd);
} else if (0 == strcmp(l, "run-tests")) {
// TODO Capture (and compress) emulator memory dump if a test causes a KernelPanic or EsPanic.
// TODO Using SMP/KVM if available in the optimised test runs.
int successCount = 0, failureCount = 0;
CallSystem("mkdir -p root/Essence/Settings/API\\ Tests");
FILE *testFailures = fopen("bin/Logs/Test Failures.txt", "wb");
for (int optimisations = 0; optimisations <= 1; optimisations++) {
for (uint32_t index = 0; index < sizeof(tests) / sizeof(tests[0]); index++) {
CallSystem("rm -f bin/Logs/qemu_serial1.txt");
FILE *f = fopen("root/Essence/Settings/API Tests/test.dat", "wb");
fwrite(&index, 1, sizeof(uint32_t), f);
uint32_t mode = 1;
fwrite(&mode, 1, sizeof(uint32_t), f);
fclose(f);
emulatorTimeout = tests[index].timeoutSeconds;
if (optimisations) BuildAndRun(OPTIMISE_FULL, true, DEBUG_LATER, EMULATOR_QEMU_NO_GUI, LOG_NORMAL);
else BuildAndRun(OPTIMISE_OFF, true, DEBUG_LATER, EMULATOR_QEMU_NO_GUI, LOG_NORMAL);
emulatorTimeout = 0;
if (emulatorDidTimeout) encounteredErrors = false;
if (encounteredErrors) { fprintf(stderr, "Compile errors, stopping tests.\n"); goto stopTests; }
char *log = (char *) LoadFile("bin/Logs/qemu_serial1.txt", NULL);
if (!log) { fprintf(stderr, "No log file, stopping tests.\n"); goto stopTests; }
bool success = strstr(log, "[APITests-Success]\n") && !emulatorDidTimeout;
bool failure = strstr(log, "[APITests-Failure]\n");
if (emulatorDidTimeout) fprintf(stderr, "'%s' (%d/%d): " ColorError "timeout" ColorNormal ".\n", tests[index].cName, optimisations, index);
else if (success) fprintf(stderr, "'%s' (%d/%d): success.\n", tests[index].cName, optimisations, index);
else if (failure) fprintf(stderr, "'%s' (%d/%d): " ColorError "failure" ColorNormal ".\n", tests[index].cName, optimisations, index);
else fprintf(stderr, "'%s' (%d/%d): " ColorError "no response" ColorNormal ".\n", tests[index].cName, optimisations, index);
if (success) successCount++;
else failureCount++;
free(log);
if (!success) CallSystemF("mv bin/Logs/qemu_serial1.txt bin/Logs/test_%d_%d.txt", optimisations, index);
if (!success) fprintf(testFailures, "%d/%d %s\n", optimisations, index, tests[index].cName);
}
}
stopTests:;
fprintf(stderr, ColorHighlight "%d/%d tests succeeded." ColorNormal "\n", successCount, successCount + failureCount);
fclose(testFailures);
if (failureCount && automatedBuild) exit(1);
RunTests(-1);
} else if (0 == memcmp(l, "run-test ", 9)) {
RunTests(atoi(l + 9));
} else if (0 == strcmp(l, "setup-pre-built-toolchain")) {
CallSystem("mv bin/source cross");
CallSystem("mkdir -p cross/bin2");