diff options
62 files changed, 330 insertions, 106 deletions
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 94d6b19d..73c4fdf8 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -39,10 +39,10 @@ repositories { dependencies { implementation(kotlin("gradle-plugin", version = "1.4.31")) implementation("org.jlleitschuh.gradle:ktlint-gradle:10.0.0") - implementation("org.jetbrains.dokka:dokka-gradle-plugin:0.10.1") implementation("org.jetbrains.kotlin:kotlin-allopen:1.4.31") implementation("org.jetbrains.kotlinx:kotlinx-benchmark-plugin:0.3.0") implementation("org.jetbrains.dokka:dokka-gradle-plugin:1.4.32") + implementation("gradle.plugin.com.github.jengelman.gradle.plugins:shadow:7.0.0") } tasks.withType<KotlinCompile>().configureEach { diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 6aa9260b..bb187a40 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -26,7 +26,6 @@ import org.gradle.api.JavaVersion import org.gradle.api.Project import org.gradle.kotlin.dsl.extra import kotlin.properties.ReadOnlyProperty -import kotlin.reflect.KProperty /** * This class contains the versions of the dependencies shared by the different @@ -46,6 +45,7 @@ public class Versions(private val project: Project) { val slf4j by version() val kotlinLogging by version(name = "kotlin-logging") val log4j by version() + val config by version() val kotlinxCoroutines by version(name = "kotlinx-coroutines") diff --git a/buildSrc/src/main/kotlin/distribution-conventions.gradle.kts b/buildSrc/src/main/kotlin/distribution-conventions.gradle.kts index a0b7593d..57e5b284 100644 --- a/buildSrc/src/main/kotlin/distribution-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/distribution-conventions.gradle.kts @@ -39,12 +39,23 @@ distributions { from("README.md") from("LICENSE.txt") + from("docs") { into("docs") } - // Include the distributions of the sub project. + // Include distributions of the subprojects getTasksByName("assembleDist", true) .filter { it.project != project } - .map { it.project.the<DistributionContainer>()["main"] } - .forEach { with(it.contents) } + .map { it.project.name to it.project.the<DistributionContainer>() } + .forEach { (name, dist) -> + dist.findByName("main")?.let { with(it.contents) } + + // Include experiments if they exist + val experiment = dist.findByName("experiment") + if (experiment != null) { + into("experiments/${name.removePrefix("opendc-experiments-")}") { + with(experiment.contents) + } + } + } } } } diff --git a/buildSrc/src/main/kotlin/experiment-conventions.gradle.kts b/buildSrc/src/main/kotlin/experiment-conventions.gradle.kts index 4745ff1a..580f67cb 100644 --- a/buildSrc/src/main/kotlin/experiment-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/experiment-conventions.gradle.kts @@ -1,3 +1,5 @@ +import gradle.kotlin.dsl.accessors._9bf86420fccbde1948375f641de89b70.sourceSets + /* * Copyright (c) 2021 AtLarge Research * @@ -22,10 +24,12 @@ plugins { `java-library` + distribution + id("com.github.johnrengelman.shadow") } dependencies { - implementation(project(":opendc-harness")) + runtimeOnly(project(":opendc-harness:opendc-harness-junit5")) } tasks.register<Test>("experiment") { @@ -38,3 +42,20 @@ tasks.register<Test>("experiment") { testClassesDirs = sourceSets["main"].output.classesDirs classpath = sourceSets["main"].runtimeClasspath } + +distributions { + create("experiment") { + contents { + from("README.md") + from(tasks.shadowJar.get()) + } + } +} + +tasks.shadowJar { + dependencies { + // Do not include the JUnit 5 runner in the final shadow jar, since it is only necessary for development + // inside IDE + exclude(project(":opendc-harness:opendc-harness-junit5")) + } +} diff --git a/gradle.properties b/gradle.properties index cbe19a08..20f4b711 100644 --- a/gradle.properties +++ b/gradle.properties @@ -47,6 +47,7 @@ hadoop-client.version = 3.2.1 sentry-log4j2.version = 4.2.0 mongodb-driver-sync.version = 4.2.1 classgraph.version = 4.8.102 +config.version = 1.4.1 # Dependencies (Testing) junit-jupiter.version = 5.7.1 diff --git a/opendc-experiments/opendc-experiments-capelin/build.gradle.kts b/opendc-experiments/opendc-experiments-capelin/build.gradle.kts index b2d7cc30..06a35c4b 100644 --- a/opendc-experiments/opendc-experiments-capelin/build.gradle.kts +++ b/opendc-experiments/opendc-experiments-capelin/build.gradle.kts @@ -31,7 +31,7 @@ plugins { dependencies { api(platform(project(":opendc-platform"))) - api(project(":opendc-harness")) + api(project(":opendc-harness:opendc-harness-engine")) implementation(project(":opendc-format")) implementation(project(":opendc-simulator:opendc-simulator-core")) implementation(project(":opendc-simulator:opendc-simulator-compute")) @@ -39,6 +39,7 @@ dependencies { implementation(project(":opendc-compute:opendc-compute-simulator")) implementation("io.github.microutils:kotlin-logging") + implementation("com.typesafe:config") implementation("me.tongfei:progressbar:${versions["progressbar"]}") implementation("com.github.ajalt.clikt:clikt:${versions["clikt"]}") diff --git a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/Portfolio.kt b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/Portfolio.kt index fc6f79d3..b70eefb2 100644 --- a/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/Portfolio.kt +++ b/opendc-experiments/opendc-experiments-capelin/src/main/kotlin/org/opendc/experiments/capelin/Portfolio.kt @@ -22,6 +22,7 @@ package org.opendc.experiments.capelin +import com.typesafe.config.ConfigFactory import io.opentelemetry.sdk.metrics.export.MetricProducer import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.cancel @@ -60,19 +61,9 @@ public abstract class Portfolio(name: String) : Experiment(name) { private val logger = KotlinLogging.logger {} /** - * The path to where the environments are located. + * The configuration to use. */ - private val environmentPath by anyOf(File("input/environments/")) - - /** - * The path to where the traces are located. - */ - private val tracePath by anyOf(File("input/traces/")) - - /** - * The path to where the output results should be written. - */ - private val outputPath by anyOf(File("output/")) + private val config = ConfigFactory.load().getConfig("opendc.experiments.capelin") /** * The path to the original VM placements file. @@ -115,7 +106,7 @@ public abstract class Portfolio(name: String) : Experiment(name) { @OptIn(ExperimentalCoroutinesApi::class) override fun doRun(repeat: Int): Unit = runBlockingSimulation { val seeder = Random(repeat.toLong()) - val environment = Sc20ClusterEnvironmentReader(File(environmentPath, "${topology.name}.txt")) + val environment = Sc20ClusterEnvironmentReader(File(config.getString("env-path"), "${topology.name}.txt")) val chan = Channel<Unit>(Channel.CONFLATED) val allocationPolicy = createComputeScheduler(seeder) @@ -131,7 +122,7 @@ public abstract class Portfolio(name: String) : Experiment(name) { val rawReaders = workloadNames.map { workloadName -> traceReaders.computeIfAbsent(workloadName) { logger.info { "Loading trace $workloadName" } - Sc20RawParquetTraceReader(File(tracePath, workloadName)) + Sc20RawParquetTraceReader(File(config.getString("trace-path"), workloadName)) } } @@ -141,7 +132,7 @@ public abstract class Portfolio(name: String) : Experiment(name) { val trace = Sc20ParquetTraceReader(rawReaders, performanceInterferenceModel, workload, seeder.nextInt()) val monitor = ParquetExperimentMonitor( - outputPath, + File(config.getString("output-path")), "portfolio_id=$name/scenario_id=$id/run_id=$repeat", 4096 ) diff --git a/opendc-experiments/opendc-experiments-capelin/src/main/resources/application.conf b/opendc-experiments/opendc-experiments-capelin/src/main/resources/application.conf new file mode 100644 index 00000000..f0e0f2d3 --- /dev/null +++ b/opendc-experiments/opendc-experiments-capelin/src/main/resources/application.conf @@ -0,0 +1,6 @@ +# Default configuration for the Capelin experiments +opendc.experiments.capelin { + env-path = input/environments/ + trace-path = input/traces/ + output-path = output +} diff --git a/opendc-experiments/opendc-experiments-energy21/build.gradle.kts b/opendc-experiments/opendc-experiments-energy21/build.gradle.kts index 32b1086d..fc37fc1c 100644 --- a/opendc-experiments/opendc-experiments-energy21/build.gradle.kts +++ b/opendc-experiments/opendc-experiments-energy21/build.gradle.kts @@ -27,17 +27,11 @@ plugins { `kotlin-library-conventions` `experiment-conventions` `testing-conventions` - application -} - -application { - mainClass.set("org.opendc.harness.runner.console.ConsoleRunnerKt") - applicationDefaultJvmArgs = listOf("-Xms2500M") } dependencies { api(platform(project(":opendc-platform"))) - api(project(":opendc-harness")) + api(project(":opendc-harness:opendc-harness-engine")) implementation(project(":opendc-format")) implementation(project(":opendc-simulator:opendc-simulator-core")) implementation(project(":opendc-simulator:opendc-simulator-compute")) @@ -45,6 +39,7 @@ dependencies { implementation(project(":opendc-experiments:opendc-experiments-capelin")) implementation(project(":opendc-telemetry:opendc-telemetry-sdk")) implementation("io.github.microutils:kotlin-logging") + implementation("com.typesafe:config") implementation("org.apache.parquet:parquet-avro:${versions["parquet-avro"]}") implementation("org.apache.hadoop:hadoop-client:${versions["hadoop-client"]}") { diff --git a/opendc-experiments/opendc-experiments-energy21/src/main/kotlin/org/opendc/experiments/energy21/EnergyExperiment.kt b/opendc-experiments/opendc-experiments-energy21/src/main/kotlin/org/opendc/experiments/energy21/EnergyExperiment.kt index bb6dcd3a..7460a1e7 100644 --- a/opendc-experiments/opendc-experiments-energy21/src/main/kotlin/org/opendc/experiments/energy21/EnergyExperiment.kt +++ b/opendc-experiments/opendc-experiments-energy21/src/main/kotlin/org/opendc/experiments/energy21/EnergyExperiment.kt @@ -22,11 +22,11 @@ package org.opendc.experiments.energy21 +import com.typesafe.config.ConfigFactory import io.opentelemetry.api.metrics.MeterProvider import io.opentelemetry.sdk.metrics.SdkMeterProvider import io.opentelemetry.sdk.metrics.export.MetricProducer import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.coroutineScope import mu.KotlinLogging @@ -66,14 +66,9 @@ public class EnergyExperiment : Experiment("Energy Modeling 2021") { private val logger = KotlinLogging.logger {} /** - * The path to where the traces are located. + * The configuration to use. */ - private val tracePath by anyOf(File("input/traces/")) - - /** - * The path to where the output results should be written. - */ - private val outputPath by anyOf(File("output/")) + private val config = ConfigFactory.load().getConfig("opendc.experiments.energy21") /** * The traces to test. @@ -85,9 +80,7 @@ public class EnergyExperiment : Experiment("Energy Modeling 2021") { */ private val powerModel by anyOf(PowerModelType.LINEAR, PowerModelType.CUBIC, PowerModelType.INTERPOLATION) - @OptIn(ExperimentalCoroutinesApi::class) override fun doRun(repeat: Int): Unit = runBlockingSimulation { - val chan = Channel<Unit>(Channel.CONFLATED) val allocationPolicy = FilterScheduler( filters = listOf(ComputeFilter(), ComputeCapabilitiesFilter()), @@ -99,8 +92,8 @@ public class EnergyExperiment : Experiment("Energy Modeling 2021") { .setClock(clock.toOtelClock()) .build() - val monitor = ParquetExperimentMonitor(outputPath, "power_model=$powerModel/run_id=$repeat", 4096) - val trace = Sc20StreamingParquetTraceReader(File(tracePath, trace), random = Random(1).asKotlinRandom()) + val monitor = ParquetExperimentMonitor(File(config.getString("output-path")), "power_model=$powerModel/run_id=$repeat", 4096) + val trace = Sc20StreamingParquetTraceReader(File(config.getString("trace-path"), trace), random = Random(1).asKotlinRandom()) withComputeService(clock, meterProvider, allocationPolicy) { scheduler -> withMonitor(monitor, clock, meterProvider as MetricProducer, scheduler) { diff --git a/opendc-experiments/opendc-experiments-energy21/src/main/resources/application.conf b/opendc-experiments/opendc-experiments-energy21/src/main/resources/application.conf new file mode 100644 index 00000000..3e011862 --- /dev/null +++ b/opendc-experiments/opendc-experiments-energy21/src/main/resources/application.conf @@ -0,0 +1,8 @@ +# Default configuration for the energy experiments +opendc.experiments.energy21 { + # Path to the directory containing the input traces + trace-path = input/traces + + # Path to the output directory to write the results to + output-path = output +} diff --git a/opendc-experiments/opendc-experiments-serverless20/build.gradle.kts b/opendc-experiments/opendc-experiments-serverless20/build.gradle.kts index 40b15af4..f19d6067 100644 --- a/opendc-experiments/opendc-experiments-serverless20/build.gradle.kts +++ b/opendc-experiments/opendc-experiments-serverless20/build.gradle.kts @@ -31,12 +31,13 @@ plugins { dependencies { api(platform(project(":opendc-platform"))) - api(project(":opendc-harness")) + api(project(":opendc-harness:opendc-harness-engine")) implementation(project(":opendc-serverless:opendc-serverless-service")) implementation(project(":opendc-serverless:opendc-serverless-simulator")) implementation(project(":opendc-telemetry:opendc-telemetry-sdk")) - + implementation(project(":opendc-harness:opendc-harness-cli")) implementation("io.github.microutils:kotlin-logging") + implementation("com.typesafe:config") implementation("org.apache.parquet:parquet-avro:${versions["parquet-avro"]}") implementation("org.apache.hadoop:hadoop-client:${versions["hadoop-client"]}") { diff --git a/opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/ServerlessExperiment.kt b/opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/ServerlessExperiment.kt index 67b5ea54..3ff01e39 100644 --- a/opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/ServerlessExperiment.kt +++ b/opendc-experiments/opendc-experiments-serverless20/src/main/kotlin/org/opendc/experiments/serverless/ServerlessExperiment.kt @@ -22,9 +22,9 @@ package org.opendc.experiments.serverless +import com.typesafe.config.ConfigFactory import io.opentelemetry.api.metrics.MeterProvider import io.opentelemetry.sdk.metrics.SdkMeterProvider -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -59,14 +59,9 @@ public class ServerlessExperiment : Experiment("Serverless") { private val logger = KotlinLogging.logger {} /** - * The path to where the traces are located. + * The configuration to use. */ - private val tracePath by anyOf(File("../../input/traces/serverless")) - - /** - * The path to where the output results should be written. - */ - private val outputPath by anyOf(File("output/")) + private val config = ConfigFactory.load().getConfig("opendc.experiments.serverless20") /** * The routing policy to test. @@ -78,14 +73,13 @@ public class ServerlessExperiment : Experiment("Serverless") { */ private val coldStartModel by anyOf(ColdStartModel.LAMBDA, ColdStartModel.AZURE, ColdStartModel.GOOGLE) - @OptIn(ExperimentalCoroutinesApi::class) override fun doRun(repeat: Int): Unit = runBlockingSimulation { val meterProvider: MeterProvider = SdkMeterProvider .builder() .setClock(clock.toOtelClock()) .build() - val trace = ServerlessTraceReader().parse(tracePath) + val trace = ServerlessTraceReader().parse(File(config.getString("trace-path"))) val traceById = trace.associateBy { it.id } val delayInjector = StochasticDelayInjector(coldStartModel, Random()) val deployer = SimFunctionDeployer(clock, this, createMachineModel(), delayInjector) { FunctionTraceWorkload(traceById.getValue(it.name)) } diff --git a/opendc-experiments/opendc-experiments-serverless20/src/main/resources/application.conf b/opendc-experiments/opendc-experiments-serverless20/src/main/resources/application.conf new file mode 100644 index 00000000..a065c5d6 --- /dev/null +++ b/opendc-experiments/opendc-experiments-serverless20/src/main/resources/application.conf @@ -0,0 +1,8 @@ +# Default configuration for the serverless experiments +opendc.experiments.serverless20 { + # Path to the directory containing the serverless trace + trace-path = input/traces/serverless + + # Path to the output directory to write the results to + output-path = output +} diff --git a/opendc-harness/build.gradle.kts b/opendc-harness/build.gradle.kts index 01b4ecd6..7a9a8463 100644 --- a/opendc-harness/build.gradle.kts +++ b/opendc-harness/build.gradle.kts @@ -21,25 +21,3 @@ */ description = "Harness for defining repeatable experiments using OpenDC" - -/* Build configuration */ -plugins { - `kotlin-library-conventions` - `testing-conventions` - `jacoco-conventions` -} - -dependencies { - api(platform(project(":opendc-platform"))) - api("org.jetbrains.kotlinx:kotlinx-coroutines-core") - api("org.junit.platform:junit-platform-commons:${versions.junitPlatform}") - - implementation("org.junit.platform:junit-platform-engine:${versions.junitPlatform}") - implementation("io.github.classgraph:classgraph:${versions["classgraph"]}") - implementation("io.github.microutils:kotlin-logging") - - implementation("com.github.ajalt.clikt:clikt:${versions["clikt"]}") - implementation("me.tongfei:progressbar:${versions["progressbar"]}") - - runtimeOnly("org.apache.logging.log4j:log4j-slf4j-impl:${versions.log4j}") -} diff --git a/opendc-harness/opendc-harness-api/build.gradle.kts b/opendc-harness/opendc-harness-api/build.gradle.kts new file mode 100644 index 00000000..67b1ce11 --- /dev/null +++ b/opendc-harness/opendc-harness-api/build.gradle.kts @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +description = "API for OpenDC Experiment Harness" + +/* Build configuration */ +plugins { + `kotlin-library-conventions` +} + +dependencies { + api(platform(project(":opendc-platform"))) + api("org.junit.platform:junit-platform-commons:${versions.junitPlatform}") + + implementation("io.github.microutils:kotlin-logging") +} diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/api/ExperimentDefinition.kt b/opendc-harness/opendc-harness-api/src/main/kotlin/org/opendc/harness/api/ExperimentDefinition.kt index 88b26ee1..c90717d2 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/api/ExperimentDefinition.kt +++ b/opendc-harness/opendc-harness-api/src/main/kotlin/org/opendc/harness/api/ExperimentDefinition.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 AtLarge Research + * Copyright (c) 2021 AtLarge Research * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/api/Parameter.kt b/opendc-harness/opendc-harness-api/src/main/kotlin/org/opendc/harness/api/Parameter.kt index bb5c8c2b..1f4fdde1 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/api/Parameter.kt +++ b/opendc-harness/opendc-harness-api/src/main/kotlin/org/opendc/harness/api/Parameter.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 AtLarge Research + * Copyright (c) 2021 AtLarge Research * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/api/Scenario.kt b/opendc-harness/opendc-harness-api/src/main/kotlin/org/opendc/harness/api/Scenario.kt index a8dbf01e..a8dbf01e 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/api/Scenario.kt +++ b/opendc-harness/opendc-harness-api/src/main/kotlin/org/opendc/harness/api/Scenario.kt diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/api/Trial.kt b/opendc-harness/opendc-harness-api/src/main/kotlin/org/opendc/harness/api/Trial.kt index 2d6ecd19..2d6ecd19 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/api/Trial.kt +++ b/opendc-harness/opendc-harness-api/src/main/kotlin/org/opendc/harness/api/Trial.kt diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/dsl/Experiment.kt b/opendc-harness/opendc-harness-api/src/main/kotlin/org/opendc/harness/dsl/Experiment.kt index 41d4207a..41d4207a 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/dsl/Experiment.kt +++ b/opendc-harness/opendc-harness-api/src/main/kotlin/org/opendc/harness/dsl/Experiment.kt diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/dsl/ParameterProvider.kt b/opendc-harness/opendc-harness-api/src/main/kotlin/org/opendc/harness/dsl/ParameterProvider.kt index e4bb9c64..e4bb9c64 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/dsl/ParameterProvider.kt +++ b/opendc-harness/opendc-harness-api/src/main/kotlin/org/opendc/harness/dsl/ParameterProvider.kt diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/dsl/Parameters.kt b/opendc-harness/opendc-harness-api/src/main/kotlin/org/opendc/harness/dsl/Parameters.kt index 7d269ba1..7d269ba1 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/dsl/Parameters.kt +++ b/opendc-harness/opendc-harness-api/src/main/kotlin/org/opendc/harness/dsl/Parameters.kt diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/internal/ParameterDelegate.kt b/opendc-harness/opendc-harness-api/src/main/kotlin/org/opendc/harness/internal/ParameterDelegate.kt index aaf90b99..aaf90b99 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/internal/ParameterDelegate.kt +++ b/opendc-harness/opendc-harness-api/src/main/kotlin/org/opendc/harness/internal/ParameterDelegate.kt diff --git a/opendc-harness/opendc-harness-cli/build.gradle.kts b/opendc-harness/opendc-harness-cli/build.gradle.kts new file mode 100644 index 00000000..3e169e2a --- /dev/null +++ b/opendc-harness/opendc-harness-cli/build.gradle.kts @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +description = "Command line interface of OpenDC Harness" + +/* Build configuration */ +plugins { + `kotlin-library-conventions` + application +} + +application { + applicationName = "opendc-harness" + mainClass.set("org.opendc.harness.runner.cli.ConsoleRunnerKt") +} + +dependencies { + api(platform(project(":opendc-platform"))) + api(project(":opendc-harness:opendc-harness-engine")) + + implementation("io.github.microutils:kotlin-logging") + implementation("com.github.ajalt.clikt:clikt:${versions["clikt"]}") + implementation("me.tongfei:progressbar:${versions["progressbar"]}") + + runtimeOnly("org.apache.logging.log4j:log4j-slf4j-impl:${versions.log4j}") +} diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/runner/console/ConsoleExperimentReporter.kt b/opendc-harness/opendc-harness-cli/src/main/kotlin/org/opendc/harness/runner/cli/ConsoleExperimentReporter.kt index 2db74ef4..7177467a 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/runner/console/ConsoleExperimentReporter.kt +++ b/opendc-harness/opendc-harness-cli/src/main/kotlin/org/opendc/harness/runner/cli/ConsoleExperimentReporter.kt @@ -20,7 +20,7 @@ * SOFTWARE. */ -package org.opendc.harness.runner.console +package org.opendc.harness.runner.cli import me.tongfei.progressbar.ProgressBar import me.tongfei.progressbar.ProgressBarBuilder diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/runner/console/ConsoleRunner.kt b/opendc-harness/opendc-harness-cli/src/main/kotlin/org/opendc/harness/runner/cli/ConsoleRunner.kt index ae221c7f..06800f0e 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/runner/console/ConsoleRunner.kt +++ b/opendc-harness/opendc-harness-cli/src/main/kotlin/org/opendc/harness/runner/cli/ConsoleRunner.kt @@ -20,19 +20,26 @@ * SOFTWARE. */ -package org.opendc.harness.runner.console +package org.opendc.harness.runner.cli import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.parameters.arguments.argument +import com.github.ajalt.clikt.parameters.arguments.multiple +import com.github.ajalt.clikt.parameters.arguments.unique import com.github.ajalt.clikt.parameters.options.default import com.github.ajalt.clikt.parameters.options.multiple import com.github.ajalt.clikt.parameters.options.option +import com.github.ajalt.clikt.parameters.options.unique +import com.github.ajalt.clikt.parameters.types.file import com.github.ajalt.clikt.parameters.types.int import mu.KotlinLogging +import org.junit.platform.commons.util.ClassLoaderUtils import org.opendc.harness.engine.ExperimentEngineLauncher import org.opendc.harness.engine.discovery.DiscoveryProvider import org.opendc.harness.engine.discovery.DiscoveryRequest import org.opendc.harness.engine.discovery.DiscoverySelector import org.opendc.harness.engine.scheduler.ThreadPoolExperimentScheduler +import java.net.URLClassLoader /** * The logger for this experiment runner. @@ -53,23 +60,49 @@ public class ConsoleRunner : CliktCommand(name = "opendc-harness") { /** * The selected experiments to run by name. */ - private val experiments by option("-e", "--experiments", help = "Names of experiments to explore") - .multiple(emptyList()) + private val experiments by argument(help = "Experiments to explore") + .multiple() + .unique() /** * The maximum number of worker threads to use. */ private val parallelism by option("-p", "--parallelism", help = "Maximum number of concurrent simulation runs") .int() - .default(Runtime.getRuntime().availableProcessors()) + .default(Runtime.getRuntime().availableProcessors() - 1) + + /** + * Additional classpath entries to load. + */ + private val additionalClasspathEntries by option("--class-path", help = "Additional classpath entries to load") + .file(mustExist = true) + .multiple() + .unique() + + /** + * Configuration file to load. + */ + private val config by option("-c", "--config", help = "Configuration file for the experiments") + .file(mustExist = true, canBeDir = false, mustBeReadable = true) override fun run() { logger.info { "Starting OpenDC Console Experiment Runner" } - val discovery = DiscoveryProvider.createComposite() + val config = config + if (config != null) { + System.setProperty("config.file", config.path) + } + + val classLoader = createClassLoader() + // TODO: Add way to specify class loader for scheduler + Thread.currentThread().contextClassLoader = classLoader + + val discovery = DiscoveryProvider.createComposite(classLoader) val experiments = discovery.discover( DiscoveryRequest( - selectors = experiments.map { DiscoverySelector.Name(it) } + selectors = experiments.flatMap { + listOf(DiscoverySelector.Name(it), DiscoverySelector.Meta("class.name", it)) + } ) ) @@ -91,6 +124,30 @@ public class ConsoleRunner : CliktCommand(name = "opendc-harness") { logger.info { "Finished all experiments. Exiting." } } + + /** + * Create a [ClassLoader] that is used to load the + */ + private fun createClassLoader(): ClassLoader { + val parent = ClassLoaderUtils.getDefaultClassLoader() + + if (additionalClasspathEntries.isNotEmpty()) { + val urls = additionalClasspathEntries.flatMap { file -> + if (file.isDirectory) { + file.walk() + .filter { it.extension == "jar" } + .map { it.toURI().toURL() } + .toList() + } else { + listOf(file.toURI().toURL()) + } + } + + return URLClassLoader.newInstance(urls.toTypedArray(), parent) + } + + return parent + } } /** diff --git a/opendc-harness/src/main/resources/log4j2.xml b/opendc-harness/opendc-harness-cli/src/main/resources/log4j2.xml index 9553d964..32d81416 100644 --- a/opendc-harness/src/main/resources/log4j2.xml +++ b/opendc-harness/opendc-harness-cli/src/main/resources/log4j2.xml @@ -1,8 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- - ~ MIT License - ~ - ~ Copyright (c) 2020 atlarge-research + ~ Copyright (c) 2021 AtLarge Research ~ ~ Permission is hereby granted, free of charge, to any person obtaining a copy ~ of this software and associated documentation files (the "Software"), to deal diff --git a/opendc-harness/opendc-harness-engine/build.gradle.kts b/opendc-harness/opendc-harness-engine/build.gradle.kts new file mode 100644 index 00000000..bffafdac --- /dev/null +++ b/opendc-harness/opendc-harness-engine/build.gradle.kts @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +description = "Engine for running experiments using the OpenDC Harness" + +/* Build configuration */ +plugins { + `kotlin-library-conventions` + `testing-conventions` + `jacoco-conventions` +} + +dependencies { + api(platform(project(":opendc-platform"))) + api(project(":opendc-harness:opendc-harness-api")) + api("org.jetbrains.kotlinx:kotlinx-coroutines-core") + + implementation("io.github.classgraph:classgraph:${versions["classgraph"]}") + implementation("io.github.microutils:kotlin-logging") +} diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/ExperimentEngine.kt b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/ExperimentEngine.kt index a36f1f9b..a36f1f9b 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/ExperimentEngine.kt +++ b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/ExperimentEngine.kt diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/ExperimentEngineLauncher.kt b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/ExperimentEngineLauncher.kt index ddd30483..759e96f8 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/ExperimentEngineLauncher.kt +++ b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/ExperimentEngineLauncher.kt @@ -26,11 +26,11 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.runBlocking import org.opendc.harness.api.ExperimentDefinition +import org.opendc.harness.engine.internal.CompositeExperimentExecutionListener import org.opendc.harness.engine.scheduler.ExperimentScheduler import org.opendc.harness.engine.scheduler.ThreadPoolExperimentScheduler import org.opendc.harness.engine.strategy.CartesianExperimentStrategy import org.opendc.harness.engine.strategy.ExperimentStrategy -import org.opendc.harness.internal.CompositeExperimentExecutionListener /** * A builder class for conducting experiments via the [ExperimentEngine]. diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/ExperimentExecutionListener.kt b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/ExperimentExecutionListener.kt index 9ef71863..9ef71863 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/ExperimentExecutionListener.kt +++ b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/ExperimentExecutionListener.kt diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/discovery/Discovery.kt b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/discovery/Discovery.kt index f7f73b38..f7f73b38 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/discovery/Discovery.kt +++ b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/discovery/Discovery.kt diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/discovery/DiscoveryFilter.kt b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/discovery/DiscoveryFilter.kt index 219d09cd..219d09cd 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/discovery/DiscoveryFilter.kt +++ b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/discovery/DiscoveryFilter.kt diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/discovery/DiscoveryProvider.kt b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/discovery/DiscoveryProvider.kt index fad255de..c4b420c5 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/discovery/DiscoveryProvider.kt +++ b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/discovery/DiscoveryProvider.kt @@ -22,7 +22,7 @@ package org.opendc.harness.engine.discovery -import org.opendc.harness.internal.CompositeDiscovery +import org.opendc.harness.engine.internal.CompositeDiscovery import java.util.* /** @@ -40,7 +40,7 @@ public interface DiscoveryProvider { /** * Factory method for creating a new [Discovery] instance. */ - public fun create(): Discovery + public fun create(classLoader: ClassLoader): Discovery public companion object { /** @@ -58,8 +58,8 @@ public interface DiscoveryProvider { /** * Obtain a composite [Discovery] that combines the results of all available providers. */ - public fun createComposite(): Discovery { - return CompositeDiscovery(providers) + public fun createComposite(classLoader: ClassLoader): Discovery { + return CompositeDiscovery(classLoader, providers) } } } diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/discovery/DiscoveryRequest.kt b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/discovery/DiscoveryRequest.kt index 5bc08dac..5bc08dac 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/discovery/DiscoveryRequest.kt +++ b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/discovery/DiscoveryRequest.kt diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/discovery/DiscoverySelector.kt b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/discovery/DiscoverySelector.kt index 67681303..67681303 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/discovery/DiscoverySelector.kt +++ b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/discovery/DiscoverySelector.kt diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/internal/CompositeDiscovery.kt b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/internal/CompositeDiscovery.kt index 67a895e4..726125a8 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/internal/CompositeDiscovery.kt +++ b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/internal/CompositeDiscovery.kt @@ -20,7 +20,7 @@ * SOFTWARE. */ -package org.opendc.harness.internal +package org.opendc.harness.engine.internal import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.* @@ -32,11 +32,11 @@ import org.opendc.harness.engine.discovery.DiscoveryRequest /** * A composite [Discovery] instance that combines the results of multiple delegate instances. */ -internal class CompositeDiscovery(providers: Iterable<DiscoveryProvider>) : Discovery { +internal class CompositeDiscovery(classLoader: ClassLoader, providers: Iterable<DiscoveryProvider>) : Discovery { /** * The [Discovery] instances to delegate to. */ - private val delegates = providers.map { it.create() } + private val delegates = providers.map { it.create(classLoader) } @OptIn(FlowPreview::class) override fun discover(request: DiscoveryRequest): Flow<ExperimentDefinition> { diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/internal/CompositeExperimentExecutionListener.kt b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/internal/CompositeExperimentExecutionListener.kt index a3cd6bd2..62b4ca8b 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/internal/CompositeExperimentExecutionListener.kt +++ b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/internal/CompositeExperimentExecutionListener.kt @@ -20,7 +20,7 @@ * SOFTWARE. */ -package org.opendc.harness.internal +package org.opendc.harness.engine.internal import org.opendc.harness.api.ExperimentDefinition import org.opendc.harness.api.Scenario diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/internal/DslDiscovery.kt b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/internal/DslDiscovery.kt index eb6303d6..3fa3fe35 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/internal/DslDiscovery.kt +++ b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/internal/DslDiscovery.kt @@ -20,7 +20,7 @@ * SOFTWARE. */ -package org.opendc.harness.internal +package org.opendc.harness.engine.internal import io.github.classgraph.ClassGraph import io.github.classgraph.ScanResult @@ -36,7 +36,7 @@ import org.opendc.harness.engine.discovery.DiscoverySelector /** * A [Discovery] implementation that discovers [Experiment] instances on the classpath. */ -internal class DslDiscovery : Discovery { +internal class DslDiscovery(private val classLoader: ClassLoader) : Discovery { /* * Lazily memoize the results of the classpath scan. */ @@ -84,6 +84,7 @@ internal class DslDiscovery : Discovery { */ private fun scan(): ScanResult { return ClassGraph() + .addClassLoader(classLoader) .enableClassInfo() .enableExternalClasses() .ignoreClassVisibility() diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/internal/DslDiscoveryProvider.kt b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/internal/DslDiscoveryProvider.kt index 752ba4bb..6a9bd599 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/internal/DslDiscoveryProvider.kt +++ b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/internal/DslDiscoveryProvider.kt @@ -20,7 +20,7 @@ * SOFTWARE. */ -package org.opendc.harness.internal +package org.opendc.harness.engine.internal import org.opendc.harness.dsl.Experiment import org.opendc.harness.engine.discovery.Discovery @@ -32,5 +32,5 @@ import org.opendc.harness.engine.discovery.DiscoveryProvider public class DslDiscoveryProvider : DiscoveryProvider { override val id: String = "dsl" - override fun create(): Discovery = DslDiscovery() + override fun create(classLoader: ClassLoader): Discovery = DslDiscovery(classLoader) } diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/internal/ScenarioImpl.kt b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/internal/ScenarioImpl.kt index d255004d..65d19e87 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/internal/ScenarioImpl.kt +++ b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/internal/ScenarioImpl.kt @@ -20,7 +20,7 @@ * SOFTWARE. */ -package org.opendc.harness.internal +package org.opendc.harness.engine.internal import org.opendc.harness.api.ExperimentDefinition import org.opendc.harness.api.Parameter diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/scheduler/ExperimentScheduler.kt b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/scheduler/ExperimentScheduler.kt index 0265554a..0265554a 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/scheduler/ExperimentScheduler.kt +++ b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/scheduler/ExperimentScheduler.kt diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/scheduler/ExperimentSchedulerProvider.kt b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/scheduler/ExperimentSchedulerProvider.kt index a93d4bf6..a93d4bf6 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/scheduler/ExperimentSchedulerProvider.kt +++ b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/scheduler/ExperimentSchedulerProvider.kt diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/scheduler/ThreadPoolExperimentScheduler.kt b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/scheduler/ThreadPoolExperimentScheduler.kt index 1ae533cf..1ae533cf 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/scheduler/ThreadPoolExperimentScheduler.kt +++ b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/scheduler/ThreadPoolExperimentScheduler.kt diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/scheduler/ThreadPoolExperimentSchedulerProvider.kt b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/scheduler/ThreadPoolExperimentSchedulerProvider.kt index cf9a132f..cf9a132f 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/scheduler/ThreadPoolExperimentSchedulerProvider.kt +++ b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/scheduler/ThreadPoolExperimentSchedulerProvider.kt diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/strategy/CartesianExperimentStrategy.kt b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/strategy/CartesianExperimentStrategy.kt index e5e08003..733eca8f 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/strategy/CartesianExperimentStrategy.kt +++ b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/strategy/CartesianExperimentStrategy.kt @@ -25,7 +25,7 @@ package org.opendc.harness.engine.strategy import org.opendc.harness.api.ExperimentDefinition import org.opendc.harness.api.Parameter import org.opendc.harness.api.Scenario -import org.opendc.harness.internal.ScenarioImpl +import org.opendc.harness.engine.internal.ScenarioImpl /** * An [ExperimentStrategy] that takes the cartesian product of the parameters and evaluates every combination. diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/strategy/CartesianExperimentStrategyProvider.kt b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/strategy/CartesianExperimentStrategyProvider.kt index f18795a3..f18795a3 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/strategy/CartesianExperimentStrategyProvider.kt +++ b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/strategy/CartesianExperimentStrategyProvider.kt diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/strategy/ExperimentStrategy.kt b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/strategy/ExperimentStrategy.kt index 3a0148ad..3a0148ad 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/strategy/ExperimentStrategy.kt +++ b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/strategy/ExperimentStrategy.kt diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/strategy/ExperimentStrategyProvider.kt b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/strategy/ExperimentStrategyProvider.kt index 7fa05f34..7fa05f34 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/engine/strategy/ExperimentStrategyProvider.kt +++ b/opendc-harness/opendc-harness-engine/src/main/kotlin/org/opendc/harness/engine/strategy/ExperimentStrategyProvider.kt diff --git a/opendc-harness/opendc-harness-engine/src/main/resources/META-INF/services/org.opendc.harness.engine.discovery.DiscoveryProvider b/opendc-harness/opendc-harness-engine/src/main/resources/META-INF/services/org.opendc.harness.engine.discovery.DiscoveryProvider new file mode 100644 index 00000000..83ac5015 --- /dev/null +++ b/opendc-harness/opendc-harness-engine/src/main/resources/META-INF/services/org.opendc.harness.engine.discovery.DiscoveryProvider @@ -0,0 +1 @@ +org.opendc.harness.engine.internal.DslDiscoveryProvider diff --git a/opendc-harness/src/main/resources/META-INF/services/org.opendc.harness.engine.scheduler.ExperimentSchedulerProvider b/opendc-harness/opendc-harness-engine/src/main/resources/META-INF/services/org.opendc.harness.engine.scheduler.ExperimentSchedulerProvider index 2ba3a7cb..2ba3a7cb 100644 --- a/opendc-harness/src/main/resources/META-INF/services/org.opendc.harness.engine.scheduler.ExperimentSchedulerProvider +++ b/opendc-harness/opendc-harness-engine/src/main/resources/META-INF/services/org.opendc.harness.engine.scheduler.ExperimentSchedulerProvider diff --git a/opendc-harness/src/main/resources/META-INF/services/org.opendc.harness.engine.strategy.ExperimentStrategyProvider b/opendc-harness/opendc-harness-engine/src/main/resources/META-INF/services/org.opendc.harness.engine.strategy.ExperimentStrategyProvider index cb1c70ac..cb1c70ac 100644 --- a/opendc-harness/src/main/resources/META-INF/services/org.opendc.harness.engine.strategy.ExperimentStrategyProvider +++ b/opendc-harness/opendc-harness-engine/src/main/resources/META-INF/services/org.opendc.harness.engine.strategy.ExperimentStrategyProvider diff --git a/opendc-harness/src/test/kotlin/org/opendc/harness/EngineTest.kt b/opendc-harness/opendc-harness-engine/src/test/kotlin/org/opendc/harness/EngineTest.kt index 6f2989db..6955f7c5 100644 --- a/opendc-harness/src/test/kotlin/org/opendc/harness/EngineTest.kt +++ b/opendc-harness/opendc-harness-engine/src/test/kotlin/org/opendc/harness/EngineTest.kt @@ -50,7 +50,7 @@ internal class EngineTest { @Test fun discovery() { runBlocking { - val discovery = DiscoveryProvider.findById("dsl")?.create() + val discovery = DiscoveryProvider.findById("dsl")?.create(Thread.currentThread().contextClassLoader) assertNotNull(discovery) val res = mutableListOf<ExperimentDefinition>() discovery?.discover(DiscoveryRequest())?.toList(res) diff --git a/opendc-harness/src/test/kotlin/org/opendc/harness/TestExperiment.kt b/opendc-harness/opendc-harness-engine/src/test/kotlin/org/opendc/harness/TestExperiment.kt index bedd1c76..bedd1c76 100644 --- a/opendc-harness/src/test/kotlin/org/opendc/harness/TestExperiment.kt +++ b/opendc-harness/opendc-harness-engine/src/test/kotlin/org/opendc/harness/TestExperiment.kt diff --git a/opendc-harness/opendc-harness-junit5/build.gradle.kts b/opendc-harness/opendc-harness-junit5/build.gradle.kts new file mode 100644 index 00000000..aa0b78d5 --- /dev/null +++ b/opendc-harness/opendc-harness-junit5/build.gradle.kts @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +description = "JUnit Platform interface to the OpenDC Harness" + +/* Build configuration */ +plugins { + `kotlin-library-conventions` +} + +dependencies { + api(platform(project(":opendc-platform"))) + api(project(":opendc-harness:opendc-harness-engine")) + + implementation("io.github.microutils:kotlin-logging") + implementation("org.junit.platform:junit-platform-engine:${versions.junitPlatform}") +} diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/runner/junit5/JUnitExperimentExecutionListener.kt b/opendc-harness/opendc-harness-junit5/src/main/kotlin/org/opendc/harness/runner/junit5/JUnitExperimentExecutionListener.kt index 9e2b629d..9e2b629d 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/runner/junit5/JUnitExperimentExecutionListener.kt +++ b/opendc-harness/opendc-harness-junit5/src/main/kotlin/org/opendc/harness/runner/junit5/JUnitExperimentExecutionListener.kt diff --git a/opendc-harness/src/main/kotlin/org/opendc/harness/runner/junit5/OpenDCTestEngine.kt b/opendc-harness/opendc-harness-junit5/src/main/kotlin/org/opendc/harness/runner/junit5/OpenDCTestEngine.kt index ab7367b8..7fc97f6d 100644 --- a/opendc-harness/src/main/kotlin/org/opendc/harness/runner/junit5/OpenDCTestEngine.kt +++ b/opendc-harness/opendc-harness-junit5/src/main/kotlin/org/opendc/harness/runner/junit5/OpenDCTestEngine.kt @@ -25,6 +25,7 @@ package org.opendc.harness.runner.junit5 import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.emptyFlow import mu.KotlinLogging +import org.junit.platform.commons.util.ClassLoaderUtils import org.junit.platform.engine.* import org.junit.platform.engine.discovery.ClassNameFilter import org.junit.platform.engine.discovery.ClassSelector @@ -63,7 +64,7 @@ public class OpenDCTestEngine : TestEngine { val classNames = request.getSelectorsByType(ClassSelector::class.java).map { DiscoverySelector.Meta("class.name", it.className) } val classNameFilters = request.getFiltersByType(ClassNameFilter::class.java).map { DiscoveryFilter.Name(it.toPredicate()) } - val discovery = DiscoveryProvider.createComposite() + val discovery = DiscoveryProvider.createComposite(ClassLoaderUtils.getDefaultClassLoader()) val definitions = discovery.discover(DiscoveryRequest(classNames, classNameFilters)) return ExperimentEngineDescriptor(uniqueId, definitions) diff --git a/opendc-harness/src/main/resources/META-INF/services/org.junit.platform.engine.TestEngine b/opendc-harness/opendc-harness-junit5/src/main/resources/META-INF/services/org.junit.platform.engine.TestEngine index b83eec0c..b83eec0c 100644 --- a/opendc-harness/src/main/resources/META-INF/services/org.junit.platform.engine.TestEngine +++ b/opendc-harness/opendc-harness-junit5/src/main/resources/META-INF/services/org.junit.platform.engine.TestEngine diff --git a/opendc-harness/src/main/resources/META-INF/services/org.opendc.harness.engine.discovery.DiscoveryProvider b/opendc-harness/src/main/resources/META-INF/services/org.opendc.harness.engine.discovery.DiscoveryProvider deleted file mode 100644 index d6a73ded..00000000 --- a/opendc-harness/src/main/resources/META-INF/services/org.opendc.harness.engine.discovery.DiscoveryProvider +++ /dev/null @@ -1 +0,0 @@ -org.opendc.harness.internal.DslDiscoveryProvider diff --git a/opendc-platform/build.gradle.kts b/opendc-platform/build.gradle.kts index ea0591ad..3fbc144e 100644 --- a/opendc-platform/build.gradle.kts +++ b/opendc-platform/build.gradle.kts @@ -31,6 +31,7 @@ dependencies { api("org.jetbrains.kotlinx:kotlinx-coroutines-core:${versions.kotlinxCoroutines}") api("org.jetbrains.kotlinx:kotlinx-coroutines-test:${versions.kotlinxCoroutines}") + api("com.typesafe:config:1.4.1") api("io.github.microutils:kotlin-logging:${versions.kotlinLogging}") runtime("org.slf4j:slf4j-simple:${versions.slf4j}") runtime("org.apache.logging.log4j:log4j-slf4j-impl:${versions.log4j}") diff --git a/settings.gradle.kts b/settings.gradle.kts index cd0c8be5..1372f0dc 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -43,5 +43,8 @@ include(":opendc-simulator:opendc-simulator-compute") include(":opendc-simulator:opendc-simulator-failures") include(":opendc-telemetry:opendc-telemetry-api") include(":opendc-telemetry:opendc-telemetry-sdk") -include(":opendc-harness") +include(":opendc-harness:opendc-harness-api") +include(":opendc-harness:opendc-harness-engine") +include(":opendc-harness:opendc-harness-cli") +include(":opendc-harness:opendc-harness-junit5") include(":opendc-utils") |
