Skip to content

Commit

Permalink
jsonrpc: added functional tests for floresta-cli commands (#340)
Browse files Browse the repository at this point in the history
* getmemoryinfo (linux only)

* getrpcinfo

* uptime

fix: florestad getrpcinfo command and florestad binary on tests

* florestad/src/florestad.rs: bug fix on start method when send 'logpath' from 'floresta-cli getrpcinfo' command;

fix: check for florestad binaries

* search for binaries in /tmp/floresta-integration-tests or ./target/release

* tests/test_framework/test_framework: added full path of 'florestad' binary to avoid break tests
  • Loading branch information
qlrd authored Jan 21, 2025
1 parent ee49346 commit a6768ac
Show file tree
Hide file tree
Showing 7 changed files with 359 additions and 5 deletions.
2 changes: 1 addition & 1 deletion florestad/src/florestad.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ impl Florestad {
.json_rpc_address
.as_ref()
.map(|x| Self::get_ip_address(x, 8332)),
data_dir.clone() + "/output.log",
data_dir.clone() + "output.log",
));

if self.json_rpc.set(server).is_err() {
Expand Down
8 changes: 7 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ florestacli-getpeerinfo-test = "python tests/run_tests.py --test-name floresta_c
florestacli-addnode-test = "python tests/run_tests.py --test-name floresta_cli_addnode"
florestacli-stop-test = "python tests/run_tests.py --test-name floresta_cli_stop"
florestacli-getroots-test = "python tests/run_tests.py --test-name floresta_cli_getroots"
florestacli-getrpcinfo-test = "python tests/run_tests.py --test-name floresta_cli_getrpcinfo"
florestacli-getmemoryinfo-test = "python tests/run_tests.py --test-name floresta_cli_getmemoryinfo"
florestacli-uptime-test = "python tests/run_tests.py --test-name floresta_cli_uptime"
tests = [
"restart-test",
"florestacli-getblockchaininfo-test",
Expand All @@ -50,7 +53,10 @@ tests = [
"florestacli-getpeerinfo-test",
"florestacli-addnode-test",
"florestacli-stop-test",
"florestacli-getroots-test"
"florestacli-getroots-test",
"florestacli-getrpcinfo-test",
"florestacli-getmemoryinfo-test",
"florestacli-uptime-test"
]
pre-commit = ["format", "lint", "tests"]

Expand Down
116 changes: 116 additions & 0 deletions tests/floresta_cli_getmemoryinfo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
"""
floresta_cli_getmemoryinfo.py
This functional test cli utility to interact with a Floresta node with `getmemoryinfo`
"""

import os
import re
import sys
import tempfile
from test_framework.test_framework import FlorestaTestFramework
from test_framework.floresta_rpc import REGTEST_RPC_SERVER


class GetMemoryInfoTest(FlorestaTestFramework):
"""
Test `getmemoryinfo` rpc call, by creating a node and get
some memory stats with `stats` and `mallocinfo` modes
"""

nodes = [-1]

# pylint: disable=duplicate-code
data_dir = os.path.normpath(
os.path.join(
tempfile.gettempdir(),
"floresta-func-tests",
"florestacli-getmemoryinfo-test",
"node-0",
)
)

def set_test_params(self):
"""
Setup the two node florestad process with different data-dirs, electrum-addresses
and rpc-addresses in the same regtest network
"""
GetMemoryInfoTest.nodes[0] = self.add_node_settings(
chain="regtest",
extra_args=[
f"--data-dir={GetMemoryInfoTest.data_dir}",
],
rpcserver=REGTEST_RPC_SERVER,
)

def test_mode_stats_ibd(self, node):
"""
Test `getmemoryinfo stats` when node is in IBD.
It should return a dictionary with key(str)/value(int).
"""
if sys.platform == "linux":
result = node.get_memoryinfo("stats")
assert "locked" in result
assert "chunks_free" in result["locked"]
assert "chunks_used" in result["locked"]
assert "free" in result["locked"]
assert "locked" in result["locked"]
assert "total" in result["locked"]
assert "used" in result["locked"]
assert result["locked"]["chunks_free"] >= 0
assert result["locked"]["chunks_used"] >= 0
assert result["locked"]["free"] >= 0
assert result["locked"]["locked"] >= 0
assert result["locked"]["total"] >= 0
assert result["locked"]["used"] >= 0
else:
print(
f"Skiping test: 'getmemoryinfo stats' not implemented for '{sys.platform}'"
)

def test_mode_mallocinfo_ibd(self, node):
"""
Test `getmemoryinfo mallocinfo` when node is in IBD
It should return a malloc xml string.
"""
if sys.platform == "linux":
pattern = (
r'<malloc version="[^"]+">'
r'<heap nr="\d+">'
r"<allocated>\d+</allocated>"
r"<free>\d+</free>"
r"<total>\d+</total>"
r"<locked>\d+</locked>"
r'<chunks nr="\d+">'
r"<used>\d+</used>"
r"<free>\d+</free>"
r"</chunks>"
r"</heap>"
r"</malloc>"
)
result = node.get_memoryinfo("mallocinfo")
assert re.fullmatch(pattern, result)
else:
print(
f"Skiping test: 'getmemoryinfo malloc' not implemented for '{sys.platform}'"
)

def run_test(self):
"""
Run JSONRPC server on first, wait to connect, then call `addnode ip[:port]`
"""
# Start node
self.run_node(GetMemoryInfoTest.nodes[0])
self.wait_for_rpc_connection(GetMemoryInfoTest.nodes[0])

# Test assertions
node = self.get_node(GetMemoryInfoTest.nodes[0])
self.test_mode_stats_ibd(node)
self.test_mode_mallocinfo_ibd(node)

# Stop node
self.stop_node(GetMemoryInfoTest.nodes[0])


if __name__ == "__main__":
GetMemoryInfoTest().main()
74 changes: 74 additions & 0 deletions tests/floresta_cli_getrpcinfo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""
floresta_cli_getrpcinfo.py
This functional test cli utility to interact with a Floresta node with `getrpcinfo`
"""

import os
import tempfile
from test_framework.test_framework import FlorestaTestFramework
from test_framework.floresta_rpc import REGTEST_RPC_SERVER


class GetRpcInfoTest(FlorestaTestFramework):
"""
Test `getrpcinfo` rpc call, by creating a node
"""

nodes = [-1]
data_dir = os.path.normpath(
os.path.join(
tempfile.gettempdir(),
"floresta-func-tests",
"florestacli-getrpcinfo-test",
"node-0",
)
)

def set_test_params(self):
"""
Setup the two node florestad process with different data-dirs, electrum-addresses
and rpc-addresses in the same regtest network
"""
GetRpcInfoTest.nodes[0] = self.add_node_settings(
chain="regtest",
extra_args=[
f"--data-dir={GetRpcInfoTest.data_dir}",
],
rpcserver=REGTEST_RPC_SERVER,
)

def test_rpcinfo_result(self, node):
"""
Test if the 'getrpcinfo' result was built correctly
"""
result = node.get_rpcinfo()
assert "active_commands" in result
assert "logpath" in result
assert len(result["active_commands"]) == 1
assert "duration" in result["active_commands"][0]
assert "method" in result["active_commands"][0]
assert result["active_commands"][0]["duration"] == 0
assert result["active_commands"][0]["method"] == "getrpcinfo"
assert result["logpath"] == os.path.normpath(
os.path.join(GetRpcInfoTest.data_dir, "regtest", "output.log")
)

def run_test(self):
"""
Run JSONRPC server on first, wait to connect, then call `addnode ip[:port]`
"""
# Start node
self.run_node(GetRpcInfoTest.nodes[0])
self.wait_for_rpc_connection(GetRpcInfoTest.nodes[0])

# Test assertions
node = self.get_node(GetRpcInfoTest.nodes[0])
self.test_rpcinfo_result(node)

# Stop node
self.stop_node(GetRpcInfoTest.nodes[0])


if __name__ == "__main__":
GetRpcInfoTest().main()
74 changes: 74 additions & 0 deletions tests/floresta_cli_uptime.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""
floresta_cli_uptime.py
This functional test cli utility to interact with a Floresta node with `uptime`
"""

import os
import time
import tempfile
from test_framework.test_framework import FlorestaTestFramework
from test_framework.floresta_rpc import REGTEST_RPC_SERVER


class UptimeTest(FlorestaTestFramework):
"""
Test `uptime` rpc call, by creating a node, wait for
some time (10 seconds) and assert that this wait time is
equal to how long florestad has been running
"""

nodes = [-1]

# pylint: disable=duplicate-code
data_dir = os.path.normpath(
os.path.join(
tempfile.gettempdir(),
"floresta-func-tests",
"florestacli-uptime-test",
"node-0",
)
)

def set_test_params(self):
"""
Setup the two node florestad process with different data-dirs, electrum-addresses
and rpc-addresses in the same regtest network
"""
UptimeTest.nodes[0] = self.add_node_settings(
chain="regtest",
extra_args=[
f"--data-dir={UptimeTest.data_dir}",
],
rpcserver=REGTEST_RPC_SERVER,
)

def run_test(self):
"""
Run JSONRPC server on first, wait to connect, then call `addnode ip[:port]`
"""
# Start node
self.run_node(UptimeTest.nodes[0])
self.wait_for_rpc_connection(UptimeTest.nodes[0])

# wait for some seconds before get the uptime
# and get the current time
before = time.time()
time.sleep(5)

# Test assertions
node = self.get_node(UptimeTest.nodes[0])
uptime = node.uptime()

# calculate the elapsed time
after = time.time()
elapsed = int(after - before)

assert uptime == elapsed

# Stop node
self.stop_node(UptimeTest.nodes[0])


if __name__ == "__main__":
UptimeTest().main()
26 changes: 25 additions & 1 deletion tests/test_framework/floresta_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,31 @@ def get_addnode(self, node: str):

def get_roots(self):
"""
Returns the roots of our current forest state performing
Returns the roots of our current floresta state performing
`perform_request('getroots')`
"""
return self.perform_request("getroots")

def get_memoryinfo(self, mode: str):
"""
Returns stats about our memory usage performing
`perform_request('getmemoryinfo', params=[str])`
"""
if mode not in ("stats", "mallocinfo"):
raise ValueError(f"Invalid getmemoryinfo mode: '{mode}'")

return self.perform_request("getmemoryinfo", params=[mode])

def get_rpcinfo(self):
"""
Returns stats about our RPC server performing
`perform_request('getrpcinfo')`
"""
return self.perform_request("getrpcinfo")

def uptime(self):
"""
Returns for how long florestad has been running, in seconds, performing
`perform_request('uptime')`
"""
return self.perform_request("uptime")
Loading

0 comments on commit a6768ac

Please sign in to comment.