Skip to content

Commit 7bdfb9a

Browse files
committed
chore: extended missing test for client and network
Signed-off-by: Manish Dait <[email protected]>
1 parent 028bf1b commit 7bdfb9a

File tree

3 files changed

+166
-3
lines changed

3 files changed

+166
-3
lines changed

src/hiero_sdk_python/executable.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,9 @@ def set_grpc_deadline(self, grpc_deadline: Union[int, float]):
157157

158158
if self._request_timeout is not None and grpc_deadline > self._request_timeout:
159159
warnings.warn(
160-
"grpc_deadline should be smaller than request_timeout", FutureWarning
160+
"grpc_deadline should be smaller than request_timeout. "
161+
"This configuration may cause operations to fail unexpectedly."
162+
, FutureWarning
161163
)
162164

163165
self._grpc_deadline = float(grpc_deadline)
@@ -186,7 +188,9 @@ def set_request_timeout(self, request_timeout: Union[int, float]):
186188

187189
if self._grpc_deadline is not None and request_timeout < self._grpc_deadline:
188190
warnings.warn(
189-
"request_timeout should be larger than grpc_deadline,", FutureWarning
191+
"request_timeout should be larger than grpc_deadline. "
192+
"This configuration may cause operations to fail unexpectedly.",
193+
FutureWarning
190194
)
191195

192196
self._request_timeout = float(request_timeout)

tests/unit/client_test.py

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
from decimal import Decimal
66
import os
77
import pytest
8-
from unittest.mock import patch
8+
from unittest.mock import MagicMock, patch
99

1010
from hiero_sdk_python.client import client as client_module
1111

1212
from hiero_sdk_python import Client, AccountId, PrivateKey
1313
from hiero_sdk_python.hbar import Hbar
14+
from hiero_sdk_python.transaction.transaction_id import TransactionId
1415

1516
pytestmark = pytest.mark.unit
1617

@@ -466,3 +467,74 @@ def test_update_network_refreshes_nodes_and_returns_self():
466467
assert returned is client
467468

468469
client.close()
470+
471+
def test_warning_when_grpc_deadline_exceeds_request_timeout():
472+
"""Warn when grpc_deadline is greater than request_timeout."""
473+
client = Client.for_testnet()
474+
client.set_request_timeout(2)
475+
476+
with pytest.warns(FutureWarning):
477+
client.set_grpc_deadline(7)
478+
479+
480+
def test_warning_when_request_timeout_less_than_grpc_deadline():
481+
"""Warn when request_timeout is less than grpc_deadline."""
482+
client = Client.for_testnet()
483+
client.set_grpc_deadline(7)
484+
485+
with pytest.warns(FutureWarning):
486+
client.set_request_timeout(2)
487+
488+
489+
def test_generate_transaction_id_requires_operator_set():
490+
"""Test that generate_transaction_id raises ValueError if operator_account_id is not set."""
491+
client = Client.for_testnet()
492+
client.operator_account_id = None # ensure not set
493+
494+
with pytest.raises(ValueError, match="Operator account ID must be set"):
495+
client.generate_transaction_id()
496+
497+
client.close()
498+
499+
500+
def test_generate_transaction_id_returns_transaction_id(monkeypatch):
501+
"""Test that generate_transaction_id returns a TransactionId object when operator is set."""
502+
client = Client.for_testnet()
503+
client.operator_account_id = AccountId(0, 0, 1234)
504+
505+
fake_txid = MagicMock(spec=TransactionId)
506+
monkeypatch.setattr("hiero_sdk_python.transaction.transaction_id.TransactionId.generate", lambda account_id: fake_txid)
507+
508+
txid = client.generate_transaction_id()
509+
assert txid is fake_txid
510+
511+
client.close()
512+
513+
514+
def test_get_node_account_ids_returns_correct_list():
515+
"""Test that get_node_account_ids returns a list of node AccountIds."""
516+
client = Client.for_testnet()
517+
518+
# Mock some nodes with _account_id attributes
519+
mock_node1 = MagicMock()
520+
mock_node1._account_id = AccountId(0, 0, 1001)
521+
mock_node2 = MagicMock()
522+
mock_node2._account_id = AccountId(0, 0, 1002)
523+
524+
client.network.nodes = [mock_node1, mock_node2]
525+
526+
node_ids = client.get_node_account_ids()
527+
assert node_ids == [mock_node1._account_id, mock_node2._account_id]
528+
529+
client.close()
530+
531+
532+
def test_get_node_account_ids_raises_when_no_nodes():
533+
"""Test that get_node_account_ids raises ValueError if no nodes are configured."""
534+
client = Client.for_testnet()
535+
client.network.nodes = []
536+
537+
with pytest.raises(ValueError, match="No nodes available"):
538+
client.get_node_account_ids()
539+
540+
client.close()

tests/unit/network_test.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,3 +361,90 @@ def test_get_node_returns_none_when_not_found():
361361
network._healthy_nodes = [node]
362362

363363
assert network._get_node("0.0.999") is None
364+
365+
366+
# Tests parse_mirror_address
367+
@pytest.mark.parametrize(
368+
"mirror_addr,expected_host,expected_port",
369+
[
370+
("localhost:5551", "localhost", 5551),
371+
("127.0.0.1:8080", "127.0.0.1", 8080),
372+
("mirror.hedera.com:443", "mirror.hedera.com", 443),
373+
("justhost", "justhost", 443), # no port defaults to 443
374+
("badport:abc", "badport", 443), # invalid port defaults to 443
375+
],
376+
)
377+
def test_parse_mirror_address(mirror_addr, expected_host, expected_port):
378+
"""Test that _parse_mirror_address correctly splits mirror_address into host and port."""
379+
network = Network("testnet", mirror_address=mirror_addr)
380+
host, port = network._parse_mirror_address()
381+
assert host == expected_host
382+
assert port == expected_port
383+
384+
385+
# Tests _determine_scheme_and_port
386+
@pytest.mark.parametrize(
387+
"host,port,expected_scheme,expected_port",
388+
[
389+
("localhost", 443, "http", 8080),
390+
("127.0.0.1", 80, "http", 80),
391+
("127.0.0.1", 5000, "http", 5000),
392+
("hedera.com", 5600, "https", 443),
393+
("hedera.com", 443, "https", 443),
394+
("hedera.com", 8443, "https", 8443),
395+
],
396+
)
397+
def test_determine_scheme_and_port(host, port, expected_scheme, expected_port):
398+
"""Test that _determine_scheme_and_port correctly computes the scheme (http/https)."""
399+
network = Network("testnet")
400+
scheme, out_port = network._determine_scheme_and_port(host, port)
401+
assert out_port == expected_port
402+
assert scheme == expected_scheme
403+
404+
405+
# Tests for _build_rest_url
406+
@pytest.mark.parametrize(
407+
"scheme,host,port,expected_url",
408+
[
409+
("https", "hedera.com", 443, "https://hedera.com/api/v1"),
410+
("https", "hedera.com", 8443, "https://hedera.com:8443/api/v1"),
411+
("http", "localhost", 80, "http://localhost/api/v1"),
412+
("http", "localhost", 8080, "http://localhost:8080/api/v1"),
413+
],
414+
)
415+
def test_build_rest_url(scheme, host, port, expected_url):
416+
"""Test that _build_rest_url constructs the correct REST API URL."""
417+
network = Network("testnet")
418+
url = network._build_rest_url(scheme, host, port)
419+
assert url == expected_url
420+
421+
422+
def test_get_mirror_rest_url_fallback():
423+
"""Test get_mirror_rest_url fallback behavior when network is not in MIRROR_NODE_URLS."""
424+
# Custom network with no entry in MIRROR_NODE_URLS
425+
network = Network("customnet", mirror_address="localhost:1234")
426+
427+
scheme, port = network._determine_scheme_and_port(*network._parse_mirror_address())
428+
expected_url = network._build_rest_url(scheme, "localhost", port)
429+
430+
assert network.get_mirror_rest_url() == expected_url
431+
432+
433+
@pytest.mark.unit
434+
def test_resolve_nodes_fallback_to_default(monkeypatch):
435+
"""Test that _resolve_nodes falls back to DEFAULT_NODES if no nodes are provided and mirror fetch returns empty."""
436+
network_name = "testnet"
437+
network = Network(network_name)
438+
439+
# Patch _fetch_nodes_from_mirror_node to return empty list
440+
monkeypatch.setattr(network, "_fetch_nodes_from_mirror_node", lambda: [])
441+
442+
# Call _resolve_nodes with nodes=None should fallback to DEFAULT_NODES
443+
resolved_nodes = network._resolve_nodes(None)
444+
445+
# DEFAULT_NODES for testnet has 4 entries (0..3)
446+
expected_count = len(network.DEFAULT_NODES[network_name])
447+
assert isinstance(resolved_nodes, list)
448+
assert all(isinstance(n, _Node) for n in resolved_nodes)
449+
assert len(resolved_nodes) == expected_count
450+
assert resolved_nodes[0]._account_id == network.DEFAULT_NODES[network_name][0][1]

0 commit comments

Comments
 (0)