diff --git a/contrib/clboss-askrene-layer-summary b/contrib/clboss-askrene-layer-summary index d5b4bac..699bf3a 100755 --- a/contrib/clboss-askrene-layer-summary +++ b/contrib/clboss-askrene-layer-summary @@ -128,8 +128,15 @@ def percentile(sorted_vals, q): def load_layers(args, network_option): if args.input is not None: - raw = sys.stdin.read() if args.input == "-" else open(args.input).read() - return json.loads(raw).get("layers", []) + try: + if args.input == "-": + raw = sys.stdin.read() + else: + with open(args.input) as f: + raw = f.read() + return json.loads(raw).get("layers", []) + except (OSError, json.JSONDecodeError) as e: + sys.exit(f"failed to load --input data: {e}") res = run_lightning_cli_command( args.lightning_dir, network_option, "askrene-listlayers", args.layer ) @@ -239,6 +246,10 @@ def main(): s = summarize(target) depth = s.pop("_depth") + if args.json and args.top > 0: + sys.exit("--json cannot be combined with --top " + "(the top list is human-readable only)") + if args.json: print(json.dumps(s, indent=2)) else: diff --git a/tests/boss/test_askrene_layer.cpp b/tests/boss/test_askrene_layer.cpp index 8d0230c..7d96fcd 100644 --- a/tests/boss/test_askrene_layer.cpp +++ b/tests/boss/test_askrene_layer.cpp @@ -320,6 +320,16 @@ test_coalesce_drops_dominated( MockRpcServer& server ) { auto const layer = std::string("coalesce-layer"); + /* Pin the coalescing bucket astronomically large so both writes + * below always land in the same Ev::now()/window bucket regardless + * of when the test runs; otherwise a run straddling a bucket + * boundary re-emits the dominated write as a keep-alive and + * assert_sentinel fires spuriously. This is the final test before + * Shutdown, so the global window needs no restore. */ + Boss::Mod::AskreneLayer::set_aging_window_secs( + std::uint64_t(1000) * 365 * 24 * 60 * 60 + ); + auto assert_first = [](Jsmn::Object const& req) { auto id = assert_method(req, "askrene-inform-channel"); auto params = req["params"];