11import logging
22import os
33import pytest
4- from mssql_python .logging_config import setup_logging , get_logger , logger
4+ import glob
5+ from mssql_python .logging_config import setup_logging , get_logger , LoggingManager
56
67def get_log_file_path ():
8+ # Get the LoggingManager singleton instance
9+ manager = LoggingManager ()
10+ # If logging is enabled, return the actual log file path
11+ if manager .enabled and manager .log_file :
12+ return manager .log_file
13+ # For fallback/cleanup, try to find existing log files in the logs directory
714 repo_root_dir = os .path .dirname (os .path .dirname (os .path .abspath (__file__ )))
15+ log_dir = os .path .join (repo_root_dir , "mssql_python" , "logs" )
16+ os .makedirs (log_dir , exist_ok = True )
17+
18+ # Try to find existing log files
19+ log_files = glob .glob (os .path .join (log_dir , "mssql_python_trace_*.log" ))
20+ if log_files :
21+ # Return the most recently created log file
22+ return max (log_files , key = os .path .getctime )
23+
24+ # Fallback to default pattern
825 pid = os .getpid ()
9- log_file = os .path .join (repo_root_dir , "mssql_python" , f"mssql_python_trace_{ pid } .log" )
10- return log_file
26+ return os .path .join (log_dir , f"mssql_python_trace_{ pid } .log" )
1127
1228@pytest .fixture
1329def cleanup_logger ():
1430 """Cleanup logger & log files before and after each test"""
1531 def cleanup ():
32+ # Get the LoggingManager singleton instance
33+ manager = LoggingManager ()
1634 logger = get_logger ()
1735 if logger is not None :
1836 logger .handlers .clear ()
19- log_file_path = get_log_file_path ()
20- if os .path .exists (log_file_path ):
21- os .remove (log_file_path )
22- logger = False
37+
38+ # Try to remove the actual log file if it exists
39+ try :
40+ log_file_path = get_log_file_path ()
41+ if os .path .exists (log_file_path ):
42+ os .remove (log_file_path )
43+ except :
44+ pass # Ignore errors during cleanup
45+
46+ # Reset the LoggingManager instance
47+ manager ._enabled = False
48+ manager ._initialized = False
49+ manager ._logger = None
50+ manager ._log_file = None
2351 # Perform cleanup before the test
2452 cleanup ()
2553 yield
@@ -29,8 +57,11 @@ def cleanup():
2957def test_no_logging (cleanup_logger ):
3058 """Test that logging is off by default"""
3159 try :
60+ # Get the LoggingManager singleton instance
61+ manager = LoggingManager ()
3262 logger = get_logger ()
3363 assert logger is None
64+ assert manager .enabled == False
3465 except Exception as e :
3566 pytest .fail (f"Logging not off by default. Error: { e } " )
3667
@@ -40,7 +71,8 @@ def test_setup_logging(cleanup_logger):
4071 setup_logging () # This must enable logging
4172 logger = get_logger ()
4273 assert logger is not None
43- assert logger == logging .getLogger ('mssql_python.logging_config' )
74+ # Fix: Check for the correct logger name
75+ assert logger == logging .getLogger ('mssql_python' )
4476 assert logger .level == logging .DEBUG # DEBUG level
4577 except Exception as e :
4678 pytest .fail (f"Logging setup failed: { e } " )
@@ -83,4 +115,115 @@ def test_logging_in_stdout_mode(cleanup_logger, capsys):
83115 captured_stdout = capsys .readouterr ().out
84116 assert test_message in captured_stdout , "Log message not found in stdout"
85117 except Exception as e :
86- pytest .fail (f"Logging in stdout mode failed: { e } " )
118+ pytest .fail (f"Logging in stdout mode failed: { e } " )
119+
120+ def test_python_layer_prefix (cleanup_logger ):
121+ """Test that Python layer logs have the correct prefix"""
122+ try :
123+ setup_logging ()
124+ logger = get_logger ()
125+ assert logger is not None
126+
127+ # Log a test message
128+ test_message = "This is a Python layer test message"
129+ logger .info (test_message )
130+
131+ # Check if the log file contains the message with [Python Layer log] prefix
132+ log_file_path = get_log_file_path ()
133+ with open (log_file_path , 'r' ) as f :
134+ log_content = f .read ()
135+
136+ # The logged message should have the Python Layer prefix
137+ assert "[Python Layer log]" in log_content , "Python Layer log prefix not found"
138+ assert test_message in log_content , "Test message not found in log file"
139+ except Exception as e :
140+ pytest .fail (f"Python layer prefix test failed: { e } " )
141+
142+ def test_different_log_levels (cleanup_logger ):
143+ """Test that different log levels work correctly"""
144+ try :
145+ setup_logging ()
146+ logger = get_logger ()
147+ assert logger is not None
148+
149+ # Log messages at different levels
150+ debug_msg = "This is a DEBUG message"
151+ info_msg = "This is an INFO message"
152+ warning_msg = "This is a WARNING message"
153+ error_msg = "This is an ERROR message"
154+
155+ logger .debug (debug_msg )
156+ logger .info (info_msg )
157+ logger .warning (warning_msg )
158+ logger .error (error_msg )
159+
160+ # Check if the log file contains all messages
161+ log_file_path = get_log_file_path ()
162+ with open (log_file_path , 'r' ) as f :
163+ log_content = f .read ()
164+
165+ assert debug_msg in log_content , "DEBUG message not found in log file"
166+ assert info_msg in log_content , "INFO message not found in log file"
167+ assert warning_msg in log_content , "WARNING message not found in log file"
168+ assert error_msg in log_content , "ERROR message not found in log file"
169+
170+ # Also check for level indicators in the log
171+ assert "DEBUG" in log_content , "DEBUG level not found in log file"
172+ assert "INFO" in log_content , "INFO level not found in log file"
173+ assert "WARNING" in log_content , "WARNING level not found in log file"
174+ assert "ERROR" in log_content , "ERROR level not found in log file"
175+ except Exception as e :
176+ pytest .fail (f"Log levels test failed: { e } " )
177+
178+ def test_singleton_behavior (cleanup_logger ):
179+ """Test that LoggingManager behaves as a singleton"""
180+ try :
181+ # Create multiple instances of LoggingManager
182+ manager1 = LoggingManager ()
183+ manager2 = LoggingManager ()
184+
185+ # They should be the same instance
186+ assert manager1 is manager2 , "LoggingManager instances are not the same"
187+
188+ # Enable logging through one instance
189+ manager1 ._enabled = True
190+
191+ # The other instance should reflect this change
192+ assert manager2 .enabled == True , "Singleton state not shared between instances"
193+
194+ # Reset for cleanup
195+ manager1 ._enabled = False
196+ except Exception as e :
197+ pytest .fail (f"Singleton behavior test failed: { e } " )
198+
199+ def test_timestamp_in_log_filename (cleanup_logger ):
200+ """Test that log filenames include timestamps"""
201+ try :
202+ setup_logging ()
203+
204+ # Get the log file path
205+ log_file_path = get_log_file_path ()
206+ filename = os .path .basename (log_file_path )
207+
208+ # Extract parts of the filename
209+ parts = filename .split ('_' )
210+
211+ # The filename should follow the pattern: mssql_python_trace_YYYYMMDD_HHMMSS_PID.log
212+ # Fix: Account for the fact that "mssql_python" contains an underscore
213+ assert parts [0 ] == "mssql" , "Incorrect filename prefix part 1"
214+ assert parts [1 ] == "python" , "Incorrect filename prefix part 2"
215+ assert parts [2 ] == "trace" , "Incorrect filename part"
216+
217+ # Check date format (YYYYMMDD)
218+ date_part = parts [3 ]
219+ assert len (date_part ) == 8 and date_part .isdigit (), "Date format incorrect in filename"
220+
221+ # Check time format (HHMMSS)
222+ time_part = parts [4 ]
223+ assert len (time_part ) == 6 and time_part .isdigit (), "Time format incorrect in filename"
224+
225+ # Process ID should be the last part before .log
226+ pid_part = parts [5 ].split ('.' )[0 ]
227+ assert pid_part .isdigit (), "Process ID not found in filename"
228+ except Exception as e :
229+ pytest .fail (f"Timestamp in filename test failed: { e } " )
0 commit comments