From ccfd73d6a30e841f40f94bd199fe3ae72fbbad6c Mon Sep 17 00:00:00 2001 From: eunhhu Date: Wed, 30 Sep 2026 15:25:02 +0100 Subject: Pin a bool's meaning on every path (015) server_meaning gives each of its 67 values a bool field, true or false: in as JSON, a query, a message's rows; over the link to B (taking it by name among reordered fields) and over HTTP to C; out through A's view and query, B's and C's views, a restart, a restart after a checkpoint and B with its module replaced. A bool must come out as true or false, never 1 or 0. Refused on every way in, with the reason checked: 1, 0, "true", null or an array as json_type, True as json (no JSON at all), a query's 1, 0, True, TRUE, "true " or nothing as query, a row's 1 as json_type: 52 refusals, 39 before. 015 says what a bool is at each boundary. This check found the stored outbox refusing bool fields (a node could not start again with a bool send waiting), fixed in the commit before. --- tests/check.py | 96 ++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 64 insertions(+), 32 deletions(-) (limited to 'tests/check.py') diff --git a/tests/check.py b/tests/check.py index 0c52cf4..117beff 100644 --- a/tests/check.py +++ b/tests/check.py @@ -3305,6 +3305,7 @@ MEANING_KEPT = """record Kept { t: text x = 0 label: text + ok = false } state kept: list of Kept by id """ @@ -3315,6 +3316,7 @@ MEANING_ROWS = """view rows = each k in kept { t = k.t x = k.x label = k.label + ok = k.ok } """ # A: what comes in (a JSON body, its rows, or a query and a plain body) is kept, and sent on; a put is answered @@ -3324,12 +3326,14 @@ MEANING_ORIGIN = MEANING_KEPT + """record Part { n = 0 u = 0 t: text + ok = false } input put = message { id: u32 n: number u: u32 t: text + ok: bool at: { x: number label: text @@ -3340,6 +3344,7 @@ input put_plain = message { n: number u: u32 t: text + ok: bool } input put_rows = message { parts: list of Part @@ -3350,19 +3355,19 @@ input touch = message { } output passed = message like put on put { - kept.add(Kept { id: put.id, n: put.n, u: put.u, t: put.t, x: put.at.x, label: put.at.label }) + kept.add(Kept { id: put.id, n: put.n, u: put.u, t: put.t, x: put.at.x, label: put.at.label, ok: put.ok }) send passed { ..put } reply put.t } on put_rows { for p in put_rows.parts { - kept.add(Kept { id: p.id, n: p.n, u: p.u, t: p.t, x: 0, label: "rows" }) - send passed { id: p.id, n: p.n, u: p.u, t: p.t, at: { x: 0, label: "rows" } } + kept.add(Kept { id: p.id, n: p.n, u: p.u, t: p.t, x: 0, label: "rows", ok: p.ok }) + send passed { id: p.id, n: p.n, u: p.u, t: p.t, ok: p.ok, at: { x: 0, label: "rows" } } } } on put_plain { - kept.add(Kept { id: put_plain.id, n: put_plain.n, u: put_plain.u, t: put_plain.t, x: 0, label: "" }) - send passed { id: put_plain.id, n: put_plain.n, u: put_plain.u, t: put_plain.t, at: { x: 0, label: "" } } + kept.add(Kept { id: put_plain.id, n: put_plain.n, u: put_plain.u, t: put_plain.t, x: 0, label: "", ok: put_plain.ok }) + send passed { id: put_plain.id, n: put_plain.n, u: put_plain.u, t: put_plain.t, ok: put_plain.ok, at: { x: 0, label: "" } } } on touch { kept[touch.id].t = touch.t @@ -3370,6 +3375,7 @@ on touch { """ + MEANING_ROWS # B: A's sends over the link, taken by name (fields in another order, u a number), kept and sent on over HTTP. MEANING_MIRROR = MEANING_KEPT + """input passed = message { + ok: bool at: { label: text x: number @@ -3381,7 +3387,8 @@ MEANING_MIRROR = MEANING_KEPT + """input passed = message { } output onward = message like passed on passed { - kept.add(Kept { id: passed.id, n: passed.n, u: passed.u, t: passed.t, x: passed.at.x, label: passed.at.label }) + kept.add(Kept { id: passed.id, n: passed.n, u: passed.u, t: passed.t, x: passed.at.x, label: passed.at.label, + ok: passed.ok }) send onward { ..passed } } """ + MEANING_ROWS @@ -3395,9 +3402,11 @@ MEANING_END = MEANING_KEPT + """input onward = message { x: number label: text } + ok: bool } on onward { - kept.add(Kept { id: onward.id, n: onward.n, u: onward.u, t: onward.t, x: onward.at.x, label: onward.at.label }) + kept.add(Kept { id: onward.id, n: onward.n, u: onward.u, t: onward.t, x: onward.at.x, label: onward.at.label, + ok: onward.ok }) } """ + MEANING_ROWS # The value set: every number a JSON reader must round correctly, u32s to its ends, texts JSON escapes and UTF-8. @@ -3419,8 +3428,9 @@ def server_meaning(aup, pure, work): out the same at every exit: A's view, a query on A, B's and C's views, A after a restart and after a checkpoint, B after its module was replaced. A number keeps its bits (zero has no sign: -0 shows as 0 and counts as 0), - a text its bytes. What must be refused is refused on every way in, and - leaves nothing behind (no row, no send).""" + a text its bytes, a bool is true or false (never 1 or 0). What must be + refused is refused on every way in, and leaves nothing behind (no row, no + send).""" import socket import struct import time @@ -3428,8 +3438,8 @@ def server_meaning(aup, pure, work): from urllib.parse import quote modules = {} for name, text in (('origin', MEANING_ORIGIN), ('mirror', MEANING_MIRROR), ('end', MEANING_END), - ('mirror-2', MEANING_MIRROR.replace(' id = 0\n n = 0\n u = 0\n t: text\n x = 0\n label: text\n', - ' label: text\n x = 0\n t: text\n u = 0\n n = 0\n id = 0\n'))): + ('mirror-2', MEANING_MIRROR.replace(' id = 0\n n = 0\n u = 0\n t: text\n x = 0\n label: text\n ok = false\n', + ' ok = false\n label: text\n x = 0\n t: text\n u = 0\n n = 0\n id = 0\n'))): source = work / f'meaning-{name}.aup' source.write_text(text) compile_module(aup, source, source.with_suffix('.pmod')) @@ -3467,6 +3477,16 @@ def server_meaning(aup, pure, work): finally: connection.close() + def refused_as(port, path, body, kind): # the status and X-Pure-Error of a request that must fail + connection = HTTPConnection('127.0.0.1', port, timeout=30) + try: + connection.request('POST', path, body, {'Content-Length': str(len(body)), 'Content-Type': kind}) + response = connection.getresponse() + response.read() + return response.status, response.getheader('X-Pure-Error') + finally: + connection.close() + def rows(name, path='/views/rows'): status, _, _, body = http(hosts[name].port, 'GET', path) assert status == 200, (name, path, status, body[:200]) @@ -3476,9 +3496,10 @@ def server_meaning(aup, pure, work): return float(shown) == want == 0 or struct.pack('