Skip to content

Commit c5a63ea

Browse files
committed
Merge bitcoin#27944: test: various USDT functional test cleanups (27831 follow-ups)
9f55773 test: refactor: usdt_mempool: store all events (stickies-v) bc43270 test: refactor: remove unnecessary nonlocal (stickies-v) 326db63 test: log sanity check assertion failures (stickies-v) f5525ad test: store utxocache events (stickies-v) f1b99ac test: refactor: deduplicate handle_utxocache_* logic (stickies-v) ad90ba3 test: refactor: rename inbound to is_inbound (stickies-v) afc0224 test: refactor: remove unnecessary blocks_checked counter (stickies-v) Pull request description: Various cleanups to the USDT functional tests, largely (but not exclusively) follow-ups to bitcoin#27831 (review). Except for slightly different logging behaviour in "test: store utxocache events" and "test: log sanity check assertion failures", this is a refactor PR, removing unnecessary code and (imo) making it more readable and maintainable. The rationale for each change is in the corresponding commit message. Note: except for "test: store utxocache events" (which relies on its parent, and I separated into two commits because we may want the parent but not the child), all commits are stand-alone and I'm okay with dropping one/multiple commits if they turn out to be controversial or undesired. ACKs for top commit: 0xB10C: ACK 9f55773. Reviewed the code and ran the USDT interface tests. I stepped through the commits and think all changes are reasonable. Tree-SHA512: 6c37a0265b6c26d4f9552a056a690b8f86f7304bd33b4419febd8b17369cf6af799cb87c16df35d0c2a1b839ad31de24661d4384eafa88816c2051c522fd3bf5
2 parents e25af11 + 9f55773 commit c5a63ea

File tree

4 files changed

+51
-77
lines changed

4 files changed

+51
-77
lines changed

test/functional/interface_usdt_mempool.py

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,7 @@ def added_test(self):
137137
"""Add a transaction to the mempool and make sure the tracepoint returns
138138
the expected txid, vsize, and fee."""
139139

140-
EXPECTED_ADDED_EVENTS = 1
141-
handled_added_events = 0
142-
event = None
140+
events = []
143141

144142
self.log.info("Hooking into mempool:added tracepoint...")
145143
node = self.nodes[0]
@@ -148,9 +146,7 @@ def added_test(self):
148146
bpf = BPF(text=MEMPOOL_TRACEPOINTS_PROGRAM, usdt_contexts=[ctx], debug=0)
149147

150148
def handle_added_event(_, data, __):
151-
nonlocal event, handled_added_events
152-
event = bpf["added_events"].event(data)
153-
handled_added_events += 1
149+
events.append(bpf["added_events"].event(data))
154150

155151
bpf["added_events"].open_perf_buffer(handle_added_event)
156152

@@ -165,7 +161,8 @@ def handle_added_event(_, data, __):
165161
self.generate(node, 1)
166162

167163
self.log.info("Ensuring mempool:added event was handled successfully...")
168-
assert_equal(EXPECTED_ADDED_EVENTS, handled_added_events)
164+
assert_equal(1, len(events))
165+
event = events[0]
169166
assert_equal(bytes(event.hash)[::-1].hex(), tx["txid"])
170167
assert_equal(event.vsize, tx["tx"].get_vsize())
171168
assert_equal(event.fee, fee)
@@ -177,9 +174,7 @@ def removed_test(self):
177174
"""Expire a transaction from the mempool and make sure the tracepoint returns
178175
the expected txid, expiry reason, vsize, and fee."""
179176

180-
EXPECTED_REMOVED_EVENTS = 1
181-
handled_removed_events = 0
182-
event = None
177+
events = []
183178

184179
self.log.info("Hooking into mempool:removed tracepoint...")
185180
node = self.nodes[0]
@@ -188,9 +183,7 @@ def removed_test(self):
188183
bpf = BPF(text=MEMPOOL_TRACEPOINTS_PROGRAM, usdt_contexts=[ctx], debug=0)
189184

190185
def handle_removed_event(_, data, __):
191-
nonlocal event, handled_removed_events
192-
event = bpf["removed_events"].event(data)
193-
handled_removed_events += 1
186+
events.append(bpf["removed_events"].event(data))
194187

195188
bpf["removed_events"].open_perf_buffer(handle_removed_event)
196189

@@ -212,7 +205,8 @@ def handle_removed_event(_, data, __):
212205
bpf.perf_buffer_poll(timeout=200)
213206

214207
self.log.info("Ensuring mempool:removed event was handled successfully...")
215-
assert_equal(EXPECTED_REMOVED_EVENTS, handled_removed_events)
208+
assert_equal(1, len(events))
209+
event = events[0]
216210
assert_equal(bytes(event.hash)[::-1].hex(), txid)
217211
assert_equal(event.reason.decode("UTF-8"), "expiry")
218212
assert_equal(event.vsize, tx["tx"].get_vsize())
@@ -226,9 +220,7 @@ def replaced_test(self):
226220
"""Replace one and two transactions in the mempool and make sure the tracepoint
227221
returns the expected txids, vsizes, and fees."""
228222

229-
EXPECTED_REPLACED_EVENTS = 1
230-
handled_replaced_events = 0
231-
event = None
223+
events = []
232224

233225
self.log.info("Hooking into mempool:replaced tracepoint...")
234226
node = self.nodes[0]
@@ -237,9 +229,7 @@ def replaced_test(self):
237229
bpf = BPF(text=MEMPOOL_TRACEPOINTS_PROGRAM, usdt_contexts=[ctx], debug=0)
238230

239231
def handle_replaced_event(_, data, __):
240-
nonlocal event, handled_replaced_events
241-
event = bpf["replaced_events"].event(data)
242-
handled_replaced_events += 1
232+
events.append(bpf["replaced_events"].event(data))
243233

244234
bpf["replaced_events"].open_perf_buffer(handle_replaced_event)
245235

@@ -261,7 +251,8 @@ def handle_replaced_event(_, data, __):
261251
bpf.perf_buffer_poll(timeout=200)
262252

263253
self.log.info("Ensuring mempool:replaced event was handled successfully...")
264-
assert_equal(EXPECTED_REPLACED_EVENTS, handled_replaced_events)
254+
assert_equal(1, len(events))
255+
event = events[0]
265256
assert_equal(bytes(event.replaced_hash)[::-1].hex(), original_tx["txid"])
266257
assert_equal(event.replaced_vsize, original_tx["tx"].get_vsize())
267258
assert_equal(event.replaced_fee, original_fee)
@@ -277,9 +268,7 @@ def rejected_test(self):
277268
"""Create an invalid transaction and make sure the tracepoint returns
278269
the expected txid, rejection reason, peer id, and peer address."""
279270

280-
EXPECTED_REJECTED_EVENTS = 1
281-
handled_rejected_events = 0
282-
event = None
271+
events = []
283272

284273
self.log.info("Adding P2P connection...")
285274
node = self.nodes[0]
@@ -291,9 +280,7 @@ def rejected_test(self):
291280
bpf = BPF(text=MEMPOOL_TRACEPOINTS_PROGRAM, usdt_contexts=[ctx], debug=0)
292281

293282
def handle_rejected_event(_, data, __):
294-
nonlocal event, handled_rejected_events
295-
event = bpf["rejected_events"].event(data)
296-
handled_rejected_events += 1
283+
events.append(bpf["rejected_events"].event(data))
297284

298285
bpf["rejected_events"].open_perf_buffer(handle_rejected_event)
299286

@@ -305,7 +292,8 @@ def handle_rejected_event(_, data, __):
305292
bpf.perf_buffer_poll(timeout=200)
306293

307294
self.log.info("Ensuring mempool:rejected event was handled successfully...")
308-
assert_equal(EXPECTED_REJECTED_EVENTS, handled_rejected_events)
295+
assert_equal(1, len(events))
296+
event = events[0]
309297
assert_equal(bytes(event.hash)[::-1].hex(), tx["tx"].hash)
310298
# The next test is already known to fail, so disable it to avoid
311299
# wasting CPU time and developer time. See

test/functional/interface_usdt_net.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,25 +121,24 @@ def __repr__(self):
121121
checked_outbound_version_msg = 0
122122
events = []
123123

124-
def check_p2p_message(event, inbound):
124+
def check_p2p_message(event, is_inbound):
125125
nonlocal checked_inbound_version_msg, checked_outbound_version_msg
126126
if event.msg_type.decode("utf-8") == "version":
127127
self.log.info(
128-
f"check_p2p_message(): {'inbound' if inbound else 'outbound'} {event}")
128+
f"check_p2p_message(): {'inbound' if is_inbound else 'outbound'} {event}")
129129
peer = self.nodes[0].getpeerinfo()[0]
130130
msg = msg_version()
131131
msg.deserialize(BytesIO(bytes(event.msg[:event.msg_size])))
132132
assert_equal(peer["id"], event.peer_id, peer["id"])
133133
assert_equal(peer["addr"], event.peer_addr.decode("utf-8"))
134134
assert_equal(peer["connection_type"],
135135
event.peer_conn_type.decode("utf-8"))
136-
if inbound:
136+
if is_inbound:
137137
checked_inbound_version_msg += 1
138138
else:
139139
checked_outbound_version_msg += 1
140140

141141
def handle_inbound(_, data, __):
142-
nonlocal events
143142
event = ctypes.cast(data, ctypes.POINTER(P2PMessage)).contents
144143
events.append((event, True))
145144

@@ -157,8 +156,8 @@ def handle_outbound(_, data, __):
157156

158157
self.log.info(
159158
"check receipt and content of in- and outbound version messages")
160-
for event, inbound in events:
161-
check_p2p_message(event, inbound)
159+
for event, is_inbound in events:
160+
check_p2p_message(event, is_inbound)
162161
assert_equal(EXPECTED_INOUTBOUND_VERSION_MSG,
163162
checked_inbound_version_msg)
164163
assert_equal(EXPECTED_INOUTBOUND_VERSION_MSG,

test/functional/interface_usdt_utxocache.py

Lines changed: 29 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -252,43 +252,30 @@ def test_add_spent(self):
252252
# that the handle_* functions succeeded.
253253
EXPECTED_HANDLE_ADD_SUCCESS = 2
254254
EXPECTED_HANDLE_SPENT_SUCCESS = 1
255-
handle_add_succeeds = 0
256-
handle_spent_succeeds = 0
257255

258-
expected_utxocache_spents = []
259256
expected_utxocache_adds = []
257+
expected_utxocache_spents = []
258+
259+
actual_utxocache_adds = []
260+
actual_utxocache_spents = []
261+
262+
def compare_utxo_with_event(utxo, event):
263+
"""Compare a utxo dict to the event produced by BPF"""
264+
assert_equal(utxo["txid"], bytes(event.txid[::-1]).hex())
265+
assert_equal(utxo["index"], event.index)
266+
assert_equal(utxo["height"], event.height)
267+
assert_equal(utxo["value"], event.value)
268+
assert_equal(utxo["is_coinbase"], event.is_coinbase)
260269

261270
def handle_utxocache_add(_, data, __):
262-
nonlocal handle_add_succeeds
263271
event = ctypes.cast(data, ctypes.POINTER(UTXOCacheChange)).contents
264272
self.log.info(f"handle_utxocache_add(): {event}")
265-
add = expected_utxocache_adds.pop(0)
266-
try:
267-
assert_equal(add["txid"], bytes(event.txid[::-1]).hex())
268-
assert_equal(add["index"], event.index)
269-
assert_equal(add["height"], event.height)
270-
assert_equal(add["value"], event.value)
271-
assert_equal(add["is_coinbase"], event.is_coinbase)
272-
except AssertionError:
273-
self.log.exception("Assertion failed")
274-
else:
275-
handle_add_succeeds += 1
273+
actual_utxocache_adds.append(event)
276274

277275
def handle_utxocache_spent(_, data, __):
278-
nonlocal handle_spent_succeeds
279276
event = ctypes.cast(data, ctypes.POINTER(UTXOCacheChange)).contents
280277
self.log.info(f"handle_utxocache_spent(): {event}")
281-
spent = expected_utxocache_spents.pop(0)
282-
try:
283-
assert_equal(spent["txid"], bytes(event.txid[::-1]).hex())
284-
assert_equal(spent["index"], event.index)
285-
assert_equal(spent["height"], event.height)
286-
assert_equal(spent["value"], event.value)
287-
assert_equal(spent["is_coinbase"], event.is_coinbase)
288-
except AssertionError:
289-
self.log.exception("Assertion failed")
290-
else:
291-
handle_spent_succeeds += 1
278+
actual_utxocache_spents.append(event)
292279

293280
bpf["utxocache_add"].open_perf_buffer(handle_utxocache_add)
294281
bpf["utxocache_spent"].open_perf_buffer(handle_utxocache_spent)
@@ -324,19 +311,18 @@ def handle_utxocache_spent(_, data, __):
324311
"is_coinbase": block_index == 0,
325312
})
326313

327-
assert_equal(EXPECTED_HANDLE_ADD_SUCCESS, len(expected_utxocache_adds))
328-
assert_equal(EXPECTED_HANDLE_SPENT_SUCCESS,
329-
len(expected_utxocache_spents))
330-
331314
bpf.perf_buffer_poll(timeout=200)
332-
bpf.cleanup()
315+
316+
assert_equal(EXPECTED_HANDLE_ADD_SUCCESS, len(expected_utxocache_adds), len(actual_utxocache_adds))
317+
assert_equal(EXPECTED_HANDLE_SPENT_SUCCESS, len(expected_utxocache_spents), len(actual_utxocache_spents))
333318

334319
self.log.info(
335320
f"check that we successfully traced {EXPECTED_HANDLE_ADD_SUCCESS} adds and {EXPECTED_HANDLE_SPENT_SUCCESS} spent")
336-
assert_equal(0, len(expected_utxocache_adds))
337-
assert_equal(0, len(expected_utxocache_spents))
338-
assert_equal(EXPECTED_HANDLE_ADD_SUCCESS, handle_add_succeeds)
339-
assert_equal(EXPECTED_HANDLE_SPENT_SUCCESS, handle_spent_succeeds)
321+
for expected_utxo, actual_event in zip(expected_utxocache_adds + expected_utxocache_spents,
322+
actual_utxocache_adds + actual_utxocache_spents):
323+
compare_utxo_with_event(expected_utxo, actual_event)
324+
325+
bpf.cleanup()
340326

341327
def test_flush(self):
342328
""" Tests the utxocache:flush tracepoint API.
@@ -367,9 +353,13 @@ def handle_utxocache_flush(_, data, __):
367353
"size": event.size
368354
})
369355
# sanity checks only
370-
assert event.memory > 0
371-
assert event.duration > 0
372-
handle_flush_succeeds += 1
356+
try:
357+
assert event.memory > 0
358+
assert event.duration > 0
359+
except AssertionError:
360+
self.log.exception("Assertion error")
361+
else:
362+
handle_flush_succeeds += 1
373363

374364
bpf["utxocache_flush"].open_perf_buffer(handle_utxocache_flush)
375365

test/functional/interface_usdt_validation.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ def __repr__(self):
8686
self.duration)
8787

8888
BLOCKS_EXPECTED = 2
89-
blocks_checked = 0
9089
expected_blocks = dict()
9190
events = []
9291

@@ -98,11 +97,9 @@ def __repr__(self):
9897
usdt_contexts=[ctx], debug=0)
9998

10099
def handle_blockconnected(_, data, __):
101-
nonlocal events, blocks_checked
102100
event = ctypes.cast(data, ctypes.POINTER(Block)).contents
103101
self.log.info(f"handle_blockconnected(): {event}")
104102
events.append(event)
105-
blocks_checked += 1
106103

107104
bpf["block_connected"].open_perf_buffer(
108105
handle_blockconnected)
@@ -127,7 +124,7 @@ def handle_blockconnected(_, data, __):
127124
# only plausibility checks
128125
assert event.duration > 0
129126
del expected_blocks[block_hash]
130-
assert_equal(BLOCKS_EXPECTED, blocks_checked)
127+
assert_equal(BLOCKS_EXPECTED, len(events))
131128
assert_equal(0, len(expected_blocks))
132129

133130
bpf.cleanup()

0 commit comments

Comments
 (0)