Skip to content

Commit

Permalink
Implemented evaluating paths #336
Browse files Browse the repository at this point in the history
Fixed failing tests

Added unit tests
  • Loading branch information
sravanmedarapu authored and bootstraponline committed Nov 11, 2018
1 parent c11234b commit ed6c617
Showing 7 changed files with 153 additions and 22 deletions.
7 changes: 5 additions & 2 deletions test_runner/src/main/kotlin/ftl/args/AndroidArgs.kt
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ import ftl.android.UnsupportedVersionId
import ftl.args.ArgsHelper.assertFileExists
import ftl.args.ArgsHelper.assertGcsFileExists
import ftl.args.ArgsHelper.calculateShards
import ftl.args.ArgsHelper.evaluateFilePath
import ftl.args.ArgsHelper.getGcsBucket
import ftl.args.ArgsHelper.mergeYmlMaps
import ftl.args.ArgsHelper.yamlMapper
@@ -45,8 +46,8 @@ class AndroidArgs(
override val resultsHistoryName = gcloud.resultsHistoryName

private val androidGcloud = androidGcloudYml.gcloud
val appApk = androidGcloud.app
val testApk = androidGcloud.test
var appApk = androidGcloud.app
var testApk = androidGcloud.test
val autoGoogleLogin = androidGcloud.autoGoogleLogin
val useOrchestrator = androidGcloud.useOrchestrator
val environmentVariables = androidGcloud.environmentVariables
@@ -85,12 +86,14 @@ class AndroidArgs(
if (appApk.startsWith(FtlConstants.GCS_PREFIX)) {
assertGcsFileExists(appApk)
} else {
appApk = evaluateFilePath(appApk, "appApk")
assertFileExists(appApk, "appApk")
}

if (testApk.startsWith(FtlConstants.GCS_PREFIX)) {
assertGcsFileExists(testApk)
} else {
testApk = evaluateFilePath(testApk, "testApk")
assertFileExists(testApk, "testApk")
}

71 changes: 71 additions & 0 deletions test_runner/src/main/kotlin/ftl/args/ArgsHelper.kt
Original file line number Diff line number Diff line change
@@ -20,9 +20,18 @@ import ftl.config.FtlConstants.defaultCredentialPath
import ftl.gc.GcStorage
import ftl.util.Utils
import java.io.File
import java.io.IOException
import java.math.RoundingMode
import java.net.URI
import java.nio.file.FileVisitResult
import java.nio.file.Files
import java.nio.file.FileSystems
import java.nio.file.SimpleFileVisitor
import java.nio.file.attribute.BasicFileAttributes
import java.nio.file.Path
import java.nio.file.Paths
import java.util.HashSet
import java.util.regex.Pattern

object ArgsHelper {

@@ -45,6 +54,19 @@ object ArgsHelper {
}
}

fun evaluateFilePath(fileRegEx: String, name: String): String {
var file = fileRegEx.trim().replaceFirst("~", System.getProperty("user.home"))
file = substituteEnvVars(file)
val searchDirectoryPath = getSearchDirectoryPath(file)
val filePaths = getAbsoluteFilePaths(searchDirectoryPath, file)
if (filePaths.size > 1) {
Utils.fatalError("$name multiple files found with expression: `$fileRegEx`: $filePaths")
} else if (filePaths.isEmpty()) {
Utils.fatalError("'$fileRegEx' $name doesn't exist")
}
return filePaths[0].toAbsolutePath().toString()
}

fun assertGcsFileExists(uri: String) {
if (!uri.startsWith(GCS_PREFIX)) {
throw IllegalArgumentException("must start with $GCS_PREFIX uri: $uri")
@@ -150,4 +172,53 @@ object ArgsHelper {
// Allow users control over projectId by checking using Google's logic first before falling back to JSON.
return ServiceOptions.getDefaultProjectId() ?: serviceAccountProjectId()
}

private fun getSearchDirectoryPath(path: String): String {
var searchDirectoryPath = String()
val pattern = "([^*]*/)"
val matcher = Pattern.compile(pattern).matcher(path)
if (matcher.find()) {
searchDirectoryPath = matcher.group(1)
}
return searchDirectoryPath
}

private fun substituteEnvVars(text: String): String {
val sb = StringBuffer()
// https://stackoverflow.com/a/2821201/2450315
val pattern = "\\$([a-zA-Z_]{1,}[a-zA-Z0-9_]{0,})"
val matcher = Pattern.compile(pattern).matcher(text)
while (matcher.find()) {
val varname = matcher.group(1)
val envValue: String = System.getenv(varname) ?: ""
matcher.appendReplacement(sb, envValue)
}
matcher.appendTail(sb)
return sb.toString()
}

private fun getAbsoluteFilePaths(searchDir: String, globPath: String): List<Path> {
val maxDepth = if (globPath.contains("/*")) Integer.MAX_VALUE else 1
val glob = "glob:$globPath"
val paths = ArrayList<Path>()
val pathMatcher = FileSystems.getDefault().getPathMatcher(glob)

Files.walkFileTree(Paths.get(searchDir), HashSet(), maxDepth, object : SimpleFileVisitor<Path>() {

@Throws(IOException::class)
override fun visitFile(path: Path, attrs: BasicFileAttributes): FileVisitResult {
if (pathMatcher.matches(path)) {
paths.add(path)
}
return FileVisitResult.CONTINUE
}

@Throws(IOException::class)
override fun visitFileFailed(file: Path, exc: IOException?): FileVisitResult {
Utils.fatalError("'$file' doesn't exist")
return FileVisitResult.CONTINUE
}
})
return paths
}
}
7 changes: 5 additions & 2 deletions test_runner/src/main/kotlin/ftl/args/IosArgs.kt
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ package ftl.args

import ftl.args.ArgsHelper.assertFileExists
import ftl.args.ArgsHelper.assertGcsFileExists
import ftl.args.ArgsHelper.evaluateFilePath
import ftl.args.ArgsHelper.mergeYmlMaps
import ftl.args.ArgsHelper.validateTestMethods
import ftl.args.ArgsHelper.yamlMapper
@@ -36,8 +37,8 @@ class IosArgs(
override val resultsHistoryName = gcloud.resultsHistoryName

private val iosGcloud = iosGcloudYml.gcloud
val xctestrunZip = iosGcloud.test
val xctestrunFile = iosGcloud.xctestrunFile
var xctestrunZip = iosGcloud.test
var xctestrunFile = iosGcloud.xctestrunFile
val xcodeVersion = iosGcloud.xcodeVersion
val devices = iosGcloud.device

@@ -70,8 +71,10 @@ class IosArgs(
if (xctestrunZip.startsWith(FtlConstants.GCS_PREFIX)) {
assertGcsFileExists(xctestrunZip)
} else {
xctestrunZip = evaluateFilePath(xctestrunZip, "xctestrunZip")
assertFileExists(xctestrunZip, "xctestrunZip")
}
xctestrunFile = evaluateFilePath(xctestrunFile, "xctestrunFile")
assertFileExists(xctestrunFile, "xctestrunFile")

devices.forEach { device -> assertDeviceSupported(device) }
7 changes: 5 additions & 2 deletions test_runner/src/test/kotlin/ftl/args/AndroidArgsFileTest.kt
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@ import org.junit.contrib.java.lang.system.SystemErrRule
import org.junit.contrib.java.lang.system.SystemOutRule
import org.junit.rules.ExpectedException
import org.junit.runner.RunWith
import java.io.File

@RunWith(FlankTestRunner::class)
class AndroidArgsFileTest {
@@ -42,6 +43,8 @@ class AndroidArgsFileTest {
private val testName = "class com.example.app.ExampleUiTest#testPasses"
private val directoryToPull = "/sdcard/screenshots"

private val appApkAbsolutePath = File(appApkLocal).absolutePath
private val testApkAbsolutePath = File(testApkLocal).absolutePath
// NOTE: Change working dir to '%MODULE_WORKING_DIR%' in IntelliJ to match gradle for this test to pass.
@Test
fun localConfigLoadsSuccessfully() {
@@ -58,10 +61,10 @@ class AndroidArgsFileTest {
private fun checkConfig(args: AndroidArgs, local: Boolean) {

with(args) {
if (local) assert(getString(testApk), testApkLocal)
if (local) assert(getString(testApk), getString(testApkAbsolutePath))
else assert(testApk, testApkGcs)

if (local) assert(getString(appApk), appApkLocal)
if (local) assert(getString(appApk), getString(appApkAbsolutePath))
else assert(appApk, appApkGcs)

assert(autoGoogleLogin, true)
19 changes: 11 additions & 8 deletions test_runner/src/test/kotlin/ftl/args/AndroidArgsTest.kt
Original file line number Diff line number Diff line change
@@ -8,13 +8,16 @@ import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
import org.junit.runner.RunWith
import java.io.File

@RunWith(FlankTestRunner::class)
class AndroidArgsTest {
private val empty = emptyList<String>()
private val appApk = "../test_app/apks/app-debug.apk"
private val testApk = "../test_app/apks/app-debug-androidTest.apk"
private val testErrorApk = "../test_app/apks/error-androidTest.apk"
private val appApkAbsolutePath = File(appApk).absolutePath
private val testApkAbsolutePath = File(testApk).absolutePath

private val androidNonDefault = """
gcloud:
@@ -123,8 +126,8 @@ class AndroidArgsTest {
assert(resultsHistoryName ?: "", "android-history")

// AndroidGcloudYml
assert(appApk, appApk)
assert(testApk, testApk)
assert(appApk, appApkAbsolutePath)
assert(testApk, testApkAbsolutePath)
assert(autoGoogleLogin, false)
assert(useOrchestrator, false)
assert(environmentVariables, linkedMapOf("clearPackageData" to "true", "randomEnvVar" to "false"))
@@ -170,8 +173,8 @@ AndroidArgs
project: projectFoo
results-history-name: android-history
# Android gcloud
app: ../test_app/apks/app-debug.apk
test: ../test_app/apks/app-debug-androidTest.apk
app: $appApkAbsolutePath
test: $testApkAbsolutePath
auto-google-login: false
use-orchestrator: false
environment-variables:
@@ -223,8 +226,8 @@ AndroidArgs
assert(projectId, "mockProjectId")

// AndroidGcloudYml
assert(appApk, appApk)
assert(testApk, testApk)
assert(appApk, appApkAbsolutePath)
assert(testApk, testApkAbsolutePath)
assert(autoGoogleLogin, true)
assert(useOrchestrator, true)
assert(environmentVariables, emptyMap<String, String>())
@@ -272,7 +275,7 @@ AndroidArgs
"""
)

assertThat(androidArgs.appApk).isEqualTo(appApk)
assertThat(androidArgs.testApk).isEqualTo(testApk)
assertThat(androidArgs.appApk).isEqualTo(appApkAbsolutePath)
assertThat(androidArgs.testApk).isEqualTo(testApkAbsolutePath)
}
}
45 changes: 45 additions & 0 deletions test_runner/src/test/kotlin/ftl/args/ArgsHelperTest.kt
Original file line number Diff line number Diff line change
@@ -15,6 +15,9 @@ import org.junit.Test
import org.junit.contrib.java.lang.system.SystemErrRule
import org.junit.rules.ExpectedException
import org.junit.runner.RunWith
import java.io.File
import org.junit.contrib.java.lang.system.EnvironmentVariables
import java.lang.RuntimeException

@RunWith(FlankTestRunner::class)
class ArgsHelperTest {
@@ -27,6 +30,9 @@ class ArgsHelperTest {
@JvmField
val systemErrRule = SystemErrRule().muteForSuccessfulTests()!!

@get:Rule
val environmentVariables = EnvironmentVariables()

@Test
fun mergeYmlMaps_succeeds() {
val merged = mergeYmlMaps(GcloudYml, IosGcloudYml)
@@ -161,4 +167,43 @@ class ArgsHelperTest {
assertThat(ArgsHelper.getDefaultProjectId())
.isEqualTo("mockProjectId")
}

@Test
fun evaluateBlobInFilePath() {
val testApkRelativePath = "../test_app/apks/app-debug-androidTest.apk"
val testApkBlobPath = "../test_app/**/app-debug-*.apk"

assertThat(File(testApkRelativePath).absolutePath)
.isEqualTo(ArgsHelper.evaluateFilePath(testApkBlobPath, "test"))
}

@Test
fun evaluateTildeInFilePath() {
val testApkPath = "~/flank_test_app/random.xctestrun"
val file = File(testApkPath.replaceFirst("~", System.getProperty("user.home")))
file.getParentFile().mkdirs()
file.createNewFile()

assertThat(file.absolutePath)
.isEqualTo(ArgsHelper.evaluateFilePath(testApkPath, "xctestrun-file"))
}

@Test
fun evaluateEnvVarInFilePath() {
environmentVariables.set("TEST_APK_DIR", "test_app/apks")
val testApkPath = "../\$TEST_APK_DIR/app-debug-androidTest.apk"
val expectedPath = File("../test_app/apks/app-debug-androidTest.apk").absolutePath
val file = File(testApkPath.replaceFirst("~", System.getProperty("user.home")))
file.getParentFile().mkdirs()
file.createNewFile()

assertThat(expectedPath)
.isEqualTo(ArgsHelper.evaluateFilePath(testApkPath, "test"))
}

@Test(expected = RuntimeException::class)
fun evaluateInvalidFilePath() {
val testApkPath = "~/flank_test_app/invalid_path/app-debug-*.xctestrun"
ArgsHelper.evaluateFilePath(testApkPath, "test")
}
}
19 changes: 11 additions & 8 deletions test_runner/src/test/kotlin/ftl/args/IosArgsTest.kt
Original file line number Diff line number Diff line change
@@ -14,13 +14,16 @@ import org.junit.Test
import org.junit.contrib.java.lang.system.SystemErrRule
import org.junit.rules.ExpectedException
import org.junit.runner.RunWith
import java.io.File

@RunWith(FlankTestRunner::class)
class IosArgsTest {
private val empty = emptyList<String>()
private val testPath = "./src/test/kotlin/ftl/fixtures/tmp/EarlGreyExample.zip"
private val xctestrunFile =
"./src/test/kotlin/ftl/fixtures/tmp/EarlGreyExampleSwiftTests_iphoneos12.1-arm64e.xctestrun"
val xctestrunFileAbsolutePath = File(xctestrunFile).absolutePath
val testAbsolutePath = File(testPath).absolutePath
private val iosNonDefault = """
gcloud:
results-bucket: mockBucket
@@ -101,8 +104,8 @@ class IosArgsTest {
assert(resultsHistoryName ?: "", "ios-history")

// IosGcloudYml
assert(xctestrunZip, testPath)
assert(xctestrunFile, xctestrunFile)
assert(xctestrunZip, testAbsolutePath)
assert(xctestrunFile, xctestrunFileAbsolutePath)
val device = Device("iphone8", "11.2", "c", "d")
assert(xcodeVersion ?: "", "9.2")
assert(devices, listOf(device, device))
@@ -131,8 +134,8 @@ IosArgs
project: projectFoo
results-history-name: ios-history
# iOS gcloud
test: $testPath
xctestrun-file: $xctestrunFile
test: $testAbsolutePath
xctestrun-file: $xctestrunFileAbsolutePath
xcode-version: 9.2
device:
- model: iphone8
@@ -177,8 +180,8 @@ IosArgs
assert(projectId, "mockProjectId")

// IosGcloudYml
assert(xctestrunZip, testPath)
assert(xctestrunFile, xctestrunFile)
assert(xctestrunZip, testAbsolutePath)
assert(xctestrunFile, xctestrunFileAbsolutePath)
assert(devices, listOf(Device("iphone8", "11.2")))

// FlankYml
@@ -224,8 +227,8 @@ IosArgs
)

with(iosArgs) {
assertThat(xctestrunZip).isEqualTo(testPath)
assertThat(xctestrunFile).isEqualTo(xctestrunFile)
assertThat(xctestrunZip).isEqualTo(testAbsolutePath)
assertThat(xctestrunFile).isEqualTo(xctestrunFileAbsolutePath)
}
}
}

0 comments on commit ed6c617

Please sign in to comment.