"""Run knowledge tests with isolated app data and external networking disabled.""" import contextlib import importlib import io import json import os from pathlib import Path import socket import sys import tempfile import threading import time import unittest from unittest import mock root = Path(sys.argv[1]).resolve() output = Path(sys.argv[2]).resolve() modules = sys.argv[3:] or ['test_knowledge','test_knowledge_search','test_knowledge_review','test_knowledge_tasks','test_knowledge_model_output','test_model_gateway'] sys.path.insert(0, str(root)) sys.path.insert(1, str(Path(__file__).parent)) os.environ['QT_QPA_PLATFORM'] = 'offscreen' os.environ['KNOWLEDGE_QDRANT_URL'] = '' os.environ['KNOWLEDGE_EMBEDDING_URL'] = '' os.environ['KNOWLEDGE_EMBEDDING_MODEL'] = '' import runtime_paths original_connect, original_pair = socket.socket.connect, socket.socketpair internal = threading.local() def connect(sock, address): if getattr(internal, 'wakeup', False): return original_connect(sock, address) raise AssertionError('External network blocked in audit') def socketpair(*args, **kwargs): internal.wakeup = True try: return original_pair(*args, **kwargs) finally: internal.wakeup = False with tempfile.TemporaryDirectory(prefix='recognition-knowledge-') as directory, contextlib.ExitStack() as stack: stack.enter_context(mock.patch.object(runtime_paths,'application_data_dir',return_value=Path(directory))) stack.enter_context(mock.patch.object(socket.socket,'connect',connect)) stack.enter_context(mock.patch.object(socket,'socketpair',socketpair)) stack.enter_context(mock.patch.object(socket.socket,'connect_ex',side_effect=AssertionError('External network blocked in audit'))) stream = io.StringIO() with contextlib.redirect_stdout(stream), contextlib.redirect_stderr(stream): suite = unittest.defaultTestLoader.loadTestsFromNames(modules) start = time.monotonic() result = unittest.TextTestRunner(stream=stream, verbosity=2).run(suite) output.parent.mkdir(parents=True,exist_ok=True) output.with_suffix('.log').write_text(stream.getvalue(),encoding='utf-8') data = {'root':str(root),'modules':modules,'tests':result.testsRun,'failures':len(result.failures), 'errors':len(result.errors),'skipped':len(result.skipped),'elapsed_seconds':round(time.monotonic()-start,2)} output.with_suffix('.json').write_text(json.dumps(data,ensure_ascii=False,indent=2),encoding='utf-8') print(json.dumps(data,ensure_ascii=False)) if not result.wasSuccessful(): for test, error in result.failures+result.errors: print(str(test), error) sys.exit(0 if result.wasSuccessful() else 1)