memtag_test: improve capturing of test results

Using debuggerd + logcat parsing is unreliable and slow, print SEGV signal code to stderr instead.
This commit is contained in:
Dmitry Muhomor 2023-10-29 15:06:14 +02:00
parent 1adfed0252
commit 6ad888c42a
2 changed files with 28 additions and 56 deletions

View File

@ -2,6 +2,7 @@
#undef NDEBUG #undef NDEBUG
#include <assert.h> #include <assert.h>
#include <malloc.h> #include <malloc.h>
#include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
@ -249,6 +250,11 @@ map<string, function<void()>> tests = {
#undef TEST #undef TEST
}; };
void segv_handler(int, siginfo_t *si, void *) {
fprintf(stderr, "SEGV_CODE %i", si->si_code);
exit(139); // standard exit code for SIGSEGV
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
setbuf(stdout, NULL); setbuf(stdout, NULL);
assert(argc == 2); assert(argc == 2);
@ -259,6 +265,13 @@ int main(int argc, char **argv) {
assert(mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, M_HEAP_TAGGING_LEVEL_ASYNC) == 1); assert(mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, M_HEAP_TAGGING_LEVEL_ASYNC) == 1);
struct sigaction sa = {
.sa_sigaction = segv_handler,
.sa_flags = SA_SIGINFO,
};
assert(sigaction(SIGSEGV, &sa, nullptr) == 0);
test_fn(); test_fn();
do_context_switch(); do_context_switch();

View File

@ -19,10 +19,19 @@ public class MemtagTest extends BaseHostJUnit4Test {
private static final String TEST_BINARY = "/data/local/tmp/memtag_test"; private static final String TEST_BINARY = "/data/local/tmp/memtag_test";
enum Result { enum Result {
SUCCESS, SUCCESS(0, ""),
// it's expected that the device is configured to use asymm MTE tag checking mode // it's expected that the device is configured to use asymm MTE tag checking mode
ASYNC_MTE_ERROR, ASYNC_MTE_ERROR(139, "SEGV_CODE 8"),
SYNC_MTE_ERROR, SYNC_MTE_ERROR(139, "SEGV_CODE 9"),
;
public final int exitCode;
public final String stderr;
Result(int exitCode, String stderr) {
this.exitCode = exitCode;
this.stderr = stderr;
}
} }
private static final int SEGV_EXIT_CODE = 139; private static final int SEGV_EXIT_CODE = 139;
@ -31,62 +40,12 @@ public class MemtagTest extends BaseHostJUnit4Test {
var args = new ArrayList<String>(); var args = new ArrayList<String>();
args.add(TEST_BINARY); args.add(TEST_BINARY);
args.add(name); args.add(name);
var device = getDevice();
long deviceDate = device.getDeviceDate();
String cmdLine = String.join(" ", args); String cmdLine = String.join(" ", args);
var result = device.executeShellV2Command(cmdLine);
int expectedExitCode = expectedResult == Result.SUCCESS ? 0 : SEGV_EXIT_CODE; var result = getDevice().executeShellV2Command(cmdLine);
assertEquals("process exit code", expectedExitCode, result.getExitCode().intValue()); assertEquals("process exit code", expectedResult.exitCode, result.getExitCode().intValue());
assertEquals("stderr", expectedResult.stderr, result.getStderr());
if (expectedResult == Result.SUCCESS) {
return;
}
try {
// wait a bit for debuggerd to capture the crash
Thread.sleep(50);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
try (var logcat = device.getLogcatSince(deviceDate)) {
try (var s = logcat.createInputStream()) {
String[] lines = new String(s.readAllBytes()).split("\n");
boolean foundCmd = false;
String cmd = "Cmdline: " + cmdLine;
String expectedSignalCode = switch (expectedResult) {
case ASYNC_MTE_ERROR -> "SEGV_MTEAERR";
case SYNC_MTE_ERROR -> "SEGV_MTESERR";
default -> throw new IllegalStateException(expectedResult.name());
};
for (String line : lines) {
if (!foundCmd) {
if (line.contains(cmd)) {
foundCmd = true;
}
continue;
}
if (line.contains("signal 11 (SIGSEGV), code")) {
if (!line.contains(expectedSignalCode)) {
break;
} else {
return;
}
}
if (line.contains("backtrace")) {
break;
}
}
fail("missing " + expectedSignalCode + " crash in logcat");
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
} }
@Test @Test