summaryrefslogtreecommitdiff
path: root/opendc-simulator/opendc-simulator-compute/src/test/kotlin
diff options
context:
space:
mode:
authorDante Niewenhuis <d.niewenhuis@hotmail.com>2024-10-25 13:32:41 +0200
committerGitHub <noreply@github.com>2024-10-25 13:32:41 +0200
commit5a365dbc068f2a8cdfa9813c39cc84bb30e15637 (patch)
tree72716d562787b85e03cdc7fe1d30c827054d25a0 /opendc-simulator/opendc-simulator-compute/src/test/kotlin
parent27f5b7dcb05aefdab9b762175d538931face0aba (diff)
Rewrote the FlowEngine (#256)
* Removed unused components. Updated tests. Improved checkpointing model Improved model, started with SimPowerSource implemented FailureModels and Checkpointing First working version midway commit first update All simulation are now run with a single CPU and single MemoryUnit. multi CPUs are combined into one. This is for performance and explainability. * fixed merge conflicts * Updated M3SA paths. * Fixed small typo
Diffstat (limited to 'opendc-simulator/opendc-simulator-compute/src/test/kotlin')
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt883
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorTest.kt269
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorTest.kt234
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/ConservativeScalingGovernorTest.kt94
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/OnDemandScalingGovernorTest.kt78
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/PerformanceScalingGovernorTest.kt50
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/PowerSaveScalingGovernorTest.kt72
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/power/PowerModelTest.kt180
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimChainWorkloadTest.kt310
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimFlopsWorkloadTest.kt59
-rw-r--r--opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimTraceWorkloadTest.kt160
11 files changed, 364 insertions, 2025 deletions
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt
index be6d289c..2b6a922e 100644
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt
+++ b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/SimMachineTest.kt
@@ -22,33 +22,17 @@
package org.opendc.simulator.compute
-import io.mockk.every
-import io.mockk.mockk
-import kotlinx.coroutines.CancellationException
-import kotlinx.coroutines.cancel
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.yield
-import org.junit.jupiter.api.Assertions.assertAll
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
-import org.junit.jupiter.api.assertThrows
-import org.opendc.simulator.compute.device.SimNetworkAdapter
-import org.opendc.simulator.compute.model.Cpu
-import org.opendc.simulator.compute.model.MachineModel
-import org.opendc.simulator.compute.model.MemoryUnit
-import org.opendc.simulator.compute.model.NetworkAdapter
-import org.opendc.simulator.compute.model.StorageDevice
-import org.opendc.simulator.compute.power.CpuPowerModels
-import org.opendc.simulator.compute.workload.SimTrace
-import org.opendc.simulator.compute.workload.SimWorkload
-import org.opendc.simulator.compute.workload.SimWorkloads
-import org.opendc.simulator.flow2.FlowEngine
-import org.opendc.simulator.flow2.source.SimpleFlowSource
+import org.opendc.simulator.compute.cpu.CpuPowerModels
+import org.opendc.simulator.compute.machine.SimMachine
+import org.opendc.simulator.compute.models.CpuModel
+import org.opendc.simulator.compute.models.MachineModel
+import org.opendc.simulator.compute.models.MemoryUnit
+import org.opendc.simulator.compute.workload.TraceWorkload
+import org.opendc.simulator.engine.FlowEngine
import org.opendc.simulator.kotlin.runSimulation
-import org.opendc.simulator.network.SimNetworkSink
-import org.opendc.simulator.power.SimPowerSource
import java.util.concurrent.ThreadLocalRandom
/**
@@ -61,529 +45,390 @@ class SimMachineTest {
fun setUp() {
machineModel =
MachineModel(
- Cpu(
+ CpuModel(
0,
2,
- 1000.0,
+ 1000.0f,
"Intel",
"Xeon",
"amd64",
),
MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000 * 4),
- listOf(NetworkAdapter("Mellanox", "ConnectX-5", 25000.0)),
- listOf(StorageDevice("Samsung", "EVO", 1000.0, 250.0, 250.0)),
)
}
// @Test
- fun testFlopsWorkload() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- machine.runWorkload(SimWorkloads.flops(2_000, 1.0))
-
- // Two cores execute 1000 MFlOps per second (1000 ms)
- assertEquals(1000, timeSource.millis())
- }
+// fun testFlopsWorkload() =
+// runSimulation {
+// val engine = FlowEngine.create(dispatcher)
+// val graph = engine.newGraph()
+//
+// val machine =
+// SimBareMetalMachine.create(
+// graph,
+// machineModel,
+// )
+//
+// machine.runWorkload(SimWorkloads.flops(2_000, 1.0))
+//
+// // Two cores execute 1000 MFlOps per second (1000 ms)
+// assertEquals(1000, timeSource.millis())
+// }
@Test
fun testTraceWorkload() =
runSimulation {
val random = ThreadLocalRandom.current()
- val builder = SimTrace.builder()
- repeat(1000000) {
-// val timestamp = it.toLong() * 1000
-// val deadline = timestamp + 1000
+ val builder = TraceWorkload.builder()
+ repeat(100) {
builder.add(1000, random.nextDouble(0.0, 4500.0), 1)
}
- val trace = builder.build()
-
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
+ val traceWorkload = builder.build()
- machine.runWorkload(trace.createWorkload(0))
-
- // Two cores execute 1000 MFlOps per second (1000 ms)
- assertEquals(1000000000, timeSource.millis())
- }
-
-// @Test
- fun testDualSocketMachine() =
- runSimulation {
val engine = FlowEngine.create(dispatcher)
val graph = engine.newGraph()
-
- val cpuNode = machineModel.cpu
- val machineModel =
- MachineModel(
- List(cpuNode.coreCount * 2) {
- Cpu(
- it,
- cpuNode.coreCount,
- 1000.0,
- )
- },
- MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000 * 4),
- )
- val machine =
- SimBareMetalMachine.create(
+ val simMachine =
+ SimMachine(
graph,
machineModel,
- )
-
- machine.runWorkload(SimWorkloads.flops(2_000, 1.0))
-
- // Two sockets with two cores execute 2000 MFlOps per second (500 ms)
- assertEquals(500, timeSource.millis())
- }
-
- @Test
- fun testPower() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- SimPsuFactories.simple(CpuPowerModels.linear(100.0, 50.0)),
- )
- val source = SimPowerSource(graph, 1000.0f)
- source.connect(machine.psu)
-
- coroutineScope {
- launch { machine.runWorkload(SimWorkloads.flops(2_000, 1.0)) }
-
- yield()
- assertAll(
- { assertEquals(100.0, machine.psu.powerDraw) },
- { assertEquals(100.0f, source.powerDraw) },
- )
- }
- }
-
- @Test
- fun testCapacityClamp() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- machine.runWorkload(
- object : SimWorkload {
- override fun onStart(ctx: SimMachineContext) {
- val cpu = ctx.cpu
-
- cpu.frequency = (cpu.cpuModel.totalCapacity + 1000.0)
- assertEquals(cpu.cpuModel.totalCapacity, cpu.frequency)
- cpu.frequency = -1.0
- assertEquals(0.0, cpu.frequency)
-
- ctx.shutdown()
- }
-
- override fun setOffset(now: Long) {}
-
- override fun onStop(ctx: SimMachineContext) {}
-
- override fun makeSnapshot(now: Long) {
- }
-
- override fun getSnapshot(): SimWorkload = this
-
- override fun createCheckpointModel() {}
-
- override fun getCheckpointInterval(): Long {
- return -1
- }
-
- override fun getCheckpointDuration(): Long {
- return -1
- }
-
- override fun getCheckpointIntervalScaling(): Double {
- return -1.0
- }
- },
- )
- }
-
- @Test
- fun testMemory() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- machine.runWorkload(
- object : SimWorkload {
- override fun onStart(ctx: SimMachineContext) {
- assertEquals(32_000 * 4.0, ctx.memory.capacity)
- ctx.shutdown()
- }
-
- override fun setOffset(now: Long) {}
-
- override fun onStop(ctx: SimMachineContext) {}
-
- override fun makeSnapshot(now: Long) {}
-
- override fun getSnapshot(): SimWorkload = this
-
- override fun createCheckpointModel() {}
-
- override fun getCheckpointInterval(): Long {
- return -1
- }
-
- override fun getCheckpointDuration(): Long {
- return -1
- }
-
- override fun getCheckpointIntervalScaling(): Double {
- return -1.0
- }
- },
- )
- }
-
- @Test
- fun testMemoryUsage() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- machine.runWorkload(
- object : SimWorkload {
- override fun onStart(ctx: SimMachineContext) {
- val source = SimpleFlowSource(ctx.graph, ctx.memory.capacity.toFloat(), 1.0f) { ctx.shutdown() }
- ctx.graph.connect(source.output, ctx.memory.input)
- }
-
- override fun setOffset(now: Long) {}
-
- override fun onStop(ctx: SimMachineContext) {}
-
- override fun makeSnapshot(now: Long) {
- }
-
- override fun getSnapshot(): SimWorkload = this
-
- override fun createCheckpointModel() {}
-
- override fun getCheckpointInterval(): Long {
- return -1
- }
-
- override fun getCheckpointDuration(): Long {
- return -1
- }
-
- override fun getCheckpointIntervalScaling(): Double {
- return -1.0
- }
- },
- )
-
- assertEquals(1000, timeSource.millis())
- }
-
- @Test
- fun testNetUsage() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- val adapter = (machine.peripherals[0] as SimNetworkAdapter)
- adapter.connect(SimNetworkSink(graph, adapter.bandwidth.toFloat()))
-
- machine.runWorkload(
- object : SimWorkload {
- override fun onStart(ctx: SimMachineContext) {
- val iface = ctx.networkInterfaces[0]
- val source =
- SimpleFlowSource(ctx.graph, 800.0f, 0.8f) {
- ctx.shutdown()
- it.close()
- }
- ctx.graph.connect(source.output, iface.tx)
- }
-
- override fun setOffset(now: Long) {}
-
- override fun onStop(ctx: SimMachineContext) {}
-
- override fun makeSnapshot(now: Long) {
- }
-
- override fun getSnapshot(): SimWorkload = this
-
- override fun createCheckpointModel() {}
-
- override fun getCheckpointInterval(): Long {
- return -1
- }
-
- override fun getCheckpointDuration(): Long {
- return -1
- }
-
- override fun getCheckpointIntervalScaling(): Double {
- return -1.0
- }
- },
- )
-
- assertEquals(40, timeSource.millis())
- }
-
- @Test
- fun testDiskReadUsage() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- machine.runWorkload(
- object : SimWorkload {
- override fun onStart(ctx: SimMachineContext) {
- val disk = ctx.storageInterfaces[0]
- val source = SimpleFlowSource(ctx.graph, 800.0f, 0.8f) { ctx.shutdown() }
- ctx.graph.connect(source.output, disk.read)
- }
-
- override fun setOffset(now: Long) {}
-
- override fun onStop(ctx: SimMachineContext) {}
-
- override fun makeSnapshot(now: Long) {}
-
- override fun getSnapshot(): SimWorkload = this
-
- override fun createCheckpointModel() {}
-
- override fun getCheckpointInterval(): Long {
- return -1
- }
-
- override fun getCheckpointDuration(): Long {
- return -1
- }
-
- override fun getCheckpointIntervalScaling(): Double {
- return -1.0
- }
- },
- )
-
- assertEquals(4000, timeSource.millis())
- }
-
- @Test
- fun testDiskWriteUsage() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- machine.runWorkload(
- object : SimWorkload {
- override fun onStart(ctx: SimMachineContext) {
- val disk = ctx.storageInterfaces[0]
- val source = SimpleFlowSource(ctx.graph, 800.0f, 0.8f) { ctx.shutdown() }
- ctx.graph.connect(source.output, disk.write)
- }
-
- override fun setOffset(now: Long) {}
-
- override fun onStop(ctx: SimMachineContext) {}
-
- override fun makeSnapshot(now: Long) {}
-
- override fun getSnapshot(): SimWorkload = this
-
- override fun createCheckpointModel() {}
-
- override fun getCheckpointInterval(): Long {
- return -1
- }
-
- override fun getCheckpointDuration(): Long {
- return -1
- }
-
- override fun getCheckpointIntervalScaling(): Double {
- return -1.0
- }
- },
- )
-
- assertEquals(4000, timeSource.millis())
- }
-
- @Test
- fun testCancellation() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- try {
- coroutineScope {
- launch { machine.runWorkload(SimWorkloads.flops(2_000, 1.0)) }
- cancel()
- }
- } catch (_: CancellationException) {
- // Ignore
- }
-
- assertEquals(0, timeSource.millis())
- }
-
- @Test
- fun testConcurrentRuns() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- coroutineScope {
- launch {
- machine.runWorkload(SimWorkloads.flops(2_000, 1.0))
+ CpuPowerModels.constant(0.0),
+ ) { cause ->
}
- assertThrows<IllegalStateException> {
- machine.runWorkload(SimWorkloads.flops(2_000, 1.0))
+ val virtualMachine =
+ simMachine.startWorkload(traceWorkload) { cause ->
+ assertEquals(100000, timeSource.millis())
}
- }
- }
-
- @Test
- fun testCatchStartFailure() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- val workload = mockk<SimWorkload>()
- every { workload.onStart(any()) } throws IllegalStateException()
-
- assertThrows<IllegalStateException> { machine.runWorkload(workload) }
- }
-
- @Test
- fun testCatchStopFailure() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- val workload = mockk<SimWorkload>()
- every { workload.onStart(any()) } answers { (it.invocation.args[0] as SimMachineContext).shutdown() }
- every { workload.onStop(any()) } throws IllegalStateException()
-
- assertThrows<IllegalStateException> { machine.runWorkload(workload) }
- }
-
- @Test
- fun testCatchShutdownFailure() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- val workload = mockk<SimWorkload>()
- every { workload.onStart(any()) } answers { (it.invocation.args[0] as SimMachineContext).shutdown(IllegalStateException()) }
- assertThrows<IllegalStateException> { machine.runWorkload(workload) }
+ // Two cores execute 1000 MFlOps per second (1000 ms)
}
- @Test
- fun testCatchNestedFailure() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- val workload = mockk<SimWorkload>()
- every { workload.onStart(any()) } answers { (it.invocation.args[0] as SimMachineContext).shutdown(IllegalStateException()) }
- every { workload.onStop(any()) } throws IllegalStateException()
-
- val exc = assertThrows<IllegalStateException> { machine.runWorkload(workload) }
- assertEquals(1, exc.cause!!.suppressedExceptions.size)
- }
+// @Test
+// fun testDualSocketMachine() =
+// runSimulation {
+// val engine = FlowEngine.create(dispatcher)
+// val graph = engine.newGraph()
+//
+// val cpuNode = machineModel.cpu
+// val machineModel =
+// MachineModel(
+// List(cpuNode.coreCount * 2) {
+// CpuModel(
+// it,
+// cpuNode.coreCount,
+// 1000.0,
+// )
+// },
+// MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000 * 4),
+// )
+// val machine =
+// SimBareMetalMachine.create(
+// graph,
+// machineModel,
+// CpuPowerModels.constant(0.0)
+// )
+//
+// machine.runWorkload(SimWorkloads.flops(2_000, 1.0))
+//
+// // Two sockets with two cores execute 2000 MFlOps per second (500 ms)
+// assertEquals(500, timeSource.millis())
+// }
+//
+// // @Test
+// // fun testPower() =
+// // runSimulation {
+// // val engine = FlowEngine.create(dispatcher)
+// // val graph = engine.newGraph()
+// // val machine =
+// // SimBareMetalMachine.create(
+// // graph,
+// // machineModel,
+// // CpuPowerModels.linear(100.0, 50.0),
+// // )
+// // val source = SimPowerSource(graph, 1000.0f)
+// // source.connect(machine.psu)
+// //
+// // coroutineScope {
+// // launch { machine.runWorkload(SimWorkloads.flops(2_000, 1.0)) }
+// //
+// // yield()
+// // assertAll(
+// // { assertEquals(100.0, machine.psu.powerDraw) },
+// // { assertEquals(100.0f, source.powerDraw) },
+// // )
+// // }
+// // }
+//
+// @Test
+// fun testCapacityClamp() =
+// runSimulation {
+// val engine = FlowEngine.create(dispatcher)
+// val graph = engine.newGraph()
+//
+// val machine =
+// SimBareMetalMachine.create(
+// graph,
+// machineModel,
+// CpuPowerModels.constant(0.0)
+// )
+//
+// machine.runWorkload(
+// object : SimWorkload {
+// override fun onStart(ctx: SimMachineContext) {
+// val cpu = ctx.cpu
+//
+// cpu.frequency = (cpu.cpuModel.totalCapacity + 1000.0)
+// assertEquals(cpu.cpuModel.totalCapacity, cpu.frequency)
+// cpu.frequency = -1.0
+// assertEquals(0.0, cpu.frequency)
+//
+// ctx.shutdown()
+// }
+//
+// override fun setOffset(now: Long) {}
+//
+// override fun onStop(ctx: SimMachineContext) {}
+//
+// override fun makeSnapshot(now: Long) {
+// }
+//
+// override fun getSnapshot(): SimWorkload = this
+//
+// override fun createCheckpointModel() {}
+//
+// override fun getCheckpointInterval(): Long {
+// return -1
+// }
+//
+// override fun getCheckpointDuration(): Long {
+// return -1
+// }
+//
+// override fun getCheckpointIntervalScaling(): Double {
+// return -1.0
+// }
+// },
+// )
+// }
+//
+// @Test
+// fun testMemory() =
+// runSimulation {
+// val engine = FlowEngine.create(dispatcher)
+// val graph = engine.newGraph()
+//
+// val machine =
+// SimBareMetalMachine.create(
+// graph,
+// machineModel,
+// CpuPowerModels.constant(0.0)
+// )
+//
+// machine.runWorkload(
+// object : SimWorkload {
+// override fun onStart(ctx: SimMachineContext) {
+// assertEquals(32_000 * 4.0, ctx.memory.capacity)
+// ctx.shutdown()
+// }
+//
+// override fun setOffset(now: Long) {}
+//
+// override fun onStop(ctx: SimMachineContext) {}
+//
+// override fun makeSnapshot(now: Long) {}
+//
+// override fun getSnapshot(): SimWorkload = this
+//
+// override fun createCheckpointModel() {}
+//
+// override fun getCheckpointInterval(): Long {
+// return -1
+// }
+//
+// override fun getCheckpointDuration(): Long {
+// return -1
+// }
+//
+// override fun getCheckpointIntervalScaling(): Double {
+// return -1.0
+// }
+// },
+// )
+// }
+//
+// @Test
+// fun testMemoryUsage() =
+// runSimulation {
+// val engine = FlowEngine.create(dispatcher)
+// val graph = engine.newGraph()
+//
+// val machine =
+// SimBareMetalMachine.create(
+// graph,
+// machineModel,
+// CpuPowerModels.constant(0.0)
+// )
+//
+// machine.runWorkload(
+// object : SimWorkload {
+// override fun onStart(ctx: SimMachineContext) {
+// val source = SimpleFlowSource(ctx.graph, ctx.memory.capacity.toFloat(), 1.0f) { ctx.shutdown() }
+// ctx.graph.connect(source.output, ctx.memory.input)
+// }
+//
+// override fun setOffset(now: Long) {}
+//
+// override fun onStop(ctx: SimMachineContext) {}
+//
+// override fun makeSnapshot(now: Long) {
+// }
+//
+// override fun getSnapshot(): SimWorkload = this
+//
+// override fun createCheckpointModel() {}
+//
+// override fun getCheckpointInterval(): Long {
+// return -1
+// }
+//
+// override fun getCheckpointDuration(): Long {
+// return -1
+// }
+//
+// override fun getCheckpointIntervalScaling(): Double {
+// return -1.0
+// }
+// },
+// )
+//
+// assertEquals(1000, timeSource.millis())
+// }
+//
+// @Test
+// fun testCancellation() =
+// runSimulation {
+// val engine = FlowEngine.create(dispatcher)
+// val graph = engine.newGraph()
+//
+// val machine =
+// SimBareMetalMachine.create(
+// graph,
+// machineModel,
+// CpuPowerModels.constant(0.0)
+// )
+//
+// try {
+// coroutineScope {
+// launch { machine.runWorkload(SimWorkloads.flops(2_000, 1.0)) }
+// cancel()
+// }
+// } catch (_: CancellationException) {
+// // Ignore
+// }
+//
+// assertEquals(0, timeSource.millis())
+// }
+//
+// @Test
+// fun testConcurrentRuns() =
+// runSimulation {
+// val engine = FlowEngine.create(dispatcher)
+// val graph = engine.newGraph()
+//
+// val machine =
+// SimBareMetalMachine.create(
+// graph,
+// machineModel,
+// CpuPowerModels.constant(0.0)
+// )
+//
+// coroutineScope {
+// launch {
+// machine.runWorkload(SimWorkloads.flops(2_000, 1.0))
+// }
+//
+// assertThrows<IllegalStateException> {
+// machine.runWorkload(SimWorkloads.flops(2_000, 1.0))
+// }
+// }
+// }
+//
+// @Test
+// fun testCatchStartFailure() =
+// runSimulation {
+// val engine = FlowEngine.create(dispatcher)
+// val graph = engine.newGraph()
+//
+// val machine =
+// SimBareMetalMachine.create(
+// graph,
+// machineModel,
+// CpuPowerModels.constant(0.0)
+// )
+//
+// val workload = mockk<SimWorkload>()
+// every { workload.onStart(any()) } throws IllegalStateException()
+//
+// assertThrows<IllegalStateException> { machine.runWorkload(workload) }
+// }
+//
+// @Test
+// fun testCatchStopFailure() =
+// runSimulation {
+// val engine = FlowEngine.create(dispatcher)
+// val graph = engine.newGraph()
+//
+// val machine =
+// SimBareMetalMachine.create(
+// graph,
+// machineModel,
+// CpuPowerModels.constant(0.0)
+// )
+//
+// val workload = mockk<SimWorkload>()
+// every { workload.onStart(any()) } answers { (it.invocation.args[0] as SimMachineContext).shutdown() }
+// every { workload.onStop(any()) } throws IllegalStateException()
+//
+// assertThrows<IllegalStateException> { machine.runWorkload(workload) }
+// }
+//
+// @Test
+// fun testCatchShutdownFailure() =
+// runSimulation {
+// val engine = FlowEngine.create(dispatcher)
+// val graph = engine.newGraph()
+//
+// val machine =
+// SimBareMetalMachine.create(
+// graph,
+// machineModel,
+// CpuPowerModels.constant(0.0)
+// )
+//
+// val workload = mockk<SimWorkload>()
+// every { workload.onStart(any()) } answers { (it.invocation.args[0] as SimMachineContext).shutdown(IllegalStateException()) }
+//
+// assertThrows<IllegalStateException> { machine.runWorkload(workload) }
+// }
+//
+// @Test
+// fun testCatchNestedFailure() =
+// runSimulation {
+// val engine = FlowEngine.create(dispatcher)
+// val graph = engine.newGraph()
+//
+// val machine =
+// SimBareMetalMachine.create(
+// graph,
+// machineModel,
+// CpuPowerModels.constant(0.0)
+// )
+//
+// val workload = mockk<SimWorkload>()
+// every { workload.onStart(any()) } answers { (it.invocation.args[0] as SimMachineContext).shutdown(IllegalStateException()) }
+// every { workload.onStop(any()) } throws IllegalStateException()
+//
+// val exc = assertThrows<IllegalStateException> { machine.runWorkload(workload) }
+// assertEquals(1, exc.cause!!.suppressedExceptions.size)
+// }
}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorTest.kt
deleted file mode 100644
index 6cebc46f..00000000
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimFairShareHypervisorTest.kt
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * 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.
- */
-
-package org.opendc.simulator.compute.kernel
-
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.yield
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.BeforeEach
-import org.junit.jupiter.api.Test
-import org.junit.jupiter.api.assertAll
-import org.junit.jupiter.api.assertDoesNotThrow
-import org.opendc.simulator.compute.SimBareMetalMachine
-import org.opendc.simulator.compute.kernel.cpufreq.ScalingGovernors
-import org.opendc.simulator.compute.kernel.interference.VmInterferenceModel
-import org.opendc.simulator.compute.model.Cpu
-import org.opendc.simulator.compute.model.MachineModel
-import org.opendc.simulator.compute.model.MemoryUnit
-import org.opendc.simulator.compute.runWorkload
-import org.opendc.simulator.compute.workload.SimTrace
-import org.opendc.simulator.compute.workload.SimTraceFragment
-import org.opendc.simulator.flow2.FlowEngine
-import org.opendc.simulator.flow2.mux.FlowMultiplexerFactory
-import org.opendc.simulator.kotlin.runSimulation
-import java.util.SplittableRandom
-
-/**
- * Test suite for the [SimHypervisor] class.
- */
-internal class SimFairShareHypervisorTest {
- private lateinit var model: MachineModel
-
- @BeforeEach
- fun setUp() {
- model =
- MachineModel(
- Cpu(
- 0,
- 1,
- 3200.0,
- "Intel",
- "Xeon",
- "amd64",
- ),
- // memory
- MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000 * 4),
- )
- }
-
- /**
- * Test overcommitting of resources via the hypervisor with a single VM.
- */
- @Test
- fun testOvercommittedSingle() =
- runSimulation {
- val duration = 5 * 60L
- val workloadA =
- SimTrace.ofFragments(
- SimTraceFragment(0, duration * 1000, 28.0, 1),
- SimTraceFragment(duration * 1000, duration * 1000, 3500.0, 1),
- SimTraceFragment(duration * 2000, duration * 1000, 0.0, 1),
- SimTraceFragment(duration * 3000, duration * 1000, 183.0, 1),
- ).createWorkload(0)
-
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine = SimBareMetalMachine.create(graph, model)
- val hypervisor =
- SimHypervisor.create(
- FlowMultiplexerFactory.maxMinMultiplexer(),
- SplittableRandom(0L),
- ScalingGovernors.performance(),
- )
-
- launch { machine.runWorkload(hypervisor) }
- yield()
-
- val vm = hypervisor.newMachine(model)
- vm.runWorkload(workloadA)
-
- yield()
- machine.cancel()
-
- assertAll(
- { assertEquals(319781, hypervisor.counters.cpuActiveTime, "Active time does not match") },
- { assertEquals(880219, hypervisor.counters.cpuIdleTime, "Idle time does not match") },
- { assertEquals(28125, hypervisor.counters.cpuStealTime, "Steal time does not match") },
- { assertEquals(1200000, timeSource.millis()) { "Current time is correct" } },
- )
- }
-
- /**
- * Test overcommitting of resources via the hypervisor with two VMs.
- */
- @Test
- fun testOvercommittedDual() =
- runSimulation {
- val duration = 5 * 60L
- val workloadA =
- SimTrace.ofFragments(
- SimTraceFragment(0, duration * 1000, 28.0, 1),
- SimTraceFragment(duration * 1000, duration * 1000, 3500.0, 1),
- SimTraceFragment(duration * 2000, duration * 1000, 0.0, 1),
- SimTraceFragment(duration * 3000, duration * 1000, 183.0, 1),
- ).createWorkload(0)
- val workloadB =
- SimTrace.ofFragments(
- SimTraceFragment(0, duration * 1000, 28.0, 1),
- SimTraceFragment(duration * 1000, duration * 1000, 3100.0, 1),
- SimTraceFragment(duration * 2000, duration * 1000, 0.0, 1),
- SimTraceFragment(duration * 3000, duration * 1000, 73.0, 1),
- ).createWorkload(0)
-
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine = SimBareMetalMachine.create(graph, model)
- val hypervisor =
- SimHypervisor.create(
- FlowMultiplexerFactory.maxMinMultiplexer(),
- SplittableRandom(0L),
- ScalingGovernors.performance(),
- )
-
- launch { machine.runWorkload(hypervisor) }
-
- yield()
- coroutineScope {
- launch {
- val vm = hypervisor.newMachine(model)
- vm.runWorkload(workloadA)
- hypervisor.removeMachine(vm)
- }
- val vm = hypervisor.newMachine(model)
- vm.runWorkload(workloadB)
- hypervisor.removeMachine(vm)
- }
- yield()
- machine.cancel()
- yield()
-
- assertAll(
- { assertEquals(329250, hypervisor.counters.cpuActiveTime, "Active time does not match") },
- { assertEquals(870750, hypervisor.counters.cpuIdleTime, "Idle time does not match") },
- { assertEquals(318750, hypervisor.counters.cpuStealTime, "Steal time does not match") },
- { assertEquals(1200000, timeSource.millis()) },
- )
- }
-
- @Test
- fun testMultipleCPUs() =
- runSimulation {
- val model =
- MachineModel(
- Cpu(
- 0,
- 2,
- 3200.0,
- "Intel",
- "Xeon",
- "amd64",
- ),
- // memory
- MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000 * 4),
- )
-
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine = SimBareMetalMachine.create(graph, model)
- val hypervisor =
- SimHypervisor.create(
- FlowMultiplexerFactory.maxMinMultiplexer(),
- SplittableRandom(0L),
- ScalingGovernors.performance(),
- )
-
- assertDoesNotThrow {
- launch { machine.runWorkload(hypervisor) }
- }
-
- machine.cancel()
- }
-
- @Test
- fun testInterference() =
- runSimulation {
- val model =
- MachineModel(
- Cpu(
- 0,
- 2,
- 3200.0,
- "Intel",
- "Xeon",
- "amd64",
- ),
- // memory
- MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000 * 4),
- )
-
- val interferenceModel =
- VmInterferenceModel.builder()
- .addGroup(setOf("a", "b"), 0.0, 0.9)
- .addGroup(setOf("a", "c"), 0.0, 0.6)
- .addGroup(setOf("a", "n"), 0.1, 0.8)
- .build()
-
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine = SimBareMetalMachine.create(graph, model)
- val hypervisor = SimHypervisor.create(FlowMultiplexerFactory.maxMinMultiplexer(), SplittableRandom(0L))
-
- val duration = 5 * 60L
- val workloadA =
- SimTrace.ofFragments(
- SimTraceFragment(0, duration * 1000, 0.0, 1),
- SimTraceFragment(duration * 1000, duration * 1000, 28.0, 1),
- SimTraceFragment(duration * 2000, duration * 1000, 3500.0, 1),
- SimTraceFragment(duration * 3000, duration * 1000, 183.0, 1),
- ).createWorkload(0)
- val workloadB =
- SimTrace.ofFragments(
- SimTraceFragment(0, duration * 1000, 0.0, 1),
- SimTraceFragment(duration * 1000, duration * 1000, 28.0, 1),
- SimTraceFragment(duration * 2000, duration * 1000, 3100.0, 1),
- SimTraceFragment(duration * 3000, duration * 1000, 73.0, 1),
- ).createWorkload(0)
-
- launch {
- machine.runWorkload(hypervisor)
- }
-
- coroutineScope {
- launch {
- val vm = hypervisor.newMachine(model)
- vm.runWorkload(workloadA, meta = mapOf("interference-model" to interferenceModel.getProfile("a")!!))
- hypervisor.removeMachine(vm)
- }
- val vm = hypervisor.newMachine(model)
- vm.runWorkload(workloadB, meta = mapOf("interference-model" to interferenceModel.getProfile("b")!!))
- hypervisor.removeMachine(vm)
- }
-
- machine.cancel()
- }
-}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorTest.kt
deleted file mode 100644
index b4ae372c..00000000
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/SimSpaceSharedHypervisorTest.kt
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * 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.
- */
-
-package org.opendc.simulator.compute.kernel
-
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.yield
-import org.junit.jupiter.api.Assertions.assertAll
-import org.junit.jupiter.api.Assertions.assertDoesNotThrow
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.Assertions.assertFalse
-import org.junit.jupiter.api.Assertions.assertTrue
-import org.junit.jupiter.api.BeforeEach
-import org.junit.jupiter.api.Test
-import org.junit.jupiter.api.assertThrows
-import org.opendc.simulator.compute.SimBareMetalMachine
-import org.opendc.simulator.compute.model.Cpu
-import org.opendc.simulator.compute.model.MachineModel
-import org.opendc.simulator.compute.model.MemoryUnit
-import org.opendc.simulator.compute.runWorkload
-import org.opendc.simulator.compute.workload.SimTrace
-import org.opendc.simulator.compute.workload.SimTraceFragment
-import org.opendc.simulator.compute.workload.SimWorkloads
-import org.opendc.simulator.flow2.FlowEngine
-import org.opendc.simulator.flow2.mux.FlowMultiplexerFactory
-import org.opendc.simulator.kotlin.runSimulation
-import java.util.SplittableRandom
-
-/**
- * A test suite for a space-shared [SimHypervisor].
- */
-internal class SimSpaceSharedHypervisorTest {
- private lateinit var machineModel: MachineModel
-
- @BeforeEach
- fun setUp() {
- machineModel =
- MachineModel(
- Cpu(
- 0,
- 1,
- 3200.0,
- "Intel",
- "Xeon",
- "amd64",
- ),
- // memory
- MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000 * 4),
- )
- }
-
- /**
- * Test a trace workload.
- */
- @Test
- fun testTrace() =
- runSimulation {
- val duration = 5 * 60L
- val workloadA =
- SimTrace.ofFragments(
- SimTraceFragment(0, duration * 1000, 28.0, 1),
- SimTraceFragment(duration * 1000, duration * 1000, 3500.0, 1),
- SimTraceFragment(duration * 2000, duration * 1000, 0.0, 1),
- SimTraceFragment(duration * 3000, duration * 1000, 183.0, 1),
- ).createWorkload(0)
-
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine = SimBareMetalMachine.create(graph, machineModel)
- val hypervisor = SimHypervisor.create(FlowMultiplexerFactory.forwardingMultiplexer(), SplittableRandom(0L))
-
- launch { machine.runWorkload(hypervisor) }
- val vm = hypervisor.newMachine(machineModel)
- vm.runWorkload(workloadA)
- yield()
-
- hypervisor.removeMachine(vm)
- machine.cancel()
-
- assertEquals(5 * 60L * 4000, timeSource.millis()) { "Took enough time" }
- }
-
- /**
- * Test runtime workload on hypervisor.
- */
- @Test
- fun testRuntimeWorkload() =
- runSimulation {
- val duration = 5 * 60L * 1000
- val workload = SimWorkloads.runtime(duration, 1.0)
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine = SimBareMetalMachine.create(graph, machineModel)
- val hypervisor = SimHypervisor.create(FlowMultiplexerFactory.forwardingMultiplexer(), SplittableRandom(0L))
-
- launch { machine.runWorkload(hypervisor) }
- yield()
- val vm = hypervisor.newMachine(machineModel)
- vm.runWorkload(workload)
- hypervisor.removeMachine(vm)
-
- machine.cancel()
-
- assertEquals(duration, timeSource.millis()) { "Took enough time" }
- }
-
- /**
- * Test FLOPs workload on hypervisor.
- */
- @Test
- fun testFlopsWorkload() =
- runSimulation {
- val duration = 5 * 60L * 1000
- val workload = SimWorkloads.flops((duration * 3.2).toLong(), 1.0)
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine = SimBareMetalMachine.create(graph, machineModel)
- val hypervisor = SimHypervisor.create(FlowMultiplexerFactory.forwardingMultiplexer(), SplittableRandom(0L))
-
- launch { machine.runWorkload(hypervisor) }
- yield()
- val vm = hypervisor.newMachine(machineModel)
- vm.runWorkload(workload)
- machine.cancel()
-
- assertEquals(duration, timeSource.millis()) { "Took enough time" }
- }
-
- /**
- * Test two workloads running sequentially.
- */
- @Test
- fun testTwoWorkloads() =
- runSimulation {
- val duration = 5 * 60L * 1000
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine = SimBareMetalMachine.create(graph, machineModel)
- val hypervisor = SimHypervisor.create(FlowMultiplexerFactory.forwardingMultiplexer(), SplittableRandom(0L))
-
- launch { machine.runWorkload(hypervisor) }
- yield()
-
- val vm = hypervisor.newMachine(machineModel)
- vm.runWorkload(SimWorkloads.runtime(duration, 1.0))
- hypervisor.removeMachine(vm)
-
- yield()
-
- val vm2 = hypervisor.newMachine(machineModel)
- vm2.runWorkload(SimWorkloads.runtime(duration, 1.0))
- hypervisor.removeMachine(vm2)
-
- machine.cancel()
-
- assertEquals(duration * 2, timeSource.millis()) { "Took enough time" }
- }
-
- /**
- * Test concurrent workloads on the machine.
- */
- @Test
- fun testConcurrentWorkloadFails() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine = SimBareMetalMachine.create(graph, machineModel)
- val hypervisor = SimHypervisor.create(FlowMultiplexerFactory.forwardingMultiplexer(), SplittableRandom(0L))
-
- launch { machine.runWorkload(hypervisor) }
- yield()
-
- val vm = hypervisor.newMachine(machineModel)
- launch { vm.runWorkload(SimWorkloads.runtime(10_000, 1.0)) }
- yield()
-
- assertAll(
- { assertFalse(hypervisor.canFit(machineModel)) },
- { assertThrows<IllegalArgumentException> { hypervisor.newMachine(machineModel) } },
- )
-
- machine.cancel()
- vm.cancel()
- }
-
- /**
- * Test concurrent workloads on the machine.
- */
- @Test
- fun testConcurrentWorkloadSucceeds() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine = SimBareMetalMachine.create(graph, machineModel)
- val hypervisor = SimHypervisor.create(FlowMultiplexerFactory.forwardingMultiplexer(), SplittableRandom(0L))
-
- launch { machine.runWorkload(hypervisor) }
- yield()
-
- hypervisor.removeMachine(hypervisor.newMachine(machineModel))
-
- assertAll(
- { assertTrue(hypervisor.canFit(machineModel)) },
- { assertDoesNotThrow { hypervisor.newMachine(machineModel) } },
- )
-
- machine.cancel()
- }
-}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/ConservativeScalingGovernorTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/ConservativeScalingGovernorTest.kt
deleted file mode 100644
index 4a930df6..00000000
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/ConservativeScalingGovernorTest.kt
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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.
- */
-
-package org.opendc.simulator.compute.kernel.cpufreq
-
-import io.mockk.every
-import io.mockk.mockk
-import io.mockk.verify
-import org.junit.jupiter.api.Test
-
-/**
- * Test suite for the conservative [ScalingGovernor].
- */
-internal class ConservativeScalingGovernorTest {
- @Test
- fun testSetStartLimitWithoutPStates() {
- val cpuCapacity = 4100.0
- val minSpeed = cpuCapacity / 2
- val defaultThreshold = 0.8
- val defaultStepSize = 0.05 * cpuCapacity
- val governor = ScalingGovernors.conservative(defaultThreshold)
-
- val policy = mockk<ScalingPolicy>(relaxUnitFun = true)
- every { policy.max } returns cpuCapacity
- every { policy.min } returns minSpeed
-
- var target = 0.0
- every { policy.target } answers { target }
- every { policy.target = any() } propertyType Double::class answers { target = value }
-
- val logic = governor.newGovernor(policy)
- logic.onStart()
- logic.onLimit(0.5)
-
- // Upwards scaling
- logic.onLimit(defaultThreshold + 0.2)
-
- // Downwards scaling
- logic.onLimit(defaultThreshold + 0.1)
-
- verify(exactly = 2) { policy.target = minSpeed }
- verify(exactly = 1) { policy.target = minSpeed + defaultStepSize }
- }
-
- @Test
- fun testSetStartLimitWithPStatesAndParams() {
- val firstPState = 1000.0
- val cpuCapacity = 4100.0
- val minSpeed = firstPState
- val threshold = 0.5
- val stepSize = 0.02 * cpuCapacity
- val governor = ScalingGovernors.conservative(threshold, stepSize)
-
- val policy = mockk<ScalingPolicy>(relaxUnitFun = true)
- every { policy.max } returns cpuCapacity
- every { policy.min } returns firstPState
-
- var target = 0.0
- every { policy.target } answers { target }
- every { policy.target = any() } propertyType Double::class answers { target = value }
-
- val logic = governor.newGovernor(policy)
- logic.onStart()
- logic.onLimit(0.5)
-
- // Upwards scaling
- logic.onLimit(threshold + 0.2)
-
- // Downwards scaling
- logic.onLimit(threshold + 0.1)
-
- verify(exactly = 2) { policy.target = minSpeed }
- verify(exactly = 1) { policy.target = minSpeed + stepSize }
- }
-}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/OnDemandScalingGovernorTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/OnDemandScalingGovernorTest.kt
deleted file mode 100644
index d6a7090b..00000000
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/OnDemandScalingGovernorTest.kt
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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.
- */
-
-package org.opendc.simulator.compute.kernel.cpufreq
-
-import io.mockk.every
-import io.mockk.mockk
-import io.mockk.verify
-import org.junit.jupiter.api.Test
-
-/**
- * Test suite for the on-demand [ScalingGovernor].
- */
-internal class OnDemandScalingGovernorTest {
- @Test
- fun testSetStartLimitWithoutPStates() {
- val cpuCapacity = 4100.0
- val minSpeed = cpuCapacity / 2
- val defaultThreshold = 0.8
- val governor = ScalingGovernors.ondemand(defaultThreshold)
-
- val policy = mockk<ScalingPolicy>(relaxUnitFun = true)
- every { policy.min } returns minSpeed
- every { policy.max } returns cpuCapacity
-
- val logic = governor.newGovernor(policy)
- logic.onStart()
- verify(exactly = 1) { policy.target = minSpeed }
-
- logic.onLimit(0.5)
- verify(exactly = 1) { policy.target = minSpeed + 0.5 * (cpuCapacity - minSpeed) / 100 }
-
- logic.onLimit(defaultThreshold)
- verify(exactly = 1) { policy.target = cpuCapacity }
- }
-
- @Test
- fun testSetStartLimitWithPStatesAndParams() {
- val firstPState = 1000.0
- val cpuCapacity = 4100.0
- val threshold = 0.5
- val governor = ScalingGovernors.ondemand(threshold)
-
- val policy = mockk<ScalingPolicy>(relaxUnitFun = true)
- every { policy.max } returns cpuCapacity
- every { policy.min } returns firstPState
-
- val logic = governor.newGovernor(policy)
-
- logic.onStart()
- verify(exactly = 1) { policy.target = firstPState }
-
- logic.onLimit(0.1)
- verify(exactly = 1) { policy.target = firstPState + 0.1 * (cpuCapacity - firstPState) / 100 }
-
- logic.onLimit(threshold)
- verify(exactly = 1) { policy.target = cpuCapacity }
- }
-}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/PerformanceScalingGovernorTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/PerformanceScalingGovernorTest.kt
deleted file mode 100644
index f03f41fe..00000000
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/PerformanceScalingGovernorTest.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.
- */
-
-package org.opendc.simulator.compute.kernel.cpufreq
-
-import io.mockk.every
-import io.mockk.spyk
-import io.mockk.verify
-import org.junit.jupiter.api.Test
-
-/**
- * Test suite for the [PerformanceScalingGovernor]
- */
-internal class PerformanceScalingGovernorTest {
- @Test
- fun testSetStartLimit() {
- val policy = spyk<ScalingPolicy>()
- val logic = ScalingGovernors.performance().newGovernor(policy)
-
- every { policy.max } returns 4100.0
-
- logic.onStart()
- verify(exactly = 1) { policy.target = 4100.0 }
-
- logic.onLimit(0.0)
- verify(exactly = 1) { policy.target = 4100.0 }
-
- logic.onLimit(1.0)
- verify(exactly = 1) { policy.target = 4100.0 }
- }
-}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/PowerSaveScalingGovernorTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/PowerSaveScalingGovernorTest.kt
deleted file mode 100644
index 4cee8199..00000000
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/kernel/cpufreq/PowerSaveScalingGovernorTest.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.
- */
-
-package org.opendc.simulator.compute.kernel.cpufreq
-
-import io.mockk.every
-import io.mockk.mockk
-import io.mockk.verify
-import org.junit.jupiter.api.Test
-
-/**
- * Test suite for the [PowerSaveScalingGovernor]
- */
-internal class PowerSaveScalingGovernorTest {
- @Test
- fun testSetStartLimitWithoutPStates() {
- val cpuCapacity = 4100.0
- val minSpeed = cpuCapacity / 2
- val policy = mockk<ScalingPolicy>(relaxUnitFun = true)
- val logic = ScalingGovernors.powerSave().newGovernor(policy)
-
- every { policy.max } returns cpuCapacity
- every { policy.min } returns minSpeed
-
- logic.onStart()
-
- logic.onLimit(0.0)
- verify(exactly = 1) { policy.target = minSpeed }
-
- logic.onLimit(1.0)
- verify(exactly = 1) { policy.target = minSpeed }
- }
-
- @Test
- fun testSetStartLimitWithPStates() {
- val cpuCapacity = 4100.0
- val firstPState = 1000.0
- val policy = mockk<ScalingPolicy>(relaxUnitFun = true)
- val logic = ScalingGovernors.powerSave().newGovernor(policy)
-
- every { policy.max } returns cpuCapacity
- every { policy.min } returns firstPState
-
- logic.onStart()
- verify(exactly = 1) { policy.target = firstPState }
-
- logic.onLimit(0.0)
- verify(exactly = 1) { policy.target = firstPState }
-
- logic.onLimit(1.0)
- verify(exactly = 1) { policy.target = firstPState }
- }
-}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/power/PowerModelTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/power/PowerModelTest.kt
deleted file mode 100644
index e3bea821..00000000
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/power/PowerModelTest.kt
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * 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.
- */
-
-package org.opendc.simulator.compute.power
-
-import org.junit.jupiter.api.Assertions.assertAll
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.Test
-import org.junit.jupiter.params.ParameterizedTest
-import org.junit.jupiter.params.provider.Arguments
-import org.junit.jupiter.params.provider.MethodSource
-import java.util.stream.Stream
-import kotlin.math.pow
-
-internal class PowerModelTest {
- private val epsilon = 10.0.pow(-3)
- private val cpuUtil = 0.9
-
- @ParameterizedTest
- @MethodSource("machinePowerModelArgs")
- fun `compute power consumption given CPU loads`(
- powerModel: CpuPowerModel,
- expectedPowerConsumption: Double,
- ) {
- val computedPowerConsumption = powerModel.computePower(cpuUtil)
- assertEquals(expectedPowerConsumption, computedPowerConsumption, epsilon)
- }
-
- @ParameterizedTest
- @MethodSource("machinePowerModelArgs")
- fun `ignore idle power when computing power consumptions`(
- powerModel: CpuPowerModel,
- expectedPowerConsumption: Double,
- ) {
- val zeroPowerModel = CpuPowerModels.zeroIdle(powerModel)
-
- assertAll(
- { assertEquals(expectedPowerConsumption, zeroPowerModel.computePower(cpuUtil), epsilon) },
- { assertEquals(0.0, zeroPowerModel.computePower(0.0)) },
- )
- }
-
- @Test
- fun `compute power draw by the SPEC benchmark model`() {
- val powerModel =
- CpuPowerModels.interpolate(
- 58.4, 98.0, 109.0, 118.0, 128.0, 140.0, 153.0, 170.0, 189.0, 205.0, 222.0,
- )
-
- assertAll(
- { assertEquals(58.4, powerModel.computePower(0.0)) },
- { assertEquals(58.4 + (98 - 58.4) / 5, powerModel.computePower(0.02)) },
- { assertEquals(98.0, powerModel.computePower(0.1)) },
- { assertEquals(140.0, powerModel.computePower(0.5)) },
- { assertEquals(189.0, powerModel.computePower(0.8)) },
- { assertEquals(189.0 + 0.7 * 10 * (205 - 189) / 10, powerModel.computePower(0.87)) },
- { assertEquals(205.0, powerModel.computePower(0.9)) },
- { assertEquals(222.0, powerModel.computePower(1.0)) },
- )
- }
-
- @Test
- fun `test linear model`() {
- val powerModel = CpuPowerModels.linear(400.0, 200.0)
-
- assertAll(
- { assertEquals(200.0, powerModel.computePower(-0.1)) },
- { assertEquals(200.0, powerModel.computePower(0.0)) },
- { assertEquals(220.0, powerModel.computePower(0.1)) },
- { assertEquals(240.0, powerModel.computePower(0.2)) },
- { assertEquals(260.0, powerModel.computePower(0.3)) },
- { assertEquals(280.0, powerModel.computePower(0.4)) },
- { assertEquals(300.0, powerModel.computePower(0.5)) },
- { assertEquals(320.0, powerModel.computePower(0.6)) },
- { assertEquals(340.0, powerModel.computePower(0.7)) },
- { assertEquals(360.0, powerModel.computePower(0.8)) },
- { assertEquals(380.0, powerModel.computePower(0.9)) },
- { assertEquals(400.0, powerModel.computePower(1.0)) },
- { assertEquals(400.0, powerModel.computePower(1.1)) },
- )
- }
-
- @Test
- fun `test sqrt model`() {
- val powerModel = CpuPowerModels.sqrt(400.0, 200.0)
-
- assertAll(
- { assertEquals(200.0, powerModel.computePower(-1.0), 1.0) },
- { assertEquals(200.0, powerModel.computePower(0.0), 1.0) },
- { assertEquals(263.0, powerModel.computePower(0.1), 1.0) },
- { assertEquals(289.0, powerModel.computePower(0.2), 1.0) },
- { assertEquals(309.0, powerModel.computePower(0.3), 1.0) },
- { assertEquals(326.0, powerModel.computePower(0.4), 1.0) },
- { assertEquals(341.0, powerModel.computePower(0.5), 1.0) },
- { assertEquals(354.0, powerModel.computePower(0.6), 1.0) },
- { assertEquals(367.0, powerModel.computePower(0.7), 1.0) },
- { assertEquals(378.0, powerModel.computePower(0.8), 1.0) },
- { assertEquals(389.0, powerModel.computePower(0.9), 1.0) },
- { assertEquals(400.0, powerModel.computePower(1.0), 1.0) },
- { assertEquals(400.0, powerModel.computePower(1.1), 1.0) },
- )
- }
-
- @Test
- fun `test square model`() {
- val powerModel = CpuPowerModels.square(400.0, 200.0)
-
- assertAll(
- { assertEquals(200.0, powerModel.computePower(-1.0), 1.0) },
- { assertEquals(200.0, powerModel.computePower(0.0), 1.0) },
- { assertEquals(202.0, powerModel.computePower(0.1), 1.0) },
- { assertEquals(208.0, powerModel.computePower(0.2), 1.0) },
- { assertEquals(218.0, powerModel.computePower(0.3), 1.0) },
- { assertEquals(232.0, powerModel.computePower(0.4), 1.0) },
- { assertEquals(250.0, powerModel.computePower(0.5), 1.0) },
- { assertEquals(272.0, powerModel.computePower(0.6), 1.0) },
- { assertEquals(298.0, powerModel.computePower(0.7), 1.0) },
- { assertEquals(328.0, powerModel.computePower(0.8), 1.0) },
- { assertEquals(362.0, powerModel.computePower(0.9), 1.0) },
- { assertEquals(400.0, powerModel.computePower(1.0), 1.0) },
- { assertEquals(400.0, powerModel.computePower(1.1), 1.0) },
- )
- }
-
- @Test
- fun `test cubic model`() {
- val powerModel = CpuPowerModels.cubic(400.0, 200.0)
-
- assertAll(
- { assertEquals(200.0, powerModel.computePower(-1.0), 1.0) },
- { assertEquals(200.0, powerModel.computePower(0.0), 1.0) },
- { assertEquals(200.0, powerModel.computePower(0.1), 1.0) },
- { assertEquals(201.0, powerModel.computePower(0.2), 1.0) },
- { assertEquals(205.0, powerModel.computePower(0.3), 1.0) },
- { assertEquals(212.0, powerModel.computePower(0.4), 1.0) },
- { assertEquals(225.0, powerModel.computePower(0.5), 1.0) },
- { assertEquals(243.0, powerModel.computePower(0.6), 1.0) },
- { assertEquals(268.0, powerModel.computePower(0.7), 1.0) },
- { assertEquals(302.0, powerModel.computePower(0.8), 1.0) },
- { assertEquals(345.0, powerModel.computePower(0.9), 1.0) },
- { assertEquals(400.0, powerModel.computePower(1.0), 1.0) },
- { assertEquals(400.0, powerModel.computePower(1.1), 1.0) },
- )
- }
-
- @Suppress("unused")
- private companion object {
- @JvmStatic
- fun machinePowerModelArgs(): Stream<Arguments> =
- Stream.of(
- Arguments.of(CpuPowerModels.constant(0.0), 0.0),
- Arguments.of(CpuPowerModels.linear(350.0, 200.0), 335.0),
- Arguments.of(CpuPowerModels.square(350.0, 200.0), 321.5),
- Arguments.of(CpuPowerModels.cubic(350.0, 200.0), 309.35),
- Arguments.of(CpuPowerModels.sqrt(350.0, 200.0), 342.302),
- Arguments.of(CpuPowerModels.mse(350.0, 200.0, 1.4), 340.571),
- Arguments.of(CpuPowerModels.asymptotic(350.0, 200.0, 0.3, false), 338.765),
- Arguments.of(CpuPowerModels.asymptotic(350.0, 200.0, 0.3, true), 323.072),
- )
- }
-}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimChainWorkloadTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimChainWorkloadTest.kt
deleted file mode 100644
index 582635fc..00000000
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimChainWorkloadTest.kt
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright (c) 2022 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.
- */
-
-package org.opendc.simulator.compute.workload
-
-import io.mockk.every
-import io.mockk.mockk
-import io.mockk.spyk
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.launch
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.BeforeEach
-import org.junit.jupiter.api.Test
-import org.junit.jupiter.api.assertThrows
-import org.opendc.simulator.compute.SimBareMetalMachine
-import org.opendc.simulator.compute.SimMachineContext
-import org.opendc.simulator.compute.model.Cpu
-import org.opendc.simulator.compute.model.MachineModel
-import org.opendc.simulator.compute.model.MemoryUnit
-import org.opendc.simulator.compute.runWorkload
-import org.opendc.simulator.flow2.FlowEngine
-import org.opendc.simulator.kotlin.runSimulation
-
-/**
- * Test suite for the [SimChainWorkload] class.
- */
-class SimChainWorkloadTest {
- private lateinit var machineModel: MachineModel
-
- @BeforeEach
- fun setUp() {
- machineModel =
- MachineModel(
- Cpu(
- 0,
- 2,
- 1000.0,
- "Intel",
- "Xeon",
- "amd64",
- ),
- // memory
- MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000 * 4),
- )
- }
-
- @Test
- fun testMultipleWorkloads() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- val workload =
- SimWorkloads.chain(
- SimWorkloads.runtime(1000, 1.0, 0L, 0L),
- SimWorkloads.runtime(1000, 1.0, 0L, 0L),
- )
-
- machine.runWorkload(workload)
-
- assertEquals(2000, timeSource.millis())
- }
-
- @Test
- fun testStartFailure() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- val workloadA = mockk<SimWorkload>()
- every { workloadA.onStart(any()) } throws IllegalStateException("Staged")
- every { workloadA.onStop(any()) } returns Unit
-
- val workload =
- SimWorkloads.chain(
- workloadA,
- SimWorkloads.runtime(1000, 1.0, 0L, 0L),
- )
-
- assertThrows<IllegalStateException> { machine.runWorkload(workload) }
-
- assertEquals(0, timeSource.millis())
- }
-
-// @Test
- fun testStartFailureSecond() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- val workloadA = mockk<SimWorkload>()
- every { workloadA.onStart(any()) } throws IllegalStateException("Staged")
- every { workloadA.onStop(any()) } returns Unit
-
- val workload =
- SimWorkloads.chain(
- SimWorkloads.runtime(1000, 1.0),
- workloadA,
- SimWorkloads.runtime(1000, 1.0),
- )
-
- assertThrows<IllegalStateException> { machine.runWorkload(workload) }
-
- assertEquals(1000, timeSource.millis())
- }
-
- @Test
- fun testStopFailure() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- val workloadA = spyk<SimWorkload>(SimRuntimeWorkload(1000, 1.0))
- every { workloadA.onStop(any()) } throws IllegalStateException("Staged")
-
- val workload =
- SimWorkloads.chain(
- workloadA,
- SimWorkloads.runtime(1000, 1.0),
- )
-
- assertThrows<IllegalStateException> { machine.runWorkload(workload) }
-
- assertEquals(1000, timeSource.millis())
- }
-
- @Test
- fun testStopFailureSecond() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- val workloadA = spyk<SimWorkload>(SimRuntimeWorkload(1000, 1.0))
- every { workloadA.onStop(any()) } throws IllegalStateException("Staged")
-
- val workload =
- SimWorkloads.chain(
- SimWorkloads.runtime(1000, 1.0),
- workloadA,
- SimWorkloads.runtime(1000, 1.0),
- )
-
- assertThrows<IllegalStateException> { machine.runWorkload(workload) }
-
- assertEquals(2000, timeSource.millis())
- }
-
-// @Test
- fun testStartAndStopFailure() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- val workloadA = mockk<SimWorkload>()
- every { workloadA.onStart(any()) } throws IllegalStateException()
- every { workloadA.onStop(any()) } throws IllegalStateException()
-
- val workload =
- SimWorkloads.chain(
- SimRuntimeWorkload(1000, 1.0),
- workloadA,
- )
-
- val exc = assertThrows<IllegalStateException> { machine.runWorkload(workload) }
-
- assertEquals(2, exc.cause!!.suppressedExceptions.size)
- assertEquals(1000, timeSource.millis())
- }
-
-// @Test
- fun testShutdownAndStopFailure() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- val workloadA = mockk<SimWorkload>()
- every { workloadA.onStart(any()) } answers { (it.invocation.args[0] as SimMachineContext).shutdown(IllegalStateException()) }
- every { workloadA.onStop(any()) } throws IllegalStateException()
-
- val workload =
- SimWorkloads.chain(
- SimRuntimeWorkload(1000, 1.0),
- workloadA,
- )
-
- val exc = assertThrows<IllegalStateException> { machine.runWorkload(workload) }
-
- assertEquals(1, exc.cause!!.suppressedExceptions.size)
- assertEquals(1000, timeSource.millis())
- }
-
-// @Test
- fun testShutdownAndStartFailure() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- val workloadA = mockk<SimWorkload>(relaxUnitFun = true)
- every { workloadA.onStart(any()) } answers { (it.invocation.args[0] as SimMachineContext).shutdown(IllegalStateException()) }
-
- val workloadB = mockk<SimWorkload>(relaxUnitFun = true)
- every { workloadB.onStart(any()) } throws IllegalStateException()
-
- val workload =
- SimWorkloads.chain(
- SimRuntimeWorkload(1000, 1.0),
- workloadA,
- workloadB,
- )
-
- val exc = assertThrows<IllegalStateException> { machine.runWorkload(workload) }
- assertEquals(1, exc.cause!!.suppressedExceptions.size)
- assertEquals(1000, timeSource.millis())
- }
-
- @Test
- fun testSnapshot() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine = SimBareMetalMachine.create(graph, machineModel)
- val workload =
- SimWorkloads.chain(
- SimWorkloads.runtime(1000, 1.0),
- SimWorkloads.runtime(1000, 1.0),
- )
-
- val job = launch { machine.runWorkload(workload) }
- delay(500L)
-
- workload.makeSnapshot(500L)
- val snapshot = workload.getSnapshot()
-
- job.join()
-
- assertEquals(2000, timeSource.millis())
-
- machine.runWorkload(snapshot)
-
- assertEquals(4000, timeSource.millis())
- }
-}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimFlopsWorkloadTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimFlopsWorkloadTest.kt
deleted file mode 100644
index edbc0571..00000000
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimFlopsWorkloadTest.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2020 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.
- */
-
-package org.opendc.simulator.compute.workload
-
-import org.junit.jupiter.api.Test
-import org.junit.jupiter.api.assertThrows
-
-/**
- * Test suite for [SimFlopsWorkload] class.
- */
-class SimFlopsWorkloadTest {
- @Test
- fun testFlopsNonNegative() {
- assertThrows<IllegalArgumentException>("FLOPs must be non-negative") {
- SimFlopsWorkload(-1, 1.0)
- }
- }
-
- @Test
- fun testUtilizationNonZero() {
- assertThrows<IllegalArgumentException>("Utilization cannot be zero") {
- SimFlopsWorkload(1, 0.0)
- }
- }
-
- @Test
- fun testUtilizationPositive() {
- assertThrows<IllegalArgumentException>("Utilization cannot be negative") {
- SimFlopsWorkload(1, -1.0)
- }
- }
-
- @Test
- fun testUtilizationNotLargerThanOne() {
- assertThrows<IllegalArgumentException>("Utilization cannot be larger than one") {
- SimFlopsWorkload(1, 2.0)
- }
- }
-}
diff --git a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimTraceWorkloadTest.kt b/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimTraceWorkloadTest.kt
deleted file mode 100644
index a53f6c65..00000000
--- a/opendc-simulator/opendc-simulator-compute/src/test/kotlin/org/opendc/simulator/compute/workload/SimTraceWorkloadTest.kt
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * 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.
- */
-
-package org.opendc.simulator.compute.workload
-
-import kotlinx.coroutines.delay
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.BeforeEach
-import org.junit.jupiter.api.Test
-import org.opendc.simulator.compute.SimBareMetalMachine
-import org.opendc.simulator.compute.model.Cpu
-import org.opendc.simulator.compute.model.MachineModel
-import org.opendc.simulator.compute.model.MemoryUnit
-import org.opendc.simulator.compute.runWorkload
-import org.opendc.simulator.flow2.FlowEngine
-import org.opendc.simulator.kotlin.runSimulation
-
-/**
- * Test suite for the [SimTraceWorkloadTest] class.
- */
-class SimTraceWorkloadTest {
- private lateinit var machineModel: MachineModel
-
- @BeforeEach
- fun setUp() {
- machineModel =
- MachineModel(
- Cpu(
- 0,
- 2,
- 1000.0,
- "Intel",
- "Xeon",
- "amd64",
- ),
- // memory
- MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000 * 4),
- )
- }
-
- @Test
- fun testSmoke() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- val workload =
- SimTrace.ofFragments(
- SimTraceFragment(0, 1000, 2 * 28.0, 2),
- SimTraceFragment(1000, 1000, 2 * 3100.0, 2),
- SimTraceFragment(2000, 1000, 0.0, 2),
- SimTraceFragment(3000, 1000, 2 * 73.0, 2),
- ).createWorkload(0)
-
- machine.runWorkload(workload)
-
- assertEquals(4000, timeSource.millis())
- }
-
-// @Test // fixme: Fix delayed start and enable test
- fun testOffset() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- val workload =
- SimTrace.ofFragments(
- SimTraceFragment(0, 1000, 2 * 28.0, 2),
- SimTraceFragment(1000, 1000, 2 * 3100.0, 2),
- SimTraceFragment(2000, 1000, 0.0, 2),
- SimTraceFragment(3000, 1000, 2 * 73.0, 2),
- ).createWorkload(1000)
-
- machine.runWorkload(workload)
-
- assertEquals(5000, timeSource.millis()) // fixme: should be 5000 but this is 4000 for now to make all tests succeed
- }
-
- @Test
- fun testSkipFragment() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- val workload =
- SimTrace.ofFragments(
- SimTraceFragment(0, 1000, 2 * 28.0, 2),
- SimTraceFragment(1000, 1000, 2 * 3100.0, 2),
- SimTraceFragment(2000, 1000, 0.0, 2),
- SimTraceFragment(3000, 1000, 2 * 73.0, 2),
- ).createWorkload(0)
-
- delay(1000L)
- machine.runWorkload(workload)
-
- assertEquals(4000, timeSource.millis())
- }
-
- @Test
- fun testZeroCores() =
- runSimulation {
- val engine = FlowEngine.create(dispatcher)
- val graph = engine.newGraph()
-
- val machine =
- SimBareMetalMachine.create(
- graph,
- machineModel,
- )
-
- val workload =
- SimTrace.ofFragments(
- SimTraceFragment(0, 1000, 2 * 28.0, 2),
- SimTraceFragment(1000, 1000, 2 * 3100.0, 2),
- SimTraceFragment(2000, 1000, 0.0, 0),
- SimTraceFragment(3000, 1000, 2 * 73.0, 2),
- ).createWorkload(0)
-
- machine.runWorkload(workload)
-
- assertEquals(4000, timeSource.millis())
- }
-}