mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-14 13:22:37 +00:00
test(app): retain Android workspace memory diagnostic
Preserve the device assertion for a supplemental LOW_MEMORY exit seen with 800 projects. This does not establish the cause of the cold-start ANR reported in #4408 and changes no production behavior.
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
# Android workspace memory diagnostic
|
||||
|
||||
Supplemental reproduction for [#4408](https://github.com/getpaseo/paseo/issues/4408), using the production 0.11.2 APK on an Android 16 emulator. This tests an adapted failure: opening the sidebar with 800 projects, each containing one workspace, produced a `LOW_MEMORY` exit after 66–90 seconds. It does not reproduce the reported 18-second cold-start ANR or establish its cause.
|
||||
|
||||
Before running:
|
||||
|
||||
- Use a dedicated emulator with the production APK installed and notifications permission settled. Bind the agent-device session to that emulator before running.
|
||||
- Pair the app with an isolated daemon containing 800 active workspaces, each in its own project. Use Project grouping and leave projects expanded. The observed fixture used existing directories inside a Git checkout, with workspace titles permuted by `(index * 317) % 800`, no agents, and no terminals.
|
||||
- Record the daemon revision, emulator RAM and Java heap settings, and the project/workspace distribution. Device memory pressure controls whether Android kills the app.
|
||||
|
||||
Run from the repository root with the agent-device session, Android serial, and an artifact directory:
|
||||
|
||||
```sh
|
||||
node packages/app/e2e/mobile/workspace-memory/android.mjs workspace-memory emulator-5556 .dev/workspace-memory
|
||||
```
|
||||
|
||||
The test cold-starts the paired app, opens its sidebar, samples memory and the process ID every five seconds for two minutes, and verifies that closing the sidebar responds. A process exit or restart fails the assertion. Memory, exit records, and logs stay in the supplied artifact directory.
|
||||
|
||||
Control: repeat with 800 workspaces grouped into one project. That distribution survived the two-minute automated check and responded to closing the sidebar, with total PSS near 300 MB. The project-per-workspace fixture reached about 2.5 GB PSS before Android recorded `LOW_MEMORY`; its Java heap rose and fell rather than showing the reporter's full-heap ANR. Neither result proves that shared collators would fix the report.
|
||||
|
||||
This diagnostic is deliberately outside CI and contains no production change.
|
||||
@@ -0,0 +1,65 @@
|
||||
// Requires a paired production app and the workspace fixture described in README.md.
|
||||
import assert from "node:assert/strict";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { mkdirSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { setTimeout as delay } from "node:timers/promises";
|
||||
|
||||
const [, , session, serial, artifacts] = process.argv;
|
||||
assert(session && serial && artifacts, "Pass session, Android serial, and artifact directory");
|
||||
mkdirSync(artifacts, { recursive: true });
|
||||
|
||||
function ad(...args) {
|
||||
return execFileSync("agent-device", [...args, "--session", session], {
|
||||
encoding: "utf8",
|
||||
timeout: 60_000,
|
||||
});
|
||||
}
|
||||
function adb(...args) {
|
||||
return execFileSync("adb", ["-s", serial, ...args], {
|
||||
encoding: "utf8",
|
||||
timeout: 15_000,
|
||||
});
|
||||
}
|
||||
function pid() {
|
||||
try {
|
||||
return adb("shell", "pidof", "sh.paseo").trim();
|
||||
} catch {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
ad("open", "sh.paseo", "--relaunch", "--platform", "android");
|
||||
ad("wait", "text", "Open menu", "15000");
|
||||
assert.equal(
|
||||
JSON.parse(ad("perf", "memory", "sample", "--json")).data.deviceId,
|
||||
serial,
|
||||
"Session and adb serial must address the same device",
|
||||
);
|
||||
const initialPid = pid();
|
||||
assert(initialPid, "App must have a process before opening the sidebar");
|
||||
ad("press", 'label="Open menu"', "--settle");
|
||||
const startedAt = Date.now();
|
||||
const samples = [];
|
||||
try {
|
||||
while (Date.now() - startedAt < 120_000) {
|
||||
const currentPid = pid();
|
||||
samples.push({
|
||||
elapsedMs: Date.now() - startedAt,
|
||||
pid: currentPid,
|
||||
meminfo: currentPid ? adb("shell", "dumpsys", "meminfo", "sh.paseo") : "",
|
||||
});
|
||||
writeFileSync(join(artifacts, "samples.json"), JSON.stringify(samples, null, 2));
|
||||
assert.equal(currentPid, initialPid, "Opening the workspace sidebar must keep the app alive");
|
||||
await delay(5_000);
|
||||
}
|
||||
ad("press", 'label="Close sidebar"', "--settle");
|
||||
ad("wait", "text", "Open menu", "10000");
|
||||
console.log("PASS: app survived two minutes with the sidebar open and responded to Close");
|
||||
} finally {
|
||||
writeFileSync(
|
||||
join(artifacts, "exit-info.txt"),
|
||||
adb("shell", "dumpsys", "activity", "exit-info", "sh.paseo"),
|
||||
);
|
||||
writeFileSync(join(artifacts, "logcat.txt"), adb("logcat", "-d", "-t", "4000"));
|
||||
}
|
||||
Reference in New Issue
Block a user