pocketpy/scripts/run_tests.py
diiviikk5 6f2366dc2d fix: replace os.system() with subprocess.run() for security and robustness
- Replace os.system() calls with subprocess.run() using list args to avoid shell injection (CWE-78, Bandit B605/B607)

- Replace assert-based error handling with proper exceptions (ValueError, RuntimeError, FileNotFoundError) that survive python -O (Bandit B101)

- Use sys.executable instead of hardcoded 'python' to ensure correct interpreter (Bandit B607)

Files changed: cmake_build.py, scripts/run_tests.py, compileall.py, amalgamate.py
2026-02-08 01:44:02 +05:30

96 lines
2.7 KiB
Python

import os
import sys
import time
import subprocess
pkpy_exe = 'main.exe' if sys.platform == 'win32' else './main'
def test_file(filepath, cpython=False):
if cpython:
result = subprocess.run([sys.executable, filepath])
return result.returncode == 0
result = subprocess.run([pkpy_exe, filepath])
if result.returncode != 0:
print('Return code:', result.returncode)
return result.returncode == 0
def test_dir(path):
print("Testing directory:", path)
for filename in sorted(os.listdir(path)):
if not filename.endswith('.py') and not filename.endswith('.pyc'):
continue
filepath = os.path.join(path, filename)
print("> " + filepath, flush=True)
if path == 'benchmarks/':
_0 = time.time()
if not test_file(filepath, cpython=True):
print('cpython run failed')
continue
_1 = time.time()
if not test_file(filepath): exit(1)
_2 = time.time()
print(f' cpython: {_1 - _0:.6f}s (100%)')
print(f' pocketpy: {_2 - _1:.6f}s ({(_2 - _1) / (_1 - _0) * 100:.2f}%)')
else:
if not test_file(filepath):
print('-' * 50)
print("TEST FAILED!")
exit(1)
# print("TEST FAILED! Press any key to continue...")
# input()
print('CPython:', str(sys.version).replace('\n', ''))
print('System:', '64-bit' if sys.maxsize > 2**32 else '32-bit')
def test_repl():
print("[REPL Test Enabled]")
if sys.platform in ['linux', 'darwin']:
cmd = './main'
else:
cmd = None
if cmd is not None:
res = subprocess.run([cmd], encoding='utf-8', input=r'''
def add(a, b):
return a + b
class A:
def __init__(self, x):
self.x = x
def get(self):
return self.x
print('ans_1:', add(1, 2))
print('ans_2:', A('abc').get())
exit()
''', capture_output=True, check=True)
res.check_returncode()
# assert 'ans_1: 3' in res.stdout, res.stdout
if 'ans_1: 3' not in res.stdout:
print(res.stdout)
exit(1)
# assert 'ans_2: abc' in res.stdout, res.stdout
if 'ans_2: abc' not in res.stdout:
print(res.stdout)
exit(1)
subprocess.run([sys.executable, 'compileall.py', pkpy_exe, 'tests', 'tmp/tests'], check=True)
if len(sys.argv) == 2:
if 'benchmark' not in sys.argv[1]:
raise ValueError(f"Expected 'benchmark' in argument, got: {sys.argv[1]!r}")
test_dir('benchmarks/')
else:
test_dir('tests/')
test_repl()
if os.path.exists('tmp/tests'):
print('-' * 50)
time.sleep(3)
test_dir('tmp/tests/')
print("ALL TESTS PASSED")