forked from Rockachopa/Timmy-time-dashboard
Move 97 test files from flat tests/ into 13 subdirectories: tests/dashboard/ (8 files — routes, mobile, mission control) tests/swarm/ (17 files — coordinator, docker, routing, tasks) tests/timmy/ (12 files — agent, backends, CLI, tools) tests/self_coding/ (14 files — git safety, indexer, self-modify) tests/lightning/ (3 files — L402, LND, interface) tests/creative/ (8 files — assembler, director, image/music/video) tests/integrations/ (10 files — chat bridge, telegram, voice, websocket) tests/mcp/ (4 files — bootstrap, discovery, executor) tests/spark/ (3 files — engine, tools, events) tests/hands/ (3 files — registry, oracle, phase5) tests/scripture/ (1 file) tests/infrastructure/ (3 files — router cascade, API) tests/security/ (3 files — XSS, regression) Fix Path(__file__) reference in test_mobile_scenarios.py for new depth. Add __init__.py to all test subdirectories. Tests: 1503 passed, 9 failed (pre-existing), 53 errors (pre-existing) https://claude.ai/code/session_019oMFNvD8uSGSSmBMGkBfQN
130 lines
4.2 KiB
Python
130 lines
4.2 KiB
Python
"""Functional tests for lightning.lnd_backend — LND gRPC backend.
|
|
|
|
gRPC is stubbed via sys.modules; tests verify initialization, error
|
|
handling, and the placeholder method behavior.
|
|
"""
|
|
|
|
import importlib
|
|
import os
|
|
import sys
|
|
from unittest.mock import patch, MagicMock
|
|
|
|
import pytest
|
|
|
|
from lightning.base import (
|
|
BackendNotAvailableError,
|
|
Invoice,
|
|
LightningError,
|
|
)
|
|
|
|
|
|
def _make_grpc_mock():
|
|
"""Create a mock grpc module with required attributes."""
|
|
mock_grpc = MagicMock()
|
|
mock_grpc.StatusCode.NOT_FOUND = "NOT_FOUND"
|
|
mock_grpc.RpcError = type("RpcError", (Exception,), {
|
|
"code": lambda self: "NOT_FOUND",
|
|
"details": lambda self: "mocked error",
|
|
})
|
|
return mock_grpc
|
|
|
|
|
|
@pytest.fixture
|
|
def lnd_module():
|
|
"""Reload lnd_backend with grpc stubbed so GRPC_AVAILABLE=True."""
|
|
grpc_mock = _make_grpc_mock()
|
|
old = sys.modules.get("grpc")
|
|
sys.modules["grpc"] = grpc_mock
|
|
try:
|
|
import lightning.lnd_backend as mod
|
|
importlib.reload(mod)
|
|
yield mod
|
|
finally:
|
|
if old is not None:
|
|
sys.modules["grpc"] = old
|
|
else:
|
|
sys.modules.pop("grpc", None)
|
|
# Reload to restore original state
|
|
import lightning.lnd_backend as mod2
|
|
importlib.reload(mod2)
|
|
|
|
|
|
class TestLndBackendInit:
|
|
def test_init_with_explicit_params(self, lnd_module):
|
|
backend = lnd_module.LndBackend(
|
|
host="localhost:10009",
|
|
tls_cert_path="/fake/tls.cert",
|
|
macaroon_path="/fake/admin.macaroon",
|
|
verify_ssl=True,
|
|
)
|
|
assert backend._host == "localhost:10009"
|
|
assert backend._tls_cert_path == "/fake/tls.cert"
|
|
assert backend._macaroon_path == "/fake/admin.macaroon"
|
|
assert backend._verify_ssl is True
|
|
|
|
def test_init_from_env_vars(self, lnd_module):
|
|
env = {
|
|
"LND_GRPC_HOST": "remote:9999",
|
|
"LND_TLS_CERT_PATH": "/env/tls.cert",
|
|
"LND_MACAROON_PATH": "/env/macaroon",
|
|
"LND_VERIFY_SSL": "false",
|
|
}
|
|
with patch.dict(os.environ, env):
|
|
backend = lnd_module.LndBackend()
|
|
assert backend._host == "remote:9999"
|
|
assert backend._verify_ssl is False
|
|
|
|
def test_init_raises_without_grpc(self):
|
|
from lightning.lnd_backend import LndBackend
|
|
with pytest.raises(LightningError, match="grpcio not installed"):
|
|
LndBackend()
|
|
|
|
def test_name_is_lnd(self, lnd_module):
|
|
assert lnd_module.LndBackend.name == "lnd"
|
|
|
|
def test_grpc_available_true_after_reload(self, lnd_module):
|
|
assert lnd_module.GRPC_AVAILABLE is True
|
|
|
|
|
|
class TestLndBackendMethods:
|
|
@pytest.fixture
|
|
def backend(self, lnd_module):
|
|
return lnd_module.LndBackend(
|
|
host="localhost:10009",
|
|
macaroon_path="/fake/path",
|
|
)
|
|
|
|
def test_check_stub_raises_not_available(self, backend):
|
|
"""_check_stub should raise BackendNotAvailableError when stub is None."""
|
|
with pytest.raises(BackendNotAvailableError, match="not fully implemented"):
|
|
backend._check_stub()
|
|
|
|
def test_create_invoice_raises_not_available(self, backend):
|
|
with pytest.raises(BackendNotAvailableError):
|
|
backend.create_invoice(1000, memo="test")
|
|
|
|
def test_check_payment_raises_not_available(self, backend):
|
|
with pytest.raises(BackendNotAvailableError):
|
|
backend.check_payment("abc123")
|
|
|
|
def test_get_invoice_raises_not_available(self, backend):
|
|
with pytest.raises(BackendNotAvailableError):
|
|
backend.get_invoice("abc123")
|
|
|
|
def test_settle_invoice_returns_false(self, backend):
|
|
"""LND auto-settles, so manual settle always returns False."""
|
|
result = backend.settle_invoice("hash", "preimage")
|
|
assert result is False
|
|
|
|
def test_list_invoices_raises_not_available(self, backend):
|
|
with pytest.raises(BackendNotAvailableError):
|
|
backend.list_invoices()
|
|
|
|
def test_get_balance_raises_not_available(self, backend):
|
|
with pytest.raises(BackendNotAvailableError):
|
|
backend.get_balance_sats()
|
|
|
|
def test_health_check_raises_not_available(self, backend):
|
|
with pytest.raises(BackendNotAvailableError):
|
|
backend.health_check()
|