From 3fdeb79737d2b84c737df8a55abc6eaab1e407b7 Mon Sep 17 00:00:00 2001 From: Yuneng Jiang Date: Wed, 26 Aug 2026 08:19:56 -0700 Subject: [PATCH] fix(test): keep the mutmut sentinel out of the cleared environment test_google_login_only_threads_user_code_when_enabled cleared the whole process environment for the duration of the call. mutmut's trampoline reads os.environ['MUTANT_UNDER_TEST'] with a bare subscript, so the first trampolined callee inside the block, _get_cli_sso_flow_or_raise, raised KeyError. The bare `except Exception: pass` swallowed it and the assertion then read call_args on a mock that was never called, which is where "'NoneType' object has no attribute 'kwargs'" came from. The test only needs the SSO provider variables unset, so it now preserves the rest of the environment instead of clearing everything. google_login does not raise here, so the try/except is gone and any future exception propagates; the added assert turns a silent early return into a readable failure instead of an AttributeError. Root cause measured in a trampolined copy of the mutated folder with MUTANT_UNDER_TEST=stats: the old test fails there with KeyError: 'MUTANT_UNDER_TEST' inside _mutmut_trampoline, the new one passes. That was the only test the mutation run could not execute, so the --deselect comes back out and it counts toward the score again. --- pyproject.toml | 10 ------ .../proxy/management_endpoints/test_ui_sso.py | 32 +++++++++++++------ 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 67f798a8572..37b00373f8a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -369,21 +369,11 @@ mutate_only_covered_lines = true # rejects the SHA256 instance the fixture builds with "Algorithm must be a # registered hash algorithm". Nothing to do with mutation coverage, and one # erroring test is enough to end the stats phase before any mutant runs. -# test_google_login_only_threads_user_code_when_enabled is the same story, one -# test rather than a whole file. It calls google_login inside a bare -# `except Exception: pass` and then reads a mock's call_args, so any early raise -# inside the sandbox surfaces as `'NoneType' object has no attribute 'kwargs'`. -# Deselected rather than ignored so the rest of test_ui_sso.py still counts. -# Measured, not guessed: running the folder in the sandbox with the -x of the -# stats phase overridden gives 1 failed, 2901 passed, so this is the only test -# that cannot run there. pytest_add_cli_args = [ "-p", "no:retry", "-p", "no:rerunfailures", "-p", "no:xdist", "--ignore=tests/test_litellm/proxy/management_endpoints/test_saml_sso.py", - "--deselect", - "tests/test_litellm/proxy/management_endpoints/test_ui_sso.py::TestCLIKeyRegenerationFlow::test_google_login_only_threads_user_code_when_enabled", ] [tool.coverage.run] diff --git a/tests/test_litellm/proxy/management_endpoints/test_ui_sso.py b/tests/test_litellm/proxy/management_endpoints/test_ui_sso.py index 3facbf07889..e648bd09734 100644 --- a/tests/test_litellm/proxy/management_endpoints/test_ui_sso.py +++ b/tests/test_litellm/proxy/management_endpoints/test_ui_sso.py @@ -33,6 +33,15 @@ from litellm.types.proxy.management_endpoints.ui_sso import ( TeamMappings, ) +_SSO_PROVIDER_ENV_VARS = ( + "DISABLE_ADMIN_UI", + "MICROSOFT_CLIENT_ID", + "GOOGLE_CLIENT_ID", + "GENERIC_CLIENT_ID", + "SAML_IDP_METADATA_URL", + "SAML_IDP_METADATA_XML", +) + def _wire_team_create_tx(prisma_client): """`/team/new` inserts the team and mirrors it onto the access groups in one transaction, @@ -2796,10 +2805,15 @@ class TestCLIKeyRegenerationFlow: mock_request.base_url = "https://proxy.example.com/" mock_cache = MagicMock(redis_cache=None) mock_cache.get_cache.return_value = {"poll_secret_hash": "h"} + env_without_sso_providers = { + name: value + for name, value in os.environ.items() + if name not in _SSO_PROVIDER_ENV_VARS + } async def drive(enabled: bool): with ( - patch.dict(os.environ, {}, clear=True), + patch.dict(os.environ, env_without_sso_providers, clear=True), patch("litellm.proxy.proxy_server.premium_user", True), patch("litellm.proxy.proxy_server.prisma_client", MagicMock()), patch("litellm.proxy.proxy_server.user_api_key_cache", mock_cache), @@ -2825,15 +2839,13 @@ class TestCLIKeyRegenerationFlow: return_value=None, ) as mock_get_cli_state, ): - try: - await google_login( - request=mock_request, - source="litellm-cli", - key="cli-validsessionkey123456", - user_code="WXYZ-2345", - ) - except Exception: - pass + await google_login( + request=mock_request, + source="litellm-cli", + key="cli-validsessionkey123456", + user_code="WXYZ-2345", + ) + assert mock_get_cli_state.called return mock_get_cli_state.call_args.kwargs["user_code"] assert await drive(enabled=True) == "WXYZ-2345"