NVIDIA / NVIDIA/Model-Optimizer

[Coverage] Direct unit-test suites for five untested core modules (conversion, core_utils, tensor_quantizer, model_calib, export/postprocess) — plus bugs found along the way

Open
#1,902 5 comments 0 reactions 1 assignee View on GitHub

@kevalmorabia97 is already working on this.

Since Jul 21, 2026.

Dominant language
Python
Stars
3.8k
Forks
604
Avg merge
2d 8h
Merged PRs (30d)
142

Description

Summary

While auditing test coverage, we found that several load-bearing modules have no direct unit-test file — they are exercised only incidentally through higher-level flows. We wrote hermetic, CPU-only unit suites (per CONTRIBUTING's tests/unit rules: fast, no network, no GPU) for five of them, adversarially reviewed and mutation-checked each suite, and will attach one PR per module so each is reviewable in isolation:

Module Suite Tests
torch/quantization/conversion.py test_conversion.py 63
torch/quantization/utils/core_utils.py test_core_utils.py 128
torch/quantization/nn/modules/tensor_quantizer.py test_tensor_quantizer.py 90 (incl. hand-computed INT8/FP8/block fake-quant values)
torch/quantization/model_calib.py test_model_calib.py 42
torch/export/postprocess.py test_postprocess.py 74 (TP/PP split layouts, padding math)

397 tests, ~4.2k lines, total runtime ~5s. Each suite was verified to kill seeded mutations of its target (wrong scale direction, flipped split axes, broken running-max, etc.), so this is regression-detection capacity, not line-count.

Bugs found while writing these (documented in-test with NOTE: documents current behavior comments; happy to file/fix separately as preferred)

  1. _normalize_fused_experts_quantizer_name collides with SequentialQuantizer child names (introduced in #1340: the singular weight_quantizer.<N> pattern matches sequential children). Two consequences, both reproduced: (a) applying the same list-of-configs twice via set_quantizer_attributes_full nests SequentialQuantizers inside sub-slots (non-idempotent, corrupt state); (b) set_quantizer_attributes_partial with a list and a *weight_quantizer wildcard now raises ValueError mid-iteration for targets that are already sequential — a regression against its own docstring. Suggested fix: skip normalization when the matched quantizer's parent is a SequentialQuantizer.
  2. awq() silently no-ops on an unknown algorithm string (public __all__ API; only the mtq.quantize config layer validates the literal). One-line raise ValueError in an else would match the module's fail-fast style.
  3. TensorQuantizer.extra_repr dead code: the disabled branch builds a detailed string, then returns the literal "disabled", discarding it.
  4. update_lm_head_quantization warns "Enable lm_head quantization" even when quantizers are already disabled, and its sole call site (model_config_export.py:323) appears to pass inference_pipeline_parallel into the inference_tensor_parallel parameter.
  5. Minor exception-safety inconsistencies: replace_function/calibrate_with_adapters/enable_fake_quant yield without try/finally (unlike export_torch_mode et al.), so an exception mid-context leaks the patched state.

The behavior-documenting tests are written to fail-and-force-update when these are fixed.

PRs

Will be linked below, one per module, each self-contained.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.