22
33package ftl.run.common
44
5- import com.google.api.services.testing.model.Environment
6- import com.google.api.services.testing.model.TestExecution
75import com.google.api.services.testing.model.TestMatrix
86import ftl.args.IArgs
97import ftl.gc.GcTestMatrix
10- import ftl.util.StopWatch
11- import ftl.util.StopWatchMatrix
12- import ftl.util.isCompleted
13- import kotlinx.coroutines.Dispatchers
14- import kotlinx.coroutines.async
15- import kotlinx.coroutines.awaitAll
8+ import ftl.run.status.TestMatrixStatusPrinter
9+ import ftl.util.MatrixState
1610import kotlinx.coroutines.coroutineScope
1711import kotlinx.coroutines.delay
1812import kotlinx.coroutines.flow.Flow
13+ import kotlinx.coroutines.flow.asFlow
14+ import kotlinx.coroutines.flow.flatMapMerge
1915import kotlinx.coroutines.flow.flow
16+ import kotlinx.coroutines.flow.fold
2017import kotlinx.coroutines.flow.onEach
21- import kotlinx.coroutines.flow.reduce
2218
2319suspend fun pollMatrices (
2420 testMatricesIds : Iterable <String >,
2521 args : IArgs ,
26- stopWatch : StopWatch = StopWatch ()
27- ): List <TestMatrix > = coroutineScope {
28- stopWatch.start()
29- testMatricesIds.map { testMatrixId ->
30- async(Dispatchers .IO ) {
31- matrixChangesFlow(
32- testMatrixId = testMatrixId,
33- projectId = args.project
34- ).printChanges(
35- stopWatch = stopWatch,
36- args = args
37- ).reduce { _, latest ->
38- latest
39- }
40- }
41- }.awaitAll()
22+ printMatrixStatus : (TestMatrix ) -> Unit = TestMatrixStatusPrinter (
23+ args = args,
24+ testMatricesIds = testMatricesIds
25+ )
26+ ): Collection <TestMatrix > = coroutineScope {
27+ testMatricesIds.asFlow().flatMapMerge { testMatrixId ->
28+ matrixChangesFlow(
29+ testMatrixId = testMatrixId,
30+ projectId = args.project
31+ )
32+ }.onEach {
33+ printMatrixStatus(it)
34+ }.fold(emptyMap<String , TestMatrix >()) { matrices, next ->
35+ matrices + (next.testMatrixId to next)
36+ }.values.also {
37+ println ()
38+ }
4239}
4340
4441private fun matrixChangesFlow (
@@ -52,63 +49,6 @@ private fun matrixChangesFlow(
5249 }
5350}
5451
55- private fun Flow<TestMatrix>.printChanges (
56- stopWatch : StopWatch ,
57- args : IArgs ,
58- cache : MutableMap <String , ExecutionStatus > = mutableMapOf()
59- ) = onEach { matrix: TestMatrix ->
60- matrix.testExecutions.map { execution ->
61- printExecutionStatus(
62- watch = StopWatchMatrix (stopWatch, execution.formatName(args)),
63- previous = cache[execution.id] ? : ExecutionStatus (),
64- current = execution.getDeviceStatus().also {
65- cache[execution.id] = it
66- }
67- )
68- }
69- if (matrix.isCompleted) StopWatchMatrix (
70- stopwatch = stopWatch,
71- matrixId = matrix.testMatrixId
72- ).puts(matrix.state)
73- }
74-
75- private fun printExecutionStatus (
76- previous : ExecutionStatus ,
77- current : ExecutionStatus ,
78- watch : StopWatchMatrix
79- ) {
80- if (current.error != previous.error && current.error != null ) {
81- watch.puts(" Error: ${current.error} " )
82- }
83- current.progress.minus(previous.progress).forEach { message ->
84- watch.puts(message)
85- }
86- if (current.state != previous.state) {
87- watch.puts(current.state)
88- }
89- }
90-
91- private fun TestExecution.formatName (args : IArgs ): String {
92- val matrixExecutionId = id.split(" _" )
93- val matrixId = matrixExecutionId.first()
94- val executionId = matrixExecutionId.takeIf { args.flakyTestAttempts > 0 }?.getOrNull(1 )?.let { " $it " } ? : " "
95- val env: Environment ? = environment
96- val device = env?.androidDevice?.androidModelId ? : env?.iosDevice?.iosModelId
97- val deviceVersion = env?.androidDevice?.androidVersionId ? : env?.iosDevice?.iosVersionId
98- val shard = shard?.takeUnless { args.disableSharding }?.run { " shard-${(shardIndex ? : 0 )} " } ? : " "
99- return " $matrixId $device -$deviceVersion$shard$executionId "
100- }
101-
102- private fun TestExecution.getDeviceStatus () = ExecutionStatus (
103- testExecutionId = id,
104- state = state,
105- error = testDetails?.errorMessage,
106- progress = testDetails?.progressMessages ? : emptyList()
107- )
108-
109- private data class ExecutionStatus (
110- val testExecutionId : String = " " ,
111- val state : String = " " ,
112- val error : String? = null ,
113- val progress : List <String > = emptyList()
114- )
52+ private val TestMatrix .isCompleted: Boolean
53+ get() = MatrixState .completed(state) &&
54+ testExecutions?.all { MatrixState .completed(it.state) } ? : true
0 commit comments