Added Native API test
This commit is contained in:
@@ -147,7 +147,7 @@ public class Runner {
|
||||
log.log(Level.INFO, "Running " + testName + "...");
|
||||
|
||||
String testLogDir = logDir.isEmpty() ? null : logDir + '/' + testName;
|
||||
try (TestProcess p = new TestProcess(test, testLogDir, currentOs.getLibExt())) {
|
||||
try (TestProcess p = new TestProcess(test, currentOs, testLogDir)) {
|
||||
Object holder = (m.getModifiers() & Modifier.STATIC) == 0 ? m.getDeclaringClass().newInstance() : null;
|
||||
m.invoke(holder, p);
|
||||
log.info("OK");
|
||||
|
||||
@@ -16,7 +16,9 @@ import java.lang.annotation.Target;
|
||||
@Repeatable(Tests.class)
|
||||
public @interface Test {
|
||||
|
||||
Class<?> mainClass();
|
||||
String[] sh() default {};
|
||||
|
||||
Class<?> mainClass() default Test.class;
|
||||
|
||||
String args() default "";
|
||||
|
||||
|
||||
@@ -58,24 +58,10 @@ public class TestProcess implements Closeable {
|
||||
private final Map<String, File> tmpFiles = new HashMap<>();
|
||||
private final int timeout = 30;
|
||||
|
||||
public TestProcess(Test test, String logDir, String libExt) throws Exception {
|
||||
public TestProcess(Test test, Os currentOs, String logDir) throws Exception {
|
||||
this.logDir = logDir;
|
||||
|
||||
List<String> cmd = new ArrayList<>();
|
||||
cmd.add(System.getProperty("java.home") + "/bin/java");
|
||||
cmd.add("-cp");
|
||||
cmd.add(System.getProperty("java.class.path"));
|
||||
if (test.debugNonSafepoints()) {
|
||||
cmd.add("-XX:+UnlockDiagnosticVMOptions");
|
||||
cmd.add("-XX:+DebugNonSafepoints");
|
||||
}
|
||||
addArgs(cmd, test.jvmArgs());
|
||||
if (!test.agentArgs().isEmpty()) {
|
||||
cmd.add("-agentpath:build/lib/libasyncProfiler." + libExt + "=" + substituteFiles(test.agentArgs()));
|
||||
}
|
||||
cmd.add(test.mainClass().getName());
|
||||
addArgs(cmd, test.args());
|
||||
|
||||
List<String> cmd = buildCommandLine(test, currentOs);
|
||||
log.log(Level.FINE, "Running " + cmd);
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(cmd).inheritIO();
|
||||
@@ -87,8 +73,39 @@ public class TestProcess implements Closeable {
|
||||
}
|
||||
this.p = pb.start();
|
||||
|
||||
// Give the JVM some time to initialize
|
||||
Thread.sleep(700);
|
||||
if (cmd.get(0).endsWith("java")) {
|
||||
// Give the JVM some time to initialize
|
||||
Thread.sleep(700);
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> buildCommandLine(Test test, Os currentOs) {
|
||||
List<String> cmd = new ArrayList<>();
|
||||
|
||||
String[] sh = test.sh();
|
||||
if (sh.length > 0) {
|
||||
cmd.add("/bin/sh");
|
||||
cmd.add("-e");
|
||||
cmd.add("-c");
|
||||
cmd.add(substituteFiles(String.join(";", sh)));
|
||||
} else {
|
||||
cmd.add(System.getProperty("java.home") + "/bin/java");
|
||||
cmd.add("-cp");
|
||||
cmd.add(System.getProperty("java.class.path"));
|
||||
if (test.debugNonSafepoints()) {
|
||||
cmd.add("-XX:+UnlockDiagnosticVMOptions");
|
||||
cmd.add("-XX:+DebugNonSafepoints");
|
||||
}
|
||||
addArgs(cmd, test.jvmArgs());
|
||||
if (!test.agentArgs().isEmpty()) {
|
||||
cmd.add("-agentpath:build/lib/libasyncProfiler." + currentOs.getLibExt() + "=" +
|
||||
substituteFiles(test.agentArgs()));
|
||||
}
|
||||
cmd.add(test.mainClass().getName());
|
||||
addArgs(cmd, test.args());
|
||||
}
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
private String getExtFromFile(File file) {
|
||||
@@ -124,7 +141,7 @@ public class TestProcess implements Closeable {
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
do {
|
||||
File f = createTempFile(m.group(1));
|
||||
File f = createTempFile(m.group(1), m.group(2));
|
||||
m.appendReplacement(sb, f.getPath());
|
||||
} while (m.find());
|
||||
|
||||
@@ -132,13 +149,17 @@ public class TestProcess implements Closeable {
|
||||
}
|
||||
|
||||
private File createTempFile(String fileId) {
|
||||
try {
|
||||
File f = File.createTempFile("ap-" + fileId.substring(1), null);
|
||||
tmpFiles.put(fileId, f);
|
||||
return f;
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
return createTempFile(fileId, null);
|
||||
}
|
||||
|
||||
private File createTempFile(String fileId, String ext) {
|
||||
return tmpFiles.computeIfAbsent(fileId, key -> {
|
||||
try {
|
||||
return File.createTempFile("ap-" + key.substring(1), ext);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void clearTempFiles() {
|
||||
@@ -199,6 +220,10 @@ public class TestProcess implements Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
public int exitCode() {
|
||||
return p.exitValue();
|
||||
}
|
||||
|
||||
public Output waitForExit(String fileId) throws TimeoutException, InterruptedException {
|
||||
waitForExit(p, timeout);
|
||||
return readFile(fileId);
|
||||
@@ -239,8 +264,12 @@ public class TestProcess implements Closeable {
|
||||
return readFile(PROFOUT);
|
||||
}
|
||||
|
||||
public File getFile(String fileId) {
|
||||
return tmpFiles.get(fileId);
|
||||
}
|
||||
|
||||
public Output readFile(String fileId) {
|
||||
File f = tmpFiles.get(fileId);
|
||||
File f = getFile(fileId);
|
||||
try (Stream<String> stream = Files.lines(f.toPath())) {
|
||||
return new Output(stream.toArray(String[]::new));
|
||||
} catch (IOException e) {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright The async-profiler authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package test.c;
|
||||
|
||||
import one.profiler.test.Os;
|
||||
import one.profiler.test.Output;
|
||||
import one.profiler.test.Test;
|
||||
import one.profiler.test.TestProcess;
|
||||
|
||||
public class CTests {
|
||||
|
||||
// TODO: Make the test work on macOS
|
||||
@Test(sh = {"gcc -Isrc test/test/c/nativeApi.c -ldl -o%c", "%c %f.jfr"}, output = true, os = Os.LINUX)
|
||||
public void nativeApi(TestProcess p) throws Exception {
|
||||
Output out = p.waitForExit(TestProcess.STDOUT);
|
||||
assert p.exitCode() == 0;
|
||||
assert out.contains("Starting profiler");
|
||||
assert out.contains("Stopping profiler");
|
||||
assert p.getFile("%f").length() > 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright The async-profiler authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "asprof.h"
|
||||
|
||||
|
||||
static void fail(const char* msg) {
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void uninterruptible_sleep(unsigned long ms) {
|
||||
struct timespec ts = {ms / 1000, (ms % 1000) * 1000000};
|
||||
while (nanosleep(&ts, &ts) < 0 && errno == EINTR) ;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
fail("Too few arguments");
|
||||
}
|
||||
|
||||
void* lib = dlopen("build/lib/libasyncProfiler.so", RTLD_NOW);
|
||||
if (lib == NULL) {
|
||||
fail("Failed to load libasyncProfiler.so");
|
||||
}
|
||||
|
||||
asprof_init_t asprof_init = dlsym(lib, "asprof_init");
|
||||
asprof_init();
|
||||
|
||||
char cmd[4096];
|
||||
snprintf(cmd, sizeof(cmd), "start,event=cpu,interval=1ms,wall=10ms,cstack=dwarf,loglevel=debug,file=%s", argv[1]);
|
||||
|
||||
printf("Starting profiler\n");
|
||||
asprof_execute_t asprof_execute = dlsym(lib, "asprof_execute");
|
||||
asprof_error_t err = asprof_execute(cmd, NULL);
|
||||
if (err != NULL) {
|
||||
fail(err);
|
||||
}
|
||||
|
||||
uninterruptible_sleep(2000);
|
||||
|
||||
printf("Stopping profiler\n");
|
||||
err = asprof_execute("stop", NULL);
|
||||
if (err != NULL) {
|
||||
fail(err);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user