Skip to content

Commit

Permalink
test: add smoke tests with pyln-testing
Browse files Browse the repository at this point in the history
  • Loading branch information
michael1011 committed Sep 7, 2024
1 parent ea3f498 commit b350cac
Show file tree
Hide file tree
Showing 6 changed files with 1,198 additions and 213 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ target/
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
.idea/

tests/*.tar.gz
tests/hold/protos/*
!tests/hold/protos/__init__.py
**/__pycache__
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ db-stop:
docker stop hold-db

integration-tests:
cd tests && poetry run pytest
cd tests && poetry run pytest hold/

binaries:
docker buildx build . -o=build --target=binaries
Expand Down
1,219 changes: 1,012 additions & 207 deletions tests/poetry.lock

Large diffs are not rendered by default.

12 changes: 7 additions & 5 deletions tests/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ license = "MIT"

[tool.poetry.dependencies]
python = "^3.10"
pytest = "^8.3.2"
ruff = "^0.6.1"
grpcio = "^1.65.5"
grpcio-tools = "^1.65.5"
pytest = ">=7,<8"
ruff = "^0.6.4"
grpcio = "^1.66.1"
grpcio-tools = "^1.66.1"
bolt11 = "^2.1.0"
pyln-client = "^24.8.1"
pyln-testing = "^24.8"

[build-system]
requires = ["poetry-core"]
Expand All @@ -24,5 +26,5 @@ exclude = ["hold/protos"]
select = ["ALL"]
ignore = [
"D100", "D101", "D102", "D103", "D104", "D107", "D211", "D212", "S605", "D203", "ISC001", "COM812", "S101",
"PLR2004", "PT011", "TCH001"
"PLR2004", "PT011", "TCH001", "F403", "F405"
]
17 changes: 17 additions & 0 deletions tests/setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash
set -x

script_dir=$(dirname -- "$(readlink -f -- "$0")")
cargo_toml_path="$script_dir/../Cargo.toml"
version=$(awk -F'=' '/^\[package\]/ { in_package = 1 } in_package && /version/ { gsub(/[" ]/, "", $2); print $2; exit }' "$cargo_toml_path")

artifact_url="https://github.com/BoltzExchange/hold/releases/download/v$version/hold-linux-amd64.tar.gz"
archive_file="$script_dir/hold.tar.gz"

if ! curl -L "$artifact_url" -o "$archive_file"; then
exit 1
fi

if ! tar -xzvf "$archive_file" -C "$script_dir"; then
exit 1
fi
160 changes: 160 additions & 0 deletions tests/test_hold.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
from __future__ import annotations

from hashlib import sha256
from pathlib import Path
from threading import Thread

from pyln.client import RpcError
from pyln.testing.fixtures import *


def new_preimage() -> tuple[str, str]:
preimage = os.urandom(32)
return preimage.hex(), sha256(preimage).hexdigest()


@pytest.fixture
def plugin_path() -> Path:
return Path.cwd() / "build" / "hold-linux-amd64"


def pay_with_thread(rpc: any, bolt11: str) -> None:
logger = logging.getLogger(__name__)
try:
rpc.dev_pay(bolt11, dev_use_shadow=False)
except RpcError as e:
logger.info("error paying invoice with payment hash: %s", e)


def test_holdinvoice(node_factory: NodeFactory, plugin_path: Path) -> None:
node = node_factory.get_node(options={"important-plugin": plugin_path})

amount = 1_000
_, payment_hash = new_preimage()
res = node.rpc.call(
"holdinvoice",
{
"amount": amount,
"payment_hash": payment_hash,
},
)

decoded = node.rpc.call("decode", [res["bolt11"]])

assert decoded["payment_hash"] == payment_hash
assert decoded["amount_msat"] == amount


def test_listholdinvoices(node_factory: NodeFactory, plugin_path: Path) -> None:
node = node_factory.get_node(options={"important-plugin": plugin_path})

hashes = [new_preimage()[0] for _ in range(5)]
invoices = [
node.rpc.call(
"holdinvoice",
{
"amount": 1_000,
"payment_hash": payment_hash,
},
)["bolt11"]
for payment_hash in hashes
]

assert len(node.rpc.call("listholdinvoices")["holdinvoices"]) == len(hashes)
assert node.rpc.call(
"listholdinvoices", {"payment_hash": hashes[0]}
) == node.rpc.call("listholdinvoices", {"bolt11": invoices[0]})


def test_settle(
node_factory: NodeFactory, bitcoind: BitcoinD, plugin_path: Path
) -> None:
l1 = node_factory.get_node(options={"important-plugin": plugin_path})
l2 = node_factory.get_node()

l1.rpc.connect(l2.info["id"], "localhost", l2.port)
cl1, _ = l1.fundchannel(l2, 1_000_000)
cl2, _ = l2.fundchannel(l1, 1_000_000)

bitcoind.generate_block(6)

l1.wait_channel_active(cl1)
l1.wait_channel_active(cl2)

preimage, payment_hash = new_preimage()
amount = 1_000
invoice = l1.rpc.call(
"holdinvoice", {"amount": amount, "payment_hash": payment_hash}
)["bolt11"]

Thread(target=pay_with_thread, args=(l2, invoice)).start()
time.sleep(1)

assert (
l1.rpc.call(
"listholdinvoices",
{
"payment_hash": payment_hash,
},
)["holdinvoices"][0]["state"]
== "accepted"
)

l1.rpc.call("settleholdinvoice", {"preimage": preimage})

assert (
l1.rpc.call(
"listholdinvoices",
{
"payment_hash": payment_hash,
},
)["holdinvoices"][0]["state"]
== "paid"
)


def test_cancel(
node_factory: NodeFactory, bitcoind: BitcoinD, plugin_path: Path
) -> None:
l1 = node_factory.get_node(options={"important-plugin": plugin_path})
l2 = node_factory.get_node()

l1.rpc.connect(l2.info["id"], "localhost", l2.port)
cl1, _ = l1.fundchannel(l2, 1_000_000)
cl2, _ = l2.fundchannel(l1, 1_000_000)

bitcoind.generate_block(6)

l1.wait_channel_active(cl1)
l1.wait_channel_active(cl2)

_, payment_hash = new_preimage()
amount = 1_000
invoice = l1.rpc.call(
"holdinvoice", {"amount": amount, "payment_hash": payment_hash}
)["bolt11"]

Thread(target=pay_with_thread, args=(l2, invoice)).start()
time.sleep(1)

assert (
l1.rpc.call(
"listholdinvoices",
{
"payment_hash": payment_hash,
},
)["holdinvoices"][0]["state"]
== "accepted"
)

l1.rpc.call("cancelholdinvoice", {"payment_hash": payment_hash})

assert (
l1.rpc.call(
"listholdinvoices",
{
"payment_hash": payment_hash,
},
)["holdinvoices"][0]["state"]
== "cancelled"
)

0 comments on commit b350cac

Please sign in to comment.