"""Traffic counters: a numbered counter keeps what it counted across a reload, the value belonging to the process rather than to the configuration read.""" import re import time def run(t): origin = t.free_port() proxy = t.free_port() adm = t.free_port() server = t.start("counters", f""" log auth iponly allow * http data * /data httpsrv -p{origin} flush auth iponly allow * countin 3/counted D 100 * * * proxy -p{proxy} admin -p{adm} """, ports=[origin, proxy, adm]) def counted(): """The counter's value in MB, as the counters page shows it.""" page = t.http(f"http://127.0.0.1:{adm}/C").text m = re.search(r"counted.*?([0-9]+\.[0-9])", page, re.S) return float(m.group(1)) if m else None def wait_counted(least, timeout=5.0): deadline = time.time() + timeout value = counted() while (value is None or value < least) and time.time() < deadline: time.sleep(0.1) value = counted() return value reply = t.http(f"http://127.0.0.1:{origin}/data?size=300000", proxy=f"127.0.0.1:{proxy}") t.eq(300000, reply.length, "a body passes through the counted proxy") before = wait_counted(0.2) t.ok("the counter counts it") if before is not None and before >= 0.2 else \ t.fail("the counter counts it", ">= 0.2", before) # reload, and wait for the services of the new configuration to run out = server.output() accepting = out.count("Accepting connections") t.http(f"http://127.0.0.1:{adm}/R") deadline = time.time() + 10 while time.time() < deadline and server.output().count("Accepting connections") < accepting + 3: time.sleep(0.05) after = wait_counted(0.2) t.eq(before, after, "a reload keeps what the numbered counter counted")