Skip to content

Commit 490db84

Browse files
authored
Merge pull request #2807 from IntersectMBO/get_block_info_from_log
feat(tests): enhance block minting checks using log data
2 parents bbd0001 + 6f822c5 commit 490db84

File tree

1 file changed

+76
-40
lines changed

1 file changed

+76
-40
lines changed

cardano_node_tests/tests/test_blocks.py

Lines changed: 76 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import logging
77
import os
88
import random
9+
import re
910
import shutil
1011
import signal
1112
import sqlite3
@@ -38,7 +39,7 @@ class TestLeadershipSchedule:
3839
@allure.link(helpers.get_vcs_link())
3940
@pytest.mark.dbsync
4041
@pytest.mark.parametrize("for_epoch", ("current", "next"))
41-
def test_pool_blocks(
42+
def test_pool_blocks( # noqa: C901
4243
self,
4344
cluster_manager: cluster_management.ClusterManager,
4445
cluster_use_pool: tp.Tuple[clusterlib.ClusterLib, str],
@@ -48,12 +49,10 @@ def test_pool_blocks(
4849
4950
* query leadership schedule for selected pool for current epoch or next epoch
5051
* wait for epoch that comes after the queried epoch
51-
* check in log files that the blocks were minted in expected slots
52-
* if db-sync is available:
53-
54-
- get info about minted blocks in queried epoch for the selected pool
55-
- compare leadership schedule with blocks that were actually minted
56-
- compare db-sync records with ledger state dump
52+
* get info about minted blocks in queried epoch for the selected pool
53+
* compare leadership schedule with blocks that were actually minted
54+
* compare log records with ledger state dump
55+
* (optional) check minted blocks in db-sync
5756
"""
5857
# pylint: disable=unused-argument
5958
cluster, pool_name = cluster_use_pool
@@ -62,10 +61,10 @@ def test_pool_blocks(
6261
pool_rec = cluster_manager.cache.addrs_data[pool_name]
6362
pool_id = cluster.g_stake_pool.get_stake_pool_id(pool_rec["cold_key_pair"].vkey_file)
6463

65-
state_dir = cluster_nodes.get_cluster_env().state_dir
66-
pool_log_fname = f"{pool_name.replace('node-', '')}.stdout"
67-
pool_log = state_dir / pool_log_fname
68-
seek_offsets = {str(pool_log): helpers.get_eof_offset(pool_log)}
64+
pool_log = (
65+
cluster_nodes.get_cluster_env().state_dir / f"{pool_name.replace('node-', '')}.stdout"
66+
)
67+
seek_offset = helpers.get_eof_offset(pool_log)
6968
timestamp = time.time()
7069

7170
if for_epoch == "current":
@@ -90,27 +89,66 @@ def test_pool_blocks(
9089
)
9190
slots_when_scheduled = {r.slot_no for r in leadership_schedule}
9291

93-
expected_msgs = [
94-
(pool_log_fname, rf'TraceForgedBlock"\),\("slot",Number {s}')
95-
for s in slots_when_scheduled
96-
]
97-
9892
# Wait for epoch that comes after the queried epoch
99-
cluster.wait_for_epoch(epoch_no=queried_epoch + 1)
93+
cluster.wait_for_epoch(epoch_no=queried_epoch + 1, padding_seconds=10)
94+
95+
# Get number of minted blocks from ledger
96+
ledger_state = clusterlib_utils.get_ledger_state(cluster_obj=cluster)
97+
clusterlib_utils.save_ledger_state(
98+
cluster_obj=cluster,
99+
state_name=temp_template,
100+
ledger_state=ledger_state,
101+
)
102+
blocks_before: tp.Dict[str, int] = ledger_state["blocksBefore"]
103+
pool_id_dec = helpers.decode_bech32(pool_id)
104+
minted_blocks_ledger = blocks_before.get(pool_id_dec) or 0
100105

101106
errors: tp.List[str] = []
102107

103-
log_msgs_errors = logfiles.check_msgs_presence_in_logs(
104-
regex_pairs=expected_msgs,
105-
seek_offsets=seek_offsets,
106-
state_dir=state_dir,
107-
timestamp=timestamp,
108-
)
109-
if len(log_msgs_errors) > len(leadership_schedule) // 2:
110-
log_msgs_errors_joined = "\n ".join(log_msgs_errors)
111-
errors.append(f"Lot of slots missed: \n {log_msgs_errors_joined}")
108+
def _check_logs() -> None:
109+
# Get info about minted blocks in queried epoch for the selected pool
110+
minted_lines = logfiles.find_msgs_in_logs(
111+
regex='"TraceForgedBlock"',
112+
logfile=pool_log,
113+
seek_offset=seek_offset,
114+
timestamp=timestamp,
115+
)
116+
tip = cluster.g_query.get_tip()
117+
last_slot_queried_epoch = int(tip["slot"]) - int(tip["slotInEpoch"] - 1)
118+
first_slot_queried_epoch = (
119+
last_slot_queried_epoch - int(cluster.genesis["epochLength"]) + 1
120+
)
121+
slots_pattern = re.compile(r'"slot",Number (\d+)\.0')
122+
slots_when_minted = {
123+
s
124+
for m in minted_lines
125+
if (o := slots_pattern.search(m)) is not None
126+
and first_slot_queried_epoch <= (s := int(o.group(1))) <= last_slot_queried_epoch
127+
}
112128

113-
if configuration.HAS_DBSYNC:
129+
# Compare leadership schedule with blocks that were actually minted
130+
difference_scheduled = slots_when_minted.difference(slots_when_scheduled)
131+
if difference_scheduled:
132+
errors.append(
133+
f"Some blocks were minted in other slots than scheduled: {difference_scheduled}"
134+
)
135+
136+
difference_minted = slots_when_scheduled.difference(slots_when_minted)
137+
if len(difference_minted) > len(leadership_schedule) // 5:
138+
errors.append(f"Lot of slots missed: {difference_minted}")
139+
140+
# Compare log records with ledger state dump
141+
minted_blocks_logs = len(slots_when_minted)
142+
# Some minted block may not be adopted, and so the total number of adopted blocks
143+
# may be lower than the number of minted blocks.
144+
if minted_blocks_ledger > minted_blocks_logs:
145+
errors.append(
146+
"Number of minted blocks reported by ledger state "
147+
"is higher than number extracted from log file: "
148+
f"{minted_blocks_ledger} vs {minted_blocks_logs}"
149+
)
150+
151+
def _check_dbsync() -> None:
114152
# Get info about minted blocks in queried epoch for the selected pool
115153
minted_blocks = list(
116154
dbsync_queries.query_blocks(
@@ -123,30 +161,28 @@ def test_pool_blocks(
123161
difference_scheduled = slots_when_minted.difference(slots_when_scheduled)
124162
if difference_scheduled:
125163
errors.append(
126-
f"Some blocks were minted in other slots than scheduled: {difference_scheduled}"
164+
"DB-Sync: Some blocks were minted in other slots than scheduled: "
165+
f"{difference_scheduled}"
127166
)
128167

129168
difference_minted = slots_when_scheduled.difference(slots_when_minted)
130-
if len(difference_minted) > len(leadership_schedule) // 2:
131-
errors.append(f"Lot of slots missed: {difference_minted}")
169+
if len(difference_minted) > len(leadership_schedule) // 3:
170+
errors.append(f"DB-Sync: Lot of slots missed: {difference_minted}")
132171

133172
# Compare db-sync records with ledger state dump
134-
ledger_state = clusterlib_utils.get_ledger_state(cluster_obj=cluster)
135-
clusterlib_utils.save_ledger_state(
136-
cluster_obj=cluster,
137-
state_name=temp_template,
138-
ledger_state=ledger_state,
139-
)
140-
blocks_before: tp.Dict[str, int] = ledger_state["blocksBefore"]
141-
pool_id_dec = helpers.decode_bech32(pool_id)
142-
minted_blocks_ledger = blocks_before.get(pool_id_dec) or 0
143173
minted_blocks_db = len(slots_when_minted)
144174
if minted_blocks_ledger != minted_blocks_db:
145175
errors.append(
146-
"Numbers of minted blocks reported by ledger state and db-sync don't match: "
176+
"DB-Sync: Numbers of minted blocks reported by ledger state "
177+
"and db-sync don't match: "
147178
f"{minted_blocks_ledger} vs {minted_blocks_db}"
148179
)
149180

181+
_check_logs()
182+
183+
if configuration.HAS_DBSYNC:
184+
_check_dbsync()
185+
150186
if errors:
151187
# Xfail if cardano-api GH-269 is still open
152188
if (

0 commit comments

Comments
 (0)