diff --git a/tests/config/test_sm70_acceleration.py b/tests/config/test_sm70_acceleration.py index 7515c2f64..86d6d9a2d 100644 --- a/tests/config/test_sm70_acceleration.py +++ b/tests/config/test_sm70_acceleration.py @@ -17,7 +17,12 @@ def config(monkeypatch): envs.disable_envs_cache() # Other operator tests may monkeypatch a dynamic env attribute. Remove # their restored concrete values so this fixture exercises actual getters. - for name in _SM70_DFLASH2_VERIFIER_DEFAULTS: + # monkeypatch.setattr reads the old value with getattr, so undoing a patch of + # a name that vllm/envs.py resolves lazily through module __getattr__ leaves a + # concrete attribute behind, and that shadow hides the getter from every later + # test in the process. Drop every shadowed declared name, not only the + # verifier defaults, so these reports never depend on another file's leftovers. + for name in [k for k in dict(vars(envs)) if k in envs.environment_variables]: monkeypatch.delitem(vars(envs), name, raising=False) for name, value in { **_SM70_BATCH_GEMM_DEFAULTS, @@ -415,7 +420,14 @@ def test_flash_next_batch_memory_and_explicit_off(config, monkeypatch): monkeypatch.setenv(name, "0") report = acc.build_report(config)["flash_next_batch"] assert report["packed_weight_memory"]["total_bytes"] == 0 - assert all(row["reason"] == "user_override" for row in report["controls"].values()) + # Same requirement as all(row["reason"] == "user_override" ...), named by row + # so that a control which is still on shows up as {'NAME': None} on failure. + offenders = { + name: row["reason"] + for name, row in report["controls"].items() + if row["reason"] != "user_override" + } + assert offenders == {} def test_flash_next_memory_does_not_guess_other_tp_layout(config): diff --git a/tests/v1/worker/test_gdn_replay_review_cpu.py b/tests/v1/worker/test_gdn_replay_review_cpu.py index 9140e9eab..1f0066e89 100644 --- a/tests/v1/worker/test_gdn_replay_review_cpu.py +++ b/tests/v1/worker/test_gdn_replay_review_cpu.py @@ -31,6 +31,23 @@ pytestmark = [pytest.mark.cpu_test, pytest.mark.skip_global_cleanup] +def _patch_env_flag(monkeypatch, name, value): + """Override one vllm.envs boolean switch for this test only. + + Every declared vllm.envs name resolves lazily through the module + ``__getattr__`` (vllm/envs.py:19565), so ``monkeypatch.setattr(envs, name, + value)`` records the *resolved* value as the old value and puts it back as a + concrete module attribute on undo. That shadow then hides the getter from + every later test in the same pytest process, which makes unrelated tests that + only change the environment order-dependent. Deleting any pre-existing + shadow and writing the flag into ``os.environ`` (what the getter reads) is + restored exactly by monkeypatch, so nothing leaks. + """ + + monkeypatch.delitem(vars(envs), name, raising=False) + monkeypatch.setenv(name, "1" if value else "0") + + def _config(policy): return SimpleNamespace( speculative_config=SimpleNamespace( @@ -59,8 +76,8 @@ def resolve(monkeypatch): monkeypatch.setattr( config_module, "_any_participating_device_is_capability", lambda *a: True ) - monkeypatch.setattr(envs, "VLLM_SM70_QWEN_GDN_SPEC_CORE_OP", False) - monkeypatch.setattr(envs, "VLLM_SM70_FUSED_SIGMOID_MIXED_QKV", True) + _patch_env_flag(monkeypatch, "VLLM_SM70_QWEN_GDN_SPEC_CORE_OP", False) + _patch_env_flag(monkeypatch, "VLLM_SM70_FUSED_SIGMOID_MIXED_QKV", True) return resolver @@ -92,8 +109,8 @@ def test_enabled_replay_admits_the_whole_verify_batch( ): # Replay is off by default from 0.1.4; request it so the enabled branch runs. policy = Sm70DFlash2Config(fused_gdn_verify=False, spec_state_replay=True) - monkeypatch.setattr(envs, "VLLM_SM70_QWEN38_WIDE_M_GDN", wide) - monkeypatch.setattr(envs, "VLLM_SM70_GDN_TAIL_COPY", False) + _patch_env_flag(monkeypatch, "VLLM_SM70_QWEN38_WIDE_M_GDN", wide) + _patch_env_flag(monkeypatch, "VLLM_SM70_GDN_TAIL_COPY", False) enabled = resolve(_config(policy)) assert enabled num_tokens = requests * 8 diff --git a/tests/v1/worker/test_gdn_spec_state_replay.py b/tests/v1/worker/test_gdn_spec_state_replay.py index c2a984cc3..257c96a57 100644 --- a/tests/v1/worker/test_gdn_spec_state_replay.py +++ b/tests/v1/worker/test_gdn_spec_state_replay.py @@ -7,6 +7,7 @@ import pytest import torch +from vllm import envs from vllm.config.speculative import SpeculativeConfig from vllm.model_executor.layers.mamba.abstract import MambaBase from vllm.v1.attention.backends.gdn_attn import select_gdn_state_block_ids @@ -21,6 +22,23 @@ BS = 1664 +def _patch_env_flag(monkeypatch, name, value): + """Override one vllm.envs boolean switch for this test only. + + Every declared vllm.envs name resolves lazily through the module + ``__getattr__`` (vllm/envs.py:19565), so ``monkeypatch.setattr(envs, name, + value)`` records the *resolved* value as the old value and puts it back as a + concrete module attribute on undo. That shadow then hides the getter from + every later test in the same pytest process, which makes unrelated tests that + only change the environment order-dependent. Deleting any pre-existing + shadow and writing the flag into ``os.environ`` (what the getter reads) is + restored exactly by monkeypatch, so nothing leaks. + """ + + monkeypatch.delitem(vars(envs), name, raising=False) + monkeypatch.setenv(name, "1" if value else "0") + + def _table(**kwargs): defaults = dict(num_columns=SLOTS + 1, block_size=BS) defaults.update(kwargs) @@ -151,12 +169,8 @@ def test_replay_halves_the_blocks_a_request_holds(): def test_non_speculative_rows_read_the_running_block_with_replay(monkeypatch): - from vllm import envs - # Exercise the accepted-column selection, not the legacy slot-zero override. - monkeypatch.setattr( - envs, "VLLM_SM70_MTP_LEGACY_GDN_NON_SPEC_SLOT0", False, raising=False - ) + _patch_env_flag(monkeypatch, "VLLM_SM70_MTP_LEGACY_GDN_NON_SPEC_SLOT0", False) table = torch.tensor([[3, PAD_SLOT_ID, PAD_SLOT_ID], [4, PAD_SLOT_ID, PAD_SLOT_ID]]) accepted = torch.tensor([1, 3]) assert select_gdn_state_block_ids(table, accepted, 2, state_columns=1).tolist() == [ @@ -198,15 +212,14 @@ def _replay_config(**overrides): @pytest.fixture def sm70(monkeypatch): import vllm.config.vllm as config_module - from vllm import envs from vllm.platforms import current_platform monkeypatch.setattr(current_platform, "is_cuda", lambda: True) monkeypatch.setattr( config_module, "_any_participating_device_is_capability", lambda *a: True ) - monkeypatch.setattr(envs, "VLLM_SM70_QWEN_GDN_SPEC_CORE_OP", False, raising=False) - monkeypatch.setattr(envs, "VLLM_SM70_FUSED_SIGMOID_MIXED_QKV", True, raising=False) + _patch_env_flag(monkeypatch, "VLLM_SM70_QWEN_GDN_SPEC_CORE_OP", False) + _patch_env_flag(monkeypatch, "VLLM_SM70_FUSED_SIGMOID_MIXED_QKV", True) return config_module._resolve_gdn_spec_state_replay @@ -331,11 +344,10 @@ def test_dflash_replay_is_the_only_change_to_gdn_allocation(sm70): def test_replay_alone_widens_the_mixed_qkv_verifier_admission( monkeypatch, wide, num_tokens ): - from vllm import envs from vllm.model_executor.layers.mamba.gdn import qwen_gdn_linear_attn as gdn - monkeypatch.setattr(envs, "VLLM_SM70_QWEN38_WIDE_M_GDN", wide, raising=False) - monkeypatch.setattr(envs, "VLLM_SM70_GDN_TAIL_COPY", False, raising=False) + _patch_env_flag(monkeypatch, "VLLM_SM70_QWEN38_WIDE_M_GDN", wide) + _patch_env_flag(monkeypatch, "VLLM_SM70_GDN_TAIL_COPY", False) admits = gdn.QwenGatedDeltaNetAttention._mixed_qkv_verify_admits # Replay off (MTP, no speculation, DFlash with replay off): the band as before. off = SimpleNamespace(spec_state_replay=False)