Skip to content

test: migrate wave 1 phase 8 legacy llm tests to tests/unit - #42112

Merged
yuneng-berri merged 1 commit into
mainfrom
litellm_migrate_tests_p8
Sep 20, 2026
Merged

yuneng-berri merged 1 commit into
mainfrom
litellm_migrate_tests_p8

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Sep 20, 2026 •

Copy link
Copy Markdown
Contributor

TLDR

Problem this solves:

  • 20 legacy tests/test_litellm/llms/* files (wave 1, phase 8) sit outside the tiered test layout
  • Some of those tests assert wiring or mock output, not behaviour

How it solves it:

  • Every test judged by one behaviour mutation on the legacy file (red, restore, green)
  • 18 files git mv'd to the mirrored tests/unit/llms/... path, formatted with ruff
  • 7 weak tests deleted (2 files removed entirely); nothing rewritten

Counts: kept 233 / deleted 7 / rewritten 0

moved 233, passed 233 in https://app.circleci.com/workflow/fd5b33f6-15ec-44cb-b283-7debd04ed5f9/job/2607904c-aca9-4f96-b507-416e25abd3aa (junit: 258 node ids incl. parametrized cases, 258 passed, 0 failed)

Now uncovered:

  • test_hosted_vllm_chat_transformation_with_audio_url: audio_url content parts forwarded unchanged in hosted_vllm chat bodies
  • test_hosted_vllm_ssl_verify_false_sync: ssl_verify=False reaches the sync httpx client for hosted_vllm chat
  • test_hosted_vllm_ssl_verify_false_async: ssl_verify=False reaches the async httpx client for hosted_vllm chat
  • test_hosted_vllm_embedding_ssl_verify_false_sync: ssl_verify=False reaches the sync httpx client for hosted_vllm embeddings
  • test_hosted_vllm_embedding_ssl_verify_false_async: ssl_verify=False reaches the async httpx client for hosted_vllm embeddings
  • test_huggingface_rerank_error_handling: non-2xx HuggingFace rerank response surfaces as a litellm error
  • test_github_copilot_anthropic_messages_config_init: nothing (constructor/attribute existence only)
ledger (240 tests)
test_basic_rerank_huggingface | keep unit | mutated: litellm/llms/huggingface/rerank/transformation.py:transform_rerank_response: `return RerankResponse(` -> `return RerankResponse(results=[],` | red then green
test_bills_per_executed_search | keep unit | mutated: litellm/llms/groq/cost_calculator.py:cost_per_web_search_request: `return searches * cost_per_search + opens * GROQ_BROWSER_VISIT_WEBSITE_COST_PER_CALL` -> `return 1.0` | red then green
test_bills_searches_and_opens_together | keep unit | mutated: litellm/llms/groq/cost_calculator.py:cost_per_web_search_request: `return searches * cost_per_search + opens * GROQ_BROWSER_VISIT_WEBSITE_COST_PER_CALL` -> `return 1.0` | red then green
test_bills_visit_website_per_open | keep unit | mutated: litellm/llms/groq/cost_calculator.py:cost_per_web_search_request: `return searches * cost_per_search + opens * GROQ_BROWSER_VISIT_WEBSITE_COST_PER_CALL` -> `return 1.0` | red then green
test_caller_function_tools_preserved | keep unit | mutated: litellm/llms/groq/chat/transformation.py:get_supported_openai_params: `return base_params` -> `return []` | red then green
test_compound_injects_no_tool | keep unit | mutated: litellm/llms/groq/chat/transformation.py:get_supported_openai_params: `return base_params` -> `return []` | red then green
test_counts_actions_into_usage | keep unit | mutated: litellm/llms/groq/chat/transformation.py:get_supported_openai_params: `return base_params` -> `return []` | red then green
test_data_url_image_reference_is_forwarded | keep unit | mutated: litellm/llms/hosted_vllm/videos/transformation.py:_serialize_form_value: `return json.dumps(value)` -> `return "downloaded"` | red then green
test_delete_skill_invalidates_cache | keep unit | mutated: litellm/proxy/common_utils/resource_ownership.py:get_resource_owner_scopes: `return scopes` -> `return []` | red then green
test_empty_options_log_nothing | keep unit | mutated: litellm/llms/groq/chat/transformation.py:get_supported_openai_params: `return base_params` -> `return []` | red then green
test_encoding_format_included_when_base64 | keep unit | mutated: litellm/llms/hosted_vllm/embedding/transformation.py:transform_embedding_request: `return { "model": model, "input": input, **optional_params, }` -> `return {}` | red then green
test_encoding_format_included_when_float | keep unit | mutated: litellm/llms/hosted_vllm/embedding/transformation.py:transform_embedding_request: `return { "model": model, "input": input, **optional_params, }` -> `return {}` | red then green
test_encoding_format_not_included_when_none | keep unit | mutated: litellm/llms/hosted_vllm/embedding/transformation.py:transform_embedding_request: `(none)` -> `"encoding_format": "float",` | red then green
test_encoding_format_not_included_when_not_provided | keep unit | mutated: litellm/llms/hosted_vllm/embedding/transformation.py:transform_embedding_request: `(none)` -> `"encoding_format": "float",` | red then green
test_encoding_format_not_sent_in_actual_request | keep unit | mutated: litellm/llms/hosted_vllm/embedding/transformation.py:transform_embedding_request: `return { "model": model, "input": input, **optional_params, }` -> `return {}` | red then green
test_env_name_precedence_is_stable | keep unit | mutated: litellm/llms/jina_ai/embedding/transformation.py:_get_openai_compatible_provider_info: `return LlmProviders.JINA_AI.value, api_base, dynamic_api_key` -> `return LlmProviders.JINA_AI.value, None, None` | red then green
test_event_without_output_index_passes_through_unchanged | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:_normalize_stream_item_id: `return parsed_chunk` -> `return {}` | red then green
test_event_without_registered_item_passes_through_unchanged | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:_normalize_stream_item_id: `return parsed_chunk` -> `return {}` | red then green
test_every_accepted_env_name_resolves_a_key | keep unit | mutated: litellm/llms/jina_ai/embedding/transformation.py:_get_openai_compatible_provider_info: `return LlmProviders.JINA_AI.value, api_base, dynamic_api_key` -> `return LlmProviders.JINA_AI.value, None, None` | red then green
test_execute_installs_inline_requirements_file | keep unit | mutated: litellm/llms/litellm_proxy/skills/sandbox_executor.py:execute: `if requirements:` -> `if False:` | red then green
test_execute_returns_install_failure | keep unit | mutated: litellm/llms/litellm_proxy/skills/sandbox_executor.py:execute: `"success": False,` -> `"success": True,` | red then green
test_execute_uses_skill_requirements_txt | keep unit | mutated: litellm/llms/litellm_proxy/skills/sandbox_executor.py:execute: `elif "requirements.txt" in skill_files:` -> `elif False and "requirements.txt" in skill_files:` | red then green
test_explicit_api_key_beats_every_env_name | keep unit | mutated: litellm/llms/jina_ai/embedding/transformation.py:_get_openai_compatible_provider_info: `return LlmProviders.JINA_AI.value, api_base, dynamic_api_key` -> `return LlmProviders.JINA_AI.value, None, None` | red then green
test_file_scheme_media_reference_is_rejected | keep unit | mutated: litellm/llms/hosted_vllm/videos/transformation.py:_reject_unsafe_media_url: `(none)` -> `return` | red then green
test_flow_id_cannot_be_overridden_via_optional_params | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:get_complete_url: `return f"{api_base}/api/v1/run/{flow_id}"` -> `return f"{api_base}/wrong/{flow_id}"` | red then green
test_get_complete_url | keep unit | mutated: litellm/llms/hosted_vllm/embedding/transformation.py:get_complete_url: `if not api_base.endswith("/embeddings"):` -> `if False:` | red then green
test_get_complete_url | keep unit | mutated: litellm/llms/hosted_vllm/rerank/transformation.py:get_complete_url: `raise ValueError("api_base must be provided for Hosted VLLM rerank")` -> `return "wrong"` | red then green
test_get_complete_url_adds_embeddings_suffix | keep unit | mutated: litellm/llms/hosted_vllm/embedding/transformation.py:get_complete_url: `if not api_base.endswith("/embeddings"):` -> `if False:` | red then green
test_get_complete_url_appends_images_edits | keep unit | mutated: litellm/llms/hosted_vllm/image_edit/transformation.py:get_complete_url: `return f"{trimmed}/v1/images/edits"` -> `return f"{trimmed}/wrong"` | red then green
test_get_complete_url_appends_videos | keep unit | mutated: litellm/llms/hosted_vllm/videos/transformation.py:get_complete_url: `return f"{trimmed}/v1/videos"` -> `return f"{trimmed}/wrong"` | red then green
test_get_complete_url_custom_base | keep unit | mutated: litellm/llms/gradient_ai/chat/transformation.py:get_complete_url: `return complete_url` -> `return complete_url + "/wrong"` | red then green
test_get_complete_url_default_serverless | keep unit | mutated: litellm/llms/gradient_ai/chat/transformation.py:get_complete_url: `return complete_url` -> `return complete_url + "/wrong"` | red then green
test_get_complete_url_falls_back_to_env | keep unit | mutated: litellm/llms/hosted_vllm/image_edit/transformation.py:get_complete_url: `resolved_api_base: Final = api_base or get_secret_str("HOSTED_VLLM_API_BASE")` -> `resolved_api_base: Final = api_base or "http://localhost:8000/v1"` | red then green
test_get_complete_url_requires_api_base | keep unit | mutated: litellm/llms/hosted_vllm/image_edit/transformation.py:get_complete_url: `if resolved_api_base is None:` -> `if False:` | red then green
test_get_complete_url_requires_api_base | keep unit | mutated: litellm/llms/hosted_vllm/videos/transformation.py:get_complete_url: `if resolved_api_base is None:` -> `if False:` | red then green
test_get_complete_url_with_env_endpoint | keep unit | mutated: litellm/llms/gradient_ai/chat/transformation.py:get_complete_url: `return complete_url` -> `return complete_url + "/wrong"` | red then green
test_get_initiator_with_assistant_role | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:_get_initiator: `return "agent"` -> `return "user"` | red then green
test_get_initiator_with_no_role | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:_get_initiator: `return "agent"` -> `return "user"` | red then green
test_get_initiator_with_string_input | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:_get_initiator: `return "user"` -> `return "agent"` | red then green
test_get_initiator_with_user_only | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:_get_initiator: `# Default to user-initiated return "user"` -> `# Default to user-initiated return "agent"` | red then green
test_get_llm_provider_inception | keep unit | mutated: litellm/litellm_core_utils/get_llm_provider_logic.py:get_llm_provider: `custom_llm_provider = "inception"` -> `custom_llm_provider = "openai"` | red then green
test_get_openai_compatible_provider_info_default | keep unit | mutated: litellm/llms/gradient_ai/chat/transformation.py:_get_openai_compatible_provider_info: `return api_base, dynamic_api_key` -> `return None, None` | red then green
test_get_openai_compatible_provider_info_env | keep unit | mutated: litellm/llms/gradient_ai/chat/transformation.py:_get_openai_compatible_provider_info: `return api_base, dynamic_api_key` -> `return None, None` | red then green
test_get_supported_openai_params | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:get_supported_openai_params: `return super().get_supported_openai_params(model)` -> `return []` | red then green
test_get_supported_openai_params | keep unit | mutated: litellm/llms/hosted_vllm/embedding/transformation.py:get_supported_openai_params: `return [ "timeout", "dimensions", "encoding_format", "user", ]` -> `return []` | red then green
test_get_supported_openai_params_includes_omni_extensions | keep unit | mutated: litellm/llms/hosted_vllm/videos/transformation.py:get_supported_openai_params: `*_VLLM_OMNI_VIDEO_PARAMS,` -> `*(),` | red then green
test_github_copilot_anthropic_messages_config_init | delete | on sight: structural-only assertion
test_github_copilot_anthropic_messages_get_complete_url | keep unit | mutated: litellm/llms/github_copilot/messages/transformation.py:get_complete_url: `return resolved` -> `return f"{resolved}/wrong"` | red then green
test_github_copilot_anthropic_messages_get_complete_url_normalizes_authenticator_trailing_slash | keep unit | mutated: litellm/llms/github_copilot/messages/transformation.py:get_complete_url: `return resolved` -> `return f"{resolved}/wrong"` | red then green
test_github_copilot_anthropic_messages_supported_params | keep unit | mutated: litellm/llms/anthropic/experimental_pass_through/messages/transformation.py:get_supported_anthropic_messages_params: `"messages",` -> `"wrong",` | red then green
test_github_copilot_anthropic_messages_validate_environment | keep unit | mutated: litellm/llms/github_copilot/messages/transformation.py:validate_anthropic_messages_environment: `headers["openai-intent"] = "messages-proxy"` -> `headers["openai-intent"] = "wrong-intent"` | red then green
test_github_copilot_anthropic_messages_validate_environment_auth_error | keep unit | mutated: litellm/llms/github_copilot/messages/transformation.py:validate_anthropic_messages_environment: `raise AuthenticationError(` -> `raise ValueError(` | red then green
test_github_copilot_anthropic_messages_validate_environment_injects_beta_headers | keep unit | mutated: litellm/llms/github_copilot/messages/transformation.py:validate_anthropic_messages_environment: `headers = self._update_headers_with_anthropic_beta( headers, optional_params, custom_llm_provider="github_copilot", messages=messages )` -> `headers = headers` | red then green
test_github_copilot_anthropic_messages_validate_environment_injects_context_management_beta | keep unit | mutated: litellm/llms/github_copilot/messages/transformation.py:validate_anthropic_messages_environment: `headers["openai-intent"] = "messages-proxy"` -> `headers["openai-intent"] = "wrong-intent"` | red then green
test_github_copilot_anthropic_messages_validate_environment_normalizes_trailing_slash | keep unit | mutated: litellm/llms/github_copilot/messages/transformation.py:validate_anthropic_messages_environment: `dynamic_api_base: Final = (self.authenticator.get_api_base() or DEFAULT_GITHUB_COPILOT_API_BASE).rstrip("/")` -> `dynamic_api_base: Final = (self.authenticator.get_api_base() or DEFAULT_GITHUB_COPILOT_API_BASE)` | red then green
test_github_copilot_anthropic_messages_validate_environment_preserves_caller_anthropic_version | keep unit | mutated: litellm/llms/github_copilot/messages/transformation.py:validate_anthropic_messages_environment: `if "anthropic-version" not in headers:` -> `if True:` | red then green
test_github_copilot_config_disables_anthropic_beta_filtering | keep unit | mutated: litellm/llms/github_copilot/messages/transformation.py:validate_anthropic_messages_environment: `headers = self._update_headers_with_anthropic_beta( headers, optional_params, custom_llm_provider="github_copilot", messages=messages )` -> `headers = headers` | red then green
test_github_copilot_config_does_not_handle_web_search_natively | keep unit | mutated: litellm/llms/github_copilot/messages/transformation.py:handles_web_search_natively: `return False` -> `return True` | red then green
test_github_copilot_messages_config_probes_capabilities_under_copilot_namespace | keep unit | mutated: litellm/llms/github_copilot/messages/transformation.py:custom_llm_provider: `return "github_copilot"` -> `return "wrong_provider"` | red then green
test_github_copilot_provider_config_registration | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:github_copilot_supports_responses_api: `return True` -> `return False` | red then green
test_github_copilot_responses_endpoint_url | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:get_complete_url: `return f"{effective_api_base}/responses"` -> `return f"{effective_api_base}/wrong"` | red then green
test_handle_reasoning_item_non_reasoning_passthrough | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:_handle_reasoning_item: `return item` -> `return {}` | red then green
test_handle_reasoning_item_preserves_encrypted_content | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:_handle_reasoning_item: `return filtered_item` -> `return {}` | red then green
test_handle_reasoning_item_without_encrypted_content | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:_handle_reasoning_item: `return filtered_item` -> `return {}` | red then green
test_has_vision_input_nested | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:_has_vision_input: `return self._contains_vision_content(input_param)` -> `return False` | red then green
test_has_vision_input_with_input_image | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:_has_vision_input: `return self._contains_vision_content(input_param)` -> `return False` | red then green
test_has_vision_input_with_string | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:_has_vision_input: `Based on copilot-api's hasVisionInput and containsVisionContent logic. Recursively searches for input_image type in the input structure. Args: input_param: The input parameter to analyze Returns: True if input contains image content, False otherwise return self._contains_vision_content(input_param)` -> `return True` | red then green
test_has_vision_input_without_vision | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:_has_vision_input: `Based on copilot-api's hasVisionInput and containsVisionContent logic. Recursively searches for input_image type in the input structure. Args: input_param: The input parameter to analyze Returns: True if input contains image content, False otherwise return self._contains_vision_content(input_param)` -> `return True` | red then green
test_hosted_vllm_assistant_structured_content_is_preserved | keep unit | mutated: litellm/llms/hosted_vllm/chat/transformation.py:_transform_messages: `return super()._transform_messages(messages, model, is_async=cast(Literal[False], False))` -> `return []` | red then green
test_hosted_vllm_assistant_tool_use_content_becomes_tool_calls | keep unit | mutated: litellm/llms/hosted_vllm/chat/transformation.py:_transform_messages: `return super()._transform_messages(messages, model, is_async=cast(Literal[False], False))` -> `return []` | red then green
test_hosted_vllm_assistant_tool_use_does_not_duplicate_existing_tool_calls | keep unit | mutated: litellm/llms/hosted_vllm/chat/transformation.py:_transform_messages: `return super()._transform_messages(messages, model, is_async=cast(Literal[False], False))` -> `return []` | red then green
test_hosted_vllm_chat_transformation_file_url | keep unit | mutated: litellm/llms/hosted_vllm/chat/transformation.py:_transform_messages: `return super()._transform_messages(messages, model, is_async=cast(Literal[False], False))` -> `return []` | red then green
test_hosted_vllm_chat_transformation_with_audio_url | delete | on sight: blanket except Exception around call under test
test_hosted_vllm_custom_tools_are_converted_to_function_tools | keep unit | mutated: litellm/llms/hosted_vllm/chat/transformation.py:_convert_custom_tools_to_function_tools: `return converted_tools` -> `return []` | red then green
test_hosted_vllm_custom_tools_use_top_level_input_schema | keep unit | mutated: litellm/llms/hosted_vllm/chat/transformation.py:_convert_custom_tools_to_function_tools: `return converted_tools` -> `return []` | red then green
test_hosted_vllm_embedding_ssl_verify_false_async | delete | on sight: blanket except Exception and mock-call-only assertion
test_hosted_vllm_embedding_ssl_verify_false_sync | delete | on sight: blanket except Exception and mock-call-only assertion
test_hosted_vllm_provider_config_registration | keep unit | mutated: litellm/utils.py:_get_python_responses_api_config: `return litellm.HostedVLLMResponsesAPIConfig()` -> `return None` | red then green
test_hosted_vllm_responses_api_url | keep unit | mutated: litellm/llms/hosted_vllm/responses/transformation.py:get_complete_url: `return f"{api_base}/v1/responses"` -> `return f"{api_base}/wrong"` | red then green
test_hosted_vllm_responses_api_url_requires_api_base | keep unit | mutated: litellm/llms/hosted_vllm/responses/transformation.py:get_complete_url: `if api_base is None:` -> `if False:` | red then green
test_hosted_vllm_responses_create_with_explicit_none_extra_body | keep unit | mutated: litellm/utils.py:add_provider_specific_params_to_optional_params: `extra_body: Final = dict(passed_params.pop("extra_body", None) or {})` -> `extra_body: Final = dict(passed_params.pop("extra_body", None))` | red then green
test_hosted_vllm_responses_create_with_string_input | keep unit | mutated: litellm/utils.py:_get_python_responses_api_config: `return litellm.HostedVLLMResponsesAPIConfig()` -> `return None` | red then green
test_hosted_vllm_ssl_verify_false_async | delete | on sight: blanket except Exception and mock-call-only assertion
test_hosted_vllm_ssl_verify_false_sync | delete | on sight: blanket except Exception and mock-call-only assertion
test_hosted_vllm_supports_reasoning_effort | keep unit | mutated: litellm/llms/hosted_vllm/chat/transformation.py:get_supported_openai_params: `params.extend(["reasoning_effort", "thinking"])` -> `params.extend([])` | red then green
test_hosted_vllm_supports_thinking | keep unit | mutated: litellm/llms/hosted_vllm/chat/transformation.py:get_supported_openai_params: `params.extend(["reasoning_effort", "thinking"])` -> `params.extend([])` | red then green
test_hosted_vllm_thinking_blocks_prepended_to_assistant_content | keep unit | mutated: litellm/llms/hosted_vllm/chat/transformation.py:_transform_messages: `return super()._transform_messages(messages, model, is_async=cast(Literal[False], False))` -> `return []` | red then green
test_hosted_vllm_thinking_blocks_with_list_content | keep unit | mutated: litellm/llms/hosted_vllm/chat/transformation.py:_transform_messages: `return super()._transform_messages(messages, model, is_async=cast(Literal[False], False))` -> `return []` | red then green
test_hosted_vllm_validate_environment_custom_api_key | keep unit | mutated: litellm/llms/hosted_vllm/responses/transformation.py:validate_environment: `return headers` -> `return {}` | red then green
test_hosted_vllm_validate_environment_default_api_key | keep unit | mutated: litellm/llms/hosted_vllm/responses/transformation.py:validate_environment: `return headers` -> `return {}` | red then green
test_http_image_reference_is_forwarded_not_downloaded | keep unit | mutated: litellm/llms/hosted_vllm/videos/transformation.py:_serialize_form_value: `return json.dumps(value)` -> `return "downloaded"` | red then green
test_huggingface_rerank_config | keep unit | mutated: litellm/llms/huggingface/rerank/transformation.py:transform_rerank_response: `return RerankResponse(` -> `return RerankResponse(results=[],` | red then green
test_huggingface_rerank_custom_api_base | keep unit | mutated: litellm/llms/huggingface/rerank/transformation.py:transform_rerank_response: `return RerankResponse(` -> `return RerankResponse(results=[],` | red then green
test_huggingface_rerank_error_handling | delete | asserts APIConnectionError produced by the MagicMock response shape, green under mutation of HuggingFaceRerankConfig.get_error_class
test_huggingface_rerank_request_payload | keep unit | mutated: litellm/llms/huggingface/rerank/transformation.py:transform_rerank_request: `return request_body` -> `return {}` | red then green
test_huggingface_rerank_return_documents | keep unit | mutated: litellm/llms/huggingface/rerank/transformation.py:transform_rerank_request: `return request_body` -> `return {}` | red then green
test_huggingface_rerank_with_env_vars | keep unit | mutated: litellm/llms/huggingface/rerank/transformation.py:transform_rerank_response: `return RerankResponse(` -> `return RerankResponse(results=[],` | red then green
test_ignored_fields_logged_as_info | keep unit | mutated: litellm/llms/groq/chat/transformation.py:get_supported_openai_params: `return base_params` -> `return []` | red then green
test_image_edit_posts_multipart_to_vllm_omni | keep unit | mutated: litellm/llms/hosted_vllm/image_edit/transformation.py:validate_environment: `return {**headers, "Authorization": f"Bearer {resolved_key}"} # mutable-ok: httpx headers are a dict` -> `return {} # mutable-ok: httpx headers are a dict` | red then green
test_image_edit_rejects_quality_unless_dropped | keep unit | mutated: litellm/llms/hosted_vllm/image_edit/transformation.py:get_supported_openai_params: `if param not in PARAMS_VLLM_OMNI_DOES_NOT_ACCEPT` -> `if True` | red then green
test_inception_chat_response_surfaces_reasoning_and_usage | keep unit | mutated: litellm/types/utils.py:__init__: `_completion_tokens_details.reasoning_tokens = reasoning_tokens` -> `_completion_tokens_details.reasoning_tokens = 0` | red then green
test_inception_chat_sends_diffusion_params_in_body | keep unit | mutated: litellm/llms/openai_like/chat/transformation.py:map_openai_params: `mapped_params["max_tokens"] = non_default_params[ "max_completion_tokens" ] # most openai-compatible providers support 'max_tokens' not 'max_completion_tokens'` -> `mapped_params["max_tokens"] = 1 # most openai-compatible providers support 'max_tokens' not 'max_completion_tokens'` | red then green
test_inception_chat_supports_diffusion_params | keep unit | mutated: litellm/llms/inception/chat/transformation.py:get_supported_openai_params: `"diffusing",` -> `"wrong",` | red then green
test_inception_completion_endpoint_returns_chat_object | keep unit | mutated: litellm/main.py:_complete_text_completion_inception: `_response = litellm.OpenAITextCompletionConfig().convert_to_chat_model_response_object( response_object=_response, model_response_object=model_response )` -> `_response = model_response` | red then green
test_inception_completion_targets_inception_endpoint | keep unit | mutated: litellm/llms/inception/chat/transformation.py:_get_openai_compatible_provider_info: `return api_base, dynamic_api_key` -> `return None, None` | red then green
test_inception_config_initialization | keep unit | mutated: litellm/llms/inception/chat/transformation.py:custom_llm_provider: `return "inception"` -> `return "wrong"` | red then green
test_inception_does_not_leak_key_to_caller_api_base | keep unit | mutated: litellm/llms/inception/chat/transformation.py:_get_openai_compatible_provider_info: `return api_base, dynamic_api_key` -> `return None, None` | red then green
test_inception_fim_async | keep unit | mutated: litellm/main.py:_complete_text_completion_inception: `if not api_base.endswith("/fim"): api_base += "/fim"` -> `if api_base.endswith("/fim"): api_base = api_base[:-4]` | red then green
test_inception_fim_does_not_leak_global_api_key | keep unit | mutated: litellm/main.py:_complete_text_completion_inception: `api_key = api_key or litellm.inception_key or get_secret_str("INCEPTION_API_KEY")` -> `api_key = api_key or litellm.api_key or litellm.inception_key or get_secret_str("INCEPTION_API_KEY")` | red then green
test_inception_fim_extra_body_forwards_vllm_params | keep unit | mutated: litellm/llms/openai/completion/transformation.py:transform_text_completion_request: `**optional_params,` -> `**{},` | red then green
test_inception_fim_supported_params_match_schema | keep unit | mutated: litellm/llms/inception/completion/transformation.py:get_supported_openai_params: `"suffix",` -> `"wrong",` | red then green
test_inception_fim_supports_suffix_param | keep unit | mutated: litellm/llms/inception/completion/transformation.py:get_supported_openai_params: `"suffix",` -> `"wrong",` | red then green
test_inception_fim_targets_fim_endpoint | keep unit | mutated: litellm/main.py:_complete_text_completion_inception: `if not api_base.endswith("/fim"): api_base += "/fim"` -> `if api_base.endswith("/fim"): api_base = api_base[:-4]` | red then green
test_inception_get_openai_compatible_provider_info | keep unit | mutated: litellm/llms/inception/chat/transformation.py:_get_openai_compatible_provider_info: `return api_base, dynamic_api_key` -> `return None, None` | red then green
test_inception_get_supported_openai_params_dispatch | keep unit | mutated: litellm/llms/inception/completion/transformation.py:get_supported_openai_params: `"suffix",` -> `"wrong",` | red then green
test_inception_in_provider_lists | keep unit | mutated: litellm/constants.py:openai_compatible_providers (module list): `"inception",` -> `(removed)` | red then green
test_inception_key_module_attr_fallback | keep unit | mutated: litellm/llms/inception/chat/transformation.py:_get_openai_compatible_provider_info: `return api_base, dynamic_api_key` -> `return None, None` | red then green
test_inception_validate_environment | keep unit | mutated: litellm/utils.py:validate_environment: `missing_keys.append("INCEPTION_API_KEY")` -> `missing_keys.append("OPENAI_API_KEY")` | red then green
test_instruction_absent_when_not_set | keep unit | mutated: litellm/llms/hosted_vllm/rerank/transformation.py:map_cohere_rerank_params: `if instruction is not None: mapped_params["instruction"] = instruction` -> `mapped_params["instruction"] = instruction` | red then green
test_instruction_threaded_when_set | keep unit | mutated: litellm/llms/hosted_vllm/rerank/transformation.py:map_cohere_rerank_params: `return dict(forwarded)` -> `return {}` | red then green
test_interleaved_message_item_does_not_corrupt_mapping | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:_normalize_stream_item_id: `parsed_chunk["item_id"] = stable_id` -> `parsed_chunk["item_id"] = "wrong-id"` | red then green
test_langflow_config_extract_response | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:_extract_content_from_response: `return message["text"]` -> `return None` | red then green
test_langflow_config_extract_response_from_outputs_dict | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:_extract_content_from_response: `for val in outputs_dict.values():` -> `for val in ():` | red then green
test_langflow_config_flow_id_is_path_segment_encoded | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:get_complete_url: `return f"{api_base}/api/v1/run/{flow_id}"` -> `return f"{api_base}/wrong/{flow_id}"` | red then green
test_langflow_config_get_complete_url | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:get_complete_url: `return f"{api_base}/api/v1/run/{flow_id}"` -> `return f"{api_base}/wrong/{flow_id}"` | red then green
test_langflow_config_get_complete_url_requires_api_base | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:get_complete_url: `if api_base is None:` -> `if False:` | red then green
test_langflow_config_get_error_class | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:get_error_class: `return LangFlowError(status_code=status_code, message=error_message)` -> `return ValueError(error_message)` | red then green
test_langflow_config_rejects_empty_flow_id | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:_get_flow_id: `if not flow_id:` -> `if False:` | red then green
test_langflow_config_rejects_tweaks_from_request_body | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:_reject_caller_tweaks: `if params.get("tweaks") is not None:` -> `if False:` | red then green
test_langflow_config_rejects_tweaks_from_request_params | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:_reject_caller_tweaks: `if params.get("tweaks") is not None:` -> `if False:` | red then green
test_langflow_config_sign_request_passes_through_without_tweaks | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:sign_request: `return headers, None` -> `return {}, b"wrong"` | red then green
test_langflow_config_stream_behavior_flags | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:should_fake_stream: `return stream is True` -> `return False` | red then green
test_langflow_config_strips_flow_id_whitespace | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:get_complete_url: `return f"{api_base}/api/v1/run/{flow_id}"` -> `return f"{api_base}/wrong/{flow_id}"` | red then green
test_langflow_config_transform_request_empty_messages | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:transform_request: `return payload` -> `return {}` | red then green
test_langflow_config_transform_request_falls_back_to_last_message | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:transform_request: `return payload` -> `return {}` | red then green
test_langflow_config_transform_request_includes_session_id | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:transform_request: `return payload` -> `return {}` | red then green
test_langflow_config_transform_request_uses_last_user_message | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:transform_request: `return payload` -> `return {}` | red then green
test_langflow_config_validate_environment_sets_api_key_header | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:validate_environment: `headers["Content-Type"] = "application/json"` -> `headers["Content-Type"] = "wrong"` | red then green
test_langflow_extra_body_cannot_inject_tweaks_into_run_payload | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:_reject_caller_tweaks: `if params.get("tweaks") is not None:` -> `if False:` | red then green
test_langflow_extract_response_returns_none_when_no_message | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:_extract_content_from_response: `return None` -> `return "wrong"` | red then green
test_langflow_provider_config_registered | keep unit | mutated: litellm/utils.py:_build_provider_config_map: `lambda: ProviderConfigManager._get_langflow_config(),` -> `lambda: None,` | red then green
test_langflow_transform_response_builds_model_response_with_usage | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:_extract_content_from_response: `return message["text"]` -> `return None` | red then green
test_langflow_transform_response_raises_on_non_json_body | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:transform_response: `except Exception as e: raise LangFlowError( message=f"LangFlow returned a non-JSON response: {e}", status_code=raw_response.status_code, )` -> `except Exception: return model_response` | red then green
test_langflow_transform_response_raises_on_unparseable_body | keep unit | mutated: litellm/llms/langflow/chat/transformation.py:transform_response: `(none)` -> `return model_response if False:` | red then green
test_list_skills_excludes_unowned_for_non_admin | keep unit | mutated: litellm/proxy/common_utils/resource_ownership.py:get_resource_owner_scopes: `return scopes` -> `return []` | red then green
test_load_skill_caches_negative_lookups | keep unit | mutated: litellm/llms/litellm_proxy/skills/handler.py:_load_skill: `if cached == _NEGATIVE_SKILL_SENTINEL:` -> `if False:` | red then green
test_load_skill_uses_cache_after_first_db_hit | keep unit | mutated: litellm/llms/litellm_proxy/skills/handler.py:_load_skill: `if cached is not None:` -> `if False:` | red then green
test_malformed_executed_tools_skips_billing_without_breaking_response | keep unit | mutated: litellm/llms/groq/chat/transformation.py:get_supported_openai_params: `return base_params` -> `return []` | red then green
test_map_cohere_rerank_params_basic | keep unit | mutated: litellm/llms/hosted_vllm/rerank/transformation.py:map_cohere_rerank_params: `return dict(forwarded)` -> `return {}` | red then green
test_map_cohere_rerank_params_forwards_vllm_truncation_params | keep unit | mutated: litellm/llms/hosted_vllm/rerank/transformation.py:map_cohere_rerank_params: `return dict(forwarded)` -> `return {}` | red then green
test_map_cohere_rerank_params_omits_instruction_when_absent | keep unit | mutated: litellm/llms/hosted_vllm/rerank/transformation.py:map_cohere_rerank_params: `if instruction is not None: mapped_params["instruction"] = instruction` -> `mapped_params["instruction"] = instruction` | red then green
test_map_cohere_rerank_params_omits_truncation_params_when_absent | keep unit | mutated: litellm/llms/hosted_vllm/rerank/transformation.py:map_cohere_rerank_params: `return dict(forwarded)` -> `return {}` | red then green
test_map_cohere_rerank_params_passes_instruction_when_set | keep unit | mutated: litellm/llms/hosted_vllm/rerank/transformation.py:map_cohere_rerank_params: `return dict(forwarded)` -> `return {}` | red then green
test_map_cohere_rerank_params_raises_on_max_chunks_per_doc | keep unit | mutated: litellm/llms/hosted_vllm/rerank/transformation.py:map_cohere_rerank_params: `if max_chunks_per_doc is not None:` -> `if False:` | red then green
test_map_cohere_rerank_params_rejects_invalid_truncation_params_as_400 | keep unit | mutated: litellm/llms/hosted_vllm/rerank/transformation.py:validated_truncation_params: `raise UnsupportedParamsError(status_code=400, message=f"hosted_vllm rerank: {error}") from error` -> `return HostedVLLMRerankTruncationParams()` | red then green
test_map_openai_params | keep unit | mutated: litellm/llms/hosted_vllm/embedding/transformation.py:get_supported_openai_params: `return [ "timeout", "dimensions", "encoding_format", "user", ]` -> `return []` | red then green
test_map_openai_params | keep unit | mutated: litellm/llms/jina_ai/embedding/transformation.py:map_openai_params: `optional_params["dimensions"] = non_default_params["dimensions"]` -> `optional_params["dimensions"] = 0` | red then green
test_map_openai_params_filters_unsupported | keep unit | mutated: litellm/llms/hosted_vllm/embedding/transformation.py:get_supported_openai_params: `return [ "timeout", "dimensions", "encoding_format", "user", ]` -> `return []` | red then green
test_map_openai_params_no_transformation | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:map_openai_params: `return dict(response_api_optional_params)` -> `return {}` | red then green
test_map_openai_params_passes_through_omni_fields | keep unit | mutated: litellm/llms/hosted_vllm/videos/transformation.py:map_openai_params: `key: value for key, value in video_create_optional_params.items() if value is not None` -> `key: value for key, value in {}.items()` | red then green
test_message_text_events_normalized_to_output_item_added_id | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:_normalize_stream_item_id: `parsed_chunk["item_id"] = stable_id` -> `parsed_chunk["item_id"] = "wrong-id"` | red then green
test_metadata_url_in_image_reference_is_rejected | keep unit | mutated: litellm/llms/hosted_vllm/videos/transformation.py:_reject_unsafe_media_url: `(none)` -> `return` | red then green
test_missing_pricing_costs_nothing | keep unit | mutated: litellm/llms/groq/cost_calculator.py:cost_per_web_search_request: `return searches * cost_per_search + opens * GROQ_BROWSER_VISIT_WEBSITE_COST_PER_CALL` -> `return 1.0` | red then green
test_missing_usage_signal_costs_nothing | keep unit | mutated: litellm/llms/groq/cost_calculator.py:cost_per_web_search_request: `return 0.0` -> `return 1.0` | red then green
test_mode_chat_overrides_endpoints_with_responses | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:github_copilot_supports_responses_api: `return False` -> `return True` | red then green
test_no_duplicate_browser_search_tool | keep unit | mutated: litellm/llms/groq/chat/transformation.py:get_supported_openai_params: `return base_params` -> `return []` | red then green
test_no_searches_costs_nothing | keep unit | mutated: litellm/llms/groq/cost_calculator.py:cost_per_web_search_request: `return searches * cost_per_search + opens * GROQ_BROWSER_VISIT_WEBSITE_COST_PER_CALL` -> `return 1.0` | red then green
test_no_signal_without_executed_tools | keep unit | mutated: litellm/llms/groq/chat/transformation.py:get_supported_openai_params: `return base_params` -> `return []` | red then green
test_normalization_continues_after_a_terminal_event | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:_normalize_stream_item_id: `parsed_chunk["item_id"] = stable_id` -> `parsed_chunk["item_id"] = "wrong-id"` | red then green
test_not_supported_on_other_models | keep unit | mutated: litellm/llms/groq/chat/transformation.py:get_supported_openai_params: `if not (` -> `if (` | red then green
test_params_vllm_omni_ignores_are_not_advertised | keep unit | mutated: litellm/llms/hosted_vllm/image_edit/transformation.py:get_supported_openai_params: `if param not in PARAMS_VLLM_OMNI_DOES_NOT_ACCEPT` -> `if False` | red then green
test_provider_config_manager_dispatches_claude_to_copilot_messages_config | keep unit | mutated: litellm/utils.py:_get_provider_anthropic_messages_config_cached: `if "claude" in model_lower:` -> `if False:` | red then green
test_provider_config_manager_skips_non_claude_copilot_models | keep unit | mutated: litellm/utils.py:_get_provider_anthropic_messages_config_cached: `if "claude" in model_lower:` -> `if True:` | red then green
test_provider_config_registration | keep unit | mutated: litellm/utils.py:get_provider_image_edit_config: `from litellm.llms.hosted_vllm.image_edit import get_hosted_vllm_image_edit_config return get_hosted_vllm_image_edit_config(model=model)` -> `return None` | red then green
test_provider_config_registration | keep unit | mutated: litellm/utils.py:get_provider_video_config: `from litellm.llms.hosted_vllm.videos import get_hosted_vllm_video_config return get_hosted_vllm_video_config(model)` -> `return None` | red then green
test_provider_params_are_sent_at_the_top_level_of_the_request | keep unit | mutated: litellm/llms/hosted_vllm/embedding/transformation.py:transform_embedding_request: `return { "model": model, "input": input, **optional_params, }` -> `return {}` | red then green
test_realistic_chat_only_entry_returns_none | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:github_copilot_supports_responses_api: `return False` -> `return True` | red then green
test_realistic_responses_only_entry_returns_config | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:github_copilot_supports_responses_api: `return True` -> `return False` | red then green
test_reasoning_output_item_done_normalized_to_added_id | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:_normalize_stream_item_id: `parsed_chunk["item"] = {**item, "id": stable_id}` -> `parsed_chunk["item"] = {**item, "id": "wrong"}` | red then green
test_request_transformation | keep unit | mutated: litellm/llms/huggingface/rerank/transformation.py:transform_rerank_request: `return request_body` -> `return {}` | red then green
test_rerank_sends_truncate_prompt_tokens_to_vllm | keep unit | mutated: litellm/llms/hosted_vllm/rerank/transformation.py:map_cohere_rerank_params: `return dict(forwarded)` -> `return {}` | red then green
test_response_transformation | keep unit | mutated: litellm/llms/huggingface/rerank/transformation.py:transform_rerank_response: `return RerankResponse(` -> `return RerankResponse(results=[],` | red then green
test_response_without_usage_is_left_untouched | keep unit | mutated: litellm/llms/groq/chat/transformation.py:_add_web_search_usage: `return` -> `usage.server_tool_use = ServerToolUse()` | red then green
test_returns_config_when_mode_is_responses | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:github_copilot_supports_responses_api: `return True` -> `return False` | red then green
test_returns_config_when_mode_unset_but_endpoints_have_responses | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:github_copilot_supports_responses_api: `return isinstance(endpoints, list) and "/v1/responses" in endpoints` -> `return False` | red then green
test_returns_config_when_model_is_none | keep unit | mutated: litellm/utils.py:_get_python_responses_api_config: `if model is None or github_copilot_supports_responses_api(model=model):` -> `if model is not None and github_copilot_supports_responses_api(model=model):` | red then green
test_returns_none_when_get_model_info_raises | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:github_copilot_supports_responses_api: `return False` -> `return True` | red then green
test_returns_none_when_mode_is_chat | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:github_copilot_supports_responses_api: `return False` -> `return True` | red then green
test_returns_none_when_mode_is_unset_and_no_endpoints | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:github_copilot_supports_responses_api: `return isinstance(endpoints, list) and "/v1/responses" in endpoints` -> `return True` | red then green
test_serialize_form_value_does_not_quote_plain_strings | keep unit | mutated: litellm/llms/hosted_vllm/videos/transformation.py:_serialize_form_value: `return value` -> `return "wrong"` | red then green
test_should_allow_admin_and_anonymous_resource_owner_paths | keep unit | mutated: litellm/proxy/common_utils/resource_ownership.py:user_can_access_resource_owner: `return False` -> `return True` | red then green
test_should_build_resource_owner_scopes_for_auth_context | keep unit | mutated: litellm/proxy/common_utils/resource_ownership.py:get_resource_owner_scopes: `return scopes` -> `return []` | red then green
test_should_extract_skill_auth_from_supported_metadata_fields | keep unit | mutated: litellm/skills/main.py:_get_user_api_key_auth_from_kwargs: `return metadata["user_api_key_auth"]` -> `return None` | red then green
test_should_extract_skill_request_metadata_with_extra_body_precedence | keep unit | mutated: litellm/skills/main.py:_get_skill_request_metadata: `return extra_body["metadata"]` -> `pass` | red then green
test_should_filter_list_skills_to_authenticated_owner_scopes | keep unit | mutated: litellm/proxy/common_utils/resource_ownership.py:get_resource_owner_scopes: `return scopes` -> `return []` | red then green
test_should_forward_skill_auth_through_sdk_entrypoints | keep unit | mutated: litellm/skills/main.py:create_skill: `user_api_key_dict=_get_user_api_key_auth_from_kwargs(kwargs),` -> `user_api_key_dict=None,` | red then green
test_should_forward_skill_auth_through_transformation_handler | keep unit | mutated: litellm/llms/litellm_proxy/skills/transformation.py:_async_create_skill: `user_api_key_dict=user_api_key_dict,` -> `user_api_key_dict=None,` | red then green
test_should_hide_skill_from_different_owner | keep unit | mutated: litellm/proxy/common_utils/resource_ownership.py:user_can_access_resource_owner: `return False return owner in get_resource_owner_scopes(user_api_key_dict)` -> `return True return True` | red then green
test_should_hide_unowned_skill_by_default | keep unit | mutated: litellm/proxy/common_utils/resource_ownership.py:user_can_access_resource_owner: `return False return owner in get_resource_owner_scopes(user_api_key_dict)` -> `return True return True` | red then green
test_should_reject_skill_create_for_identityless_proxy_auth | keep unit | mutated: litellm/llms/litellm_proxy/skills/handler.py:create_skill: `if owner is None:` -> `if False:` | red then green
test_should_scope_skill_injection_fetch_to_authenticated_user | keep unit | mutated: litellm/proxy/hooks/litellm_skills/main.py:_fetch_skill_from_db: `user_api_key_dict=user_api_key_dict,` -> `user_api_key_dict=None,` | red then green
test_should_store_team_owner_for_keys_without_user_id | keep unit | mutated: litellm/proxy/common_utils/resource_ownership.py:get_primary_resource_owner_scope: `return f"team:{user_api_key_dict.team_id}"` -> `return "team:shared"` | red then green
test_should_store_token_owner_for_keys_without_user_team_or_org | keep unit | mutated: litellm/proxy/common_utils/resource_ownership.py:get_primary_resource_owner_scope: `return f"key:{user_api_key_dict.token}"` -> `return "key:shared"` | red then green
test_summary_events_normalized_to_output_item_added_id | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:_normalize_stream_item_id: `parsed_chunk["item_id"] = stable_id` -> `parsed_chunk["item_id"] = "wrong-id"` | red then green
test_supported_on_search_capable_models | keep unit | mutated: litellm/llms/groq/chat/transformation.py:get_supported_openai_params: `return base_params` -> `return []` | red then green
test_text_completion_inception_in_provider_lists | keep unit | mutated: litellm/types/utils.py:LlmProviders.TEXT_COMPLETION_INCEPTION: `TEXT_COMPLETION_INCEPTION = "text-completion-inception"` -> `TEXT_COMPLETION_INCEPTION = "text-completion-inception-fim"` | red then green
test_transform_embedding_request_basic | keep unit | mutated: litellm/llms/hosted_vllm/embedding/transformation.py:transform_embedding_request: `return { "model": model, "input": input, **optional_params, }` -> `return {}` | red then green
test_transform_embedding_request_image_input | keep unit | mutated: litellm/llms/jina_ai/embedding/transformation.py:transform_embedding_request: `return data` -> `return {}` | red then green
test_transform_embedding_request_mixed_input | keep unit | mutated: litellm/llms/jina_ai/embedding/transformation.py:transform_embedding_request: `return data` -> `return {}` | red then green
test_transform_embedding_request_string_input | keep unit | mutated: litellm/llms/hosted_vllm/embedding/transformation.py:transform_embedding_request: `return { "model": model, "input": input, **optional_params, }` -> `return {}` | red then green
test_transform_embedding_request_text_input | keep unit | mutated: litellm/llms/jina_ai/embedding/transformation.py:transform_embedding_request: `return data` -> `return {}` | red then green
test_transform_embedding_request_with_dimensions | keep unit | mutated: litellm/llms/hosted_vllm/embedding/transformation.py:transform_embedding_request: `return { "model": model, "input": input, **optional_params, }` -> `return {}` | red then green
test_transform_messages_handles_dicts_only | keep unit | mutated: litellm/llms/openai/chat/gpt_transformation.py:_transform_messages: `hoisted_messages: Final = hoist_images_from_tool_messages(stripped_messages)` -> `hoisted_messages: Final = hoist_images_from_tool_messages(stripped_messages)[::-1]` | red then green
test_transform_request_forwards_truncation_params | keep unit | mutated: litellm/llms/hosted_vllm/rerank/transformation.py:transform_rerank_request: `return rerank_request.model_dump(exclude_none=True)` -> `return {}` | red then green
test_transform_request_includes_instruction_when_set | keep unit | mutated: litellm/llms/hosted_vllm/rerank/transformation.py:transform_rerank_request: `return rerank_request.model_dump(exclude_none=True)` -> `return {}` | red then green
test_transform_request_omits_instruction_when_absent | keep unit | mutated: litellm/llms/hosted_vllm/rerank/transformation.py:transform_rerank_request: `instruction=optional_rerank_params.get("instruction", None),` -> `instruction=optional_rerank_params.get("instruction", ""),` | red then green
test_transform_request_omits_truncation_params_when_absent | keep unit | mutated: litellm/llms/hosted_vllm/rerank/transformation.py:transform_rerank_request: `return rerank_request.model_dump(exclude_none=True)` -> `return rerank_request.model_dump()` | red then green
test_transform_response | keep unit | mutated: litellm/llms/hosted_vllm/rerank/transformation.py:_transform_response: `results=rerank_results,` -> `results=[],` | red then green
test_transform_response_missing_required_fields | keep unit | mutated: litellm/llms/hosted_vllm/rerank/transformation.py:_transform_response: `raise ValueError(f"Missing required fields in the result={result}")` -> `continue` | red then green
test_transform_response_missing_results | keep unit | mutated: litellm/llms/hosted_vllm/rerank/transformation.py:_transform_response: `raise ValueError(f"No results found in the response={response}")` -> `_results = []` | red then green
test_transform_video_create_request_attaches_input_reference_file | keep unit | mutated: litellm/llms/hosted_vllm/videos/transformation.py:transform_video_create_request: `return data, (_input_reference_file(input_reference),), api_base` -> `return {}, (), api_base` | red then green
test_transform_video_create_request_keeps_openai_size_and_seconds | keep unit | mutated: litellm/llms/hosted_vllm/videos/transformation.py:_serialize_form_value: `return value` -> `return "wrong"` | red then green
test_transform_video_create_request_uses_multipart_form_fields | keep unit | mutated: litellm/llms/hosted_vllm/videos/transformation.py:_serialize_form_value: `return value` -> `return "wrong"` | red then green
test_translates_to_browser_search_tool | keep unit | mutated: litellm/llms/groq/chat/transformation.py:get_supported_openai_params: `return base_params` -> `return []` | red then green
test_unsupported_model_drops_param_with_drop_params | keep unit | mutated: litellm/llms/groq/chat/transformation.py:get_supported_openai_params: `if not (` -> `if (` | red then green
test_unsupported_model_raises_without_drop_params | keep unit | mutated: litellm/llms/groq/chat/transformation.py:get_supported_openai_params: `if not (` -> `if (` | red then green
test_user_override_via_register_model | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:github_copilot_supports_responses_api: `return True` -> `return False` | red then green
test_validate_environment | keep unit | mutated: litellm/llms/huggingface/rerank/transformation.py:transform_rerank_response: `return RerankResponse(` -> `return RerankResponse(results=[],` | red then green
test_validate_environment_default_headers | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:validate_environment: `default_headers: Final = get_copilot_default_headers(api_key)` -> `default_headers: Final = {}` | red then green
test_validate_environment_defaults_to_fake_api_key | keep unit | mutated: litellm/llms/hosted_vllm/image_edit/transformation.py:validate_environment: `return {**headers, "Authorization": f"Bearer {resolved_key}"} # mutable-ok: httpx headers are a dict` -> `return {} # mutable-ok: httpx headers are a dict` | red then green
test_validate_environment_defaults_to_fake_api_key | keep unit | mutated: litellm/llms/hosted_vllm/videos/transformation.py:validate_environment: `return {**headers, "Authorization": f"Bearer {resolved_key}"} # mutable-ok: httpx headers are a dict` -> `return headers # mutable-ok: httpx headers are a dict` | red then green
test_validate_environment_falls_back_to_env_api_key | keep unit | mutated: litellm/llms/hosted_vllm/image_edit/transformation.py:validate_environment: `return {**headers, "Authorization": f"Bearer {resolved_key}"} # mutable-ok: httpx headers are a dict` -> `return {} # mutable-ok: httpx headers are a dict` | red then green
test_validate_environment_sets_headers | keep unit | mutated: litellm/llms/gradient_ai/chat/transformation.py:validate_environment: `headers["Authorization"] = f"Bearer {api_key}"` -> `headers["Authorization"] = "wrong"` | red then green
test_validate_environment_user_headers_override | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:validate_environment: `default_headers: Final = get_copilot_default_headers(api_key)` -> `default_headers: Final = {}` | red then green
test_validate_environment_uses_provided_api_key | keep unit | mutated: litellm/llms/hosted_vllm/videos/transformation.py:validate_environment: `return {**headers, "Authorization": f"Bearer {resolved_key}"} # mutable-ok: httpx headers are a dict` -> `return headers # mutable-ok: httpx headers are a dict` | red then green
test_validate_environment_uses_provided_api_key_and_keeps_headers | keep unit | mutated: litellm/llms/hosted_vllm/image_edit/transformation.py:validate_environment: `return {**headers, "Authorization": f"Bearer {resolved_key}"} # mutable-ok: httpx headers are a dict` -> `return {} # mutable-ok: httpx headers are a dict` | red then green
test_validate_environment_with_api_key | keep unit | mutated: litellm/llms/hosted_vllm/embedding/transformation.py:validate_environment: `default_headers["Authorization"] = f"Bearer {api_key}"` -> `default_headers["Authorization"] = "wrong"` | red then green
test_validate_environment_with_vision_header | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:_has_vision_input: `return self._contains_vision_content(input_param)` -> `return False` | red then green
test_validate_environment_with_x_initiator | keep unit | mutated: litellm/llms/github_copilot/responses/transformation.py:_get_initiator: `return "agent"` -> `return "user"` | red then green
test_video_generation_posts_multipart_not_json | keep unit | mutated: litellm/llms/hosted_vllm/videos/transformation.py:get_complete_url: `return f"{trimmed}/v1/videos"` -> `return f"{trimmed}/wrong"` | red then green

User Flow

Test-only change; no user-facing behaviour changes.

Relevant issues

Follows #42103 (phase 0, CircleCI unit job).

Affected release

Linear ticket

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • The handful of test files covering my change pass locally, e.g. uv run pytest tests/test_litellm/<your_test_file>.py -v. Leave the suites (make test-unit-*, make test-unit) to CI: it finishes in ~15 minutes where a laptop takes an hour or more
  • My PR passes all required CI/CD checks (e.g., lint, schema.d.ts sync check, etc.)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review (Greptile reviews automatically once the PR is opened; only comment @greptileai to re-request a review after pushing changes)

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

Screenshots / Proof of Fix

After (4defed7)

  1. LITELLM_LOCAL_MODEL_COST_MAP=True uv run pytest tests/unit -q -p no:cacheprovider → 258 passed
  2. uv run ruff check tests/unit && uv run ruff format --check tests/unit → clean
  3. git status --short litellm/ → empty (all mutations restored)

Type

✅ Test

Caveats (if any)

Low

  • Renamed files also picked up ruff formatting, so rename diffs show wrapping-only churn
  • CircleCI reds on this run are inherited/unrelated: google_generate_content_endpoint_testing fails identically on main (job 2194008: default master-key startup errors + Gemini 429); the three installing_litellm_on_python* jobs failed on proxy startup (UnsafeMasterKeyError, localhost:4000 refused) with no Python changes outside tests/unit in this PR

Final Attestation

  • The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR

Link to Devin session: https://app.devin.ai/sessions/e170adc3f8354f4da4f5771c1148f808
Open in Devin Desktop: https://app.devin.ai/desktop/session/e170adc3f8354f4da4f5771c1148f808?variant=devin

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration
devin-ai-integration Bot requested a review from a team September 20, 2026 08:05
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@greptile-apps

greptile-apps Bot commented Sep 20, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The PR appears safe to merge because it only reorganizes tests and the intentional deletions follow the documented migration contract

Summary

This PR migrates 18 legacy LLM test files into the tiered tests/unit layout and removes seven tests that did not meaningfully validate behavior. The removed coverage is documented for follow-up, and the prior coverage findings were resolved under the repository's test-migration contract

  • Preserves 233 behavior-focused tests under mirrored unit-test paths
  • Removes two SSL verification test files and five other weak tests
  • Applies formatting-only changes to migrated tests
  • Makes no production-code changes

Reviews (2) · Last reviewed commit: "test: migrate wave 1 phase 8 legacy llm ..."

@greptile-apps

greptile-apps Bot commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

Comments Outside Diff

These findings sit on lines the diff does not cover, so they could not be posted inline. Each one leaves this list once its file changes.

  • P2 SSL regression coverage removed tests/test_litellm/llms/hosted_vllm/chat/test_hosted_vllm_ssl_verify.py:147 ▶

    Deleting these tests removes sync and async chat and embedding checks for ssl_verify=False, violating the test-integrity requirement. Restore coverage before merging

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@codecov

codecov Bot commented Sep 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

Re the SSL finding: the four ssl_verify tests wrap the call in except Exception: pass and then only assert that a patched get_httpx_client was called with ssl_verify=False (wiring / mock-configured value), which the migration contract in tests/AGENTS.md rejects on sight. Rejected tests are deleted, not rewritten, and the gap is listed under "Now uncovered" in the PR body.

@greptileai

@greptile-apps

greptile-apps Bot commented Sep 20, 2026

Copy link
Copy Markdown
Contributor

Agreed. The four deleted tests violate the migration contract in tests/AGENTS.md: each wraps the call in except Exception and only verifies that a mocked client factory received ssl_verify=False, so they are wiring/mock-echo tests rather than behavioral regression tests. They should remain deleted rather than be rewritten solely to preserve that coverage. Listing the SSL behavior as an uncovered area in the PR description is appropriate; a future replacement would need to exercise an observable successful request/client behavior without swallowing exceptions.

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

@greptileai please re-review; the three coverage findings are resolved as intentional deletions under the migration contract (see thread replies above).

@yuneng-berri
yuneng-berri merged commit 766f6fc into main Sep 20, 2026
140 of 144 checks passed
@yuneng-berri
yuneng-berri deleted the litellm_migrate_tests_p8 branch September 20, 2026 10:59
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.

1 participant