delivery-telemetry §6.6 reads a CMSD field back into the description §6.1 to §6.3 write, passing over other senders' keys, and refuses with cmsd_malformed, cmsd_type or cmsd_version; §10 lists the extension's CMCD and CMSD custom keys in full, and the registry lists each as a wire identifier of the new kind telemetry-key (and WPJ1, the projection descriptor's magic). telemetry-conformance/cmsd-read/ holds the fields and their outcomes; cmsd_read_verify.py is the second implementation. Co-Authored-By: Claude Opus 5.5 <[email protected]>
330 lines
11 KiB
Python
330 lines
11 KiB
Python
"""The second implementation of reading CMSD fields (extensions/delivery-telemetry.md §6.6),
|
|
written from that text and RFC 9651, sharing no code with wai-rs.
|
|
|
|
python3 -I cmsd_read_verify.py <telemetry-conformance-dir>
|
|
|
|
It reads every field of cmsd-read/cases.json and requires the outcome
|
|
expected/cmsd-read.json states, reads every field expected/cmsd.json states back to its
|
|
description under cmsd/, requires §6.6's table to be the codes the corpus gives, and then
|
|
requires every mutated copy of the corpus to fail. Standard library only.
|
|
"""
|
|
|
|
import copy
|
|
import json
|
|
import os
|
|
import re
|
|
import sys
|
|
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
PREFIX = "science.transaction.wai-"
|
|
|
|
|
|
class Bad(Exception):
|
|
def __init__(self, code):
|
|
Exception.__init__(self, code)
|
|
self.code = code
|
|
|
|
|
|
# ---- RFC 9651, the subset §3.3 writes ---------------------------------------------
|
|
|
|
class Parser:
|
|
def __init__(self, s):
|
|
self.s, self.i = s, 0
|
|
|
|
def peek(self):
|
|
return self.s[self.i] if self.i < len(self.s) else None
|
|
|
|
def key(self):
|
|
c = self.peek()
|
|
if c is None or not (("a" <= c <= "z") or c == "*"):
|
|
raise Bad("cmsd_malformed")
|
|
st = self.i
|
|
while self.peek() is not None and re.fullmatch(r"[a-z0-9_.*-]", self.peek()):
|
|
self.i += 1
|
|
return self.s[st:self.i]
|
|
|
|
def bare(self):
|
|
c = self.peek()
|
|
if c is not None and (c == "-" or c.isdigit()):
|
|
st = self.i
|
|
if c == "-":
|
|
self.i += 1
|
|
d = self.i
|
|
while self.peek() is not None and self.peek().isdigit():
|
|
self.i += 1
|
|
if self.peek() == "." or self.i == d or self.i - d > 15:
|
|
raise Bad("cmsd_malformed")
|
|
return ("int", int(self.s[st:self.i]))
|
|
if c == '"':
|
|
self.i += 1
|
|
out = ""
|
|
while True:
|
|
c = self.peek()
|
|
if c is None:
|
|
raise Bad("cmsd_malformed")
|
|
self.i += 1
|
|
if c == '"':
|
|
return ("str", out)
|
|
if c == "\\":
|
|
e = self.peek()
|
|
if e not in ('"', "\\"):
|
|
raise Bad("cmsd_malformed")
|
|
out += e
|
|
self.i += 1
|
|
elif 0x20 <= ord(c) <= 0x7E:
|
|
out += c
|
|
else:
|
|
raise Bad("cmsd_malformed")
|
|
if c == "?":
|
|
self.i += 1
|
|
v = self.peek()
|
|
if v not in ("0", "1"):
|
|
raise Bad("cmsd_malformed")
|
|
self.i += 1
|
|
return ("bool", v == "1")
|
|
if c is not None and (c.isalpha() and c.isascii() or c == "*"):
|
|
st = self.i
|
|
while self.peek() is not None and re.fullmatch(r"[A-Za-z0-9!#$%&'*+.^_`|~:/-]", self.peek()):
|
|
self.i += 1
|
|
return ("token", self.s[st:self.i])
|
|
raise Bad("cmsd_malformed")
|
|
|
|
def params(self):
|
|
out = {}
|
|
while self.peek() == ";":
|
|
self.i += 1
|
|
while self.peek() == " ":
|
|
self.i += 1
|
|
k = self.key()
|
|
if self.peek() == "=":
|
|
self.i += 1
|
|
v = self.bare()
|
|
else:
|
|
v = ("bool", True)
|
|
out[k] = v
|
|
return out
|
|
|
|
def sep(self):
|
|
while self.peek() in (" ", "\t"):
|
|
self.i += 1
|
|
if self.i == len(self.s):
|
|
return False
|
|
if self.peek() != ",":
|
|
raise Bad("cmsd_malformed")
|
|
self.i += 1
|
|
while self.peek() in (" ", "\t"):
|
|
self.i += 1
|
|
if self.i == len(self.s):
|
|
raise Bad("cmsd_malformed")
|
|
return True
|
|
|
|
|
|
def parse_dict(s):
|
|
p = Parser(s)
|
|
while p.peek() == " ":
|
|
p.i += 1
|
|
out = {}
|
|
if p.i == len(s):
|
|
return out
|
|
while True:
|
|
k = p.key()
|
|
if p.peek() == "=":
|
|
p.i += 1
|
|
if p.peek() == "(":
|
|
p.i += 1
|
|
items = []
|
|
while True:
|
|
while p.peek() == " ":
|
|
p.i += 1
|
|
if p.peek() == ")":
|
|
p.i += 1
|
|
break
|
|
t, v = p.bare()
|
|
if t != "int" or p.peek() not in (" ", ")"):
|
|
raise Bad("cmsd_malformed")
|
|
items.append(v)
|
|
v = ("list", items)
|
|
else:
|
|
v = p.bare()
|
|
else:
|
|
v = ("bool", True)
|
|
if p.peek() == ";":
|
|
raise Bad("cmsd_malformed")
|
|
out[k] = v
|
|
if not p.sep():
|
|
return out
|
|
|
|
|
|
def parse_list(s):
|
|
p = Parser(s)
|
|
while p.peek() == " ":
|
|
p.i += 1
|
|
out = []
|
|
if p.i == len(s):
|
|
return out
|
|
while True:
|
|
v = p.bare()
|
|
out.append((v, p.params()))
|
|
if not p.sep():
|
|
return out
|
|
|
|
|
|
# ---- §6.6 --------------------------------------------------------------------------
|
|
|
|
def want(v, kind):
|
|
if v[0] != kind:
|
|
raise Bad("cmsd_type")
|
|
return v[1]
|
|
|
|
|
|
def nonneg(v):
|
|
x = want(v, "int")
|
|
if x < 0:
|
|
raise Bad("cmsd_type")
|
|
return x
|
|
|
|
|
|
def nonempty(v):
|
|
x = want(v, "str")
|
|
if x == "":
|
|
raise Bad("cmsd_type")
|
|
return x
|
|
|
|
|
|
def hex64(v):
|
|
x = nonempty(v)
|
|
if not re.fullmatch(r"[0-9a-f]{64}", x):
|
|
raise Bad("cmsd_type")
|
|
return x
|
|
|
|
|
|
def decimal(v):
|
|
x = nonempty(v)
|
|
if not re.fullmatch(r"0|[1-9][0-9]{0,14}", x):
|
|
raise Bad("cmsd_type")
|
|
return int(x)
|
|
|
|
|
|
def read_static(field):
|
|
d = parse_dict(field)
|
|
out = {"at": None, "d": None, "ht": None, "nor": None, "nrr": None, "ot": None, "sf": None, "st": None,
|
|
"su": False, "content_hash": None, "layer": None, "layers_total": None, "receipt": None, "op": None}
|
|
named = {"v", "at", "d", "ht", "nor", "nrr", "ot", "sf", "st", "su"}
|
|
for k, v in d.items():
|
|
if v[0] == "list":
|
|
if k in named or k.startswith(PREFIX):
|
|
raise Bad("cmsd_type")
|
|
continue
|
|
if k == "v":
|
|
if want(v, "int") != 1:
|
|
raise Bad("cmsd_version")
|
|
elif k in ("at", "d", "ht"):
|
|
out[k] = nonneg(v)
|
|
elif k in ("nor", "nrr"):
|
|
out[k] = nonempty(v)
|
|
elif k in ("ot", "sf", "st"):
|
|
out[k] = want(v, "token")
|
|
elif k == "su":
|
|
out["su"] = want(v, "bool")
|
|
elif k == PREFIX + "ch":
|
|
out["content_hash"] = hex64(v)
|
|
elif k == PREFIX + "l":
|
|
out["layer"] = decimal(v)
|
|
elif k == PREFIX + "lt":
|
|
out["layers_total"] = decimal(v)
|
|
elif k == PREFIX + "rcpt":
|
|
out["receipt"] = hex64(v)
|
|
elif k == PREFIX + "op":
|
|
out["op"] = want(v, "token")
|
|
return out
|
|
|
|
|
|
def read_dynamic(field):
|
|
out = []
|
|
for value, params in parse_list(field):
|
|
e = {"server": nonempty(value), "du": False, "etp": None, "mb": None, "rd": None, "rtt": None, "drop": None}
|
|
for k, v in params.items():
|
|
if k == "du":
|
|
e["du"] = want(v, "bool")
|
|
elif k in ("etp", "mb", "rd", "rtt"):
|
|
e[k] = nonneg(v)
|
|
elif k == PREFIX + "drop":
|
|
e["drop"] = decimal(v)
|
|
out.append(e)
|
|
return out
|
|
|
|
|
|
def read(field, value):
|
|
try:
|
|
return {"read": read_static(value) if field == "static" else read_dynamic(value)}
|
|
except Bad as e:
|
|
return {"refuse": e.code}
|
|
|
|
|
|
def table_codes():
|
|
text = open(os.path.join(HERE, "..", "extensions", "delivery-telemetry.md"), encoding="utf-8").read()
|
|
at = text.index("§6.6")
|
|
end = text.index("\n## ", at)
|
|
return re.findall(r"^\| `(cmsd_[a-z]+)` \|", text[at:end], re.M)
|
|
|
|
|
|
def check(cases, expected, written, descs):
|
|
fails = []
|
|
given = set()
|
|
for c in cases:
|
|
got = read(c["field"], c["value"])
|
|
if got != expected.get(c["name"]):
|
|
fails.append("%s: expected %s, read %s" % (c["name"], json.dumps(expected.get(c["name"]))[:120], json.dumps(got)[:120]))
|
|
if "refuse" in got:
|
|
given.add(got["refuse"])
|
|
if sorted(expected) != sorted(c["name"] for c in cases):
|
|
fails.append("expected/cmsd-read.json and cmsd-read/cases.json name different cases")
|
|
for n, desc in descs.items():
|
|
got = read("static" if n.startswith("static") else "dynamic", written[n])
|
|
if got != {"read": desc}:
|
|
fails.append("cmsd/%s: its field does not read back to it" % n)
|
|
codes = table_codes()
|
|
if sorted(codes) != sorted(given):
|
|
fails.append("§6.6's codes %s, the corpus gives %s" % (codes, sorted(given)))
|
|
return fails
|
|
|
|
|
|
def main(argv):
|
|
if len(argv) != 2:
|
|
print(__doc__)
|
|
return 2
|
|
d = argv[1]
|
|
load = lambda p: json.load(open(os.path.join(d, p), encoding="utf-8"))
|
|
cases, expected, written = load("cmsd-read/cases.json"), load("expected/cmsd-read.json"), load("expected/cmsd.json")
|
|
descs = {n[:-5]: load("cmsd/" + n) for n in sorted(os.listdir(os.path.join(d, "cmsd")))}
|
|
fails = check(cases, expected, written, descs)
|
|
for f in fails:
|
|
print("FAIL", f)
|
|
print("%d fields read, %d written fields read back: %d failures" % (len(cases), len(descs), len(fails)))
|
|
muts = []
|
|
|
|
def mutate(label, f):
|
|
c, e, w, ds = copy.deepcopy(cases), copy.deepcopy(expected), copy.deepcopy(written), copy.deepcopy(descs)
|
|
f(c, e, w, ds)
|
|
muts.append((label, c, e, w, ds))
|
|
|
|
mutate("a refusal stated with another code", lambda c, e, w, ds: e.__setitem__("static-version-2", {"refuse": "cmsd_type"}))
|
|
mutate("a field's duration changed", lambda c, e, w, ds: c[0].__setitem__("value", c[0]["value"].replace("d=40", "d=41")))
|
|
mutate("a read field's layer stated otherwise", lambda c, e, w, ds: e["static-as-written"]["read"].__setitem__("layer", 1))
|
|
mutate("a dynamic entry's server stated otherwise", lambda c, e, w, ds: e["dynamic-two-nodes"]["read"][0].__setitem__("server", "edge-8"))
|
|
mutate("a written field no longer its description's", lambda c, e, w, ds: w.__setitem__("static-base", w["static-base"].replace("ot=v", "ot=a")))
|
|
def drop_malformed(c, e, w, ds):
|
|
for n in [x["name"] for x in c if e[x["name"]].get("refuse") == "cmsd_malformed"]:
|
|
c[:] = [x for x in c if x["name"] != n]
|
|
e.pop(n)
|
|
mutate("every case refused with cmsd_malformed dropped", drop_malformed)
|
|
ok = True
|
|
for label, c, e, w, ds in muts:
|
|
caught = check(c, e, w, ds)
|
|
print(("PASS" if caught else "FAIL") + " mutated copy fails: " + label)
|
|
ok &= bool(caught)
|
|
return 0 if not fails and ok else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main(sys.argv))
|