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 --- .../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 +++--- 7 files changed, 979 insertions(+), 858 deletions(-) (limited to 'opendc-simulator/opendc-simulator-compute/src/test') 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()) + } } -- cgit v1.2.3