Skip to content

Harden DFX artifact validation: bind to the current run - #1254

Merged
ChaoZheng109 merged 1 commit into
hw-native-sys:mainfrom
doraemonmj:dfx-run-marker-validation
Jul 3, 2026
Merged

ChaoZheng109 merged 1 commit into
hw-native-sys:mainfrom
doraemonmj:dfx-run-marker-validation

Conversation

@doraemonmj

Copy link
Copy Markdown
Contributor

What

The DFX scene tests locate their output directory by globbing
outputs/<label>_* and taking the newest by mtime, without confirming it
belongs to the current test invocation. Two problems, both from issue #1249's
section A:

  • Stale-directory (A.2): a leftover outputs/<label>_<old-ts>/ from a
    prior run/session with the same case label satisfies the glob and gets
    validated in place of (or instead of) the current run's real output —
    masking a current-run capture regression.
  • Silent-skip (A.1): _swimlane_validate.py and dep_gen/test_dep_gen.py
    returned without asserting when the glob matched nothing, so a total capture
    failure (no output dir produced) passed as green.

How

Capture a time.time() marker before super().test_run(...), thread it into
the validators, and keep only directories whose mtime >= marker; then
assert at least one such directory exists. Fixed in lockstep across the
a2a3 and a5 mirrors so they stay byte-identical modulo arch strings:

  • pmu, dep_gen, dep_gen_chain, args_dump, scope_stats,
    l2_swimlane (+ mixed)
  • shared _swimlane_validate.validate_perf_artifact now takes a since= marker

PMU header check (A.3)

Kept membership-only. Confirmed nothing in the repo reads pmu.csv
positionally (the only consumer is the test itself), so enforcing column
order would add brittleness without catching a real break. Instead the
docstring is corrected to state column order is not enforced — resolving the
doc/impl mismatch without tightening behavior.

Testing

All six DFX smokes pass on a2a3sim (silicon-agnostic) with their
--enable-* flags. The marker-filter + assert paths are exercised by real
captures.

Scope

Refs #1249. Section B (adding the DFX smoke steps to the st-sim-a5 CI job)
is intentionally left out of this PR.

@coderabbitai

coderabbitai Bot commented Jul 2, 2026 •

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f62bd0f0-1afa-4213-ada4-4226bb38abbe

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Multiple DFX smoke tests under a2a3 and a5 tensormap_and_ringbuffer suites now capture a run_marker/since timestamp before invoking the base test run, then filter and select output directories by modification time relative to that marker instead of picking the globally latest matching directory, asserting a current-run match exists.

Changes

a2a3 DFX run-scoped output validation

Layer / File(s) Summary
args_dump run-scoped selection
tests/st/a2a3/.../args_dump/test_args_dump.py
Records run_marker before super().test_run(...), filters output dirs by st_mtime >= run_marker, asserts a match exists, selects newest.
dep_gen / dep_gen_chain post-validation
tests/st/a2a3/.../dep_gen/test_dep_gen.py, .../dep_gen_chain.py
Passes run_marker into _post_validate, which now filters candidate directories by mtime and asserts existence instead of silently skipping.
l2_swimlane validator and callers
tests/st/a2a3/.../l2_swimlane/_swimlane_validate.py, test_l2_swimlane.py, test_l2_swimlane_mixed.py
validate_perf_artifact requires a since param, filters and asserts matching output dirs, threads out_dir through smoke/differential checks; _validate_dump_func_ids gains a since filter.
pmu / scope_stats artifact checks
tests/st/a2a3/.../pmu/test_pmu.py, .../scope_stats/test_scope_stats.py
_validate_pmu_artifact/_validate_scope_stats_artifact accept run_marker, filter directories by mtime, assert matches, and update pmu docstring expectations.

Estimated code review effort: 3 (Moderate) | ~25 minutes

a5 DFX run-scoped output validation

Layer / File(s) Summary
args_dump run-scoped selection
tests/st/a5/.../args_dump/test_args_dump.py
Same run_marker-based directory filtering pattern applied to a5 args_dump test.
dep_gen / dep_gen_chain post-validation
tests/st/a5/.../dep_gen/test_dep_gen.py, .../dep_gen_chain.py
_post_validate now takes run_marker, filters output dirs by mtime, and asserts a match exists.
l2_swimlane validator and callers
tests/st/a5/.../l2_swimlane/_swimlane_validate.py, test_l2_swimlane.py, test_l2_swimlane_mixed.py
validate_perf_artifact requires since, threads out_dir through smoke/differential checks; _validate_dump_func_ids gains since filtering.
pmu / scope_stats artifact checks
tests/st/a5/.../pmu/test_pmu.py, .../scope_stats/test_scope_stats.py
_validate_pmu_artifact/_validate_scope_stats_artifact accept run_marker, filter by mtime, and assert matches; pmu docstring updated.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TestRun as test_run
  participant Validator as validate_perf_artifact / _post_validate
  participant FS as OutputsDir

  TestRun->>TestRun: run_marker = time.time()
  TestRun->>TestRun: super().test_run(...)
  TestRun->>Validator: validate(..., since/run_marker=run_marker)
  Validator->>FS: glob candidate output directories
  FS-->>Validator: directory list
  Validator->>Validator: filter dirs where st_mtime >= run_marker
  Validator->>Validator: assert at least one match, select newest
  Validator->>FS: assert expected artifact file exists in selected dir
Loading

Possibly related issues

Possibly related PRs

  • hw-native-sys/simpler#916: Both modify validate_perf_artifact in _swimlane_validate.py, this PR further scoping output-directory selection using a since marker.

Poem

A rabbit checked the clock at dawn,
"No stale burrow shall we don!"
With run_marker set just right,
Only fresh dirs come to light.
Hop, hop — mtime filters clean,
The freshest warren's now serene. 🐇⏱️

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: binding DFX artifact validation to the current run.
Description check ✅ Passed The description is directly related to the changeset and accurately describes the validation-hardening updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@doraemonmj

Copy link
Copy Markdown
Contributor Author

close #1249

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request updates several test suites across the a2a3 and a5 platforms to ensure that validation checks bind only to the output directories generated during the current test invocation, rather than stale directories from prior runs. This is achieved by capturing a pre-run timestamp marker using time.time() and filtering output directories based on their modification time. The review feedback highlights a potential source of test flakiness on filesystems with coarse modification time resolutions (e.g., 1 second) and suggests subtracting a 2-second buffer from the captured timestamp to prevent current-run directories from being incorrectly filtered out.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread tests/st/a2a3/tensormap_and_ringbuffer/dfx/args_dump/test_args_dump.py Outdated
Comment thread tests/st/a5/tensormap_and_ringbuffer/dfx/args_dump/test_args_dump.py Outdated
Comment thread tests/st/a2a3/tensormap_and_ringbuffer/dfx/dep_gen/test_dep_gen.py Outdated
Comment thread tests/st/a5/tensormap_and_ringbuffer/dfx/dep_gen/test_dep_gen.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
tests/st/a2a3/tensormap_and_ringbuffer/dfx/pmu/test_pmu.py (1)

32-32: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Constant name still implies "prefix" semantics.

The docstring now explicitly states column order isn't enforced (membership-only), but the constant is still named _REQUIRED_HEADER_PREFIX. Consider renaming to _REQUIRED_HEADER_COLUMNS (or similar) to match the corrected semantics.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/st/a2a3/tensormap_and_ringbuffer/dfx/pmu/test_pmu.py` at line 32, The
constant name in test_pmu.py still suggests prefix ordering even though the
logic now only checks required members. Rename `_REQUIRED_HEADER_PREFIX` to
something like `_REQUIRED_HEADER_COLUMNS` and update any references in the PMU
test helpers so the name matches the membership-only semantics.
tests/st/a2a3/tensormap_and_ringbuffer/dfx/l2_swimlane/_swimlane_validate.py (1)

49-70: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Correct fix; consider extracting the duplicated dir-selection helper.

The since-based filtering here is correct. However, the identical matches = [...]; assert matches; out_dir = max(...) block is now copy-pasted across test_args_dump.py, test_dep_gen.py, test_dep_gen_chain.py, test_pmu.py, test_scope_stats.py, and test_l2_swimlane_mixed.py's _validate_dump_func_ids. This PR had to touch every one of those copies to fix the same stale-directory bug class — a shared helper (e.g. _select_current_run_dir(safe_label, since) in scene_test.py) would centralize this logic and prevent future drift.

♻️ Sketch of a shared helper
def _select_current_run_dir(safe_label: str, since: float) -> Path:
    matches = [p for p in _outputs_dir().glob(f"{safe_label}_*") if p.stat().st_mtime >= since]
    assert matches, f"no output dir for {safe_label!r} created this run"
    return max(matches, key=lambda p: p.stat().st_mtime)

Also applies to: 104-104, 145-145

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/st/a2a3/tensormap_and_ringbuffer/dfx/l2_swimlane/_swimlane_validate.py`
around lines 49 - 70, The current since-based directory selection in
validate_perf_artifact is correct, but the same matches/assert/max pattern is
duplicated across several test validators and should be centralized. Extract the
run-dir selection logic into a shared helper such as
_select_current_run_dir(safe_label, since) in the common test utilities (for
example scene_test.py), then update validate_perf_artifact and the other
duplicated call sites to use it so stale-directory handling stays consistent and
future fixes only need to land once.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@tests/st/a2a3/tensormap_and_ringbuffer/dfx/l2_swimlane/_swimlane_validate.py`:
- Around line 49-70: The current since-based directory selection in
validate_perf_artifact is correct, but the same matches/assert/max pattern is
duplicated across several test validators and should be centralized. Extract the
run-dir selection logic into a shared helper such as
_select_current_run_dir(safe_label, since) in the common test utilities (for
example scene_test.py), then update validate_perf_artifact and the other
duplicated call sites to use it so stale-directory handling stays consistent and
future fixes only need to land once.

In `@tests/st/a2a3/tensormap_and_ringbuffer/dfx/pmu/test_pmu.py`:
- Line 32: The constant name in test_pmu.py still suggests prefix ordering even
though the logic now only checks required members. Rename
`_REQUIRED_HEADER_PREFIX` to something like `_REQUIRED_HEADER_COLUMNS` and
update any references in the PMU test helpers so the name matches the
membership-only semantics.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c59a1d1e-7272-4de4-af83-15739ad5db2c

📥 Commits

Reviewing files that changed from the base of the PR and between 4d5fbe4 and 0b0f30f.

📒 Files selected for processing (16)
  • tests/st/a2a3/tensormap_and_ringbuffer/dfx/args_dump/test_args_dump.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dfx/dep_gen/test_dep_gen.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dfx/dep_gen/test_dep_gen_chain.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dfx/l2_swimlane/_swimlane_validate.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dfx/l2_swimlane/test_l2_swimlane.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dfx/l2_swimlane/test_l2_swimlane_mixed.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dfx/pmu/test_pmu.py
  • tests/st/a2a3/tensormap_and_ringbuffer/dfx/scope_stats/test_scope_stats.py
  • tests/st/a5/tensormap_and_ringbuffer/dfx/args_dump/test_args_dump.py
  • tests/st/a5/tensormap_and_ringbuffer/dfx/dep_gen/test_dep_gen.py
  • tests/st/a5/tensormap_and_ringbuffer/dfx/dep_gen/test_dep_gen_chain.py
  • tests/st/a5/tensormap_and_ringbuffer/dfx/l2_swimlane/_swimlane_validate.py
  • tests/st/a5/tensormap_and_ringbuffer/dfx/l2_swimlane/test_l2_swimlane.py
  • tests/st/a5/tensormap_and_ringbuffer/dfx/l2_swimlane/test_l2_swimlane_mixed.py
  • tests/st/a5/tensormap_and_ringbuffer/dfx/pmu/test_pmu.py
  • tests/st/a5/tensormap_and_ringbuffer/dfx/scope_stats/test_scope_stats.py

@doraemonmj
doraemonmj force-pushed the dfx-run-marker-validation branch from 0b0f30f to 23534b0 Compare July 2, 2026 07:26
The DFX scene tests locate their output directory by globbing
outputs/<label>_* and taking the newest by mtime. That let a stale
directory from a prior run/session with the same label satisfy the glob
and be validated in place of a missing current-run output, masking a
capture regression; two helpers also silently returned when the glob
matched nothing, so a total capture failure passed as green.

Capture a whole-second time marker before each run (floored via
int(time.time()) so a coarse-mtime filesystem that truncates directory
mtimes to the second can't spuriously exclude the current run) and keep
only directories created past it, then assert at least one exists.
Applied in lockstep across the a2a3 and a5 mirrors: pmu, dep_gen,
dep_gen_chain, args_dump, scope_stats, l2_swimlane (+ mixed) and the
shared _swimlane_validate helper (now takes a since= marker).

The PMU header check asserts an ordered prefix, not membership: the CSV
header literal and the positional row writer in pmu_collector.cpp are
separate code paths, so a header reordered out of sync with the rows
would silently mislabel every data column for any consumer. The ordered
assertion is what keeps the header in the row order.
@doraemonmj
doraemonmj force-pushed the dfx-run-marker-validation branch from 23534b0 to e5f0a2b Compare July 3, 2026 06:02
@ChaoZheng109
ChaoZheng109 merged commit fb65fe9 into hw-native-sys:main Jul 3, 2026
16 checks passed
@doraemonmj
doraemonmj deleted the dfx-run-marker-validation branch August 10, 2026 06:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants