From 52bc0f91edfbdea377bde4a846b7f44f50604f39 Mon Sep 17 00:00:00 2001
From: "stu126940@mail.uni-kiel.de" <stu126940@mail.uni-kiel.de>
Date: Wed, 23 Jun 2021 17:54:44 +0200
Subject: [PATCH] Add more test for TheodoliteController

---
 .../execution/operator/BenchmarkCRDummy.kt    |  34 ++++
 .../execution/operator/ControllerDummy.kt     |  91 +++++++++
 .../execution/operator/ControllerTest.kt      | 190 +++++++++---------
 .../execution/operator/ExecutionCRDummy.kt    |  52 +++++
 4 files changed, 271 insertions(+), 96 deletions(-)
 create mode 100644 theodolite-quarkus/src/test/kotlin/theodolite/execution/operator/BenchmarkCRDummy.kt
 create mode 100644 theodolite-quarkus/src/test/kotlin/theodolite/execution/operator/ControllerDummy.kt
 create mode 100644 theodolite-quarkus/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt

diff --git a/theodolite-quarkus/src/test/kotlin/theodolite/execution/operator/BenchmarkCRDummy.kt b/theodolite-quarkus/src/test/kotlin/theodolite/execution/operator/BenchmarkCRDummy.kt
new file mode 100644
index 000000000..f3fd06a16
--- /dev/null
+++ b/theodolite-quarkus/src/test/kotlin/theodolite/execution/operator/BenchmarkCRDummy.kt
@@ -0,0 +1,34 @@
+package theodolite.execution.operator
+
+import theodolite.benchmark.KubernetesBenchmark
+import theodolite.model.crd.BenchmarkCRD
+import theodolite.util.KafkaConfig
+
+class BenchmarkCRDummy(name: String) {
+
+    private val benchmark = KubernetesBenchmark()
+    private val benchmarkCR = BenchmarkCRD(benchmark)
+
+    fun getCR(): BenchmarkCRD {
+        return benchmarkCR
+    }
+
+    init {
+        val kafkaConfig = KafkaConfig()
+
+        kafkaConfig.bootstrapServer = ""
+        kafkaConfig.topics = emptyList()
+
+        benchmarkCR.spec = benchmark
+        benchmarkCR.metadata.name = name
+        benchmarkCR.kind = "Benchmark"
+        benchmarkCR.apiVersion = "v1"
+
+        benchmark.appResource = emptyList()
+        benchmark.loadGenResource = emptyList()
+        benchmark.resourceTypes = emptyList()
+        benchmark.loadTypes = emptyList()
+        benchmark.kafkaConfig = kafkaConfig
+        benchmark.name = benchmarkCR.metadata.name
+    }
+}
\ No newline at end of file
diff --git a/theodolite-quarkus/src/test/kotlin/theodolite/execution/operator/ControllerDummy.kt b/theodolite-quarkus/src/test/kotlin/theodolite/execution/operator/ControllerDummy.kt
new file mode 100644
index 000000000..a729c5013
--- /dev/null
+++ b/theodolite-quarkus/src/test/kotlin/theodolite/execution/operator/ControllerDummy.kt
@@ -0,0 +1,91 @@
+package theodolite.execution.operator
+
+import io.fabric8.kubernetes.client.NamespacedKubernetesClient
+import io.fabric8.kubernetes.client.dsl.MixedOperation
+import io.fabric8.kubernetes.client.dsl.Resource
+import io.fabric8.kubernetes.internal.KubernetesDeserializer
+import theodolite.k8s.K8sContextFactory
+import theodolite.model.crd.*
+
+private const val SCOPE = "Namespaced"
+private const val EXECUTION_SINGULAR = "execution"
+private const val EXECUTION_PLURAL = "executions"
+private const val BENCHMARK_SINGULAR = "benchmark"
+private const val BENCHMARK_PLURAL = "benchmarks"
+private const val API_VERSION = "v1"
+private const val RESYNC_PERIOD = 10 * 60 * 1000.toLong()
+private const val GROUP = "theodolite.com"
+
+class ControllerDummy(val client: NamespacedKubernetesClient) {
+
+    private lateinit var controller: TheodoliteController
+
+    fun getController(): TheodoliteController {
+        return this.controller
+    }
+
+    init {
+        KubernetesDeserializer.registerCustomKind(
+            "$GROUP/$API_VERSION",
+            EXECUTION_SINGULAR,
+            ExecutionCRD::class.java
+        )
+
+        KubernetesDeserializer.registerCustomKind(
+            "$GROUP/$API_VERSION",
+            BENCHMARK_SINGULAR,
+            BenchmarkCRD::class.java
+        )
+
+        val contextFactory = K8sContextFactory()
+        val executionContext =
+            contextFactory
+                .create(
+                    API_VERSION,
+                    SCOPE,
+                    GROUP,
+                    EXECUTION_PLURAL
+                )
+        val benchmarkContext =
+            contextFactory
+                .create(
+                    API_VERSION,
+                    SCOPE,
+                    GROUP,
+                    BENCHMARK_PLURAL
+                )
+
+        val executionCRDClient: MixedOperation<
+                ExecutionCRD,
+                BenchmarkExecutionList,
+                DoneableExecution,
+                Resource<ExecutionCRD, DoneableExecution>> = client.customResources(
+            executionContext,
+            ExecutionCRD::class.java,
+            BenchmarkExecutionList::class.java,
+            DoneableExecution::class.java
+        )
+
+        val benchmarkCRDClient = client.customResources(
+            benchmarkContext,
+            BenchmarkCRD::class.java,
+            KubernetesBenchmarkList::class.java,
+            DoneableBenchmark::class.java
+        )
+
+        val executionStateHandler = ExecutionStateHandler(
+            context = executionContext,
+            client = client
+        )
+
+        val appResource = System.getenv("THEODOLITE_APP_RESOURCES") ?: "./config"
+        this.controller =
+            TheodoliteController(
+                namespace = client.namespace,
+                path = appResource,
+                benchmarkCRDClient = benchmarkCRDClient,
+                executionCRDClient = executionCRDClient,
+                executionStateHandler = executionStateHandler
+            )
+    }
+}
\ No newline at end of file
diff --git a/theodolite-quarkus/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt b/theodolite-quarkus/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt
index e01504763..a56e27e76 100644
--- a/theodolite-quarkus/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt
+++ b/theodolite-quarkus/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt
@@ -3,108 +3,62 @@ package theodolite.execution.operator
 import com.google.gson.Gson
 import com.google.gson.GsonBuilder
 import io.fabric8.kubernetes.client.CustomResourceList
-import io.fabric8.kubernetes.client.dsl.MixedOperation
-import io.fabric8.kubernetes.client.dsl.Resource
 import io.fabric8.kubernetes.client.server.mock.KubernetesServer
-import io.fabric8.kubernetes.internal.KubernetesDeserializer
 import io.quarkus.test.junit.QuarkusTest
 import org.junit.jupiter.api.AfterEach
 import org.junit.jupiter.api.Assertions.assertEquals
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
+import theodolite.benchmark.BenchmarkExecution
 import theodolite.benchmark.KubernetesBenchmark
-import theodolite.k8s.K8sContextFactory
-import theodolite.model.crd.*
-import theodolite.util.KafkaConfig
-
-private const val DEFAULT_NAMESPACE = "default"
-private const val SCOPE = "Namespaced"
-private const val EXECUTION_SINGULAR = "execution"
-private const val EXECUTION_PLURAL = "executions"
-private const val BENCHMARK_SINGULAR = "benchmark"
-private const val BENCHMARK_PLURAL = "benchmarks"
-private const val API_VERSION = "v1"
-private const val RESYNC_PERIOD = 10 * 60 * 1000.toLong()
-private const val GROUP = "theodolite.com"
+import theodolite.model.crd.BenchmarkCRD
+import theodolite.model.crd.ExecutionCRD
 
 @QuarkusTest
 class ControllerTest {
     private final val server = KubernetesServer(false, false)
-    private final val testResourcePath = "./src/test/resources/k8s-resource-files/"
     lateinit var controller: TheodoliteController
-    lateinit var benchmarkCRDClient: MixedOperation<BenchmarkCRD, KubernetesBenchmarkList, DoneableBenchmark, Resource<BenchmarkCRD, DoneableBenchmark>>
     private val gson: Gson = GsonBuilder().enableComplexMapKeySerialization().create()
 
-    private val kafkaConfig = KafkaConfig()
-    private val benchmark = KubernetesBenchmark()
+    private var benchmark = KubernetesBenchmark()
+    private var execution = BenchmarkExecution()
+
+    private val benchmarkResourceList = CustomResourceList<BenchmarkCRD>()
+    private val executionResourceList = CustomResourceList<ExecutionCRD>()
 
 
     @BeforeEach
     fun setUp() {
         server.before()
-
-        KubernetesDeserializer.registerCustomKind(
-            "$GROUP/$API_VERSION",
-            EXECUTION_SINGULAR,
-            ExecutionCRD::class.java
-        )
-
-        KubernetesDeserializer.registerCustomKind(
-            "$GROUP/$API_VERSION",
-            BENCHMARK_SINGULAR,
-            BenchmarkCRD::class.java
-        )
-
-        val contextFactory = K8sContextFactory()
-        val executionContext = contextFactory.create(API_VERSION, SCOPE, GROUP, EXECUTION_PLURAL)
-        val benchmarkContext = contextFactory.create(API_VERSION, SCOPE, GROUP, BENCHMARK_PLURAL)
-
-        val executionCRDClient: MixedOperation<
-                ExecutionCRD,
-                BenchmarkExecutionList,
-                DoneableExecution,
-                Resource<ExecutionCRD, DoneableExecution>> = server.client.customResources(
-            executionContext,
-            ExecutionCRD::class.java,
-            BenchmarkExecutionList::class.java,
-            DoneableExecution::class.java
-        )
-
-        this.benchmarkCRDClient = server.client.customResources(
-            benchmarkContext,
-            BenchmarkCRD::class.java,
-            KubernetesBenchmarkList::class.java,
-            DoneableBenchmark::class.java
-        )
-
-        val executionStateHandler = ExecutionStateHandler(
-            context = executionContext,
-            client = server.client
-        )
-
-        val appResource = System.getenv("THEODOLITE_APP_RESOURCES") ?: "./config"
-        this.controller =
-            TheodoliteController(
-                namespace = server.client.namespace,
-                path = appResource,
-                benchmarkCRDClient = benchmarkCRDClient,
-                executionCRDClient = executionCRDClient,
-                executionStateHandler = executionStateHandler
-            )
-
-
-        // create benchmarks
-
-        kafkaConfig.bootstrapServer = ""
-        kafkaConfig.topics = emptyList()
-
-        benchmark.name = "Test-Benchmark"
-        benchmark.appResource = emptyList()
-        benchmark.loadGenResource = emptyList()
-        benchmark.resourceTypes = emptyList()
-        benchmark.loadTypes = emptyList()
-        benchmark.kafkaConfig = kafkaConfig
-
+        this.controller = ControllerDummy(server.client).getController()
+
+        // benchmark
+        val benchmark1 = BenchmarkCRDummy(name = "Test-Benchmark")
+        val benchmark2 = BenchmarkCRDummy(name = "Test-Benchmark-123")
+        benchmarkResourceList.items = listOf(benchmark1.getCR(), benchmark2.getCR())
+
+        // execution
+        val execution1 = ExecutionCRDummy(name = "matching-execution", benchmark =  "Test-Benchmark")
+        val execution2 = ExecutionCRDummy(name = "non-matching-execution", benchmark = "Test-Benchmark-456")
+        val execution3 = ExecutionCRDummy(name = "second-matching-execution", benchmark = "Test-Benchmark")
+        executionResourceList.items = listOf(execution1.getCR(), execution2.getCR(), execution3.getCR())
+
+        this.benchmark = benchmark1.getCR().spec
+        this.execution = execution1.getCR().spec
+
+        server
+            .expect()
+            .get()
+            .withPath("/apis/theodolite.com/v1/namespaces/test/benchmarks")
+            .andReturn(200, benchmarkResourceList)
+            .always()
+
+        server
+            .expect()
+            .get()
+            .withPath("/apis/theodolite.com/v1/namespaces/test/executions")
+            .andReturn(200, executionResourceList)
+            .always()
     }
 
     @AfterEach
@@ -113,22 +67,66 @@ class ControllerTest {
     }
 
     @Test
-    fun test() {
-        val crd = BenchmarkCRD(benchmark)
-        crd.spec = benchmark
-        crd.metadata.name = "Test-Benchmark"
-        crd.kind = "Benchmark"
-        crd.apiVersion = "v1"
+    fun getBenchmarksTest() {
+        val method = controller
+            .javaClass
+            .getDeclaredMethod("getBenchmarks")
+        method.isAccessible = true
 
-        val list = CustomResourceList<BenchmarkCRD>()
-        list.items = listOf(crd)
+        val result = method.invoke(controller) as List<KubernetesBenchmark>
 
-        server.expect().get().withPath("/apis/theodolite.com/v1/namespaces/test/benchmarks").andReturn(200, list).always()
+        assertEquals(2, result.size)
+        assertEquals(
+            gson.toJson(benchmark),
+            gson.toJson(result.firstOrNull()))
+    }
 
-        val method = controller.javaClass.getDeclaredMethod("getBenchmarks")
+    @Test
+    fun getNextExecution() {
+        val method = controller
+            .javaClass
+            .getDeclaredMethod("getNextExecution")
         method.isAccessible = true
-        benchmark.name = crd.metadata.name
-        val result = method.invoke(controller) as List<KubernetesBenchmark>
-        assertEquals(gson.toJson(result[0]), gson.toJson(benchmark))
+
+        val result = method.invoke(controller) as BenchmarkExecution?
+
+        assertEquals(
+            gson.toJson(this.execution),
+            gson.toJson(result))
+    }
+
+    @Test
+    fun setAdditionalLabelsTest() {
+        val method = controller
+            .javaClass
+            .getDeclaredMethod("setAdditionalLabels",
+                String::class.java,
+                String::class.java,
+                List::class.java,
+                BenchmarkExecution::class.java)
+        method.isAccessible = true
+
+        this.benchmark.appResource = listOf("test-resource.yaml")
+
+        method.invoke(controller,
+            "test-value",
+            "test-name",
+            this.benchmark.appResource,
+            this.execution
+        ) as BenchmarkExecution?
+
+        assertEquals(
+            "test-name",
+            this.execution
+                .configOverrides.firstOrNull()
+                ?.patcher
+                ?.properties
+                ?.get("variableName")
+        )
+        assertEquals(
+            "test-value",
+            this.execution
+                .configOverrides.firstOrNull()
+                ?.value)
     }
 }
\ No newline at end of file
diff --git a/theodolite-quarkus/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt b/theodolite-quarkus/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt
new file mode 100644
index 000000000..258931929
--- /dev/null
+++ b/theodolite-quarkus/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt
@@ -0,0 +1,52 @@
+package theodolite.execution.operator
+
+import theodolite.benchmark.BenchmarkExecution
+import theodolite.model.crd.ExecutionCRD
+import theodolite.model.crd.ExecutionStatus
+import theodolite.model.crd.States
+
+class ExecutionCRDummy(name: String, benchmark: String) {
+
+    private val execution = BenchmarkExecution()
+    private val executionState = ExecutionStatus()
+    private val executionCR = ExecutionCRD(execution, executionState)
+
+    fun getCR(): ExecutionCRD {
+        return this.executionCR
+    }
+
+    init {
+        // configure metadata
+        executionCR.spec = execution
+        executionCR.metadata.name = name
+        executionCR.kind = "Execution"
+        executionCR.apiVersion = "v1"
+
+        // configure execution
+        val loadType = BenchmarkExecution.LoadDefinition()
+        loadType.loadType = ""
+        loadType.loadValues = emptyList()
+
+        val resourceDef = BenchmarkExecution.ResourceDefinition()
+        resourceDef.resourceType = ""
+        resourceDef.resourceValues = emptyList()
+
+        val exec = BenchmarkExecution.Execution()
+        exec.afterTeardownDelay = 0
+        exec.duration = 0
+        exec.loadGenerationDelay = 0
+        exec.repetitions = 1
+        exec.restrictions = emptyList()
+        exec.strategy = ""
+
+        execution.benchmark = benchmark
+        execution.load = loadType
+        execution.resources = resourceDef
+        execution.slos = emptyList()
+        execution.execution = exec
+        execution.configOverrides = mutableListOf()
+        execution.name = executionCR.metadata.name
+
+        executionState.executionState = States.PENDING.value
+    }
+}
\ No newline at end of file
-- 
GitLab