Skip to content

Commit 4283fc8

Browse files
committed
Split up and comment the long tests
1 parent 521c483 commit 4283fc8

7 files changed

Lines changed: 583 additions & 266 deletions

File tree

tests/conftest.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,25 @@ def dbapi():
1010
"""Get the mock DB-API 2 module."""
1111
mock_db.threadsafety = 2
1212
return mock_db
13+
14+
15+
@pytest.fixture
16+
def con_cls():
17+
"""Get the mock connection class with the ping counter reset.
18+
19+
The ping method is unavailable, and the counter is reset again
20+
after the test, even when the test fails.
21+
"""
22+
con_cls = mock_db.Connection
23+
con_cls.has_ping = False
24+
con_cls.num_pings = 0
25+
yield con_cls
26+
con_cls.has_ping = False
27+
con_cls.num_pings = 0
28+
29+
30+
@pytest.fixture
31+
def ping_con_cls(con_cls):
32+
"""Get the mock connection class with a working ping method."""
33+
con_cls.has_ping = True
34+
return con_cls

tests/test_persistent_db.py

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ def test_threads(dbapi):
7575
result_queue.append(Queue(1))
7676

7777
def run_queries(idx):
78+
"""Answer the queries sent to this thread until it gets None.
79+
80+
Every answer is prefixed with the thread number and the usage
81+
count of the connection, so that the main thread can check that
82+
the thread kept using its own connection.
83+
"""
7884
this_db = persist.connection()
7985
db = None
8086
while True:
@@ -107,17 +113,21 @@ def run_queries(idx):
107113
thread = Thread(target=run_queries, args=(i,))
108114
threads.append(thread)
109115
thread.start()
116+
# all threads are alive and have an unused connection of their own
110117
for i in range(num_threads):
111118
query_queue[i].put('ping', timeout=1)
112119
for i in range(num_threads):
113120
r = result_queue[i].get(timeout=1)
114121
assert r == f'{i}(0): ok - thread alive'
115122
assert threads[i].is_alive()
123+
# let thread number i run i + 1 queries on its own connection
116124
for i in range(num_threads):
117125
for j in range(i + 1):
118126
query_queue[i].put(f'select test{j}', timeout=1)
119127
r = result_queue[i].get(timeout=1)
120128
assert r == f'{i}({j + 1}): test{j}'
129+
# closing the connection of the second thread restarts its usage count,
130+
# but does not affect the connections of the other threads
121131
query_queue[1].put('select test4', timeout=1)
122132
r = result_queue[1].get(timeout=1)
123133
assert r == '1(3): test4'
@@ -128,13 +138,15 @@ def run_queries(idx):
128138
query_queue[1].put(f'select test{j}', timeout=1)
129139
r = result_queue[1].get(timeout=1)
130140
assert r == f'1({j + 1}): test{j}'
141+
# every thread still has its own connection with its own usage count
131142
for i in range(num_threads):
132143
assert threads[i].is_alive()
133144
query_queue[i].put('ping', timeout=1)
134145
for i in range(num_threads):
135146
r = result_queue[i].get(timeout=1)
136147
assert r == f'{i}({i + 1}): ok - thread alive'
137148
assert threads[i].is_alive()
149+
# send the sentinel that makes the threads finish
138150
for i in range(num_threads):
139151
query_queue[i].put(None, timeout=1)
140152

@@ -189,58 +201,74 @@ class Threadlocal:
189201
assert isinstance(persist.thread, Threadlocal)
190202

191203

192-
def test_ping_check(dbapi):
193-
"""Check that connections are pinged as configured."""
194-
con_cls = dbapi.Connection
195-
con_cls.has_ping = True
196-
con_cls.num_pings = 0
204+
def test_ping_check_never(dbapi, ping_con_cls):
205+
"""Check that connections are not pinged when ping is 0."""
197206
persist = PersistentDB(dbapi, 0, None, None, 0, True)
198207
db = persist.connection()
199208
assert db._con.valid is True
200-
assert con_cls.num_pings == 0
209+
assert ping_con_cls.num_pings == 0
210+
# the closed connection is handed out again without being pinged,
211+
# so the fact that it is broken goes unnoticed
201212
db.close()
202213
db = persist.connection()
203214
assert db._con.valid is False
204-
assert con_cls.num_pings == 0
215+
assert ping_con_cls.num_pings == 0
216+
217+
218+
def test_ping_check_when_fetched(dbapi, ping_con_cls):
219+
"""Check that connections are pinged when ping is 1."""
205220
persist = PersistentDB(dbapi, 0, None, None, 1, True)
206221
db = persist.connection()
207222
assert db._con.valid is True
208-
assert con_cls.num_pings == 1
223+
assert ping_con_cls.num_pings == 1
224+
# the closed connection is pinged when it is requested again,
225+
# so it is transparently reopened
209226
db.close()
210227
db = persist.connection()
211228
assert db._con.valid is True
212-
assert con_cls.num_pings == 2
229+
assert ping_con_cls.num_pings == 2
230+
231+
232+
def test_ping_check_when_cursor_created(dbapi, ping_con_cls):
233+
"""Check that connections are pinged when ping is 2."""
213234
persist = PersistentDB(dbapi, 0, None, None, 2, True)
214235
db = persist.connection()
215236
assert db._con.valid is True
216-
assert con_cls.num_pings == 2
237+
assert ping_con_cls.num_pings == 0
238+
# requesting the closed connection does not ping it yet
217239
db.close()
218240
db = persist.connection()
219241
assert db._con.valid is False
220-
assert con_cls.num_pings == 2
242+
assert ping_con_cls.num_pings == 0
243+
# but creating a cursor does, which reopens the connection
221244
cursor = db.cursor()
222245
assert db._con.valid is True
223-
assert con_cls.num_pings == 3
246+
assert ping_con_cls.num_pings == 1
247+
# executing a query does not ping again
224248
cursor.execute('select test')
225249
assert db._con.valid is True
226-
assert con_cls.num_pings == 3
250+
assert ping_con_cls.num_pings == 1
251+
252+
253+
def test_ping_check_when_query_executed(dbapi, ping_con_cls):
254+
"""Check that connections are pinged when ping is 4."""
227255
persist = PersistentDB(dbapi, 0, None, None, 4, True)
228256
db = persist.connection()
229257
assert db._con.valid is True
230-
assert con_cls.num_pings == 3
258+
assert ping_con_cls.num_pings == 0
259+
# neither requesting the connection nor creating a cursor pings it
231260
db.close()
232261
db = persist.connection()
233262
assert db._con.valid is False
234-
assert con_cls.num_pings == 3
263+
assert ping_con_cls.num_pings == 0
235264
cursor = db.cursor()
236265
db._con.close()
237266
assert db._con.valid is False
238-
assert con_cls.num_pings == 3
267+
assert ping_con_cls.num_pings == 0
268+
# only executing a query does, which reopens the connection
239269
cursor.execute('select test')
240270
assert db._con.valid is True
241-
assert con_cls.num_pings == 4
242-
con_cls.has_ping = False
243-
con_cls.num_pings = 0
271+
assert ping_con_cls.num_pings == 1
244272

245273

246274
def test_failed_transaction(dbapi):

tests/test_persistent_pg.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ def test_threads():
5353
result_queue.append(Queue(1))
5454

5555
def run_queries(idx):
56+
"""Answer the queries sent to this thread until it gets None.
57+
58+
Every answer is prefixed with the thread number and the usage
59+
count of the connection, so that the main thread can check that
60+
the thread kept using its own connection.
61+
"""
5662
this_db = persist.connection().db
5763
db = None
5864
while True:
@@ -82,17 +88,21 @@ def run_queries(idx):
8288
thread = Thread(target=run_queries, args=(i,))
8389
threads.append(thread)
8490
thread.start()
91+
# all threads are alive and have an unused connection of their own
8592
for i in range(num_threads):
8693
query_queue[i].put('ping', timeout=1)
8794
for i in range(num_threads):
8895
r = result_queue[i].get(timeout=1)
8996
assert r == f'{i}(0): ok - thread alive'
9097
assert threads[i].is_alive()
98+
# let thread number i run i + 1 queries on its own connection
9199
for i in range(num_threads):
92100
for j in range(i + 1):
93101
query_queue[i].put(f'select test{j}', timeout=1)
94102
r = result_queue[i].get(timeout=1)
95103
assert r == f'{i}({j + 1}): test{j}'
104+
# closing the connection of the second thread restarts its usage count,
105+
# but does not affect the connections of the other threads
96106
query_queue[1].put('select test4', timeout=1)
97107
r = result_queue[1].get(timeout=1)
98108
assert r == '1(3): test4'
@@ -103,13 +113,15 @@ def run_queries(idx):
103113
query_queue[1].put(f'select test{j}', timeout=1)
104114
r = result_queue[1].get(timeout=1)
105115
assert r == f'1({j + 1}): test{j}'
116+
# every thread still has its own connection with its own usage count
106117
for i in range(num_threads):
107118
assert threads[i].is_alive()
108119
query_queue[i].put('ping', timeout=1)
109120
for i in range(num_threads):
110121
r = result_queue[i].get(timeout=1)
111122
assert r == f'{i}({i + 1}): ok - thread alive'
112123
assert threads[i].is_alive()
124+
# send the sentinel that makes the threads finish
113125
for i in range(num_threads):
114126
query_queue[i].put(None, timeout=1)
115127

0 commit comments

Comments
 (0)