Skip to content

Commit 651ea7b

Browse files
echonet: refactor, add test utils, share code (#10584)
1 parent f1c5cff commit 651ea7b

File tree

4 files changed

+86
-124
lines changed

4 files changed

+86
-124
lines changed

echonet/tests/test_l1_blocks.py

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,10 @@
88

99
from l1_blocks import L1Blocks
1010
from l1_client import L1Client
11+
from test_utils import TestUtils
1112

1213

1314
class TestFindL1BlockForTx(unittest.TestCase):
14-
FEEDER_TX_SAMPLE = {
15-
"transaction_hash": "0x83c298ad90f4d1b35c0a324fa162a3ab3d3d3a4dcc046f0965bd045083a472",
16-
"version": "0x0",
17-
"contract_address": "0x616757a151c21f9be8775098d591c2807316d992bbc3bb1a5c1821630589256",
18-
"entry_point_selector": "0x1b64b1b3b690b43b9b514fb81377518f4039cd3e4f4914d8a6bdf01d679fb19",
19-
"nonce": "0x19b255",
20-
"calldata": [
21-
"0xf5b6ee2caeb6769659f6c091d209dfdcaf3f69eb",
22-
"0x4c46e830bb56ce22735d5d8fc9cb90309317d0f",
23-
"0xc50a951c4426760ba75c5253985a16196b342168",
24-
"0x11bf9dbebdd770c31ff13808c96a1cb2de15a240274dc527e7d809bb2bf38df",
25-
"0x956dfdeac59085edc3",
26-
"0x0",
27-
],
28-
"type": "L1_HANDLER",
29-
}
30-
3115
def mock_log(self, block_number: int, nonce: int) -> dict:
3216
nonce_hex = f"{nonce:064x}"
3317
return {
@@ -60,7 +44,7 @@ def test_find_l1_block_for_tx_success(self):
6044
mock_client.get_block_number_by_timestamp.side_effect = [100, 200]
6145
mock_client.get_logs.return_value = [self.mock_log(150, 1684053)]
6246

63-
result = L1Blocks.find_l1_block_for_tx(self.FEEDER_TX_SAMPLE, 1000, mock_client)
47+
result = L1Blocks.find_l1_block_for_tx(TestUtils.FEEDER_TX, 1000, mock_client)
6448

6549
self.assertEqual(result, 150)
6650

@@ -71,7 +55,7 @@ def test_find_l1_block_for_tx_multiple_logs_finds_second(self):
7155
mock_log_matching_nonce = self.mock_log(150, 1684053)
7256
mock_client.get_logs.return_value = [mock_log_non_matching_nonce, mock_log_matching_nonce]
7357

74-
result = L1Blocks.find_l1_block_for_tx(self.FEEDER_TX_SAMPLE, 1000, mock_client)
58+
result = L1Blocks.find_l1_block_for_tx(TestUtils.FEEDER_TX, 1000, mock_client)
7559

7660
self.assertEqual(result, 150) # Should return second log's block number
7761

@@ -81,7 +65,7 @@ def test_find_l1_block_for_tx_logs_dont_match(self):
8165
mock_log_non_matching_nonce = self.mock_log(150, 25) # Different nonce
8266
mock_client.get_logs.return_value = [mock_log_non_matching_nonce]
8367

84-
result = L1Blocks.find_l1_block_for_tx(self.FEEDER_TX_SAMPLE, 1000, mock_client)
68+
result = L1Blocks.find_l1_block_for_tx(TestUtils.FEEDER_TX, 1000, mock_client)
8569

8670
self.assertIsNone(result)
8771

@@ -90,7 +74,7 @@ def test_find_l1_block_for_tx_no_logs_found(self):
9074
mock_client.get_block_number_by_timestamp.side_effect = [100, 200]
9175
mock_client.get_logs.return_value = []
9276

93-
result = L1Blocks.find_l1_block_for_tx(self.FEEDER_TX_SAMPLE, 1000, mock_client)
77+
result = L1Blocks.find_l1_block_for_tx(TestUtils.FEEDER_TX, 1000, mock_client)
9478

9579
self.assertIsNone(result)
9680

echonet/tests/test_l1_client.py

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,56 +6,28 @@
66
import requests
77
import unittest
88
from l1_client import L1Client
9+
from test_utils import TestUtils
910
from unittest.mock import Mock, patch
1011

1112

1213
class TestL1Client(unittest.TestCase):
13-
BLOCK_NUMBER_SAMPLE = 20_861_344 # 0x13e51a0
14-
15-
RPC_LOG_RESULT_SAMPLE = {
16-
"address": "0xc662c410c0ecf747543f5ba90660f6abebd9c8c4",
17-
"topics": [
18-
"0xdb80dd488acf86d17c747445b0eabb5d57c541d3bd7b6b87af987858e5066b2b",
19-
"0x000000000000000000000000023a2aac5d0fa69e3243994672822ba43e34e5c9",
20-
"0x07c76a71952ce3acd1f953fd2a3fda8564408b821ff367041c89f44526076633",
21-
"0x02d757788a8d8d6f21d1cd40bce38a8222d70654214e96ff95d8086e684fbee5",
22-
],
23-
"data": (
24-
"0x0000000000000000000000000000000000000000000000000000000000000060"
25-
"0000000000000000000000000000000000000000000000000000000000195c23"
26-
"0000000000000000000000000000000000000000000000000000000000000001"
27-
"0000000000000000000000000000000000000000000000000000000000000003"
28-
"001e220c4ac08b2f247d45721e08af1b2d8d65b640cea780534c8f20dc6ea981"
29-
"000000000000000000000000000000000000000000001c468e3281804cca0000"
30-
"0000000000000000000000000000000000000000000000000000000000000000"
31-
),
32-
"blockNumber": hex(BLOCK_NUMBER_SAMPLE),
33-
"blockHash": "0xe090b2c6fbffb35b6e07d5943938384daa59c8c9fefe487d9952ef9894f2483e",
34-
"transactionHash": "0x66c2ef5ae6708ede5e47daaabfc4b54a53c423160ec27eac06524ea3cd939622",
35-
"transactionIndex": hex(146),
36-
"logIndex": hex(749),
37-
"removed": False,
38-
"blockTimestamp": hex(1_727_673_743),
39-
}
40-
4114
@patch("l1_client.requests.post")
4215
def test_get_logs_retries_after_exception_and_succeeds_on_second_attempt(self, mock_post):
4316
request_exception = requests.RequestException("some error")
4417

4518
successful_response = Mock()
4619
successful_response.raise_for_status.return_value = None
47-
successful_response.json.return_value = {"result": [self.RPC_LOG_RESULT_SAMPLE]}
48-
20+
successful_response.json.return_value = {"result": [TestUtils.RAW_JSON_LOG]}
4921
mock_post.side_effect = [request_exception, successful_response]
5022

5123
client = L1Client(api_key="api_key")
5224
logs = client.get_logs(
53-
from_block=self.BLOCK_NUMBER_SAMPLE,
54-
to_block=self.BLOCK_NUMBER_SAMPLE,
25+
from_block=TestUtils.BLOCK_NUMBER_SAMPLE,
26+
to_block=TestUtils.BLOCK_NUMBER_SAMPLE,
5527
)
5628

5729
self.assertEqual(mock_post.call_count, 2)
58-
self.assertEqual(logs, [self.RPC_LOG_RESULT_SAMPLE])
30+
self.assertEqual(logs, [TestUtils.RAW_JSON_LOG])
5931

6032
def test_get_logs_raises_on_invalid_block_range(self):
6133
client = L1Client(api_key="api_key")

echonet/tests/test_l1_events.py

Lines changed: 9 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -7,102 +7,41 @@
77
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
88

99
from l1_events import L1Events
10+
from test_utils import TestUtils
1011

1112

1213
class TestL1Events(unittest.TestCase):
13-
RAW_JSON_LOG = {
14-
"address": "0xc662c410c0ecf747543f5ba90660f6abebd9c8c4",
15-
"topics": [
16-
"0xdb80dd488acf86d17c747445b0eabb5d57c541d3bd7b6b87af987858e5066b2b", # event_signature
17-
"0x000000000000000000000000f5b6ee2caeb6769659f6c091d209dfdcaf3f69eb", # from_address
18-
"0x0616757a151c21f9be8775098d591c2807316d992bbc3bb1a5c1821630589256", # to_address
19-
"0x01b64b1b3b690b43b9b514fb81377518f4039cd3e4f4914d8a6bdf01d679fb19", # selector
20-
],
21-
"data": "0x0000000000000000000000000000000000000000000000000000000000000060"
22-
"000000000000000000000000000000000000000000000000000000000019b255"
23-
"00000000000000000000000000000000000000000000000000001308aba4ade2"
24-
"0000000000000000000000000000000000000000000000000000000000000005"
25-
"00000000000000000000000004c46e830bb56ce22735d5d8fc9cb90309317d0f"
26-
"000000000000000000000000c50a951c4426760ba75c5253985a16196b342168"
27-
"011bf9dbebdd770c31ff13808c96a1cb2de15a240274dc527e7d809bb2bf38df"
28-
"0000000000000000000000000000000000000000000000956dfdeac59085edc3"
29-
"0000000000000000000000000000000000000000000000000000000000000000",
30-
"blockHash": "0xb33512d13e1a2ff4f3aa6e799a4a2455249be5198760a3f41300a8362d802bf8",
31-
"blockNumber": "0x16cda82",
32-
"blockTimestamp": "0x692c23df",
33-
"transactionHash": "0x726df509fdd23a944f923a6fc18e80cbe7300a54aa34f8e6bd77e9961ca6ce52",
34-
"transactionIndex": "0x4f",
35-
"logIndex": "0x7b",
36-
"removed": False,
37-
}
38-
39-
L1_EVENT = L1Events.L1Event(
40-
contract_address="0x616757a151c21f9be8775098d591c2807316d992bbc3bb1a5c1821630589256",
41-
entry_point_selector=0x1B64B1B3B690B43B9B514FB81377518F4039CD3E4F4914D8A6BDF01D679FB19,
42-
calldata=[
43-
0xF5B6EE2CAEB6769659F6C091D209DFDCAF3F69EB,
44-
0x04C46E830BB56CE22735D5D8FC9CB90309317D0F,
45-
0xC50A951C4426760BA75C5253985A16196B342168,
46-
0x11BF9DBEBDD770C31FF13808C96A1CB2DE15A240274DC527E7D809BB2BF38DF,
47-
0x956DFDEAC59085EDC3,
48-
0x0,
49-
],
50-
nonce=0x19B255,
51-
fee=0x1308ABA4ADE2,
52-
l1_tx_hash="0x726df509fdd23a944f923a6fc18e80cbe7300a54aa34f8e6bd77e9961ca6ce52",
53-
block_timestamp=1764500447,
54-
block_number=23911042,
55-
)
56-
57-
# L1_HANDLER tx from feeder gateway, expected to match the L1Event decoded from L1 logs.
58-
FEEDER_TX = {
59-
"transaction_hash": "0x83c298ad90f4d1b35c0a324fa162a3ab3d3d3a4dcc046f0965bd045083a472",
60-
"version": "0x0",
61-
"contract_address": "0x616757a151c21f9be8775098d591c2807316d992bbc3bb1a5c1821630589256",
62-
"entry_point_selector": "0x1b64b1b3b690b43b9b514fb81377518f4039cd3e4f4914d8a6bdf01d679fb19",
63-
"nonce": "0x19b255",
64-
"calldata": [
65-
"0xf5b6ee2caeb6769659f6c091d209dfdcaf3f69eb",
66-
"0x4c46e830bb56ce22735d5d8fc9cb90309317d0f",
67-
"0xc50a951c4426760ba75c5253985a16196b342168",
68-
"0x11bf9dbebdd770c31ff13808c96a1cb2de15a240274dc527e7d809bb2bf38df",
69-
"0x956dfdeac59085edc3",
70-
"0x0",
71-
],
72-
"type": "L1_HANDLER",
73-
}
74-
7514
def test_decode_log_success(self):
76-
result = L1Events.decode_log(self.RAW_JSON_LOG)
15+
result = L1Events.decode_log(TestUtils.RAW_JSON_LOG)
7716

7817
self.assertIsInstance(result, L1Events.L1Event)
79-
self.assertEqual(result, self.L1_EVENT)
18+
self.assertEqual(result, TestUtils.L1_EVENT)
8019

8120
def test_decode_log_invalid_topics_raises_error(self):
8221
with self.assertRaisesRegex(
8322
ValueError, "Log has insufficient topics for LogMessageToL2 event"
8423
):
85-
log = copy.deepcopy(self.RAW_JSON_LOG)
24+
log = copy.deepcopy(TestUtils.RAW_JSON_LOG)
8625
log["topics"] = ["0x1", "0x2"]
8726
L1Events.decode_log(log)
8827

8928
def test_decode_log_wrong_signature_raises_error(self):
90-
log = copy.deepcopy(self.RAW_JSON_LOG)
29+
log = copy.deepcopy(TestUtils.RAW_JSON_LOG)
9130
log["topics"][0] = "0x0000000000000000000000000000000000000000000000000000000000000001"
9231
with self.assertRaisesRegex(ValueError, "Unhandled event signature"):
9332
L1Events.decode_log(log)
9433

9534
def test_matches_l1_handler_tx_success(self):
96-
l1_event = self.L1_EVENT
35+
l1_event = TestUtils.L1_EVENT
9736

98-
feeder_tx = self.FEEDER_TX
37+
feeder_tx = TestUtils.FEEDER_TX
9938

10039
self.assertTrue(L1Events.l1_event_matches_feeder_tx(l1_event, feeder_tx))
10140

10241
def test_matches_l1_handler_tx_mismatches(self):
103-
l1_event = self.L1_EVENT
42+
l1_event = TestUtils.L1_EVENT
10443

105-
base_feeder_tx = self.FEEDER_TX
44+
base_feeder_tx = TestUtils.FEEDER_TX
10645

10746
mismatch_cases = [
10847
("type", {"type": "INVOKE"}),

echonet/tests/test_utils.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
from l1_events import L1Events
2+
3+
4+
class TestUtils:
5+
BLOCK_NUMBER_SAMPLE = 23911042
6+
7+
RAW_JSON_LOG = {
8+
"address": "0xc662c410c0ecf747543f5ba90660f6abebd9c8c4",
9+
"topics": [
10+
"0xdb80dd488acf86d17c747445b0eabb5d57c541d3bd7b6b87af987858e5066b2b", # event_signature
11+
"0x000000000000000000000000f5b6ee2caeb6769659f6c091d209dfdcaf3f69eb", # from_address
12+
"0x0616757a151c21f9be8775098d591c2807316d992bbc3bb1a5c1821630589256", # to_address
13+
"0x01b64b1b3b690b43b9b514fb81377518f4039cd3e4f4914d8a6bdf01d679fb19", # selector
14+
],
15+
"data": "0x0000000000000000000000000000000000000000000000000000000000000060"
16+
"000000000000000000000000000000000000000000000000000000000019b255"
17+
"00000000000000000000000000000000000000000000000000001308aba4ade2"
18+
"0000000000000000000000000000000000000000000000000000000000000005"
19+
"00000000000000000000000004c46e830bb56ce22735d5d8fc9cb90309317d0f"
20+
"000000000000000000000000c50a951c4426760ba75c5253985a16196b342168"
21+
"011bf9dbebdd770c31ff13808c96a1cb2de15a240274dc527e7d809bb2bf38df"
22+
"0000000000000000000000000000000000000000000000956dfdeac59085edc3"
23+
"0000000000000000000000000000000000000000000000000000000000000000",
24+
"blockHash": "0xb33512d13e1a2ff4f3aa6e799a4a2455249be5198760a3f41300a8362d802bf8",
25+
"blockNumber": "0x16cda82",
26+
"blockTimestamp": "0x692c23df",
27+
"transactionHash": "0x726df509fdd23a944f923a6fc18e80cbe7300a54aa34f8e6bd77e9961ca6ce52",
28+
"transactionIndex": "0x4f",
29+
"logIndex": "0x7b",
30+
"removed": False,
31+
}
32+
33+
L1_EVENT = L1Events.L1Event(
34+
contract_address="0x616757a151c21f9be8775098d591c2807316d992bbc3bb1a5c1821630589256",
35+
entry_point_selector=0x1B64B1B3B690B43B9B514FB81377518F4039CD3E4F4914D8A6BDF01D679FB19,
36+
calldata=[
37+
0xF5B6EE2CAEB6769659F6C091D209DFDCAF3F69EB,
38+
0x04C46E830BB56CE22735D5D8FC9CB90309317D0F,
39+
0xC50A951C4426760BA75C5253985A16196B342168,
40+
0x11BF9DBEBDD770C31FF13808C96A1CB2DE15A240274DC527E7D809BB2BF38DF,
41+
0x956DFDEAC59085EDC3,
42+
0x0,
43+
],
44+
nonce=0x19B255,
45+
fee=0x1308ABA4ADE2,
46+
l1_tx_hash="0x726df509fdd23a944f923a6fc18e80cbe7300a54aa34f8e6bd77e9961ca6ce52",
47+
block_timestamp=1764500447,
48+
block_number=23911042,
49+
)
50+
51+
# L1_HANDLER tx from feeder gateway, expected to match the L1Event decoded from L1 logs.
52+
FEEDER_TX = {
53+
"transaction_hash": "0x83c298ad90f4d1b35c0a324fa162a3ab3d3d3a4dcc046f0965bd045083a472",
54+
"version": "0x0",
55+
"contract_address": "0x616757a151c21f9be8775098d591c2807316d992bbc3bb1a5c1821630589256",
56+
"entry_point_selector": "0x1b64b1b3b690b43b9b514fb81377518f4039cd3e4f4914d8a6bdf01d679fb19",
57+
"nonce": "0x19b255",
58+
"calldata": [
59+
"0xf5b6ee2caeb6769659f6c091d209dfdcaf3f69eb",
60+
"0x4c46e830bb56ce22735d5d8fc9cb90309317d0f",
61+
"0xc50a951c4426760ba75c5253985a16196b342168",
62+
"0x11bf9dbebdd770c31ff13808c96a1cb2de15a240274dc527e7d809bb2bf38df",
63+
"0x956dfdeac59085edc3",
64+
"0x0",
65+
],
66+
"type": "L1_HANDLER",
67+
}

0 commit comments

Comments
 (0)