""" Tests for the ``aliases`` feature in the model cost map. The ``_expand_model_aliases`` function processes ``aliases`` lists from model entries, creating shared dict references for alias entries at load time. """ from unittest.mock import patch from litellm import verbose_logger from litellm.litellm_core_utils.get_model_cost_map import _expand_model_aliases # --------------------------------------------------------------------------- # Core expansion behaviour # --------------------------------------------------------------------------- class TestExpandModelAliases: """Unit tests for _expand_model_aliases.""" def test_basic_expansion(self): """Aliases are added as top-level entries in model_cost.""" model_cost = { "my-model-latest": { "aliases": ["my-model-20250101"], "input_cost_per_token": 1e-06, "litellm_provider": "test", "mode": "chat", }, } result = _expand_model_aliases(model_cost) assert "my-model-20250101" in result assert result["my-model-20250101"]["input_cost_per_token"] == 1e-06 assert result["my-model-20250101"]["litellm_provider"] == "test" def test_multiple_aliases(self): """A single entry can declare multiple aliases.""" model_cost = { "provider/model-latest": { "aliases": ["provider/model-v1", "provider/model-v2"], "input_cost_per_token": 5e-06, "litellm_provider": "provider", "mode": "chat", }, } result = _expand_model_aliases(model_cost) assert "provider/model-v1" in result assert "provider/model-v2" in result def test_shared_dict_reference(self): """Alias entries share the same dict object as the canonical entry (no copy).""" model_cost = { "canonical-model": { "aliases": ["alias-model"], "input_cost_per_token": 2e-06, "litellm_provider": "test", "mode": "chat", }, } result = _expand_model_aliases(model_cost) assert result["alias-model"] is result["canonical-model"] def test_aliases_key_removed(self): """The ``aliases`` key is removed from the entry after expansion.""" model_cost = { "my-model": { "aliases": ["my-model-alias"], "input_cost_per_token": 1e-06, "litellm_provider": "test", "mode": "chat", }, } result = _expand_model_aliases(model_cost) assert "aliases" not in result["my-model"] assert "aliases" not in result["my-model-alias"] def test_entries_without_aliases_unchanged(self): """Entries with no ``aliases`` key are left untouched.""" model_cost = { "plain-model": { "input_cost_per_token": 3e-06, "litellm_provider": "test", "mode": "chat", }, } result = _expand_model_aliases(model_cost) assert "plain-model" in result assert result["plain-model"]["input_cost_per_token"] == 3e-06 assert len(result) == 1 def test_empty_aliases_list(self): """An empty ``aliases`` list is treated the same as no aliases.""" model_cost = { "model-a": { "aliases": [], "input_cost_per_token": 1e-06, "litellm_provider": "test", "mode": "chat", }, } result = _expand_model_aliases(model_cost) assert len(result) == 1 assert "model-a" in result assert "aliases" not in result["model-a"] # --------------------------------------------------------------------------- # Conflict handling # --------------------------------------------------------------------------- class TestAliasConflicts: """Tests for alias conflict detection and handling.""" def test_alias_conflicts_with_canonical_entry(self): """Alias that matches an existing canonical entry is skipped with a warning.""" model_cost = { "model-latest": { "aliases": ["model-dated"], "input_cost_per_token": 1e-06, "litellm_provider": "test", "mode": "chat", }, "model-dated": { "input_cost_per_token": 1e-06, "litellm_provider": "test", "mode": "chat", }, } with patch.object(verbose_logger, "warning") as mock_warn: result = _expand_model_aliases(model_cost) # The canonical "model-dated" entry is preserved, not overwritten assert "model-dated" in result # Verify a warning about the alias conflict was logged mock_warn.assert_called() warning_messages = " ".join(str(c) for c in mock_warn.call_args_list) assert "alias conflict" in warning_messages.lower() def test_duplicate_alias_across_entries(self): """Same alias claimed by two different entries: second one is skipped.""" model_cost = { "model-a": { "aliases": ["shared-alias"], "input_cost_per_token": 1e-06, "litellm_provider": "test", "mode": "chat", }, "model-b": { "aliases": ["shared-alias"], "input_cost_per_token": 2e-06, "litellm_provider": "test", "mode": "chat", }, } with patch.object(verbose_logger, "warning") as mock_warn: result = _expand_model_aliases(model_cost) # "shared-alias" should point to model-a (first one wins) assert "shared-alias" in result assert result["shared-alias"]["input_cost_per_token"] == 1e-06 # Verify a warning about the alias conflict was logged mock_warn.assert_called() warning_messages = " ".join(str(c) for c in mock_warn.call_args_list) assert "alias conflict" in warning_messages.lower() def test_canonical_entry_not_overwritten_by_alias(self): """An alias must never overwrite an existing canonical entry's data.""" original_cost = 9.99e-06 model_cost = { "existing-model": { "input_cost_per_token": original_cost, "litellm_provider": "test", "mode": "chat", }, "other-model": { "aliases": ["existing-model"], "input_cost_per_token": 1e-06, "litellm_provider": "test", "mode": "chat", }, } result = _expand_model_aliases(model_cost) # Original entry must be preserved assert result["existing-model"]["input_cost_per_token"] == original_cost # --------------------------------------------------------------------------- # Integration with model_cost dict mutation # --------------------------------------------------------------------------- class TestAliasIntegration: """Higher-level tests verifying aliases work with the model_cost dict.""" def test_mutation_through_alias_visible_on_canonical(self): """Since alias is a shared reference, mutations are visible on both.""" model_cost = { "canonical": { "aliases": ["alias"], "input_cost_per_token": 1e-06, "litellm_provider": "test", "mode": "chat", }, } result = _expand_model_aliases(model_cost) # Mutate via alias result["alias"]["input_cost_per_token"] = 999 assert result["canonical"]["input_cost_per_token"] == 999 def test_mixed_entries_with_and_without_aliases(self): """A model_cost dict with a mix of aliased and plain entries.""" model_cost = { "model-with-alias": { "aliases": ["alias-1", "alias-2"], "input_cost_per_token": 1e-06, "litellm_provider": "test", "mode": "chat", }, "plain-model": { "input_cost_per_token": 2e-06, "litellm_provider": "test", "mode": "chat", }, } result = _expand_model_aliases(model_cost) assert len(result) == 4 # 2 canonical + 2 aliases assert "alias-1" in result assert "alias-2" in result assert "plain-model" in result assert "model-with-alias" in result def test_expand_on_empty_dict(self): """Expanding an empty dict returns an empty dict.""" assert _expand_model_aliases({}) == {}