Skip to content

test(amber-python): add unit tests for Udon debugger#4510

Merged
Yicong-Huang merged 6 commits into
apache:mainfrom
Yicong-Huang:test/add-udon-python-tests
Apr 26, 2026
Merged

test(amber-python): add unit tests for Udon debugger#4510
Yicong-Huang merged 6 commits into
apache:mainfrom
Yicong-Huang:test/add-udon-python-tests

Conversation

@Yicong-Huang
Copy link
Copy Markdown
Contributor

What changes were proposed in this PR?

Adds the first Python-side unit tests for the Udon UDF debugger:

  • test_debug_manager.py (6 cases) — covers DebugManager's init state, command/event pipe checks, prompt == "", flushed-output round-trip via Pdb.stdout, and independence of the command vs event pipes.
  • test_debug_command_handler.py (7 cases) — covers WorkerDebugCommandHandler.translate_debug_command: b/break with lineno prepends module:, condition arg is preserved, no-arg b falls through, non-break commands pass through, and whitespace is stripped.

No production code is touched.

Any related issues, documentation, discussions?

Closes #4509

How was this PR tested?

Ran the new tests locally with the project's shared venv:

$ python -m pytest core/architecture/managers/test_debug_manager.py \
                   core/architecture/handlers/control/test_debug_command_handler.py -v
======================== 13 passed in 1.00s ========================

Was this PR authored or co-authored using generative AI tooling?

Generated-by: Claude Code (Opus 4.7)

Adds two pytest modules covering the previously-untested Python runtime
of the Udon UDF debugger:

- test_debug_manager.py: command/event pipe state, prompt initialization,
  flushed-output round-trip, pipe independence.
- test_debug_command_handler.py: translate_debug_command rewrites b/break
  with module:lineno, preserves condition arg, passes other commands
  through, and strips whitespace.

Closes apache#4509
Added 9 more cases on top of the initial 13:

- DebugManager: Pdb is wired to debug_in/debug_out (round-trip via the
  debugger's stdin/stdout), event pipe supports successive round-trips,
  Pdb is constructed with nosigint=True.
- WorkerDebugCommandHandler.translate_debug_command: internal whitespace
  is collapsed, break-with-only-lineno emits no trailing space.
- WorkerDebugCommandHandler.debug_command (async): translates then
  forwards to debug_manager, resumes USER/EXCEPTION/DEBUG pause types in
  order, returns EmptyReturn, passes non-break commands through. Driven
  via asyncio.run to avoid pulling in pytest-asyncio.

Refs apache#4509
Adds 12 more cases pinning the debugger's behavior on inputs the
frontend isn't expected to send today, so that future changes to either
side surface as test failures rather than silent regressions:

- DebugManager: empty command, repeated put without consume (silent
  overwrite), embedded-newline command passed verbatim, event pipe
  overwrite-on-second-flush.
- translate_debug_command: empty/whitespace-only raise ValueError,
  case-sensitive `b`/`break` match, function-name and explicit
  filename:line args are still module-prefixed, None module_name renders
  as the string "None".
- debug_command async: empty cmd propagates the ValueError; on a
  translation failure neither put_debug_command nor resume runs.

Refs apache#4509
@Yicong-Huang Yicong-Huang self-assigned this Apr 26, 2026
CI's `ruff format --check` step rejected the previous commits' line
wrapping. Reformatted with the project's pinned ruff 0.14.7. No test
behavior changes.
@Yicong-Huang Yicong-Huang enabled auto-merge (squash) April 26, 2026 01:34
@Yicong-Huang Yicong-Huang requested a review from zuozhiw April 26, 2026 01:35
Copy link
Copy Markdown
Contributor

@zuozhiw zuozhiw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good thank you

@Yicong-Huang Yicong-Huang merged commit b2f178d into apache:main Apr 26, 2026
11 checks passed
@Yicong-Huang Yicong-Huang deleted the test/add-udon-python-tests branch April 26, 2026 01:43
Yicong-Huang added a commit that referenced this pull request Apr 27, 2026
…input (#4512)

### What changes were proposed in this PR?

Fixes four correctness gaps in
`WorkerDebugCommandHandler.translate_debug_command` that were pinned as
quirks by the unit tests added in #4510:

| Input | Before | After |
| --- | --- | --- |
| `""` / `" "` | `ValueError: not enough values to unpack` |
`ValueError("debug command cannot be empty")` |
| `b foo.py:5` | `b my_udf:foo.py:5` (rejected by pdb) | `b foo.py:5`
(passed through) |
| `b my_func` | `b my_udf:my_func` (rejected by pdb — filename prefix
requires lineno) | `b my_func` (passed through; pdb resolves the symbol)
|
| `b 5` with `operator_module_name = None` | `b None:5` (no such module)
| `ValueError("executor module not initialized; cannot set breakpoint")`
|

The rule is now: **only prepend `module:` when the target is a numeric
line in the operator's own UDF module.** Function-name and explicit
`filename:lineno` forms — both of which pdb already accepts — pass
through unchanged.

### Any related issues, documentation, discussions?

Closes #4511. Follow-up to #4510 (which introduced the tests that
exposed these gaps).

### How was this PR tested?

- Updated the four pinning tests from #4510
(`test_break_with_function_name_*`,
`test_break_with_explicit_filename_*`, `test_module_name_none_*`,
`test_empty_command_*`) to assert the new intentional behaviors.
- Added one new test for the function-name fallback when the executor
module isn't initialized yet.
- Local: `python -m pytest
core/architecture/managers/test_debug_manager.py
core/architecture/handlers/control/test_debug_command_handler.py` — 35
passed.
- Local: `ruff format --check .` and `ruff check .` — clean.

### Was this PR authored or co-authored using generative AI tooling?

Generated-by: Claude Code (Opus 4.7)
Yicong-Huang added a commit that referenced this pull request Apr 27, 2026
…current-tuple handlers (#4520)

### What changes were proposed in this PR?

Adds unit tests for the two debugger-adjacent worker RPC handlers that
had no Python coverage:

- **`test_evaluate_expression_handler.py`** (4 cases) — covers
`EvaluateExpressionHandler.evaluate_python_expression`, which backs the
frontend's "watch variable" feature. Verifies the evaluator's return is
passed through unchanged, the runtime context exposes the executor as
`self` / current tuple as `tuple_` / current port id as `input_`, the
context is read fresh on each call (not snapshot at handler
construction), and the handler tolerates `None` tuple/port (worker
before any input has arrived).
- **`test_replay_current_tuple_handler.py`** (6 cases) — covers
`RetryCurrentTupleHandler.retry_current_tuple` (used by debugger "step
over an exception" flows). Verifies it chains the current tuple onto the
front of the input iterator, resumes `USER_PAUSE` + `EXCEPTION_PAUSE` in
order, **does not** resume `DEBUG_PAUSE` (so an active debugging session
is not silently dropped), no-ops when the worker is `COMPLETED`, and
still chains correctly when the remaining iterator is empty.

No production code is touched. Async handlers are driven via
`asyncio.run` to avoid pulling in `pytest-asyncio`, matching the pattern
from #4510 / #4512.

### Any related issues, documentation, discussions?

Closes #4516. Same gap pattern as #4509.

### How was this PR tested?

```
$ python -m pytest core/architecture/handlers/control/test_evaluate_expression_handler.py \
                   core/architecture/handlers/control/test_replay_current_tuple_handler.py -v
======================== 10 passed in 1.14s ========================
```

`ruff format --check .` and `ruff check .` clean locally.

### Was this PR authored or co-authored using generative AI tooling?

Generated-by: Claude Code (Opus 4.7)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add unit tests for Udon Python UDF debugger

2 participants