From cbf2f3d2cdc94341a9eff79a3780357d8de7335c Mon Sep 17 00:00:00 2001
From: Marcel Becker <stu117960@mail.uni-kiel.de>
Date: Sun, 19 Dec 2021 16:56:42 +0100
Subject: [PATCH] Restructured yaml and associated changes to
 TheodoliteExecutor

---
 theodolite/crd/crd-execution.yaml             | 25 +++++++++++++------
 .../benchmark/BenchmarkExecution.kt           | 16 ++++++++++--
 .../execution/TheodoliteExecutor.kt           | 20 ++++++---------
 .../theodolite/strategies/StrategyFactory.kt  | 23 +++++++++++------
 ...positeStrategy.kt => RestrictionSearch.kt} |  8 +++---
 .../src/main/kotlin/theodolite/util/Config.kt |  7 +++---
 ...rategyTest.kt => RestrictionSearchTest.kt} | 18 ++++++-------
 7 files changed, 70 insertions(+), 47 deletions(-)
 rename theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/{CompositeStrategy.kt => RestrictionSearch.kt} (88%)
 rename theodolite/src/test/kotlin/theodolite/{CompositeStrategyTest.kt => RestrictionSearchTest.kt} (91%)

diff --git a/theodolite/crd/crd-execution.yaml b/theodolite/crd/crd-execution.yaml
index d9cd41903..fde590bbb 100644
--- a/theodolite/crd/crd-execution.yaml
+++ b/theodolite/crd/crd-execution.yaml
@@ -81,10 +81,24 @@ spec:
                 description: Defines the overall parameter for the execution.
                 type: object
                 required: ["strategy", "duration", "repetitions", "restrictions"]
+                metric:
+                  default: "demand"
+                  type: string
+                  oneOf:
+                    - "demand"
+                    - "capacity"
+                strategy:
+                  description: Defines the used strategy for the execution, either 'LinearSearch', 'BinarySearch' or 'InitialGuessSearch'
+                  type: object
+                  name: string
+                  properties:
+                    restrictions:
+                      description: List of restriction strategys used to delimit the search space.
+                      type: array
+                      items:
+                        type: string
+                    guessStrategy: string
                 properties:
-                  strategy:
-                    description: Defines the used strategy for the execution, either 'LinearSearch' or 'BinarySearch'
-                    type: string
                   duration:
                     description: Defines the duration of each experiment in seconds.
                     type: integer
@@ -94,11 +108,6 @@ spec:
                   loadGenerationDelay:
                     description: Seconds to wait between the start of the SUT and the load generator.
                     type: integer
-                  restrictions:
-                    description: List of restriction strategys used to delimit the search space.
-                    type: array
-                    items:
-                      type: string
               configOverrides:
                 description:  List of patchers that are used to override existing configurations.
                 type: array
diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt b/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt
index f2dda487d..168daa457 100644
--- a/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt
+++ b/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt
@@ -3,6 +3,7 @@ package theodolite.benchmark
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize
 import io.fabric8.kubernetes.api.model.KubernetesResource
 import io.quarkus.runtime.annotations.RegisterForReflection
+import theodolite.strategies.searchstrategy.SearchStrategy
 import theodolite.util.ConfigurationOverride
 import kotlin.properties.Delegates
 
@@ -41,14 +42,25 @@ class BenchmarkExecution : KubernetesResource {
     @JsonDeserialize
     @RegisterForReflection
     class Execution : KubernetesResource {
-        lateinit var strategy: String
+        lateinit var metric: String
+        lateinit var strategy: Strategy
         var duration by Delegates.notNull<Long>()
         var repetitions by Delegates.notNull<Int>()
-        lateinit var restrictions: List<String>
         var loadGenerationDelay = 0L
         var afterTeardownDelay = 5L
     }
 
+    /**
+     * This Strategy encapsulates the [restrictions] which is used for restricting the resources.
+     */
+    @JsonDeserialize
+    @RegisterForReflection
+    class Strategy : KubernetesResource {
+        lateinit var name: String
+        lateinit var restrictions: List<String>
+        lateinit var guessStrategy: String
+    }
+
     /**
      * Measurable metric.
      * [sloType] determines the type of the metric.
diff --git a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt b/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt
index 315d1cf1a..4091a058e 100644
--- a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt
+++ b/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt
@@ -5,7 +5,6 @@ import theodolite.benchmark.BenchmarkExecution
 import theodolite.benchmark.KubernetesBenchmark
 import theodolite.patcher.PatcherDefinitionFactory
 import theodolite.strategies.StrategyFactory
-import theodolite.strategies.searchstrategy.CompositeStrategy
 import theodolite.util.*
 import java.io.File
 import java.time.Duration
@@ -34,8 +33,8 @@ class TheodoliteExecutor(
      * Creates all required components to start Theodolite.
      *
      * @return a [Config], that contains a list of [LoadDimension]s,
-     *          a list of [Resource]s , and the [CompositeStrategy].
-     * The [CompositeStrategy] is configured and able to find the minimum required resource for the given load.
+     *          a list of [Resource]s , and the [restrictionSearch].
+     * The [searchStrategy] is configured and able to find the minimum required resource for the given load.
      */
     private fun buildConfig(): Config {
         val results = Results()
@@ -93,14 +92,7 @@ class TheodoliteExecutor(
                     resourcePatcherDefinition
                 )
             },
-            compositeStrategy = CompositeStrategy(
-                benchmarkExecutor = executor,
-                searchStrategy = strategyFactory.createSearchStrategy(executor, config.execution.strategy),
-                restrictionStrategies = strategyFactory.createRestrictionStrategy(
-                    results,
-                    config.execution.restrictions
-                )
-            )
+            searchStrategy = strategyFactory.createSearchStrategy(executor, config.execution.strategy, results)
         )
     }
 
@@ -125,16 +117,18 @@ class TheodoliteExecutor(
         )
 
         val config = buildConfig()
+        //TODO: Differentiate metrics here
+
         // execute benchmarks for each load
         try {
             for (load in config.loads) {
                 if (executor.run.get()) {
-                    config.compositeStrategy.findSuitableResource(load, config.resources)
+                    config.searchStrategy.findSuitableResource(load, config.resources)
                 }
             }
         } finally {
             ioHandler.writeToJSONFile(
-                config.compositeStrategy.benchmarkExecutor.results,
+                config.searchStrategy.benchmarkExecutor.results,
                 "${resultsFolder}exp${this.config.executionId}-result"
             )
         }
diff --git a/theodolite/src/main/kotlin/theodolite/strategies/StrategyFactory.kt b/theodolite/src/main/kotlin/theodolite/strategies/StrategyFactory.kt
index 829370e8c..7de70c5d2 100644
--- a/theodolite/src/main/kotlin/theodolite/strategies/StrategyFactory.kt
+++ b/theodolite/src/main/kotlin/theodolite/strategies/StrategyFactory.kt
@@ -1,12 +1,10 @@
 package theodolite.strategies
 
+import theodolite.benchmark.BenchmarkExecution
 import theodolite.execution.BenchmarkExecutor
 import theodolite.strategies.restriction.LowerBoundRestriction
 import theodolite.strategies.restriction.RestrictionStrategy
-import theodolite.strategies.searchstrategy.BinarySearch
-import theodolite.strategies.searchstrategy.FullSearch
-import theodolite.strategies.searchstrategy.LinearSearch
-import theodolite.strategies.searchstrategy.SearchStrategy
+import theodolite.strategies.searchstrategy.*
 import theodolite.util.Results
 
 /**
@@ -23,13 +21,22 @@ class StrategyFactory {
      *
      * @throws IllegalArgumentException if the [SearchStrategy] was not one of the allowed options.
      */
-    fun createSearchStrategy(executor: BenchmarkExecutor, searchStrategyString: String): SearchStrategy {
-        return when (searchStrategyString) {
+    fun createSearchStrategy(executor: BenchmarkExecutor, searchStrategyObject: BenchmarkExecution.Strategy, results: Results): SearchStrategy {
+
+        var strategy : SearchStrategy = when (searchStrategyObject.name) {
             "FullSearch" -> FullSearch(executor)
             "LinearSearch" -> LinearSearch(executor)
             "BinarySearch" -> BinarySearch(executor)
-            else -> throw IllegalArgumentException("Search Strategy $searchStrategyString not found")
+            "InitialGuessSearch" -> when (searchStrategyObject.guessStrategy){
+                "PrevResourceMinGuess" -> InitialGuessSearchStrategy(executor,PrevResourceMinGuess(), results)
+                else -> throw IllegalArgumentException("Guess Strategy ${searchStrategyObject.guessStrategy} not found")
+            }
+            else -> throw IllegalArgumentException("Search Strategy $searchStrategyObject not found")
+        }
+        if(searchStrategyObject.restrictions.isNotEmpty()){
+            strategy = RestrictionSearch(executor,strategy,createRestrictionStrategy(results, searchStrategyObject.restrictions))
         }
+        return strategy
     }
 
     /**
@@ -42,7 +49,7 @@ class StrategyFactory {
      *
      * @throws IllegalArgumentException if param searchStrategyString was not one of the allowed options.
      */
-    fun createRestrictionStrategy(results: Results, restrictionStrings: List<String>): Set<RestrictionStrategy> {
+    private fun createRestrictionStrategy(results: Results, restrictionStrings: List<String>): Set<RestrictionStrategy> {
         return restrictionStrings
             .map { restriction ->
                 when (restriction) {
diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/CompositeStrategy.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/RestrictionSearch.kt
similarity index 88%
rename from theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/CompositeStrategy.kt
rename to theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/RestrictionSearch.kt
index 41cc5c325..776cdeba5 100644
--- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/CompositeStrategy.kt
+++ b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/RestrictionSearch.kt
@@ -7,14 +7,14 @@ import theodolite.util.LoadDimension
 import theodolite.util.Resource
 
 /**
- *  Composite strategy that combines a SearchStrategy and a set of RestrictionStrategy.
+ *  Strategy that combines a SearchStrategy and a set of RestrictionStrategy.
  *
- * @param searchStrategy the [SearchStrategy] that is executed as part of this [CompositeStrategy].
+ * @param searchStrategy the [SearchStrategy] that is executed as part of this [RestrictionSearch].
  * @param restrictionStrategies the set of [RestrictionStrategy] that are connected conjunctive to restrict the [Resource]
  * @param benchmarkExecutor Benchmark executor which runs the individual benchmarks.
  */
 @RegisterForReflection
-class CompositeStrategy(
+class RestrictionSearch(
     benchmarkExecutor: BenchmarkExecutor,
     private val searchStrategy: SearchStrategy,
     val restrictionStrategies: Set<RestrictionStrategy>
@@ -27,4 +27,4 @@ class CompositeStrategy(
         }
         return this.searchStrategy.findSuitableResource(load, restrictedResources)
     }
-}
+}
\ No newline at end of file
diff --git a/theodolite/src/main/kotlin/theodolite/util/Config.kt b/theodolite/src/main/kotlin/theodolite/util/Config.kt
index afbf784e9..e3fde8fcf 100644
--- a/theodolite/src/main/kotlin/theodolite/util/Config.kt
+++ b/theodolite/src/main/kotlin/theodolite/util/Config.kt
@@ -1,18 +1,19 @@
 package theodolite.util
 
 import io.quarkus.runtime.annotations.RegisterForReflection
-import theodolite.strategies.searchstrategy.CompositeStrategy
+import theodolite.strategies.searchstrategy.RestrictionSearch
+import theodolite.strategies.searchstrategy.SearchStrategy
 
 /**
  * Config class that represents a configuration of a theodolite run.
  *
  * @param loads the [LoadDimension] of the execution
  * @param resources the [Resource] of the execution
- * @param compositeStrategy the [CompositeStrategy] of the execution
+ * @param searchStrategy the [SearchStrategy] of the execution
  */
 @RegisterForReflection
 data class Config(
     val loads: List<LoadDimension>,
     val resources: List<Resource>,
-    val compositeStrategy: CompositeStrategy
+    val searchStrategy: SearchStrategy
 )
diff --git a/theodolite/src/test/kotlin/theodolite/CompositeStrategyTest.kt b/theodolite/src/test/kotlin/theodolite/RestrictionSearchTest.kt
similarity index 91%
rename from theodolite/src/test/kotlin/theodolite/CompositeStrategyTest.kt
rename to theodolite/src/test/kotlin/theodolite/RestrictionSearchTest.kt
index 580d9e747..965040e06 100644
--- a/theodolite/src/test/kotlin/theodolite/CompositeStrategyTest.kt
+++ b/theodolite/src/test/kotlin/theodolite/RestrictionSearchTest.kt
@@ -6,17 +6,18 @@ import org.junit.jupiter.api.Test
 import theodolite.benchmark.BenchmarkExecution
 import theodolite.strategies.restriction.LowerBoundRestriction
 import theodolite.strategies.searchstrategy.BinarySearch
-import theodolite.strategies.searchstrategy.CompositeStrategy
+import theodolite.strategies.searchstrategy.RestrictionSearch
 import theodolite.strategies.searchstrategy.LinearSearch
 import theodolite.util.LoadDimension
 import theodolite.util.Resource
 import theodolite.util.Results
 
 @QuarkusTest
-class CompositeStrategyTest {
+class RestrictionSearchTest {
+
 
     @Test
-    fun testEnd2EndLinearSearch() {
+    fun restrictionSearchTestLinearSearch() {
         val mockResults = arrayOf(
             arrayOf(true, true, true, true, true, true, true),
             arrayOf(false, false, true, true, true, true, true),
@@ -35,7 +36,7 @@ class CompositeStrategyTest {
         val linearSearch = LinearSearch(benchmarkExecutor)
         val lowerBoundRestriction = LowerBoundRestriction(results)
         val strategy =
-            CompositeStrategy(benchmarkExecutor, linearSearch, setOf(lowerBoundRestriction))
+            RestrictionSearch(benchmarkExecutor, linearSearch, setOf(lowerBoundRestriction))
 
         val actual: ArrayList<Resource?> = ArrayList()
         val expected: ArrayList<Resource?> = ArrayList(listOf(0, 2, 2, 3, 4, 6).map { x -> Resource(x, emptyList()) })
@@ -49,7 +50,7 @@ class CompositeStrategyTest {
     }
 
     @Test
-    fun testEnd2EndBinarySearch() {
+    fun restrictionSearchTestBinarySearch() {
         val mockResults = arrayOf(
             arrayOf(true, true, true, true, true, true, true),
             arrayOf(false, false, true, true, true, true, true),
@@ -68,8 +69,7 @@ class CompositeStrategyTest {
             TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 0)
         val binarySearch = BinarySearch(benchmarkExecutorImpl)
         val lowerBoundRestriction = LowerBoundRestriction(results)
-        val strategy =
-            CompositeStrategy(benchmarkExecutorImpl, binarySearch, setOf(lowerBoundRestriction))
+        val strategy = RestrictionSearch(benchmarkExecutorImpl, binarySearch, setOf(lowerBoundRestriction))
 
         val actual: ArrayList<Resource?> = ArrayList()
         val expected: ArrayList<Resource?> = ArrayList(listOf(0, 2, 2, 3, 4, 6).map { x -> Resource(x, emptyList()) })
@@ -83,7 +83,7 @@ class CompositeStrategyTest {
     }
 
     @Test
-    fun testEnd2EndBinarySearch2() {
+    fun restrictionSearchTestBinarySearch2() {
         val mockResults = arrayOf(
             arrayOf(true, true, true, true, true, true, true, true),
             arrayOf(false, false, true, true, true, true, true, true),
@@ -102,7 +102,7 @@ class CompositeStrategyTest {
         val binarySearch = BinarySearch(benchmarkExecutor)
         val lowerBoundRestriction = LowerBoundRestriction(results)
         val strategy =
-            CompositeStrategy(benchmarkExecutor, binarySearch, setOf(lowerBoundRestriction))
+            RestrictionSearch(benchmarkExecutor, binarySearch, setOf(lowerBoundRestriction))
 
         val actual: ArrayList<Resource?> = ArrayList()
         val expected: ArrayList<Resource?> =
-- 
GitLab