Skip to content

test(jit): assert BMM export symlink under GEN_SRC_DIR - #4187

Merged
aleozlx merged 1 commit into
flashinfer-ai:mainfrom
kahyunnam:fix/issue-4166-symlink-test-gen-src-dir
Jul 28, 2026
Merged

aleozlx merged 1 commit into
flashinfer-ai:mainfrom
kahyunnam:fix/issue-4166-symlink-test-gen-src-dir

Conversation

@kahyunnam

@kahyunnam kahyunnam commented Jul 27, 2026

Copy link
Copy Markdown
Member

📌 Description

Fixes #4166.

tests/utils/test_gen_module_symlink_race_condition.py fails on release-v0.6.16 rc1 (unit_test_b300, cu129/cu130):

AssertionError: Expected /tmp/flashinfer_test_fused_moe_symlink_ng4ln5vs/flashinfer/trtllm/
batched_gemm/trtllmGen_bmm_export to be a symlink

Root cause

#3468 ("move JIT symlinks to writable gen dir", b9890c85) moved the trtllmGen_bmm_export symlink from FLASHINFER_CUBIN_DIR to FLASHINFER_GEN_SRC_DIR in flashinfer/jit/fused_moe.py, flashinfer/jit/moe_utils.py, and flashinfer/jit/gemm/core.py. That PR touched three production files and no tests.

The test redirects only FLASHINFER_CUBIN_DIR, then asserts the symlink under it, so it now checks a location the code no longer writes to.

There is a second, quieter consequence. Since FLASHINFER_GEN_SRC_DIR is never redirected, the symlink is created in the real workspace directory and points into the test's temp directory, which shutil.rmtree deletes on teardown. The between-iteration symlink_path.unlink() also targeted the temp path, so it never removed the symlink actually in use — meaning the race stopped being re-triggered after the first iteration, and the test would have silently under-tested even with the assertion path corrected.

Fix

  • Redirect FLASHINFER_GEN_SRC_DIR alongside FLASHINFER_CUBIN_DIR in the worker, and assert the symlink there. tests/jit/test_jit_cpp_ext.py already redirects FLASHINFER_GEN_SRC_DIR this way, and flashinfer/aot.py reassigns the same attribute, so this is the established pattern.
  • Keep the artifact cache and generated-source dir as separate temp subdirectories, so the assertion still fails if the symlink ever moves back under FLASHINFER_CUBIN_DIR. Pointing both at one directory would make the assertion pass either way.
  • Restore the race semantics and confine all symlinks to the temp tree.
  • Correct the ensure_symlink() docstring, which still cited the pre-fix: move JIT symlinks to writable gen dir #3468 CUBIN_DIR location.

No production behavior changes; the only non-test edit is a docstring.

🔍 Related Issues

🚀 Pull Request Checklist

✅ Pre-commit Checks

  • I have installed pre-commit by running pip install pre-commit (or used my preferred method).
  • I have installed the hooks with pre-commit install.
  • I have run the hooks manually with pre-commit run --all-files and fixed any reported issues.

All hooks pass on the changed files (ruff check, ruff format, mypy, whitespace/EOL).

🧪 Tests

  • Tests have been updated as needed.

The test requires SM100/SM12x and returns early elsewhere, so it cannot be executed end-to-end on the SM89/90 host available to me. It still needs a B300/GB200 run to confirm the CI failure is cleared.

To verify the path logic without that hardware, I exercised the real gen_trtllm_gen_fused_moe_sm100_module() with only artifact download/checksum verification stubbed (the symlink is created before the nvcc-arch check raises), and recorded the ensure_symlink() link path. A stand-in directory represents the shared workspace dir so nothing touches the real cache.

Redirecting FLASHINFER_CUBIN_DIR only, as the test did before:

[ensure_symlink] link=/tmp/verify_before_.../shared_workspace_generated/flashinfer/trtllm/batched_gemm/trtllmGen_bmm_export
  symlink present in cubin_dir (old assertion target) : False   <-- assertion fails, matches #4166
  symlink present in shared gen dir (real workspace)  : True    <-- leaks outside the temp tree
  symlink present in test gen dir (temp, isolated)    : False

Redirecting both, as this PR does:

[ensure_symlink] link=/tmp/verify_after_.../generated/flashinfer/trtllm/batched_gemm/trtllmGen_bmm_export
  symlink present in cubin_dir (old assertion target) : False
  symlink present in shared gen dir (real workspace)  : False   <-- no leak
  symlink present in test gen dir (temp, isolated)    : True    <-- assertion passes

Collection and the non-SM100 early-return path were also confirmed green: pytest -q tests/utils/test_gen_module_symlink_race_condition.py1 passed.

Reviewer Notes

gen_fused_moe_worker_process now takes a (cubin_dir, gen_src_dir) tuple, since Pool.map passes a single argument.

flashinfer/jit/moe_utils.py and flashinfer/jit/gemm/core.py have the same symlink layout but no test asserts their paths, so nothing else needed updating.

Summary by CodeRabbit

  • Documentation

    • Corrected an example path in the symlink helper documentation.
  • Tests

    • Improved race-condition coverage for generated module symlinks.
    • Reduced test flakiness by separating generated files from cached build artifacts.

PR flashinfer-ai#3468 moved the trtllmGen_bmm_export symlink from FLASHINFER_CUBIN_DIR
to FLASHINFER_GEN_SRC_DIR without updating the race-condition test, which
still redirected only FLASHINFER_CUBIN_DIR and asserted the symlink under
it:

  AssertionError: Expected /tmp/.../flashinfer/trtllm/batched_gemm/
  trtllmGen_bmm_export to be a symlink

Because FLASHINFER_GEN_SRC_DIR was never redirected, the symlink was also
created in the real workspace directory and pointed into the test's temp
directory, which is deleted on teardown. The between-iteration unlink()
targeted the temp path too, so it never removed the symlink actually in
use and the race stopped being re-triggered after the first iteration.

Redirect FLASHINFER_GEN_SRC_DIR alongside FLASHINFER_CUBIN_DIR and assert
the symlink there. The two are kept as separate temp subdirectories so the
assertion still fails if the symlink moves back under FLASHINFER_CUBIN_DIR.

Also correct the ensure_symlink() docstring, which still referred to the
pre-flashinfer-ai#3468 CUBIN_DIR location.
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 92a63b8c-b440-49c0-9c31-e84e9fed4b35

📥 Commits

Reviewing files that changed from the base of the PR and between d536efd and 7736b6f.

📒 Files selected for processing (2)
  • flashinfer/jit/cubin_loader.py
  • tests/utils/test_gen_module_symlink_race_condition.py

📝 Walkthrough

Walkthrough

The change corrects the ensure_symlink documentation and updates the symlink race test to use separate cubin-cache and generated-source directories while validating concurrent symlink creation and header access.

Changes

Symlink race test

Layer / File(s) Summary
Generated-source symlink path and worker validation
flashinfer/jit/cubin_loader.py, tests/utils/test_gen_module_symlink_race_condition.py
The documented symlink path now uses GEN_SRC_DIR; workers patch both directory settings and validate the symlink and generated headers.
Separated-directory race orchestration
tests/utils/test_gen_module_symlink_race_condition.py
The race test uses distinct cubins and generated directories and removes only the generated-source symlink between worker runs.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested labels: run-ci

Suggested reviewers: saltyminty, bkryu, jimmyzho

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: asserting the BMM export symlink under GEN_SRC_DIR.
Description check ✅ Passed The description matches the template well, with description, related issues, tests, checklist, and reviewer notes filled in.
Linked Issues check ✅ Passed The changes address #4166 by redirecting FLASHINFER_GEN_SRC_DIR and asserting the symlink in the correct location.
Out of Scope Changes check ✅ Passed The extra docstring tweak and test refactor are directly related to the same symlink-path fix and are not out of scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@kahyunnam

Copy link
Copy Markdown
Member Author

/bot run tests/utils

@flashinfer-bot

Copy link
Copy Markdown
Collaborator

GitLab MR !1054 has been created, and the CI pipeline #59840427 is currently running. I'll report back once the pipeline job completes.

@aleozlx
aleozlx merged commit 417bbd2 into flashinfer-ai:main Jul 28, 2026
32 of 54 checks passed
aleozlx added a commit that referenced this pull request Jul 28, 2026
….6.16rc2 (#4197)

Cherry-picks for the `release-v0.6.16` branch, plus the version bump to
`0.6.16rc2`.

## Commits

| Commit | Source | Status |
| --- | --- | --- |
| `fix(norm): convert float2 to e4m3 directly in packed cast` | #4167
(`e683e307` on `main`) | merged upstream |
| `feat(xqa): ragged Q and per-row sliding-window masking for
speculative decode` | #4137 (`60783fb9` on `main`) | merged upstream |
| `test(jit): assert BMM export symlink under GEN_SRC_DIR` | #4187
(`417bbd29` on `main`) | merged upstream |
| `feat(mla): support packed low-head and variable-Q decode` | #4178 (PR
head `0774943c`) | **not yet merged** to `main` |
| `bump version to 0.6.16rc2` | — | — |

Applied in `main` merge order; #4187 sits directly on top of #4137
upstream, so that ordering is preserved.

## Notes

- **#4189 was not cherry-picked** — it was merged directly into
`release-v0.6.16` (`34368112`) and is already the base of this branch.
- **#4178 is still open against `main`.** It was cherry-picked at the
request of the release owner. Its two head commits (`b6cc59491`,
`0774943c2`) are squashed into one commit here, mirroring how it will
land upstream. If the PR changes before merge, this commit should be
dropped and re-picked.
- The three merged cherry-picks apply cleanly with patch-ids identical
to their sources. The #4178 squash is byte-identical to the PR's
combined diff.
- The #4178 commit was committed with `--no-verify`: the `mypy`
pre-commit hook reports two pre-existing `[no-redef]` errors in
`flashinfer/mla/_core.py` (conditional `if/else` imports of
`_check_can_implement` / `_get_split_kv_and_workspace_size`). These
reproduce identically on PR #4178's own branch and on the
`release-v0.6.16` base — they are not introduced by this cherry-pick,
and surface only when those modules are checked together. Left unfixed
here to keep the cherry-pick faithful.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Lee Yongjun <jqueen.astro@gmail.com>
Co-authored-by: yichengj <yichengj@nvidia.com>
Co-authored-by: bryu <bryu@nvidia.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Ka-Hyun Nam <knam@nvidia.com>
Co-authored-by: mingyangw <mingyangw@nvidia.com>
aleozlx pushed a commit that referenced this pull request Jul 29, 2026
…4225)

## Summary

Fixes two test regressions introduced by #4191 (release-only, not on
`main`):

- **#4208** — `test_make_tuning_config_reuses_topk_ids_initializer`
called `get_trtllm_moe_sm100_module.cache_clear()`, but #4191 moved
`@functools.cache` to `_get_trtllm_moe_sm100_module_impl`.
- **#4166 (re-open)** — #4187 updated the symlink test to assert under
`GEN_SRC_DIR/flashinfer/...`, but #4191 moved the export symlink to
`GEN_SRC_DIR/trtllm_export/fused_moe_trtllm_sm100/flashinfer/...`.

Both failures appeared on all Blackwell jobs in Test Cycle 2 (pipeline
59912149, rc3).

## Test plan

- [x] `pytest
tests/autotuner/test_autotuner_core.py::test_make_tuning_config_reuses_topk_ids_initializer`
— pass
- [x] `pytest tests/utils/test_gen_module_symlink_race_condition.py` —
pass
- [ ] B300/GB200 CI rerun to confirm cycle-2 green on these two files
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug][v0.6.16] test_gen_module_symlink_race_condition assert is_symlink

3 participants