Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions app/src/androidTest/java/net/megaproxy487/DocumentsDeviceTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
import androidx.test.uiautomator.UiSelector
import android.view.accessibility.AccessibilityNodeInfo
import net.megaproxy487.data.ConfigTransfer
import net.megaproxy487.data.ConfigSubscription
import kotlinx.coroutines.runBlocking
Expand Down Expand Up @@ -36,9 +36,14 @@ class DocumentsDeviceTest : DeviceTestBase() {
}
private fun downloads() {
systemNode(By.desc("Show roots")).click()
val downloads = device.findObject(UiSelector().resourceId("android:id/title").text("Downloads"))
assertTrue("Downloads root missing", downloads.waitForExists(10_000))
downloads.click()
systemNode(By.res("android:id/title").text("Downloads"))
// Drawer animation changes coordinates after discovery. Invoke the row's action instead.
var node = requireNotNull(instrumentation.uiAutomation.rootInActiveWindow
?.findAccessibilityNodeInfosByViewId("android:id/title")
?.firstOrNull { it.text?.toString() == "Downloads" }) { "Downloads root missing" }
while (!node.isClickable) node = requireNotNull(node.parent) { "Downloads root is not actionable" }
assertTrue("Downloads root rejected click", node.performAction(AccessibilityNodeInfo.ACTION_CLICK))
assertTrue("Document roots drawer did not close", device.wait(Until.gone(By.text("Open from")), 10_000))
}
private fun importFile() {
appNode(By.desc(text(R.string.import_action)).enabled(true)).click()
Expand Down
8 changes: 7 additions & 1 deletion scripts/android_device_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,14 @@ def require_success(output):

def finish_case(shell, results, label, case, suite, log_start):
error_message = None
evidence = (
(("anr", ("dumpsys", "dropbox", "--print", "data_app_anr")),)
if case.find("failure") is not None
else ()
)
for name, words in (
("logcat", ("logcat", "-d", "-v", "threadtime", "-T", log_start)),
*evidence,
("force-stop", ("am", "force-stop", PACKAGE)),
):
try:
Expand All @@ -84,7 +90,7 @@ def finish_case(shell, results, label, case, suite, log_start):
message = f"{name} failed ({type(error).__name__}, exit {getattr(error, 'returncode', 'unknown')})"
ET.SubElement(case, "failure", message=message)
error_message = error_message or message
if name == "logcat" or error_message:
if name != "force-stop" or error_message:
(results / (label + f"-{name}.txt")).write_text(output)
suite.set("tests", str(len(suite)))
suite.set("failures", str(sum(c.find("failure") is not None for c in suite)))
Expand Down
20 changes: 20 additions & 0 deletions scripts/tests/test_android_device_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,26 @@ def test_logcat_failure_preserves_evidence_and_failed_report(self):
(results / "test-force-stop.txt").read_text(), "device offline"
)

def test_failed_case_collects_anr_stacks_before_stopping_app(self):
suite = ET.Element("testsuite")
case = ET.SubElement(suite, "testcase", time="1.0")
ET.SubElement(case, "failure", message="Instrumentation timed out")
shell = Mock(side_effect=["logcat", "ANR thread stacks", ""])
with tempfile.TemporaryDirectory() as directory:
results = Path(directory)
m.finish_case(shell, results, "test", case, suite, "10-22 08:18:00.000")
self.assertEqual(
(results / "test-anr.txt").read_text(), "ANR thread stacks"
)
self.assertEqual(
shell.call_args_list[-2:],
[
call("dumpsys", "dropbox", "--print", "data_app_anr"),
call("am", "force-stop", m.PACKAGE),
],
)
self.assertEqual(suite.get("failures"), "1")

def test_adb_success_is_not_enough(self):
for output in (
"INSTRUMENTATION_CODE: 0",
Expand Down
Loading