|
7 | 7 |
|
8 | 8 | import pytest |
9 | 9 |
|
10 | | -from agents.memory.providers.redis import RedisSession, RedisSessionManager |
| 10 | +from agents.memory.providers.redis import RedisSession |
11 | 11 |
|
12 | 12 |
|
13 | 13 | class TestRedisSession: |
@@ -336,214 +336,3 @@ def test_session_without_ttl(self): |
336 | 336 | """Test session creation without TTL.""" |
337 | 337 | session = RedisSession("test_session", ttl=None) |
338 | 338 | assert session.ttl is None |
339 | | - |
340 | | - |
341 | | -class TestRedisSessionManager: |
342 | | - """Test cases for RedisSessionManager class.""" |
343 | | - |
344 | | - @pytest.fixture |
345 | | - def session_manager(self): |
346 | | - """Create a RedisSessionManager instance for testing.""" |
347 | | - return RedisSessionManager( |
348 | | - redis_url="redis://localhost:6379", |
349 | | - db=1, |
350 | | - session_prefix="manager_session", |
351 | | - messages_prefix="manager_messages", |
352 | | - default_ttl=7200, |
353 | | - max_connections=5, |
354 | | - ) |
355 | | - |
356 | | - def test_init(self, session_manager): |
357 | | - """Test RedisSessionManager initialization.""" |
358 | | - assert session_manager.redis_url == "redis://localhost:6379" |
359 | | - assert session_manager.db == 1 |
360 | | - assert session_manager.session_prefix == "manager_session" |
361 | | - assert session_manager.messages_prefix == "manager_messages" |
362 | | - assert session_manager.default_ttl == 7200 |
363 | | - # Note: We don't need to test the internal pool creation since it's an implementation detail |
364 | | - |
365 | | - @patch('agents.memory.providers.redis.redis.Redis') |
366 | | - def test_get_session(self, mock_redis_class, session_manager): |
367 | | - """Test getting a session instance.""" |
368 | | - mock_redis_instance = MagicMock() |
369 | | - mock_redis_class.return_value = mock_redis_instance |
370 | | - |
371 | | - session = session_manager.get_session("test_session_456", ttl=1800) |
372 | | - |
373 | | - assert isinstance(session, RedisSession) |
374 | | - assert session.session_id == "test_session_456" |
375 | | - assert session.redis_url == "redis://localhost:6379" |
376 | | - assert session.db == 1 |
377 | | - assert session.session_prefix == "manager_session" |
378 | | - assert session.messages_prefix == "manager_messages" |
379 | | - assert session.ttl == 1800 |
380 | | - |
381 | | - # Verify Redis instance was created with connection pool |
382 | | - mock_redis_class.assert_called_once() |
383 | | - call_kwargs = mock_redis_class.call_args[1] |
384 | | - assert 'connection_pool' in call_kwargs |
385 | | - assert session._redis_client == mock_redis_instance |
386 | | - |
387 | | - @patch('agents.memory.providers.redis.redis.ConnectionPool.from_url') |
388 | | - def test_get_session_default_ttl(self, mock_pool_from_url, session_manager): |
389 | | - """Test getting session with default TTL.""" |
390 | | - session = session_manager.get_session("test_session_789") |
391 | | - assert session.ttl == 7200 |
392 | | - |
393 | | - @patch('agents.memory.providers.redis.redis.ConnectionPool.from_url') |
394 | | - @patch('agents.memory.providers.redis.redis.Redis') |
395 | | - async def test_list_sessions(self, mock_redis_class, mock_pool_from_url, session_manager): |
396 | | - """Test listing all sessions.""" |
397 | | - mock_redis_instance = AsyncMock() |
398 | | - mock_redis_class.return_value = mock_redis_instance |
399 | | - mock_redis_instance.keys.return_value = [ |
400 | | - "manager_session:session1", |
401 | | - "manager_session:session2", |
402 | | - "manager_session:session3" |
403 | | - ] |
404 | | - |
405 | | - sessions = await session_manager.list_sessions() |
406 | | - |
407 | | - mock_redis_instance.keys.assert_called_once_with("manager_session:*") |
408 | | - mock_redis_instance.aclose.assert_called_once() |
409 | | - assert sessions == ["session1", "session2", "session3"] |
410 | | - |
411 | | - @patch('agents.memory.providers.redis.redis.ConnectionPool.from_url') |
412 | | - @patch('agents.memory.providers.redis.redis.Redis') |
413 | | - async def test_list_sessions_with_pattern( |
414 | | - self, mock_redis_class, mock_pool_from_url, session_manager |
415 | | - ): |
416 | | - """Test listing sessions with pattern filter.""" |
417 | | - mock_redis_instance = AsyncMock() |
418 | | - mock_redis_class.return_value = mock_redis_instance |
419 | | - mock_redis_instance.keys.return_value = [ |
420 | | - "manager_session:user_123_session1", |
421 | | - "manager_session:user_123_session2" |
422 | | - ] |
423 | | - |
424 | | - sessions = await session_manager.list_sessions(pattern="user_123_*") |
425 | | - |
426 | | - mock_redis_instance.keys.assert_called_once_with("manager_session:user_123_*") |
427 | | - assert sessions == ["user_123_session1", "user_123_session2"] |
428 | | - |
429 | | - @patch('agents.memory.providers.redis.redis.ConnectionPool.from_url') |
430 | | - @patch('agents.memory.providers.redis.redis.Redis') |
431 | | - async def test_delete_session(self, mock_redis_class, mock_pool_from_url, session_manager): |
432 | | - """Test deleting a session.""" |
433 | | - mock_redis_instance = AsyncMock() |
434 | | - mock_redis_class.return_value = mock_redis_instance |
435 | | - mock_redis_instance.delete.return_value = 2 # Both keys deleted |
436 | | - |
437 | | - result = await session_manager.delete_session("test_session") |
438 | | - |
439 | | - mock_redis_instance.delete.assert_called_once_with( |
440 | | - "manager_session:test_session", |
441 | | - "manager_messages:test_session" |
442 | | - ) |
443 | | - mock_redis_instance.aclose.assert_called_once() |
444 | | - assert result is True |
445 | | - |
446 | | - @patch('agents.memory.providers.redis.redis.ConnectionPool.from_url') |
447 | | - @patch('agents.memory.providers.redis.redis.Redis') |
448 | | - async def test_delete_session_not_exists( |
449 | | - self, mock_redis_class, mock_pool_from_url, session_manager |
450 | | - ): |
451 | | - """Test deleting non-existent session.""" |
452 | | - mock_redis_instance = AsyncMock() |
453 | | - mock_redis_class.return_value = mock_redis_instance |
454 | | - mock_redis_instance.delete.return_value = 0 # No keys deleted |
455 | | - |
456 | | - result = await session_manager.delete_session("nonexistent_session") |
457 | | - |
458 | | - assert result is False |
459 | | - |
460 | | - @patch('agents.memory.providers.redis.redis.ConnectionPool.from_url') |
461 | | - async def test_close(self, mock_pool_from_url, session_manager): |
462 | | - """Test closing connection pool.""" |
463 | | - mock_pool = AsyncMock() |
464 | | - session_manager._redis_pool = mock_pool |
465 | | - |
466 | | - await session_manager.close() |
467 | | - |
468 | | - mock_pool.aclose.assert_called_once() |
469 | | - |
470 | | - @patch('agents.memory.providers.redis.redis.ConnectionPool.from_url') |
471 | | - async def test_context_manager(self, mock_pool_from_url, session_manager): |
472 | | - """Test async context manager functionality.""" |
473 | | - session_manager.close = AsyncMock() |
474 | | - |
475 | | - async with session_manager as manager: |
476 | | - assert manager == session_manager |
477 | | - |
478 | | - session_manager.close.assert_called_once() |
479 | | - |
480 | | - |
481 | | -class TestRedisSessionIntegration: |
482 | | - """Integration tests for Redis session functionality.""" |
483 | | - |
484 | | - @pytest.fixture |
485 | | - def redis_session_no_ttl(self): |
486 | | - """Create a RedisSession without TTL for testing.""" |
487 | | - return RedisSession("integration_test_session", ttl=None) |
488 | | - |
489 | | - @patch('agents.memory.providers.redis.redis.from_url') |
490 | | - async def test_session_lifecycle(self, mock_from_url, redis_session_no_ttl, sample_items): |
491 | | - """Test complete session lifecycle operations.""" |
492 | | - mock_redis = AsyncMock() |
493 | | - mock_from_url.return_value = mock_redis |
494 | | - |
495 | | - # Create a proper async context manager mock |
496 | | - mock_pipeline = AsyncMock() |
497 | | - mock_context_manager = AsyncMock() |
498 | | - mock_context_manager.__aenter__.return_value = mock_pipeline |
499 | | - mock_context_manager.__aexit__.return_value = None |
500 | | - |
501 | | - # Make pipeline() return the context manager directly (not a coroutine) |
502 | | - mock_redis.pipeline = MagicMock(return_value=mock_context_manager) |
503 | | - |
504 | | - # Mock responses for different operations |
505 | | - mock_redis.exists.return_value = False |
506 | | - mock_redis.lrange.return_value = [json.dumps(item) for item in sample_items] |
507 | | - mock_redis.llen.return_value = len(sample_items) |
508 | | - mock_redis.rpop.return_value = json.dumps(sample_items[-1]) |
509 | | - mock_redis.hgetall.return_value = { |
510 | | - "session_id": "integration_test_session", |
511 | | - "created_at": "1234567890.0", |
512 | | - "updated_at": "1234567890.0" |
513 | | - } |
514 | | - |
515 | | - session = redis_session_no_ttl |
516 | | - |
517 | | - # Add items |
518 | | - await session.add_items(sample_items) |
519 | | - |
520 | | - # Get all items |
521 | | - items = await session.get_items() |
522 | | - assert len(items) == len(sample_items) |
523 | | - |
524 | | - # Get session size |
525 | | - size = await session.get_session_size() |
526 | | - assert size == len(sample_items) |
527 | | - |
528 | | - # Get session info |
529 | | - info = await session.get_session_info() |
530 | | - assert info["session_id"] == "integration_test_session" |
531 | | - |
532 | | - # Pop last item |
533 | | - popped_item = await session.pop_item() |
534 | | - assert popped_item == sample_items[-1] |
535 | | - |
536 | | - # Clear session |
537 | | - await session.clear_session() |
538 | | - |
539 | | - # Close session |
540 | | - await session.close() |
541 | | - |
542 | | - @pytest.fixture |
543 | | - def sample_items(self): |
544 | | - """Create sample items for integration testing.""" |
545 | | - return [ |
546 | | - {"role": "user", "content": [{"type": "text", "text": "Hello"}]}, |
547 | | - {"role": "assistant", "content": [{"type": "text", "text": "Hi there!"}]}, |
548 | | - {"role": "user", "content": [{"type": "text", "text": "How are you?"}]}, |
549 | | - ] |
0 commit comments