Multi-device¶
โ Implemented ๐งช Tested
Current state: Fully implemented. Parallel device execution,
criticalSectionsynchronization, thebarriersync point, per-device abort strategies, and YAML anchor support are all active. See the Status Glossary for chip definitions.
Goal¶
Enable true parallel steps in executePlan, while supporting critical
sections where only one device can proceed at a time. Keep the plan format
close to the existing single-device test plans by adding a device key per
step and a simple devices list. Parallelism is implicit: top-level steps
for different devices run concurrently unless synchronized via
criticalSection.
YAML Syntax¶
Simple device labels, allocated by JUnitRunner/Daemon:
devices: ["A", "B"]
steps:
- tool: launchApp
device: A
appId: com.chat.app
label: Launch chat app (sender)
- tool: launchApp
device: B
appId: com.chat.app
label: Launch chat app (receiver)
Top-level steps remain consistent; parallelism is implicit:
devices: ["A", "B"]
steps:
- tool: launchApp
params:
device: A
appId: com.chat.app
label: Launch sender
- tool: launchApp
params:
device: B
appId: com.chat.app
label: Launch receiver
- tool: criticalSection
params:
lock: "chat-room"
deviceCount: 2
steps:
- tool: inputText
params:
device: A
text: "Hello"
label: Type message
- tool: imeAction
params:
device: A
action: send
label: Send message
- tool: systemTray
params:
device: B
action: find
notification: { body: "Hello" }
awaitTimeout: 5000
label: Verify notification
YAML anchors (merge keys) are supported for reuse and validation:
devices: ["A", "B"]
tap: &tap
tool: tapOn
action: tap
steps:
- <<: *tap
device: A
id: "com.google.android.deskclock:id/tab_menu_alarm"
label: Tap Alarm tab
- <<: *tap
device: B
id: "com.google.android.deskclock:id/tab_menu_alarm"
label: Tap Alarm tab
Semantics:
devicesis a list of labels to allocate sessions for; JUnitRunner requests the required number of devices from the MCP Daemon and maps them to labels.deviceon a step selects the label for routing.- Steps targeting different devices run concurrently by default.
criticalSectionis a mutex; all devices must reach it, then steps execute one device at a time within the section. See Critical Section for details.barriersynchronizes devices without serializing actions: every device runs its ownbarrierstep with a sharedlockanddeviceCount, blocks until alldeviceCountdevices arrive, then all proceed concurrently (no held section, no steps). Use it when tracks must line up at a point but should then continue in parallel. LikecriticalSection,barrieris daemon-only and may not be nested inside acriticalSection.
Implementation¶
Plan Validation¶
Plans are validated at parse time:
- If devices field is present, every step must have a device parameter โ including criticalSection and barrier steps and each of their nested sub-steps (there is no device-agnostic exemption)
- Device labels must be unique and non-empty strings
- Steps cannot reference undeclared device labels
- If any step uses device labels or criticalSection, the plan must declare devices
Execution Model¶
Sequential Mode (Single Device):
- Plans without devices field execute sequentially as before
- Backward compatible with all existing plans
Parallel Mode (Multi-Device): - Plan is partitioned into device tracks based on device labels - Each device track executes independently in parallel - Steps within a device maintain their relative order - Both plan position and device track position are tracked for debugging
Abort Strategy¶
Configurable behavior when a device fails:
- immediate (default): Abort all devices immediately
- finish-current-step: Let other devices finish their current step before aborting
Per-Device Timing¶
Debug mode or failures log per-device execution timing:
[PARALLEL_EXEC] A: SUCCESS - 5/5 steps (1234ms)
[PARALLEL_EXEC] B: FAILED - 3/5 steps (987ms)
[PARALLEL_EXEC] B: Failed at plan step 7 (track step 2): Timeout waiting for element
Known Limitations¶
- YAML anchors (
<<merge keys) merge all keys, includingdevice; a per-stepdevicewritten after the merge simply overrides the merged value. - Parallel actions can cause ordering hazards without explicit locks - use critical sections to synchronize.
- Each device’s abort signal is checked between steps, not mid-step.