#!/usr/bin/env python3 """ Simple MBAP test harness. - Loads `data/raw/code/mbap.json` - For each entry with `code` and `test_list`, runs a heuristic mock AVAP executor - Compares returned `result` against each test's expected value and prints a summary Note: This is a heuristic mock executor — it supports many common AVAP idioms but is not a full AVAP interpreter. It aims to be useful for quick verification. """ import json import re import sys import hashlib import random import string from pathlib import Path MBAP_PATH = Path(__file__).resolve().parents[1] / "data" / "raw" / "code" / "mbap.json" def load_mbap(path: Path): with open(path, "r", encoding="utf-8") as f: return json.load(f) def transform_avap_to_python(code: str) -> str: lines = code.splitlines() out_lines = [] for raw in lines: line = raw.strip() if not line: continue # remove addParam(...) calls if re.match(r'addParam\(', line): continue # getListLen(var, lenvar) -> lenvar = len(var) m = re.match(r'getListLen\(([^,]+),\s*([A-Za-z_][A-Za-z0-9_]*)\)', line) if m: out_lines.append(f"{m.group(2).strip()} = len({m.group(1).strip()})") continue # itemFromList(list, idx, var) -> var = list[idx] m = re.match(r'itemFromList\(([^,]+),\s*([^,]+),\s*([A-Za-z_][A-Za-z0-9_]*)\)', line) if m: out_lines.append(f"{m.group(3).strip()} = {m.group(1).strip()}[{m.group(2).strip()}]") continue # AddVariableToJSON(idx, value, result) -> result.append(value) m = re.match(r'AddVariableToJSON\(([^,]+),\s*([^,]+),\s*([A-Za-z_][A-Za-z0-9_]*)\)', line) if m: out_lines.append(f"{m.group(3).strip()}.append({m.group(2).strip()})") continue # startLoop(i, s, e) -> for i in range(s, e+1): m = re.match(r'startLoop\(([^,]+),\s*([^,]+),\s*([^,]+)\)', line) if m: out_lines.append(f"for {m.group(1).strip()} in range({m.group(2).strip()}, {m.group(3).strip()}+1):") continue # simple else/end tokens if line.startswith('else()'): out_lines.append('else:') continue if line.startswith('endLoop') or line == 'end()': continue # if(a, b, "op") m = re.match(r'if\(([^,]*),\s*([^,]*),\s*"([^"]+)"\)', line) if m: a = m.group(1).strip() b = m.group(2).strip() op = m.group(3).strip() if op in ('==', '!=', '>', '<', '>=', '<='): out_lines.append(f"if {a} {op} {b}:") else: # treat as raw expression out_lines.append(f"if {op}:") continue # addResult(x) -> output = x m = re.match(r'addResult\(([^)]+)\)', line) if m: out_lines.append(f"output = {m.group(1).strip()}") continue # encodeSHA256(src, dst) m = re.match(r'encodeSHA256\(([^,]+),\s*([A-Za-z_][A-Za-z0-9_]*)\)', line) if m: out_lines.append("import hashlib") out_lines.append(f"{m.group(2)} = hashlib.sha256(str({m.group(1)}).encode()).hexdigest()") continue # encodeMD5 m = re.match(r'encodeMD5\(([^,]+),\s*([A-Za-z_][A-Za-z0-9_]*)\)', line) if m: out_lines.append("import hashlib") out_lines.append(f"{m.group(2)} = hashlib.md5(str({m.group(1)}).encode()).hexdigest()") continue # randomString(len, token) m = re.match(r'randomString\(([^,]+),\s*([A-Za-z_][A-Za-z0-9_]*)\)', line) if m: out_lines.append(f"{m.group(2)} = ''.join(__random.choice(__letters) for _ in range(int({m.group(1)})))") continue # getRegex(text, pattern, matches) -> use python re.findall m = re.match(r'getRegex\(([^,]+),\s*"([^"]+)",\s*([A-Za-z_][A-Za-z0-9_]*)\)', line) if m: out_lines.append(f"{m.group(3)} = re.findall(r'{m.group(2)}', str({m.group(1)}))") continue # RequestGet/Post -> mock if line.startswith('RequestGet(') or line.startswith('RequestPost('): out_lines.append("response = {'_mock': 'response'}") out_lines.append("output = response") continue # function foo(...) { -> def foo(...): m = re.match(r'function\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(([^)]*)\)\s*\{', line) if m: args = m.group(2).strip() out_lines.append(f"def {m.group(1)}({args}):") continue # return(...) -> return ... m = re.match(r'return\(([^)]+)\)', line) if m: out_lines.append(f"return {m.group(1).strip()}") continue # simple replacements to make many lines valid python-ish line = line.replace('&&', 'and').replace('||', 'or') # remove trailing semicolons if any if line.endswith(';'): line = line[:-1] out_lines.append(line) # Ensure we always expose 'output' variable at the end if not set py = '\n'.join(out_lines) guard = "\nif 'output' not in locals():\n output = locals().get('result', None)\n" return py + guard def mock_execute(code: str, inputs: dict): """Heuristic mock executor: - Creates a restricted locals dict with provided `inputs` - Transforms AVAP-ish code into Python-ish code - Executes it and returns {'result': output} or {'error': msg} """ # prepare locals globs = {"__builtins__": {}} locals_: dict = {} # expose helpers locals_['re'] = re locals_['hashlib'] = hashlib locals_['__random'] = random locals_['__letters'] = string.ascii_letters + string.digits # copy input params into locals if isinstance(inputs, dict): for k, v in inputs.items(): locals_[k] = v # transform py = transform_avap_to_python(code) try: exec(py, globs, locals_) output = locals_.get('output', None) return {'result': output} except Exception as e: return {'error': str(e), 'transformed': py} def canonical_expected(test_item): """Try to extract expected value from a test item. Accepts several common shapes: {'input':..., 'expected':...}, {'in':..., 'out':...}, or simple dicts. """ if isinstance(test_item, dict): if 'expected' in test_item: return test_item['expected'] if 'output' in test_item: return test_item['output'] if 'result' in test_item: return test_item['result'] # some datasets embed expected as the last item if 'expected_result' in test_item: return test_item['expected_result'] return None def canonical_input(test_item): if isinstance(test_item, dict): if 'input' in test_item: return test_item['input'] if 'in' in test_item: return test_item['in'] # if dict and contains params keys other than expected, assume it's the input itself # heuristics: if contains keys other than 'expected'/'output' treat as params keys = set(test_item.keys()) if not keys.intersection({'expected','output','result','description'}): return test_item return {} def run_all(path: Path): data = load_mbap(path) total = 0 passed = 0 for entry in data: task_id = entry.get('task_id') code = entry.get('code') tests = entry.get('test_list') or [] if not code: continue print(f"Task {task_id}: processing {len(tests)} tests") for ti, test_item in enumerate(tests): total += 1 inp = canonical_input(test_item) expected = canonical_expected(test_item) res = mock_execute(code, inp) if 'error' in res: print(f" test #{ti+1}: ERROR -> {res['error']}") # optionally show transformed code for debugging # print(res.get('transformed')) continue got = res.get('result') ok = (expected is None) or (got == expected) if ok: passed += 1 status = 'PASS' else: status = 'FAIL' print(f" test #{ti+1}: {status} | expected={expected!r} got={got!r}") print(f"\nSummary: passed {passed}/{total} tests") if __name__ == '__main__': p = MBAP_PATH if not p.exists(): print(f"mbap.json not found at {p}") sys.exit(1) run_all(p)