@@ -521,7 +521,7 @@ class TestRunnerServiceImplTest {
521521 ).isEqualTo(" redfin-30-en-portrait" )
522522
523523 assertThat(
524- result.mergedResults.readFully()
524+ result.mergedResults? .readFully()
525525 ).isEqualTo(
526526 " merged-results" .toByteArray(Charsets .UTF_8 )
527527 )
@@ -889,7 +889,7 @@ class TestRunnerServiceImplTest {
889889 ).isEqualTo(" redfin-30-en-portrait" )
890890
891891 assertThat(
892- result.mergedResults.readFully()
892+ result.mergedResults? .readFully()
893893 ).isEqualTo(
894894 " merged-results" .toByteArray(Charsets .UTF_8 )
895895 )
@@ -1047,6 +1047,307 @@ class TestRunnerServiceImplTest {
10471047 )
10481048 }
10491049
1050+ @Test
1051+ fun emptyResults () = runBlocking {
1052+ val resultRelativePath = " my-test-matrix-results"
1053+ val resultPath = " ${fakeBackend.fakeGoogleCloudApi.rootGcsPath} /$resultRelativePath "
1054+ val testMatrix = fakeBackend.fakeFirebaseTestLabApi.createTestMatrix(
1055+ projectId = fakeBackend.firebaseProjectId,
1056+ requestId = " requestId" ,
1057+ testMatrix = TestMatrix (
1058+ resultStorage = ResultStorage (
1059+ googleCloudStorage = GoogleCloudStorage (resultPath),
1060+ toolResultsExecution = ToolResultsExecution (
1061+ executionId = " test_executionId" ,
1062+ historyId = " test_historyId"
1063+ )
1064+ ),
1065+ projectId = fakeBackend.firebaseProjectId,
1066+ environmentMatrix = EnvironmentMatrix (),
1067+ testSpecification = TestSpecification ()
1068+ )
1069+ )
1070+ val testMatrixId = testMatrix.testMatrixId!!
1071+
1072+ assertThat(
1073+ subject.getTestMatrix(testMatrixId)
1074+ ).isEqualTo(
1075+ testMatrix
1076+ )
1077+ // incomplete, no results
1078+ assertThat(
1079+ subject.getTestMatrixResults(testMatrix)
1080+ ).isNull()
1081+ fakeBackend.finishTest(
1082+ testMatrixId = testMatrixId,
1083+ outcome = TestMatrix .OutcomeSummary .SUCCESS
1084+ )
1085+ assertThat(
1086+ subject.getTestMatrixResults(testMatrix)
1087+ ).isNull()
1088+
1089+ val results = subject.getTestMatrixResults(testMatrixId)
1090+ assertThat(results).isEmpty()
1091+ // check screenshots is null when list of testIdentifiers is empty
1092+ val screenshots = subject.getTestMatrixArtifacts(
1093+ testMatrixId,
1094+ emptyList()
1095+ )
1096+ assertThat(
1097+ screenshots
1098+ ).isNull()
1099+ }
1100+
1101+ @Test
1102+ fun mergedResultsMissing () = runBlocking {
1103+ val resultRelativePath = " my-test-matrix-results"
1104+ val resultPath = " ${fakeBackend.fakeGoogleCloudApi.rootGcsPath} /$resultRelativePath "
1105+ val testMatrix = fakeBackend.fakeFirebaseTestLabApi.createTestMatrix(
1106+ projectId = fakeBackend.firebaseProjectId,
1107+ requestId = " requestId" ,
1108+ testMatrix = TestMatrix (
1109+ resultStorage = ResultStorage (
1110+ googleCloudStorage = GoogleCloudStorage (resultPath),
1111+ toolResultsExecution = ToolResultsExecution (
1112+ executionId = " test_executionId" ,
1113+ historyId = " test_historyId"
1114+ )
1115+ ),
1116+ projectId = fakeBackend.firebaseProjectId,
1117+ environmentMatrix = EnvironmentMatrix (),
1118+ testSpecification = TestSpecification ()
1119+ )
1120+ )
1121+ val testMatrixId = testMatrix.testMatrixId!!
1122+
1123+ assertThat(
1124+ subject.getTestMatrix(testMatrixId)
1125+ ).isEqualTo(
1126+ testMatrix
1127+ )
1128+ // incomplete, no results
1129+ assertThat(
1130+ subject.getTestMatrixResults(testMatrix)
1131+ ).isNull()
1132+ fakeBackend.finishTest(
1133+ testMatrixId = testMatrixId,
1134+ outcome = TestMatrix .OutcomeSummary .SUCCESS
1135+ )
1136+ assertThat(
1137+ subject.getTestMatrixResults(testMatrix)
1138+ ).isNull()
1139+
1140+ fakeBackend.fakeGoogleCloudApi.upload(
1141+ " $resultRelativePath /redfin-30-en-portrait/logcat" ,
1142+ " logcat" .toByteArray(Charsets .UTF_8 )
1143+ )
1144+ fakeBackend.fakeGoogleCloudApi.upload(
1145+ " $resultRelativePath /redfin-30-en-portrait/test_result_1.xml" ,
1146+ " test_result_1 content xml" .toByteArray(Charsets .UTF_8 )
1147+ )
1148+ fakeBackend.fakeGoogleCloudApi.upload(
1149+ " $resultRelativePath /redfin-30-en-portrait/test_cases/0000_logcat" ,
1150+ " test1 logcat" .toByteArray(Charsets .UTF_8 )
1151+ )
1152+ fakeBackend.fakeGoogleCloudApi.upload(
1153+ " $resultRelativePath /redfin-30-en-portrait/test_cases/0001_logcat" ,
1154+ " test2 logcat" .toByteArray(Charsets .UTF_8 )
1155+ )
1156+ fakeBackend.fakeGoogleCloudApi.upload(
1157+ " $resultRelativePath /redfin-30-en-portrait/artifacts/sdcard/Android/data/test/cache/androidx_screenshots/class1_name1_emulator_actual.png" ,
1158+ " class1 name1 emulator actual" .toByteArray(Charsets .UTF_8 )
1159+ )
1160+ fakeBackend.fakeGoogleCloudApi.upload(
1161+ " $resultRelativePath /redfin-30-en-portrait/artifacts/sdcard/Android/data/test/cache/androidx_screenshots/class1_name1_emulator_diff.png" ,
1162+ " class1 name1 emulator diff" .toByteArray(Charsets .UTF_8 )
1163+ )
1164+ fakeBackend.fakeGoogleCloudApi.upload(
1165+ " $resultRelativePath /redfin-30-en-portrait/artifacts/sdcard/Android/data/test/cache/androidx_screenshots/class1_name1_emulator_expected.png" ,
1166+ " class1 name1 emulator expected" .toByteArray(Charsets .UTF_8 )
1167+ )
1168+ fakeBackend.fakeGoogleCloudApi.upload(
1169+ " $resultRelativePath /redfin-30-en-portrait/artifacts/sdcard/Android/data/test/cache/androidx_screenshots/class1_name1_emulator_goldResult.textproto" ,
1170+ " class1 name1 emulator textproto" .toByteArray(Charsets .UTF_8 )
1171+ )
1172+ // No test is associated with this artifact. findArtifacts should not throw errors, even when unexpected files are encountered
1173+ fakeBackend.fakeGoogleCloudApi.upload(
1174+ " $resultRelativePath /redfin-30-en-portrait/artifacts/sdcard/Android/data/test/cache/androidx_screenshots/class5_name5_emulator_goldResult.textproto" ,
1175+ " class5 name5 emulator textproto" .toByteArray(Charsets .UTF_8 )
1176+ )
1177+
1178+ fakeToolsResultApi.addStep(
1179+ projectId = fakeBackend.firebaseProjectId,
1180+ executionId = " test_executionId" ,
1181+ historyId = " test_historyId" ,
1182+ step = Step (
1183+ stepId = UUID .randomUUID().toString(),
1184+ testExecutionStep = TestExecutionStep (
1185+ toolExecution = ToolExecution (
1186+ toolOutputs = listOf (
1187+ ToolOutputReference (
1188+ testCase = TestCaseReference (
1189+ className = " class1" ,
1190+ name = " name1"
1191+ ),
1192+ output = FileReference (
1193+ fileUri = " $resultPath /redfin-30-en-portrait/test_cases/0000_logcat"
1194+ )
1195+ ),
1196+ ToolOutputReference (
1197+ testCase = TestCaseReference (
1198+ className = " class3" ,
1199+ name = " name3"
1200+ ),
1201+ output = FileReference (
1202+ fileUri = " $resultPath /redfin-30-en-portrait/test_cases/0002_logcat"
1203+ )
1204+ )
1205+ )
1206+ )
1207+ )
1208+ )
1209+ )
1210+ val results = subject.getTestMatrixResults(testMatrixId)
1211+ assertThat(results).hasSize(1 )
1212+ val result = results!! .single()
1213+ assertThat(
1214+ result.deviceId
1215+ ).isEqualTo(" redfin-30-en-portrait" )
1216+
1217+ assertThat(
1218+ result.mergedResults
1219+ ).isNull()
1220+
1221+ assertThat(result.testRuns).hasSize(1 )
1222+ result.testRuns.first().let { testRun ->
1223+ val testIdentifier1 = TestRunnerService .TestIdentifier (
1224+ className = " class1" ,
1225+ name = " name1" ,
1226+ runNumber = testRun.deviceRun.runNumber
1227+ )
1228+ val screenshots1 = subject.getTestMatrixArtifacts(
1229+ testMatrixId,
1230+ listOf (testIdentifier1)
1231+ )
1232+ assertThat(
1233+ testRun.deviceRun.deviceId
1234+ ).isEqualTo(
1235+ " redfin-30-en-portrait"
1236+ )
1237+
1238+ assertThat(
1239+ testRun.logcat?.readFully()
1240+ ).isEqualTo(
1241+ " logcat" .toByteArray(Charsets .UTF_8 )
1242+ )
1243+
1244+ assertThat(
1245+ testRun.xmlResults.map { it.readFully().toString(Charsets .UTF_8 ) }
1246+ ).containsExactly(
1247+ " test_result_1 content xml"
1248+ )
1249+
1250+ assertThat(
1251+ testRun.testCaseArtifacts.size
1252+ ).isEqualTo(
1253+ 1
1254+ )
1255+ assertThat(
1256+ testRun.testCaseArtifacts[
1257+ testIdentifier1
1258+ ]?.size
1259+ ).isEqualTo(
1260+ 1
1261+ )
1262+ // step and logcat both have valid values for test1
1263+ assertThat(
1264+ testRun.testCaseArtifacts[
1265+ testIdentifier1
1266+ ]?.first {
1267+ it.resourceType == TestRunnerService .TestCaseArtifact .ResourceType .LOGCAT
1268+ }?.resultFileResource?.gcsPath.toString()
1269+ ).isEqualTo(
1270+ " $resultPath /redfin-30-en-portrait/test_cases/0000_logcat"
1271+ )
1272+ assertThat(
1273+ testRun.testCaseArtifacts[
1274+ testIdentifier1
1275+ ]?.first {
1276+ it.resourceType == TestRunnerService .TestCaseArtifact .ResourceType .LOGCAT
1277+ }?.resultFileResource?.readFully()?.toString(Charsets .UTF_8 )
1278+ ).isEqualTo(
1279+ " test1 logcat"
1280+ )
1281+ assertThat(
1282+ screenshots1?.get(testIdentifier1)?.count {
1283+ it.resourceType == TestRunnerService .TestCaseArtifact .ResourceType .PNG
1284+ }
1285+ ).isEqualTo(
1286+ 3
1287+ )
1288+ assertThat(
1289+ screenshots1?.get(testIdentifier1)?.count {
1290+ it.resourceType == TestRunnerService .TestCaseArtifact .ResourceType .TEXTPROTO
1291+ }
1292+ ).isEqualTo(
1293+ 1
1294+ )
1295+ assertThat(
1296+ screenshots1?.get(testIdentifier1)?.first {
1297+ it.resourceType == TestRunnerService .TestCaseArtifact .ResourceType .TEXTPROTO
1298+ }?.resultFileResource?.gcsPath.toString()
1299+ ).isEqualTo(
1300+ " $resultPath /redfin-30-en-portrait/artifacts/sdcard/Android/data/test/cache/androidx_screenshots/class1_name1_emulator_goldResult.textproto"
1301+ )
1302+
1303+ // step for test2 is missing
1304+ assertThat(
1305+ testRun.testCaseArtifacts[
1306+ TestRunnerService .TestIdentifier (
1307+ className = " class2" ,
1308+ name = " name2" ,
1309+ runNumber = testRun.deviceRun.runNumber
1310+ )
1311+ ]
1312+ ).isNull()
1313+ // No screenshots for test2
1314+ val testIdentifier2 = TestRunnerService .TestIdentifier (
1315+ className = " class2" ,
1316+ name = " name2" ,
1317+ runNumber = testRun.deviceRun.runNumber
1318+ )
1319+ val screenshots2 = subject.getTestMatrixArtifacts(
1320+ testMatrixId,
1321+ listOf (testIdentifier2)
1322+ )
1323+ assertThat(
1324+ screenshots2
1325+ ).isEmpty()
1326+ // logcat for test3 is missing from gcloud folder
1327+ assertThat(
1328+ testRun.testCaseArtifacts[
1329+ TestRunnerService .TestIdentifier (
1330+ className = " class3" ,
1331+ name = " name3" ,
1332+ runNumber = testRun.deviceRun.runNumber
1333+ )
1334+ ]
1335+ ).isNull()
1336+ // No screenshots for test3 either
1337+ val testIdentifier3 = TestRunnerService .TestIdentifier (
1338+ className = " class2" ,
1339+ name = " name2" ,
1340+ runNumber = testRun.deviceRun.runNumber
1341+ )
1342+ val screenshots3 = subject.getTestMatrixArtifacts(
1343+ testMatrixId,
1344+ listOf (testIdentifier3)
1345+ )
1346+ assertThat(
1347+ screenshots3
1348+ ).isEmpty()
1349+ }
1350+ }
10501351 @Test
10511352 fun parseDeviceId () {
10521353 assertThat(
0 commit comments