From 1b6668514a939996f4e235c23351d9f1c7698ace Mon Sep 17 00:00:00 2001 From: pawelpasterz <32893017+pawelpasterz@users.noreply.github.com> Date: Fri, 5 Mar 2021 14:29:02 +0100 Subject: [PATCH] test: Implement logic to clear LocalGcs after each test (#1661) Fixes #1578 Change description: * there are only 2 tests that require pre-uploaded files -- now they upload filed on their own (`ArgsHelperTest#assertGcsFileExists succeeds` & `TestRunnerTest#mockedAndroidTestRun gcsAndHistoryName`) * Google API provides `FakeStorageRpc` which is created with `LocalStorageHelper.getOptions()` * `FakeStorageRpc` can be cleaned/reseted only by calling `LocalStorageHelper.getOptions()` (both its hashmaps are cleared) * Above is, unfortunately, the only way to clear `FakeStorageRpc` -- storage has `reset` method but it's not exposed * The `TestStorageProvider` is introduced to wrap additional test logic * Intention behind `TestStorageProvider` is `GcStorage` should not be aware of how it is used (tests or production ) * The `TestStorageProvider` has nullable `Storage` filed. It can be cleared (set null) with `#clearStorage` * If storage is null `TestStorageProvider` will invoke `LocalStorageHelper.getOptions()` and assign reference to storage field. * `FlankTestRunner` has a custom listener that will invoke `LocalGcs#clear()` after each test run ## Test Plan > How do we know the code works? Unfortunately, there is no straightforward way to verify it since OOM error occurred only on GH Actions machines, randomly. --- .../src/main/kotlin/ftl/gc/GcStorage.kt | 19 ++++++++++++++++++- .../test/kotlin/ftl/args/ArgsHelperTest.kt | 5 +++++ .../src/test/kotlin/ftl/run/TestRunnerTest.kt | 6 ++++++ .../kotlin/ftl/test/util/FlankTestRunner.kt | 15 ++++++++++++++- .../src/test/kotlin/ftl/test/util/LocalGcs.kt | 12 ++++-------- 5 files changed, 47 insertions(+), 10 deletions(-) diff --git a/test_runner/src/main/kotlin/ftl/gc/GcStorage.kt b/test_runner/src/main/kotlin/ftl/gc/GcStorage.kt index 72b6ff7acf..4c1c5d9da1 100644 --- a/test_runner/src/main/kotlin/ftl/gc/GcStorage.kt +++ b/test_runner/src/main/kotlin/ftl/gc/GcStorage.kt @@ -51,7 +51,7 @@ object GcStorage { val storage: Storage by lazy { GoogleApiLogger.silenceComputeEngine() if (FtlConstants.useMock) { - LocalStorageHelper.getOptions().service + TestStorageProvider.storage } else { storageOptions.service } @@ -210,3 +210,20 @@ object GcStorage { private fun String.dropLeadingSlash() = drop(1) } + +object TestStorageProvider { + init { + require(FtlConstants.useMock) { "Storage provider can be used only during tests" } + } + + private var backingStorage: Storage? = null + + val storage: Storage + get() = backingStorage ?: LocalStorageHelper.getOptions().service.apply { + backingStorage = this + } + + fun clearStorage() { + backingStorage = null + } +} diff --git a/test_runner/src/test/kotlin/ftl/args/ArgsHelperTest.kt b/test_runner/src/test/kotlin/ftl/args/ArgsHelperTest.kt index 13c1d7f532..f4d8f2b878 100644 --- a/test_runner/src/test/kotlin/ftl/args/ArgsHelperTest.kt +++ b/test_runner/src/test/kotlin/ftl/args/ArgsHelperTest.kt @@ -16,6 +16,7 @@ import ftl.shard.TestMethod import ftl.shard.TestShard import ftl.shard.stringShards import ftl.test.util.FlankTestRunner +import ftl.test.util.LocalGcs import ftl.test.util.TestHelper.absolutePath import ftl.test.util.assertThrowsWithMessage import io.mockk.every @@ -76,6 +77,10 @@ class ArgsHelperTest { @Test fun `assertGcsFileExists succeeds`() { + // given + LocalGcs.uploadFileForTest("../test_projects/android/apks/app-debug.apk") + + // then assertGcsFileExists("gs://tmp_bucket_2/app-debug.apk") } diff --git a/test_runner/src/test/kotlin/ftl/run/TestRunnerTest.kt b/test_runner/src/test/kotlin/ftl/run/TestRunnerTest.kt index b2b44566df..37a2b95400 100644 --- a/test_runner/src/test/kotlin/ftl/run/TestRunnerTest.kt +++ b/test_runner/src/test/kotlin/ftl/run/TestRunnerTest.kt @@ -12,6 +12,7 @@ import ftl.args.IosArgs import ftl.http.executeWithRetry import ftl.run.common.getDownloadPath import ftl.test.util.FlankTestRunner +import ftl.test.util.LocalGcs import io.mockk.every import io.mockk.mockk import io.mockk.mockkStatic @@ -120,6 +121,11 @@ class TestRunnerTest { @Test fun `mockedAndroidTestRun gcsAndHistoryName`() { + // given + LocalGcs.uploadFileForTest("../test_projects/android/apks/app-debug.apk") + LocalGcs.uploadFileForTest("../test_projects/android/apks/app-debug-androidTest.apk") + + // then val gcsConfig = AndroidArgs.load(Paths.get("src/test/kotlin/ftl/fixtures/flank.gcs.yml")) runBlocking { gcsConfig.newTestRun() diff --git a/test_runner/src/test/kotlin/ftl/test/util/FlankTestRunner.kt b/test_runner/src/test/kotlin/ftl/test/util/FlankTestRunner.kt index 288816def3..bf1ea25ea8 100644 --- a/test_runner/src/test/kotlin/ftl/test/util/FlankTestRunner.kt +++ b/test_runner/src/test/kotlin/ftl/test/util/FlankTestRunner.kt @@ -1,6 +1,9 @@ package ftl.test.util import ftl.mock.MockServer +import org.junit.runner.Description +import org.junit.runner.notification.RunListener +import org.junit.runner.notification.RunNotifier import org.junit.runners.BlockJUnit4ClassRunner class FlankTestRunner(klass: Class<*>) : BlockJUnit4ClassRunner(klass) { @@ -10,7 +13,17 @@ class FlankTestRunner(klass: Class<*>) : BlockJUnit4ClassRunner(klass) { println("FlankTestRunner init\n") MockServer.start() - LocalGcs.uploadFiles() } } + + override fun run(notifier: RunNotifier?) { + val listener = object : RunListener() { + override fun testFinished(description: Description?) { + LocalGcs.clear() + super.testFinished(description) + } + } + notifier?.addListener(listener) + super.run(notifier) + } } diff --git a/test_runner/src/test/kotlin/ftl/test/util/LocalGcs.kt b/test_runner/src/test/kotlin/ftl/test/util/LocalGcs.kt index 8d3abd6054..061e57949b 100644 --- a/test_runner/src/test/kotlin/ftl/test/util/LocalGcs.kt +++ b/test_runner/src/test/kotlin/ftl/test/util/LocalGcs.kt @@ -2,6 +2,7 @@ package ftl.test.util import com.google.cloud.storage.BlobInfo import ftl.gc.GcStorage +import ftl.gc.TestStorageProvider import ftl.run.exception.FlankGeneralError import org.junit.Assert import java.nio.file.Files @@ -29,14 +30,9 @@ object LocalGcs { ) } - fun uploadFiles() { - val appApk = "../test_projects/android/apks/app-debug.apk" - val testApk = "../test_projects/android/apks/app-debug-androidTest.apk" - val ipaZip = "./src/test/kotlin/ftl/fixtures/tmp/ios/EarlGreyExample/EarlGreyExample.zip" - val xctestrun = "./src/test/kotlin/ftl/fixtures/tmp/ios/EarlGreyExample/EarlGreyExampleSwiftTests.xctestrun" + fun uploadFileForTest(path: String) = uploadToMockGcs(Paths.get(path)) - listOf(appApk, testApk, ipaZip, xctestrun).forEach { file -> - uploadToMockGcs(Paths.get(file)) - } + fun clear() { + TestStorageProvider.clearStorage() } }