Skip to main content
Glama
test_model_restrictions.pyโ€ข17.5 kB
#!/usr/bin/env python3 """ Model Restriction Testing Script Tests model filtering, cost control, and provider restrictions """ import os import tempfile from unittest.mock import patch import pytest # Add project root to path import sys from pathlib import Path sys.path.append(str(Path(__file__).parent.parent.parent)) from utils.models import ModelRestrictionService, select_best_model, get_model_context_limit class TestModelRestrictions: """Test model restriction functionality""" def setup_method(self): """Setup for each test""" # Save original environment self.original_env = {} for key in [ "OPENAI_ALLOWED_MODELS", "GOOGLE_ALLOWED_MODELS", "ANTHROPIC_ALLOWED_MODELS", "BLOCKED_MODELS", "DISABLED_MODEL_PATTERNS", ]: self.original_env[key] = os.environ.get(key) def teardown_method(self): """Restore original environment""" for key, value in self.original_env.items(): if value is not None: os.environ[key] = value else: os.environ.pop(key, None) def test_restriction_service_initialization(self): """Test ModelRestrictionService initialization""" service = ModelRestrictionService() assert hasattr(service, "openai_allowed") assert hasattr(service, "google_allowed") assert hasattr(service, "anthropic_allowed") assert hasattr(service, "blocked_models") assert hasattr(service, "disabled_patterns") def test_openai_model_restrictions(self): """Test OpenAI model restrictions""" # Set specific allowed models os.environ["OPENAI_ALLOWED_MODELS"] = "gpt-4,gpt-4o,o1-mini" service = ModelRestrictionService() # Allowed models assert service.is_model_allowed("gpt-4") assert service.is_model_allowed("gpt-4o") assert service.is_model_allowed("o1-mini") # Not allowed models assert not service.is_model_allowed("gpt-3.5-turbo") assert not service.is_model_allowed("text-davinci-003") def test_google_model_restrictions(self): """Test Google/Gemini model restrictions""" # Set specific allowed models os.environ["GOOGLE_ALLOWED_MODELS"] = "gemini-1.5-pro,gemini-2.0-flash" service = ModelRestrictionService() # Allowed models assert service.is_model_allowed("gemini-1.5-pro") assert service.is_model_allowed("gemini-2.0-flash") # Not allowed models assert not service.is_model_allowed("gemini-1.0-pro") assert not service.is_model_allowed("gemini-1.5-flash") def test_anthropic_model_restrictions(self): """Test Anthropic model restrictions""" # Set specific allowed models os.environ["ANTHROPIC_ALLOWED_MODELS"] = "claude-3-5-sonnet-20241022,claude-3-haiku-20240307" service = ModelRestrictionService() # Allowed models assert service.is_model_allowed("claude-3-5-sonnet-20241022") assert service.is_model_allowed("claude-3-haiku-20240307") # Not allowed models assert not service.is_model_allowed("claude-2.1") assert not service.is_model_allowed("claude-3-opus-20240229") def test_blocked_models(self): """Test globally blocked models""" os.environ["BLOCKED_MODELS"] = "gpt-4,claude-3-opus-20240229,gemini-1.0-pro" service = ModelRestrictionService() # These should be blocked regardless of provider settings assert not service.is_model_allowed("gpt-4") assert not service.is_model_allowed("claude-3-opus-20240229") assert not service.is_model_allowed("gemini-1.0-pro") # These should still be allowed assert service.is_model_allowed("gpt-4o") assert service.is_model_allowed("claude-3-5-sonnet-20241022") assert service.is_model_allowed("gemini-2.0-flash") def test_disabled_model_patterns(self): """Test pattern-based model disabling""" os.environ["DISABLED_MODEL_PATTERNS"] = "gpt-3,claude-2,mini" service = ModelRestrictionService() # Models matching patterns should be blocked assert not service.is_model_allowed("gpt-3.5-turbo") assert not service.is_model_allowed("claude-2.1") assert not service.is_model_allowed("gpt-4o-mini") assert not service.is_model_allowed("o1-mini") # Models not matching patterns should be allowed assert service.is_model_allowed("gpt-4") assert service.is_model_allowed("claude-3-5-sonnet-20241022") assert service.is_model_allowed("gemini-2.0-flash") def test_combined_restrictions(self): """Test multiple restriction types working together""" # Set up complex restrictions os.environ["OPENAI_ALLOWED_MODELS"] = "gpt-4,gpt-4o,o1-mini" os.environ["BLOCKED_MODELS"] = "gpt-4" # Block gpt-4 even though it's in allowed os.environ["DISABLED_MODEL_PATTERNS"] = "mini" # Block anything with 'mini' service = ModelRestrictionService() # gpt-4 is allowed by OpenAI list but blocked globally assert not service.is_model_allowed("gpt-4") # o1-mini is allowed by OpenAI list but blocked by pattern assert not service.is_model_allowed("o1-mini") # gpt-4o passes all restrictions assert service.is_model_allowed("gpt-4o") # Non-OpenAI models not in allowed lists should be rejected assert not service.is_model_allowed("gemini-2.0-flash") def test_case_insensitive_restrictions(self): """Test that restrictions work case-insensitively""" os.environ["BLOCKED_MODELS"] = "GPT-4,Claude-3-Opus" os.environ["DISABLED_MODEL_PATTERNS"] = "MINI,FLASH" service = ModelRestrictionService() # Should block regardless of case assert not service.is_model_allowed("gpt-4") assert not service.is_model_allowed("GPT-4") assert not service.is_model_allowed("claude-3-opus-20240229") assert not service.is_model_allowed("CLAUDE-3-OPUS-20240229") # Pattern matching should be case-insensitive assert not service.is_model_allowed("gpt-4o-mini") assert not service.is_model_allowed("GPT-4O-MINI") assert not service.is_model_allowed("gemini-2.0-flash") assert not service.is_model_allowed("GEMINI-2.0-FLASH") def test_empty_restrictions(self): """Test behavior with empty restriction lists""" # Clear all restrictions for key in [ "OPENAI_ALLOWED_MODELS", "GOOGLE_ALLOWED_MODELS", "ANTHROPIC_ALLOWED_MODELS", "BLOCKED_MODELS", "DISABLED_MODEL_PATTERNS", ]: os.environ.pop(key, None) service = ModelRestrictionService() # With no restrictions, all models should be allowed assert service.is_model_allowed("gpt-4") assert service.is_model_allowed("claude-3-5-sonnet-20241022") assert service.is_model_allowed("gemini-2.0-flash") assert service.is_model_allowed("random-model-name") def test_whitespace_handling_in_restrictions(self): """Test handling of whitespace in restriction strings""" # Set restrictions with extra whitespace os.environ["OPENAI_ALLOWED_MODELS"] = " gpt-4 , gpt-4o , o1-mini " os.environ["BLOCKED_MODELS"] = " claude-3-opus , gemini-1.0-pro " service = ModelRestrictionService() # Should handle whitespace correctly assert service.is_model_allowed("gpt-4") assert service.is_model_allowed("gpt-4o") assert service.is_model_allowed("o1-mini") assert not service.is_model_allowed("claude-3-opus") assert not service.is_model_allowed("gemini-1.0-pro") def test_restriction_summary(self): """Test getting restriction summary""" os.environ["OPENAI_ALLOWED_MODELS"] = "gpt-4,gpt-4o" os.environ["GOOGLE_ALLOWED_MODELS"] = "gemini-2.0-flash" os.environ["BLOCKED_MODELS"] = "dangerous-model" os.environ["DISABLED_MODEL_PATTERNS"] = "old,deprecated" service = ModelRestrictionService() summary = service.get_restriction_summary() assert "openai_allowed" in summary assert "google_allowed" in summary assert "anthropic_allowed" in summary assert "blocked_models" in summary assert "disabled_patterns" in summary assert "gpt-4" in summary["openai_allowed"] assert "gpt-4o" in summary["openai_allowed"] assert "gemini-2.0-flash" in summary["google_allowed"] assert "dangerous-model" in summary["blocked_models"] assert "old" in summary["disabled_patterns"] assert "deprecated" in summary["disabled_patterns"] def test_model_auto_selection_with_restrictions(self): """Test model auto-selection respects restrictions""" # Set restrictions that limit available models os.environ["OPENAI_ALLOWED_MODELS"] = "gpt-4o-mini" os.environ["GOOGLE_ALLOWED_MODELS"] = "gemini-1.5-flash" os.environ["BLOCKED_MODELS"] = "gpt-4,claude-3-5-sonnet-20241022" # Test different modes and contexts test_cases = [ ("chat", 1000, 0), # Small prompt, chat mode ("analyze", 50000, 5), # Large prompt, analyze mode ("think", 10000, 2), # Medium prompt, think mode ] for mode, prompt_size, file_count in test_cases: selected_model = select_best_model(mode, prompt_size, file_count) # Selected model should be allowed by restrictions service = ModelRestrictionService() assert service.is_model_allowed( selected_model ), f"Auto-selected model {selected_model} violates restrictions for mode {mode}" def test_cost_control_through_restrictions(self): """Test using restrictions for cost control""" # Block expensive models, allow only cheaper ones os.environ["BLOCKED_MODELS"] = "gpt-4,claude-3-5-sonnet-20241022,gemini-1.5-pro,o1-preview" os.environ["OPENAI_ALLOWED_MODELS"] = "gpt-4o-mini" os.environ["GOOGLE_ALLOWED_MODELS"] = "gemini-1.5-flash" os.environ["ANTHROPIC_ALLOWED_MODELS"] = "claude-3-haiku-20240307" service = ModelRestrictionService() # Expensive models should be blocked expensive_models = ["gpt-4", "claude-3-5-sonnet-20241022", "gemini-1.5-pro", "o1-preview"] for model in expensive_models: assert not service.is_model_allowed(model), f"Expensive model {model} should be blocked" # Cheaper models should be allowed cheaper_models = ["gpt-4o-mini", "gemini-1.5-flash", "claude-3-haiku-20240307"] for model in cheaper_models: assert service.is_model_allowed(model), f"Cheaper model {model} should be allowed" def test_development_vs_production_restrictions(self): """Test different restrictions for different environments""" # Development environment - allow experimental models dev_restrictions = { "OPENAI_ALLOWED_MODELS": "gpt-4,gpt-4o,o1-preview,o1-mini", "GOOGLE_ALLOWED_MODELS": "gemini-2.0-flash,gemini-1.5-pro", "ANTHROPIC_ALLOWED_MODELS": "claude-3-5-sonnet-20241022,claude-3-haiku-20240307", } # Production environment - only stable models prod_restrictions = { "OPENAI_ALLOWED_MODELS": "gpt-4o-mini", "GOOGLE_ALLOWED_MODELS": "gemini-1.5-flash", "ANTHROPIC_ALLOWED_MODELS": "claude-3-haiku-20240307", "BLOCKED_MODELS": "o1-preview,o1-mini,gemini-2.0-flash", # Block experimental } # Test development restrictions for key, value in dev_restrictions.items(): os.environ[key] = value dev_service = ModelRestrictionService() assert dev_service.is_model_allowed("o1-preview") # Experimental allowed in dev assert dev_service.is_model_allowed("gemini-2.0-flash") # Test production restrictions for key, value in prod_restrictions.items(): os.environ[key] = value prod_service = ModelRestrictionService() assert not prod_service.is_model_allowed("o1-preview") # Experimental blocked in prod assert not prod_service.is_model_allowed("gemini-2.0-flash") assert prod_service.is_model_allowed("gpt-4o-mini") # Stable allowed def test_model_context_limits_with_restrictions(self): """Test that context limits work with model restrictions""" # Set up model with known context limit test_model = "gpt-4" expected_limit = get_model_context_limit(test_model) # Ensure we get a reasonable limit assert expected_limit > 0 assert expected_limit >= 8000 # GPT-4 should have at least 8K context # Test with restricted model os.environ["BLOCKED_MODELS"] = test_model service = ModelRestrictionService() # Model should be blocked even though we can get its context limit assert not service.is_model_allowed(test_model) def test_provider_specific_restrictions(self): """Test that provider-specific logic works correctly""" service = ModelRestrictionService() # Test OpenAI model detection openai_models = ["gpt-4", "gpt-3.5-turbo", "o1-preview", "o3-mini"] for model in openai_models: # These should be detected as OpenAI models assert model.startswith(("gpt", "o1", "o3")) # Test Google model detection google_models = ["gemini-1.5-pro", "gemini-2.0-flash"] for model in google_models: # These should be detected as Google models assert model.startswith("gemini") # Test Anthropic model detection anthropic_models = ["claude-3-5-sonnet-20241022", "claude-3-haiku-20240307"] for model in anthropic_models: # These should be detected as Anthropic models assert model.startswith("claude") class TestModelRestrictionIntegration: """Test model restriction integration with other components""" def setup_method(self): """Setup for integration tests""" self.original_env = {} for key in [ "OPENAI_ALLOWED_MODELS", "GOOGLE_ALLOWED_MODELS", "ANTHROPIC_ALLOWED_MODELS", "BLOCKED_MODELS", "DISABLED_MODEL_PATTERNS", ]: self.original_env[key] = os.environ.get(key) def teardown_method(self): """Restore environment""" for key, value in self.original_env.items(): if value is not None: os.environ[key] = value else: os.environ.pop(key, None) def test_restrictions_with_model_selection(self): """Test restrictions work with automatic model selection""" # Allow only specific models os.environ["OPENAI_ALLOWED_MODELS"] = "gpt-4o-mini" os.environ["GOOGLE_ALLOWED_MODELS"] = "gemini-1.5-flash" # Test that auto-selection respects restrictions for mode in ["chat", "analyze", "debug"]: selected = select_best_model(mode, 1000, 0) service = ModelRestrictionService() # Should select an allowed model assert service.is_model_allowed(selected), f"Auto-selected {selected} for {mode} mode violates restrictions" def test_restrictions_error_scenarios(self): """Test error handling when all models are restricted""" # Block everything os.environ["BLOCKED_MODELS"] = "gpt,claude,gemini,llama,mistral,phi" service = ModelRestrictionService() # Common models should be blocked common_models = ["gpt-4", "gpt-4o", "claude-3-5-sonnet-20241022", "gemini-2.0-flash", "llama-3-8b"] for model in common_models: assert not service.is_model_allowed(model) # This should still work for unknown models assert service.is_model_allowed("unknown-model-12345") if __name__ == "__main__": # Run individual tests import argparse parser = argparse.ArgumentParser(description="Test Model Restrictions") parser.add_argument("--test", help="Specific test to run") parser.add_argument("--verbose", "-v", action="store_true", help="Verbose output") parser.add_argument("--integration", action="store_true", help="Run integration tests only") args = parser.parse_args() if args.integration: pytest.main([f"{__file__}::TestModelRestrictionIntegration", "-v" if args.verbose else ""]) elif args.test: if "." in args.test: pytest.main([f"{__file__}::{args.test}", "-v" if args.verbose else ""]) else: # Try both classes for class_name in ["TestModelRestrictions", "TestModelRestrictionIntegration"]: try: pytest.main([f"{__file__}::{class_name}::test_{args.test}", "-v" if args.verbose else ""]) break except: continue else: print(f"โŒ Test {args.test} not found") else: # Run all tests pytest.main([__file__, "-v" if args.verbose else ""])

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/david-strejc/sage-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server