pytest: add schema support for JSON responses.

This adds our first (basic) schema, and sews support into pyln-testing
so it will load schemas for any method for doc/schemas/{method}.schema.json.

All JSON responses in a test run are checked against the schema (if any).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2021-05-26 15:17:01 +09:30
parent 8a67c4a1ba
commit ea99a05249
6 changed files with 237 additions and 4 deletions

View File

@@ -601,7 +601,17 @@ class PrettyPrintingLightningRpc(LightningRpc):
eyes. It has some overhead since we re-serialize the request and
result to json in order to pretty print it.
Also validates (optional) schemas for us.
"""
def __init__(self, socket_path, executor=None, logger=logging,
patch_json=True, jsonschemas={}):
super().__init__(
socket_path,
executor,
logger,
patch_json,
)
self.jsonschemas = jsonschemas
def call(self, method, payload=None):
id = self.next_id
@@ -615,6 +625,10 @@ class PrettyPrintingLightningRpc(LightningRpc):
"id": id,
"result": res
}, indent=2))
if method in self.jsonschemas:
self.jsonschemas[method].validate(res)
return res
@@ -625,6 +639,7 @@ class LightningNode(object):
allow_warning=False,
allow_bad_gossip=False,
db=None, port=None, disconnect=None, random_hsm=None, options=None,
jsonschemas={},
**kwargs):
self.bitcoin = bitcoind
self.executor = executor
@@ -639,7 +654,7 @@ class LightningNode(object):
self.rc = 0
socket_path = os.path.join(lightning_dir, TEST_NETWORK, "lightning-rpc").format(node_id)
self.rpc = PrettyPrintingLightningRpc(socket_path, self.executor)
self.rpc = PrettyPrintingLightningRpc(socket_path, self.executor, jsonschemas=jsonschemas)
self.daemon = LightningD(
lightning_dir, bitcoindproxy=bitcoind.get_proxy(),
@@ -1196,7 +1211,7 @@ class NodeFactory(object):
"""A factory to setup and start `lightningd` daemons.
"""
def __init__(self, request, testname, bitcoind, executor, directory,
db_provider, node_cls, throttler):
db_provider, node_cls, throttler, jsonschemas):
if request.node.get_closest_marker("slow_test") and SLOW_MACHINE:
self.valgrind = False
else:
@@ -1211,6 +1226,7 @@ class NodeFactory(object):
self.db_provider = db_provider
self.node_cls = node_cls
self.throttler = throttler
self.jsonschemas = jsonschemas
def split_options(self, opts):
"""Split node options from cli options
@@ -1289,6 +1305,7 @@ class NodeFactory(object):
node = self.node_cls(
node_id, lightning_dir, self.bitcoind, self.executor, self.valgrind, db=db,
port=port, options=options, may_fail=may_fail or expect_fail,
jsonschemas=self.jsonschemas,
**kwargs
)