Skip to content

Commit

Permalink
test: Implement logic to clear LocalGcs after each test (#1661)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
pawelpasterz authored Mar 5, 2021
1 parent fe72d53 commit 1b66685
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 10 deletions.
19 changes: 18 additions & 1 deletion test_runner/src/main/kotlin/ftl/gc/GcStorage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ object GcStorage {
val storage: Storage by lazy {
GoogleApiLogger.silenceComputeEngine()
if (FtlConstants.useMock) {
LocalStorageHelper.getOptions().service
TestStorageProvider.storage
} else {
storageOptions.service
}
Expand Down Expand Up @@ -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
}
}
5 changes: 5 additions & 0 deletions test_runner/src/test/kotlin/ftl/args/ArgsHelperTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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")
}

Expand Down
6 changes: 6 additions & 0 deletions test_runner/src/test/kotlin/ftl/run/TestRunnerTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down
15 changes: 14 additions & 1 deletion test_runner/src/test/kotlin/ftl/test/util/FlankTestRunner.kt
Original file line number Diff line number Diff line change
@@ -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) {
Expand All @@ -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)
}
}
12 changes: 4 additions & 8 deletions test_runner/src/test/kotlin/ftl/test/util/LocalGcs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
}
}

0 comments on commit 1b66685

Please sign in to comment.