Changeset 11187 in ntrip for trunk/BNC/tests
- Timestamp:
- Nov 9, 2026, 5:37:55 PM (37 hours ago)
- Location:
- trunk/BNC/tests
- Files:
-
- 6 edited
-
README.md (modified) (1 diff)
-
cases/log_structured/case.json (modified) (1 diff)
-
cases/log_structured/expected/PPPQuickStart.jsonl.gz (modified) ( previous)
-
cases/log_structured/expected/PPPQuickStart.logfmt.gz (modified) ( previous)
-
cases/log_structured/expected/logcheck.txt.gz (modified) ( previous)
-
tools/logcheck.py (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/BNC/tests/README.md
r11179 r11187 33 33 | `tools/net_check.py` | UDP/RTP sender filter and upload status checks on loopback (not part of `run_tests.py`) | 34 34 | `tools/cred_check.py` | credentials files (`~/.netrc`, BNC format) for download and upload (not part of `run_tests.py`) | 35 | `tools/logcheck.py` | structured logfile: JSON/logfmt syntax, both formats equal, `time` = `gpst`- leap seconds, `msg` = classic logfile |35 | `tools/logcheck.py` | structured logfile: JSON/logfmt syntax, both formats equal, `time` = classic GPS time stamp - leap seconds, optional `epoch`, `msg` = classic logfile | 36 36 | `work/` | scratch output, not versioned | 37 37 -
trunk/BNC/tests/cases/log_structured/case.json
r11185 r11187 24 24 "-key", "logFormatStructured", "logfmt"]}, 25 25 {"dir": "chk", "tool": ["logcheck.py", "Output/PPPQuickStart.log_251117", 26 "Output/PPPQuickStart.jsonl _251117",27 "lf/Output/PPPQuickStart.logfmt _251117"]}],26 "Output/PPPQuickStart.jsonl", 27 "lf/Output/PPPQuickStart.logfmt"]}], 28 28 "outputs": [ 29 {"glob": "Output/PPPQuickStart.jsonl _251117", "name": "PPPQuickStart.jsonl"},30 {"glob": "lf/Output/PPPQuickStart.logfmt _251117", "name": "PPPQuickStart.logfmt"},29 {"glob": "Output/PPPQuickStart.jsonl", "name": "PPPQuickStart.jsonl"}, 30 {"glob": "lf/Output/PPPQuickStart.logfmt", "name": "PPPQuickStart.logfmt"}, 31 31 {"glob": "chk/stdout.txt", "name": "logcheck.txt"} 32 32 ] -
trunk/BNC/tests/tools/logcheck.py
r11179 r11187 6 6 Checks that every line of the JSON file is a JSON object and every line of the 7 7 logfmt file a sequence of key=value pairs, that both carry the same records, 8 that the records have the mandatory keys in the documented order, that 'time' 9 (UTC) is 'gpst' minus the GPS-UTC leap seconds and that the 'msg' of the 10 records equals the text of the classic logfile line by line (classic lines 11 without their "yy-mm-dd hh:mm:ss " prefix; the start line is skipped, it goes 12 to the file of the current date). Prints a summary of the records per level, 8 that the records have the mandatory keys in the documented order (optional 9 'epoch' after 'time', GPS Time without 'Z'), that the 'msg' of the records 10 (for RTCM scan message types: 'mp', 'message_type', 'size') equals the text of 11 the classic logfile line by line (classic lines without 12 their "yy-mm-dd hh:mm:ss " prefix; the start line is skipped, it goes to the 13 file of the current date) and that 'time' (UTC) is the GPS Time stamp of the 14 classic line minus the GPS-UTC leap seconds. Prints a summary of the records per level, 13 15 component and event; exit code 1 on any error. 14 16 """ … … 20 22 import sys 21 23 22 HEAD = ["time", " gpst", "level", "component", "event"]24 HEAD = ["time", "level", "component", "event"] 23 25 LEVELS = {"info", "warning", "error"} 24 26 LEAP_GPS_UTC = 18 # valid since 2017-01-01 … … 68 70 69 71 72 def classic_text(r): 73 """Text of the classic logfile line of a record: 'msg', except for the 74 message types of the RTCM scan, which carry the short text 'Received message' 75 and the details in their fields.""" 76 if r.get("event") == "stream_content" and "message_type" in r: 77 if r["msg"] != "Received message": 78 return "unexpected msg %r" % r["msg"] 79 size = " (size %d)" % r["size"] if "size" in r else " " 80 return "%s: Received message type %d%s" % (r["mp"], r["message_type"], size) 81 return r.get("msg") 82 83 70 84 def main(): 71 85 errors = [] 72 classic =[]86 classic, stamps = [], [] 73 87 for line in open(sys.argv[1], encoding="latin-1", newline="").read().split("\r\n"): 74 88 if not line or "========== Start BNC" in line: 75 89 continue 76 classic.append(line[18:] if re.match(r"\d\d-\d\d-\d\d \d\d:\d\d:\d\d ", line) else line) 90 if re.match(r"\d\d-\d\d-\d\d \d\d:\d\d:\d\d ", line): 91 classic.append(line[18:]) 92 stamps.append(datetime.datetime.strptime(line[:17], "%y-%m-%d %H:%M:%S")) 93 else: 94 classic.append(line) 95 stamps.append(None) 77 96 78 97 recs = [] … … 92 111 errors.append("json %d records, logfmt %d" % (len(recs), len(lf))) 93 112 for k, (a, b) in enumerate(zip(recs, lf), 1): 94 if list(a.keys()) != list(b.keys()) or any(a[x] != b[x] for x in a): 113 # the start line carries the wall clock time of each run 114 start = "========== Start BNC" in a.get("msg", "") 115 if list(a.keys()) != list(b.keys()) or any(a[x] != b[x] for x in a 116 if not (start and x == "time")): 95 117 errors.append("record %d differs between json and logfmt" % k) 96 118 … … 98 120 for k, r in enumerate(recs, 1): 99 121 keys = list(r.keys()) 100 if keys[:5] != HEAD or keys[-2:] != ["msg", "v"]: 122 if keys[1:2] == ["epoch"]: 123 try: 124 datetime.datetime.strptime(r["epoch"], "%Y-%m-%dT%H:%M:%S.%f") 125 except ValueError: 126 errors.append("record %d: epoch %s" % (k, r["epoch"])) 127 keys = keys[:1] + keys[2:] 128 if keys[:4] != HEAD or keys[-2:] != ["msg", "v"]: 101 129 errors.append("record %d: keys %s" % (k, keys)) 102 130 continue 103 131 if r["level"] not in LEVELS: 104 132 errors.append("record %d: level %s" % (k, r["level"])) 105 utc = datetime.datetime.strptime(r["time"], "%Y-%m-%dT%H:%M:%S.%fZ")106 gps = datetime.datetime.strptime(r["gpst"], "%Y-%m-%dT%H:%M:%S.%f")107 if (gps - utc).total_seconds() != LEAP_GPS_UTC:108 errors.append("record %d: time %s gpst %s" % (k, r["time"], r["gpst"]))109 133 count[(r["level"], r["component"], r["event"])] += 1 110 134 111 msgs = [r.get("msg") for r in recs if "========== Start BNC" not in r.get("msg", "")] 135 body = [r for r in recs if "========== Start BNC" not in r.get("msg", "")] 136 msgs = [classic_text(r) for r in body] 137 for k, (r, st) in enumerate(zip(body, stamps), 1): 138 utc = datetime.datetime.strptime(r["time"], "%Y-%m-%dT%H:%M:%S.%fZ") 139 if st is not None and (st - utc.replace(microsecond=0)).total_seconds() != LEAP_GPS_UTC: 140 errors.append("record %d: time %s, classic %s" % (k, r["time"], st)) 112 141 if msgs != classic: 113 142 for k, (a, b) in enumerate(zip(msgs, classic), 1):
Note:
See TracChangeset
for help on using the changeset viewer.
