diff options
Diffstat (limited to 'opendc-compute/opendc-compute-service/src/test')
6 files changed, 0 insertions, 1536 deletions
diff --git a/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/ComputeServiceTest.kt b/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/ComputeServiceTest.kt deleted file mode 100644 index eb686faf..00000000 --- a/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/ComputeServiceTest.kt +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.compute.service - -import io.mockk.coEvery -import io.mockk.coVerify -import io.mockk.every -import io.mockk.mockk -import io.mockk.slot -import io.mockk.verify -import kotlinx.coroutines.delay -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertNull -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertThrows -import org.opendc.compute.api.Flavor -import org.opendc.compute.api.Image -import org.opendc.compute.api.Task -import org.opendc.compute.api.TaskState -import org.opendc.compute.api.TaskWatcher -import org.opendc.compute.service.driver.Host -import org.opendc.compute.service.driver.HostListener -import org.opendc.compute.service.driver.HostModel -import org.opendc.compute.service.driver.HostState -import org.opendc.compute.service.scheduler.FilterScheduler -import org.opendc.compute.service.scheduler.filters.ComputeFilter -import org.opendc.compute.service.scheduler.filters.RamFilter -import org.opendc.compute.service.scheduler.filters.VCpuFilter -import org.opendc.compute.service.scheduler.weights.RamWeigher -import org.opendc.simulator.kotlin.SimulationCoroutineScope -import org.opendc.simulator.kotlin.runSimulation -import java.time.Duration -import java.util.UUID - -/** - * Test suite for the [ComputeService] interface. - */ -internal class ComputeServiceTest { - private lateinit var scope: SimulationCoroutineScope - private lateinit var service: ComputeService - - @BeforeEach - fun setUp() { - scope = SimulationCoroutineScope() - val computeScheduler = - FilterScheduler( - filters = listOf(ComputeFilter(), VCpuFilter(allocationRatio = 1.0), RamFilter(allocationRatio = 1.0)), - weighers = listOf(RamWeigher()), - ) - service = ComputeService(scope.dispatcher, computeScheduler, Duration.ofMinutes(5), 10) - } - - @Test - fun testClientClose() = - scope.runSimulation { - val client = service.newClient() - - assertEquals(emptyList<Flavor>(), client.queryFlavors()) - assertEquals(emptyList<Image>(), client.queryImages()) - assertEquals(emptyList<Task>(), client.queryTasks()) - - client.close() - - assertThrows<IllegalStateException> { client.queryFlavors() } - assertThrows<IllegalStateException> { client.queryImages() } - assertThrows<IllegalStateException> { client.queryTasks() } - - assertThrows<IllegalStateException> { client.findFlavor(UUID.randomUUID()) } - assertThrows<IllegalStateException> { client.findImage(UUID.randomUUID()) } - assertThrows<IllegalStateException> { client.findTask(UUID.randomUUID()) } - - assertThrows<IllegalStateException> { client.newFlavor("test", 1, 2) } - assertThrows<IllegalStateException> { client.newImage("test") } - assertThrows<IllegalStateException> { client.newTask("test", mockk(), mockk()) } - } - - @Test - fun testClientCreate() = - scope.runSimulation { - val client = service.newClient() - - val flavor = client.newFlavor("test", 1, 1024) - assertEquals(listOf(flavor), client.queryFlavors()) - assertEquals(flavor, client.findFlavor(flavor.uid)) - val image = client.newImage("test") - assertEquals(listOf(image), client.queryImages()) - assertEquals(image, client.findImage(image.uid)) - val server = client.newTask("test", image, flavor, start = false) - assertEquals(listOf(server), client.queryTasks()) - assertEquals(server, client.findTask(server.uid)) - - server.delete() - assertNull(client.findTask(server.uid)) - - image.delete() - assertNull(client.findImage(image.uid)) - - flavor.delete() - assertNull(client.findFlavor(flavor.uid)) - - assertThrows<IllegalStateException> { server.start() } - } - - @Test - fun testClientOnClose() = - scope.runSimulation { - service.close() - assertThrows<IllegalStateException> { - service.newClient() - } - } - - @Test - fun testAddHost() = - scope.runSimulation { - val host = mockk<Host>(relaxUnitFun = true) - - every { host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { host.state } returns HostState.UP - - assertEquals(emptySet<Host>(), service.hosts) - - service.addHost(host) - - verify(exactly = 1) { host.addListener(any()) } - - assertEquals(1, service.hosts.size) - - service.removeHost(host) - - verify(exactly = 1) { host.removeListener(any()) } - } - - @Test - fun testAddHostDouble() = - scope.runSimulation { - val host = mockk<Host>(relaxUnitFun = true) - - every { host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { host.state } returns HostState.DOWN - - assertEquals(emptySet<Host>(), service.hosts) - - service.addHost(host) - service.addHost(host) - - verify(exactly = 1) { host.addListener(any()) } - } - - @Test - fun testServerStartWithoutEnoughCpus() = - scope.runSimulation { - val client = service.newClient() - val flavor = client.newFlavor("test", 1, 0) - val image = client.newImage("test") - val server = client.newTask("test", image, flavor, start = false) - - server.start() - delay(5L * 60 * 1000) - server.reload() - assertEquals(TaskState.TERMINATED, server.state) - } - - @Test - fun testServerStartWithoutEnoughMemory() = - scope.runSimulation { - val client = service.newClient() - val flavor = client.newFlavor("test", 0, 1024) - val image = client.newImage("test") - val server = client.newTask("test", image, flavor, start = false) - - server.start() - delay(5L * 60 * 1000) - server.reload() - assertEquals(TaskState.TERMINATED, server.state) - } - - @Test - fun testServerStartWithoutEnoughResources() = - scope.runSimulation { - val client = service.newClient() - val flavor = client.newFlavor("test", 1, 1024) - val image = client.newImage("test") - val server = client.newTask("test", image, flavor, start = false) - - server.start() - delay(5L * 60 * 1000) - server.reload() - assertEquals(TaskState.TERMINATED, server.state) - } - - @Test - fun testServerCancelRequest() = - scope.runSimulation { - val client = service.newClient() - val flavor = client.newFlavor("test", 1, 1024) - val image = client.newImage("test") - val server = client.newTask("test", image, flavor, start = false) - - server.start() - server.stop() - delay(5L * 60 * 1000) - server.reload() - assertEquals(TaskState.TERMINATED, server.state) - } - - @Test - fun testServerCannotFitOnHost() = - scope.runSimulation { - val host = mockk<Host>(relaxUnitFun = true) - - every { host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { host.state } returns HostState.UP - every { host.canFit(any()) } returns false - - service.addHost(host) - - val client = service.newClient() - val flavor = client.newFlavor("test", 1, 1024) - val image = client.newImage("test") - val server = client.newTask("test", image, flavor, start = false) - - server.start() - delay(10L * 60 * 1000) - server.reload() - assertEquals(TaskState.PROVISIONING, server.state) - - verify { host.canFit(server) } - } - - @Test - fun testHostAvailableAfterSomeTime() = - scope.runSimulation { - val host = mockk<Host>(relaxUnitFun = true) - val listeners = mutableListOf<HostListener>() - - every { host.uid } returns UUID.randomUUID() - every { host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { host.state } returns HostState.DOWN - every { host.addListener(any()) } answers { listeners.add(it.invocation.args[0] as HostListener) } - every { host.canFit(any()) } returns false - - service.addHost(host) - - val client = service.newClient() - val flavor = client.newFlavor("test", 1, 1024) - val image = client.newImage("test") - val server = client.newTask("test", image, flavor, start = false) - - server.start() - delay(5L * 60 * 1000) - - every { host.state } returns HostState.UP - listeners.forEach { it.onStateChanged(host, HostState.UP) } - - delay(5L * 60 * 1000) - server.reload() - assertEquals(TaskState.PROVISIONING, server.state) - - verify { host.canFit(server) } - } - - @Test - fun testHostUnavailableAfterSomeTime() = - scope.runSimulation { - val host = mockk<Host>(relaxUnitFun = true) - val listeners = mutableListOf<HostListener>() - - every { host.uid } returns UUID.randomUUID() - every { host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { host.state } returns HostState.UP - every { host.addListener(any()) } answers { listeners.add(it.invocation.args[0] as HostListener) } - every { host.canFit(any()) } returns false - - service.addHost(host) - - val client = service.newClient() - val flavor = client.newFlavor("test", 1, 1024) - val image = client.newImage("test") - val server = client.newTask("test", image, flavor, start = false) - - delay(5L * 60 * 1000) - - every { host.state } returns HostState.DOWN - listeners.forEach { it.onStateChanged(host, HostState.DOWN) } - - server.start() - delay(5L * 60 * 1000) - server.reload() - assertEquals(TaskState.PROVISIONING, server.state) - - verify(exactly = 0) { host.canFit(server) } - } - - @Test - fun testServerDeploy() = - scope.runSimulation { - val host = mockk<Host>(relaxUnitFun = true) - val listeners = mutableListOf<HostListener>() - - every { host.uid } returns UUID.randomUUID() - every { host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { host.state } returns HostState.UP - every { host.canFit(any()) } returns true - every { host.addListener(any()) } answers { listeners.add(it.invocation.args[0] as HostListener) } - - service.addHost(host) - - val client = service.newClient() - val flavor = client.newFlavor("test", 1, 1024) - val image = client.newImage("test") - val server = client.newTask("test", image, flavor, start = false) - val slot = slot<Task>() - - val watcher = mockk<TaskWatcher>(relaxUnitFun = true) - server.watch(watcher) - - // Start server - server.start() - delay(5L * 60 * 1000) - coVerify { host.spawn(capture(slot)) } - - listeners.forEach { it.onStateChanged(host, slot.captured, TaskState.RUNNING) } - - server.reload() - assertEquals(TaskState.RUNNING, server.state) - - verify { watcher.onStateChanged(server, TaskState.RUNNING) } - - // Stop server - listeners.forEach { it.onStateChanged(host, slot.captured, TaskState.TERMINATED) } - - server.reload() - assertEquals(TaskState.TERMINATED, server.state) - - verify { watcher.onStateChanged(server, TaskState.TERMINATED) } - } - - @Test - fun testServerDeployFailure() = - scope.runSimulation { - val host = mockk<Host>(relaxUnitFun = true) - val listeners = mutableListOf<HostListener>() - - every { host.uid } returns UUID.randomUUID() - every { host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { host.state } returns HostState.UP - every { host.canFit(any()) } returns true - every { host.addListener(any()) } answers { listeners.add(it.invocation.args[0] as HostListener) } - coEvery { host.spawn(any()) } throws IllegalStateException() - - service.addHost(host) - - val client = service.newClient() - val flavor = client.newFlavor("test", 1, 1024) - val image = client.newImage("test") - val server = client.newTask("test", image, flavor, start = false) - - server.start() - delay(5L * 60 * 1000) - - server.reload() - assertEquals(TaskState.PROVISIONING, server.state) - } -} diff --git a/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/ServiceFlavorTest.kt b/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/ServiceFlavorTest.kt deleted file mode 100644 index 7938f789..00000000 --- a/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/ServiceFlavorTest.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.compute.service - -import io.mockk.every -import io.mockk.mockk -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertNotEquals -import org.junit.jupiter.api.Test -import org.opendc.compute.api.Flavor -import java.util.UUID - -/** - * Test suite for the [ServiceFlavor] implementation. - */ -class ServiceFlavorTest { - @Test - fun testEquality() { - val service = mockk<ComputeService>() - val uid = UUID.randomUUID() - val a = ServiceFlavor(service, uid, "test", 1, 1024, mutableMapOf(), mutableMapOf<String, Any>()) - val b = ServiceFlavor(service, uid, "test", 1, 1024, mutableMapOf(), mutableMapOf<String, Any>()) - - assertEquals(a, b) - } - - @Test - fun testInequalityWithDifferentType() { - val service = mockk<ComputeService>() - val uid = UUID.randomUUID() - val a = ServiceFlavor(service, uid, "test", 1, 1024, mutableMapOf(), mutableMapOf<String, Any>()) - - val b = mockk<Flavor>(relaxUnitFun = true) - every { b.uid } returns UUID.randomUUID() - - assertNotEquals(a, b) - } - - @Test - fun testInequalityWithIncorrectType() { - val service = mockk<ComputeService>() - val uid = UUID.randomUUID() - val a = ServiceFlavor(service, uid, "test", 1, 1024, mutableMapOf(), mutableMapOf<String, Any>()) - - assertNotEquals(a, Unit) - } -} diff --git a/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/ServiceImageTest.kt b/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/ServiceImageTest.kt deleted file mode 100644 index c36d75f4..00000000 --- a/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/ServiceImageTest.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.compute.service - -import io.mockk.every -import io.mockk.mockk -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertNotEquals -import org.junit.jupiter.api.Test -import org.opendc.compute.api.Image -import java.util.UUID - -/** - * Test suite for the [ServiceFlavor] implementation. - */ -class ServiceImageTest { - @Test - fun testEquality() { - val service = mockk<ComputeService>() - val uid = UUID.randomUUID() - val a = ServiceImage(service, uid, "test", mutableMapOf(), mutableMapOf<String, Any>()) - val b = ServiceImage(service, uid, "test", mutableMapOf(), mutableMapOf<String, Any>()) - - assertEquals(a, b) - } - - @Test - fun testInequalityWithDifferentType() { - val service = mockk<ComputeService>() - val uid = UUID.randomUUID() - val a = ServiceImage(service, uid, "test", mutableMapOf(), mutableMapOf<String, Any>()) - - val b = mockk<Image>(relaxUnitFun = true) - every { b.uid } returns UUID.randomUUID() - - assertNotEquals(a, b) - } - - @Test - fun testInequalityWithIncorrectType() { - val service = mockk<ComputeService>() - val uid = UUID.randomUUID() - val a = ServiceImage(service, uid, "test", mutableMapOf(), mutableMapOf<String, Any>()) - - assertNotEquals(a, Unit) - } -} diff --git a/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/ServiceTaskTest.kt b/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/ServiceTaskTest.kt deleted file mode 100644 index e77665fe..00000000 --- a/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/ServiceTaskTest.kt +++ /dev/null @@ -1,442 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.compute.service - -import io.mockk.every -import io.mockk.mockk -import io.mockk.verify -import kotlinx.coroutines.yield -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertNotEquals -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertThrows -import org.opendc.compute.api.Task -import org.opendc.compute.api.TaskState -import org.opendc.compute.service.driver.Host -import org.opendc.simulator.kotlin.runSimulation -import java.util.UUID - -/** - * Test suite for the [ServiceTask] implementation. - */ -class ServiceTaskTest { - @Test - fun testEquality() { - val service = mockk<ComputeService>() - val uid = UUID.randomUUID() - val flavor = mockFlavor() - val image = mockImage() - - val a = - ServiceTask( - service, - uid, - "test", - flavor, - image, - mutableMapOf(), - mutableMapOf<String, Any>(), - ) - val b = - ServiceTask( - service, - uid, - "test", - flavor, - image, - mutableMapOf(), - mutableMapOf<String, Any>(), - ) - - assertEquals(a, b) - } - - @Test - fun testInequalityWithDifferentType() { - val service = mockk<ComputeService>() - val uid = UUID.randomUUID() - val flavor = mockFlavor() - val image = mockImage() - val a = - ServiceTask( - service, - uid, - "test", - flavor, - image, - mutableMapOf(), - mutableMapOf<String, Any>(), - ) - - val b = mockk<Task>(relaxUnitFun = true) - every { b.uid } returns UUID.randomUUID() - - assertNotEquals(a, b) - } - - @Test - fun testInequalityWithIncorrectType() { - val service = mockk<ComputeService>() - val uid = UUID.randomUUID() - val flavor = mockFlavor() - val image = mockImage() - val a = - ServiceTask( - service, - uid, - "test", - flavor, - image, - mutableMapOf(), - mutableMapOf<String, Any>(), - ) - - assertNotEquals(a, Unit) - } - - @Test - fun testStartTerminatedServer() = - runSimulation { - val service = mockk<ComputeService>() - val uid = UUID.randomUUID() - val flavor = mockFlavor() - val image = mockImage() - val server = - ServiceTask( - service, - uid, - "test", - flavor, - image, - mutableMapOf(), - mutableMapOf<String, Any>(), - ) - - every { service.schedule(any()) } answers { ComputeService.SchedulingRequest(it.invocation.args[0] as ServiceTask, 0) } - - server.start() - - verify(exactly = 1) { service.schedule(server) } - assertEquals(TaskState.PROVISIONING, server.state) - } - - @Test - fun testStartDeletedServer() = - runSimulation { - val service = mockk<ComputeService>() - val uid = UUID.randomUUID() - val flavor = mockFlavor() - val image = mockImage() - val server = - ServiceTask( - service, - uid, - "test", - flavor, - image, - mutableMapOf(), - mutableMapOf<String, Any>(), - ) - - server.setState(TaskState.DELETED) - - assertThrows<IllegalStateException> { server.start() } - } - - @Test - fun testStartProvisioningServer() = - runSimulation { - val service = mockk<ComputeService>() - val uid = UUID.randomUUID() - val flavor = mockFlavor() - val image = mockImage() - val server = - ServiceTask( - service, - uid, - "test", - flavor, - image, - mutableMapOf(), - mutableMapOf<String, Any>(), - ) - - server.setState(TaskState.PROVISIONING) - - server.start() - - assertEquals(TaskState.PROVISIONING, server.state) - } - - @Test - fun testStartRunningServer() = - runSimulation { - val service = mockk<ComputeService>() - val uid = UUID.randomUUID() - val flavor = mockFlavor() - val image = mockImage() - val server = - ServiceTask( - service, - uid, - "test", - flavor, - image, - mutableMapOf(), - mutableMapOf<String, Any>(), - ) - - server.setState(TaskState.RUNNING) - - server.start() - - assertEquals(TaskState.RUNNING, server.state) - } - - @Test - fun testStopProvisioningServer() = - runSimulation { - val service = mockk<ComputeService>() - val uid = UUID.randomUUID() - val flavor = mockFlavor() - val image = mockImage() - val server = - ServiceTask( - service, - uid, - "test", - flavor, - image, - mutableMapOf(), - mutableMapOf<String, Any>(), - ) - val request = ComputeService.SchedulingRequest(server, 0) - - every { service.schedule(any()) } returns request - - server.start() - server.stop() - - assertTrue(request.isCancelled) - assertEquals(TaskState.TERMINATED, server.state) - } - - @Test - fun testStopTerminatedServer() = - runSimulation { - val service = mockk<ComputeService>() - val uid = UUID.randomUUID() - val flavor = mockFlavor() - val image = mockImage() - val server = - ServiceTask( - service, - uid, - "test", - flavor, - image, - mutableMapOf(), - mutableMapOf<String, Any>(), - ) - - server.setState(TaskState.TERMINATED) - server.stop() - - assertEquals(TaskState.TERMINATED, server.state) - } - - @Test - fun testStopDeletedServer() = - runSimulation { - val service = mockk<ComputeService>() - val uid = UUID.randomUUID() - val flavor = mockFlavor() - val image = mockImage() - val server = - ServiceTask( - service, - uid, - "test", - flavor, - image, - mutableMapOf(), - mutableMapOf<String, Any>(), - ) - - server.setState(TaskState.DELETED) - server.stop() - - assertEquals(TaskState.DELETED, server.state) - } - - @Test - fun testStopRunningServer() = - runSimulation { - val service = mockk<ComputeService>() - val uid = UUID.randomUUID() - val flavor = mockFlavor() - val image = mockImage() - val server = - ServiceTask( - service, - uid, - "test", - flavor, - image, - mutableMapOf(), - mutableMapOf<String, Any>(), - ) - val host = mockk<Host>(relaxUnitFun = true) - - server.setState(TaskState.RUNNING) - server.host = host - server.stop() - yield() - - verify { host.stop(server) } - } - - @Test - fun testDeleteProvisioningServer() = - runSimulation { - val service = mockk<ComputeService>(relaxUnitFun = true) - val uid = UUID.randomUUID() - val flavor = mockFlavor() - val image = mockImage() - val server = - ServiceTask( - service, - uid, - "test", - flavor, - image, - mutableMapOf(), - mutableMapOf<String, Any>(), - ) - val request = ComputeService.SchedulingRequest(server, 0) - - every { service.schedule(any()) } returns request - - server.start() - server.delete() - - assertTrue(request.isCancelled) - assertEquals(TaskState.DELETED, server.state) - verify { service.delete(server) } - } - - @Test - fun testDeleteTerminatedServer() = - runSimulation { - val service = mockk<ComputeService>(relaxUnitFun = true) - val uid = UUID.randomUUID() - val flavor = mockFlavor() - val image = mockImage() - val server = - ServiceTask( - service, - uid, - "test", - flavor, - image, - mutableMapOf(), - mutableMapOf<String, Any>(), - ) - - server.setState(TaskState.TERMINATED) - server.delete() - - assertEquals(TaskState.DELETED, server.state) - - verify { service.delete(server) } - } - - @Test - fun testDeleteDeletedServer() = - runSimulation { - val service = mockk<ComputeService>(relaxUnitFun = true) - val uid = UUID.randomUUID() - val flavor = mockFlavor() - val image = mockImage() - val server = - ServiceTask( - service, - uid, - "test", - flavor, - image, - mutableMapOf(), - mutableMapOf<String, Any>(), - ) - - server.setState(TaskState.DELETED) - server.delete() - - assertEquals(TaskState.DELETED, server.state) - } - - @Test - fun testDeleteRunningServer() = - runSimulation { - val service = mockk<ComputeService>(relaxUnitFun = true) - val uid = UUID.randomUUID() - val flavor = mockFlavor() - val image = mockImage() - val server = - ServiceTask( - service, - uid, - "test", - flavor, - image, - mutableMapOf(), - mutableMapOf<String, Any>(), - ) - val host = mockk<Host>(relaxUnitFun = true) - - server.setState(TaskState.RUNNING) - server.host = host - server.delete() - yield() - - verify { host.delete(server) } - verify { service.delete(server) } - } - - private fun mockFlavor(): ServiceFlavor { - val flavor = mockk<ServiceFlavor>() - every { flavor.name } returns "c5.large" - every { flavor.uid } returns UUID.randomUUID() - every { flavor.coreCount } returns 2 - every { flavor.memorySize } returns 4096 - return flavor - } - - private fun mockImage(): ServiceImage { - val image = mockk<ServiceImage>() - every { image.name } returns "ubuntu-20.04" - every { image.uid } returns UUID.randomUUID() - return image - } -} diff --git a/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/scheduler/FilterSchedulerTest.kt b/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/scheduler/FilterSchedulerTest.kt deleted file mode 100644 index add10f8f..00000000 --- a/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/scheduler/FilterSchedulerTest.kt +++ /dev/null @@ -1,536 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.compute.service.scheduler - -import io.mockk.every -import io.mockk.mockk -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertNull -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertAll -import org.junit.jupiter.api.assertThrows -import org.opendc.compute.api.Task -import org.opendc.compute.service.HostView -import org.opendc.compute.service.driver.HostModel -import org.opendc.compute.service.driver.HostState -import org.opendc.compute.service.scheduler.filters.ComputeFilter -import org.opendc.compute.service.scheduler.filters.DifferentHostFilter -import org.opendc.compute.service.scheduler.filters.InstanceCountFilter -import org.opendc.compute.service.scheduler.filters.RamFilter -import org.opendc.compute.service.scheduler.filters.SameHostFilter -import org.opendc.compute.service.scheduler.filters.VCpuCapacityFilter -import org.opendc.compute.service.scheduler.filters.VCpuFilter -import org.opendc.compute.service.scheduler.weights.CoreRamWeigher -import org.opendc.compute.service.scheduler.weights.InstanceCountWeigher -import org.opendc.compute.service.scheduler.weights.RamWeigher -import org.opendc.compute.service.scheduler.weights.VCpuWeigher -import java.util.Random -import java.util.UUID - -/** - * Test suite for the [FilterScheduler]. - */ -internal class FilterSchedulerTest { - @Test - fun testInvalidSubsetSize() { - assertThrows<IllegalArgumentException> { - FilterScheduler( - filters = emptyList(), - weighers = emptyList(), - subsetSize = 0, - ) - } - - assertThrows<IllegalArgumentException> { - FilterScheduler( - filters = emptyList(), - weighers = emptyList(), - subsetSize = -2, - ) - } - } - - @Test - fun testNoHosts() { - val scheduler = - FilterScheduler( - filters = emptyList(), - weighers = emptyList(), - ) - - val task = mockk<Task>() - every { task.flavor.coreCount } returns 2 - every { task.flavor.memorySize } returns 1024 - - assertNull(scheduler.select(task)) - } - - @Test - fun testNoFiltersAndSchedulers() { - val scheduler = - FilterScheduler( - filters = emptyList(), - weighers = emptyList(), - ) - - val hostA = mockk<HostView>() - every { hostA.host.state } returns HostState.DOWN - - val hostB = mockk<HostView>() - every { hostB.host.state } returns HostState.UP - - scheduler.addHost(hostA) - scheduler.addHost(hostB) - - val task = mockk<Task>() - every { task.flavor.coreCount } returns 2 - every { task.flavor.memorySize } returns 1024 - - // Make sure we get the first host both times - assertAll( - { assertEquals(hostA, scheduler.select(task)) }, - { assertEquals(hostA, scheduler.select(task)) }, - ) - } - - @Test - fun testNoFiltersAndSchedulersRandom() { - val scheduler = - FilterScheduler( - filters = emptyList(), - weighers = emptyList(), - subsetSize = Int.MAX_VALUE, - random = Random(1), - ) - - val hostA = mockk<HostView>() - every { hostA.host.state } returns HostState.DOWN - - val hostB = mockk<HostView>() - every { hostB.host.state } returns HostState.UP - - scheduler.addHost(hostA) - scheduler.addHost(hostB) - - val task = mockk<Task>() - every { task.flavor.coreCount } returns 2 - every { task.flavor.memorySize } returns 1024 - - // Make sure we get the first host both times - assertAll( - { assertEquals(hostB, scheduler.select(task)) }, - { assertEquals(hostA, scheduler.select(task)) }, - ) - } - - @Test - fun testHostIsDown() { - val scheduler = - FilterScheduler( - filters = listOf(ComputeFilter()), - weighers = emptyList(), - ) - - val host = mockk<HostView>() - every { host.host.state } returns HostState.DOWN - - scheduler.addHost(host) - - val task = mockk<Task>() - every { task.flavor.coreCount } returns 2 - every { task.flavor.memorySize } returns 1024 - - assertNull(scheduler.select(task)) - } - - @Test - fun testHostIsUp() { - val scheduler = - FilterScheduler( - filters = listOf(ComputeFilter()), - weighers = emptyList(), - ) - - val host = mockk<HostView>() - every { host.host.state } returns HostState.UP - - scheduler.addHost(host) - - val task = mockk<Task>() - every { task.flavor.coreCount } returns 2 - every { task.flavor.memorySize } returns 1024 - - assertEquals(host, scheduler.select(task)) - } - - @Test - fun testRamFilter() { - val scheduler = - FilterScheduler( - filters = listOf(RamFilter(1.0)), - weighers = emptyList(), - ) - - val hostA = mockk<HostView>() - every { hostA.host.state } returns HostState.UP - every { hostA.host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { hostA.availableMemory } returns 512 - - val hostB = mockk<HostView>() - every { hostB.host.state } returns HostState.UP - every { hostB.host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { hostB.availableMemory } returns 2048 - - scheduler.addHost(hostA) - scheduler.addHost(hostB) - - val task = mockk<Task>() - every { task.flavor.coreCount } returns 2 - every { task.flavor.memorySize } returns 1024 - - assertEquals(hostB, scheduler.select(task)) - } - - @Test - fun testRamFilterOvercommit() { - val scheduler = - FilterScheduler( - filters = listOf(RamFilter(1.5)), - weighers = emptyList(), - ) - - val host = mockk<HostView>() - every { host.host.state } returns HostState.UP - every { host.host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { host.availableMemory } returns 2048 - - scheduler.addHost(host) - - val task = mockk<Task>() - every { task.flavor.coreCount } returns 2 - every { task.flavor.memorySize } returns 2300 - - assertNull(scheduler.select(task)) - } - - @Test - fun testVCpuFilter() { - val scheduler = - FilterScheduler( - filters = listOf(VCpuFilter(1.0)), - weighers = emptyList(), - ) - - val hostA = mockk<HostView>() - every { hostA.host.state } returns HostState.UP - every { hostA.host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { hostA.provisionedCores } returns 3 - - val hostB = mockk<HostView>() - every { hostB.host.state } returns HostState.UP - every { hostB.host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { hostB.provisionedCores } returns 0 - - scheduler.addHost(hostA) - scheduler.addHost(hostB) - - val task = mockk<Task>() - every { task.flavor.coreCount } returns 2 - every { task.flavor.memorySize } returns 1024 - - assertEquals(hostB, scheduler.select(task)) - } - - @Test - fun testVCpuFilterOvercommit() { - val scheduler = - FilterScheduler( - filters = listOf(VCpuFilter(16.0)), - weighers = emptyList(), - ) - - val host = mockk<HostView>() - every { host.host.state } returns HostState.UP - every { host.host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { host.provisionedCores } returns 0 - - scheduler.addHost(host) - - val task = mockk<Task>() - every { task.flavor.coreCount } returns 8 - every { task.flavor.memorySize } returns 1024 - - assertNull(scheduler.select(task)) - } - -// TODO: fix when schedulers are reworked -// @Test - fun testVCpuCapacityFilter() { - val scheduler = - FilterScheduler( - filters = listOf(VCpuCapacityFilter()), - weighers = emptyList(), - ) - - val hostA = mockk<HostView>() - every { hostA.host.state } returns HostState.UP - every { hostA.host.model } returns HostModel(8 * 2600.0, 8, 2048) - every { hostA.availableMemory } returns 512 - scheduler.addHost(hostA) - - val hostB = mockk<HostView>() - every { hostB.host.state } returns HostState.UP - every { hostB.host.model } returns HostModel(4 * 3200.0, 4, 2048) - every { hostB.availableMemory } returns 512 - - scheduler.addHost(hostB) - - val task = mockk<Task>() - every { task.flavor.coreCount } returns 2 - every { task.flavor.memorySize } returns 1024 - every { task.flavor.meta } returns mapOf("cpu-capacity" to 2 * 3200.0) - - assertEquals(hostB, scheduler.select(task)) - } - - @Test - fun testInstanceCountFilter() { - val scheduler = - FilterScheduler( - filters = listOf(InstanceCountFilter(limit = 2)), - weighers = emptyList(), - ) - - val hostA = mockk<HostView>() - every { hostA.host.state } returns HostState.UP - every { hostA.host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { hostA.instanceCount } returns 2 - - val hostB = mockk<HostView>() - every { hostB.host.state } returns HostState.UP - every { hostB.host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { hostB.instanceCount } returns 0 - - scheduler.addHost(hostA) - scheduler.addHost(hostB) - - val task = mockk<Task>() - every { task.flavor.coreCount } returns 2 - every { task.flavor.memorySize } returns 1024 - - assertEquals(hostB, scheduler.select(task)) - } - - @Test - fun testAffinityFilter() { - val scheduler = - FilterScheduler( - filters = listOf(SameHostFilter()), - weighers = emptyList(), - ) - - val taskA = mockk<Task>() - every { taskA.uid } returns UUID.randomUUID() - every { taskA.flavor.coreCount } returns 2 - every { taskA.flavor.memorySize } returns 1024 - - val hostA = mockk<HostView>() - every { hostA.host.state } returns HostState.UP - every { hostA.host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { hostA.host.instances } returns emptySet() - every { hostA.provisionedCores } returns 3 - - val hostB = mockk<HostView>() - every { hostB.host.state } returns HostState.UP - every { hostB.host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { hostB.host.instances } returns setOf(taskA) - every { hostB.provisionedCores } returns 0 - - scheduler.addHost(hostA) - scheduler.addHost(hostB) - - val taskB = mockk<Task>() - every { taskB.flavor.coreCount } returns 2 - every { taskB.flavor.memorySize } returns 1024 - every { taskB.meta } returns emptyMap() - - assertEquals(hostA, scheduler.select(taskB)) - - every { taskB.meta } returns mapOf("scheduler_hint:same_host" to setOf(taskA.uid)) - - assertEquals(hostB, scheduler.select(taskB)) - } - - @Test - fun testAntiAffinityFilter() { - val scheduler = - FilterScheduler( - filters = listOf(DifferentHostFilter()), - weighers = emptyList(), - ) - - val taskA = mockk<Task>() - every { taskA.uid } returns UUID.randomUUID() - every { taskA.flavor.coreCount } returns 2 - every { taskA.flavor.memorySize } returns 1024 - - val hostA = mockk<HostView>() - every { hostA.host.state } returns HostState.UP - every { hostA.host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { hostA.host.instances } returns setOf(taskA) - every { hostA.provisionedCores } returns 3 - - val hostB = mockk<HostView>() - every { hostB.host.state } returns HostState.UP - every { hostB.host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { hostB.host.instances } returns emptySet() - every { hostB.provisionedCores } returns 0 - - scheduler.addHost(hostA) - scheduler.addHost(hostB) - - val taskB = mockk<Task>() - every { taskB.flavor.coreCount } returns 2 - every { taskB.flavor.memorySize } returns 1024 - every { taskB.meta } returns emptyMap() - - assertEquals(hostA, scheduler.select(taskB)) - - every { taskB.meta } returns mapOf("scheduler_hint:different_host" to setOf(taskA.uid)) - - assertEquals(hostB, scheduler.select(taskB)) - } - - @Test - fun testRamWeigher() { - val scheduler = - FilterScheduler( - filters = emptyList(), - weighers = listOf(RamWeigher(1.5)), - ) - - val hostA = mockk<HostView>() - every { hostA.host.state } returns HostState.UP - every { hostA.host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { hostA.availableMemory } returns 1024 - - val hostB = mockk<HostView>() - every { hostB.host.state } returns HostState.UP - every { hostB.host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { hostB.availableMemory } returns 512 - - scheduler.addHost(hostA) - scheduler.addHost(hostB) - - val task = mockk<Task>() - every { task.flavor.coreCount } returns 2 - every { task.flavor.memorySize } returns 1024 - - assertEquals(hostA, scheduler.select(task)) - } - - // TODO: fix test when updating schedulers -// @Test - fun testCoreRamWeigher() { - val scheduler = - FilterScheduler( - filters = emptyList(), - weighers = listOf(CoreRamWeigher(1.5)), - ) - - val hostA = mockk<HostView>() - every { hostA.host.state } returns HostState.UP - every { hostA.host.model } returns HostModel(12 * 2600.0, 12, 2048) - every { hostA.availableMemory } returns 1024 - - val hostB = mockk<HostView>() - every { hostB.host.state } returns HostState.UP - every { hostB.host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { hostB.availableMemory } returns 512 - - scheduler.addHost(hostA) - scheduler.addHost(hostB) - - val task = mockk<Task>() - every { task.flavor.coreCount } returns 2 - every { task.flavor.memorySize } returns 1024 - - assertEquals(hostB, scheduler.select(task)) - } - - @Test - fun testVCpuWeigher() { - val scheduler = - FilterScheduler( - filters = emptyList(), - weighers = listOf(VCpuWeigher(16.0)), - ) - - val hostA = mockk<HostView>() - every { hostA.host.state } returns HostState.UP - every { hostA.host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { hostA.provisionedCores } returns 2 - - val hostB = mockk<HostView>() - every { hostB.host.state } returns HostState.UP - every { hostB.host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { hostB.provisionedCores } returns 0 - - scheduler.addHost(hostA) - scheduler.addHost(hostB) - - val task = mockk<Task>() - every { task.flavor.coreCount } returns 2 - every { task.flavor.memorySize } returns 1024 - - assertEquals(hostB, scheduler.select(task)) - } - - @Test - fun testInstanceCountWeigher() { - val scheduler = - FilterScheduler( - filters = emptyList(), - weighers = listOf(InstanceCountWeigher(multiplier = -1.0)), - ) - - val hostA = mockk<HostView>() - every { hostA.host.state } returns HostState.UP - every { hostA.host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { hostA.instanceCount } returns 2 - - val hostB = mockk<HostView>() - every { hostB.host.state } returns HostState.UP - every { hostB.host.model } returns HostModel(4 * 2600.0, 4, 2048) - every { hostB.instanceCount } returns 0 - - scheduler.addHost(hostA) - scheduler.addHost(hostB) - - val task = mockk<Task>() - every { task.flavor.coreCount } returns 2 - every { task.flavor.memorySize } returns 1024 - - assertEquals(hostB, scheduler.select(task)) - } -} diff --git a/opendc-compute/opendc-compute-service/src/test/resources/log4j2.xml b/opendc-compute/opendc-compute-service/src/test/resources/log4j2.xml deleted file mode 100644 index 0dfb75f2..00000000 --- a/opendc-compute/opendc-compute-service/src/test/resources/log4j2.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (c) 2021 AtLarge Research - ~ - ~ Permission is hereby granted, free of charge, to any person obtaining a copy - ~ of this software and associated documentation files (the "Software"), to deal - ~ in the Software without restriction, including without limitation the rights - ~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - ~ copies of the Software, and to permit persons to whom the Software is - ~ furnished to do so, subject to the following conditions: - ~ - ~ The above copyright notice and this permission notice shall be included in all - ~ copies or substantial portions of the Software. - ~ - ~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - ~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - ~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - ~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - ~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - ~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - ~ SOFTWARE. - --> - -<Configuration status="WARN" packages="org.apache.logging.log4j.core"> - <Appenders> - <Console name="Console" target="SYSTEM_OUT"> - <PatternLayout pattern="%d{HH:mm:ss.SSS} [%highlight{%-5level}] %logger{36} - %msg%n" disableAnsi="false"/> - </Console> - </Appenders> - <Loggers> - <Logger name="org.opendc" level="trace" additivity="false"> - <AppenderRef ref="Console"/> - </Logger> - <Root level="info"> - <AppenderRef ref="Console"/> - </Root> - </Loggers> -</Configuration> |
