Skip to content

Commit

Permalink
fix(core): unify FileManager logic for screenshot file with generic l…
Browse files Browse the repository at this point in the history
…ogic
  • Loading branch information
Malinskiy committed Feb 4, 2024
1 parent c4e09e6 commit 6faa9c5
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 31 deletions.
50 changes: 27 additions & 23 deletions core/src/main/kotlin/com/malinskiy/marathon/io/FileManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,26 @@ import java.util.UUID
class FileManager(private val maxPath: Int, private val maxFilename: Int, private val output: File) {
val log = MarathonLogging.logger("FileManager")

fun createFile(fileType: FileType, pool: DevicePoolId, device: DeviceInfo, test: Test? = null, testBatchId: String? = null): File {
fun createFile(
fileType: FileType,
pool: DevicePoolId,
device: DeviceInfo,
test: Test? = null,
testBatchId: String? = null,
id: String? = null
): File {
val directory = when {
test != null || testBatchId != null -> createDirectory(fileType, pool, device)
else -> createDirectory(fileType, pool)
}
val filename = when {
test != null -> createTestFilename(test, fileType, testBatchId)
testBatchId != null -> createBatchFilename(testBatchId, fileType)
else -> createDeviceFilename(device, fileType)
test != null -> createTestFilename(test, fileType, testBatchId, id = id)
testBatchId != null -> createBatchFilename(testBatchId, fileType, id = id)
else -> createDeviceFilename(device, fileType, id = id)
}
return createFile(directory, filename)
}

fun createScreenshotFile(extension: String, pool: DevicePoolId, device: DeviceInfo, test: Test, testBatchId: String): File {
val directory = createDirectory(FileType.SCREENSHOT, pool, device)
val filename =
createTestFilename(
test,
FileType.SCREENSHOT,
testBatchId = null,
extension,
UUID.randomUUID().toString()
)
return createFile(directory, filename)
}

fun createFolder(folderType: FolderType, pool: DevicePoolId? = null, device: DeviceInfo? = null): File {
var path = get(output.absolutePath, folderType.dir)
if (pool != null) {
Expand All @@ -57,8 +51,10 @@ class FileManager(private val maxPath: Int, private val maxFilename: Int, privat
val maybeTooLongPath = path.toFile()
path = if (maxPath > 0 && maybeTooLongPath.absolutePath.length > maxPath) {
val trimmed = maybeTooLongPath.absolutePath.take(maxPath)
log.error { "Directory path length cannot exceed $maxPath characters and has been trimmed from $maybeTooLongPath to $trimmed and can create a conflict. " +
"This happened because the combination of file path, pool name and device serial is too long." }
log.error {
"Directory path length cannot exceed $maxPath characters and has been trimmed from $maybeTooLongPath to $trimmed and can create a conflict. " +

Check warning on line 55 in core/src/main/kotlin/com/malinskiy/marathon/io/FileManager.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/kotlin/com/malinskiy/marathon/io/FileManager.kt#L53-L55

Added lines #L53 - L55 were not covered by tests
"This happened because the combination of file path, pool name and device serial is too long."
}
File(trimmed)

Check warning on line 58 in core/src/main/kotlin/com/malinskiy/marathon/io/FileManager.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/kotlin/com/malinskiy/marathon/io/FileManager.kt#L58

Added line #L58 was not covered by tests
} else {
maybeTooLongPath
Expand Down Expand Up @@ -98,17 +94,22 @@ class FileManager(private val maxPath: Int, private val maxFilename: Int, privat
val maybeTooLongPath = File(directory.toFile(), trimmedFilename)
return if (maxPath > 0 && maybeTooLongPath.absolutePath.length > maxPath) {
val trimmed = maybeTooLongPath.absolutePath.substring(0 until maxPath)
log.error { "File path length cannot exceed $maxPath characters and has been trimmed from $maybeTooLongPath to $trimmed and can create a conflict. " +
"This happened because the combination of file path, test class name, and test name is too long." }
log.error {
"File path length cannot exceed $maxPath characters and has been trimmed from $maybeTooLongPath to $trimmed and can create a conflict. " +
"This happened because the combination of file path, test class name, and test name is too long."
}
File(trimmed)
} else {
maybeTooLongPath
}
}

private fun createBatchFilename(testBatchId: String, fileType: FileType): String {
private fun createBatchFilename(testBatchId: String, fileType: FileType, id: String? = null): String {

Check warning on line 107 in core/src/main/kotlin/com/malinskiy/marathon/io/FileManager.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/kotlin/com/malinskiy/marathon/io/FileManager.kt#L107

Added line #L107 was not covered by tests
return StringBuilder().apply {
append(testBatchId)
if (id != null) {
append("-$id")

Check warning on line 111 in core/src/main/kotlin/com/malinskiy/marathon/io/FileManager.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/kotlin/com/malinskiy/marathon/io/FileManager.kt#L111

Added line #L111 was not covered by tests
}
if (fileType.suffix.isNotEmpty()) {
append(".$testBatchId")
}
Expand Down Expand Up @@ -139,9 +140,12 @@ class FileManager(private val maxPath: Int, private val maxFilename: Int, privat
return "$testName$testSuffix"
}

private fun createDeviceFilename(device: DeviceInfo, fileType: FileType): String {
private fun createDeviceFilename(device: DeviceInfo, fileType: FileType, id: String? = null): String {

Check warning on line 143 in core/src/main/kotlin/com/malinskiy/marathon/io/FileManager.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/kotlin/com/malinskiy/marathon/io/FileManager.kt#L143

Added line #L143 was not covered by tests
return StringBuilder().apply {
append(device.safeSerialNumber)
if (id != null) {
append("-$id")

Check warning on line 147 in core/src/main/kotlin/com/malinskiy/marathon/io/FileManager.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/kotlin/com/malinskiy/marathon/io/FileManager.kt#L147

Added line #L147 was not covered by tests
}
if (fileType.suffix.isNotEmpty()) {
append(".${fileType.suffix}")
}
Expand Down
3 changes: 3 additions & 0 deletions core/src/main/kotlin/com/malinskiy/marathon/io/FileType.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ enum class FileType(val dir: String, val suffix: String) {
VIDEO("video", "mp4"),
SCREENSHOT("screenshot", "gif"),
SCREENSHOT_PNG("screenshot", "png"),
SCREENSHOT_JPG("screenshot", "jpg"),
SCREENSHOT_WEBP("screenshot", "jpg"),
SCREENSHOT_GIF("screenshot", "jpg"),
XCTESTRUN("xctestrun", "xctestrun"),
BILL("bill", "json"),
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,25 @@ class FileManagerTest {
file.name shouldBeEqualTo "127.0.0.1-5037-emulator-5554.log"
}

@Test
fun testScreenshotfile() {
val fileManager = FileManager(0, 255, output)
val file = fileManager.createFile(
FileType.SCREENSHOT_PNG, poolId, DeviceInfo(
operatingSystem = OperatingSystem("23"),
serialNumber = "127.0.0.1:5037:emulator-5554",
model = "Android SDK built for x86",
manufacturer = "unknown",
networkState = NetworkState.CONNECTED,
deviceFeatures = listOf(DeviceFeature.SCREENSHOT, DeviceFeature.VIDEO),
healthy = true
),
test = shortNameTest,
id = "on-device-test",
)
file.name shouldBeEqualTo "com.example.Clazz#method-on-device-test.png"
}

@Test
fun testTooLongOutputPathUnlimitedFilename() {
val test = com.malinskiy.marathon.test.Test(
Expand All @@ -110,5 +129,7 @@ class FileManagerTest {
val limitedOutputDirectory = File(tempDir, "x".repeat(additionalPathCharacters))
val limitedFileManager = FileManager(limitedMaxPath, 0, limitedOutputDirectory)
val file = limitedFileManager.createFile(FileType.LOG, poolId, deviceInfo, test, batchId)
}

file.path.length shouldBeEqualTo 255
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import com.malinskiy.marathon.device.toDeviceInfo
import com.malinskiy.marathon.execution.Attachment
import com.malinskiy.marathon.execution.AttachmentType
import com.malinskiy.marathon.io.FileManager
import com.malinskiy.marathon.io.FileType
import com.malinskiy.marathon.log.MarathonLogging
import com.malinskiy.marathon.report.attachment.AttachmentListener
import com.malinskiy.marathon.report.attachment.AttachmentProvider
import java.util.UUID

class AdamScreenCaptureTestRunListener(
private val pool: DevicePoolId,
Expand All @@ -27,14 +29,30 @@ class AdamScreenCaptureTestRunListener(
val screenshots = testMetrics.filterKeys { it == "com.malinskiy.adam.junit4.android.screencapture.AdamScreenCaptureProcessor.v1" }
screenshots.values.forEach { path ->
val extension = path.substringAfterLast('.')
val attachmentType = when (extension) {
"jpeg", "jpg" -> AttachmentType.SCREENSHOT_JPEG
"png" -> AttachmentType.SCREENSHOT_PNG
"webp" -> AttachmentType.SCREENSHOT_WEBP
else -> null
var attachmentType: AttachmentType? = null
var fileType: FileType? = null
when (extension) {
"jpeg", "jpg" -> {
attachmentType = AttachmentType.SCREENSHOT_JPEG
fileType = FileType.SCREENSHOT_JPG
}
"png" -> {
attachmentType = AttachmentType.SCREENSHOT_PNG
fileType = FileType.SCREENSHOT_PNG
}
"webp" -> {
attachmentType = AttachmentType.SCREENSHOT_WEBP
fileType = FileType.SCREENSHOT_WEBP
}
"gif" -> {
attachmentType = AttachmentType.SCREENSHOT_GIF
fileType = FileType.SCREENSHOT_GIF
}
else -> Unit
}
if (attachmentType != null) {
val localFile = fileManager.createScreenshotFile(extension, pool, device.toDeviceInfo(), test.toTest(), testBatchId)

if (attachmentType != null && fileType != null) {
val localFile = fileManager.createFile(fileType, pool, device.toDeviceInfo(), test.toTest(), testBatchId = testBatchId, id = UUID.randomUUID().toString())
device.safePullFile(path, localFile.absolutePath)
logger.debug { "Received screen capture file $path" }
attachmentListeners.forEach {
Expand Down

0 comments on commit 6faa9c5

Please sign in to comment.