@@ -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