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

134
tests/bal_fixtures.py Normal file
View File

@@ -0,0 +1,134 @@
"""
Shared test fixtures for the BAL plugin test-suite.
This module centralises the "plausible data" used by the mock tests:
* Valid Bitcoin (regtest) addresses are read **read-only** from the
``giovanna7`` wallet so the heirs / change / will-executor addresses are
genuine, well-formed addresses for the active network.
* A lightweight fake wallet and a fake ``bal_plugin`` are provided so the
core inheritance logic (``Heirs.buildTransactions`` / ``get_transactions``)
can be exercised without a running Electrum daemon or any network access.
Nothing here touches the real wallet file other than reading it; the file is
opened read-only and never written back.
"""
import json
import os
from unittest.mock import MagicMock
from electrum.transaction import PartialTxInput, TxOutpoint
from electrum.util import bfh
# Read-only path to the giovanna7 regtest wallet used to source valid addresses.
GIOVANNA7_WALLET = (
"/home/steal/devel/bal/electrum2/.electrum2222/regtest/wallets.old/giovanna7"
)
# Fallback regtest addresses (used if the wallet file is not available, e.g. on
# CI), so the address-dependent tests can still run. These are valid regtest
# bech32 addresses taken from the giovanna7 wallet.
_FALLBACK_RECEIVING = [
"bcrt1qpm5utekdtmzwnlkh7jq5497vwwf6sm38tljan5",
"bcrt1qazle627r46apscly8lj4q5cxfxgrtuew879jde",
"bcrt1qh2c83yulvs7kgw0g6q3lkxqws4cnf0uxpcgcpt",
"bcrt1qsprcgaldcn6v6l6jw0w6annv7hgkpw7ycxu6mu",
"bcrt1qy02pnw9lulnnwg6m77yghn6v7ndgnjph3hrdmy",
"bcrt1qrmjaxllejgqu6azftsfu2cdjyrz8wjxzsv7wvp",
]
_FALLBACK_CHANGE = [
"bcrt1qzu5u0fgpxq5v42r62aefc2xjn6mehgzhtj4pld",
"bcrt1qs9ya5hserz44elcpt992r0ycrmh3w3chzffawc",
"bcrt1q28qtj5ugfcm4psqenq54sh55uryealeeprk6ju",
]
def load_addresses():
"""Return ``(receiving, change)`` address lists from the giovanna7 wallet.
Falls back to a small hard-coded set of valid regtest addresses when the
wallet file cannot be read, so the tests remain runnable everywhere.
"""
try:
with open(GIOVANNA7_WALLET, "r") as f:
data = json.load(f)
receiving = data["addresses"]["receiving"]
change = data["addresses"]["change"]
if receiving and change:
return receiving, change
except Exception:
pass
return list(_FALLBACK_RECEIVING), list(_FALLBACK_CHANGE)
# Module-level cached address pools.
RECEIVING_ADDRESSES, CHANGE_ADDRESSES = load_addresses()
def heir_addresses(n):
"""Return ``n`` distinct valid heir addresses from the giovanna7 wallet."""
# Use addresses further into the list so they do not collide with the
# change address used by the fake wallet.
return RECEIVING_ADDRESSES[10 : 10 + n]
def willexecutor_addresses(n):
"""Return ``n`` distinct valid will-executor payout addresses."""
return RECEIVING_ADDRESSES[100 : 100 + n]
def change_address():
"""Return a single valid change address."""
return CHANGE_ADDRESSES[0]
def make_utxo(txid_hex, value, out_idx=0):
"""Build a minimal spendable ``PartialTxInput`` with the given value.
Only the fields required by the inheritance transaction builder are set
(trusted value + ``is_mine``); this mirrors how Electrum hands UTXOs to the
plugin without needing a real wallet.
"""
txin = PartialTxInput(prevout=TxOutpoint(txid=bfh(txid_hex), out_idx=out_idx))
txin._trusted_value_sats = value
txin._TxInput__value_sats = value
txin.is_mine = True
return txin
def make_utxos(n, value=1_000_000, prefix="a1"):
"""Return ``n`` synthetic UTXOs of ``value`` satoshis each."""
return [make_utxo(f"{prefix}{i:062x}", value) for i in range(n)]
def fake_wallet(dust_threshold=546):
"""Return a MagicMock wallet sufficient for the inheritance builder.
The change address comes from the real giovanna7 wallet so generated
transactions carry a valid change output address.
"""
w = MagicMock()
w.dust_threshold.return_value = dust_threshold
w.get_change_addresses_for_new_transaction.return_value = [change_address()]
w.get_utxos.return_value = []
w.db.get.return_value = {}
w.db.get_transaction.return_value = None
return w
def fake_bal_plugin(willexecutors=None, no_willexecutor=False, decimal_point=8):
"""Return a fake ``bal_plugin`` exposing only what the builder reads.
Args:
willexecutors: ``{url: we_dict}`` mapping returned by
``Willexecutors.get_willexecutors`` (patched in the tests).
no_willexecutor: value of the ``NO_WILLEXECUTOR`` toggle (whether a
local backup transaction without will-executor is also produced).
decimal_point: BTC decimal point (8 for satoshi precision).
"""
plugin = MagicMock()
plugin.get_decimal_point.return_value = decimal_point
plugin.NO_WILLEXECUTOR.get.return_value = no_willexecutor
plugin._willexecutors = willexecutors or {}
return plugin