Skip to content

Commit

Permalink
Add abstraction classes for tests
Browse files Browse the repository at this point in the history
This commit introduces the AbstractTest class for general tests.
It also adds the AbstractHaraMessageTest to be used for tests dependent
on the Hara client messages.

Signed-off-by: Saeed Rezaee <[email protected]>
  • Loading branch information
SaeedRe committed Feb 22, 2024
1 parent 6b74ead commit bcb2569
Show file tree
Hide file tree
Showing 8 changed files with 358 additions and 254 deletions.
2 changes: 1 addition & 1 deletion dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ ext {
joda:'joda-time:joda-time:2.10.13'
]
test_dependencies = [
testng: 'org.testng:testng:7.5'
testng: 'org.testng:testng:7.9.0'
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import okhttp3.OkHttpClient
import org.eclipse.hara.ddiclient.api.ConfigDataProvider
import org.eclipse.hara.ddiclient.api.DeploymentPermitProvider
Expand All @@ -30,35 +29,20 @@ import org.eclipse.hara.ddiclient.api.MessageListener
import org.eclipse.hara.ddiclient.api.Updater
import org.eclipse.hara.ddiclient.integrationtest.api.management.Action
import org.eclipse.hara.ddiclient.integrationtest.api.management.ActionStatus
import org.eclipse.hara.ddiclient.integrationtest.api.management.HawkbitAssignDistributionBody
import org.eclipse.hara.ddiclient.integrationtest.api.management.HawkbitTargetInfo
import org.eclipse.hara.ddiclient.integrationtest.api.management.ManagementApi
import org.eclipse.hara.ddiclient.integrationtest.api.management.ManagementClient
import org.eclipse.hara.ddiclient.integrationtest.api.management.ServerSystemConfig
import org.eclipse.hara.ddiclient.integrationtest.utils.TestUtils
import org.eclipse.hara.ddiclient.integrationtest.utils.addOkhttpLogger
import org.eclipse.hara.ddiclient.integrationtest.utils.internalLog
import org.testng.Assert
import org.testng.annotations.AfterTest
import org.testng.annotations.BeforeTest
import org.eclipse.hara.ddiclient.integrationtest.utils.safeStopClient
import java.io.File
import java.lang.Exception
import kotlin.coroutines.cancellation.CancellationException
import kotlin.time.Duration.Companion.seconds

abstract class AbstractDeploymentTest {

protected lateinit var managementApi: ManagementApi
abstract val targetId: String
protected var actionId: Int = 0
abstract class AbstractDeploymentTest: AbstractTest() {

private var assertServerActionsScope = CoroutineScope(Dispatchers.IO)
private var assertServerActionsOnCompleteJob: Deferred<Unit>? = null
private var testScope = CoroutineScope(Dispatchers.Default)

private val throwableScope = CoroutineScope(Dispatchers.Default)
private var throwableJob: Deferred<Unit>? = null

private val eventListener = object : MessageListener {
override fun onMessage(message: MessageListener.Message) {
"Message received: $message".internalLog()
Expand All @@ -80,18 +64,6 @@ abstract class AbstractDeploymentTest {
}
}

@BeforeTest
open fun beforeTest() {
managementApi = ManagementClient.newInstance(TestUtils.hawkbitUrl)
}

@AfterTest
open fun afterTest() {
}

protected fun setPollingTime(time: String) = runBlocking {
managementApi.setPollingTime(TestUtils.basic, ServerSystemConfig(time))
}

protected fun defaultClientFromTargetId(
directoryDataProvider: DirectoryForArtifactsProvider = TestUtils.directoryDataProvider,
Expand Down Expand Up @@ -139,26 +111,6 @@ abstract class AbstractDeploymentTest {
deploymentPermitProvider = deploymentBehavior).invoke(targetId)
}

protected suspend fun reCreateTestTargetOnServer() {
runCatching {
managementApi.deleteTarget(TestUtils.basic, targetId)
}
runCatching {
managementApi.createTarget(
TestUtils.basic, listOf(HawkbitTargetInfo(targetId)))
}
}

protected suspend fun assignDistributionToTheTarget(
distribution: HawkbitAssignDistributionBody) {
val response =
managementApi.assignDistributionToTarget(TestUtils.basic,
targetId, distribution)
if (response.assignedActions.isNotEmpty()) {
actionId = response.assignedActions.first().id
}
}

protected suspend fun startTheTestAndWaitForResult(client: HaraClient,
deployment: TestUtils.TargetDeployments) {
client.startAsync()
Expand Down Expand Up @@ -202,20 +154,4 @@ abstract class AbstractDeploymentTest {
TestUtils.firstActionWithAssignmentEntry
))

private suspend fun assertEquals(actual: Any?, expected: Any?) {
throwableJob = throwableScope.async {
Assert.assertEquals(actual, expected)
}
try {
throwableJob?.await()
} catch (ignored: CancellationException) {
}
}

private fun HaraClient.safeStopClient() {
try {
stop()
} catch (ignored: Exception) {
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
*
* * Copyright © 2017-2024 Kynetics LLC
* *
* * This program and the accompanying materials are made
* * available under the terms of the Eclipse Public License 2.0
* * which is available at https://www.eclipse.org/legal/epl-2.0/
* *
* * SPDX-License-Identifier: EPL-2.0
*
*/

package org.eclipse.hara.ddiclient.integrationtest

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient
import org.eclipse.hara.ddiclient.api.ConfigDataProvider
import org.eclipse.hara.ddiclient.api.DeploymentPermitProvider
import org.eclipse.hara.ddiclient.api.DirectoryForArtifactsProvider
import org.eclipse.hara.ddiclient.api.DownloadBehavior
import org.eclipse.hara.ddiclient.api.HaraClient
import org.eclipse.hara.ddiclient.api.MessageListener
import org.eclipse.hara.ddiclient.api.Updater
import org.eclipse.hara.ddiclient.integrationtest.utils.internalLog
import kotlin.coroutines.cancellation.CancellationException

abstract class AbstractHaraMessageTest : AbstractTest() {

private var expectedHaraMessages = mutableListOf<ExpectedMessage>()
open val expectedMessagesAssertionListener:
List<suspend (ExpectedMessage) -> Unit> = listOf()

private val expectedMessageChannel =
Channel<ExpectedMessage>(5, BufferOverflow.DROP_OLDEST)

private val checkMessagesScope = CoroutineScope(Dispatchers.IO)
private var checkExpectedMessagesJob: Deferred<Unit>? = null

open val expectedMessagesList: MutableList<MutableList<ExpectedMessage>> =
mutableListOf(expectedHaraMessages)

open fun filterHaraMessages(message: MessageListener.Message): Boolean = true

protected fun sendExpectedMessage(message: ExpectedMessage) {
checkMessagesScope.launch {
expectedMessageChannel.send(message)
}
}

protected suspend fun startWatchingExpectedMessages(lastTest: Boolean = false) {
checkExpectedMessagesJob = getExpectedMessagesCheckingJob(lastTest)
try {
checkExpectedMessagesJob?.await()
} catch (ignored: CancellationException) {
}
}

open val messageListener: MessageListener
get() = object : MessageListener {
override fun onMessage(message: MessageListener.Message) {
"Received message: $message".internalLog()
if (filterHaraMessages(message)) {
sendExpectedMessage(ExpectedMessage.HaraMessage(message))
}
}
}

private suspend fun getExpectedMessagesCheckingJob(lastTest: Boolean): Deferred<Unit> {
return checkMessagesScope.async {
for (msg in expectedMessageChannel) {
when (msg) {
is ExpectedMessage.HaraMessage -> {
if (expectedHaraMessages.isNotEmpty()) {
assertEquals(msg, expectedHaraMessages.removeFirst())
}
}

else -> {
expectedMessagesAssertionListener.forEach {
it.invoke(msg)
}
}
}
val finished = expectedMessagesList.map {
it.isEmpty()
}
if (finished.all { it }) {
"All expected messages received".internalLog()
checkExpectedMessagesJob?.cancel()
if (lastTest) {
safeStopClient()
}
}
}
}
}

override fun clientFromTargetId(
directoryDataProvider: DirectoryForArtifactsProvider,
configDataProvider: ConfigDataProvider, updater: Updater,
messageListeners: List<MessageListener>,
deploymentPermitProvider: DeploymentPermitProvider,
downloadBehavior: DownloadBehavior,
okHttpClientBuilder: OkHttpClient.Builder,
targetToken: String?,
gatewayToken: String?): (String) -> HaraClient {
return super.clientFromTargetId(
directoryDataProvider, configDataProvider, updater,
listOf(messageListener),
deploymentPermitProvider,
downloadBehavior, okHttpClientBuilder,
targetToken, gatewayToken)
}

protected fun expectMessages(vararg messages: MessageListener.Message) {
expectedHaraMessages.clear()
expectedHaraMessages.addAll(messages.map { ExpectedMessage.HaraMessage(it) })
}


sealed class ExpectedMessage {

data class HaraMessage(val message: MessageListener.Message) : ExpectedMessage()
}
}
Loading

0 comments on commit bcb2569

Please sign in to comment.