Skip to content

Commit

Permalink
test: adopt USDT utxocache interface tests
Browse files Browse the repository at this point in the history
The USDT interface exposes process internals via the tracepoints. This
means, the USDT interface tests somewhat awardly depend on these
internals. If internals change, the tests have to adopt to that change.
Previously, the USDT interface tests weren't run in the CI so changes
could break the USDT interface tests without being noticed (e.g.
bitcoin/bitcoin#25486).

In fa13375 a 'self.rescan_utxos()' call
was added in the 'generate()' function of the test framework.
'rescan_utxos()' causes the UTXO cache to be flushed. In the USDT
interface tests for the 'utxocache:flush' trancepoint, 'generate()' is
used. As the utxo cache is now flushed more often, the number of flushes
the tests expectes need to be adopted. Also, the utxo cache has now a
different size when being flushed.

The utxocache tracepoint is tested by shutting the node down and
pruning blocks, to test the 'for_prune' argument.

Changes:
- A list 'expected_flushes' is now used which contains 'mode',
  'for_prune', and 'size' for each expected flush.
- When a flush happens, the expected-flush is removed from the list.
  This list is checked to be empty (unchanged).
- Previously, shutting down caused these two flushes:
    UTXOCacheFlush(duration=*, mode=ALWAYS, size=104, memory=*, for_prune=False)
    UTXOCacheFlush(duration=*, mode=ALWAYS, size=0, memory=*, for_prune=False)
  now it causes these flushes:
    UTXOCacheFlush(duration=*, mode=ALWAYS, size=2, memory=*, for_prune=False)
    UTXOCacheFlush(duration=*, mode=ALWAYS, size=0, memory=*, for_prune=False)
  The 104 UTXOs flushed previously were mainly coinbase UTXOs generated
  in previous tests and the test setup. These are now already flushed.
- In the 'for_prune' test we previously hooked into the tracepoint
  before mining blocks. This changed to only get notified about the
  tracepoint being triggered for the prune. Here, the utxo cache is
  empty already as it has just been flushed in 'generate()'.
  old:
    UTXOCacheFlush(duration=*, mode=NONE, size=350, memory=*, for_prune=True)
  new:
    UTXOCacheFlush(duration=*, mode=NONE, size=0, memory=*, for_prune=True)
  • Loading branch information
0xB10C committed Jul 2, 2022
1 parent 220a5a2 commit dba6f82
Showing 1 changed file with 14 additions and 19 deletions.
33 changes: 14 additions & 19 deletions test/functional/interface_usdt_utxocache.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,16 +345,17 @@ def test_flush(self):
# that the handle_* functions succeeded.
EXPECTED_HANDLE_FLUSH_SUCCESS = 3
handle_flush_succeeds = 0
possible_cache_sizes = set()
expected_flushes = []
expected_flushes = list()

def handle_utxocache_flush(_, data, __):
nonlocal handle_flush_succeeds
event = ctypes.cast(data, ctypes.POINTER(UTXOCacheFlush)).contents
self.log.info(f"handle_utxocache_flush(): {event}")
expected = expected_flushes.pop(0)
assert_equal(expected["mode"], FLUSHMODE_NAME[event.mode])
possible_cache_sizes.remove(event.size) # fails if size not in set
expected_flushes.remove({
"mode": FLUSHMODE_NAME[event.mode],
"for_prune": event.for_prune,
"size": event.size
})
# sanity checks only
assert(event.memory > 0)
assert(event.duration > 0)
Expand All @@ -363,25 +364,27 @@ def handle_utxocache_flush(_, data, __):
bpf["utxocache_flush"].open_perf_buffer(handle_utxocache_flush)

self.log.info("stop the node to flush the UTXO cache")
UTXOS_IN_CACHE = 104 # might need to be changed if the eariler tests are modified
UTXOS_IN_CACHE = 2 # might need to be changed if the eariler tests are modified
# A node shutdown causes two flushes. One that flushes UTXOS_IN_CACHE
# UTXOs and one that flushes 0 UTXOs. Normally the 0-UTXO-flush is the
# second flush, however it can happen that the order changes.
possible_cache_sizes = {UTXOS_IN_CACHE, 0}
flush_for_shutdown = {"mode": "ALWAYS", "for_prune": False}
expected_flushes.extend([flush_for_shutdown, flush_for_shutdown])
expected_flushes.append({"mode": "ALWAYS", "for_prune": False, "size": UTXOS_IN_CACHE})
expected_flushes.append({"mode": "ALWAYS", "for_prune": False, "size": 0})
self.stop_node(0)

bpf.perf_buffer_poll(timeout=200)
bpf.cleanup()

self.log.info("check that we don't expect additional flushes")
assert_equal(0, len(expected_flushes))
assert_equal(0, len(possible_cache_sizes))

self.log.info("restart the node with -prune")
self.start_node(0, ["-fastprune=1", "-prune=1"])

BLOCKS_TO_MINE = 350
self.log.info(f"mine {BLOCKS_TO_MINE} blocks to be able to prune")
self.generate(self.wallet, BLOCKS_TO_MINE)

self.log.info("test the utxocache:flush tracepoint API with pruning")
self.log.info("hook into the utxocache:flush tracepoint")
ctx = USDT(pid=self.nodes[0].process.pid)
Expand All @@ -390,15 +393,8 @@ def handle_utxocache_flush(_, data, __):
bpf = BPF(text=utxocache_flushes_program, usdt_contexts=[ctx], debug=0)
bpf["utxocache_flush"].open_perf_buffer(handle_utxocache_flush)

BLOCKS_TO_MINE = 350
self.log.info(f"mine {BLOCKS_TO_MINE} blocks to be able to prune")
self.generate(self.wallet, BLOCKS_TO_MINE)
# we added BLOCKS_TO_MINE coinbase UTXOs to the cache
possible_cache_sizes = {BLOCKS_TO_MINE}
expected_flushes.append(
{"mode": "NONE", "for_prune": True, "size_fn": lambda x: x == BLOCKS_TO_MINE})

self.log.info(f"prune blockchain to trigger a flush for pruning")
expected_flushes.append({"mode": "NONE", "for_prune": True, "size": 0})
self.nodes[0].pruneblockchain(315)

bpf.perf_buffer_poll(timeout=500)
Expand All @@ -407,7 +403,6 @@ def handle_utxocache_flush(_, data, __):
self.log.info(
f"check that we don't expect additional flushes and that the handle_* function succeeded")
assert_equal(0, len(expected_flushes))
assert_equal(0, len(possible_cache_sizes))
assert_equal(EXPECTED_HANDLE_FLUSH_SUCCESS, handle_flush_succeeds)


Expand Down

0 comments on commit dba6f82

Please sign in to comment.