Skip to content

Commit 0e5ec20

Browse files
authored
Merge branch 'staging' into fix/thewhaleking/str-formatting-for-alpha
2 parents 34758a6 + 3db617d commit 0e5ec20

File tree

9 files changed

+149
-86
lines changed

9 files changed

+149
-86
lines changed

tests/unit_tests/conftest.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import pytest
22
from aioresponses import aioresponses
3+
from async_substrate_interface.sync_substrate import SubstrateInterface
4+
5+
import bittensor.core.subtensor
36

47

58
@pytest.fixture
@@ -11,3 +14,30 @@ def force_legacy_torch_compatible_api(monkeypatch):
1114
def mock_aio_response():
1215
with aioresponses() as m:
1316
yield m
17+
18+
19+
@pytest.fixture
20+
def mock_substrate_interface(mocker):
21+
mocked = mocker.MagicMock(
22+
autospec=SubstrateInterface,
23+
)
24+
25+
mocker.patch("bittensor.core.subtensor.SubstrateInterface", return_value=mocked)
26+
27+
return mocked
28+
29+
30+
@pytest.fixture
31+
def subtensor(mock_substrate_interface):
32+
return bittensor.core.subtensor.Subtensor()
33+
34+
35+
@pytest.fixture
36+
def mock_get_external_ip(mocker):
37+
mocked = mocker.Mock(
38+
return_value="192.168.1.1",
39+
)
40+
41+
mocker.patch("bittensor.utils.networking.get_external_ip", mocked)
42+
43+
return mocked

tests/unit_tests/extrinsics/asyncex/test_commit_reveal.py

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

tests/unit_tests/extrinsics/test_commit_reveal.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,6 @@
66
from bittensor.core import subtensor as subtensor_module
77
from bittensor.core.chain_data import SubnetHyperparameters
88
from bittensor.core.extrinsics import commit_reveal
9-
from bittensor.core.subtensor import Subtensor
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-
yield Subtensor()
209

2110

2211
@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,23 +1,10 @@
1-
import pytest
21
from bittensor_wallet import Wallet
32

4-
from bittensor.core import subtensor as subtensor_module
5-
from bittensor.core.settings import version_as_int
6-
from bittensor.core.subtensor import Subtensor
73
from bittensor.core.extrinsics.commit_weights import (
84
_do_commit_weights,
95
_do_reveal_weights,
106
)
11-
12-
13-
@pytest.fixture
14-
def subtensor(mocker):
15-
fake_substrate = mocker.MagicMock()
16-
fake_substrate.websocket.sock.getsockopt.return_value = 0
17-
mocker.patch.object(
18-
subtensor_module, "SubstrateInterface", return_value=fake_substrate
19-
)
20-
return Subtensor()
7+
from bittensor.core.settings import version_as_int
218

229

2310
def test_do_commit_weights(subtensor, mocker):

tests/unit_tests/extrinsics/test_transfer.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,7 @@
1-
import pytest
2-
3-
from bittensor.core import subtensor as subtensor_module
41
from bittensor.core.extrinsics.transfer import _do_transfer
5-
from bittensor.core.subtensor import Subtensor
62
from bittensor.utils.balance import Balance
73

84

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-
195
def test_do_transfer_is_success_true(subtensor, mocker):
206
"""Successful do_transfer call."""
217
# Prep

tests/unit_tests/test_axon.py

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
1+
import asyncio
2+
import contextlib
13
import re
4+
import threading
25
import time
36
from dataclasses import dataclass
47
from typing import Any, Optional, Tuple
58
from unittest import IsolatedAsyncioTestCase
69
from unittest.mock import AsyncMock, MagicMock, patch
710

11+
import aiohttp
812
import fastapi
913
import netaddr
1014
import pydantic
1115
import pytest
16+
import uvicorn
1217
from fastapi.testclient import TestClient
1318
from starlette.requests import Request
1419

15-
from bittensor.core.axon import AxonMiddleware, Axon
20+
from bittensor.core.axon import Axon, AxonMiddleware, FastAPIThreadedServer
1621
from bittensor.core.errors import RunException
1722
from bittensor.core.settings import version_as_int
1823
from bittensor.core.stream import StreamingSynapse
@@ -26,7 +31,7 @@
2631
)
2732

2833

29-
def test_attach_initial():
34+
def test_attach_initial(mock_get_external_ip):
3035
# Create a mock AxonServer instance
3136
server = Axon()
3237

@@ -71,7 +76,7 @@ def wrong_verify_fn(synapse: TestSynapse) -> bool:
7176
server.attach(forward_fn, blacklist_fn, priority_fn, wrong_verify_fn)
7277

7378

74-
def test_attach():
79+
def test_attach(mock_get_external_ip):
7580
# Create a mock AxonServer instance
7681
server = Axon()
7782

@@ -144,7 +149,7 @@ def mock_request():
144149

145150

146151
@pytest.fixture
147-
def axon_instance():
152+
def axon_instance(mock_get_external_ip):
148153
axon = Axon()
149154
axon.required_hash_fields = {"test_endpoint": ["field1", "field2"]}
150155
axon.forward_class_types = {
@@ -329,7 +334,7 @@ async def test_verify_body_integrity_error_cases(
329334
(MockInfo(), "MockInfoString", "edge_case_empty_string"),
330335
],
331336
)
332-
def test_to_string(info_return, expected_output, test_id):
337+
def test_to_string(info_return, expected_output, test_id, mock_get_external_ip):
333338
# Arrange
334339
axon = Axon()
335340
with patch.object(axon, "info", return_value=info_return):
@@ -358,7 +363,9 @@ def test_to_string(info_return, expected_output, test_id):
358363
),
359364
],
360365
)
361-
def test_valid_ipv4_and_ipv6_address(ip, port, expected_ip_type, test_id):
366+
def test_valid_ipv4_and_ipv6_address(
367+
ip, port, expected_ip_type, test_id, mock_get_external_ip
368+
):
362369
# Arrange
363370
hotkey = MockHotkey("5EemgxS7cmYbD34esCFoBgUZZC8JdnGtQvV5Qw3QFUCRRtGP")
364371
coldkey = MockHotkey("5EemgxS7cmYbD34esCFoBgUZZC8JdnGtQvV5Qw3QFUCRRtGP")
@@ -431,7 +438,14 @@ def test_invalid_ip_address(ip, port, expected_exception):
431438
],
432439
)
433440
def test_axon_str_representation(
434-
ip, port, ss58_address, started, forward_fns, expected_str, test_id
441+
ip,
442+
port,
443+
ss58_address,
444+
started,
445+
forward_fns,
446+
expected_str,
447+
test_id,
448+
mock_get_external_ip,
435449
):
436450
# Arrange
437451
hotkey = MockHotkey(ss58_address)
@@ -765,3 +779,50 @@ async def forward_fn(synapse: streaming_synapse_cls):
765779
"computed_body_hash": "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a",
766780
},
767781
)
782+
783+
784+
@pytest.mark.asyncio
785+
async def test_threaded_fastapi():
786+
server_started = threading.Event()
787+
server_stopped = threading.Event()
788+
789+
@contextlib.asynccontextmanager
790+
async def lifespan(app):
791+
server_started.set()
792+
yield
793+
server_stopped.set()
794+
795+
app = fastapi.FastAPI(
796+
lifespan=lifespan,
797+
)
798+
app.get("/")(lambda: "Hello World")
799+
800+
server = FastAPIThreadedServer(
801+
uvicorn.Config(app, loop="none"),
802+
)
803+
server.start()
804+
805+
server_started.wait(3.0)
806+
807+
async def wait_for_server():
808+
while not (server.started or server_stopped.is_set()):
809+
await asyncio.sleep(1.0)
810+
811+
await asyncio.wait_for(wait_for_server(), 7.0)
812+
813+
assert server.is_running is True
814+
815+
async with aiohttp.ClientSession(
816+
base_url="http://127.0.0.1:8000",
817+
) as session:
818+
async with session.get("/") as response:
819+
assert await response.text() == '"Hello World"'
820+
821+
server.stop()
822+
823+
assert server.should_exit is True
824+
825+
server_stopped.wait()
826+
827+
with pytest.raises(aiohttp.ClientConnectorError):
828+
await session.get("/")

tests/unit_tests/test_dendrite.py

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

3030

3131
@pytest.fixture
32-
def setup_dendrite():
32+
def setup_dendrite(mock_get_external_ip):
3333
# Assuming bittensor.Wallet() returns a wallet object
3434
user_wallet = get_mock_wallet()
3535
dendrite_obj = Dendrite(user_wallet)
@@ -51,7 +51,10 @@ def axon_info():
5151
@pytest.fixture(scope="session")
5252
def setup_axon():
5353
wallet = get_mock_wallet()
54-
axon = Axon(wallet)
54+
axon = Axon(
55+
wallet,
56+
external_ip="192.168.1.1",
57+
)
5558
axon.attach(forward_fn=dummy)
5659
axon.start()
5760
yield axon
@@ -103,15 +106,15 @@ def __await__(self):
103106
return self().__await__()
104107

105108

106-
def test_dendrite_create_wallet():
109+
def test_dendrite_create_wallet(mock_get_external_ip):
107110
d = Dendrite(get_mock_wallet())
108111
d = Dendrite(get_mock_wallet().hotkey)
109112
d = Dendrite(get_mock_wallet().coldkeypub)
110113
assert d.__str__() == d.__repr__()
111114

112115

113116
@pytest.mark.asyncio
114-
async def test_forward_many():
117+
async def test_forward_many(mock_get_external_ip):
115118
n = 10
116119
d = Dendrite(wallet=get_mock_wallet())
117120
d.call = AsyncMock()
@@ -128,7 +131,7 @@ async def test_forward_many():
128131
assert len([resp]) == 1
129132

130133

131-
def test_pre_process_synapse():
134+
def test_pre_process_synapse(mock_get_external_ip):
132135
d = Dendrite(wallet=get_mock_wallet())
133136
s = Synapse()
134137
synapse = d.preprocess_synapse_for_request(

tests/unit_tests/test_subtensor.py

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def call_params_with_certificate():
7373
return params
7474

7575

76-
def test_methods_comparable(mocker):
76+
def test_methods_comparable(mock_substrate_interface):
7777
"""Verifies that methods in sync and async Subtensors are comparable."""
7878
# Preps
7979
subtensor = Subtensor(_mock=True)
@@ -142,9 +142,7 @@ def test_serve_axon_with_external_ip_set():
142142
assert axon_info.ip == external_ip
143143

144144

145-
def test_serve_axon_with_external_port_set():
146-
external_ip: str = "2001:0db8:85a3:0000:0000:8a2e:0370:7334"
147-
145+
def test_serve_axon_with_external_port_set(mock_get_external_ip):
148146
internal_port: int = 1234
149147
external_port: int = 5678
150148

@@ -179,14 +177,10 @@ def test_serve_axon_with_external_port_set():
179177
config=mock_config,
180178
)
181179

182-
with mock.patch(
183-
"bittensor.utils.networking.get_external_ip", return_value=external_ip
184-
):
185-
# mock the get_external_ip function to return the external ip
186-
mock_subtensor.serve_axon(
187-
netuid=-1,
188-
axon=mock_axon_with_external_port_set,
189-
)
180+
mock_subtensor.serve_axon(
181+
netuid=-1,
182+
axon=mock_axon_with_external_port_set,
183+
)
190184

191185
mock_serve_axon.assert_called_once()
192186
# verify that the axon is served to the network with the external port
@@ -294,24 +288,6 @@ def test_determine_chain_endpoint_and_network(
294288
assert result_endpoint == expected_endpoint
295289

296290

297-
@pytest.fixture
298-
def subtensor(mocker):
299-
fake_substrate = mocker.MagicMock()
300-
fake_substrate.websocket.sock.getsockopt.return_value = 0
301-
mocker.patch.object(
302-
subtensor_module, "SubstrateInterface", return_value=fake_substrate
303-
)
304-
mocker.patch.object(
305-
sync_substrate,
306-
"connect",
307-
return_value=mocker.MagicMock(),
308-
)
309-
fake_websocket = mocker.MagicMock()
310-
fake_websocket.client.connect.return_value = 0
311-
# mocker.patch.object(subtensor_module, "ws_client", return_value=fake_websocket)
312-
return Subtensor()
313-
314-
315291
@pytest.fixture
316292
def mock_logger():
317293
with mock.patch.object(logging, "warning") as mock_warning:

0 commit comments

Comments
 (0)