Skip to content

Commit 1f27022

Browse files
test(2472): offline unittests
1 parent 8db8d5a commit 1f27022

File tree

9 files changed

+122
-98
lines changed

9 files changed

+122
-98
lines changed

tests/unit_tests/conftest.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import pytest
22
from aioresponses import aioresponses
3+
from substrateinterface.base import SubstrateInterface
4+
from websockets.sync.client import ClientConnection
5+
6+
import bittensor.core.subtensor
37

48

59
@pytest.fixture
@@ -11,3 +15,46 @@ def force_legacy_torch_compatible_api(monkeypatch):
1115
def mock_aio_response():
1216
with aioresponses() as m:
1317
yield m
18+
19+
20+
@pytest.fixture
21+
def websockets_client_connection(mocker):
22+
return mocker.Mock(
23+
autospec=ClientConnection,
24+
**{
25+
"close_code": None,
26+
"socket.getsockopt.return_value": 0,
27+
},
28+
)
29+
30+
31+
@pytest.fixture
32+
def subtensor(websockets_client_connection, mock_substrate_interface):
33+
return bittensor.core.subtensor.Subtensor(
34+
websocket=websockets_client_connection,
35+
)
36+
37+
38+
@pytest.fixture
39+
def mock_substrate_interface(websockets_client_connection, mocker):
40+
mocked = mocker.MagicMock(
41+
autospec=SubstrateInterface,
42+
**{
43+
"websocket": websockets_client_connection,
44+
},
45+
)
46+
47+
mocker.patch("bittensor.core.subtensor.SubstrateInterface", return_value=mocked)
48+
49+
return mocked
50+
51+
52+
@pytest.fixture
53+
def mock_get_external_ip(mocker):
54+
mocked = mocker.Mock(
55+
return_value="192.168.1.1",
56+
)
57+
58+
mocker.patch("bittensor.utils.networking.get_external_ip", mocked)
59+
60+
return mocked

tests/unit_tests/extrinsics/test_async_commit_reveal.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
@pytest.fixture
1111
def subtensor(mocker):
1212
fake_substrate = mocker.AsyncMock()
13-
fake_substrate.websocket.sock.getsockopt.return_value = 0
13+
fake_substrate.websocket.socket.getsockopt.return_value = 0
1414
mocker.patch.object(
1515
subtensor_module, "AsyncSubstrateInterface", return_value=fake_substrate
1616
)

tests/unit_tests/extrinsics/test_commit_reveal.py

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,10 @@
1-
from bittensor.core import subtensor as subtensor_module
2-
from bittensor.core.chain_data import SubnetHyperparameters
3-
from bittensor.core.subtensor import Subtensor
4-
from bittensor.core.extrinsics import commit_reveal
1+
import numpy as np
52
import pytest
63
import torch
7-
import numpy as np
8-
94

10-
@pytest.fixture
11-
def subtensor(mocker):
12-
fake_substrate = mocker.MagicMock()
13-
fake_substrate.websocket.sock.getsockopt.return_value = 0
14-
mocker.patch.object(
15-
subtensor_module, "SubstrateInterface", return_value=fake_substrate
16-
)
17-
yield Subtensor()
5+
from bittensor.core import subtensor as subtensor_module
6+
from bittensor.core.chain_data import SubnetHyperparameters
7+
from bittensor.core.extrinsics import commit_reveal
188

199

2010
@pytest.fixture

tests/unit_tests/extrinsics/test_commit_weights.py

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,9 @@
1-
import pytest
2-
31
from bittensor.core import subtensor as subtensor_module
4-
from bittensor.core.settings import version_as_int
5-
from bittensor.core.subtensor import Subtensor
62
from bittensor.core.extrinsics.commit_weights import (
73
do_commit_weights,
84
do_reveal_weights,
95
)
10-
11-
12-
@pytest.fixture
13-
def subtensor(mocker):
14-
fake_substrate = mocker.MagicMock()
15-
fake_substrate.websocket.sock.getsockopt.return_value = 0
16-
mocker.patch.object(
17-
subtensor_module, "SubstrateInterface", return_value=fake_substrate
18-
)
19-
return Subtensor()
6+
from bittensor.core.settings import version_as_int
207

218

229
def test_do_commit_weights(subtensor, mocker):

tests/unit_tests/extrinsics/test_transfer.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,8 @@
1-
import pytest
2-
31
from bittensor.core import subtensor as subtensor_module
42
from bittensor.core.extrinsics.transfer import do_transfer
5-
from bittensor.core.subtensor import Subtensor
63
from bittensor.utils.balance import Balance
74

85

9-
@pytest.fixture
10-
def subtensor(mocker):
11-
fake_substrate = mocker.MagicMock()
12-
fake_substrate.websocket.sock.getsockopt.return_value = 0
13-
mocker.patch.object(
14-
subtensor_module, "SubstrateInterface", return_value=fake_substrate
15-
)
16-
return Subtensor()
17-
18-
196
def test_do_transfer_is_success_true(subtensor, mocker):
207
"""Successful do_transfer call."""
218
# Prep

tests/unit_tests/test_axon.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
)
4848

4949

50-
def test_attach_initial():
50+
def test_attach_initial(mock_get_external_ip):
5151
# Create a mock AxonServer instance
5252
server = Axon()
5353

@@ -92,7 +92,7 @@ def wrong_verify_fn(synapse: TestSynapse) -> bool:
9292
server.attach(forward_fn, blacklist_fn, priority_fn, wrong_verify_fn)
9393

9494

95-
def test_attach():
95+
def test_attach(mock_get_external_ip):
9696
# Create a mock AxonServer instance
9797
server = Axon()
9898

@@ -165,7 +165,7 @@ def mock_request():
165165

166166

167167
@pytest.fixture
168-
def axon_instance():
168+
def axon_instance(mock_get_external_ip):
169169
axon = Axon()
170170
axon.required_hash_fields = {"test_endpoint": ["field1", "field2"]}
171171
axon.forward_class_types = {
@@ -352,7 +352,7 @@ async def test_verify_body_integrity_error_cases(
352352
(MockInfo(), "MockInfoString", "edge_case_empty_string"),
353353
],
354354
)
355-
def test_to_string(info_return, expected_output, test_id):
355+
def test_to_string(info_return, expected_output, test_id, mock_get_external_ip):
356356
# Arrange
357357
axon = Axon()
358358
with patch.object(axon, "info", return_value=info_return):
@@ -381,7 +381,9 @@ def test_to_string(info_return, expected_output, test_id):
381381
),
382382
],
383383
)
384-
def test_valid_ipv4_and_ipv6_address(ip, port, expected_ip_type, test_id):
384+
def test_valid_ipv4_and_ipv6_address(
385+
ip, port, expected_ip_type, test_id, mock_get_external_ip
386+
):
385387
# Arrange
386388
hotkey = MockHotkey("5EemgxS7cmYbD34esCFoBgUZZC8JdnGtQvV5Qw3QFUCRRtGP")
387389
coldkey = MockHotkey("5EemgxS7cmYbD34esCFoBgUZZC8JdnGtQvV5Qw3QFUCRRtGP")
@@ -454,7 +456,14 @@ def test_invalid_ip_address(ip, port, expected_exception):
454456
],
455457
)
456458
def test_axon_str_representation(
457-
ip, port, ss58_address, started, forward_fns, expected_str, test_id
459+
ip,
460+
port,
461+
ss58_address,
462+
started,
463+
forward_fns,
464+
expected_str,
465+
test_id,
466+
mock_get_external_ip,
458467
):
459468
# Arrange
460469
hotkey = MockHotkey(ss58_address)

tests/unit_tests/test_dendrite.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def dummy(synapse: SynapseDummy) -> SynapseDummy:
4848

4949

5050
@pytest.fixture
51-
def setup_dendrite():
51+
def setup_dendrite(mock_get_external_ip):
5252
# Assuming bittensor.Wallet() returns a wallet object
5353
user_wallet = get_mock_wallet()
5454
dendrite_obj = Dendrite(user_wallet)
@@ -70,7 +70,10 @@ def axon_info():
7070
@pytest.fixture(scope="session")
7171
def setup_axon():
7272
wallet = get_mock_wallet()
73-
axon = Axon(wallet)
73+
axon = Axon(
74+
wallet,
75+
external_ip="192.168.1.1",
76+
)
7477
axon.attach(forward_fn=dummy)
7578
axon.start()
7679
yield axon
@@ -122,15 +125,15 @@ def __await__(self):
122125
return self().__await__()
123126

124127

125-
def test_dendrite_create_wallet():
128+
def test_dendrite_create_wallet(mock_get_external_ip):
126129
d = Dendrite(get_mock_wallet())
127130
d = Dendrite(get_mock_wallet().hotkey)
128131
d = Dendrite(get_mock_wallet().coldkeypub)
129132
assert d.__str__() == d.__repr__()
130133

131134

132135
@pytest.mark.asyncio
133-
async def test_forward_many():
136+
async def test_forward_many(mock_get_external_ip):
134137
n = 10
135138
d = Dendrite(wallet=get_mock_wallet())
136139
d.call = AsyncMock()
@@ -147,7 +150,7 @@ async def test_forward_many():
147150
assert len([resp]) == 1
148151

149152

150-
def test_pre_process_synapse():
153+
def test_pre_process_synapse(mock_get_external_ip):
151154
d = Dendrite(wallet=get_mock_wallet())
152155
s = Synapse()
153156
synapse = d.preprocess_synapse_for_request(

tests/unit_tests/test_subtensor.py

Lines changed: 11 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,7 @@ def test_serve_axon_with_external_ip_set():
9797
assert axon_info.ip == external_ip
9898

9999

100-
def test_serve_axon_with_external_port_set():
101-
external_ip: str = "2001:0db8:85a3:0000:0000:8a2e:0370:7334"
102-
100+
def test_serve_axon_with_external_port_set(mock_get_external_ip):
103101
internal_port: int = 1234
104102
external_port: int = 5678
105103

@@ -134,14 +132,10 @@ def test_serve_axon_with_external_port_set():
134132
config=mock_config,
135133
)
136134

137-
with mock.patch(
138-
"bittensor.utils.networking.get_external_ip", return_value=external_ip
139-
):
140-
# mock the get_external_ip function to return the external ip
141-
mock_subtensor.serve_axon(
142-
netuid=-1,
143-
axon=mock_axon_with_external_port_set,
144-
)
135+
mock_subtensor.serve_axon(
136+
netuid=-1,
137+
axon=mock_axon_with_external_port_set,
138+
)
145139

146140
mock_serve_axon.assert_called_once()
147141
# verify that the axon is served to the network with the external port
@@ -249,19 +243,6 @@ def test_determine_chain_endpoint_and_network(
249243
assert result_endpoint == expected_endpoint
250244

251245

252-
@pytest.fixture
253-
def subtensor(mocker):
254-
fake_substrate = mocker.MagicMock()
255-
fake_substrate.websocket.sock.getsockopt.return_value = 0
256-
mocker.patch.object(
257-
subtensor_module, "SubstrateInterface", return_value=fake_substrate
258-
)
259-
fake_websocket = mocker.MagicMock()
260-
fake_websocket.client.connect.return_value = 0
261-
mocker.patch.object(subtensor_module, "ws_client", return_value=fake_websocket)
262-
return Subtensor()
263-
264-
265246
@pytest.fixture
266247
def mock_logger():
267248
with mock.patch.object(logging, "warning") as mock_warning:
@@ -1925,37 +1906,26 @@ def test_reveal_weights_false(subtensor, mocker):
19251906
assert mocked_extrinsic.call_count == 5
19261907

19271908

1928-
def test_connect_without_substrate(mocker):
1929-
"""Ensure re-connection is called when using an alive substrate."""
1909+
def test_connect_without_substrate(subtensor, websockets_client_connection, mocker):
1910+
"""Ensure re-connection is called when using a disconnected substrate."""
19301911
# Prep
1931-
fake_substrate = mocker.MagicMock()
1932-
fake_substrate.websocket.sock.getsockopt.return_value = 1
1933-
mocker.patch.object(
1934-
subtensor_module, "SubstrateInterface", return_value=fake_substrate
1935-
)
1936-
fake_subtensor = Subtensor()
1912+
websockets_client_connection.socket.getsockopt.return_value = 1
19371913
spy_get_substrate = mocker.spy(Subtensor, "_get_substrate")
19381914

19391915
# Call
1940-
_ = fake_subtensor.block
1916+
_ = subtensor.block
19411917

19421918
# Assertions
19431919
assert spy_get_substrate.call_count == 1
19441920

19451921

1946-
def test_connect_with_substrate(mocker):
1922+
def test_connect_with_substrate(subtensor, mocker):
19471923
"""Ensure re-connection is non called when using an alive substrate."""
19481924
# Prep
1949-
fake_substrate = mocker.MagicMock()
1950-
fake_substrate.websocket.socket.getsockopt.return_value = 0
1951-
mocker.patch.object(
1952-
subtensor_module, "SubstrateInterface", return_value=fake_substrate
1953-
)
1954-
fake_subtensor = Subtensor()
19551925
spy_get_substrate = mocker.spy(Subtensor, "_get_substrate")
19561926

19571927
# Call
1958-
_ = fake_subtensor.block
1928+
_ = subtensor.block
19591929

19601930
# Assertions
19611931
assert spy_get_substrate.call_count == 0

tests/unit_tests/utils/test_networking.py

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,42 @@ def test_int_to_ip6_underflow():
8383

8484

8585
# Test getting external IP address
86-
def test_get_external_ip():
86+
def test_get_external_ip(mocker):
8787
"""Test getting the external IP address."""
88-
assert utils.networking.get_external_ip()
88+
mocked_requests_get = mock.Mock(
89+
return_value=mock.Mock(
90+
**{
91+
"text": "192.168.1.1",
92+
},
93+
),
94+
)
95+
96+
mocker.patch.object(
97+
requests,
98+
"get",
99+
mocked_requests_get,
100+
)
101+
102+
assert utils.networking.get_external_ip() == "192.168.1.1"
103+
104+
mocked_requests_get.assert_called_once_with("https://checkip.amazonaws.com")
89105

90106

91-
def test_get_external_ip_os_broken():
107+
def test_get_external_ip_os_broken(mocker):
92108
"""Test getting the external IP address when os.popen is broken."""
109+
mocked_requests_get = mock.Mock(
110+
return_value=mock.Mock(
111+
**{
112+
"text": "192.168.1.1",
113+
},
114+
),
115+
)
116+
117+
mocker.patch.object(
118+
requests,
119+
"get",
120+
mocked_requests_get,
121+
)
93122

94123
class FakeReadline:
95124
def readline(self):
@@ -99,7 +128,9 @@ def mock_call():
99128
return FakeReadline()
100129

101130
with mock.patch.object(os, "popen", new=mock_call):
102-
assert utils.networking.get_external_ip()
131+
assert utils.networking.get_external_ip() == "192.168.1.1"
132+
133+
mocked_requests_get.assert_called_once_with("https://checkip.amazonaws.com")
103134

104135

105136
def test_get_external_ip_os_request_urllib_broken():

0 commit comments

Comments
 (0)