summaryrefslogtreecommitdiff
path: root/opendc-compute/opendc-compute-service/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'opendc-compute/opendc-compute-service/src/test')
-rw-r--r--opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/ComputeServiceTest.kt40
-rw-r--r--opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/InternalServerTest.kt87
-rw-r--r--opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/scheduler/FilterSchedulerTest.kt407
3 files changed, 479 insertions, 55 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
index a6258845..564f9493 100644
--- 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
@@ -37,9 +37,10 @@ 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.ComputeCapabilitiesFilter
import org.opendc.compute.service.scheduler.filters.ComputeFilter
-import org.opendc.compute.service.scheduler.weights.MemoryWeigher
+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.core.SimulationCoroutineScope
import org.opendc.simulator.core.runBlockingSimulation
import java.util.*
@@ -57,11 +58,10 @@ internal class ComputeServiceTest {
scope = SimulationCoroutineScope()
val clock = scope.clock
val computeScheduler = FilterScheduler(
- filters = listOf(ComputeFilter(), ComputeCapabilitiesFilter()),
- weighers = listOf(MemoryWeigher() to -1.0)
+ filters = listOf(ComputeFilter(), VCpuFilter(allocationRatio = 1.0), RamFilter(allocationRatio = 1.0)),
+ weighers = listOf(RamWeigher())
)
- val meter = MeterProvider.noop().get("opendc-compute")
- service = ComputeService(scope.coroutineContext, clock, meter, computeScheduler)
+ service = ComputeService(scope.coroutineContext, clock, MeterProvider.noop(), computeScheduler)
}
@Test
@@ -167,9 +167,9 @@ internal class ComputeServiceTest {
val server = client.newServer("test", image, flavor, start = false)
server.start()
- delay(5 * 60 * 1000)
+ delay(5L * 60 * 1000)
server.refresh()
- assertEquals(ServerState.ERROR, server.state)
+ assertEquals(ServerState.TERMINATED, server.state)
}
@Test
@@ -180,9 +180,9 @@ internal class ComputeServiceTest {
val server = client.newServer("test", image, flavor, start = false)
server.start()
- delay(5 * 60 * 1000)
+ delay(5L * 60 * 1000)
server.refresh()
- assertEquals(ServerState.ERROR, server.state)
+ assertEquals(ServerState.TERMINATED, server.state)
}
@Test
@@ -193,9 +193,9 @@ internal class ComputeServiceTest {
val server = client.newServer("test", image, flavor, start = false)
server.start()
- delay(5 * 60 * 1000)
+ delay(5L * 60 * 1000)
server.refresh()
- assertEquals(ServerState.ERROR, server.state)
+ assertEquals(ServerState.TERMINATED, server.state)
}
@Test
@@ -207,7 +207,7 @@ internal class ComputeServiceTest {
server.start()
server.stop()
- delay(5 * 60 * 1000)
+ delay(5L * 60 * 1000)
server.refresh()
assertEquals(ServerState.TERMINATED, server.state)
}
@@ -228,7 +228,7 @@ internal class ComputeServiceTest {
val server = client.newServer("test", image, flavor, start = false)
server.start()
- delay(10 * 60 * 1000)
+ delay(10L * 60 * 1000)
server.refresh()
assertEquals(ServerState.PROVISIONING, server.state)
@@ -254,12 +254,12 @@ internal class ComputeServiceTest {
val server = client.newServer("test", image, flavor, start = false)
server.start()
- delay(5 * 60 * 1000)
+ delay(5L * 60 * 1000)
every { host.state } returns HostState.UP
listeners.forEach { it.onStateChanged(host, HostState.UP) }
- delay(5 * 60 * 1000)
+ delay(5L * 60 * 1000)
server.refresh()
assertEquals(ServerState.PROVISIONING, server.state)
@@ -284,13 +284,13 @@ internal class ComputeServiceTest {
val image = client.newImage("test")
val server = client.newServer("test", image, flavor, start = false)
- delay(5 * 60 * 1000)
+ delay(5L * 60 * 1000)
every { host.state } returns HostState.DOWN
listeners.forEach { it.onStateChanged(host, HostState.DOWN) }
server.start()
- delay(5 * 60 * 1000)
+ delay(5L * 60 * 1000)
server.refresh()
assertEquals(ServerState.PROVISIONING, server.state)
@@ -344,7 +344,7 @@ internal class ComputeServiceTest {
// Start server
server.start()
- delay(5 * 60 * 1000)
+ delay(5L * 60 * 1000)
coVerify { host.spawn(capture(slot), true) }
listeners.forEach { it.onStateChanged(host, slot.captured, ServerState.RUNNING) }
@@ -383,7 +383,7 @@ internal class ComputeServiceTest {
val server = client.newServer("test", image, flavor, start = false)
server.start()
- delay(5 * 60 * 1000)
+ delay(5L * 60 * 1000)
server.refresh()
assertEquals(ServerState.PROVISIONING, server.state)
diff --git a/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/InternalServerTest.kt b/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/InternalServerTest.kt
index 20ea8d20..dfd3bc67 100644
--- a/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/InternalServerTest.kt
+++ b/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/InternalServerTest.kt
@@ -47,8 +47,9 @@ class InternalServerTest {
fun testEquality() {
val service = mockk<ComputeServiceImpl>()
val uid = UUID.randomUUID()
- val flavor = mockk<InternalFlavor>()
- val image = mockk<InternalImage>()
+ val flavor = mockFlavor()
+ val image = mockImage()
+
val a = InternalServer(service, uid, "test", flavor, image, mutableMapOf(), mutableMapOf())
val b = InternalServer(service, uid, "test", flavor, image, mutableMapOf(), mutableMapOf())
@@ -59,8 +60,8 @@ class InternalServerTest {
fun testEqualityWithDifferentType() {
val service = mockk<ComputeServiceImpl>()
val uid = UUID.randomUUID()
- val flavor = mockk<InternalFlavor>()
- val image = mockk<InternalImage>()
+ val flavor = mockFlavor()
+ val image = mockImage()
val a = InternalServer(service, uid, "test", flavor, image, mutableMapOf(), mutableMapOf())
val b = mockk<Server>(relaxUnitFun = true)
@@ -73,8 +74,8 @@ class InternalServerTest {
fun testInequalityWithDifferentType() {
val service = mockk<ComputeServiceImpl>()
val uid = UUID.randomUUID()
- val flavor = mockk<InternalFlavor>()
- val image = mockk<InternalImage>()
+ val flavor = mockFlavor()
+ val image = mockImage()
val a = InternalServer(service, uid, "test", flavor, image, mutableMapOf(), mutableMapOf())
val b = mockk<Server>(relaxUnitFun = true)
@@ -87,8 +88,8 @@ class InternalServerTest {
fun testInequalityWithIncorrectType() {
val service = mockk<ComputeServiceImpl>()
val uid = UUID.randomUUID()
- val flavor = mockk<InternalFlavor>()
- val image = mockk<InternalImage>()
+ val flavor = mockFlavor()
+ val image = mockImage()
val a = InternalServer(service, uid, "test", flavor, image, mutableMapOf(), mutableMapOf())
assertNotEquals(a, Unit)
@@ -98,11 +99,11 @@ class InternalServerTest {
fun testStartTerminatedServer() = runBlockingSimulation {
val service = mockk<ComputeServiceImpl>()
val uid = UUID.randomUUID()
- val flavor = mockk<InternalFlavor>()
- val image = mockk<InternalImage>()
+ val flavor = mockFlavor()
+ val image = mockImage()
val server = InternalServer(service, uid, "test", flavor, image, mutableMapOf(), mutableMapOf())
- every { service.schedule(any()) } answers { ComputeServiceImpl.SchedulingRequest(it.invocation.args[0] as InternalServer) }
+ every { service.schedule(any()) } answers { ComputeServiceImpl.SchedulingRequest(it.invocation.args[0] as InternalServer, 0) }
server.start()
@@ -114,8 +115,8 @@ class InternalServerTest {
fun testStartDeletedServer() = runBlockingSimulation {
val service = mockk<ComputeServiceImpl>()
val uid = UUID.randomUUID()
- val flavor = mockk<InternalFlavor>()
- val image = mockk<InternalImage>()
+ val flavor = mockFlavor()
+ val image = mockImage()
val server = InternalServer(service, uid, "test", flavor, image, mutableMapOf(), mutableMapOf())
server.state = ServerState.DELETED
@@ -127,8 +128,8 @@ class InternalServerTest {
fun testStartProvisioningServer() = runBlockingSimulation {
val service = mockk<ComputeServiceImpl>()
val uid = UUID.randomUUID()
- val flavor = mockk<InternalFlavor>()
- val image = mockk<InternalImage>()
+ val flavor = mockFlavor()
+ val image = mockImage()
val server = InternalServer(service, uid, "test", flavor, image, mutableMapOf(), mutableMapOf())
server.state = ServerState.PROVISIONING
@@ -142,8 +143,8 @@ class InternalServerTest {
fun testStartRunningServer() = runBlockingSimulation {
val service = mockk<ComputeServiceImpl>()
val uid = UUID.randomUUID()
- val flavor = mockk<InternalFlavor>()
- val image = mockk<InternalImage>()
+ val flavor = mockFlavor()
+ val image = mockImage()
val server = InternalServer(service, uid, "test", flavor, image, mutableMapOf(), mutableMapOf())
server.state = ServerState.RUNNING
@@ -157,10 +158,10 @@ class InternalServerTest {
fun testStopProvisioningServer() = runBlockingSimulation {
val service = mockk<ComputeServiceImpl>()
val uid = UUID.randomUUID()
- val flavor = mockk<InternalFlavor>()
- val image = mockk<InternalImage>()
+ val flavor = mockFlavor()
+ val image = mockImage()
val server = InternalServer(service, uid, "test", flavor, image, mutableMapOf(), mutableMapOf())
- val request = ComputeServiceImpl.SchedulingRequest(server)
+ val request = ComputeServiceImpl.SchedulingRequest(server, 0)
every { service.schedule(any()) } returns request
@@ -175,8 +176,8 @@ class InternalServerTest {
fun testStopTerminatedServer() = runBlockingSimulation {
val service = mockk<ComputeServiceImpl>()
val uid = UUID.randomUUID()
- val flavor = mockk<InternalFlavor>()
- val image = mockk<InternalImage>()
+ val flavor = mockFlavor()
+ val image = mockImage()
val server = InternalServer(service, uid, "test", flavor, image, mutableMapOf(), mutableMapOf())
server.state = ServerState.TERMINATED
@@ -189,8 +190,8 @@ class InternalServerTest {
fun testStopDeletedServer() = runBlockingSimulation {
val service = mockk<ComputeServiceImpl>()
val uid = UUID.randomUUID()
- val flavor = mockk<InternalFlavor>()
- val image = mockk<InternalImage>()
+ val flavor = mockFlavor()
+ val image = mockImage()
val server = InternalServer(service, uid, "test", flavor, image, mutableMapOf(), mutableMapOf())
server.state = ServerState.DELETED
@@ -203,8 +204,8 @@ class InternalServerTest {
fun testStopRunningServer() = runBlockingSimulation {
val service = mockk<ComputeServiceImpl>()
val uid = UUID.randomUUID()
- val flavor = mockk<InternalFlavor>()
- val image = mockk<InternalImage>()
+ val flavor = mockFlavor()
+ val image = mockImage()
val server = InternalServer(service, uid, "test", flavor, image, mutableMapOf(), mutableMapOf())
val host = mockk<Host>(relaxUnitFun = true)
@@ -220,10 +221,10 @@ class InternalServerTest {
fun testDeleteProvisioningServer() = runBlockingSimulation {
val service = mockk<ComputeServiceImpl>(relaxUnitFun = true)
val uid = UUID.randomUUID()
- val flavor = mockk<InternalFlavor>()
- val image = mockk<InternalImage>()
+ val flavor = mockFlavor()
+ val image = mockImage()
val server = InternalServer(service, uid, "test", flavor, image, mutableMapOf(), mutableMapOf())
- val request = ComputeServiceImpl.SchedulingRequest(server)
+ val request = ComputeServiceImpl.SchedulingRequest(server, 0)
every { service.schedule(any()) } returns request
@@ -239,8 +240,8 @@ class InternalServerTest {
fun testDeleteTerminatedServer() = runBlockingSimulation {
val service = mockk<ComputeServiceImpl>(relaxUnitFun = true)
val uid = UUID.randomUUID()
- val flavor = mockk<InternalFlavor>()
- val image = mockk<InternalImage>()
+ val flavor = mockFlavor()
+ val image = mockImage()
val server = InternalServer(service, uid, "test", flavor, image, mutableMapOf(), mutableMapOf())
server.state = ServerState.TERMINATED
@@ -255,8 +256,8 @@ class InternalServerTest {
fun testDeleteDeletedServer() = runBlockingSimulation {
val service = mockk<ComputeServiceImpl>(relaxUnitFun = true)
val uid = UUID.randomUUID()
- val flavor = mockk<InternalFlavor>()
- val image = mockk<InternalImage>()
+ val flavor = mockFlavor()
+ val image = mockImage()
val server = InternalServer(service, uid, "test", flavor, image, mutableMapOf(), mutableMapOf())
server.state = ServerState.DELETED
@@ -269,8 +270,8 @@ class InternalServerTest {
fun testDeleteRunningServer() = runBlockingSimulation {
val service = mockk<ComputeServiceImpl>(relaxUnitFun = true)
val uid = UUID.randomUUID()
- val flavor = mockk<InternalFlavor>()
- val image = mockk<InternalImage>()
+ val flavor = mockFlavor()
+ val image = mockImage()
val server = InternalServer(service, uid, "test", flavor, image, mutableMapOf(), mutableMapOf())
val host = mockk<Host>(relaxUnitFun = true)
@@ -282,4 +283,20 @@ class InternalServerTest {
coVerify { host.delete(server) }
verify { service.delete(server) }
}
+
+ private fun mockFlavor(): InternalFlavor {
+ val flavor = mockk<InternalFlavor>()
+ every { flavor.name } returns "c5.large"
+ every { flavor.uid } returns UUID.randomUUID()
+ every { flavor.cpuCount } returns 2
+ every { flavor.memorySize } returns 4096
+ return flavor
+ }
+
+ private fun mockImage(): InternalImage {
+ val image = mockk<InternalImage>()
+ 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
new file mode 100644
index 00000000..cafd4498
--- /dev/null
+++ b/opendc-compute/opendc-compute-service/src/test/kotlin/org/opendc/compute/service/scheduler/FilterSchedulerTest.kt
@@ -0,0 +1,407 @@
+/*
+ * 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.Server
+import org.opendc.compute.service.driver.HostModel
+import org.opendc.compute.service.driver.HostState
+import org.opendc.compute.service.internal.HostView
+import org.opendc.compute.service.scheduler.filters.ComputeFilter
+import org.opendc.compute.service.scheduler.filters.InstanceCountFilter
+import org.opendc.compute.service.scheduler.filters.RamFilter
+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.*
+
+/**
+ * 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 server = mockk<Server>()
+ every { server.flavor.cpuCount } returns 2
+ every { server.flavor.memorySize } returns 1024
+
+ assertNull(scheduler.select(server))
+ }
+
+ @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 server = mockk<Server>()
+ every { server.flavor.cpuCount } returns 2
+ every { server.flavor.memorySize } returns 1024
+
+ // Make sure we get the first host both times
+ assertAll(
+ { assertEquals(hostA, scheduler.select(server)) },
+ { assertEquals(hostA, scheduler.select(server)) }
+ )
+ }
+
+ @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 server = mockk<Server>()
+ every { server.flavor.cpuCount } returns 2
+ every { server.flavor.memorySize } returns 1024
+
+ // Make sure we get the first host both times
+ assertAll(
+ { assertEquals(hostB, scheduler.select(server)) },
+ { assertEquals(hostA, scheduler.select(server)) }
+ )
+ }
+
+ @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 server = mockk<Server>()
+ every { server.flavor.cpuCount } returns 2
+ every { server.flavor.memorySize } returns 1024
+
+ assertNull(scheduler.select(server))
+ }
+
+ @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 server = mockk<Server>()
+ every { server.flavor.cpuCount } returns 2
+ every { server.flavor.memorySize } returns 1024
+
+ assertEquals(host, scheduler.select(server))
+ }
+
+ @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, 2048)
+ every { hostA.availableMemory } returns 512
+
+ val hostB = mockk<HostView>()
+ every { hostB.host.state } returns HostState.UP
+ every { hostB.host.model } returns HostModel(4, 2048)
+ every { hostB.availableMemory } returns 2048
+
+ scheduler.addHost(hostA)
+ scheduler.addHost(hostB)
+
+ val server = mockk<Server>()
+ every { server.flavor.cpuCount } returns 2
+ every { server.flavor.memorySize } returns 1024
+
+ assertEquals(hostB, scheduler.select(server))
+ }
+
+ @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, 2048)
+ every { host.availableMemory } returns 2048
+
+ scheduler.addHost(host)
+
+ val server = mockk<Server>()
+ every { server.flavor.cpuCount } returns 2
+ every { server.flavor.memorySize } returns 2300
+
+ assertNull(scheduler.select(server))
+ }
+
+ @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, 2048)
+ every { hostA.provisionedCores } returns 3
+
+ val hostB = mockk<HostView>()
+ every { hostB.host.state } returns HostState.UP
+ every { hostB.host.model } returns HostModel(4, 2048)
+ every { hostB.provisionedCores } returns 0
+
+ scheduler.addHost(hostA)
+ scheduler.addHost(hostB)
+
+ val server = mockk<Server>()
+ every { server.flavor.cpuCount } returns 2
+ every { server.flavor.memorySize } returns 1024
+
+ assertEquals(hostB, scheduler.select(server))
+ }
+
+ @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, 2048)
+ every { host.provisionedCores } returns 0
+
+ scheduler.addHost(host)
+
+ val server = mockk<Server>()
+ every { server.flavor.cpuCount } returns 8
+ every { server.flavor.memorySize } returns 1024
+
+ assertNull(scheduler.select(server))
+ }
+
+ @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, 2048)
+ every { hostA.instanceCount } returns 2
+
+ val hostB = mockk<HostView>()
+ every { hostB.host.state } returns HostState.UP
+ every { hostB.host.model } returns HostModel(4, 2048)
+ every { hostB.instanceCount } returns 0
+
+ scheduler.addHost(hostA)
+ scheduler.addHost(hostB)
+
+ val server = mockk<Server>()
+ every { server.flavor.cpuCount } returns 2
+ every { server.flavor.memorySize } returns 1024
+
+ assertEquals(hostB, scheduler.select(server))
+ }
+
+ @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, 2048)
+ every { hostA.availableMemory } returns 1024
+
+ val hostB = mockk<HostView>()
+ every { hostB.host.state } returns HostState.UP
+ every { hostB.host.model } returns HostModel(4, 2048)
+ every { hostB.availableMemory } returns 512
+
+ scheduler.addHost(hostA)
+ scheduler.addHost(hostB)
+
+ val server = mockk<Server>()
+ every { server.flavor.cpuCount } returns 2
+ every { server.flavor.memorySize } returns 1024
+
+ assertEquals(hostA, scheduler.select(server))
+ }
+
+ @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, 2048)
+ every { hostA.availableMemory } returns 1024
+
+ val hostB = mockk<HostView>()
+ every { hostB.host.state } returns HostState.UP
+ every { hostB.host.model } returns HostModel(4, 2048)
+ every { hostB.availableMemory } returns 512
+
+ scheduler.addHost(hostA)
+ scheduler.addHost(hostB)
+
+ val server = mockk<Server>()
+ every { server.flavor.cpuCount } returns 2
+ every { server.flavor.memorySize } returns 1024
+
+ assertEquals(hostB, scheduler.select(server))
+ }
+
+ @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, 2048)
+ every { hostA.provisionedCores } returns 2
+
+ val hostB = mockk<HostView>()
+ every { hostB.host.state } returns HostState.UP
+ every { hostB.host.model } returns HostModel(4, 2048)
+ every { hostB.provisionedCores } returns 0
+
+ scheduler.addHost(hostA)
+ scheduler.addHost(hostB)
+
+ val server = mockk<Server>()
+ every { server.flavor.cpuCount } returns 2
+ every { server.flavor.memorySize } returns 1024
+
+ assertEquals(hostB, scheduler.select(server))
+ }
+
+ @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, 2048)
+ every { hostA.instanceCount } returns 2
+
+ val hostB = mockk<HostView>()
+ every { hostB.host.state } returns HostState.UP
+ every { hostB.host.model } returns HostModel(4, 2048)
+ every { hostB.instanceCount } returns 0
+
+ scheduler.addHost(hostA)
+ scheduler.addHost(hostB)
+
+ val server = mockk<Server>()
+ every { server.flavor.cpuCount } returns 2
+ every { server.flavor.memorySize } returns 1024
+
+ assertEquals(hostB, scheduler.select(server))
+ }
+}