Skip to content
Bitcoin Roots

v31.1-roots.1 · Commit 11: [PATCH 11/17] fix(test): bound policy oracles and retain CI diagnostics

ci/test/roots-regressions.py

Before: ci/test/roots-regressions.py · After: ci/test/roots-regressions.py

File metadata
index cb6d11eec5a42943cc4a5c2dada2f61a50248b56..7c8fe6a0cd75ac5ae13f801300d1231e4d0de4d4 100644

Download original patch · Release notes

Diff rows 1–43 of 43. Line numbers refer to the original before/after files.

+ Added− RemovedUnmarked lines are context.

Scroll the code area horizontally to read long lines. The two line-number columns refer to before and after.

ci/test/roots-regressions.py CHANGED
@@ -89,22 +89,39 @@ def run_bounded(command, timeout, log, env=None):
89
89
  return 124
90
90
 
91
91
 
92
+ def report_failure(name, result, log):
93
+ """Keep console diagnostics bounded; the artifact retains the full output."""
94
+ print(f'Roots regression {name} failed (exit {result}); full log: {log}', file=sys.stderr)
95
+ with log.open('rb') as output:
96
+ output.seek(0, os.SEEK_END)
97
+ output.seek(max(0, output.tell() - 4096))
98
+ tail = output.read(4096).decode('utf-8', errors='replace')
99
+ for line in tail.splitlines()[-12:]:
100
+ print(line[:240], file=sys.stderr)
101
+
102
+
92
103
  def execute(plan, kind, build, artifacts, runner_args):
93
104
  artifacts.mkdir(parents=True, exist_ok=True)
94
105
  records = []
95
106
  if kind == 'functional' and plan['functional']:
96
107
  command = [sys.executable, str(build / 'test/functional/test_runner.py'), *plan['functional'], *runner_args]
97
108
  timeout = plan['budgets']['functional']
98
- result = run_bounded(command, timeout, artifacts / 'functional.log')
99
- records.append({'command': command, 'timeout': timeout, 'exit': result})
109
+ log = artifacts / 'functional.log'
110
+ result = run_bounded(command, timeout, log)
111
+ records.append({'command': command, 'timeout': timeout, 'exit': result, 'log': log.name})
112
+ if result != 0:
113
+ report_failure('functional', result, log)
100
114
  elif kind == 'fuzz':
101
115
  for target in plan['fuzz']:
102
116
  # Native libFuzzer flags bound generation by time, not input counts.
103
117
  budget = plan['budgets']['fuzz']
104
118
  command = [str(build / 'bin/fuzz'), f'-max_total_time={budget}', '-timeout=5', '-seed=1',
105
119
  '-max_len=4096', '-rss_limit_mb=2048', '-artifact_prefix=' + str(artifacts / (target + '-'))]
106
- result = run_bounded(command, budget + 10, artifacts / (target + '.log'), os.environ | {'FUZZ': target})
107
- records.append({'target': target, 'command': command, 'timeout': budget + 10, 'exit': result})
120
+ log = artifacts / (target + '.log')
121
+ result = run_bounded(command, budget + 10, log, os.environ | {'FUZZ': target})
122
+ records.append({'target': target, 'command': command, 'timeout': budget + 10, 'exit': result, 'log': log.name})
123
+ if result != 0:
124
+ report_failure(target, result, log)
108
125
  (artifacts / (kind + '-results.json')).write_text(json.dumps({'selection': plan, 'results': records}, indent=2) + '\n')
109
126
  return 1 if any(record['exit'] != 0 for record in records) else 0
110
127