aim-web2.1.0rc9

This commit is contained in:
admin_rb
2026-09-22 19:23:17 +02:00
parent d095887d2e
commit 3dfc80b782
438 changed files with 31613 additions and 1510 deletions
@@ -0,0 +1,53 @@
"""Run release tests in bounded file groups using a disposable test environment.
Set AIM_TEST_CORE_ROOT to a pristine Core source extraction, not a live controller.
Artifacts go to --out; this does not install dependencies or contact real hosts.
"""
from __future__ import annotations
import argparse
import concurrent.futures
import json
import os
from pathlib import Path
import re
import subprocess
import sys
import time
def main() -> int:
parser=argparse.ArgumentParser(description=__doc__)
parser.add_argument('--out',type=Path,required=True)
parser.add_argument('--workers',type=int,default=3,choices=range(1,5))
parser.add_argument('--timeout',type=int,default=180)
args=parser.parse_args()
if args.timeout<30:parser.error('timeout must be at least 30 seconds')
core=os.environ.get('AIM_TEST_CORE_ROOT','')
if not core or not (Path(core)/'scripts/aimctl.py').is_file():
parser.error('Set AIM_TEST_CORE_ROOT to the pristine supplied Core source extraction.')
root=Path(__file__).resolve().parents[1];args.out.mkdir(parents=True,exist_ok=True)
env={**os.environ,'PYTEST_DISABLE_PLUGIN_AUTOLOAD':'1'}
def run(path: Path) -> dict:
started=time.monotonic()
try:
p=subprocess.run([sys.executable,'-m','pytest',str(path),'-q','-p','no:cacheprovider'],
cwd=root,env=env,capture_output=True,text=True,timeout=args.timeout)
output=p.stdout+p.stderr;code=p.returncode
except subprocess.TimeoutExpired as exc:
output=(exc.stdout or b'').decode(errors='replace') if isinstance(exc.stdout,bytes) else (exc.stdout or '')
output+='\nRelease test-file timeout; not a pass.\n';code=124
(args.out/(path.stem+'.log')).write_text(output)
summary=next((line for line in reversed(output.splitlines()) if re.search(r'\d+ (passed|failed|skipped|error)',line)),'No test summary')
counts={k:int(n) for n,k in re.findall(r'(\d+) (passed|failed|skipped|errors?)',summary)}
return {'file':path.name,'returncode':code,'seconds':round(time.monotonic()-started,3),'summary':summary,'counts':counts}
with concurrent.futures.ThreadPoolExecutor(max_workers=args.workers) as pool:
results=list(pool.map(run,sorted((root/'tests').glob('test_*.py'))))
totals={k:sum(x['counts'].get(k,0) for x in results) for k in ('passed','failed','skipped','error','errors')}
value={'mode':'independent bounded test-file groups','files':results,'totals':totals,
'all_passed':all(x['returncode']==0 for x in results),'native_managed_hosts_tested':False}
(args.out/'results.json').write_text(json.dumps(value,indent=2)+'\n')
for result in results:print(result['file']+': '+result['summary'],flush=True)
print(json.dumps(totals),flush=True)
return 0 if value['all_passed'] else 1
if __name__=='__main__':raise SystemExit(main())