Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a mock grpc-web-proxy #536

Merged
merged 8 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ build-self: ensure-docker
cd libs/gl-client-py; maturin develop
#mypy examples/python

check-all: check-rs check-self check-py
check-all: check-rs check-self check-py check-testing-py

check-self: ensure-docker build-self
PYTHONPATH=/repo/libs/gl-testing \
Expand Down
7 changes: 6 additions & 1 deletion libs/gl-testing/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,15 @@ GENALL += ${GEN_TESTING}

${TESTINGDIR}/gltesting/scheduler_grpc.py: testgrpc

check-testing-py:
#cd ${TESTINGDIR}; mypy gltesting
cd ${TESTINGDIR}; poetry install --with=dev; poetry run pytest tests -n 4 -vvv

testgrpc: ${REPO_ROOT}/libs/proto/glclient/scheduler.proto
python -m grpc_tools.protoc ${TESTPROTOC_OPTS} glclient/scheduler.proto
mv ${TESTINGDIR}/gltesting/glclient/scheduler_grpc.py ${TESTINGDIR}/gltesting/scheduler_grpc.py
rm -rf ${TESTINGDIR}/gltesting/glclient


protoc:
uv run python3 -m grpc_tools.protoc -I. --python_out=. --pyi_out=. --purerpc_out=. --grpc_python_out=. gltesting/test.proto

139 changes: 119 additions & 20 deletions libs/gl-testing/gltesting/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,58 @@
from pathlib import Path
import logging
import sys
from pyln.testing.fixtures import bitcoind, teardown_checks, node_cls, test_name, executor, db_provider, test_base_dir, jsonschemas
from pyln.testing.fixtures import (
bitcoind,
teardown_checks,
node_cls,
test_name,
executor,
db_provider,
test_base_dir,
jsonschemas,
)
from gltesting.network import node_factory
from pyln.testing.fixtures import directory as str_directory
from decimal import Decimal
from gltesting.grpcweb import GrpcWebProxy, NodeHandler
from clnvm import ClnVersionManager


logging.basicConfig(level=logging.DEBUG, stream=sys.stdout)
logging.getLogger().addHandler(logging.StreamHandler(sys.stdout))
logging.getLogger("sh").setLevel(logging.ERROR)
logging.getLogger("hpack").setLevel(logging.ERROR)
logger = logging.getLogger(__name__)


@pytest.fixture(autouse=True)
def paths():
"""A fixture to ensure that we have all CLN versions and that
`PATH` points to the latest one.

If you'd like to test a development version rather than the
released ones, ensure that its executable path is in the PATH
before calling `pytest` since this appends to the end.

"""
vm = ClnVersionManager()
versions = vm.get_versions()

# Should be a no-op after the first run
vm.get_all()

latest = [v for v in versions if "gl" in v.tag][-1]

os.environ["PATH"] += f":{vm.get_target_path(latest) / 'usr' / 'local' / 'bin'}"

yield


@pytest.fixture()
def directory(str_directory : str) -> Path:
def directory(str_directory: str) -> Path:
return Path(str_directory) / "gl-testing"


@pytest.fixture()
def cert_directory(directory):
yield directory / "certs"
Expand Down Expand Up @@ -79,31 +116,33 @@ def scheduler(scheduler_id, bitcoind):
btcproxy = bitcoind.get_proxy()

# Copied from pyln.testing.utils.NodeFactory.get_node
feerates=(15000, 11000, 7500, 3750)
feerates = (15000, 11000, 7500, 3750)

def mock_estimatesmartfee(r):
params = r['params']
if params == [2, 'CONSERVATIVE']:
params = r["params"]
if params == [2, "CONSERVATIVE"]:
feerate = feerates[0] * 4
elif params == [6, 'ECONOMICAL']:
elif params == [6, "ECONOMICAL"]:
feerate = feerates[1] * 4
elif params == [12, 'ECONOMICAL']:
elif params == [12, "ECONOMICAL"]:
feerate = feerates[2] * 4
elif params == [100, 'ECONOMICAL']:
elif params == [100, "ECONOMICAL"]:
feerate = feerates[3] * 4
else:
warnings.warn("Don't have a feerate set for {}/{}.".format(
params[0], params[1],
))
warnings.warn(
"Don't have a feerate set for {}/{}.".format(
params[0],
params[1],
)
)
feerate = 42
return {
'id': r['id'],
'error': None,
'result': {
'feerate': Decimal(feerate) / 10**8
},
"id": r["id"],
"error": None,
"result": {"feerate": Decimal(feerate) / 10**8},
}
btcproxy.mock_rpc('estimatesmartfee', mock_estimatesmartfee)

btcproxy.mock_rpc("estimatesmartfee", mock_estimatesmartfee)

s = Scheduler(bitcoind=btcproxy, grpc_port=grpc_port, identity=scheduler_id)
logger.debug(f"Scheduler is running at {s.grpc_addr}")
Expand All @@ -123,9 +162,7 @@ def mock_estimatesmartfee(r):
# here.

if s.debugger.reports != []:
raise ValueError(
f"Some signer reported an error: {s.debugger.reports}"
)
raise ValueError(f"Some signer reported an error: {s.debugger.reports}")


@pytest.fixture()
Expand All @@ -134,3 +171,65 @@ def clients(directory, scheduler, nobody_id):
directory=directory / "clients", scheduler=scheduler, nobody_id=nobody_id
)
yield clients


@pytest.fixture(scope="session", autouse=True)
def cln_path() -> Path:
"""Ensure that the latest CLN version is in PATH.

Some tests use the NodeFactory directly, which relies on being
able to pick a recent CLN version from the `$PATH`. By appending
at the end we just ensure that there is a CLN version to be found.

This is our Elephant in Cairo :-)
https://en.wikipedia.org/wiki/Elephant_in_Cairo
"""
manager = ClnVersionManager()
v = manager.latest()
os.environ["PATH"] += f":{v.bin_path}"
return v.bin_path


@pytest.fixture()
def grpc_test_server():
"""Creates a hello world server over grpc to test the web proxy against.

We explicitly do not use the real protos since the proxy must be
agnostic.

"""
import anyio
from threading import Thread
import purerpc
from util.grpcserver import Server

server = Server()
logging.getLogger("purerpc").setLevel(logging.DEBUG)
server.start()

yield server

server.stop()


@pytest.fixture()
def grpc_web_proxy(scheduler, grpc_test_server):
p = GrpcWebProxy(scheduler=scheduler, grpc_port=grpc_test_server.grpc_port)
p.start()

yield p

p.stop()


@pytest.fixture
def node_grpc_web_proxy(scheduler):
"""A grpc-web proxy that knows how to talk to nodes.
"""
p = GrpcWebProxy(scheduler=scheduler, grpc_port=0)
p.handler_cls = NodeHandler
p.start()

yield p

p.stop()
Loading
Loading