diff options
Diffstat (limited to 'simulator/opendc-harness')
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()) { |
