|
1 |
| -# The MIT License (MIT) |
2 |
| -# Copyright © 2024 Opentensor Foundation |
3 |
| -# |
4 |
| -# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated |
5 |
| -# documentation files (the "Software"), to deal in the Software without restriction, including without limitation |
6 |
| -# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, |
7 |
| -# and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
8 |
| -# |
9 |
| -# The above copyright notice and this permission notice shall be included in all copies or substantial portions of |
10 |
| -# the Software. |
11 |
| -# |
12 |
| -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO |
13 |
| -# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
14 |
| -# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
15 |
| -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
16 |
| -# DEALINGS IN THE SOFTWARE. |
17 |
| - |
18 | 1 | import argparse
|
19 | 2 | import unittest.mock as mock
|
20 | 3 | import datetime
|
|
31 | 14 | from bittensor.core import subtensor as subtensor_module
|
32 | 15 | from bittensor.core.async_subtensor import AsyncSubtensor, logging
|
33 | 16 | from bittensor.core.axon import Axon
|
34 |
| -from bittensor.core.chain_data import SubnetHyperparameters |
| 17 | +from bittensor.core.chain_data import SubnetHyperparameters, SelectiveMetagraphIndex |
35 | 18 | from bittensor.core.extrinsics.serving import do_serve_axon
|
36 | 19 | from bittensor.core.settings import version_as_int
|
37 | 20 | from bittensor.core.subtensor import Subtensor
|
@@ -3409,3 +3392,99 @@ def test_start_call(subtensor, mocker):
|
3409 | 3392 | wait_for_finalization=False,
|
3410 | 3393 | )
|
3411 | 3394 | assert result == mocked_extrinsic.return_value
|
| 3395 | + |
| 3396 | + |
| 3397 | +def test_get_metagraph_info_all_fields(subtensor, mocker): |
| 3398 | + """Test get_metagraph_info with all fields (default behavior).""" |
| 3399 | + # Preps |
| 3400 | + netuid = 1 |
| 3401 | + mock_value = {"mock": "data"} |
| 3402 | + |
| 3403 | + mock_runtime_call = mocker.patch.object( |
| 3404 | + subtensor.substrate, |
| 3405 | + "runtime_call", |
| 3406 | + return_value=mocker.Mock(value=mock_value), |
| 3407 | + ) |
| 3408 | + mock_from_dict = mocker.patch.object( |
| 3409 | + subtensor_module.MetagraphInfo, "from_dict", return_value="parsed_metagraph" |
| 3410 | + ) |
| 3411 | + |
| 3412 | + # Call |
| 3413 | + result = subtensor.get_metagraph_info(netuid=netuid) |
| 3414 | + |
| 3415 | + # Asserts |
| 3416 | + assert result == "parsed_metagraph" |
| 3417 | + mock_runtime_call.assert_called_once_with( |
| 3418 | + "SubnetInfoRuntimeApi", |
| 3419 | + "get_selective_metagraph", |
| 3420 | + params=[netuid, SelectiveMetagraphIndex.all_indices()], |
| 3421 | + block_hash=subtensor.determine_block_hash(None), |
| 3422 | + ) |
| 3423 | + mock_from_dict.assert_called_once_with(mock_value) |
| 3424 | + |
| 3425 | + |
| 3426 | +def test_get_metagraph_info_specific_fields(subtensor, mocker): |
| 3427 | + """Test get_metagraph_info with specific fields.""" |
| 3428 | + # Preps |
| 3429 | + netuid = 1 |
| 3430 | + mock_value = {"mock": "data"} |
| 3431 | + fields = [SelectiveMetagraphIndex.Name, SelectiveMetagraphIndex.OwnerHotkey] |
| 3432 | + |
| 3433 | + mock_runtime_call = mocker.patch.object( |
| 3434 | + subtensor.substrate, |
| 3435 | + "runtime_call", |
| 3436 | + return_value=mocker.Mock(value=mock_value), |
| 3437 | + ) |
| 3438 | + mock_from_dict = mocker.patch.object( |
| 3439 | + subtensor_module.MetagraphInfo, "from_dict", return_value="parsed_metagraph" |
| 3440 | + ) |
| 3441 | + |
| 3442 | + # Call |
| 3443 | + result = subtensor.get_metagraph_info(netuid=netuid, field_indices=fields) |
| 3444 | + |
| 3445 | + # Asserts |
| 3446 | + assert result == "parsed_metagraph" |
| 3447 | + mock_runtime_call.assert_called_once_with( |
| 3448 | + "SubnetInfoRuntimeApi", |
| 3449 | + "get_selective_metagraph", |
| 3450 | + params=[netuid, [f.value for f in fields]], |
| 3451 | + block_hash=subtensor.determine_block_hash(None), |
| 3452 | + ) |
| 3453 | + mock_from_dict.assert_called_once_with(mock_value) |
| 3454 | + |
| 3455 | + |
| 3456 | +@pytest.mark.parametrize( |
| 3457 | + "wrong_fields", |
| 3458 | + [ |
| 3459 | + [ |
| 3460 | + "invalid", |
| 3461 | + ], |
| 3462 | + [SelectiveMetagraphIndex.Active, 1], |
| 3463 | + [1, 2, 3], |
| 3464 | + ], |
| 3465 | +) |
| 3466 | +def test_get_metagraph_info_invalid_field_indices(subtensor, wrong_fields): |
| 3467 | + """Test get_metagraph_info raises ValueError on invalid field_indices.""" |
| 3468 | + with pytest.raises( |
| 3469 | + ValueError, |
| 3470 | + match="`field_indices` must be a list of SelectiveMetagraphIndex items.", |
| 3471 | + ): |
| 3472 | + subtensor.get_metagraph_info(netuid=1, field_indices=wrong_fields) |
| 3473 | + |
| 3474 | + |
| 3475 | +def test_get_metagraph_info_subnet_not_exist(subtensor, mocker): |
| 3476 | + """Test get_metagraph_info returns None when subnet doesn't exist.""" |
| 3477 | + netuid = 1 |
| 3478 | + mocker.patch.object( |
| 3479 | + subtensor.substrate, |
| 3480 | + "runtime_call", |
| 3481 | + return_value=mocker.Mock(value=None), |
| 3482 | + ) |
| 3483 | + |
| 3484 | + mocked_logger = mocker.Mock() |
| 3485 | + mocker.patch("bittensor.core.subtensor.logging.error", new=mocked_logger) |
| 3486 | + |
| 3487 | + result = subtensor.get_metagraph_info(netuid=netuid) |
| 3488 | + |
| 3489 | + assert result is None |
| 3490 | + mocked_logger.assert_called_once_with(f"Subnet {netuid} does not exist.") |
0 commit comments