| # Tutorial: Debug tests using agent debugging mode |
| |
| This tutorial explains the concepts and workflow of *agent debugging mode* in |
| `fx test` and how to manage symbol loading and breakpoint resolution when |
| integrating with automated scripts or IDE debuggers. |
| |
| ## Overview |
| |
| Agent debugging mode is designed for headless automation, IDE integration (like |
| VS Code), and scripts. It runs `zxdb` as a background server exposing a Debug |
| Adapter Protocol (DAP) endpoint on a Unix domain socket at |
| `/tmp/fx-debug-daemon.sock`. |
| |
| To start a test suite in this mode: |
| |
| ```posix-terminal |
| fx test <TEST_SUITE_NAME> --agent-debugging-mode |
| ``` |
| |
| ## Default behavior: weak attachment |
| |
| When you run `fx test --agent-debugging-mode` without any breakpoint arguments, |
| the testing framework attaches `zxdb` to the target process "weakly" (using the |
| `attach --weak` command). |
| |
| ### What is weak attachment? |
| |
| Weak attachment optimizes startup performance by preventing `zxdb` from |
| proactively querying modules and loading symbol indexes for the process. |
| |
| * **Deferred symbol loading:** `zxdb` does not load symbols upon the initial |
| attach. |
| * **Resolution limitations:** because the symbol index is missing, any |
| `file:line` or symbolic breakpoints registered dynamically through the DAP |
| UDS interface after the test starts will remain "pending" and cannot be |
| verified or resolved. |
| * **Autoresolution on crash:** an exception or external event (such as a Rust |
| panic or a C++ assertion failure) triggers symbol loading. Once stopped, |
| symbols load automatically and pending breakpoints resolve. |
| |
| ## Solution: proactive breakpoint installation |
| |
| If you need to debug a passing path, or if you want to ensure your breakpoints |
| are active and verified *before* execution starts, you must specify them on the |
| `fx test` command line: |
| |
| ```posix-terminal |
| fx test <TEST_SUITE_NAME> --agent-debugging-mode --breakpoint <SOURCE_FILE>:<LINE> |
| ``` |
| |
| ### How it works |
| |
| 1. The presence of the `--breakpoint` option tells the `fxtest` framework to |
| attach `zxdb` *normally* (omitting the `--weak` flag). |
| 2. Because the attachment is normal, `zxdb` immediately loads symbols for the |
| target process. |
| 3. `zxdb` installs and resolves the specified breakpoints upfront during the |
| initialization handshake. |
| 4. When the test execution hits the breakpoint, the debugger suspends the |
| process and sends a `"stopped"` event with `"reason": "breakpoint"` to the |
| DAP client. |
| |
| ## Interactive debugging using fx debug cli |
| |
| Once the execution stops at a breakpoint or exception, you can interact with |
| the debugger from a second terminal using the `fx debug cli` wrapper tool. |
| |
| To connect and retrieve the current debugger state: |
| |
| ```posix-terminal |
| fx debug cli --json '{"command": "get-state"}' |
| ``` |
| |
| The tool returns a JSON response listing active processes and threads: |
| |
| ```json |
| { |
| "success": true, |
| "body": { |
| "threads": [ |
| { "id": 1, "name": "initial-thread" } |
| ], |
| "processes": { "12345": "my_test_binary" } |
| } |
| } |
| ``` |
| |
| To retrieve a stack trace for a specific thread, pass the `thread_id`: |
| |
| ```posix-terminal |
| fx debug cli --json '{"command": "stackTrace", "thread_id": 1}' |
| ``` |
| |
| The tool returns the stack frame details: |
| |
| ```json |
| { |
| "success": true, |
| "body": { |
| "stackFrames": [ |
| { |
| "id": 0, |
| "name": "my_test_function", |
| "source": { |
| "name": "main_test.cc", |
| "path": "/src/main_test.cc" |
| }, |
| "line": 42, |
| "column": 1 |
| } |
| ], |
| "totalFrames": 1 |
| } |
| } |
| ``` |
| |
| Once diagnostic inspection is complete, resume the execution of the thread: |
| |
| ```posix-terminal |
| fx debug cli --json '{"command": "continue", "thread_id": 1}' |
| ``` |
| |
| Use `fx debug cli help` to get a list of all commands you can run. |
| |
| ## See also |
| |
| * [`fx debug cli` skill](/src/developer/debug/skills/fuchsia-debugger/SKILL.md) |