import json, sys, re a = json.load(open(sys.argv[1])); b = json.load(open(sys.argv[2])) def key(c): return (c['Name'], c['Tag'], c['Window'], c['Path']) A = {key(c): c for c in a['Cases']}; B = {key(c): c for c in b['Cases']} print(f"A={a['Label']} sdk={a['SdkServerAssembly']} cases={len(A)} failures={len(a['Failures'])}") print(f"B={b['Label']} sdk={b['SdkServerAssembly']} cases={len(B)} failures={len(b['Failures'])}") only = set(A) ^ set(B) if only: print("cases only in one run:", sorted(only, key=str)) diffs = 0; rows = 0; events = 0; same = 0 def norm_note(n): return re.sub(r'elapsedMs=\d+', 'elapsedMs=*', n or '') for k in sorted(set(A) & set(B), key=str): x, y = A[k], B[k]; d = [] if x['Status'] != y['Status']: d.append(f"status {x['Status']} vs {y['Status']}") if norm_note(x['Note']) != norm_note(y['Note']): d.append(f"note {x['Note']} vs {y['Note']}") if (x['Attributes'] or {}) != (y['Attributes'] or {}): d.append(f"attrs {x['Attributes']} vs {y['Attributes']}") xr, yr = x['Rows'] or [], y['Rows'] or [] rows += len(xr) if len(xr) != len(yr): d.append(f"rows {len(xr)} vs {len(yr)}") else: for i, (p, q) in enumerate(zip(xr, yr)): if (p['V'], p['Status'], p['Src'], p['Srv'] is None) != (q['V'], q['Status'], q['Src'], q['Srv'] is None): d.append(f"row[{i}] {p} vs {q}"); break xe, ye = x['Events'] or [], y['Events'] or [] events += len(xe) if xe != ye: d.append(f"events {len(xe)} vs {len(ye)}") if d: diffs += 1; print("DIFF", k, "; ".join(d)[:500]) else: same += 1 print(f"compared {same+diffs} cases: identical={same} differing={diffs}; rows compared={rows}, events compared={events} (ServerTimestamp compared for presence only: it is the read time)")