Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add printing total run duration #1773

Merged
merged 5 commits into from
Apr 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions test_runner/src/main/kotlin/ftl/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
package ftl

import ftl.presentation.cli.MainCommand
import ftl.reports.startDurationMeasurement
import ftl.run.exception.withGlobalExceptionHandling
import picocli.CommandLine

fun main(args: Array<String>) {
withGlobalExceptionHandling {
startDurationMeasurement()
CommandLine(MainCommand()).execute(*args)
}
}
5 changes: 4 additions & 1 deletion test_runner/src/main/kotlin/ftl/domain/RunTestAndroid.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ import ftl.config.defaultAndroidConfig
import ftl.config.loadAndroidConfig
import ftl.config.plus
import ftl.mock.MockServer
import ftl.reports.addStepTime
import ftl.reports.output.configure
import ftl.reports.output.log
import ftl.reports.output.outputReport
import ftl.reports.output.toOutputReportConfiguration
import ftl.run.dumpShards
import ftl.run.newTestRun
import ftl.util.DEVICE_SYSTEM
import ftl.util.StopWatch
import ftl.util.TEST_TYPE
import ftl.util.loadFile
import ftl.util.printVersionInfo
Expand All @@ -38,7 +40,7 @@ operator fun RunTestAndroid.invoke() {
if (dryRun) {
MockServer.start()
}

val prepareStopWatch = StopWatch().start()
createAndroidArgs(
config = defaultAndroidConfig() +
loadAndroidConfig(reader = loadFile(Paths.get(configPath))) +
Expand All @@ -60,6 +62,7 @@ operator fun RunTestAndroid.invoke() {
args.dumpShards()
else {
logLn(args)
addStepTime("Preparation", prepareStopWatch.check())
args.newTestRun()
}
}
Expand Down
8 changes: 7 additions & 1 deletion test_runner/src/main/kotlin/ftl/domain/RunTestIos.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ import ftl.config.defaultIosConfig
import ftl.config.loadIosConfig
import ftl.config.plus
import ftl.mock.MockServer
import ftl.reports.addStepTime
import ftl.reports.output.configure
import ftl.reports.output.log
import ftl.reports.output.outputReport
import ftl.reports.output.toOutputReportConfiguration
import ftl.run.dumpShards
import ftl.run.newTestRun
import ftl.util.DEVICE_SYSTEM
import ftl.util.StopWatch
import ftl.util.TEST_TYPE
import ftl.util.loadFile
import ftl.util.printVersionInfo
Expand All @@ -39,6 +41,7 @@ operator fun RunIosTest.invoke() {
MockServer.start()
}

val prepareStopWatch = StopWatch().start()
createIosArgs(
config = defaultIosConfig() +
loadIosConfig(reader = loadFile(Paths.get(configPath))) +
Expand All @@ -56,6 +59,9 @@ operator fun RunIosTest.invoke() {
if (dumpShards.not()) logLn(this)
}.validate().run {
if (dumpShards) dumpShards()
else runBlocking { newTestRun() }
else runBlocking {
addStepTime("Preparation", prepareStopWatch.check())
newTestRun()
}
}
}
38 changes: 38 additions & 0 deletions test_runner/src/main/kotlin/ftl/reports/DurationReport.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package ftl.reports

import flank.common.OutputLogLevel
import flank.common.logLn
import ftl.util.Duration
import ftl.util.StopWatch
import ftl.util.formatted

val totalDurationStopWatch by lazy { StopWatch() }

private val stepsTimes = mutableListOf<StepRunDuration>()

data class StepRunDuration(
val name: String,
val duration: Duration
)

fun startDurationMeasurement() {
totalDurationStopWatch.start()
}

fun addStepTime(name: String, duration: Duration) {
stepsTimes.add(StepRunDuration(name, duration))
}

fun printTotalDuration() {
logLn(level = OutputLogLevel.DETAILED)
logLn(
"Total run duration: ${totalDurationStopWatch.check().formatted(alignSeconds = true)}",
level = OutputLogLevel.DETAILED
)
stepsTimes.forEach { stepRunDuration ->
logLn(
"\t- ${stepRunDuration.name}: ${stepRunDuration.duration.formatted()}",
level = OutputLogLevel.DETAILED
)
}
}
17 changes: 12 additions & 5 deletions test_runner/src/main/kotlin/ftl/run/NewTestRun.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import ftl.args.IosArgs
import ftl.json.SavedMatrix
import ftl.json.updateMatrixMap
import ftl.json.validate
import ftl.reports.addStepTime
import ftl.reports.output.log
import ftl.reports.output.outputReport
import ftl.reports.util.ReportManager
Expand All @@ -17,6 +18,7 @@ import ftl.run.model.TestResult
import ftl.run.platform.common.printMatricesWebLinks
import ftl.run.platform.runAndroidTests
import ftl.run.platform.runIosTests
import ftl.util.measureTime
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.withTimeoutOrNull

Expand All @@ -32,12 +34,17 @@ suspend fun IArgs.newTestRun() = withTimeoutOrNull(parsedTimeout) {
matrixMap
)
}
ReportManager.generate(matrixMap, args, testShardChunks, ignoredTests)
cancelTestsOnTimeout(args.project, matrixMap.map) { fetchArtifacts(matrixMap, args) }

matrixMap.printMatricesWebLinks(project)
outputReport.log(matrixMap)
matrixMap.validate(ignoreFailedTests)
val duration = measureTime {
ReportManager.generate(matrixMap, args, testShardChunks, ignoredTests)
cancelTestsOnTimeout(args.project, matrixMap.map) { fetchArtifacts(matrixMap, args) }

matrixMap.printMatricesWebLinks(project)
outputReport.log(matrixMap)
matrixMap.validate(ignoreFailedTests)
}

addStepTime("Generating reports", duration)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import ftl.json.SavedMatrix
import ftl.reports.output.add
import ftl.reports.output.generate
import ftl.reports.output.outputReport
import ftl.reports.printTotalDuration
import ftl.run.cancelMatrices
import ftl.util.closeCrashReporter
import ftl.util.report
Expand All @@ -15,6 +16,7 @@ fun withGlobalExceptionHandling(block: () -> Int) {
withGlobalExceptionHandling(block) {
closeCrashReporter()
outputReport.generate()
printTotalDuration()
exitProcess(it)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import ftl.gc.GcStorage.uploadSessionId
import ftl.gc.GcTestMatrix
import ftl.json.MatrixMap
import ftl.json.createSavedMatrix
import ftl.reports.addStepTime
import ftl.run.common.saveSessionId
import ftl.run.common.updateMatrixFile
import ftl.util.StopWatch
import ftl.util.formatted
import ftl.util.isInvalid
import ftl.util.webLink
import kotlinx.coroutines.Dispatchers
Expand All @@ -33,10 +35,11 @@ internal suspend fun IArgs.afterRunTests(
saveConfigFile(matrixMap)
saveSessionId()
uploadSessionId()
logLn(FtlConstants.indent + "${matrixMap.map.size} matrix ids created in ${stopwatch.check()}")
logLn(FtlConstants.indent + "${matrixMap.map.size} matrix ids created in ${stopwatch.check().formatted()}")
val gcsBucket = GCS_STORAGE_LINK + resultsBucket + "/" + matrixMap.runPath
logLn("${FtlConstants.indent}Raw results will be stored in your GCS bucket at [$gcsBucket]")
matrixMap.printMatricesWebLinks(project)
addStepTime("Running tests", stopwatch.check())
}

private fun List<TestMatrix>.toSavedMatrixMap() =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import com.google.testing.model.TestMatrix
import flank.common.logLn
import ftl.args.IArgs
import ftl.config.FtlConstants
import ftl.reports.addStepTime
import ftl.util.MatrixState
import ftl.util.StopWatch
import ftl.util.formatted

class TestMatrixStatusPrinter(
private val args: IArgs,
Expand All @@ -22,10 +24,13 @@ class TestMatrixStatusPrinter(
private val allMatricesCompleted get() = cache.values.all(MatrixState::completed)

override fun invoke(matrix: TestMatrix) {
val time = stopWatch.check(alignSeconds = true)
printExecutionStatusList(time, matrix.testExecutions)
val time = stopWatch.check()
printExecutionStatusList(time.formatted(alignSeconds = true), matrix.testExecutions)
cache[matrix.testMatrixId] = matrix.state
if (allMatricesCompleted) printTestMatrixStatusList(time)
if (allMatricesCompleted) {
printTestMatrixStatusList(time.formatted(alignSeconds = true))
addStepTime("Executing matrices", time)
}
}

private fun printTestMatrixStatusList(time: String) {
Expand Down
36 changes: 23 additions & 13 deletions test_runner/src/main/kotlin/ftl/util/StopWatch.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package ftl.util

import ftl.run.exception.FlankGeneralError
import java.util.Locale
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeUnit.MILLISECONDS

class StopWatch {
Expand All @@ -13,21 +13,31 @@ class StopWatch {
return this
}

fun check(alignSeconds: Boolean = false): String {
fun check(): Duration {
if (startTime == 0L) throw FlankGeneralError("startTime is zero. start not called")

val duration = System.currentTimeMillis() - startTime
return Duration(MILLISECONDS.toSeconds(System.currentTimeMillis() - startTime))
}
}

suspend fun measureTime(block: suspend () -> Unit) = StopWatch().run {
start()
block()
check()
}

val minutes = MILLISECONDS.toMinutes(duration)
val seconds = MILLISECONDS.toSeconds(duration) % 60
data class Duration(val seconds: Long)

// align seconds
// 3m 0s
// 2m 23s
val space = if (alignSeconds && seconds < 10)
" " else
" "
fun Duration.formatted(alignSeconds: Boolean = false): String {
val minutes = TimeUnit.SECONDS.toMinutes(seconds)
val seconds = seconds % 60

return String.format(Locale.getDefault(), "%dm$space%ds", minutes, seconds)
}
// align seconds
// 3m 0s
// 2m 23s
val space = if (alignSeconds && seconds < 10)
" " else
" "

return "${minutes}m$space${seconds}s"
}
12 changes: 0 additions & 12 deletions test_runner/src/main/kotlin/ftl/util/StopWatchMatrix.kt

This file was deleted.

2 changes: 2 additions & 0 deletions test_runner/src/test/kotlin/Debug.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@file:Suppress("InvalidPackageDeclaration")

import ftl.presentation.cli.MainCommand
import ftl.reports.startDurationMeasurement
import ftl.run.exception.withGlobalExceptionHandling
import ftl.util.disableCrashReporting
import picocli.CommandLine
Expand All @@ -18,6 +19,7 @@ fun main() {
?: "YOUR PROJECT ID"

withGlobalExceptionHandling {
startDurationMeasurement()
CommandLine(MainCommand()).execute(
// "--debug",
"firebase",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package ftl.run.status
import com.google.testing.model.TestExecution
import com.google.testing.model.TestMatrix
import ftl.args.IArgs
import ftl.util.Duration
import ftl.util.MatrixState
import ftl.util.StopWatch
import ftl.util.formatted
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
Expand All @@ -21,7 +23,8 @@ class TestMatrixStatusPrinterTest {
@Test
fun test() {
// given
val time = "time"
val expectedDuration = Duration(4)
val time = expectedDuration.formatted(alignSeconds = true)
val testMatricesIds = (0..1).map(Int::toString)
val matrices = testMatricesIds.mapIndexed { index, s ->
TestMatrix().apply {
Expand All @@ -34,7 +37,7 @@ class TestMatrixStatusPrinterTest {
every { outputStyle } returns OutputStyle.Single
}
val stopWatch = mockk<StopWatch>(relaxed = true) {
every { check(any()) } returns time
every { check() } returns expectedDuration
piotradamczyk5 marked this conversation as resolved.
Show resolved Hide resolved
}
val printExecutionStatusList = mockk<(String, List<TestExecution>?) -> Unit>(relaxed = true)
val printMatrices = TestMatrixStatusPrinter(
Expand All @@ -46,16 +49,16 @@ class TestMatrixStatusPrinterTest {
val expected = listOf(
"",
"""
time 0 FINISHED
time 1 FINISHED
$time 0 FINISHED
$time 1 FINISHED
"""
)
// when
testMatricesIds.forEachIndexed { index, _ ->
printMatrices(matrices[index])

// then
verify { stopWatch.check(true) }
verify { stopWatch.check() }
verify { printExecutionStatusList(time, matrices[index].testExecutions) }
assertEquals(expected[index], systemOutRule.log.filterMockk())
}
Expand Down
Loading