From 5864cbcbfe2eb8c36ca05c3a39c7e5916aeecaec Mon Sep 17 00:00:00 2001 From: Dante Niewenhuis Date: Tue, 5 Mar 2024 13:23:57 +0100 Subject: Updated package versions, updated web server tests. (#207) * Updated all package versions including kotlin. Updated all web-server tests to run. * Changed the java version of the tests. OpenDC now only supports java 19. * small update * test update * new update * updated docker version to 19 * updated docker version to 19 --- .../simulator/compute/SimMachineBenchmarks.kt | 11 +- .../org/opendc/simulator/compute/Coroutines.kt | 5 +- .../org/opendc/simulator/compute/SimMachineTest.kt | 650 +++++++++++---------- .../compute/kernel/SimFairShareHypervisorTest.kt | 313 +++++----- .../compute/kernel/SimSpaceSharedHypervisorTest.kt | 231 ++++---- .../cpufreq/ConservativeScalingGovernorTest.kt | 8 +- .../simulator/compute/power/PowerModelTest.kt | 40 +- .../compute/workload/SimChainWorkloadTest.kt | 406 +++++++------ .../compute/workload/SimTraceWorkloadTest.kt | 189 +++--- .../opendc-simulator-core/build.gradle.kts | 2 +- .../opendc/simulator/kotlin/SimulationBuilders.kt | 16 +- .../simulator/kotlin/SimulationCoroutineScope.kt | 2 +- .../kotlin/org/opendc/simulator/TaskQueueTest.kt | 18 +- .../simulator/kotlin/SimulationBuildersTest.kt | 42 +- .../org/opendc/simulator/flow2/FlowBenchmarks.kt | 11 +- .../org/opendc/simulator/flow2/FlowEngineTest.kt | 223 +++---- .../opendc/simulator/flow2/FlowTimerQueueTest.kt | 22 +- .../flow2/mux/ForwardingFlowMultiplexerTest.kt | 45 +- .../flow2/mux/MaxMinFlowMultiplexerTest.kt | 27 +- .../opendc/simulator/flow2/sink/FlowSinkTest.kt | 115 ++-- .../opendc/simulator/network/SimNetworkSinkTest.kt | 165 +++--- .../network/SimNetworkSwitchVirtualTest.kt | 54 +- .../org/opendc/simulator/network/TestSource.kt | 5 +- .../org/opendc/simulator/power/SimPduTest.kt | 150 ++--- .../opendc/simulator/power/SimPowerSourceTest.kt | 167 +++--- .../org/opendc/simulator/power/SimUpsTest.kt | 110 ++-- .../kotlin/org/opendc/simulator/power/TestInlet.kt | 5 +- 27 files changed, 1609 insertions(+), 1423 deletions(-) (limited to 'opendc-simulator') diff --git a/opendc-simulator/opendc-simulator-compute/src/jmh/kotlin/org/opendc/simulator/compute/SimMachineBenchmarks.kt b/opendc-simulator/opendc-simulator-compute/src/jmh/kotlin/org/opendc/simulator/compute/SimMachineBenchmarks.kt index eea46b95..3707b601 100644 --- a/opendc-simulator/opendc-simulator-compute/src/jmh/kotlin/org/opendc/simulator/compute/SimMachineBenchmarks.kt +++ b/opendc-simulator/opendc-simulator-compute/src/jmh/kotlin/org/opendc/simulator/compute/SimMachineBenchmarks.kt @@ -56,10 +56,13 @@ class SimMachineBenchmarks { fun setUp() { val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2) - machineModel = MachineModel( - /*cpus*/ List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) }, - /*memory*/ List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) } - ) + machineModel = + MachineModel( + // cpus + List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) }, + // memory + List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + ) val random = ThreadLocalRandom.current() val builder = SimTrace.builder() diff --git a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/Coroutines.kt b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/Coroutines.kt index b354caff..63af2048 100644 --- a/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/Coroutines.kt +++ b/opendc-simulator/opendc-simulator-compute/src/main/kotlin/org/opendc/simulator/compute/Coroutines.kt @@ -35,7 +35,10 @@ import kotlin.coroutines.resumeWithException * @return A [SimMachineContext] that represents the execution context for the workload. * @throws IllegalStateException if a workload is already active on the machine or if the machine is closed. */ -public suspend fun SimMachine.runWorkload(workload: SimWorkload, meta: Map = emptyMap()) { +public suspend fun SimMachine.runWorkload( + workload: SimWorkload, + meta: Map = emptyMap(), +) { return suspendCancellableCoroutine { cont -> cont.invokeOnCancellation { this@runWorkload.cancel() } 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 28acaef4..f427e3a7 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 @@ -62,369 +62,419 @@ class SimMachineTest { fun setUp() { val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2) - machineModel = MachineModel( - /*cpus*/ List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) }, - /*memory*/ List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, - /*net*/ listOf(NetworkAdapter("Mellanox", "ConnectX-5", 25000.0)), - /*storage*/ listOf(StorageDevice("Samsung", "EVO", 1000.0, 250.0, 250.0)) - ) + machineModel = + MachineModel( + List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) }, + List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + 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 - ) + fun testFlopsWorkload() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - machine.runWorkload(SimWorkloads.flops(2_000, /*utilization*/ 1.0)) + val machine = + SimBareMetalMachine.create( + graph, + machineModel, + ) - // Two cores execute 1000 MFlOps per second (1000 ms) - assertEquals(1000, timeSource.millis()) - } + machine.runWorkload(SimWorkloads.flops(2_000, 1.0)) - @Test - fun testTraceWorkload() = runSimulation { - val random = ThreadLocalRandom.current() - val builder = SimTrace.builder() - repeat(1000000) { - val timestamp = it.toLong() * 1000 - val deadline = timestamp + 1000 - builder.add(deadline, random.nextDouble(0.0, 4500.0), 1) + // Two cores execute 1000 MFlOps per second (1000 ms) + assertEquals(1000, timeSource.millis()) } - val trace = builder.build() - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val machine = SimBareMetalMachine.create( - graph, - machineModel - ) + @Test + fun testTraceWorkload() = + runSimulation { + val random = ThreadLocalRandom.current() + val builder = SimTrace.builder() + repeat(1000000) { + val timestamp = it.toLong() * 1000 + val deadline = timestamp + 1000 + builder.add(deadline, random.nextDouble(0.0, 4500.0), 1) + } + val trace = builder.build() - machine.runWorkload(trace.createWorkload(0)) + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val machine = + SimBareMetalMachine.create( + graph, + machineModel, + ) - // Two cores execute 1000 MFlOps per second (1000 ms) - assertEquals(1000000000, timeSource.millis()) - } + machine.runWorkload(trace.createWorkload(0)) - @Test - fun testDualSocketMachine() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - - val cpuNode = machineModel.cpus[0].node - val machineModel = MachineModel( - /*cpus*/ List(cpuNode.coreCount * 2) { ProcessingUnit(cpuNode, it % 2, 1000.0) }, - /*memory*/ List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) } - ) - val machine = SimBareMetalMachine.create( - graph, - machineModel - ) - - machine.runWorkload(SimWorkloads.flops(2_000, /*utilization*/ 1.0)) - - // Two sockets with two cores execute 2000 MFlOps per second (500 ms) - assertEquals(500, timeSource.millis()) - } + // Two cores execute 1000 MFlOps per second (1000 ms) + assertEquals(1000000000, 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, /*capacity*/ 1000.0f) - source.connect(machine.psu) - - coroutineScope { - launch { machine.runWorkload(SimWorkloads.flops(2_000, /*utilization*/ 1.0)) } - - yield() - assertAll( - { assertEquals(100.0, machine.psu.powerDraw) }, - { assertEquals(100.0f, source.powerDraw) } - ) + fun testDualSocketMachine() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + + val cpuNode = machineModel.cpus[0].node + val machineModel = + MachineModel( + List(cpuNode.coreCount * 2) { ProcessingUnit(cpuNode, it % 2, 1000.0) }, + List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + ) + val machine = + SimBareMetalMachine.create( + 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 testCapacityClamp() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - - val machine = SimBareMetalMachine.create( - graph, - machineModel - ) + 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) - machine.runWorkload(object : SimWorkload { - override fun onStart(ctx: SimMachineContext) { - val cpu = ctx.cpus[0] - - cpu.frequency = (cpu.model.frequency + 1000.0) - assertEquals(cpu.model.frequency, cpu.frequency) - cpu.frequency = -1.0 - assertEquals(0.0, cpu.frequency) + coroutineScope { + launch { machine.runWorkload(SimWorkloads.flops(2_000, 1.0)) } - ctx.shutdown() + yield() + assertAll( + { assertEquals(100.0, machine.psu.powerDraw) }, + { assertEquals(100.0f, source.powerDraw) }, + ) } - - override fun setOffset(now: Long) {} - - override fun onStop(ctx: SimMachineContext) {} - - override fun snapshot(): SimWorkload = TODO() - }) - } + } @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() - } + fun testCapacityClamp() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - override fun setOffset(now: Long) {} + val machine = + SimBareMetalMachine.create( + graph, + machineModel, + ) - override fun onStop(ctx: SimMachineContext) {} + machine.runWorkload( + object : SimWorkload { + override fun onStart(ctx: SimMachineContext) { + val cpu = ctx.cpus[0] - override fun snapshot(): SimWorkload = TODO() - }) - } + cpu.frequency = (cpu.model.frequency + 1000.0) + assertEquals(cpu.model.frequency, cpu.frequency) + cpu.frequency = -1.0 + assertEquals(0.0, cpu.frequency) - @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) - } + ctx.shutdown() + } - override fun setOffset(now: Long) {} + override fun setOffset(now: Long) {} - override fun onStop(ctx: SimMachineContext) {} + override fun onStop(ctx: SimMachineContext) {} - override fun snapshot(): SimWorkload = TODO() - }) - - assertEquals(1000, timeSource.millis()) - } + override fun snapshot(): SimWorkload = TODO() + }, + ) + } @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) - } + 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 snapshot(): SimWorkload = TODO() + }, + ) + } - override fun setOffset(now: Long) {} + @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 snapshot(): SimWorkload = TODO() + }, + ) - override fun onStop(ctx: SimMachineContext) {} + assertEquals(1000, timeSource.millis()) + } - override fun snapshot(): SimWorkload = TODO() - }) + @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 snapshot(): SimWorkload = TODO() + }, + ) - assertEquals(40, timeSource.millis()) - } + 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) {} + 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 snapshot(): SimWorkload = TODO() + }, + ) - override fun onStop(ctx: SimMachineContext) {} + assertEquals(4000, timeSource.millis()) + } - override fun snapshot(): SimWorkload = TODO() - }) + @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 snapshot(): SimWorkload = TODO() + }, + ) - assertEquals(4000, timeSource.millis()) - } + 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) + 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 } - override fun setOffset(now: Long) {} - - override fun onStop(ctx: SimMachineContext) {} - - override fun snapshot(): SimWorkload = TODO() - }) - - assertEquals(4000, timeSource.millis()) - } + assertEquals(0, timeSource.millis()) + } @Test - fun testCancellation() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() + fun testConcurrentRuns() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - val machine = SimBareMetalMachine.create( - graph, - machineModel - ) + val machine = + SimBareMetalMachine.create( + graph, + machineModel, + ) - try { coroutineScope { - launch { machine.runWorkload(SimWorkloads.flops(2_000, /*utilization*/ 1.0)) } - cancel() - } - } catch (_: CancellationException) { - // Ignore - } - - assertEquals(0, timeSource.millis()) - } + launch { + machine.runWorkload(SimWorkloads.flops(2_000, 1.0)) + } - @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, /*utilization*/ 1.0)) - } - - assertThrows { - machine.runWorkload(SimWorkloads.flops(2_000, /*utilization*/ 1.0)) + assertThrows { + machine.runWorkload(SimWorkloads.flops(2_000, 1.0)) + } } } - } @Test - fun testCatchStartFailure() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() + fun testCatchStartFailure() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - val machine = SimBareMetalMachine.create( - graph, - machineModel - ) + val machine = + SimBareMetalMachine.create( + graph, + machineModel, + ) - val workload = mockk() - every { workload.onStart(any()) } throws IllegalStateException() + val workload = mockk() + every { workload.onStart(any()) } throws IllegalStateException() - assertThrows { machine.runWorkload(workload) } - } + assertThrows { 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() - every { workload.onStart(any()) } answers { (it.invocation.args[0] as SimMachineContext).shutdown() } - every { workload.onStop(any()) } throws IllegalStateException() - - assertThrows { machine.runWorkload(workload) } - } + fun testCatchStopFailure() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + + val machine = + SimBareMetalMachine.create( + graph, + machineModel, + ) + + val workload = mockk() + every { workload.onStart(any()) } answers { (it.invocation.args[0] as SimMachineContext).shutdown() } + every { workload.onStop(any()) } throws IllegalStateException() + + assertThrows { machine.runWorkload(workload) } + } @Test - fun testCatchShutdownFailure() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() + fun testCatchShutdownFailure() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - val machine = SimBareMetalMachine.create( - graph, - machineModel - ) + val machine = + SimBareMetalMachine.create( + graph, + machineModel, + ) - val workload = mockk() - every { workload.onStart(any()) } answers { (it.invocation.args[0] as SimMachineContext).shutdown(IllegalStateException()) } + val workload = mockk() + every { workload.onStart(any()) } answers { (it.invocation.args[0] as SimMachineContext).shutdown(IllegalStateException()) } - assertThrows { machine.runWorkload(workload) } - } + assertThrows { machine.runWorkload(workload) } + } @Test - fun testCatchNestedFailure() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - - val machine = SimBareMetalMachine.create( - graph, - machineModel - ) - - val workload = mockk() - every { workload.onStart(any()) } answers { (it.invocation.args[0] as SimMachineContext).shutdown(IllegalStateException()) } - every { workload.onStop(any()) } throws IllegalStateException() - - val exc = assertThrows { machine.runWorkload(workload) } - assertEquals(1, exc.cause!!.suppressedExceptions.size) - } + fun testCatchNestedFailure() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + + val machine = + SimBareMetalMachine.create( + graph, + machineModel, + ) + + val workload = mockk() + every { workload.onStart(any()) } answers { (it.invocation.args[0] as SimMachineContext).shutdown(IllegalStateException()) } + every { workload.onStop(any()) } throws IllegalStateException() + + val exc = assertThrows { 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 index 99f47b2f..bef22699 100644 --- 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 @@ -54,173 +54,202 @@ internal class SimFairShareHypervisorTest { @BeforeEach fun setUp() { val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 1) - model = MachineModel( - /*cpus*/ List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) }, - /*memory*/ List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) } - ) + model = + MachineModel( + // cpus + List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) }, + // memory + List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + ) } /** * 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" } } - ) - } + 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 { + 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(workloadA) + vm.runWorkload(workloadB) 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()) }, + ) } - 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 cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2) - val model = MachineModel( - /*cpus*/ List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) }, - /*memory*/ List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) } - ) - - 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()) + fun testMultipleCPUs() = + runSimulation { + val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2) + val model = + MachineModel( + // cpus + List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) }, + // memory + List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + ) + + 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) } + } - assertDoesNotThrow { - launch { machine.runWorkload(hypervisor) } + machine.cancel() } - machine.cancel() - } - @Test - fun testInterference() = runSimulation { - val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2) - val model = MachineModel( - /*cpus*/ List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) }, - /*memory*/ List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) } - ) - - 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) - } + fun testInterference() = + runSimulation { + val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2) + val model = + MachineModel( + // cpus + List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) }, + // memory + List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + ) + + 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) - coroutineScope { 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(workloadA, meta = mapOf("interference-model" to interferenceModel.getProfile("a")!!)) + vm.runWorkload(workloadB, meta = mapOf("interference-model" to interferenceModel.getProfile("b")!!)) hypervisor.removeMachine(vm) } - val vm = hypervisor.newMachine(model) - vm.runWorkload(workloadB, meta = mapOf("interference-model" to interferenceModel.getProfile("b")!!)) - hypervisor.removeMachine(vm) - } - machine.cancel() - } + 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 index 93b67aa3..b762acea 100644 --- 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 @@ -55,167 +55,176 @@ internal class SimSpaceSharedHypervisorTest { @BeforeEach fun setUp() { val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 1) - machineModel = MachineModel( - /*cpus*/ List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) }, - /*memory*/ List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) } - ) + machineModel = + MachineModel( + // cpus + List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 3200.0) }, + // memory + List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + ) } /** * 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" } - } + 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() + 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)) + 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) + launch { machine.runWorkload(hypervisor) } + yield() + val vm = hypervisor.newMachine(machineModel) + vm.runWorkload(workload) + hypervisor.removeMachine(vm) - machine.cancel() + machine.cancel() - assertEquals(duration, timeSource.millis()) { "Took enough time" } - } + 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" } - } + 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() + 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)) + val machine = SimBareMetalMachine.create(graph, machineModel) + val hypervisor = SimHypervisor.create(FlowMultiplexerFactory.forwardingMultiplexer(), SplittableRandom(0L)) - launch { machine.runWorkload(hypervisor) } - yield() + launch { machine.runWorkload(hypervisor) } + yield() - val vm = hypervisor.newMachine(machineModel) - vm.runWorkload(SimWorkloads.runtime(duration, 1.0)) - hypervisor.removeMachine(vm) + val vm = hypervisor.newMachine(machineModel) + vm.runWorkload(SimWorkloads.runtime(duration, 1.0)) + hypervisor.removeMachine(vm) - yield() + yield() - val vm2 = hypervisor.newMachine(machineModel) - vm2.runWorkload(SimWorkloads.runtime(duration, 1.0)) - hypervisor.removeMachine(vm2) + val vm2 = hypervisor.newMachine(machineModel) + vm2.runWorkload(SimWorkloads.runtime(duration, 1.0)) + hypervisor.removeMachine(vm2) - machine.cancel() + machine.cancel() - assertEquals(duration * 2, timeSource.millis()) { "Took enough time" } - } + 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() + 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)) + val machine = SimBareMetalMachine.create(graph, machineModel) + val hypervisor = SimHypervisor.create(FlowMultiplexerFactory.forwardingMultiplexer(), SplittableRandom(0L)) - launch { machine.runWorkload(hypervisor) } - yield() + launch { machine.runWorkload(hypervisor) } + yield() - val vm = hypervisor.newMachine(machineModel) - launch { vm.runWorkload(SimWorkloads.runtime(10_000, 1.0)) } - yield() + val vm = hypervisor.newMachine(machineModel) + launch { vm.runWorkload(SimWorkloads.runtime(10_000, 1.0)) } + yield() - assertAll( - { assertFalse(hypervisor.canFit(machineModel)) }, - { assertThrows { hypervisor.newMachine(machineModel) } } - ) + assertAll( + { assertFalse(hypervisor.canFit(machineModel)) }, + { assertThrows { hypervisor.newMachine(machineModel) } }, + ) - machine.cancel() - vm.cancel() - } + machine.cancel() + vm.cancel() + } /** * Test concurrent workloads on the machine. */ @Test - fun testConcurrentWorkloadSucceeds() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() + 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)) + val machine = SimBareMetalMachine.create(graph, machineModel) + val hypervisor = SimHypervisor.create(FlowMultiplexerFactory.forwardingMultiplexer(), SplittableRandom(0L)) - launch { machine.runWorkload(hypervisor) } - yield() + launch { machine.runWorkload(hypervisor) } + yield() - hypervisor.removeMachine(hypervisor.newMachine(machineModel)) + hypervisor.removeMachine(hypervisor.newMachine(machineModel)) - assertAll( - { assertTrue(hypervisor.canFit(machineModel)) }, - { assertDoesNotThrow { hypervisor.newMachine(machineModel) } } - ) + assertAll( + { assertTrue(hypervisor.canFit(machineModel)) }, + { assertDoesNotThrow { hypervisor.newMachine(machineModel) } }, + ) - machine.cancel() - } + 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 index 6b182f4c..4a930df6 100644 --- 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 @@ -51,10 +51,10 @@ internal class ConservativeScalingGovernorTest { logic.onStart() logic.onLimit(0.5) - /* Upwards scaling */ + // Upwards scaling logic.onLimit(defaultThreshold + 0.2) - /* Downwards scaling */ + // Downwards scaling logic.onLimit(defaultThreshold + 0.1) verify(exactly = 2) { policy.target = minSpeed } @@ -82,10 +82,10 @@ internal class ConservativeScalingGovernorTest { logic.onStart() logic.onLimit(0.5) - /* Upwards scaling */ + // Upwards scaling logic.onLimit(threshold + 0.2) - /* Downwards scaling */ + // Downwards scaling logic.onLimit(threshold + 0.1) verify(exactly = 2) { policy.target = minSpeed } 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 index 9a6263c5..e85758ae 100644 --- 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 @@ -36,34 +36,35 @@ internal class PowerModelTest { private val cpuUtil = 0.9 @ParameterizedTest - @MethodSource("MachinePowerModelArgs") + @MethodSource("machinePowerModelArgs") fun `compute power consumption given CPU loads`( powerModel: CpuPowerModel, - expectedPowerConsumption: Double + expectedPowerConsumption: Double, ) { val computedPowerConsumption = powerModel.computePower(cpuUtil) assertEquals(expectedPowerConsumption, computedPowerConsumption, epsilon) } @ParameterizedTest - @MethodSource("MachinePowerModelArgs") + @MethodSource("machinePowerModelArgs") fun `ignore idle power when computing power consumptions`( powerModel: CpuPowerModel, - expectedPowerConsumption: Double + expectedPowerConsumption: Double, ) { val zeroPowerModel = CpuPowerModels.zeroIdle(powerModel) assertAll( { assertEquals(expectedPowerConsumption, zeroPowerModel.computePower(cpuUtil), epsilon) }, - { assertEquals(0.0, zeroPowerModel.computePower(0.0)) } + { 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 - ) + 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)) }, @@ -73,22 +74,23 @@ internal class PowerModelTest { { 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)) } + { assertEquals(222.0, powerModel.computePower(1.0)) }, ) } @Suppress("unused") private companion object { @JvmStatic - fun MachinePowerModelArgs(): Stream = 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) - ) + fun machinePowerModelArgs(): Stream = + 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 index 08bb6509..9ea9d300 100644 --- 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 @@ -51,235 +51,255 @@ class SimChainWorkloadTest { fun setUp() { val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2) - machineModel = MachineModel( - /*cpus*/ List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) }, - /*memory*/ List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) } - ) + machineModel = + MachineModel( + // cpus + List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) }, + // memory + List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + ) } @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), - SimWorkloads.runtime(1000, 1.0) - ) + fun testMultipleWorkloads() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - machine.runWorkload(workload) + val machine = + SimBareMetalMachine.create( + graph, + machineModel, + ) - assertEquals(2000, timeSource.millis()) - } + val workload = + SimWorkloads.chain( + SimWorkloads.runtime(1000, 1.0), + SimWorkloads.runtime(1000, 1.0), + ) + + 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() - every { workloadA.onStart(any()) } throws IllegalStateException("Staged") - every { workloadA.onStop(any()) } returns Unit - - val workload = - SimWorkloads.chain( - workloadA, - SimWorkloads.runtime(1000, 1.0) - ) + fun testStartFailure() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - assertThrows { machine.runWorkload(workload) } + val machine = + SimBareMetalMachine.create( + graph, + machineModel, + ) - assertEquals(0, timeSource.millis()) - } + val workloadA = mockk() + every { workloadA.onStart(any()) } throws IllegalStateException("Staged") + every { workloadA.onStop(any()) } returns Unit - @Test - fun testStartFailureSecond() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - - val machine = SimBareMetalMachine.create( - graph, - machineModel - ) - - val workloadA = mockk() - 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) - ) + val workload = + SimWorkloads.chain( + workloadA, + SimWorkloads.runtime(1000, 1.0), + ) - assertThrows { machine.runWorkload(workload) } + assertThrows { machine.runWorkload(workload) } - assertEquals(1000, timeSource.millis()) - } + assertEquals(0, timeSource.millis()) + } @Test - fun testStopFailure() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - - val machine = SimBareMetalMachine.create( - graph, - machineModel - ) - - val workloadA = spyk(SimRuntimeWorkload(1000, 1.0)) - every { workloadA.onStop(any()) } throws IllegalStateException("Staged") - - val workload = - SimWorkloads.chain( - workloadA, - SimWorkloads.runtime(1000, 1.0) - ) + fun testStartFailureSecond() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - assertThrows { machine.runWorkload(workload) } + val machine = + SimBareMetalMachine.create( + graph, + machineModel, + ) - assertEquals(1000, timeSource.millis()) - } + val workloadA = mockk() + 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 { 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(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) - ) + fun testStopFailure() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - assertThrows { machine.runWorkload(workload) } + val machine = + SimBareMetalMachine.create( + graph, + machineModel, + ) - assertEquals(2000, timeSource.millis()) - } + val workloadA = spyk(SimRuntimeWorkload(1000, 1.0)) + every { workloadA.onStop(any()) } throws IllegalStateException("Staged") + + val workload = + SimWorkloads.chain( + workloadA, + SimWorkloads.runtime(1000, 1.0), + ) + + assertThrows { machine.runWorkload(workload) } + + assertEquals(1000, timeSource.millis()) + } @Test - fun testStartAndStopFailure() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - - val machine = SimBareMetalMachine.create( - graph, - machineModel - ) - - val workloadA = mockk() - every { workloadA.onStart(any()) } throws IllegalStateException() - every { workloadA.onStop(any()) } throws IllegalStateException() - - val workload = - SimWorkloads.chain( - SimRuntimeWorkload(1000, 1.0), - workloadA - ) + fun testStopFailureSecond() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - val exc = assertThrows { machine.runWorkload(workload) } + val machine = + SimBareMetalMachine.create( + graph, + machineModel, + ) - assertEquals(2, exc.cause!!.suppressedExceptions.size) - assertEquals(1000, timeSource.millis()) - } + val workloadA = spyk(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 { machine.runWorkload(workload) } + + assertEquals(2000, timeSource.millis()) + } @Test - fun testShutdownAndStopFailure() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - - val machine = SimBareMetalMachine.create( - graph, - machineModel - ) - - val workloadA = mockk() - 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 - ) + fun testStartAndStopFailure() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - val exc = assertThrows { machine.runWorkload(workload) } + val machine = + SimBareMetalMachine.create( + graph, + machineModel, + ) - assertEquals(1, exc.cause!!.suppressedExceptions.size) - assertEquals(1000, timeSource.millis()) - } + val workloadA = mockk() + every { workloadA.onStart(any()) } throws IllegalStateException() + every { workloadA.onStop(any()) } throws IllegalStateException() + + val workload = + SimWorkloads.chain( + SimRuntimeWorkload(1000, 1.0), + workloadA, + ) + + val exc = assertThrows { machine.runWorkload(workload) } + + assertEquals(2, 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(relaxUnitFun = true) - every { workloadA.onStart(any()) } answers { (it.invocation.args[0] as SimMachineContext).shutdown(IllegalStateException()) } - - val workloadB = mockk(relaxUnitFun = true) - every { workloadB.onStart(any()) } throws IllegalStateException() - - val workload = - SimWorkloads.chain( - SimRuntimeWorkload(1000, 1.0), - workloadA, - workloadB - ) + fun testShutdownAndStopFailure() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - val exc = assertThrows { machine.runWorkload(workload) } - assertEquals(1, exc.cause!!.suppressedExceptions.size) - assertEquals(1000, timeSource.millis()) - } + val machine = + SimBareMetalMachine.create( + graph, + machineModel, + ) + + val workloadA = mockk() + 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 { 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) - ) + fun testShutdownAndStartFailure() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + + val machine = + SimBareMetalMachine.create( + graph, + machineModel, + ) + + val workloadA = mockk(relaxUnitFun = true) + every { workloadA.onStart(any()) } answers { (it.invocation.args[0] as SimMachineContext).shutdown(IllegalStateException()) } + + val workloadB = mockk(relaxUnitFun = true) + every { workloadB.onStart(any()) } throws IllegalStateException() + + val workload = + SimWorkloads.chain( + SimRuntimeWorkload(1000, 1.0), + workloadA, + workloadB, + ) + + val exc = assertThrows { machine.runWorkload(workload) } + assertEquals(1, exc.cause!!.suppressedExceptions.size) + assertEquals(1000, timeSource.millis()) + } - val job = launch { machine.runWorkload(workload) } - delay(500L) - val snapshot = workload.snapshot() + @Test + fun testSnapshot() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - job.join() + val machine = SimBareMetalMachine.create(graph, machineModel) + val workload = + SimWorkloads.chain( + SimWorkloads.runtime(1000, 1.0), + SimWorkloads.runtime(1000, 1.0), + ) - assertEquals(2000, timeSource.millis()) + val job = launch { machine.runWorkload(workload) } + delay(500L) + val snapshot = workload.snapshot() - machine.runWorkload(snapshot) + job.join() - assertEquals(3500, timeSource.millis()) - } + assertEquals(2000, timeSource.millis()) + + machine.runWorkload(snapshot) + + assertEquals(3500, timeSource.millis()) + } } 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 index b87fd8ba..e40d4f8b 100644 --- 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 @@ -45,102 +45,113 @@ class SimTraceWorkloadTest { fun setUp() { val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2) - machineModel = MachineModel( - /*cpus*/ List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) }, - /*memory*/ List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) } - ) + machineModel = + MachineModel( + // cpus + List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) }, + // memory + List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) }, + ) } @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()) - } + 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 - } + 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()) - } + 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()) - } + 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()) + } } diff --git a/opendc-simulator/opendc-simulator-core/build.gradle.kts b/opendc-simulator/opendc-simulator-core/build.gradle.kts index 0ae95d42..027ce3e5 100644 --- a/opendc-simulator/opendc-simulator-core/build.gradle.kts +++ b/opendc-simulator/opendc-simulator-core/build.gradle.kts @@ -22,7 +22,7 @@ description = "Simulation-specific code for use in OpenDC" -/* Build configuration */ +// Build configuration plugins { `kotlin-library-conventions` } diff --git a/opendc-simulator/opendc-simulator-core/src/main/kotlin/org/opendc/simulator/kotlin/SimulationBuilders.kt b/opendc-simulator/opendc-simulator-core/src/main/kotlin/org/opendc/simulator/kotlin/SimulationBuilders.kt index 271b89e0..bc232ce0 100644 --- a/opendc-simulator/opendc-simulator-core/src/main/kotlin/org/opendc/simulator/kotlin/SimulationBuilders.kt +++ b/opendc-simulator/opendc-simulator-core/src/main/kotlin/org/opendc/simulator/kotlin/SimulationBuilders.kt @@ -66,14 +66,15 @@ import kotlin.coroutines.EmptyCoroutineContext public fun runSimulation( context: CoroutineContext = EmptyCoroutineContext, scheduler: SimulationDispatcher = SimulationDispatcher(), - body: suspend SimulationCoroutineScope.() -> Unit + body: suspend SimulationCoroutineScope.() -> Unit, ) { val (safeContext, job, dispatcher) = context.checkArguments(scheduler) val startingJobs = job.activeJobs() val scope = SimulationCoroutineScope(safeContext) - val deferred = scope.async { - body(scope) - } + val deferred = + scope.async { + body(scope) + } dispatcher.advanceUntilIdle() deferred.getCompletionExceptionOrNull()?.let { throw it @@ -105,9 +106,10 @@ private fun Job.activeJobs(): Set { * Convert a [ContinuationInterceptor] into a [SimulationDispatcher] if possible. */ internal fun ContinuationInterceptor.asSimulationDispatcher(): SimulationDispatcher { - val provider = this as? DispatcherProvider ?: throw IllegalArgumentException( - "DispatcherProvider such as SimulatorCoroutineDispatcher as the ContinuationInterceptor(Dispatcher) is required" - ) + val provider = + this as? DispatcherProvider ?: throw IllegalArgumentException( + "DispatcherProvider such as SimulatorCoroutineDispatcher as the ContinuationInterceptor(Dispatcher) is required", + ) return provider.dispatcher as? SimulationDispatcher ?: throw IllegalArgumentException("Active dispatcher is not a SimulationDispatcher") } diff --git a/opendc-simulator/opendc-simulator-core/src/main/kotlin/org/opendc/simulator/kotlin/SimulationCoroutineScope.kt b/opendc-simulator/opendc-simulator-core/src/main/kotlin/org/opendc/simulator/kotlin/SimulationCoroutineScope.kt index ca49fc53..a29e9404 100644 --- a/opendc-simulator/opendc-simulator-core/src/main/kotlin/org/opendc/simulator/kotlin/SimulationCoroutineScope.kt +++ b/opendc-simulator/opendc-simulator-core/src/main/kotlin/org/opendc/simulator/kotlin/SimulationCoroutineScope.kt @@ -43,7 +43,7 @@ public interface SimulationCoroutineScope : CoroutineScope, SimulationController */ public fun SimulationCoroutineScope( context: CoroutineContext = EmptyCoroutineContext, - scheduler: SimulationDispatcher = SimulationDispatcher() + scheduler: SimulationDispatcher = SimulationDispatcher(), ): SimulationCoroutineScope { var safeContext = context val simulationDispatcher: SimulationDispatcher diff --git a/opendc-simulator/opendc-simulator-core/src/test/kotlin/org/opendc/simulator/TaskQueueTest.kt b/opendc-simulator/opendc-simulator-core/src/test/kotlin/org/opendc/simulator/TaskQueueTest.kt index 56dd83aa..eaafedfd 100644 --- a/opendc-simulator/opendc-simulator-core/src/test/kotlin/org/opendc/simulator/TaskQueueTest.kt +++ b/opendc-simulator/opendc-simulator-core/src/test/kotlin/org/opendc/simulator/TaskQueueTest.kt @@ -47,7 +47,7 @@ class TaskQueueTest { fun testPollEmpty() { assertAll( { assertEquals(Long.MAX_VALUE, queue.peekDeadline()) }, - { assertNull(queue.poll()) } + { assertNull(queue.poll()) }, ) } @@ -63,7 +63,7 @@ class TaskQueueTest { assertAll( { assertEquals(100, queue.peekDeadline()) }, { assertEquals(entry, queue.poll()) }, - { assertNull(queue.poll()) } + { assertNull(queue.poll()) }, ) } @@ -86,7 +86,7 @@ class TaskQueueTest { { assertEquals(entryB, queue.poll()) }, { assertEquals(entryC, queue.poll()) }, { assertEquals(entryA, queue.poll()) }, - { assertNull(queue.poll()) } + { assertNull(queue.poll()) }, ) } @@ -109,7 +109,7 @@ class TaskQueueTest { { assertEquals(entryA, queue.poll()) }, { assertEquals(entryB, queue.poll()) }, { assertEquals(entryC, queue.poll()) }, - { assertNull(queue.poll()) } + { assertNull(queue.poll()) }, ) } @@ -136,7 +136,7 @@ class TaskQueueTest { { assertEquals(entryD, queue.poll()) }, { assertEquals(entryC, queue.poll()) }, { assertEquals(entryA, queue.poll()) }, - { assertNull(queue.poll()) } + { assertNull(queue.poll()) }, ) } @@ -160,7 +160,7 @@ class TaskQueueTest { { assertEquals(20, queue.peekDeadline()) }, { assertEquals(entryB, queue.poll()) }, { assertEquals(entryC, queue.poll()) }, - { assertNull(queue.poll()) } + { assertNull(queue.poll()) }, ) } @@ -184,7 +184,7 @@ class TaskQueueTest { { assertEquals(58, queue.peekDeadline()) }, { assertEquals(entryC, queue.poll()) }, { assertEquals(entryA, queue.poll()) }, - { assertNull(queue.poll()) } + { assertNull(queue.poll()) }, ) } @@ -208,7 +208,7 @@ class TaskQueueTest { { assertEquals(20, queue.peekDeadline()) }, { assertEquals(entryB, queue.poll()) }, { assertEquals(entryA, queue.poll()) }, - { assertNull(queue.poll()) } + { assertNull(queue.poll()) }, ) } @@ -228,7 +228,7 @@ class TaskQueueTest { assertAll( { assertFalse(queue.remove(10, 1)) }, - { assertFalse(queue.remove(58, 2)) } + { assertFalse(queue.remove(58, 2)) }, ) } } diff --git a/opendc-simulator/opendc-simulator-core/src/test/kotlin/org/opendc/simulator/kotlin/SimulationBuildersTest.kt b/opendc-simulator/opendc-simulator-core/src/test/kotlin/org/opendc/simulator/kotlin/SimulationBuildersTest.kt index 26419a50..b25025ef 100644 --- a/opendc-simulator/opendc-simulator-core/src/test/kotlin/org/opendc/simulator/kotlin/SimulationBuildersTest.kt +++ b/opendc-simulator/opendc-simulator-core/src/test/kotlin/org/opendc/simulator/kotlin/SimulationBuildersTest.kt @@ -38,31 +38,33 @@ import org.junit.jupiter.api.assertThrows */ class SimulationBuildersTest { @Test - fun testDelay() = runSimulation { - assertEquals(0, currentTime) - delay(100) - assertEquals(100, currentTime) - } + fun testDelay() = + runSimulation { + assertEquals(0, currentTime) + delay(100) + assertEquals(100, currentTime) + } @Test - fun testController() = runSimulation { - var completed = false + fun testController() = + runSimulation { + var completed = false - launch { - delay(20) - completed = true - } + launch { + delay(20) + completed = true + } - advanceBy(10) - assertFalse(completed) - advanceBy(11) - assertTrue(completed) + advanceBy(10) + assertFalse(completed) + advanceBy(11) + assertTrue(completed) - completed = false - launch { completed = true } - runCurrent() - assertTrue(completed) - } + completed = false + launch { completed = true } + runCurrent() + assertTrue(completed) + } @Test fun testFailOnActiveJobs() { diff --git a/opendc-simulator/opendc-simulator-flow/src/jmh/kotlin/org/opendc/simulator/flow2/FlowBenchmarks.kt b/opendc-simulator/opendc-simulator-flow/src/jmh/kotlin/org/opendc/simulator/flow2/FlowBenchmarks.kt index 59dd3bad..6bf9c2a2 100644 --- a/opendc-simulator/opendc-simulator-flow/src/jmh/kotlin/org/opendc/simulator/flow2/FlowBenchmarks.kt +++ b/opendc-simulator/opendc-simulator-flow/src/jmh/kotlin/org/opendc/simulator/flow2/FlowBenchmarks.kt @@ -50,11 +50,12 @@ class FlowBenchmarks { fun setUp() { val random = ThreadLocalRandom.current() val traceSize = 10_000_000 - trace = TraceFlowSource.Trace( - LongArray(traceSize) { (it + 1) * 1000L }, - FloatArray(traceSize) { random.nextFloat(0.0f, 4500.0f) }, - traceSize - ) + trace = + TraceFlowSource.Trace( + LongArray(traceSize) { (it + 1) * 1000L }, + FloatArray(traceSize) { random.nextFloat(0.0f, 4500.0f) }, + traceSize, + ) } @Benchmark diff --git a/opendc-simulator/opendc-simulator-flow/src/test/kotlin/org/opendc/simulator/flow2/FlowEngineTest.kt b/opendc-simulator/opendc-simulator-flow/src/test/kotlin/org/opendc/simulator/flow2/FlowEngineTest.kt index 467bf334..413a5878 100644 --- a/opendc-simulator/opendc-simulator-flow/src/test/kotlin/org/opendc/simulator/flow2/FlowEngineTest.kt +++ b/opendc-simulator/opendc-simulator-flow/src/test/kotlin/org/opendc/simulator/flow2/FlowEngineTest.kt @@ -37,161 +37,174 @@ import org.opendc.simulator.kotlin.runSimulation */ class FlowEngineTest { @Test - fun testSmoke() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() + fun testSmoke() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - val multiplexer = MaxMinFlowMultiplexer(graph) - val sink = SimpleFlowSink(graph, 2.0f) + val multiplexer = MaxMinFlowMultiplexer(graph) + val sink = SimpleFlowSink(graph, 2.0f) - graph.connect(multiplexer.newOutput(), sink.input) + graph.connect(multiplexer.newOutput(), sink.input) - val sourceA = SimpleFlowSource(graph, 2000.0f, 0.8f) - val sourceB = SimpleFlowSource(graph, 2000.0f, 0.8f) + val sourceA = SimpleFlowSource(graph, 2000.0f, 0.8f) + val sourceB = SimpleFlowSource(graph, 2000.0f, 0.8f) - graph.connect(sourceA.output, multiplexer.newInput()) - graph.connect(sourceB.output, multiplexer.newInput()) - } + graph.connect(sourceA.output, multiplexer.newInput()) + graph.connect(sourceB.output, multiplexer.newInput()) + } @Test - fun testConnectInvalidInlet() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() + fun testConnectInvalidInlet() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - val inlet = mockk() - val source = SimpleFlowSource(graph, 2000.0f, 0.8f) - assertThrows { graph.connect(source.output, inlet) } - } + val inlet = mockk() + val source = SimpleFlowSource(graph, 2000.0f, 0.8f) + assertThrows { graph.connect(source.output, inlet) } + } @Test - fun testConnectInvalidOutlet() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() + fun testConnectInvalidOutlet() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - val outlet = mockk() - val sink = SimpleFlowSink(graph, 2.0f) - assertThrows { graph.connect(outlet, sink.input) } - } + val outlet = mockk() + val sink = SimpleFlowSink(graph, 2.0f) + assertThrows { graph.connect(outlet, sink.input) } + } @Test - fun testConnectInletBelongsToDifferentGraph() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graphA = engine.newGraph() - val graphB = engine.newGraph() + fun testConnectInletBelongsToDifferentGraph() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graphA = engine.newGraph() + val graphB = engine.newGraph() - val sink = SimpleFlowSink(graphB, 2.0f) - val source = SimpleFlowSource(graphA, 2000.0f, 0.8f) + val sink = SimpleFlowSink(graphB, 2.0f) + val source = SimpleFlowSource(graphA, 2000.0f, 0.8f) - assertThrows { graphA.connect(source.output, sink.input) } - } + assertThrows { graphA.connect(source.output, sink.input) } + } @Test - fun testConnectOutletBelongsToDifferentGraph() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graphA = engine.newGraph() - val graphB = engine.newGraph() + fun testConnectOutletBelongsToDifferentGraph() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graphA = engine.newGraph() + val graphB = engine.newGraph() - val sink = SimpleFlowSink(graphA, 2.0f) - val source = SimpleFlowSource(graphB, 2000.0f, 0.8f) + val sink = SimpleFlowSink(graphA, 2.0f) + val source = SimpleFlowSource(graphB, 2000.0f, 0.8f) - assertThrows { graphA.connect(source.output, sink.input) } - } + assertThrows { graphA.connect(source.output, sink.input) } + } @Test - fun testConnectInletAlreadyConnected() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() + fun testConnectInletAlreadyConnected() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - val sink = SimpleFlowSink(graph, 2.0f) - val sourceA = SimpleFlowSource(graph, 2000.0f, 0.8f) - val sourceB = SimpleFlowSource(graph, 2000.0f, 0.8f) + val sink = SimpleFlowSink(graph, 2.0f) + val sourceA = SimpleFlowSource(graph, 2000.0f, 0.8f) + val sourceB = SimpleFlowSource(graph, 2000.0f, 0.8f) - graph.connect(sourceA.output, sink.input) - assertThrows { graph.connect(sourceB.output, sink.input) } - } + graph.connect(sourceA.output, sink.input) + assertThrows { graph.connect(sourceB.output, sink.input) } + } @Test - fun testConnectOutletAlreadyConnected() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() + fun testConnectOutletAlreadyConnected() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - val sinkA = SimpleFlowSink(graph, 2.0f) - val sinkB = SimpleFlowSink(graph, 2.0f) - val source = SimpleFlowSource(graph, 2000.0f, 0.8f) + val sinkA = SimpleFlowSink(graph, 2.0f) + val sinkB = SimpleFlowSink(graph, 2.0f) + val source = SimpleFlowSource(graph, 2000.0f, 0.8f) - graph.connect(source.output, sinkA.input) - assertThrows { graph.connect(source.output, sinkB.input) } - } + graph.connect(source.output, sinkA.input) + assertThrows { graph.connect(source.output, sinkB.input) } + } @Test - fun testDisconnectInletInvalid() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() + fun testDisconnectInletInvalid() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - val inlet = mockk() - assertThrows { graph.disconnect(inlet) } - } + val inlet = mockk() + assertThrows { graph.disconnect(inlet) } + } @Test - fun testDisconnectOutletInvalid() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() + fun testDisconnectOutletInvalid() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - val outlet = mockk() - assertThrows { graph.disconnect(outlet) } - } + val outlet = mockk() + assertThrows { graph.disconnect(outlet) } + } @Test - fun testDisconnectInletInvalidGraph() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graphA = engine.newGraph() - val graphB = engine.newGraph() + fun testDisconnectInletInvalidGraph() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graphA = engine.newGraph() + val graphB = engine.newGraph() - val sink = SimpleFlowSink(graphA, 2.0f) + val sink = SimpleFlowSink(graphA, 2.0f) - assertThrows { graphB.disconnect(sink.input) } - } + assertThrows { graphB.disconnect(sink.input) } + } @Test - fun testDisconnectOutletInvalidGraph() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graphA = engine.newGraph() - val graphB = engine.newGraph() + fun testDisconnectOutletInvalidGraph() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graphA = engine.newGraph() + val graphB = engine.newGraph() - val source = SimpleFlowSource(graphA, 2000.0f, 0.8f) + val source = SimpleFlowSource(graphA, 2000.0f, 0.8f) - assertThrows { graphB.disconnect(source.output) } - } + assertThrows { graphB.disconnect(source.output) } + } @Test - fun testInletEquality() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() + fun testInletEquality() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - val sinkA = SimpleFlowSink(graph, 2.0f) - val sinkB = SimpleFlowSink(graph, 2.0f) + val sinkA = SimpleFlowSink(graph, 2.0f) + val sinkB = SimpleFlowSink(graph, 2.0f) - val multiplexer = MaxMinFlowMultiplexer(graph) + val multiplexer = MaxMinFlowMultiplexer(graph) - assertEquals(sinkA.input, sinkA.input) - assertNotEquals(sinkA.input, sinkB.input) + assertEquals(sinkA.input, sinkA.input) + assertNotEquals(sinkA.input, sinkB.input) - assertNotEquals(multiplexer.newInput(), multiplexer.newInput()) - } + assertNotEquals(multiplexer.newInput(), multiplexer.newInput()) + } @Test - fun testOutletEquality() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() + fun testOutletEquality() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - val sourceA = SimpleFlowSource(graph, 2000.0f, 0.8f) - val sourceB = SimpleFlowSource(graph, 2000.0f, 0.8f) + val sourceA = SimpleFlowSource(graph, 2000.0f, 0.8f) + val sourceB = SimpleFlowSource(graph, 2000.0f, 0.8f) - val multiplexer = MaxMinFlowMultiplexer(graph) + val multiplexer = MaxMinFlowMultiplexer(graph) - assertEquals(sourceA.output, sourceA.output) - assertNotEquals(sourceA.output, sourceB.output) + assertEquals(sourceA.output, sourceA.output) + assertNotEquals(sourceA.output, sourceB.output) - assertNotEquals(multiplexer.newOutput(), multiplexer.newOutput()) - } + assertNotEquals(multiplexer.newOutput(), multiplexer.newOutput()) + } } diff --git a/opendc-simulator/opendc-simulator-flow/src/test/kotlin/org/opendc/simulator/flow2/FlowTimerQueueTest.kt b/opendc-simulator/opendc-simulator-flow/src/test/kotlin/org/opendc/simulator/flow2/FlowTimerQueueTest.kt index 1824959c..059bd5f5 100644 --- a/opendc-simulator/opendc-simulator-flow/src/test/kotlin/org/opendc/simulator/flow2/FlowTimerQueueTest.kt +++ b/opendc-simulator/opendc-simulator-flow/src/test/kotlin/org/opendc/simulator/flow2/FlowTimerQueueTest.kt @@ -47,7 +47,7 @@ class FlowTimerQueueTest { fun testPollEmpty() { assertAll( { assertEquals(Long.MAX_VALUE, queue.peekDeadline()) }, - { assertNull(queue.poll(100L)) } + { assertNull(queue.poll(100L)) }, ) } @@ -66,7 +66,7 @@ class FlowTimerQueueTest { { assertEquals(100, queue.peekDeadline()) }, { assertNull(queue.poll(10L)) }, { assertEquals(entry, queue.poll(200L)) }, - { assertNull(queue.poll(200L)) } + { assertNull(queue.poll(200L)) }, ) } @@ -98,7 +98,7 @@ class FlowTimerQueueTest { { assertEquals(entryB, queue.poll(100L)) }, { assertEquals(entryC, queue.poll(100L)) }, { assertEquals(entryA, queue.poll(100L)) }, - { assertNull(queue.poll(100L)) } + { assertNull(queue.poll(100L)) }, ) } @@ -137,7 +137,7 @@ class FlowTimerQueueTest { { assertEquals(entryD, queue.poll(100L)) }, { assertEquals(entryC, queue.poll(100L)) }, { assertEquals(entryA, queue.poll(100L)) }, - { assertNull(queue.poll(100L)) } + { assertNull(queue.poll(100L)) }, ) } @@ -172,7 +172,7 @@ class FlowTimerQueueTest { { assertEquals(entryA, queue.poll(100L)) }, { assertEquals(entryB, queue.poll(100L)) }, { assertEquals(entryC, queue.poll(100L)) }, - { assertNull(queue.poll(100L)) } + { assertNull(queue.poll(100L)) }, ) } @@ -207,7 +207,7 @@ class FlowTimerQueueTest { { assertEquals(entryC, queue.poll(100L)) }, { assertEquals(entryB, queue.poll(100L)) }, { assertEquals(entryA, queue.poll(100L)) }, - { assertNull(queue.poll(100L)) } + { assertNull(queue.poll(100L)) }, ) } @@ -242,7 +242,7 @@ class FlowTimerQueueTest { { assertEquals(entryB, queue.poll(100L)) }, { assertEquals(entryC, queue.poll(100L)) }, { assertEquals(entryA, queue.poll(100L)) }, - { assertNull(queue.poll(100L)) } + { assertNull(queue.poll(100L)) }, ) } @@ -277,7 +277,7 @@ class FlowTimerQueueTest { { assertEquals(entryB, queue.poll(100L)) }, { assertEquals(entryC, queue.poll(100L)) }, { assertEquals(entryA, queue.poll(100L)) }, - { assertNull(queue.poll(100L)) } + { assertNull(queue.poll(100L)) }, ) } @@ -311,7 +311,7 @@ class FlowTimerQueueTest { { assertEquals(20, queue.peekDeadline()) }, { assertEquals(entryB, queue.poll(100L)) }, { assertEquals(entryA, queue.poll(100L)) }, - { assertNull(queue.poll(100L)) } + { assertNull(queue.poll(100L)) }, ) } @@ -345,7 +345,7 @@ class FlowTimerQueueTest { { assertEquals(58, queue.peekDeadline()) }, { assertEquals(entryC, queue.poll(100L)) }, { assertEquals(entryA, queue.poll(100L)) }, - { assertNull(queue.poll(100L)) } + { assertNull(queue.poll(100L)) }, ) } @@ -379,7 +379,7 @@ class FlowTimerQueueTest { { assertEquals(20, queue.peekDeadline()) }, { assertEquals(entryB, queue.poll(100L)) }, { assertEquals(entryA, queue.poll(100L)) }, - { assertNull(queue.poll(100L)) } + { assertNull(queue.poll(100L)) }, ) } } diff --git a/opendc-simulator/opendc-simulator-flow/src/test/kotlin/org/opendc/simulator/flow2/mux/ForwardingFlowMultiplexerTest.kt b/opendc-simulator/opendc-simulator-flow/src/test/kotlin/org/opendc/simulator/flow2/mux/ForwardingFlowMultiplexerTest.kt index d1795841..2aef5174 100644 --- a/opendc-simulator/opendc-simulator-flow/src/test/kotlin/org/opendc/simulator/flow2/mux/ForwardingFlowMultiplexerTest.kt +++ b/opendc-simulator/opendc-simulator-flow/src/test/kotlin/org/opendc/simulator/flow2/mux/ForwardingFlowMultiplexerTest.kt @@ -39,33 +39,34 @@ class ForwardingFlowMultiplexerTest { * Test a trace workload. */ @Test - fun testTrace() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() + fun testTrace() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - val switch = ForwardingFlowMultiplexer(graph) - val sink = SimpleFlowSink(graph, 3200.0f) - graph.connect(switch.newOutput(), sink.input) + val switch = ForwardingFlowMultiplexer(graph) + val sink = SimpleFlowSink(graph, 3200.0f) + graph.connect(switch.newOutput(), sink.input) - yield() + yield() - assertEquals(sink.capacity, switch.capacity) { "Capacity is not detected" } + assertEquals(sink.capacity, switch.capacity) { "Capacity is not detected" } - val workload = - TraceFlowSource( - graph, - TraceFlowSource.Trace( - longArrayOf(1000, 2000, 3000, 4000), - floatArrayOf(28.0f, 3500.0f, 0.0f, 183.0f), - 4 + val workload = + TraceFlowSource( + graph, + TraceFlowSource.Trace( + longArrayOf(1000, 2000, 3000, 4000), + floatArrayOf(28.0f, 3500.0f, 0.0f, 183.0f), + 4, + ), ) - ) - graph.connect(workload.output, switch.newInput()) + graph.connect(workload.output, switch.newInput()) - advanceUntilIdle() + advanceUntilIdle() - assertAll( - { assertEquals(4000, timeSource.millis()) { "Took enough time" } } - ) - } + assertAll( + { assertEquals(4000, timeSource.millis()) { "Took enough time" } }, + ) + } } diff --git a/opendc-simulator/opendc-simulator-flow/src/test/kotlin/org/opendc/simulator/flow2/mux/MaxMinFlowMultiplexerTest.kt b/opendc-simulator/opendc-simulator-flow/src/test/kotlin/org/opendc/simulator/flow2/mux/MaxMinFlowMultiplexerTest.kt index ebae2d4e..0bcf4a3f 100644 --- a/opendc-simulator/opendc-simulator-flow/src/test/kotlin/org/opendc/simulator/flow2/mux/MaxMinFlowMultiplexerTest.kt +++ b/opendc-simulator/opendc-simulator-flow/src/test/kotlin/org/opendc/simulator/flow2/mux/MaxMinFlowMultiplexerTest.kt @@ -34,21 +34,22 @@ import org.opendc.simulator.kotlin.runSimulation */ class MaxMinFlowMultiplexerTest { @Test - fun testSmoke() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val switch = MaxMinFlowMultiplexer(graph) + fun testSmoke() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val switch = MaxMinFlowMultiplexer(graph) - val sinks = List(2) { SimpleFlowSink(graph, 2000.0f) } - for (source in sinks) { - graph.connect(switch.newOutput(), source.input) - } + val sinks = List(2) { SimpleFlowSink(graph, 2000.0f) } + for (source in sinks) { + graph.connect(switch.newOutput(), source.input) + } - val source = SimpleFlowSource(graph, 2000.0f, 1.0f) - graph.connect(source.output, switch.newInput()) + val source = SimpleFlowSource(graph, 2000.0f, 1.0f) + graph.connect(source.output, switch.newInput()) - advanceUntilIdle() + advanceUntilIdle() - assertEquals(500, timeSource.millis()) - } + assertEquals(500, timeSource.millis()) + } } diff --git a/opendc-simulator/opendc-simulator-flow/src/test/kotlin/org/opendc/simulator/flow2/sink/FlowSinkTest.kt b/opendc-simulator/opendc-simulator-flow/src/test/kotlin/org/opendc/simulator/flow2/sink/FlowSinkTest.kt index ea516c63..7085a4b9 100644 --- a/opendc-simulator/opendc-simulator-flow/src/test/kotlin/org/opendc/simulator/flow2/sink/FlowSinkTest.kt +++ b/opendc-simulator/opendc-simulator-flow/src/test/kotlin/org/opendc/simulator/flow2/sink/FlowSinkTest.kt @@ -36,82 +36,89 @@ import java.util.concurrent.ThreadLocalRandom */ class FlowSinkTest { @Test - fun testSmoke() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() + fun testSmoke() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - val sink = SimpleFlowSink(graph, 1.0f) - val source = SimpleFlowSource(graph, 2.0f, 1.0f) + val sink = SimpleFlowSink(graph, 1.0f) + val source = SimpleFlowSource(graph, 2.0f, 1.0f) - graph.connect(source.output, sink.input) - advanceUntilIdle() + graph.connect(source.output, sink.input) + advanceUntilIdle() - assertEquals(2000, timeSource.millis()) - } + assertEquals(2000, timeSource.millis()) + } @Test - fun testAdjustCapacity() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() + fun testAdjustCapacity() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - val sink = SimpleFlowSink(graph, 1.0f) - val source = SimpleFlowSource(graph, 2.0f, 1.0f) + val sink = SimpleFlowSink(graph, 1.0f) + val source = SimpleFlowSource(graph, 2.0f, 1.0f) - graph.connect(source.output, sink.input) + graph.connect(source.output, sink.input) - delay(1000) - sink.capacity = 0.5f + delay(1000) + sink.capacity = 0.5f - advanceUntilIdle() + advanceUntilIdle() - assertEquals(3000, timeSource.millis()) - } + assertEquals(3000, timeSource.millis()) + } @Test - fun testUtilization() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() + fun testUtilization() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() - val sink = SimpleFlowSink(graph, 1.0f) - val source = SimpleFlowSource(graph, 2.0f, 0.5f) + val sink = SimpleFlowSink(graph, 1.0f) + val source = SimpleFlowSource(graph, 2.0f, 0.5f) - graph.connect(source.output, sink.input) - advanceUntilIdle() + graph.connect(source.output, sink.input) + advanceUntilIdle() - assertEquals(4000, timeSource.millis()) - } + assertEquals(4000, timeSource.millis()) + } @Test - fun testFragments() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - - val sink = SimpleFlowSink(graph, 1.0f) - val trace = TraceFlowSource.Trace( - longArrayOf(1000, 2000, 3000, 4000), - floatArrayOf(1.0f, 0.5f, 2.0f, 1.0f), - 4 - ) - val source = TraceFlowSource( - graph, - trace - ) - - graph.connect(source.output, sink.input) - advanceUntilIdle() - - assertEquals(4000, timeSource.millis()) - } + fun testFragments() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + + val sink = SimpleFlowSink(graph, 1.0f) + val trace = + TraceFlowSource.Trace( + longArrayOf(1000, 2000, 3000, 4000), + floatArrayOf(1.0f, 0.5f, 2.0f, 1.0f), + 4, + ) + val source = + TraceFlowSource( + graph, + trace, + ) + + graph.connect(source.output, sink.input) + advanceUntilIdle() + + assertEquals(4000, timeSource.millis()) + } @Test fun benchmarkSink() { val random = ThreadLocalRandom.current() val traceSize = 10000000 - val trace = TraceFlowSource.Trace( - LongArray(traceSize) { it * 1000L }, - FloatArray(traceSize) { random.nextDouble(0.0, 4500.0).toFloat() }, - traceSize - ) + val trace = + TraceFlowSource.Trace( + LongArray(traceSize) { it * 1000L }, + FloatArray(traceSize) { random.nextDouble(0.0, 4500.0).toFloat() }, + traceSize, + ) return runSimulation { val engine = FlowEngine.create(dispatcher) diff --git a/opendc-simulator/opendc-simulator-network/src/test/kotlin/org/opendc/simulator/network/SimNetworkSinkTest.kt b/opendc-simulator/opendc-simulator-network/src/test/kotlin/org/opendc/simulator/network/SimNetworkSinkTest.kt index 181d9a20..4655bfea 100644 --- a/opendc-simulator/opendc-simulator-network/src/test/kotlin/org/opendc/simulator/network/SimNetworkSinkTest.kt +++ b/opendc-simulator/opendc-simulator-network/src/test/kotlin/org/opendc/simulator/network/SimNetworkSinkTest.kt @@ -42,105 +42,112 @@ import org.opendc.simulator.kotlin.runSimulation */ class SimNetworkSinkTest { @Test - fun testInitialState() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val sink = SimNetworkSink(graph, /*capacity*/ 100.0f) - - assertAll( - { assertFalse(sink.isConnected) }, - { assertNull(sink.link) }, - { assertEquals(100.0f, sink.capacity) } - ) - } + fun testInitialState() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val sink = SimNetworkSink(graph, 100.0f) + + assertAll( + { assertFalse(sink.isConnected) }, + { assertNull(sink.link) }, + { assertEquals(100.0f, sink.capacity) }, + ) + } @Test - fun testDisconnectIdempotent() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val sink = SimNetworkSink(graph, /*capacity*/ 100.0f) - - assertDoesNotThrow { sink.disconnect() } - assertFalse(sink.isConnected) - } + fun testDisconnectIdempotent() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val sink = SimNetworkSink(graph, 100.0f) + + assertDoesNotThrow { sink.disconnect() } + assertFalse(sink.isConnected) + } @Test - fun testConnectCircular() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val sink = SimNetworkSink(graph, /*capacity*/ 100.0f) - - assertThrows { - sink.connect(sink) + fun testConnectCircular() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val sink = SimNetworkSink(graph, 100.0f) + + assertThrows { + sink.connect(sink) + } } - } @Test - fun testConnectAlreadyConnectedTarget() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val sink = SimNetworkSink(graph, /*capacity*/ 100.0f) - val source = mockk(relaxUnitFun = true) - every { source.isConnected } returns true - - assertThrows { - sink.connect(source) + fun testConnectAlreadyConnectedTarget() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val sink = SimNetworkSink(graph, 100.0f) + val source = mockk(relaxUnitFun = true) + every { source.isConnected } returns true + + assertThrows { + sink.connect(source) + } } - } @Test - fun testConnectAlreadyConnected() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val sink = SimNetworkSink(graph, /*capacity*/ 100.0f) - val source1 = TestSource(graph) + fun testConnectAlreadyConnected() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val sink = SimNetworkSink(graph, 100.0f) + val source1 = TestSource(graph) - val source2 = mockk(relaxUnitFun = true) + val source2 = mockk(relaxUnitFun = true) - every { source2.isConnected } returns false + every { source2.isConnected } returns false - sink.connect(source1) - assertThrows { - sink.connect(source2) + sink.connect(source1) + assertThrows { + sink.connect(source2) + } } - } @Test - fun testConnect() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val sink = SimNetworkSink(graph, /*capacity*/ 100.0f) - val source = TestSource(graph) + fun testConnect() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val sink = SimNetworkSink(graph, 100.0f) + val source = TestSource(graph) - sink.connect(source) + sink.connect(source) - yield() + yield() - assertAll( - { assertTrue(sink.isConnected) }, - { assertTrue(source.isConnected) }, - { assertEquals(100.0f, source.outlet.capacity) } - ) + assertAll( + { assertTrue(sink.isConnected) }, + { assertTrue(source.isConnected) }, + { assertEquals(100.0f, source.outlet.capacity) }, + ) - verify { source.logic.onUpdate(any(), any()) } - } + verify { source.logic.onUpdate(any(), any()) } + } @Test - fun testDisconnect() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val sink = SimNetworkSink(graph, /*capacity*/ 100.0f) - val source = TestSource(graph) - - sink.connect(source) - sink.disconnect() - - yield() - - assertAll( - { assertFalse(sink.isConnected) }, - { assertFalse(source.isConnected) }, - { assertEquals(0.0f, source.outlet.capacity) } - ) - } + fun testDisconnect() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val sink = SimNetworkSink(graph, 100.0f) + val source = TestSource(graph) + + sink.connect(source) + sink.disconnect() + + yield() + + assertAll( + { assertFalse(sink.isConnected) }, + { assertFalse(source.isConnected) }, + { assertEquals(0.0f, source.outlet.capacity) }, + ) + } } diff --git a/opendc-simulator/opendc-simulator-network/src/test/kotlin/org/opendc/simulator/network/SimNetworkSwitchVirtualTest.kt b/opendc-simulator/opendc-simulator-network/src/test/kotlin/org/opendc/simulator/network/SimNetworkSwitchVirtualTest.kt index 4a489478..b5a00ffc 100644 --- a/opendc-simulator/opendc-simulator-network/src/test/kotlin/org/opendc/simulator/network/SimNetworkSwitchVirtualTest.kt +++ b/opendc-simulator/opendc-simulator-network/src/test/kotlin/org/opendc/simulator/network/SimNetworkSwitchVirtualTest.kt @@ -37,39 +37,41 @@ import org.opendc.simulator.kotlin.runSimulation */ class SimNetworkSwitchVirtualTest { @Test - fun testConnect() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val sink = SimNetworkSink(graph, /*capacity*/ 100.0f) - val source = TestSource(graph) - val switch = SimNetworkSwitchVirtual(graph) + fun testConnect() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val sink = SimNetworkSink(graph, 100.0f) + val source = TestSource(graph) + val switch = SimNetworkSwitchVirtual(graph) - switch.newPort().connect(sink) - switch.newPort().connect(source) + switch.newPort().connect(sink) + switch.newPort().connect(source) - yield() + yield() - assertAll( - { assertTrue(sink.isConnected) }, - { assertTrue(source.isConnected) }, - { assertEquals(100.0f, source.outlet.capacity) } - ) + assertAll( + { assertTrue(sink.isConnected) }, + { assertTrue(source.isConnected) }, + { assertEquals(100.0f, source.outlet.capacity) }, + ) - verify { source.logic.onUpdate(any(), any()) } - } + verify { source.logic.onUpdate(any(), any()) } + } @Test - fun testConnectClosedPort() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val sink = SimNetworkSink(graph, /*capacity*/ 100.0f) - val switch = SimNetworkSwitchVirtual(graph) + fun testConnectClosedPort() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val sink = SimNetworkSink(graph, 100.0f) + val switch = SimNetworkSwitchVirtual(graph) - val port = switch.newPort() - port.close() + val port = switch.newPort() + port.close() - assertThrows { - port.connect(sink) + assertThrows { + port.connect(sink) + } } - } } diff --git a/opendc-simulator/opendc-simulator-network/src/test/kotlin/org/opendc/simulator/network/TestSource.kt b/opendc-simulator/opendc-simulator-network/src/test/kotlin/org/opendc/simulator/network/TestSource.kt index f69db7a2..298a5d48 100644 --- a/opendc-simulator/opendc-simulator-network/src/test/kotlin/org/opendc/simulator/network/TestSource.kt +++ b/opendc-simulator/opendc-simulator-network/src/test/kotlin/org/opendc/simulator/network/TestSource.kt @@ -45,7 +45,10 @@ class TestSource(graph: FlowGraph) : SimNetworkPort(), FlowStageLogic { outlet.push(80.0f) } - override fun onUpdate(ctx: FlowStage, now: Long): Long = Long.MAX_VALUE + override fun onUpdate( + ctx: FlowStage, + now: Long, + ): Long = Long.MAX_VALUE override fun getOutlet(): Outlet = outlet diff --git a/opendc-simulator/opendc-simulator-power/src/test/kotlin/org/opendc/simulator/power/SimPduTest.kt b/opendc-simulator/opendc-simulator-power/src/test/kotlin/org/opendc/simulator/power/SimPduTest.kt index f596ca4e..9df72c49 100644 --- a/opendc-simulator/opendc-simulator-power/src/test/kotlin/org/opendc/simulator/power/SimPduTest.kt +++ b/opendc-simulator/opendc-simulator-power/src/test/kotlin/org/opendc/simulator/power/SimPduTest.kt @@ -34,94 +34,100 @@ import org.opendc.simulator.kotlin.runSimulation */ internal class SimPduTest { @Test - fun testZeroOutlets() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val source = SimPowerSource(graph, /*capacity*/ 100.0f) - val pdu = SimPdu(graph) - source.connect(pdu) + fun testZeroOutlets() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val source = SimPowerSource(graph, 100.0f) + val pdu = SimPdu(graph) + source.connect(pdu) - yield() + yield() - assertEquals(0.0f, source.powerDraw) - } + assertEquals(0.0f, source.powerDraw) + } @Test - fun testSingleOutlet() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val source = SimPowerSource(graph, /*capacity*/ 100.0f) - val pdu = SimPdu(graph) - source.connect(pdu) - pdu.newOutlet().connect(TestInlet(graph)) - - yield() - - assertEquals(100.0f, source.powerDraw) - } + fun testSingleOutlet() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val source = SimPowerSource(graph, 100.0f) + val pdu = SimPdu(graph) + source.connect(pdu) + pdu.newOutlet().connect(TestInlet(graph)) + + yield() + + assertEquals(100.0f, source.powerDraw) + } @Test - fun testDoubleOutlet() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val source = SimPowerSource(graph, /*capacity*/ 200.0f) - val pdu = SimPdu(graph) - source.connect(pdu) + fun testDoubleOutlet() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val source = SimPowerSource(graph, 200.0f) + val pdu = SimPdu(graph) + source.connect(pdu) - pdu.newOutlet().connect(TestInlet(graph)) - pdu.newOutlet().connect(TestInlet(graph)) + pdu.newOutlet().connect(TestInlet(graph)) + pdu.newOutlet().connect(TestInlet(graph)) - yield() + yield() - assertEquals(200.0f, source.powerDraw) - } + assertEquals(200.0f, source.powerDraw) + } @Test - fun testDisconnect() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val source = SimPowerSource(graph, /*capacity*/ 300.0f) - val pdu = SimPdu(graph) - source.connect(pdu) - - val outlet = pdu.newOutlet() - outlet.connect(TestInlet(graph)) - outlet.disconnect() + fun testDisconnect() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val source = SimPowerSource(graph, 300.0f) + val pdu = SimPdu(graph) + source.connect(pdu) + + val outlet = pdu.newOutlet() + outlet.connect(TestInlet(graph)) + outlet.disconnect() - yield() + yield() - assertEquals(0.0f, source.powerDraw) - } + assertEquals(0.0f, source.powerDraw) + } @Test - fun testLoss() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val source = SimPowerSource(graph, /*capacity*/ 500.0f) - // https://download.schneider-electric.com/files?p_Doc_Ref=SPD_NRAN-66CK3D_EN - val pdu = SimPdu(graph, /*idlePower*/ 1.5f, /*lossCoefficient*/ 0.015f) - source.connect(pdu) - pdu.newOutlet().connect(TestInlet(graph)) - - yield() - - assertEquals(251.5f, source.powerDraw, 0.01f) - } + fun testLoss() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val source = SimPowerSource(graph, 500.0f) + // https://download.schneider-electric.com/files?p_Doc_Ref=SPD_NRAN-66CK3D_EN + val pdu = SimPdu(graph, 1.5f, 0.015f) + source.connect(pdu) + pdu.newOutlet().connect(TestInlet(graph)) + + yield() + + assertEquals(251.5f, source.powerDraw, 0.01f) + } @Test - fun testOutletClose() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val source = SimPowerSource(graph, /*capacity*/ 100.0f) - val pdu = SimPdu(graph) - source.connect(pdu) - val outlet = pdu.newOutlet() - outlet.close() - - yield() - - assertThrows { - outlet.connect(TestInlet(graph)) + fun testOutletClose() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val source = SimPowerSource(graph, 100.0f) + val pdu = SimPdu(graph) + source.connect(pdu) + val outlet = pdu.newOutlet() + outlet.close() + + yield() + + assertThrows { + outlet.connect(TestInlet(graph)) + } } - } } diff --git a/opendc-simulator/opendc-simulator-power/src/test/kotlin/org/opendc/simulator/power/SimPowerSourceTest.kt b/opendc-simulator/opendc-simulator-power/src/test/kotlin/org/opendc/simulator/power/SimPowerSourceTest.kt index 03c942b4..bbc9ad92 100644 --- a/opendc-simulator/opendc-simulator-power/src/test/kotlin/org/opendc/simulator/power/SimPowerSourceTest.kt +++ b/opendc-simulator/opendc-simulator-power/src/test/kotlin/org/opendc/simulator/power/SimPowerSourceTest.kt @@ -41,108 +41,115 @@ import org.opendc.simulator.kotlin.runSimulation */ internal class SimPowerSourceTest { @Test - fun testInitialState() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val source = SimPowerSource(graph, /*capacity*/ 100.0f) - - yield() - - assertAll( - { assertFalse(source.isConnected) }, - { assertNull(source.inlet) }, - { assertEquals(100.0f, source.capacity) } - ) - } + fun testInitialState() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val source = SimPowerSource(graph, 100.0f) + + yield() + + assertAll( + { assertFalse(source.isConnected) }, + { assertNull(source.inlet) }, + { assertEquals(100.0f, source.capacity) }, + ) + } @Test - fun testDisconnectIdempotent() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val source = SimPowerSource(graph, /*capacity*/ 100.0f) - - assertDoesNotThrow { source.disconnect() } - assertFalse(source.isConnected) - } + fun testDisconnectIdempotent() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val source = SimPowerSource(graph, 100.0f) + + assertDoesNotThrow { source.disconnect() } + assertFalse(source.isConnected) + } @Test - fun testConnect() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val source = SimPowerSource(graph, /*capacity*/ 100.0f) - val inlet = TestInlet(graph) + fun testConnect() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val source = SimPowerSource(graph, 100.0f) + val inlet = TestInlet(graph) - source.connect(inlet) + source.connect(inlet) - yield() + yield() - assertAll( - { assertTrue(source.isConnected) }, - { assertEquals(inlet, source.inlet) }, - { assertTrue(inlet.isConnected) }, - { assertEquals(source, inlet.outlet) }, - { assertEquals(100.0f, source.powerDraw) } - ) - } + assertAll( + { assertTrue(source.isConnected) }, + { assertEquals(inlet, source.inlet) }, + { assertTrue(inlet.isConnected) }, + { assertEquals(source, inlet.outlet) }, + { assertEquals(100.0f, source.powerDraw) }, + ) + } @Test - fun testDisconnect() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val source = SimPowerSource(graph, /*capacity*/ 100.0f) - val inlet = TestInlet(graph) + fun testDisconnect() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val source = SimPowerSource(graph, 100.0f) + val inlet = TestInlet(graph) - source.connect(inlet) - source.disconnect() + source.connect(inlet) + source.disconnect() - yield() + yield() - assertEquals(0.0f, inlet.flowOutlet.capacity) - } + assertEquals(0.0f, inlet.flowOutlet.capacity) + } @Test - fun testDisconnectAssertion() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val source = SimPowerSource(graph, /*capacity*/ 100.0f) + fun testDisconnectAssertion() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val source = SimPowerSource(graph, 100.0f) - val inlet = mockk(relaxUnitFun = true) - every { inlet.isConnected } returns false - every { inlet.flowOutlet } returns TestInlet(graph).flowOutlet + val inlet = mockk(relaxUnitFun = true) + every { inlet.isConnected } returns false + every { inlet.flowOutlet } returns TestInlet(graph).flowOutlet - source.connect(inlet) - inlet.outlet = null + source.connect(inlet) + inlet.outlet = null - assertThrows { - source.disconnect() + assertThrows { + source.disconnect() + } } - } @Test - fun testOutletAlreadyConnected() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val source = SimPowerSource(graph, /*capacity*/ 100.0f) - val inlet = TestInlet(graph) - - source.connect(inlet) - assertThrows { - source.connect(TestInlet(graph)) - } + fun testOutletAlreadyConnected() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val source = SimPowerSource(graph, 100.0f) + val inlet = TestInlet(graph) - assertEquals(inlet, source.inlet) - } + source.connect(inlet) + assertThrows { + source.connect(TestInlet(graph)) + } + + assertEquals(inlet, source.inlet) + } @Test - fun testInletAlreadyConnected() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val source = SimPowerSource(graph, /*capacity*/ 100.0f) - val inlet = mockk(relaxUnitFun = true) - every { inlet.isConnected } returns true - - assertThrows { - source.connect(inlet) + fun testInletAlreadyConnected() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val source = SimPowerSource(graph, 100.0f) + val inlet = mockk(relaxUnitFun = true) + every { inlet.isConnected } returns true + + assertThrows { + source.connect(inlet) + } } - } } diff --git a/opendc-simulator/opendc-simulator-power/src/test/kotlin/org/opendc/simulator/power/SimUpsTest.kt b/opendc-simulator/opendc-simulator-power/src/test/kotlin/org/opendc/simulator/power/SimUpsTest.kt index 89fede63..cbd23887 100644 --- a/opendc-simulator/opendc-simulator-power/src/test/kotlin/org/opendc/simulator/power/SimUpsTest.kt +++ b/opendc-simulator/opendc-simulator-power/src/test/kotlin/org/opendc/simulator/power/SimUpsTest.kt @@ -34,71 +34,75 @@ import org.opendc.simulator.kotlin.runSimulation */ internal class SimUpsTest { @Test - fun testSingleInlet() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val source = SimPowerSource(graph, /*capacity*/ 200.0f) - val ups = SimUps(graph) - source.connect(ups.newInlet()) - ups.connect(TestInlet(graph)) + fun testSingleInlet() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val source = SimPowerSource(graph, 200.0f) + val ups = SimUps(graph) + source.connect(ups.newInlet()) + ups.connect(TestInlet(graph)) - yield() + yield() - assertEquals(100.0f, source.powerDraw) - } + assertEquals(100.0f, source.powerDraw) + } @Test - fun testDoubleInlet() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val source1 = SimPowerSource(graph, /*capacity*/ 200.0f) - val source2 = SimPowerSource(graph, /*capacity*/ 200.0f) - val ups = SimUps(graph) - source1.connect(ups.newInlet()) - source2.connect(ups.newInlet()) - - ups.connect(TestInlet(graph)) - - yield() - - assertAll( - { assertEquals(50.0f, source1.powerDraw) }, - { assertEquals(50.0f, source2.powerDraw) } - ) - } + fun testDoubleInlet() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val source1 = SimPowerSource(graph, 200.0f) + val source2 = SimPowerSource(graph, 200.0f) + val ups = SimUps(graph) + source1.connect(ups.newInlet()) + source2.connect(ups.newInlet()) + + ups.connect(TestInlet(graph)) + + yield() + + assertAll( + { assertEquals(50.0f, source1.powerDraw) }, + { assertEquals(50.0f, source2.powerDraw) }, + ) + } @Test - fun testLoss() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val source = SimPowerSource(graph, /*capacity*/ 500.0f) - // https://download.schneider-electric.com/files?p_Doc_Ref=SPD_NRAN-66CK3D_EN - val ups = SimUps(graph, /*idlePower*/ 4.0f, /*lossCoefficient*/ 0.05f) - source.connect(ups.newInlet()) - ups.connect(TestInlet(graph)) + fun testLoss() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val source = SimPowerSource(graph, 500.0f) + // https://download.schneider-electric.com/files?p_Doc_Ref=SPD_NRAN-66CK3D_EN + val ups = SimUps(graph, 4.0f, 0.05f) + source.connect(ups.newInlet()) + ups.connect(TestInlet(graph)) - yield() + yield() - assertEquals(109.0f, source.powerDraw, 0.01f) - } + assertEquals(109.0f, source.powerDraw, 0.01f) + } @Test - fun testDisconnect() = runSimulation { - val engine = FlowEngine.create(dispatcher) - val graph = engine.newGraph() - val source1 = SimPowerSource(graph, /*capacity*/ 200.0f) - val source2 = SimPowerSource(graph, /*capacity*/ 200.0f) - val ups = SimUps(graph) - source1.connect(ups.newInlet()) - source2.connect(ups.newInlet()) + fun testDisconnect() = + runSimulation { + val engine = FlowEngine.create(dispatcher) + val graph = engine.newGraph() + val source1 = SimPowerSource(graph, 200.0f) + val source2 = SimPowerSource(graph, 200.0f) + val ups = SimUps(graph) + source1.connect(ups.newInlet()) + source2.connect(ups.newInlet()) - val inlet = TestInlet(graph) + val inlet = TestInlet(graph) - ups.connect(inlet) - ups.disconnect() + ups.connect(inlet) + ups.disconnect() - yield() + yield() - assertEquals(0.0f, inlet.flowOutlet.capacity) - } + assertEquals(0.0f, inlet.flowOutlet.capacity) + } } diff --git a/opendc-simulator/opendc-simulator-power/src/test/kotlin/org/opendc/simulator/power/TestInlet.kt b/opendc-simulator/opendc-simulator-power/src/test/kotlin/org/opendc/simulator/power/TestInlet.kt index d5f509e7..1c06acf4 100644 --- a/opendc-simulator/opendc-simulator-power/src/test/kotlin/org/opendc/simulator/power/TestInlet.kt +++ b/opendc-simulator/opendc-simulator-power/src/test/kotlin/org/opendc/simulator/power/TestInlet.kt @@ -38,7 +38,10 @@ class TestInlet(graph: FlowGraph) : SimPowerInlet(), FlowStageLogic { flowOutlet.push(100.0f) } - override fun onUpdate(ctx: FlowStage, now: Long): Long = Long.MAX_VALUE + override fun onUpdate( + ctx: FlowStage, + now: Long, + ): Long = Long.MAX_VALUE override fun getFlowOutlet(): Outlet { return flowOutlet -- cgit v1.2.3