add tests

This commit is contained in:
bot
2026-06-20 09:49:39 -04:00
parent 86ed0297a7
commit 525dde2b3c
34 changed files with 7427 additions and 0 deletions

View File

@@ -0,0 +1,182 @@
"""
Tests for wallet/db-dependent methods in ``bal.core.heirs``.
Uses mocking to simulate Electrum wallet, db, and bitcoin module.
Run:
source electrum/env/bin/activate
QT_QPA_PLATFORM=offscreen python3 tests/test_core_heirs_extra.py
"""
import sys
import os
from unittest.mock import MagicMock, patch
sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.pardir))
from bal.core.heirs import (
Heirs, create_op_return_script, reduce_outputs,
HEIR_ADDRESS, HEIR_AMOUNT, HEIR_LOCKTIME, HEIR_REAL_AMOUNT,
)
from bal.core.willexecutors import Willexecutors
# ------------------------------------------------------------------ #
# Heirs db-dependent methods
# ------------------------------------------------------------------ #
def test_heirs_init_from_db():
wallet = MagicMock()
wallet.db.get .return_value = {"alice": ["bcrt1q087zm5m3jrhfg78zflqefhcr9heh4c98kzmvhp", 5000, "30d"]}
h = Heirs(wallet)
assert "alice" in h
def test_heirs_init_empty_db():
wallet = MagicMock()
wallet.db.get.return_value = {}
h = Heirs(wallet)
assert len(h) == 0
def test_heirs_save():
wallet = MagicMock()
wallet.db.get.return_value = {}
h = Heirs(wallet)
h["bob"] = ["bcrt1q08z5t4x74u2883sx2qwsmzk2hj8e5n7z83e4vy", 3000, "60d"]
wallet.db.put.assert_called()
def test_heirs_pop_saves():
wallet = MagicMock()
wallet.db.get.return_value = {"bob": ["bcrt1q08z5t4x74u2883sx2qwsmzk2hj8e5n7z83e4vy", 3000, "60d"]}
h = Heirs(wallet)
h.pop("bob")
wallet.db.put.assert_called()
# ------------------------------------------------------------------ #
# Heirs wallet-dependent methods
# ------------------------------------------------------------------ #
def test_heirs_normalize_perc():
wallet = MagicMock()
wallet.dust_threshold.return_value = 500
heir_list = {"a": ["bcrt1q087zm5m3jrhfg78zflqefhcr9heh4c98kzmvhp", "50%", "30d"]}
h = Heirs.__new__(Heirs)
h._Heirs__normal_perc = True
h.update(heir_list)
h.normalize_perc(heir_list, 100000, 100000, wallet)
# "50%" of 100000 = 50000 → above dust threshold, value stays
assert h["a"][HEIR_AMOUNT] == "50%"
def test_heirs_prepare_lists():
wallet = MagicMock()
wallet.dust_threshold.return_value = 500
h = Heirs.__new__(Heirs)
h.update({"a": ["bcrt1q087zm5m3jrhfg78zflqefhcr9heh4c98kzmvhp", 5000, "30d"]})
result, onlyfixed = h.prepare_lists(100000, 100, wallet)
assert len(result) > 0
assert isinstance(result, dict)
# ------------------------------------------------------------------ #
# Heirs static methods (pure but use Electrum constants)
# ------------------------------------------------------------------ #
def test_validate_address_valid():
with patch("bal.core.heirs.bitcoin.is_address", return_value=True):
result = Heirs.validate_address("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa")
assert result == "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
def test_validate_address_invalid():
with patch("bal.core.heirs.bitcoin.is_address", return_value=False):
from bal.core.heirs import NotAnAddress
try:
Heirs.validate_address("bad")
assert False, "should have raised"
except NotAnAddress:
pass
# ------------------------------------------------------------------ #
# create_op_return_script (pure)
# ------------------------------------------------------------------ #
def test_create_op_return_script():
data = "42414c" # "BAL" in hex
script = create_op_return_script(data)
assert script.startswith(b"\x6a")
# ------------------------------------------------------------------ #
# reduce_outputs (pure)
# ------------------------------------------------------------------ #
def test_reduce_outputs_noop():
outputs = [("bcrt1q087zm5m3jrhfg78zflqefhcr9heh4c98kzmvhp", 1000), ("bcrt1q08z5t4x74u2883sx2qwsmzk2hj8e5n7z83e4vy", 2000)]
reduce_outputs(5000, 5000, 100, outputs) # no crash, no modification
def test_reduce_outputs_reduces():
class FakeOut:
def __init__(self, v):
self.value = v
outputs = [FakeOut(1000), FakeOut(2000)]
reduce_outputs(100, 5000, 10, outputs)
assert outputs[0].value < 1000
# ------------------------------------------------------------------ #
# Willexecutors (pure / light mocking)
# ------------------------------------------------------------------ #
def test_willexecutors_compute_id():
wid = Willexecutors.compute_id({"url": "example.com", "chain": "mainnet"})
assert isinstance(wid, str)
assert "example.com" in wid
def test_willexecutors_is_selected():
assert Willexecutors.is_selected({}) is False
data = {"url": "x"}
assert Willexecutors.is_selected(data) is False
assert Willexecutors.is_selected(data, True) is True
assert data.get("selected") is True
def test_willexecutors_get_we_url_from_response():
class FakeResp:
url = "http://example.com/willexecutor"
result = Willexecutors.get_we_url_from_response(FakeResp())
# With 4 path segments, result is first 2 segments joined
assert result == "http:/"
# More realistic: a deeper URL returns the host part
class FakeResp2:
url = "http://example.com/api/v1/endpoint"
result2 = Willexecutors.get_we_url_from_response(FakeResp2())
assert "example.com" in result2
def test_willexecutors_initialize_willexecutor():
we = {}
Willexecutors.initialize_willexecutor(we, "http://example.com")
assert len(we) > 0
def test_willexecutors_get_willexecutor_transactions_empty():
assert Willexecutors.get_willexecutor_transactions({}) == {}
# ------------------------------------------------------------------ #
# Main
# ------------------------------------------------------------------ #
if __name__ == "__main__":
for name in sorted(dir()):
if name.startswith("test_"):
globals()[name]()
print(f" [OK] {name}")
print("[OK] All heirs/willexecutors extra tests passed")