Skip to content

Commit

Permalink
Add integration test framework (#44)
Browse files Browse the repository at this point in the history
* Create feature test module.

* Add integration tests.
  • Loading branch information
aoli-al authored Nov 1, 2024
1 parent f370c7b commit 40a1f3c
Show file tree
Hide file tree
Showing 15 changed files with 342 additions and 172 deletions.
24 changes: 15 additions & 9 deletions core/src/main/kotlin/org/pastalab/fray/core/command/Executor.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.pastalab.fray.core.command

import java.lang.reflect.InvocationTargetException
import java.net.URI
import java.net.URLClassLoader
import kotlinx.serialization.SerialName
Expand Down Expand Up @@ -37,17 +38,22 @@ data class MethodExecutor(

override fun execute() {
val clazz = Class.forName(clazz, true, Thread.currentThread().contextClassLoader)
if (args.isEmpty() && method != "main") {
val m = clazz.getMethod(method)
if (m.modifiers and java.lang.reflect.Modifier.STATIC == 0) {
val obj = clazz.getConstructor().newInstance()
m.invoke(obj)
try {

if (args.isEmpty() && method != "main") {
val m = clazz.getMethod(method)
if (m.modifiers and java.lang.reflect.Modifier.STATIC == 0) {
val obj = clazz.getConstructor().newInstance()
m.invoke(obj)
} else {
m.invoke(null)
}
} else {
m.invoke(null)
val m = clazz.getMethod(method, Array<String>::class.java)
m.invoke(null, args.toTypedArray())
}
} else {
val m = clazz.getMethod(method, Array<String>::class.java)
m.invoke(null, args.toTypedArray())
} catch (e: InvocationTargetException) {
throw e.targetException
}
}

Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class ApplicationCodeTransformer : ClassFileTransformer {
) ||
(dotClassName.startsWith("org.pastalab.fray") &&
!dotClassName.startsWith("org.pastalab.fray.benchmark") &&
!dotClassName.startsWith("org.pastalab.fray.test") &&
!dotClassName.startsWith(
"org.pastalab.fray.core.test",
))) {
Expand Down
33 changes: 33 additions & 0 deletions integration-test/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
plugins {
id("java")
}

group = "org.pastalab.fray.test"
version = "0.1.4-SNAPSHOT"

repositories {
mavenCentral()
}

dependencies {
testImplementation(platform("org.junit:junit-bom:5.10.0"))
testImplementation("org.junit.jupiter:junit-jupiter")
testImplementation(project(":core"))
testImplementation("io.github.classgraph:classgraph:4.8.177")
testCompileOnly(project(":runtime"))
}

tasks.test {
useJUnitPlatform()
val jvmti = project(":jvmti")
val jdk = project(":instrumentation:jdk")
val agent = project(":instrumentation:agent")
executable("${jdk.layout.buildDirectory.get().asFile}/java-inst/bin/java")
jvmArgs("-agentpath:${jvmti.layout.buildDirectory.get().asFile}/native-libs/libjvmti.so")
jvmArgs("-javaagent:${agent.layout.buildDirectory.get().asFile}/libs/" +
"${agent.name}-${agent.version}-shadow.jar")
jvmArgs("-Dfray.debug=true")
dependsOn(":instrumentation:jdk:build")
dependsOn(":instrumentation:agent:build")
dependsOn(":jvmti:build")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.pastalab.fray.test;

public class ExpectedException extends RuntimeException {
public ExpectedException() {
}

public ExpectedException(String message) {
super(message);
}

public ExpectedException(String message, Throwable cause) {
super(message, cause);
}

public ExpectedException(Throwable cause) {
super(cause);
}

public ExpectedException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.pastalab.fray.test.fail.wait;

import org.pastalab.fray.test.ExpectedException;

import java.util.concurrent.atomic.AtomicInteger;

public class IntStream {
public static void main(String[] args) {
AtomicInteger x = new AtomicInteger();
java.util.stream.IntStream.range(1, 10).parallel().forEach((i) -> x.compareAndSet(i-1, i+1));
if (x.get() != 10) {
throw new ExpectedException("x (" + x.get() + ") is not 10");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.pastalab.fray.test.fail.wait;

import org.pastalab.fray.test.ExpectedException;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;

public class NotifyOrder {
public static void notifyOrder() throws InterruptedException {
Object o = new Object();
CountDownLatch latch = new CountDownLatch(2);
AtomicBoolean flag = new AtomicBoolean(false);
AtomicBoolean notifyFlag = new AtomicBoolean(false);
AtomicBoolean bugFound = new AtomicBoolean(false);
Thread t1 = new Thread(() -> {
synchronized (o) {
try {
latch.countDown();
while (!notifyFlag.get()) {
o.wait();
}
flag.set(true);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
Thread t2 = new Thread(() -> {
synchronized (o) {
try {
latch.countDown();
while (!notifyFlag.get()) {
o.wait();
}
if (!flag.get()) {
bugFound.set(true);
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
t1.start();
t2.start();
latch.await();
synchronized (o) {
notifyFlag.set(true);
o.notifyAll();
}
t1.join();
t2.join();
if (bugFound.get()) {
throw new ExpectedException("notify order bug found");
}
}

public static void main(String[] args) throws InterruptedException {
notifyOrder();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.pastalab.fray.test.fail.wait;

import org.pastalab.fray.test.ExpectedException;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;

public class WaitSpuriousWakeup {
public static void main(String[] args) {
Object o = new Object();
CountDownLatch latch = new CountDownLatch(1);
AtomicBoolean flag = new AtomicBoolean(false);
Thread t = new Thread(() -> {
synchronized (o) {
try {
latch.countDown();
o.wait();
flag.set(true);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});

t.start();
try {
latch.await(); // Wait for the thread to start
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
synchronized (o) {
// Flag can be set before notify is called due to spurious wake up
if (flag.get()) {
throw new ExpectedException("Spurious wakeup bug found");
}
o.notify();
}
}
}
Loading

0 comments on commit 40a1f3c

Please sign in to comment.