From ca462df471a1d4a8b48b617534f83d4b9146d1fe Mon Sep 17 00:00:00 2001 From: Travis Haagen Date: Sat, 12 Oct 2024 13:21:17 -0700 Subject: [PATCH] repeated start and stop test --- build.gradle.kts | 1 + .../com/onepeloton/locust4k/LocustWorker.kt | 4 +- .../locust4k/examples/ExampleAppTest.kt | 65 +++++++++++++++++-- .../locust4k/examples/TestcontainersBase.kt | 29 +++++++++ 4 files changed, 92 insertions(+), 7 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index ba7de5e..be582ed 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -69,6 +69,7 @@ dependencies { testImplementation("org.junit.jupiter:junit-jupiter:$junitJupiterVersion") testImplementation("org.testcontainers:junit-jupiter:$testcontainersVersion") testImplementation("io.rest-assured:rest-assured:$restAssuredVersion") + testImplementation("io.rest-assured:kotlin-extensions:$restAssuredVersion") } group = "com.onepeloton.locust4k" diff --git a/src/main/kotlin/com/onepeloton/locust4k/LocustWorker.kt b/src/main/kotlin/com/onepeloton/locust4k/LocustWorker.kt index cfd3dba..15a78a7 100644 --- a/src/main/kotlin/com/onepeloton/locust4k/LocustWorker.kt +++ b/src/main/kotlin/com/onepeloton/locust4k/LocustWorker.kt @@ -345,9 +345,7 @@ class LocustWorker( taskInstance.execute(stats, taskContext) } if (isActive.not()) { - logger.warn { - "Task (${taskInstance.name()}) no longer active. Was CancellationException suppressed?" - } + logger.info { "Task (${taskInstance.name()}) cancelled (inactive)" } return@launch } } catch (e: CancellationException) { diff --git a/src/test/kotlin/com/onepeloton/locust4k/examples/ExampleAppTest.kt b/src/test/kotlin/com/onepeloton/locust4k/examples/ExampleAppTest.kt index a17bf46..c03e79b 100644 --- a/src/test/kotlin/com/onepeloton/locust4k/examples/ExampleAppTest.kt +++ b/src/test/kotlin/com/onepeloton/locust4k/examples/ExampleAppTest.kt @@ -8,7 +8,7 @@ import java.time.Duration class ExampleAppTest : TestcontainersBase() { @Test - fun singleWorkerWithLocustMasterEndingTest() { + fun singleUserWithHeadlessLocustMasterEndingTest() { val locustMasterContainer = buildLocustMasterContainer(runtimeSeconds = 5) val locustWorkerExampleContainer = buildLocustWorkerExampleContainer() try { @@ -39,6 +39,7 @@ class ExampleAppTest : TestcontainersBase() { workerLogs, stringContainsInOrder( "Starting Locust Worker", + "Connecting", "Connected to Locust", "Received ack", "Spawn message from controller", @@ -62,7 +63,7 @@ class ExampleAppTest : TestcontainersBase() { } @Test - fun singleWorkerMultipleUsersWithLocustMasterEndingTest() { + fun multipleUsersWithHeadlessLocustMasterEndingTest() { val locustMasterContainer = buildLocustMasterContainer(users = 3, spawnRate = 2, runtimeSeconds = 5) val locustWorkerExampleContainer = buildLocustWorkerExampleContainer() try { @@ -93,6 +94,7 @@ class ExampleAppTest : TestcontainersBase() { workerLogs, stringContainsInOrder( "Starting Locust Worker", + "Connecting", "Connected to Locust", "Received ack", "Spawn message from controller", @@ -105,8 +107,8 @@ class ExampleAppTest : TestcontainersBase() { "beforeExecuteLoop invoked", "Spawning Complete", "Quit message", - "afterExecuteLoop invoked", - "afterExecuteLoop invoked", + // next two messages each repeated 3 times, but order inconsistent + "Task (exampleTask) cancelled", "afterExecuteLoop invoked", "Stats consumer stopped", "Stats reporter stopped", @@ -119,4 +121,59 @@ class ExampleAppTest : TestcontainersBase() { stopContainers(locustMasterContainer, locustWorkerExampleContainer) } } + + @Test + fun singleUserWithRepeatedStartAndStop() { + val locustMasterContainer = buildLocustMasterContainer(headless = false) + val locustWorkerExampleContainer = buildLocustWorkerExampleContainer() + try { + // given + startContainers(locustMasterContainer, locustWorkerExampleContainer) + + LogMessageWaitStrategy() + .withRegEx(".*1 workers connected.*\\s") + .withStartupTimeout(Duration.ofSeconds(5)) + .waitUntilReady(locustMasterContainer) + + // when + repeat(2) { + startLoadTest(locustMasterContainer) + + LogMessageWaitStrategy() + .withRegEx(".* Spawning Complete message from controller.*\\s") + .withStartupTimeout(Duration.ofSeconds(5)) + .waitUntilReady(locustWorkerExampleContainer) + + stopLoadTest(locustMasterContainer) + } + val workerLogs = locustWorkerExampleContainer.logs + + // then + assertThat( + workerLogs, + stringContainsInOrder( + "Starting Locust Worker", + "Connecting", + "Connected to Locust", + "Received ack", + // first run + "Spawn message from controller", + "Stats reset", + "+1 (-0) user-units", + "Spawning Complete", + "Stop message from controller", + "Ack message from controller", + // second run + "Spawn message from controller", + "Stats reset", + "+1 (-0) user-units", + "Spawning Complete", + "Stop message from controller", + "Ack message from controller", + ), + ) + } finally { + stopContainers(locustMasterContainer, locustWorkerExampleContainer) + } + } } diff --git a/src/test/kotlin/com/onepeloton/locust4k/examples/TestcontainersBase.kt b/src/test/kotlin/com/onepeloton/locust4k/examples/TestcontainersBase.kt index 1d16ce4..1dbb89d 100644 --- a/src/test/kotlin/com/onepeloton/locust4k/examples/TestcontainersBase.kt +++ b/src/test/kotlin/com/onepeloton/locust4k/examples/TestcontainersBase.kt @@ -1,6 +1,9 @@ package com.onepeloton.locust4k.examples import io.github.oshai.kotlinlogging.KotlinLogging +import io.restassured.module.kotlin.extensions.Given +import io.restassured.module.kotlin.extensions.Then +import io.restassured.module.kotlin.extensions.When import org.junit.jupiter.api.fail import org.testcontainers.containers.GenericContainer import org.testcontainers.containers.Network @@ -99,4 +102,30 @@ abstract class TestcontainersBase { } } } + + protected fun startLoadTest( + locustMasterContainer: GenericContainer<*>, + users: Int = 1, + spawnRate: Int = 1, + ) { + Given { + port(locustMasterContainer.getMappedPort(8089)) + formParam("user_count", users) + formParam("spawn_rate", spawnRate) + } When { + post("/swarm") + } Then { + statusCode(200) + } + } + + protected fun stopLoadTest(locustMasterContainer: GenericContainer<*>) { + Given { + port(locustMasterContainer.getMappedPort(8089)) + } When { + get("/stop") + } Then { + statusCode(200) + } + } }