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 20, 2024
1 parent 6b74ead commit b0cddec
Show file tree
Hide file tree
Showing 7 changed files with 347 additions and 242 deletions.
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() {

protected 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: ExpectedMessage) {
expectedHaraMessages.clear()
expectedHaraMessages.addAll(messages)
}


sealed class ExpectedMessage {

data class HaraMessage(val message: MessageListener.Message) : ExpectedMessage()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
*
* * 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.runBlocking
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.HaraClientData
import org.eclipse.hara.ddiclient.api.HaraClientDefaultImpl
import org.eclipse.hara.ddiclient.api.MessageListener
import org.eclipse.hara.ddiclient.api.Updater
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.testng.Assert
import org.testng.annotations.AfterTest
import org.testng.annotations.BeforeTest
import java.lang.Exception
import kotlin.coroutines.cancellation.CancellationException

abstract class AbstractTest {

protected lateinit var managementApi: ManagementApi
abstract val targetId: String

private val throwableScope = CoroutineScope(Dispatchers.Default)

private var throwableJob: Deferred<Unit>? = null

protected var client: HaraClient? = null
set(value) {
safeStopClient()
field = value
}


@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 suspend fun reCreateTestTargetOnServer() {
runCatching {
managementApi.deleteTarget(TestUtils.basic, targetId)
}
runCatching {
managementApi.createTarget(
TestUtils.basic, listOf(HawkbitTargetInfo(targetId)))
}
}

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

protected fun safeStopClient() {
try {
client?.stop()
} catch (ignored: Exception) {
}
}

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

open fun clientFromTargetId(
directoryDataProvider: DirectoryForArtifactsProvider = TestUtils.directoryDataProvider,
configDataProvider: ConfigDataProvider = TestUtils.configDataProvider,
updater: Updater = TestUtils.updater,
messageListeners: List<MessageListener> = listOf(),
deploymentPermitProvider: DeploymentPermitProvider = object :
DeploymentPermitProvider {},
downloadBehavior: DownloadBehavior = TestUtils.downloadBehavior,
okHttpClientBuilder: OkHttpClient.Builder = OkHttpClient.Builder().addOkhttpLogger(),
targetToken: String? = "",
gatewayToken: String? = TestUtils.gatewayToken): (String) -> HaraClient =
{ targetId ->
val clientData = HaraClientData(
TestUtils.tenantName,
targetId,
TestUtils.hawkbitUrl,
gatewayToken, targetToken)

val client = HaraClientDefaultImpl()

client.init(
clientData,
directoryDataProvider,
configDataProvider,
deploymentPermitProvider,
listOf(*messageListeners.toTypedArray()),
listOf(updater),
downloadBehavior,
httpBuilder = okHttpClientBuilder
)

client
}
}
Loading

0 comments on commit b0cddec

Please sign in to comment.