Skip to content

Commit c0f2c6e

Browse files
committed
feat(simulator): Add StopWhenSendLineMatch trigger
1 parent b3d41ed commit c0f2c6e

File tree

2 files changed

+47
-2
lines changed

2 files changed

+47
-2
lines changed

hathor/simulator/trigger.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
from typing import TYPE_CHECKING, Callable
1717

1818
if TYPE_CHECKING:
19+
from re import Match, Pattern
20+
21+
from hathor.p2p.protocol import HathorLineReceiver
1922
from hathor.simulator.fake_connection import FakeConnection
2023
from hathor.simulator.miner import AbstractMiner
2124
from hathor.simulator.tx_generator import RandomTransactionGenerator
@@ -107,3 +110,32 @@ def __init__(self, sub_triggers: list[Trigger]) -> None:
107110

108111
def should_stop(self) -> bool:
109112
return all(trigger.should_stop() for trigger in self._sub_triggers)
113+
114+
115+
class StopWhenSendLineMatch(Trigger):
116+
"""Stop the simulation when the node sends a line that matches a designated regex pattern.
117+
"""
118+
119+
def __init__(self, protocol: 'HathorLineReceiver', regex: 'Pattern') -> None:
120+
# patches protocol.sendLine
121+
self.original_send_line = protocol.sendLine
122+
protocol.sendLine = self._send_line_wrapper # type: ignore[method-assign]
123+
124+
# regex pattern
125+
self.regex = regex
126+
127+
# list of matches
128+
self.matches: list['Match'] = []
129+
130+
def _send_line_wrapper(self, line: str) -> None:
131+
"""Check if line matches a designated regex pattern."""
132+
self.original_send_line(line)
133+
match = self.regex.match(line)
134+
if match:
135+
self.matches.append(match)
136+
137+
def should_stop(self) -> bool:
138+
if self.matches:
139+
self.matches = []
140+
return True
141+
return False

tests/simulation/test_trigger.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
from hathor.simulator import Simulator
2-
from hathor.simulator.trigger import StopAfterMinimumBalance, StopAfterNMinedBlocks
1+
import re
2+
3+
from hathor.p2p.messages import ProtocolMessages
4+
from hathor.simulator import FakeConnection, Simulator
5+
from hathor.simulator.trigger import StopAfterMinimumBalance, StopAfterNMinedBlocks, StopWhenSendLineMatch
36
from tests import unittest
47

58

@@ -58,3 +61,13 @@ def test_stop_after_minimum_balance(self):
5861
self.assertLess(wallet.balance[token_uid].available, minimum_balance)
5962
self.assertTrue(self.simulator.run(3600, trigger=trigger))
6063
self.assertGreaterEqual(wallet.balance[token_uid].available, minimum_balance)
64+
65+
def test_stop_after_sendline(self):
66+
manager2 = self.simulator.create_peer()
67+
conn12 = FakeConnection(self.manager1, manager2, latency=0.05)
68+
self.simulator.add_connection(conn12)
69+
70+
expected_prefix = f'^{ProtocolMessages.PEER_ID.value} '.encode('ascii')
71+
regex = re.compile(expected_prefix)
72+
trigger = StopWhenSendLineMatch(conn12._proto1, regex)
73+
self.assertTrue(self.simulator.run(120, trigger=trigger))

0 commit comments

Comments
 (0)