Skip to content

Commit 85be4bb

Browse files
committed
V4.0.2
1 parent c36ddd2 commit 85be4bb

File tree

3 files changed

+794
-7
lines changed

3 files changed

+794
-7
lines changed

tests/test_factory.py

Lines changed: 159 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def test_timed_rotating_logger_creation(self):
5959

6060
def test_logger_registry_caching(self):
6161
"""Test logger registry functionality."""
62-
# Clear registry and verify it's empty
62+
# Clear the registry and verify it's empty
6363
clear_logger_registry()
6464
assert len(get_registered_loggers()) == 0
6565

@@ -208,7 +208,7 @@ def test_factory_shutdown_logger(self):
208208
assert result is True
209209
assert "shutdown_test" not in get_registered_loggers()
210210

211-
# Try to shutdown non-existent logger
211+
# Try to shut down non-existent logger
212212
result = LoggerFactory.shutdown_logger("non_existent")
213213
assert result is False
214214

@@ -291,10 +291,10 @@ def test_factory_registry_copy_safety(self):
291291
registry_copy = get_registered_loggers()
292292
assert len(registry_copy) == 2
293293

294-
# Modify the copy (should not affect original)
294+
# Modify the copy (should not affect the original)
295295
registry_copy["new_logger"] = logger1
296296

297-
# Original registry should be unchanged
297+
# The Original registry should be unchanged
298298
original_registry = get_registered_loggers()
299299
assert len(original_registry) == 2
300300
assert "new_logger" not in original_registry
@@ -314,3 +314,158 @@ def test_factory_error_handling_during_cleanup(self):
314314
# Shutdown should handle the error gracefully
315315
result = LoggerFactory.shutdown_logger("cleanup_error_test")
316316
assert result is True
317+
318+
def test_factory_ensure_initialized_behavior(self):
319+
"""Test _ensure_initialized method behavior."""
320+
# Clear any existing initialization
321+
LoggerFactory._initialized = False
322+
LoggerFactory._atexit_registered = False
323+
324+
# Calling get_or_create_logger should trigger initialization
325+
logger = LoggerFactory.get_or_create_logger(LoggerType.BASIC, name="init_test")
326+
327+
# Should now be initialized
328+
assert LoggerFactory._initialized is True
329+
assert LoggerFactory._atexit_registered is True
330+
assert logger is not None
331+
332+
# Calling again should not re-initialize
333+
LoggerFactory._ensure_initialized()
334+
assert LoggerFactory._initialized is True
335+
336+
def test_factory_atexit_cleanup_error_handling(self):
337+
"""Test atexit cleanup error handling."""
338+
from unittest.mock import patch, Mock
339+
340+
# Mock the clear_registry method to raise an error
341+
with patch.object(LoggerFactory, 'clear_registry', side_effect=Exception("Test error")):
342+
# Should not raise an exception
343+
LoggerFactory._atexit_cleanup()
344+
345+
def test_factory_ttl_cleanup_edge_cases(self):
346+
"""Test TTL cleanup with edge cases."""
347+
import time
348+
349+
# Set very short TTL
350+
LoggerFactory.set_memory_limits(max_loggers=100, ttl_seconds=0.1)
351+
352+
# Create loggers
353+
logger1 = LoggerFactory.get_or_create_logger(LoggerType.BASIC, name="ttl_edge1")
354+
logger2 = LoggerFactory.get_or_create_logger(LoggerType.BASIC, name="ttl_edge2")
355+
356+
# Verify they're registered
357+
assert len(LoggerFactory.get_registered_loggers()) == 2
358+
359+
# Wait for TTL to expire
360+
time.sleep(0.15)
361+
362+
# Force cleanup by creating another logger
363+
logger3 = LoggerFactory.get_or_create_logger(LoggerType.BASIC, name="ttl_edge3")
364+
365+
# Old loggers should be cleaned up
366+
registry = LoggerFactory.get_registered_loggers()
367+
assert "ttl_edge1" not in registry
368+
assert "ttl_edge2" not in registry
369+
assert "ttl_edge3" in registry
370+
371+
def test_factory_lru_eviction_comprehensive(self):
372+
"""Test comprehensive LRU eviction scenarios."""
373+
# Set a small limit for testing
374+
LoggerFactory.set_memory_limits(max_loggers=2, ttl_seconds=3600)
375+
376+
# Create loggers in specific order
377+
logger1 = LoggerFactory.get_or_create_logger(LoggerType.BASIC, name="lru1")
378+
logger2 = LoggerFactory.get_or_create_logger(LoggerType.BASIC, name="lru2")
379+
380+
# Access logger1 to update its timestamp
381+
logger1_again = LoggerFactory.get_or_create_logger(LoggerType.BASIC, name="lru1")
382+
assert logger1 is logger1_again
383+
384+
# Create third logger - should evict logger2 (oldest)
385+
logger3 = LoggerFactory.get_or_create_logger(LoggerType.BASIC, name="lru3")
386+
387+
registry = LoggerFactory.get_registered_loggers()
388+
assert len(registry) == 2
389+
assert "lru1" in registry # Recently accessed
390+
assert "lru2" not in registry # Should be evicted
391+
assert "lru3" in registry # Newly created
392+
393+
def test_factory_memory_limits_from_settings(self):
394+
"""Test memory limits initialization from settings."""
395+
from unittest.mock import patch, Mock
396+
397+
# Mock settings
398+
mock_settings = Mock()
399+
mock_settings.max_loggers = 50
400+
mock_settings.logger_ttl_seconds = 1800
401+
402+
# Patch the import inside the function
403+
with patch('pythonLogs.settings.get_log_settings', return_value=mock_settings):
404+
# Reset initialization flag
405+
LoggerFactory._initialized = False
406+
407+
# This should trigger initialization from settings
408+
LoggerFactory._ensure_initialized()
409+
410+
assert LoggerFactory._max_loggers == 50
411+
assert LoggerFactory._logger_ttl == 1800
412+
assert LoggerFactory._initialized is True
413+
414+
def test_factory_zero_max_loggers_handling(self):
415+
"""Test handling of zero max_loggers setting."""
416+
# Set max_loggers to 0
417+
LoggerFactory.set_memory_limits(max_loggers=0, ttl_seconds=3600)
418+
419+
# Create a logger - it gets added after clearing registry
420+
logger1 = LoggerFactory.get_or_create_logger(LoggerType.BASIC, name="zero_test1")
421+
assert logger1 is not None
422+
423+
# Registry will contain the newly created logger (added after clearing)
424+
registry = LoggerFactory.get_registered_loggers()
425+
assert len(registry) == 1
426+
assert "zero_test1" in registry
427+
428+
# Creating another logger should clear the registry again and add the new one
429+
logger2 = LoggerFactory.get_or_create_logger(LoggerType.BASIC, name="zero_test2")
430+
assert logger2 is not None
431+
registry = LoggerFactory.get_registered_loggers()
432+
assert len(registry) == 1
433+
assert "zero_test2" in registry
434+
assert "zero_test1" not in registry # Should be cleared
435+
436+
def test_factory_negative_max_loggers_handling(self):
437+
"""Test handling of negative max_loggers setting."""
438+
# Set max_loggers to negative value
439+
LoggerFactory.set_memory_limits(max_loggers=-1, ttl_seconds=3600)
440+
441+
# Create a logger - it gets added after clearing registry
442+
logger = LoggerFactory.get_or_create_logger(LoggerType.BASIC, name="negative_test")
443+
assert logger is not None
444+
445+
# Registry will contain the newly created logger (added after clearing)
446+
registry = LoggerFactory.get_registered_loggers()
447+
assert len(registry) == 1
448+
assert "negative_test" in registry
449+
450+
def test_factory_large_scale_operations(self):
451+
"""Test factory with large scale operations."""
452+
# Set reasonable limits
453+
LoggerFactory.set_memory_limits(max_loggers=10, ttl_seconds=3600)
454+
455+
# Create many loggers
456+
created_loggers = []
457+
for i in range(20):
458+
logger = LoggerFactory.get_or_create_logger(
459+
LoggerType.BASIC,
460+
name=f"scale_test_{i}"
461+
)
462+
created_loggers.append(logger)
463+
464+
# Registry should not exceed the limit
465+
registry = LoggerFactory.get_registered_loggers()
466+
assert len(registry) <= 10
467+
468+
# All loggers should still be functional
469+
for logger in created_loggers:
470+
logger.info("Scale test message")
471+
assert logger.name is not None

0 commit comments

Comments
 (0)