extends SceneTree
## Gate: PerfMetrics is reachable on the AdminFacade at /global/perf.
##
## The facade had only two registrations (ScriptHost, the sky), so the risk here
## is not the method — snapshot() is already gate-covered — it is whether the
## REGISTRATION resolves: right scope, right path, callable at peer role, and
## answering with the shape a caller expects.
##
## Body runs in _process, not _initialize: autoloads do not exist yet during a
## SceneTree script's _initialize (measured — see gate_containment.gd).
var ok := true
var _ran := false
func _p(c: bool, m: String) -> void:
print(("ok " if c else "FAIL: ") + m)
if not c:
ok = false
func _process(_delta: float) -> bool:
if _ran:
return true
_ran = true
_run()
print("GATE perf_admin: %s" % ("PASS" if ok else "FAIL"))
return true
func _run() -> void:
var af: Node = root.get_node_or_null(^"/root/AdminFacade")
var pm: Node = root.get_node_or_null(^"/root/PerfMetrics")
if af == null or pm == null:
_p(false, "AdminFacade and PerfMetrics autoloads present (%s / %s)"
% [str(af != null), str(pm != null)])
return
_p(pm.is_in_group("admin_controllable"), "PerfMetrics joined the admin_controllable group")
_p(str(pm.get_meta("admin_scope", "")) == "global", "scope is global (survives map changes)")
_p(str(pm.get_meta("admin_name", "")) == "perf", "admin_name is 'perf'")
var methods: Array = pm.get_meta("admin_exposed_methods", []) as Array
_p(methods.has("snapshot"), "snapshot is opted in (%s)" % str(methods))
# "authority", NOT "local": results go to admin:result:<seq> with no responder
# segment under LWW, so a value-returning method run on every peer would have
# them clobber each other. See _register_admin's comment.
var scopes: Dictionary = pm.get_meta("admin_call_scopes", {}) as Dictionary
_p(str(scopes.get("snapshot", "")) == "authority",
"snapshot call scope is 'authority' (got '%s')" % str(scopes.get("snapshot", "")))
var roles: Dictionary = pm.get_meta("admin_roles", {}) as Dictionary
var srole: Dictionary = roles.get("snapshot", {}) as Dictionary
_p(str(srole.get("call", "")) == "peer",
"snapshot callable at role 'peer', not the admin default")
# The registration must actually be INDEXED by the facade, not merely tagged.
# list() returns a NODE-INFO dict -- {path, exists, controllable, children,
# props, methods} -- so children live under "children", not as top-level keys.
# An earlier version of this gate asserted the latter and failed while the
# registration was fine; the instrument was wrong, not the subject.
var listing: Dictionary = af.list("/global")
var children: Variant = listing.get("children", [])
var found := false
if children is Array:
for c: Variant in (children as Array):
if str(c).ends_with("perf"):
found = true
elif children is Dictionary:
for k: Variant in (children as Dictionary).keys():
if String(k).ends_with("perf"):
found = true
_p(found, "facade indexes it under /global (children: %s)" % str(children))
# And it must be callable at peer role, returning the documented shape.
# The payload field is "result", NOT "value" -- same correction as above.
var res: Dictionary = af.call_method("/global/perf.snapshot", [], "peer")
_p(bool(res.get("ok", false)), "call_method('/global/perf.snapshot') ok")
var val: Variant = res.get("result", null)
_p(val is Dictionary, "returns a Dictionary")
if val is Dictionary:
var d: Dictionary = val as Dictionary
for key: String in ["uptime_ms", "peers", "joined_total", "left_total", "first_peer_ms", "rtt"]:
if not d.has(key):
_p(false, "snapshot missing key '%s'" % key)
_p(d.has("rtt") and (d["rtt"] is Dictionary), "carries the per-peer rtt map")