"""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 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))