diff --git a/test_runner/src/main/kotlin/com/google/api/client/http/GoogleApiLogger.kt b/test_runner/src/main/kotlin/com/google/api/client/http/GoogleApiLogger.kt index e4978e457d..87702e1776 100644 --- a/test_runner/src/main/kotlin/com/google/api/client/http/GoogleApiLogger.kt +++ b/test_runner/src/main/kotlin/com/google/api/client/http/GoogleApiLogger.kt @@ -1,10 +1,12 @@ package com.google.api.client.http import com.google.auth.oauth2.ComputeEngineCredentials +import ftl.log.FlankLogger import java.util.logging.Level import java.util.logging.Logger import java.util.logging.SimpleFormatter import java.util.logging.StreamHandler +import kotlin.properties.Delegates // Used to enable cURL logging of the Java client API requests. // @@ -12,8 +14,13 @@ import java.util.logging.StreamHandler // // gcloud alpha firebase test ios models list --log-http // -object GoogleApiLogger { - fun logAllToStdout() { +object GoogleApiLogger : FlankLogger { + + override var isEnabled: Boolean by Delegates.observable(false) { _, _, enable -> + if (enable) logAllToStdout() + } + + private fun logAllToStdout() { val logger = HttpTransport.LOGGER logger.level = Level.ALL diff --git a/test_runner/src/main/kotlin/ftl/Main.kt b/test_runner/src/main/kotlin/ftl/Main.kt index 31c648a218..544e470a40 100644 --- a/test_runner/src/main/kotlin/ftl/Main.kt +++ b/test_runner/src/main/kotlin/ftl/Main.kt @@ -6,6 +6,7 @@ import ftl.cli.firebase.CancelCommand import ftl.cli.firebase.RefreshCommand import ftl.cli.firebase.test.AndroidCommand import ftl.cli.firebase.test.IosCommand +import ftl.log.setDebugLogging import ftl.util.Utils.readRevision import ftl.util.Utils.readVersion import picocli.CommandLine @@ -35,6 +36,12 @@ class Main : Runnable { @CommandLine.Option(names = ["-v", "--version"], description = ["Prints the version"]) private var printVersion = false + @CommandLine.Option( + names = ["--debug"], + description = ["Enables debug logging"] + ) + fun debug(enabled: Boolean) = setDebugLogging(enabled) + companion object { @JvmStatic fun main(args: Array) { diff --git a/test_runner/src/main/kotlin/ftl/args/AndroidArgs.kt b/test_runner/src/main/kotlin/ftl/args/AndroidArgs.kt index e5f4c9098f..3a5cece0fd 100644 --- a/test_runner/src/main/kotlin/ftl/args/AndroidArgs.kt +++ b/test_runner/src/main/kotlin/ftl/args/AndroidArgs.kt @@ -72,7 +72,6 @@ class AndroidArgs( override val disableSharding = cli?.disableSharding ?: flank.disableSharding override val project = cli?.project ?: flank.project override val localResultDir = cli?.localResultDir ?: flank.localResultDir - override val debug = cli?.debug ?: flank.debug private val androidFlank = androidFlankYml.flank val additionalAppTestApks = cli?.additionalAppTestApks ?: androidFlank.additionalAppTestApks diff --git a/test_runner/src/main/kotlin/ftl/args/IArgs.kt b/test_runner/src/main/kotlin/ftl/args/IArgs.kt index 5684babbc4..48c3583610 100644 --- a/test_runner/src/main/kotlin/ftl/args/IArgs.kt +++ b/test_runner/src/main/kotlin/ftl/args/IArgs.kt @@ -27,7 +27,6 @@ interface IArgs { val filesToDownload: List val disableSharding: Boolean val localResultDir: String - val debug: Boolean fun useLocalResultDir() = localResultDir != FlankYmlParams.defaultLocalResultDir diff --git a/test_runner/src/main/kotlin/ftl/args/IosArgs.kt b/test_runner/src/main/kotlin/ftl/args/IosArgs.kt index 35ceadaf38..cb3cf9416d 100644 --- a/test_runner/src/main/kotlin/ftl/args/IosArgs.kt +++ b/test_runner/src/main/kotlin/ftl/args/IosArgs.kt @@ -60,7 +60,6 @@ class IosArgs( override val disableSharding = cli?.disableSharding ?: flank.disableSharding override val project = cli?.project ?: flank.project override val localResultDir = cli?.localResultsDir ?: flank.localResultDir - override val debug = cli?.debug ?: flank.debug private val iosFlank = iosFlankYml.flank val testTargets = cli?.testTargets ?: iosFlank.testTargets.filterNotNull() diff --git a/test_runner/src/main/kotlin/ftl/args/yml/FlankYml.kt b/test_runner/src/main/kotlin/ftl/args/yml/FlankYml.kt index a9f0ec4d9d..3103c83ad0 100644 --- a/test_runner/src/main/kotlin/ftl/args/yml/FlankYml.kt +++ b/test_runner/src/main/kotlin/ftl/args/yml/FlankYml.kt @@ -34,10 +34,7 @@ class FlankYmlParams( val project: String = ArgsHelper.getDefaultProjectId() ?: "", @field:JsonProperty("local-result-dir") - val localResultDir: String = defaultLocalResultDir, - - @field:JsonProperty("debug") - val debug: Boolean = false + val localResultDir: String = defaultLocalResultDir ) { companion object : IYmlKeys { override val keys = listOf( diff --git a/test_runner/src/main/kotlin/ftl/cli/firebase/test/android/AndroidRunCommand.kt b/test_runner/src/main/kotlin/ftl/cli/firebase/test/android/AndroidRunCommand.kt index 4983acc47b..89db2b15a9 100644 --- a/test_runner/src/main/kotlin/ftl/cli/firebase/test/android/AndroidRunCommand.kt +++ b/test_runner/src/main/kotlin/ftl/cli/firebase/test/android/AndroidRunCommand.kt @@ -68,12 +68,6 @@ class AndroidRunCommand : Runnable { @Option(names = ["--dry"], description = ["Dry run on mock server"]) var dryRun: Boolean = false - @Option( - names = ["--debug"], - description = ["Enable debug logging. Will print additional debugging output to console if enabled"] - ) - var debug: Boolean? = null - // Flank specific @Option( diff --git a/test_runner/src/main/kotlin/ftl/cli/firebase/test/ios/IosRunCommand.kt b/test_runner/src/main/kotlin/ftl/cli/firebase/test/ios/IosRunCommand.kt index b235144dbe..1140c7d727 100644 --- a/test_runner/src/main/kotlin/ftl/cli/firebase/test/ios/IosRunCommand.kt +++ b/test_runner/src/main/kotlin/ftl/cli/firebase/test/ios/IosRunCommand.kt @@ -61,12 +61,6 @@ class IosRunCommand : Runnable { @Option(names = ["--dry"], description = ["Dry run on mock server"]) var dryRun: Boolean = false - @Option( - names = ["--debug"], - description = ["Enable debug logging. Will print additional debugging output to console if enabled"] - ) - var debug: Boolean? = null - // Flank specific @Option( diff --git a/test_runner/src/main/kotlin/ftl/config/FtlConstants.kt b/test_runner/src/main/kotlin/ftl/config/FtlConstants.kt index 1eb5f34d2b..4d19c6b0de 100644 --- a/test_runner/src/main/kotlin/ftl/config/FtlConstants.kt +++ b/test_runner/src/main/kotlin/ftl/config/FtlConstants.kt @@ -1,7 +1,5 @@ package ftl.config -import ch.qos.logback.classic.Level -import ch.qos.logback.classic.Logger import com.bugsnag.Bugsnag import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport import com.google.api.client.googleapis.util.Utils @@ -23,7 +21,6 @@ import java.io.IOException import java.nio.file.Path import java.nio.file.Paths import java.util.Date -import org.slf4j.LoggerFactory object FtlConstants { var useMock = false @@ -60,7 +57,6 @@ object FtlConstants { init { bugsnag.setAppVersion(readRevision()) - (LoggerFactory.getLogger(Bugsnag::class.java) as Logger).level = Level.OFF } val httpTransport: NetHttpTransport by lazy { diff --git a/test_runner/src/main/kotlin/ftl/gc/UserAuth.kt b/test_runner/src/main/kotlin/ftl/gc/UserAuth.kt index 599338dd1e..41ebb27c13 100644 --- a/test_runner/src/main/kotlin/ftl/gc/UserAuth.kt +++ b/test_runner/src/main/kotlin/ftl/gc/UserAuth.kt @@ -1,7 +1,5 @@ package ftl.gc -import ch.qos.logback.classic.Level -import ch.qos.logback.classic.Logger import com.google.auth.oauth2.ClientId import com.google.auth.oauth2.MemoryTokensStorage import com.google.auth.oauth2.UserAuthorizer @@ -23,13 +21,12 @@ import java.nio.file.Paths import java.util.concurrent.TimeUnit import kotlinx.coroutines.delay import kotlinx.coroutines.runBlocking -import org.slf4j.LoggerFactory class UserAuth { companion object { private val home = System.getProperty("user.home")!! - private val dotFlank = Paths.get(home, ".flank/")!! + private val dotFlank = Paths.get(home, ".flank/") val userToken: Path = Paths.get(dotFlank.toString(), "UserToken") fun exists() = userToken.toFile().exists() @@ -40,13 +37,6 @@ class UserAuth { } } - // Silence Jetty logging. - private val logger = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME) as Logger - - init { - logger.level = Level.OFF - } - private var waitingForUserAuth = true private val server = embeddedServer(Netty, 8085) { diff --git a/test_runner/src/main/kotlin/ftl/log/FlankLogger.kt b/test_runner/src/main/kotlin/ftl/log/FlankLogger.kt new file mode 100644 index 0000000000..294a20ede7 --- /dev/null +++ b/test_runner/src/main/kotlin/ftl/log/FlankLogger.kt @@ -0,0 +1,5 @@ +package ftl.log + +interface FlankLogger { + var isEnabled: Boolean +} diff --git a/test_runner/src/main/kotlin/ftl/log/LogbackLogger.kt b/test_runner/src/main/kotlin/ftl/log/LogbackLogger.kt new file mode 100644 index 0000000000..1933b1694a --- /dev/null +++ b/test_runner/src/main/kotlin/ftl/log/LogbackLogger.kt @@ -0,0 +1,20 @@ +package ftl.log + +import ch.qos.logback.classic.Level +import ch.qos.logback.classic.Logger +import org.slf4j.LoggerFactory.getLogger +import kotlin.properties.Delegates + +sealed class LogbackLogger(private val logger: Logger) : FlankLogger { + + constructor(logger: Any) : this(logger as Logger) + + override var isEnabled: Boolean by Delegates.observable(false) { _, _, enable -> + logger.level = if (enable) + Level.ALL else + Level.OFF + } + + object Root : LogbackLogger(getLogger(Logger.ROOT_LOGGER_NAME)) + object Bugsnag : LogbackLogger(getLogger(Bugsnag::class.java)) +} diff --git a/test_runner/src/main/kotlin/ftl/log/Loggers.kt b/test_runner/src/main/kotlin/ftl/log/Loggers.kt new file mode 100644 index 0000000000..bc830c57bc --- /dev/null +++ b/test_runner/src/main/kotlin/ftl/log/Loggers.kt @@ -0,0 +1,13 @@ +package ftl.log + +import com.google.api.client.http.GoogleApiLogger + +private val LOGGERS = listOf( + LogbackLogger.Root, + LogbackLogger.Bugsnag, + GoogleApiLogger +) + +fun setDebugLogging(enable: Boolean) = LOGGERS.forEach { logger -> + logger.isEnabled = enable +} diff --git a/test_runner/src/main/kotlin/ftl/mock/MockServer.kt b/test_runner/src/main/kotlin/ftl/mock/MockServer.kt index fbd8b0a7f7..fc1e16cd82 100644 --- a/test_runner/src/main/kotlin/ftl/mock/MockServer.kt +++ b/test_runner/src/main/kotlin/ftl/mock/MockServer.kt @@ -1,7 +1,5 @@ package ftl.mock -import ch.qos.logback.classic.Level -import ch.qos.logback.classic.Logger import com.google.api.services.testing.model.AndroidDevice import com.google.api.services.testing.model.AndroidDeviceCatalog import com.google.api.services.testing.model.Environment @@ -27,6 +25,7 @@ import com.google.gson.GsonBuilder import com.google.gson.LongSerializationPolicy import ftl.config.FtlConstants import ftl.config.FtlConstants.JSON_FACTORY +import ftl.log.LogbackLogger import ftl.util.Bash import ftl.util.StepOutcome.failure import ftl.util.StepOutcome.inconclusive @@ -47,20 +46,14 @@ import io.ktor.server.netty.Netty import java.nio.file.Files import java.nio.file.Paths import java.util.concurrent.atomic.AtomicInteger -import org.slf4j.LoggerFactory.getLogger import java.net.BindException object MockServer { private val matrixIdCounter: AtomicInteger = AtomicInteger(0) const val port = 8080 - private val logger = getLogger(Logger.ROOT_LOGGER_NAME) as Logger private var isStarted: Boolean = false - init { - logger.level = Level.OFF - } - private inline fun loadCatalog(fileName: String): T { val jsonPath = Paths.get("./src/test/kotlin/ftl/fixtures/$fileName") if (!jsonPath.toFile().exists()) throw RuntimeException("Path doesn't exist: $fileName") @@ -246,6 +239,9 @@ object MockServer { fun start() { if (isStarted) return + val loggingEnabled = LogbackLogger.Root.isEnabled + // Disable mock server initialization logs + LogbackLogger.Root.isEnabled = false val server = application try { server.start(wait = false) @@ -256,6 +252,7 @@ object MockServer { Thread.sleep(2000) server.start(wait = false) } + LogbackLogger.Root.isEnabled = loggingEnabled isStarted = true FtlConstants.useMock = true TestArtifact.checkFixtures diff --git a/test_runner/src/test/kotlin/Debug.kt b/test_runner/src/test/kotlin/Debug.kt index ec50c803e9..a796254ee2 100644 --- a/test_runner/src/test/kotlin/Debug.kt +++ b/test_runner/src/test/kotlin/Debug.kt @@ -9,13 +9,14 @@ fun main() { // run "gradle check" to generate required fixtures val projectId = System.getenv("FLANK_PROJECT_ID") ?: "YOUR PROJECT ID" - val quantity = "multiple" + val quantity = "single" val type = "success" CommandLine(Main()).execute( + "--debug", "firebase", "test", "android", "run", - "--dry", +// "--dry", "-c=src/test/kotlin/ftl/fixtures/test_app_cases/flank-$quantity-$type.yml", "--project=$projectId" ) diff --git a/test_runner/src/test/kotlin/ftl/MainTest.kt b/test_runner/src/test/kotlin/ftl/MainTest.kt index 88869b3fca..56c4fca117 100644 --- a/test_runner/src/test/kotlin/ftl/MainTest.kt +++ b/test_runner/src/test/kotlin/ftl/MainTest.kt @@ -24,7 +24,8 @@ class MainTest { private fun assertMainHelpStrings(output: String) { assertThat(output.normalizeLineEnding()).contains( "flank.jar\n" + - " [-v] [COMMAND]\n" + + " [-v] [--debug] [COMMAND]\n" + + " --debug Enables debug logging\n" + " -v, --version Prints the version\n" + "Commands:\n" + " firebase\n" + @@ -40,11 +41,26 @@ class MainTest { return systemOutRule.log.normalizeLineEnding() + systemErrRule.log.normalizeLineEnding() } + private fun unknownOption(option: String) = "Unknown option: '$option'" + @Test - fun mainCLIVersionCommand() { + fun mainCLIVersionOption() { + val option = "-v" assertThat( - runCommand("-v") - ).isNotEmpty() + runCommand(option) + ).doesNotContain( + unknownOption(option) + ) + } + + @Test + fun mainCLIDebugOption() { + val option = "--debug" + assertThat( + runCommand(option) + ).doesNotContain( + unknownOption(option) + ) } @Test @@ -54,8 +70,9 @@ class MainTest { @Test fun mainCLIErrorsOnUnknownFlag() { - val output = runCommand("-unknown-flag") - assertThat(output).contains("Unknown option: '-unknown-flag'") + val option = "-unknown-flag" + val output = runCommand(option) + assertThat(output).contains(unknownOption(option)) assertMainHelpStrings(output) }