#!/usr/bin/env python3 """ Resource Limits Enforcement Test Script Tests that container resource limits are properly applied and enforced, preventing resource exhaustion attacks and ensuring fair resource allocation. """ import os import sys import asyncio import json import time from pathlib import Path # Add session-manager to path for imports sys.path.insert(0, str(Path(__file__).parent)) from resource_manager import ( get_resource_limits, check_system_resources, should_throttle_sessions, ResourceLimits, ResourceValidator, ResourceMonitor, ) # Set up logging import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) async def test_resource_limits_configuration(): """Test resource limits configuration and validation.""" print("๐Ÿงช Testing Resource Limits Configuration") print("=" * 50) # Test default configuration print("1๏ธโƒฃ Testing default configuration...") try: limits = get_resource_limits() print( f"โœ… Default limits loaded: memory={limits.memory_limit}, cpu_quota={limits.cpu_quota}" ) # Validate limits valid, message = limits.validate() if valid: print("โœ… Default limits validation passed") else: print(f"โŒ Default limits validation failed: {message}") return False except Exception as e: print(f"โŒ Failed to load default configuration: {e}") return False # Test custom configuration print("\n2๏ธโƒฃ Testing custom configuration...") test_configs = [ {"memory_limit": "2g", "cpu_quota": 50000, "cpu_period": 100000}, {"memory_limit": "512m", "cpu_quota": 25000, "cpu_period": 100000}, {"memory_limit": "8g", "cpu_quota": 200000, "cpu_period": 100000}, ] for config in test_configs: try: valid, message, limits = ResourceValidator.validate_resource_config(config) if valid: print(f"โœ… Config {config} validated successfully") else: print(f"โŒ Config {config} validation failed: {message}") return False except Exception as e: print(f"โŒ Config {config} validation error: {e}") return False # Test invalid configurations print("\n3๏ธโƒฃ Testing invalid configurations...") invalid_configs = [ { "memory_limit": "0g", "cpu_quota": 100000, "cpu_period": 100000, }, # Zero memory { "memory_limit": "1g", "cpu_quota": 200000, "cpu_period": 100000, }, # CPU quota > period { "memory_limit": "1g", "cpu_quota": -1000, "cpu_period": 100000, }, # Negative CPU ] for config in invalid_configs: valid, message, limits = ResourceValidator.validate_resource_config(config) if not valid: print(f"โœ… Correctly rejected invalid config {config}: {message}") else: print(f"โŒ Incorrectly accepted invalid config {config}") return False return True async def test_resource_monitoring(): """Test system resource monitoring.""" print("\n๐Ÿ–ฅ๏ธ Testing System Resource Monitoring") print("=" * 50) # Test resource monitoring print("1๏ธโƒฃ Testing system resource monitoring...") try: resource_check = check_system_resources() print("โœ… System resource check completed") if isinstance(resource_check, dict): system_resources = resource_check.get("system_resources", {}) alerts = resource_check.get("alerts", []) print(f"๐Ÿ“Š System resources: {len(system_resources)} metrics collected") print(f"๐Ÿšจ Resource alerts: {len(alerts)} detected") for alert in alerts: print( f" {alert.get('level', 'unknown').upper()}: {alert.get('message', 'No message')}" ) # Test throttling logic should_throttle, reason = should_throttle_sessions() print(f"๐ŸŽ›๏ธ Session throttling: {'YES' if should_throttle else 'NO'} - {reason}") except Exception as e: print(f"โŒ Resource monitoring test failed: {e}") return False return True async def test_memory_limit_parsing(): """Test memory limit parsing functionality.""" print("\n๐Ÿ’พ Testing Memory Limit Parsing") print("=" * 50) test_cases = [ ("4g", (4 * 1024**3, "GB")), ("512m", (512 * 1024**2, "MB")), ("256k", (256 * 1024, "KB")), ("1073741824", (1073741824, "bytes")), # 1GB in bytes ] for memory_str, expected in test_cases: try: bytes_val, unit = ResourceValidator.parse_memory_limit(memory_str) if bytes_val == expected[0] and unit == expected[1]: print(f"โœ… Parsed {memory_str} -> {bytes_val} {unit}") else: print( f"โŒ Failed to parse {memory_str}: got {bytes_val} {unit}, expected {expected}" ) return False except Exception as e: print(f"โŒ Error parsing {memory_str}: {e}") return False return True async def test_docker_limits_conversion(): """Test Docker limits conversion.""" print("\n๐Ÿณ Testing Docker Limits Conversion") print("=" * 50) limits = ResourceLimits( memory_limit="2g", cpu_quota=75000, cpu_period=100000, ) docker_limits = limits.to_docker_limits() expected = { "mem_limit": "2g", "cpu_quota": 75000, "cpu_period": 100000, } if docker_limits == expected: print("โœ… Docker limits conversion correct") return True else: print(f"โŒ Docker limits conversion failed: {docker_limits} != {expected}") return False async def test_environment_variables(): """Test environment variable configuration.""" print("\n๐ŸŒ Testing Environment Variable Configuration") print("=" * 50) # Save original environment original_env = {} test_vars = [ "CONTAINER_MEMORY_LIMIT", "CONTAINER_CPU_QUOTA", "CONTAINER_CPU_PERIOD", "MAX_CONCURRENT_SESSIONS", "MEMORY_WARNING_THRESHOLD", "CPU_WARNING_THRESHOLD", ] for var in test_vars: original_env[var] = os.environ.get(var) try: # Test custom environment configuration os.environ["CONTAINER_MEMORY_LIMIT"] = "3g" os.environ["CONTAINER_CPU_QUOTA"] = "80000" os.environ["CONTAINER_CPU_PERIOD"] = "100000" os.environ["MAX_CONCURRENT_SESSIONS"] = "5" # Force reload of configuration import importlib import resource_manager importlib.reload(resource_manager) limits = resource_manager.get_resource_limits() if limits.memory_limit == "3g" and limits.cpu_quota == 80000: print("โœ… Environment variable configuration working") return True else: print(f"โŒ Environment variable configuration failed: got {limits}") return False finally: # Restore original environment for var, value in original_env.items(): if value is not None: os.environ[var] = value elif var in os.environ: del os.environ[var] async def run_all_tests(): """Run all resource limit tests.""" print("๐Ÿš€ Resource Limits Enforcement Test Suite") print("=" * 60) tests = [ ("Resource Limits Configuration", test_resource_limits_configuration), ("System Resource Monitoring", test_resource_monitoring), ("Memory Limit Parsing", test_memory_limit_parsing), ("Docker Limits Conversion", test_docker_limits_conversion), ("Environment Variables", test_environment_variables), ] results = [] for test_name, test_func in tests: print(f"\n{'=' * 20} {test_name} {'=' * 20}") try: result = await test_func() results.append(result) status = "โœ… PASSED" if result else "โŒ FAILED" print(f"\n{status}: {test_name}") except Exception as e: print(f"\nโŒ ERROR in {test_name}: {e}") results.append(False) # Summary print(f"\n{'=' * 60}") passed = sum(results) total = len(results) print(f"๐Ÿ“Š Test Results: {passed}/{total} tests passed") if passed == total: print("๐ŸŽ‰ All resource limit tests completed successfully!") print("๐Ÿ’ช Container resource limits are properly configured and enforced.") else: print("โš ๏ธ Some tests failed. Check the output above for details.") sys.exit(1) if __name__ == "__main__": asyncio.run(run_all_tests())