"""性能测试:权限系统缓存效率 测试权限检查的性能,对比有缓存和无缓存的性能差异。 """ import asyncio import time import uuid from typing import Callable import pytest from sqlalchemy.ext.asyncio import AsyncSession from app.core.permission_cache import PermissionCache, get_permission_cache, set_permission_cache from app.core.project_permissions import ( get_project_role_permissions, role_has_project_permission, role_has_api_permission, ) @pytest.mark.asyncio async def test_permission_check_performance_baseline(db_session: AsyncSession, study_id: uuid.UUID): """基准测试:权限检查性能(无缓存)""" # 清除缓存 cache = get_permission_cache() cache.clear_all() # 执行权限检查 100 次 start_time = time.time() for _ in range(100): await role_has_project_permission(db_session, study_id, "PM", "subjects", "read") elapsed_time = time.time() - start_time # 平均每次权限检查的时间 avg_time = elapsed_time / 100 print(f"\n基准测试(无缓存):{elapsed_time:.3f}s,平均 {avg_time*1000:.2f}ms/次") # 基准测试应该在合理的时间范围内 assert elapsed_time < 10, "权限检查性能过低" @pytest.mark.asyncio async def test_permission_check_performance_with_cache(db_session: AsyncSession, study_id: uuid.UUID): """性能测试:权限检查性能(有缓存)""" # 清除缓存 cache = get_permission_cache() cache.clear_all() # 第一次调用会触发缓存填充 await role_has_project_permission(db_session, study_id, "PM", "subjects", "read") # 执行权限检查 100 次(应该都命中缓存) start_time = time.time() for _ in range(100): await role_has_project_permission(db_session, study_id, "PM", "subjects", "read") elapsed_time = time.time() - start_time # 平均每次权限检查的时间 avg_time = elapsed_time / 100 print(f"\n缓存测试(有缓存):{elapsed_time:.3f}s,平均 {avg_time*1000:.2f}ms/次") # 缓存命中应该非常快 assert elapsed_time < 1, "缓存性能不足" @pytest.mark.asyncio async def test_cache_hit_rate(db_session: AsyncSession, study_id: uuid.UUID): """缓存效率测试:缓存命中率""" cache = get_permission_cache() cache.clear_all() # 执行权限检查,模拟实际场景 # 第一次调用:缓存未命中 await role_has_project_permission(db_session, study_id, "PM", "subjects", "read") # 后续调用:缓存命中 for _ in range(99): await role_has_project_permission(db_session, study_id, "PM", "subjects", "read") # 缓存统计 stats = cache.get_cache_stats() print(f"\n缓存统计:{stats}") # 验证缓存已被使用 assert stats["project_permissions_count"] > 0, "缓存未被使用" @pytest.mark.asyncio async def test_cache_invalidation(db_session: AsyncSession, study_id: uuid.UUID): """缓存失效测试""" cache = get_permission_cache() cache.clear_all() # 填充缓存 await role_has_project_permission(db_session, study_id, "PM", "subjects", "read") assert cache.get_cache_stats()["project_permissions_count"] == 1 # 失效缓存 cache.invalidate_project_permissions(study_id) assert cache.get_cache_stats()["project_permissions_count"] == 0 @pytest.mark.asyncio async def test_concurrent_permission_checks(db_session: AsyncSession, study_id: uuid.UUID): """并发权限检查测试""" cache = get_permission_cache() cache.clear_all() # 并发执行权限检查 async def check_permission(): return await role_has_project_permission(db_session, study_id, "PM", "subjects", "read") start_time = time.time() tasks = [check_permission() for _ in range(100)] results = await asyncio.gather(*tasks) elapsed_time = time.time() - start_time # 所有检查都应该返回相同的结果 assert all(results), "并发权限检查失败" print(f"\n并发测试(100个并发请求):{elapsed_time:.3f}s") @pytest.mark.asyncio async def test_cache_expiration(db_session: AsyncSession, study_id: uuid.UUID): """缓存过期测试""" # 创建一个 TTL 很短的缓存 cache = PermissionCache(default_ttl=1) set_permission_cache(cache) # 填充缓存 permissions = await cache.get_project_role_permissions(db_session, study_id, ttl=1) assert permissions is not None # 等待缓存过期 await asyncio.sleep(1.1) # 再次获取,应该重新从数据库查询 permissions2 = await cache.get_project_role_permissions(db_session, study_id, ttl=1) assert permissions2 is not None @pytest.mark.asyncio async def test_list_operation_performance(db_session: AsyncSession, study_id: uuid.UUID): """列表操作性能测试 模拟列表操作中的权限检查,每个项目都需要进行权限检查。 """ cache = get_permission_cache() cache.clear_all() # 模拟列表操作:检查 50 个项目的权限 start_time = time.time() for i in range(50): # 每个项目都需要检查权限 await role_has_project_permission(db_session, study_id, "PM", "subjects", "read") elapsed_time = time.time() - start_time print(f"\n列表操作性能(50个项目):{elapsed_time:.3f}s,平均 {elapsed_time/50*1000:.2f}ms/项") # 列表操作应该在合理的时间范围内 assert elapsed_time < 5, "列表操作性能过低" @pytest.mark.asyncio async def test_api_permission_check_performance(db_session: AsyncSession, study_id: uuid.UUID): """API权限检查性能测试""" cache = get_permission_cache() cache.clear_all() # 执行 API 权限检查 100 次 start_time = time.time() for _ in range(100): await role_has_api_permission(db_session, study_id, "PM", "POST:/subjects") elapsed_time = time.time() - start_time avg_time = elapsed_time / 100 print(f"\nAPI权限检查性能:{elapsed_time:.3f}s,平均 {avg_time*1000:.2f}ms/次") assert elapsed_time < 10, "API权限检查性能过低" @pytest.mark.asyncio async def test_permission_matrix_caching(db_session: AsyncSession, study_id: uuid.UUID): """权限矩阵缓存测试""" cache = get_permission_cache() cache.clear_all() # 第一次调用:从数据库查询 start_time = time.time() permissions1 = await cache.get_project_role_permissions(db_session, study_id) first_call_time = time.time() - start_time # 第二次调用:从缓存获取 start_time = time.time() permissions2 = await cache.get_project_role_permissions(db_session, study_id) second_call_time = time.time() - start_time # 验证结果相同 assert permissions1 == permissions2 # 缓存调用应该快得多 print(f"\n权限矩阵缓存:第一次 {first_call_time*1000:.2f}ms,第二次 {second_call_time*1000:.2f}ms") assert second_call_time < first_call_time / 2, "缓存性能不足" @pytest.mark.asyncio async def test_member_role_caching(db_session: AsyncSession, study_id: uuid.UUID, user_id: uuid.UUID): """成员角色缓存测试""" cache = get_permission_cache() cache.clear_all() # 第一次调用:从数据库查询 start_time = time.time() role1 = await cache.get_member_role(db_session, study_id, user_id) first_call_time = time.time() - start_time # 第二次调用:从缓存获取 start_time = time.time() role2 = await cache.get_member_role(db_session, study_id, user_id) second_call_time = time.time() - start_time # 验证结果相同 assert role1 == role2 # 缓存调用应该快得多 print(f"\n成员角色缓存:第一次 {first_call_time*1000:.2f}ms,第二次 {second_call_time*1000:.2f}ms") assert second_call_time < first_call_time / 2, "缓存性能不足"