Skip to content

Commit

Permalink
Merge branch 'develop' into feature/ISSUE-796/improve-screen-recorder
Browse files Browse the repository at this point in the history
  • Loading branch information
SergKhram authored Jun 28, 2024
2 parents 4ab20e1 + f7542b1 commit 9f22612
Show file tree
Hide file tree
Showing 34 changed files with 345 additions and 141 deletions.
28 changes: 0 additions & 28 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,6 @@ jobs:
- name: detekt
run: |
./gradlew clean detektCheck || true
cd-snapshot:
runs-on: ubuntu-22.04
needs: ci
if: ${{ github.ref == 'refs/heads/develop' }}
steps:
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '11'
- name: deliver maven
run: |
bash .buildsystem/deploy-sonatype.sh
env:
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
BUGSNAG_TOKEN: ${{ secrets.BUGSNAG_TOKEN }}
- name: deliver cli
run: |
./gradlew :cli:publishDistZipPublicationToGitHubRepository -PreleaseMode=SNAPSHOT
env:
GH_MAVEN_USERNAME: ${{ secrets.GH_MAVEN_USERNAME }}
GH_MAVEN_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
BUGSNAG_TOKEN: ${{ secrets.BUGSNAG_TOKEN }}
cd-release:
runs-on: ubuntu-22.04
needs: ci
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,16 @@ data class FilteringConfiguration(
JsonSubTypes.Type(value = TestFilterConfiguration.AllureFilterConfiguration::class, name = "allure"),
)
sealed class TestFilterConfiguration {
@JsonProperty("enabled")
open val enabled: Boolean = true

abstract fun validate()

data class SimpleClassnameFilterConfiguration(
@JsonProperty("regex") val regex: Regex? = null,
@JsonProperty("values") val values: List<String>? = null,
@JsonProperty("file") val file: File? = null,
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {
var i = 0
Expand Down Expand Up @@ -75,6 +79,7 @@ sealed class TestFilterConfiguration {
@JsonProperty("regex") val regex: Regex? = null,
@JsonProperty("values") val values: List<String>? = null,
@JsonProperty("file") val file: File? = null,
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {
var i = 0
Expand Down Expand Up @@ -111,6 +116,7 @@ sealed class TestFilterConfiguration {
@JsonProperty("regex") val regex: Regex? = null,
@JsonProperty("values") val values: List<String>? = null,
@JsonProperty("file") val file: File? = null,
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {
var i = 0
Expand Down Expand Up @@ -148,6 +154,7 @@ sealed class TestFilterConfiguration {
@JsonProperty("values") val values: List<String>? = null,
@JsonProperty("file") val file: File? = null,
@JsonProperty("subpackages") val subpackages: Boolean = false,
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {
var i = 0
Expand Down Expand Up @@ -184,7 +191,8 @@ sealed class TestFilterConfiguration {

data class AnnotationDataFilterConfiguration(
@JsonProperty("nameRegex") val nameRegex: Regex,
@JsonProperty("valueRegex") val valueRegex: Regex
@JsonProperty("valueRegex") val valueRegex: Regex,
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {}

Expand All @@ -200,6 +208,7 @@ sealed class TestFilterConfiguration {
@JsonProperty("regex") val regex: Regex? = null,
@JsonProperty("values") val values: List<String>? = null,
@JsonProperty("file") val file: File? = null,
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {
var i = 0
Expand Down Expand Up @@ -235,6 +244,7 @@ sealed class TestFilterConfiguration {
data class FragmentationFilterConfiguration(
val index: Int,
val count: Int,
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {
if (index < 0) throw ConfigurationException("Fragment index [$index] should be >= 0")
Expand All @@ -247,6 +257,7 @@ sealed class TestFilterConfiguration {
@JsonProperty("regex") val regex: Regex? = null,
@JsonProperty("values") val values: List<String>? = null,
@JsonProperty("file") val file: File? = null,
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {
var i = 0
Expand Down Expand Up @@ -283,6 +294,7 @@ sealed class TestFilterConfiguration {
@JsonProperty("regex") val regex: Regex? = null,
@JsonProperty("values") val values: List<String>? = null,
@JsonProperty("file") val file: File? = null,
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {
var i = 0
Expand Down Expand Up @@ -317,7 +329,8 @@ sealed class TestFilterConfiguration {

data class CompositionFilterConfiguration(
@JsonProperty("filters") val filters: List<TestFilterConfiguration>,
@JsonProperty("op") val op: OPERATION
@JsonProperty("op") val op: OPERATION,
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {
filters.forEach { it.validate() }
Expand All @@ -342,7 +355,9 @@ sealed class TestFilterConfiguration {
override fun hashCode(): Int = filters.hashCode() + op.hashCode()
}

object AllureFilterConfiguration : TestFilterConfiguration() {
data class AllureFilterConfiguration(
@JsonProperty("enabled") override val enabled: Boolean = true,
) : TestFilterConfiguration() {
override fun validate() {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,12 @@ class ConfigurationFactoryTest {
configuration.retryStrategy shouldBeEqualTo
RetryStrategyConfiguration.FixedQuotaRetryStrategyConfiguration(100, 2)

TestFilterConfiguration.SimpleClassnameFilterConfiguration(".*".toRegex()) shouldBeEqualTo
TestFilterConfiguration.SimpleClassnameFilterConfiguration(".*".toRegex())
TestFilterConfiguration.SimpleClassnameFilterConfiguration(".*".toRegex(),) shouldBeEqualTo
TestFilterConfiguration.SimpleClassnameFilterConfiguration(".*".toRegex(),)

configuration.filteringConfiguration.allowlist shouldContainSame listOf(
TestFilterConfiguration.SimpleClassnameFilterConfiguration(".*".toRegex()),
TestFilterConfiguration.SimpleClassnameFilterConfiguration(values = listOf("SimpleTest")),
TestFilterConfiguration.SimpleClassnameFilterConfiguration(".*".toRegex(),),
TestFilterConfiguration.SimpleClassnameFilterConfiguration(values = listOf("SimpleTest"),),
TestFilterConfiguration.FullyQualifiedClassnameFilterConfiguration(".*".toRegex()),
TestFilterConfiguration.FullyQualifiedClassnameFilterConfiguration(
file = File(
Expand Down Expand Up @@ -335,7 +335,7 @@ class ConfigurationFactoryTest {
val configuration = parser.parse(file)

configuration.filteringConfiguration.allowlist shouldBeEqualTo listOf(
TestFilterConfiguration.SimpleClassnameFilterConfiguration(".*".toRegex())
TestFilterConfiguration.SimpleClassnameFilterConfiguration(".*".toRegex(),)
)

configuration.filteringConfiguration.blocklist shouldBe emptyList()
Expand All @@ -349,7 +349,7 @@ class ConfigurationFactoryTest {
configuration.filteringConfiguration.allowlist shouldBe emptyList()

configuration.filteringConfiguration.blocklist shouldBeEqualTo listOf(
TestFilterConfiguration.SimpleClassnameFilterConfiguration(".*".toRegex())
TestFilterConfiguration.SimpleClassnameFilterConfiguration(".*".toRegex(),)
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class DevicePoolActor(
}

private suspend fun deviceReturnedTestBatch(device: Device, batch: TestBatch, reason: String) {
logger.debug { "pool $poolId: device ${device.serialNumber} returned test batch" }
queue.send(QueueMessage.ReturnBatch(device.toDeviceInfo(), batch, reason))
}

Expand All @@ -98,7 +99,7 @@ class DevicePoolActor(
}

// Requests a batch of tests for a random device from the list of devices not running tests at the moment.
// When @avoidingDevice is not null, attemtps to send the request for any other device whenever available.
// When @avoidingDevice is not null, attempts to send the request for any other device whenever available.
private suspend fun maybeRequestBatch(avoidingDevice: Device? = null) {
val availableDevices = devices.values.asSequence()
.map { it as DeviceActor }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ sealed class DevicePoolMessage {
object Terminate : FromScheduler()
}

sealed class FromDevice(val device: Device) : DevicePoolMessage() {
class IsReady(device: Device) : FromDevice(device)
class CompletedTestBatch(device: Device, val results: TestBatchResults) : FromDevice(device)
class ReturnTestBatch(device: Device, val batch: TestBatch, val reason: String) : FromDevice(device)
sealed class FromDevice(open val device: Device) : DevicePoolMessage() {
data class IsReady(override val device: Device) : FromDevice(device)
data class CompletedTestBatch(override val device: Device, val results: TestBatchResults) : FromDevice(device)
data class ReturnTestBatch(override val device: Device, val batch: TestBatch, val reason: String) : FromDevice(device)
}

sealed class FromQueue : DevicePoolMessage() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CompletionHandler
import kotlinx.coroutines.Job
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.async
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.channels.SendChannel
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlin.coroutines.CoroutineContext

class DeviceActor(
Expand Down Expand Up @@ -153,11 +156,12 @@ class DeviceActor(
}
}

private var job: Job? = null
private var initializeJob: Job? = null
private var executeJob: Job? = null

private fun initialize() {
logger.debug { "initialize ${device.serialNumber}" }
job = async {
initializeJob = async {
try {
withRetry(30, 10000) {
if (isActive) {
Expand All @@ -181,7 +185,7 @@ class DeviceActor(

private fun executeBatch(batch: TestBatch, result: CompletableDeferred<TestBatchResults>) {
logger.debug { "executeBatch ${device.serialNumber}" }
job = async {
executeJob = async {
try {
device.execute(configuration, devicePoolId, batch, result)
state.transition(DeviceEvent.Complete)
Expand All @@ -193,39 +197,34 @@ class DeviceActor(
state.transition(DeviceEvent.Terminate)
} catch (e: TestBatchExecutionException) {
logger.warn(e) { "Test batch failed execution" }
pool.send(
DevicePoolMessage.FromDevice.ReturnTestBatch(
device,
batch,
"Test batch failed execution:\n${e.stackTraceToString()}"
)
)
returnBatchAnd(batch, "Test batch failed execution:\n" + e.stackTraceToString()) {}
state.transition(DeviceEvent.Complete)
} catch (e: Throwable) {
logger.error(e) { "Unknown vendor exception caught. Considering this a recoverable error" }
pool.send(
DevicePoolMessage.FromDevice.ReturnTestBatch(
device, batch, "Unknown vendor exception caught. \n" +
"${e.stackTraceToString()}"
)
)
returnBatchAnd(batch, "Unknown vendor exception caught:\n" + e.stackTraceToString()) {}
state.transition(DeviceEvent.Complete)
}
}
}

private fun returnBatchAnd(batch: TestBatch, reason: String, completionHandler: CompletionHandler = {}): Job {
logger.debug { "Returning batch ${batch.id}. Reason: $reason" }
return launch {
pool.send(DevicePoolMessage.FromDevice.ReturnTestBatch(device, batch, reason))
withContext(NonCancellable) {
pool.send(DevicePoolMessage.FromDevice.ReturnTestBatch(device, batch, reason))
}
}.apply {
invokeOnCompletion(completionHandler)
}
}

private fun terminate() {
logger.debug { "terminate ${device.serialNumber}" }
job?.cancel()
close()
launch {
initializeJob?.cancelAndJoin()
executeJob?.cancelAndJoin()
close()
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import io.qameta.allure.testfilter.TestPlanSupplier
import io.qameta.allure.testfilter.TestPlanV1_0

val ALLURE_ID_ANNOTATIONS = setOf("io.qameta.allure.AllureId", "io.qameta.allure.kotlin.AllureId")
class AllureTestFilter(val cnf: TestFilterConfiguration.AllureFilterConfiguration, private val testPlanSupplier: TestPlanSupplier = FileTestPlanSupplier()) : TestFilter {

class AllureTestFilter(
val cnf: TestFilterConfiguration.AllureFilterConfiguration,
private val testPlanSupplier: TestPlanSupplier = FileTestPlanSupplier()
) : TestFilter {
private val testPlan: TestPlan? by lazy {
val optional = testPlanSupplier.supply()
if (optional.isPresent) {
Expand All @@ -21,7 +25,7 @@ class AllureTestFilter(val cnf: TestFilterConfiguration.AllureFilterConfiguratio
}

override fun filter(tests: List<Test>): List<Test> {
return if (testPlan != null && testPlan is TestPlanV1_0) {
return if (cnf.enabled && testPlan != null && testPlan is TestPlanV1_0) {
val plan = testPlan as TestPlanV1_0
tests.filter { test ->
val allureId: String? = findAllureId(test)
Expand All @@ -31,11 +35,12 @@ class AllureTestFilter(val cnf: TestFilterConfiguration.AllureFilterConfiguratio
tests
}
}

private fun findAllureId(test: Test) =
test.metaProperties.find { ALLURE_ID_ANNOTATIONS.contains(it.name) }?.values?.get("value") as? String

override fun filterNot(tests: List<Test>): List<Test> {
return if (testPlan != null && testPlan is TestPlanV1_0) {
return if (cnf.enabled && testPlan != null && testPlan is TestPlanV1_0) {
val plan = testPlan as TestPlanV1_0
tests.filterNot { test ->
val allureId: String? = findAllureId(test)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,25 @@ import com.malinskiy.marathon.test.MetaProperty
import com.malinskiy.marathon.test.Test

data class AnnotationDataFilter(val cnf: TestFilterConfiguration.AnnotationDataFilterConfiguration) : TestFilter {
override fun filter(tests: List<Test>): List<Test> = tests.filter { test ->
test.metaProperties.any {
match(it)

override fun filter(tests: List<Test>): List<Test> = if (cnf.enabled) {
tests.filter { test ->
test.metaProperties.any {
match(it)
}
}
} else {
tests
}

override fun filterNot(tests: List<Test>): List<Test> = tests.filterNot { test ->
test.metaProperties.any {
match(it)
override fun filterNot(tests: List<Test>): List<Test> = if (cnf.enabled) {
tests.filterNot { test ->
test.metaProperties.any {
match(it)
}
}
} else {
tests
}

private fun match(metaProperty: MetaProperty): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,24 @@ package com.malinskiy.marathon.execution.filter
import com.malinskiy.marathon.config.TestFilterConfiguration

class AnnotationFilter(cnf: TestFilterConfiguration.AnnotationFilterConfiguration) :
SingleValueTestFilter(cnf.regex, cnf.values, cnf.file, { test, values ->
when {
regex != null -> {
test.metaProperties.map { it.name }.any(regex::matches)
}
values != null -> {
test.metaProperties.map { it.name }.intersect(values).isNotEmpty()
}
else -> {
true
SingleValueTestFilter(
cnf.regex,
cnf.values,
cnf.file,
cnf.enabled,
{ test, values ->
when {
regex != null -> {
test.metaProperties.map { it.name }.any(regex::matches)
}

values != null -> {
test.metaProperties.map { it.name }.intersect(values).isNotEmpty()
}

else -> {
true
}
}
}
})
},
)
Loading

0 comments on commit 9f22612

Please sign in to comment.