FIX: Fixing test that does not work properly / Failing in connection pool #493
Build #pr-validation-pipeline had test failures
Details
- Failed: 117 (0.43%)
- Passed: 26,136 (96.89%)
- Other: 723 (2.68%)
- Total: 26,976
Annotations
Check failure on line 2490 in Build log
azure-pipelines / MSSQL-Python-PR-Validation
Build log #L2490
Bash exited with code '1'.
Check failure on line 2540 in Build log
azure-pipelines / MSSQL-Python-PR-Validation
Build log #L2540
Bash exited with code '1'.
Check failure on line 10 in Build log
azure-pipelines / MSSQL-Python-PR-Validation
Build log #L10
No code coverage results were found to publish.
Check failure on line 2405 in Build log
azure-pipelines / MSSQL-Python-PR-Validation
Build log #L2405
Bash exited with code '1'.
Check failure on line 1 in test_connection_execute_cursor_lifecycle
azure-pipelines / MSSQL-Python-PR-Validation
test_connection_execute_cursor_lifecycle
AssertionError: Cursor should be garbage collected after going out of scope
assert <mssql_python.cursor.Cursor object at 0x7fd46e7830e0> is None
+ where <mssql_python.cursor.Cursor object at 0x7fd46e7830e0> = <weakref at 0x7fd46ae853f0; to 'Cursor' at 0x7fd46e7830e0>()
Raw output
db_connection = <mssql_python.connection.Connection object at 0x7fd46e75fda0>
def test_connection_execute_cursor_lifecycle(db_connection):
"""Test that cursors from execute() are properly managed throughout their lifecycle"""
import gc
import weakref
import sys
# Clear any existing cursors and force garbage collection
for cursor in list(db_connection._cursors):
try:
cursor.close()
except Exception:
pass
gc.collect()
# Verify we start with a clean state
initial_cursor_count = len(db_connection._cursors)
# 1. Test that a cursor is added to tracking when created
cursor1 = db_connection.execute("SELECT 1 AS test")
cursor1.fetchall() # Consume results
# Verify cursor was added to tracking
assert (
len(db_connection._cursors) == initial_cursor_count + 1
), "Cursor should be added to connection tracking"
assert (
cursor1 in db_connection._cursors
), "Created cursor should be in the connection's tracking set"
# 2. Test that a cursor is removed when explicitly closed
cursor_id = id(cursor1) # Remember the cursor's ID for later verification
cursor1.close()
# Force garbage collection to ensure WeakSet is updated
gc.collect()
# Verify cursor was removed from tracking
remaining_cursor_ids = [id(c) for c in db_connection._cursors]
assert (
cursor_id not in remaining_cursor_ids
), "Closed cursor should be removed from connection tracking"
# 3. Test that a cursor is tracked but then removed when it goes out of scope
# Note: We'll create a cursor and verify it's tracked BEFORE leaving the scope
temp_cursor = db_connection.execute("SELECT 2 AS test")
temp_cursor.fetchall() # Consume results
# Get a weak reference to the cursor for checking collection later
cursor_ref = weakref.ref(temp_cursor)
# Verify cursor is tracked immediately after creation
assert (
len(db_connection._cursors) > initial_cursor_count
), "New cursor should be tracked immediately"
assert (
temp_cursor in db_connection._cursors
), "New cursor should be in the connection's tracking set"
# Now remove our reference to allow garbage collection
temp_cursor = None
# Force garbage collection multiple times to ensure the cursor is collected
for _ in range(3):
gc.collect()
# Verify cursor was eventually removed from tracking after collection
> assert cursor_ref() is None, "Cursor should be garbage collected after going out of scope"
E AssertionError: Cursor should be garbage collected after going out of scope
E assert <mssql_python.cursor.Cursor object at 0x7fd46e7830e0> is None
E + where <mssql_python.cursor.Cursor object at 0x7fd46e7830e0> = <weakref at 0x7fd46ae853f0; to 'Cursor' at 0x7fd46e7830e0>()
tests/test_003_connection.py:1184: AssertionError
Check failure on line 1 in test_cursor_cleanup_without_close
azure-pipelines / MSSQL-Python-PR-Validation
test_cursor_cleanup_without_close
AssertionError: assert 1 == 0
+ where 1 = len({<weakref at 0x7fd46bc43380; to 'Cursor' at 0x7fd46e0c7320>})
+ where {<weakref at 0x7fd46bc43380; to 'Cursor' at 0x7fd46e0c7320>} = <mssql_python.connection.Connection object at 0x7fd46e0c6840>._cursors
Raw output
conn_str = 'Server=tcp:127.0.0.1,1433;Database=master;Uid=SA;Pwd=Azure@123!;TrustServerCertificate=yes'
def test_cursor_cleanup_without_close(conn_str):
"""Test that cursors are properly cleaned up without closing the connection"""
conn_new = connect(conn_str)
cursor = conn_new.cursor()
cursor.execute("SELECT 1")
cursor.fetchall()
assert len(conn_new._cursors) == 1
del cursor # Remove the last reference
> assert len(conn_new._cursors) == 0 # Now the WeakSet should be empty
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E AssertionError: assert 1 == 0
E + where 1 = len({<weakref at 0x7fd46bc43380; to 'Cursor' at 0x7fd46e0c7320>})
E + where {<weakref at 0x7fd46bc43380; to 'Cursor' at 0x7fd46e0c7320>} = <mssql_python.connection.Connection object at 0x7fd46e0c6840>._cursors
tests/test_005_connection_cursor_lifecycle.py:80: AssertionError
Check failure on line 1 in test_cursor_weakref_cleanup
azure-pipelines / MSSQL-Python-PR-Validation
test_cursor_weakref_cleanup
AssertionError: Should have 1 cursor after garbage collection
assert 2 == 1
+ where 2 = len({<weakref at 0x7fd46e0f7e70; to 'Cursor' at 0x7fd46e0c74d0>, <weakref at 0x7fd46e0f7ec0; to 'Cursor' at 0x7fd46e0c64e0>})
+ where {<weakref at 0x7fd46e0f7e70; to 'Cursor' at 0x7fd46e0c74d0>, <weakref at 0x7fd46e0f7ec0; to 'Cursor' at 0x7fd46e0c64e0>} = <mssql_python.connection.Connection object at 0x7fd46e0c7b30>._cursors
Raw output
conn_str = 'Server=tcp:127.0.0.1,1433;Database=master;Uid=SA;Pwd=Azure@123!;TrustServerCertificate=yes'
def test_cursor_weakref_cleanup(conn_str):
"""Test that WeakSet properly removes garbage collected cursors"""
conn = connect(conn_str)
# Create cursors
cursor1 = conn.cursor()
cursor2 = conn.cursor()
# Check initial cursor count
assert len(conn._cursors) == 2, "Should have 2 cursors"
# Delete reference to cursor1 (should be garbage collected)
cursor1_id = id(cursor1)
del cursor1
# Force garbage collection
import gc
gc.collect()
# Check cursor count after garbage collection
> assert len(conn._cursors) == 1, "Should have 1 cursor after garbage collection"
E AssertionError: Should have 1 cursor after garbage collection
E assert 2 == 1
E + where 2 = len({<weakref at 0x7fd46e0f7e70; to 'Cursor' at 0x7fd46e0c74d0>, <weakref at 0x7fd46e0f7ec0; to 'Cursor' at 0x7fd46e0c64e0>})
E + where {<weakref at 0x7fd46e0f7e70; to 'Cursor' at 0x7fd46e0c74d0>, <weakref at 0x7fd46e0f7ec0; to 'Cursor' at 0x7fd46e0c64e0>} = <mssql_python.connection.Connection object at 0x7fd46e0c7b30>._cursors
tests/test_005_connection_cursor_lifecycle.py:176: AssertionError
Check failure on line 1 in test_cursor_del_unclosed_cursor_cleanup
azure-pipelines / MSSQL-Python-PR-Validation
test_cursor_del_unclosed_cursor_cleanup
assert 'Exception' not in 'Exception i...ys.modules\n'
'Exception' is contained here:
Exception ignored in: <function Cursor.__del__ at 0x7f5592944c20>
? +++++++++
Traceback (most recent call last):
File "/home/vsts/work/1/s/mssql_python/cursor.py", line 3029, in __del__
if sys is None or sys._is_finalizing():...
...Full output truncated (6 lines hidden), use '-vv' to show
Raw output
conn_str = 'Server=tcp:127.0.0.1,1433;Database=master;Uid=SA;Pwd=Azure@123!;TrustServerCertificate=yes'
def test_cursor_del_unclosed_cursor_cleanup(conn_str):
"""Test that __del__ properly cleans up unclosed cursors without errors"""
code = f"""
from mssql_python import connect
# Create connection and cursor
conn = connect(\"\"\"{conn_str}\"\"\")
cursor = conn.cursor()
cursor.execute("SELECT 1")
cursor.fetchall()
# Store cursor state before deletion
cursor_closed_before = cursor.closed
# Delete cursor without closing - __del__ should handle cleanup
del cursor
import gc
gc.collect()
# Verify cursor was not closed before deletion
assert cursor_closed_before is False, "Cursor should not be closed before deletion"
# Close connection
conn.close()
print("Cleanup successful")
"""
result = subprocess.run([sys.executable, "-c", code], capture_output=True, text=True)
assert result.returncode == 0, f"Expected successful cleanup, but got: {result.stderr}"
assert "Cleanup successful" in result.stdout
# Should not have any error messages
> assert "Exception" not in result.stderr
E assert 'Exception' not in 'Exception i...ys.modules\n'
E
E 'Exception' is contained here:
E Exception ignored in: <function Cursor.__del__ at 0x7f5592944c20>
E ? +++++++++
E Traceback (most recent call last):
E File "/home/vsts/work/1/s/mssql_python/cursor.py", line 3029, in __del__
E if sys is None or sys._is_finalizing():...
E
E ...Full output truncated (6 lines hidden), use '-vv' to show
tests/test_005_connection_cursor_lifecycle.py:402: AssertionError