summaryrefslogtreecommitdiff
path: root/simulator/opendc-harness
diff options
context:
space:
mode:
Diffstat (limited to 'simulator/opendc-harness')
-rw-r--r--simulator/opendc-harness/build.gradle.kts25
-rw-r--r--simulator/opendc-harness/src/main/kotlin/org/opendc/harness/engine/ExperimentEngine.kt54
-rw-r--r--simulator/opendc-harness/src/main/kotlin/org/opendc/harness/runner/junit5/JUnitExperimentExecutionListener.kt10
-rw-r--r--simulator/opendc-harness/src/main/kotlin/org/opendc/harness/runner/junit5/OpenDCTestEngine.kt14
4 files changed, 59 insertions, 44 deletions
diff --git a/simulator/opendc-harness/build.gradle.kts b/simulator/opendc-harness/build.gradle.kts
index 359d2384..f980853c 100644
--- a/simulator/opendc-harness/build.gradle.kts
+++ b/simulator/opendc-harness/build.gradle.kts
@@ -24,24 +24,21 @@ description = "Harness for defining repeatable experiments using OpenDC"
/* Build configuration */
plugins {
- `kotlin-library-convention`
+ `kotlin-library-conventions`
+ `testing-conventions`
}
dependencies {
- api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${Library.KOTLINX_COROUTINES}")
- api("org.junit.platform:junit-platform-commons:${Library.JUNIT_PLATFORM}")
+ api(platform(project(":opendc-platform")))
+ api("org.jetbrains.kotlinx:kotlinx-coroutines-core")
+ api("org.junit.platform:junit-platform-commons:${versions.junitPlatform}")
- implementation("io.github.classgraph:classgraph:4.8.98")
- implementation("me.tongfei:progressbar:0.9.0")
- implementation("io.github.microutils:kotlin-logging:2.0.4")
- implementation("com.github.ajalt.clikt:clikt:3.1.0")
+ implementation("org.junit.platform:junit-platform-engine:${versions.junitPlatform}")
+ implementation("io.github.classgraph:classgraph:${versions["classgraph"]}")
+ implementation("io.github.microutils:kotlin-logging")
- api("org.junit.platform:junit-platform-engine:${Library.JUNIT_PLATFORM}")
- api("org.junit.platform:junit-platform-suite-api:${Library.JUNIT_PLATFORM}")
- api("org.junit.platform:junit-platform-launcher:${Library.JUNIT_PLATFORM}")
+ implementation("com.github.ajalt.clikt:clikt:${versions["clikt"]}")
+ implementation("me.tongfei:progressbar:${versions["progressbar"]}")
- runtimeOnly("org.apache.logging.log4j:log4j-slf4j-impl:2.14.0")
-
- testImplementation("org.junit.jupiter:junit-jupiter-api:${Library.JUNIT_JUPITER}")
- testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${Library.JUNIT_JUPITER}")
+ runtimeOnly("org.apache.logging.log4j:log4j-slf4j-impl:${versions.log4j}")
}
diff --git a/simulator/opendc-harness/src/main/kotlin/org/opendc/harness/engine/ExperimentEngine.kt b/simulator/opendc-harness/src/main/kotlin/org/opendc/harness/engine/ExperimentEngine.kt
index 65a0604d..a36f1f9b 100644
--- a/simulator/opendc-harness/src/main/kotlin/org/opendc/harness/engine/ExperimentEngine.kt
+++ b/simulator/opendc-harness/src/main/kotlin/org/opendc/harness/engine/ExperimentEngine.kt
@@ -51,38 +51,48 @@ public class ExperimentEngine(
*
* @param root The experiment to execute.
*/
- @OptIn(InternalCoroutinesApi::class)
- public suspend fun execute(root: ExperimentDefinition): Unit = supervisorScope {
+ public suspend fun execute(root: ExperimentDefinition) {
listener.experimentStarted(root)
try {
- strategy.generate(root)
- .asFlow()
- .map { scenario ->
- listener.scenarioStarted(scenario)
- scenario
- }
- .buffer(100)
- .collect { scenario ->
- val jobs = (0 until repeats).map { repeat ->
- val worker = scheduler.allocate()
+ supervisorScope {
+ strategy.generate(root)
+ .asFlow()
+ .map { scenario ->
+ listener.scenarioStarted(scenario)
+ scenario
+ }
+ .buffer(100)
+ .collect { scenario ->
launch {
- val trial = Trial(scenario, repeat)
+ val jobs = (0 until repeats).map { repeat ->
+ val worker = scheduler.allocate()
+ launch {
+ val trial = Trial(scenario, repeat)
+ try {
+ listener.trialStarted(trial)
+ worker.dispatch(trial)
+ listener.trialFinished(trial, null)
+ } catch (e: Throwable) {
+ listener.trialFinished(trial, e)
+ throw e
+ }
+ }
+ }
+
try {
- listener.trialStarted(trial)
- worker.dispatch(trial)
- listener.trialFinished(trial, null)
+ jobs.joinAll()
+ listener.scenarioFinished(scenario, null)
+ } catch (e: CancellationException) {
+ listener.scenarioFinished(scenario, null)
+ throw e
} catch (e: Throwable) {
- listener.trialFinished(trial, e)
+ listener.scenarioFinished(scenario, e)
}
}
}
+ }
- launch {
- jobs.joinAll()
- listener.scenarioFinished(scenario, null)
- }
- }
listener.experimentFinished(root, null)
} catch (e: Throwable) {
listener.experimentFinished(root, e)
diff --git a/simulator/opendc-harness/src/main/kotlin/org/opendc/harness/runner/junit5/JUnitExperimentExecutionListener.kt b/simulator/opendc-harness/src/main/kotlin/org/opendc/harness/runner/junit5/JUnitExperimentExecutionListener.kt
index 58791549..9e2b629d 100644
--- a/simulator/opendc-harness/src/main/kotlin/org/opendc/harness/runner/junit5/JUnitExperimentExecutionListener.kt
+++ b/simulator/opendc-harness/src/main/kotlin/org/opendc/harness/runner/junit5/JUnitExperimentExecutionListener.kt
@@ -24,11 +24,13 @@ package org.opendc.harness.runner.junit5
import org.junit.platform.engine.*
import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor
+import org.junit.platform.engine.support.descriptor.ClassSource
import org.junit.platform.engine.support.descriptor.EngineDescriptor
import org.opendc.harness.api.ExperimentDefinition
import org.opendc.harness.api.Scenario
import org.opendc.harness.api.Trial
import org.opendc.harness.engine.ExperimentExecutionListener
+import java.util.*
/**
* An [ExperimentExecutionListener] that notifies JUnit platform of the progress of the experiment trials.
@@ -121,6 +123,14 @@ public class JUnitExperimentExecutionListener(
override fun mayRegisterTests(): Boolean = true
override fun toString(): String = "ExperimentDescriptor"
+
+ override fun getSource(): Optional<TestSource> {
+ val cls = meta["class.name"] as? String
+ return if (cls != null)
+ Optional.of(ClassSource.from(cls))
+ else
+ Optional.empty()
+ }
}
}
diff --git a/simulator/opendc-harness/src/main/kotlin/org/opendc/harness/runner/junit5/OpenDCTestEngine.kt b/simulator/opendc-harness/src/main/kotlin/org/opendc/harness/runner/junit5/OpenDCTestEngine.kt
index 685cd41a..ab7367b8 100644
--- a/simulator/opendc-harness/src/main/kotlin/org/opendc/harness/runner/junit5/OpenDCTestEngine.kt
+++ b/simulator/opendc-harness/src/main/kotlin/org/opendc/harness/runner/junit5/OpenDCTestEngine.kt
@@ -30,13 +30,13 @@ import org.junit.platform.engine.discovery.ClassNameFilter
import org.junit.platform.engine.discovery.ClassSelector
import org.junit.platform.engine.discovery.MethodSelector
import org.junit.platform.engine.support.descriptor.EngineDescriptor
-import org.junit.platform.launcher.LauncherDiscoveryRequest
import org.opendc.harness.api.ExperimentDefinition
import org.opendc.harness.engine.ExperimentEngineLauncher
import org.opendc.harness.engine.discovery.DiscoveryFilter
import org.opendc.harness.engine.discovery.DiscoveryProvider
import org.opendc.harness.engine.discovery.DiscoveryRequest
import org.opendc.harness.engine.discovery.DiscoverySelector
+import java.util.*
/**
* A [TestEngine] implementation that is able to run experiments defined using the harness.
@@ -47,15 +47,13 @@ public class OpenDCTestEngine : TestEngine {
*/
private val logger = KotlinLogging.logger {}
- override fun getId(): String = "opendc"
+ override fun getId(): String = "opendc-harness"
- override fun discover(request: EngineDiscoveryRequest, uniqueId: UniqueId): TestDescriptor {
- // Test whether are excluded from the engines
- val isEnabled = (request as? LauncherDiscoveryRequest)?.engineFilters?.all { it.toPredicate().test(this) } ?: true
- if (!isEnabled) {
- return ExperimentEngineDescriptor(uniqueId, emptyFlow())
- }
+ override fun getGroupId(): Optional<String> = Optional.of("org.opendc")
+ override fun getArtifactId(): Optional<String> = Optional.of("opendc-harness")
+
+ override fun discover(request: EngineDiscoveryRequest, uniqueId: UniqueId): TestDescriptor {
// IntelliJ will pass a [MethodSelector] to run just a single method inside a file. In that
// case, no experiments should be discovered, since we support only experiments by class.
if (request.getSelectorsByType(MethodSelector::class.java).isNotEmpty()) {