#!/usr/bin/env python3 """ Test script for batch operations functionality. Tests batch deletion and recovery operations for shots and assets. """ import sys import os from datetime import datetime from sqlalchemy.orm import Session # Add the backend directory to the path sys.path.append(os.path.dirname(os.path.abspath(__file__))) from database import SessionLocal from models.user import User from models.shot import Shot from models.asset import Asset from models.task import Task from services.batch_operations import BatchOperationsService def test_batch_operations(): """Test batch operations functionality.""" print("=== Testing Batch Operations ===\n") # Create database session db = SessionLocal() try: # Get a test user (admin) admin_user = db.query(User).filter(User.is_admin == True).first() if not admin_user: print("❌ No admin user found. Please create an admin user first.") return False print(f"Using admin user: {admin_user.first_name} {admin_user.last_name}") # Get some test shots and assets test_shots = db.query(Shot).filter(Shot.deleted_at.is_(None)).limit(3).all() test_assets = db.query(Asset).filter(Asset.deleted_at.is_(None)).limit(2).all() if not test_shots and not test_assets: print("❌ No active shots or assets found for testing.") return False print(f"Found {len(test_shots)} shots and {len(test_assets)} assets for testing") # Initialize batch operations service batch_service = BatchOperationsService() # Test 1: Batch deletion preview print("\n--- Test 1: Batch Deletion Preview ---") shot_ids = [shot.id for shot in test_shots] asset_ids = [asset.id for asset in test_assets] preview = batch_service.get_batch_deletion_preview(shot_ids, asset_ids, db) print(f"Preview Results:") print(f" Total items: {preview['total_items']}") print(f" Estimated tasks: {preview['estimated_tasks']}") print(f" Estimated submissions: {preview['estimated_submissions']}") print(f" Estimated attachments: {preview['estimated_attachments']}") print(f" Estimated notes: {preview['estimated_notes']}") print(f" Estimated reviews: {preview['estimated_reviews']}") print(f" Affected users: {preview['affected_users_count']}") print(f" Projects affected: {preview['projects_affected_count']}") # Test 2: Batch shot deletion if test_shots: print("\n--- Test 2: Batch Shot Deletion ---") shot_ids_to_delete = [shot.id for shot in test_shots[:2]] # Delete first 2 shots result = batch_service.batch_delete_shots(shot_ids_to_delete, db, admin_user, batch_size=10) print(f"Batch Deletion Results:") print(f" Total items: {result.total_items}") print(f" Successful deletions: {result.successful_deletions}") print(f" Failed deletions: {result.failed_deletions}") print(f" Operation duration: {result.operation_duration:.2f}s") print(f" Total deleted tasks: {result.total_deleted_tasks}") print(f" Total deleted submissions: {result.total_deleted_submissions}") for item in result.items: status = "✓" if item.success else "✗" print(f" {status} Shot {item.id} ({item.name}): {item.error or 'Success'}") # Test 3: Batch asset deletion if test_assets: print("\n--- Test 3: Batch Asset Deletion ---") asset_ids_to_delete = [asset.id for asset in test_assets[:1]] # Delete first asset result = batch_service.batch_delete_assets(asset_ids_to_delete, db, admin_user, batch_size=10) print(f"Batch Deletion Results:") print(f" Total items: {result.total_items}") print(f" Successful deletions: {result.successful_deletions}") print(f" Failed deletions: {result.failed_deletions}") print(f" Operation duration: {result.operation_duration:.2f}s") print(f" Total deleted tasks: {result.total_deleted_tasks}") for item in result.items: status = "✓" if item.success else "✗" print(f" {status} Asset {item.id} ({item.name}): {item.error or 'Success'}") # Test 4: Batch shot recovery if test_shots: print("\n--- Test 4: Batch Shot Recovery ---") shot_ids_to_recover = [shot.id for shot in test_shots[:2]] result = batch_service.batch_recover_shots(shot_ids_to_recover, db, admin_user, batch_size=10) print(f"Batch Recovery Results:") print(f" Total items: {result.total_items}") print(f" Successful recoveries: {result.successful_recoveries}") print(f" Failed recoveries: {result.failed_recoveries}") print(f" Operation duration: {result.operation_duration:.2f}s") print(f" Total recovered tasks: {result.total_recovered_tasks}") for item in result.items: status = "✓" if item.success else "✗" print(f" {status} Shot {item.id} ({item.name}): {item.error or 'Success'}") # Test 5: Batch asset recovery if test_assets: print("\n--- Test 5: Batch Asset Recovery ---") asset_ids_to_recover = [asset.id for asset in test_assets[:1]] result = batch_service.batch_recover_assets(asset_ids_to_recover, db, admin_user, batch_size=10) print(f"Batch Recovery Results:") print(f" Total items: {result.total_items}") print(f" Successful recoveries: {result.successful_recoveries}") print(f" Failed recoveries: {result.failed_recoveries}") print(f" Operation duration: {result.operation_duration:.2f}s") print(f" Total recovered tasks: {result.total_recovered_tasks}") for item in result.items: status = "✓" if item.success else "✗" print(f" {status} Asset {item.id} ({item.name}): {item.error or 'Success'}") # Test 6: Batch size optimization print("\n--- Test 6: Batch Size Optimization ---") # Test with different scenarios scenarios = [ (100, 0, "Simple items with no related data"), (50, 500, "Moderate complexity"), (20, 2000, "High complexity"), (10, 5000, "Very high complexity") ] for total_items, related_items, description in scenarios: optimal_size = batch_service.optimize_batch_size(total_items, related_items) print(f" {description}: {total_items} items, {related_items} related → batch size: {optimal_size}") print("\n✓ All batch operations tests completed successfully!") return True except Exception as e: print(f"❌ Test failed with error: {str(e)}") import traceback traceback.print_exc() return False finally: db.close() def test_performance_monitoring(): """Test performance monitoring for batch operations.""" print("\n=== Testing Performance Monitoring ===\n") db = SessionLocal() try: # Count current database records shot_count = db.query(Shot).count() asset_count = db.query(Asset).count() task_count = db.query(Task).count() print(f"Current Database State:") print(f" Shots: {shot_count}") print(f" Assets: {asset_count}") print(f" Tasks: {task_count}") # Count deleted records deleted_shots = db.query(Shot).filter(Shot.deleted_at.isnot(None)).count() deleted_assets = db.query(Asset).filter(Asset.deleted_at.isnot(None)).count() deleted_tasks = db.query(Task).filter(Task.deleted_at.isnot(None)).count() print(f"\nDeleted Records:") print(f" Deleted shots: {deleted_shots}") print(f" Deleted assets: {deleted_assets}") print(f" Deleted tasks: {deleted_tasks}") # Performance metrics batch_service = BatchOperationsService() # Test optimal batch sizes for different scenarios print(f"\nOptimal Batch Sizes:") test_cases = [ (10, 50), (100, 500), (500, 2500), (1000, 10000) ] for items, related in test_cases: optimal = batch_service.optimize_batch_size(items, related) complexity = related / items if items > 0 else 0 print(f" {items} items, {related} related (complexity: {complexity:.1f}) → batch size: {optimal}") return True except Exception as e: print(f"❌ Performance monitoring test failed: {str(e)}") return False finally: db.close() if __name__ == "__main__": print("Batch Operations Test Suite") print("=" * 50) success1 = test_batch_operations() success2 = test_performance_monitoring() if success1 and success2: print("\n🎉 All tests passed!") sys.exit(0) else: print("\n❌ Some tests failed!") sys.exit(1)