1010Note: The cursor function is not yet implemented, so related tests are commented out.
1111"""
1212
13- from mssql_python .exceptions import InterfaceError
1413import pytest
1514import time
1615from mssql_python import Connection , connect , pooling
17-
16+
1817def drop_table_if_exists (cursor , table_name ):
1918 """Drop the table if it exists"""
2019 try :
@@ -224,172 +223,3 @@ def test_connection_pooling_basic(conn_str):
224223
225224 conn1 .close ()
226225 conn2 .close ()
227-
228- # Add these tests at the end of the file
229-
230- def test_cursor_cleanup_on_connection_close (conn_str ):
231- """Test that cursors are properly cleaned up when connection is closed"""
232- # Create a new connection for this test
233- conn = connect (conn_str )
234-
235- # Create multiple cursors
236- cursor1 = conn .cursor ()
237- cursor2 = conn .cursor ()
238- cursor3 = conn .cursor ()
239-
240- # Execute something on each cursor to ensure they have statement handles
241- # Option 1: Fetch results immediately to free the connection
242- cursor1 .execute ("SELECT 1" )
243- cursor1 .fetchall ()
244-
245- cursor2 .execute ("SELECT 2" )
246- cursor2 .fetchall ()
247-
248- cursor3 .execute ("SELECT 3" )
249- cursor3 .fetchall ()
250-
251- # Close one cursor explicitly
252- cursor1 .close ()
253- assert cursor1 .closed is True , "Cursor1 should be closed"
254-
255- # Close the connection (should clean up remaining cursors)
256- conn .close ()
257-
258- # Verify all cursors are closed
259- assert cursor1 .closed is True , "Cursor1 should remain closed"
260- assert cursor2 .closed is True , "Cursor2 should be closed by connection.close()"
261- assert cursor3 .closed is True , "Cursor3 should be closed by connection.close()"
262-
263- def test_cursor_weakref_cleanup (conn_str ):
264- """Test that WeakSet properly removes garbage collected cursors"""
265- conn = connect (conn_str )
266-
267- # Create cursors
268- cursor1 = conn .cursor ()
269- cursor2 = conn .cursor ()
270-
271- # Check initial cursor count
272- assert len (conn ._cursors ) == 2 , "Should have 2 cursors"
273-
274- # Delete reference to cursor1 (should be garbage collected)
275- cursor1_id = id (cursor1 )
276- del cursor1
277-
278- # Force garbage collection
279- import gc
280- gc .collect ()
281-
282- # Check cursor count after garbage collection
283- assert len (conn ._cursors ) == 1 , "Should have 1 cursor after garbage collection"
284-
285- # Verify cursor2 is still there
286- assert cursor2 in conn ._cursors , "Cursor2 should still be in the set"
287-
288- conn .close ()
289-
290- def test_cursor_cleanup_order_no_segfault (conn_str ):
291- """Test that proper cleanup order prevents segfaults"""
292- # This test ensures cursors are cleaned before connection
293- conn = connect (conn_str )
294-
295- # Create multiple cursors with active statements
296- cursors = []
297- for i in range (5 ):
298- cursor = conn .cursor ()
299- cursor .execute (f"SELECT { i } " )
300- cursor .fetchall ()
301- cursors .append (cursor )
302-
303- # Don't close any cursors explicitly
304- # Just close the connection - it should handle cleanup properly
305- conn .close ()
306-
307- # Verify all cursors were closed
308- for cursor in cursors :
309- assert cursor .closed is True , "All cursors should be closed"
310-
311- def test_cursor_close_removes_from_connection (conn_str ):
312- """Test that closing a cursor properly cleans up references"""
313- conn = connect (conn_str )
314-
315- # Create cursors
316- cursor1 = conn .cursor ()
317- cursor2 = conn .cursor ()
318- cursor3 = conn .cursor ()
319-
320- assert len (conn ._cursors ) == 3 , "Should have 3 cursors"
321-
322- # Close cursor2
323- cursor2 .close ()
324-
325- # cursor2 should still be in the WeakSet (until garbage collected)
326- # but it should be marked as closed
327- assert cursor2 .closed is True , "Cursor2 should be closed"
328-
329- # Delete the reference and force garbage collection
330- del cursor2
331- import gc
332- gc .collect ()
333-
334- # Now should have 2 cursors
335- assert len (conn ._cursors ) == 2 , "Should have 2 cursors after closing and GC"
336-
337- conn .close ()
338-
339- def test_connection_close_idempotent (conn_str ):
340- """Test that calling close() multiple times is safe"""
341- conn = connect (conn_str )
342- cursor = conn .cursor ()
343- cursor .execute ("SELECT 1" )
344-
345- # First close
346- conn .close ()
347- assert conn ._closed is True , "Connection should be closed"
348-
349- # Second close (should not raise exception)
350- conn .close ()
351- assert conn ._closed is True , "Connection should remain closed"
352-
353- # Cursor should also be closed
354- assert cursor .closed is True , "Cursor should be closed"
355-
356- def test_cursor_after_connection_close (conn_str ):
357- """Test that creating cursor after connection close raises error"""
358- conn = connect (conn_str )
359- conn .close ()
360-
361- # Should raise exception when trying to create cursor on closed connection
362- with pytest .raises (InterfaceError ) as excinfo :
363- cursor = conn .cursor ()
364-
365- assert "closed connection" in str (excinfo .value ).lower (), "Should mention closed connection"
366-
367- def test_multiple_cursor_operations_cleanup (conn_str ):
368- """Test cleanup with multiple cursor operations"""
369- conn = connect (conn_str )
370-
371- # Create table for testing
372- cursor_setup = conn .cursor ()
373- drop_table_if_exists (cursor_setup , "#test_cleanup" )
374- cursor_setup .execute ("CREATE TABLE #test_cleanup (id INT, value VARCHAR(50))" )
375- cursor_setup .close ()
376-
377- # Create multiple cursors doing different operations
378- cursor_insert = conn .cursor ()
379- cursor_insert .execute ("INSERT INTO #test_cleanup VALUES (1, 'test1'), (2, 'test2')" )
380-
381- cursor_select1 = conn .cursor ()
382- cursor_select1 .execute ("SELECT * FROM #test_cleanup WHERE id = 1" )
383- cursor_select1 .fetchall ()
384-
385- cursor_select2 = conn .cursor ()
386- cursor_select2 .execute ("SELECT * FROM #test_cleanup WHERE id = 2" )
387- cursor_select2 .fetchall ()
388-
389- # Close connection without closing cursors
390- conn .close ()
391-
392- # All cursors should be closed
393- assert cursor_insert .closed is True
394- assert cursor_select1 .closed is True
395- assert cursor_select2 .closed is True
0 commit comments