M3.3 — Devices and device pools¶
What you'll learn
- The
ITargetDeviceabstraction and its per-platform implementations. - What a device pool is and why shared hardware needs reservation.
- How "same test, different device" maps onto the role layout from M3.2.
How it applies (QA)
Console and mobile coverage is gated by physical hardware, not by test logic. The devkit pool is a shared, contended, flaky resource, and a large share of "Gauntlet failures" on consoles are actually device problems — a kit that's offline, stuck in a bad state, or reserved by someone else. Telling a device failure from a test failure is a core QA-owner skill.
Concepts¶
ITargetDevice and its implementations¶
ITargetDevice (tier 1) abstracts "a thing a build can be installed on and launched." Each
platform has a concrete implementation (tier 2):
TargetDeviceWindows, TargetDeviceMac, TargetDevicePS4, TargetDeviceXboxOne,
TargetDeviceSwitch, TargetDeviceIOS, TargetDeviceAndroid, and so on across the platforms
Unreal supports.
Each implements the same operations behind the interface: install a build, launch it, query its
state, copy artifacts back, reboot/clean. A test written against ITargetDevice runs on any of them
— the implementation hides "how do you copy a build to a Switch devkit" vs. "how do you launch a
local Windows process."
Local vs. remote vs. devkit¶
- Local (
TargetDeviceWindows/Macon the host) — fastest; no reservation, no copy over the network. Default when-deviceis omitted. - Remote PC — another machine addressed by IP/name; needs the build copied and the process launched remotely.
- Console devkit / mobile device — special hardware that runs development builds. Slowest path: reserve it, copy/install the cooked build, launch, pull artifacts back, clean up.
The further from local, the more failure modes that have nothing to do with your test: network, reservation, devkit firmware, storage full, a previous run left it dirty.
Device pools and reservation¶
Studios share a finite set of devkits across many people and many CI jobs. A device pool is the managed set of available devices; a run reserves the device(s) it needs, uses them, and releases them. Reservation prevents two jobs from launching on the same kit at once (which corrupts both).
Implications for a test owner:
- A run can queue waiting for a free device — "slow nightly" is sometimes contention, not a slow test.
- A reservation that isn't released (crashed job, killed process) leaks a device out of the pool until reclaimed.
- "No devices available" is a pool/capacity failure, not a test failure.
Devices × roles¶
M3.2's role layout places each role on a device. The device axis is orthogonal to the role axis:
- 1 server + 2 clients, all local → three processes on one PC.
- 1 server + 2 clients, each on its own kit → three reservations from the pool.
Scaling a test from "cheap, local, every commit" to "real hardware, nightly" is mostly moving roles
from local devices onto pooled devices — same roles, different ITargetDevice targets.
Pitfall: blaming the test for a dirty device
A kit left in a bad state by a previous run (full storage, a zombie process holding a port, an OS update pending) fails the next run for reasons the next test never caused. Before deep-diving a one-off console failure, check the device's health and whether a clean/reboot makes it pass. Reproducibility across devices is the tell: fails on one kit, passes on others → suspect the kit.
Worked example — reading a device-shaped failure¶
A nightly console job log:
LogGauntlet: Reserving device from pool 'PS5-Pool' ...
LogGauntlet: Error: No devices available in pool 'PS5-Pool' after 600s
This never reached a build install, never launched the game, never ran a line of test logic. It's a capacity/reservation failure: the pool was exhausted (other jobs, or leaked reservations) for the whole wait window. The action is on the pool (capacity, stuck reservations), not the test or the build. Re-running the test unchanged will fail identically until the pool frees up.
Exercise 1 — Test fault or device fault?
Classify each as test/build or device/pool:
- "No devices available in pool after 600s."
- The game booted on the kit, reached the menu, then the verdict went red on a missing marker.
- Install failed: "not enough free space on device."
- Passes on kits 1–3, fails only on kit 4 with a launch timeout.
- A detected crash with a dump in the role's
/Saved.
Exercise 2 — Scale the layout
You have a green local 1-server/2-client test. To run it with each client on a separate PS5
kit and the server on a Win64 host, what changes — and what doesn't? Answer in terms of
roles vs. devices.
Self-check — answers
Exercise 1: 1 device/pool (capacity), 2 test/build (verdict logic), 3 device/pool (kit storage), 4 device/pool (kit-specific; passes elsewhere), 5 test/build (a real crash in the run).
Exercise 2: What changes: the device each role targets — clients move from
TargetDeviceWindows (local) to TargetDevicePS4/PS5 kits drawn from the pool (adding
reservation, build copy, and per-device failure modes), and the build matrix now needs cooked
PS5 client builds. What doesn't change: the roles themselves (still 1 server + 2 clients),
the launch order, and the pass condition — that's the payoff of the device/role separation.
Done when
- [ ] You can explain what
ITargetDeviceabstracts and name several implementations. - [ ] You can describe a device pool and why reservation exists.
- [ ] You can separate a device/pool failure from a test/build failure from a log line.
- [ ] You can scale a role layout from local to pooled devices and say what changes.