mirror of
https://github.com/stablyai/orca.git
synced 2026-10-30 16:47:34 +00:00
fix(emulator): run Android commands through the process host (#35599)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
This commit is contained in:
@@ -33,7 +33,6 @@ src/main/daemon/daemon-process-identity-query.ts
|
||||
src/main/daemon/daemon-process-inspection.ts
|
||||
src/main/daemon/daemon-process-start-time.ts
|
||||
src/main/emulator/android/android-avd-boot.ts
|
||||
src/main/emulator/android/android-command-runner.ts
|
||||
src/main/emulator/android/scrcpy-stream-session.ts
|
||||
src/main/emulator/serve-sim-helper-processes.ts
|
||||
src/main/emulator/serve-sim-runtime-materializer.ts
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import { expect, it } from 'vitest'
|
||||
import { execFileAndroidCommandRunner } from './android-command-runner'
|
||||
|
||||
it('preserves argument bytes and returns both output streams and nonzero exits as data', async () => {
|
||||
const args = ['space text', 'quote\'"', '$() & | ;', '漢🙂']
|
||||
const result = await execFileAndroidCommandRunner(process.execPath, [
|
||||
'-e',
|
||||
'process.stdout.write(JSON.stringify(process.argv.slice(1))); process.stderr.write("stderr"); process.exitCode=7',
|
||||
...args
|
||||
])
|
||||
expect(result).toEqual({ stdout: JSON.stringify(args), stderr: 'stderr', code: 7 })
|
||||
})
|
||||
|
||||
it('fails a command that exceeds its deadline', async () => {
|
||||
const result = await execFileAndroidCommandRunner(
|
||||
process.execPath,
|
||||
['-e', 'setInterval(()=>{},1000)'],
|
||||
{ timeoutMs: 500 }
|
||||
)
|
||||
expect(result).toEqual({ stdout: '', stderr: '', code: 1 })
|
||||
})
|
||||
@@ -1,4 +1,4 @@
|
||||
import { execFile } from 'node:child_process'
|
||||
import { runProcess } from '@orca/process-host'
|
||||
import { basename } from 'node:path'
|
||||
import { emulatorProbe, emulatorProbeError } from '../emulator-probe'
|
||||
|
||||
@@ -14,35 +14,36 @@ export type AndroidCommandRunner = (
|
||||
const DEFAULT_TIMEOUT_MS = 60_000
|
||||
const MAX_BUFFER_BYTES = 16 * 1024 * 1024
|
||||
|
||||
export const execFileAndroidCommandRunner: AndroidCommandRunner = (binary, args, options) =>
|
||||
new Promise((resolve) => {
|
||||
execFile(
|
||||
binary,
|
||||
[...args],
|
||||
{ timeout: options?.timeoutMs ?? DEFAULT_TIMEOUT_MS, maxBuffer: MAX_BUFFER_BYTES },
|
||||
(error, stdout, stderr) => {
|
||||
const exitCode =
|
||||
error && typeof (error as { code?: unknown }).code === 'number'
|
||||
? (error as { code: number }).code
|
||||
: error
|
||||
? 1
|
||||
: 0
|
||||
const result = {
|
||||
stdout: stdout?.toString() ?? '',
|
||||
stderr: stderr?.toString() ?? '',
|
||||
code: exitCode
|
||||
}
|
||||
if (exitCode === 0) {
|
||||
emulatorProbe('cmd', { bin: basename(binary), args })
|
||||
} else {
|
||||
emulatorProbeError('cmd.fail', error ?? new Error(result.stderr || 'nonzero exit'), {
|
||||
bin: basename(binary),
|
||||
args,
|
||||
code: exitCode,
|
||||
stderr: result.stderr.slice(0, 400)
|
||||
})
|
||||
}
|
||||
resolve(result)
|
||||
}
|
||||
)
|
||||
})
|
||||
export const execFileAndroidCommandRunner: AndroidCommandRunner = async (binary, args, options) => {
|
||||
const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS
|
||||
let result: AndroidCommandResult
|
||||
let failure: unknown
|
||||
try {
|
||||
const output = await runProcess({
|
||||
program: binary,
|
||||
args,
|
||||
timeoutMs: timeoutMs === 0 ? null : timeoutMs,
|
||||
maxOutputBytes: MAX_BUFFER_BYTES,
|
||||
killOnOutputLimit: true
|
||||
})
|
||||
result = {
|
||||
stdout: output.stdout,
|
||||
stderr: output.stderr,
|
||||
code: output.timedOut || output.outputTruncated ? 1 : (output.code ?? 1)
|
||||
}
|
||||
} catch (error) {
|
||||
failure = error
|
||||
result = { stdout: '', stderr: '', code: 1 }
|
||||
}
|
||||
if (result.code === 0) {
|
||||
emulatorProbe('cmd', { bin: basename(binary), args })
|
||||
} else {
|
||||
emulatorProbeError('cmd.fail', failure ?? new Error(result.stderr || 'nonzero exit'), {
|
||||
bin: basename(binary),
|
||||
args,
|
||||
code: result.code,
|
||||
stderr: result.stderr.slice(0, 400)
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user