#!/usr/bin/env python3
"""Pure approval/namespace/bind/counterexample gate; never connects to a database."""
import hashlib
import json
from pathlib import Path

r = Path(__file__).parent
raw = (r / 'probe2a-hex-char-proposal.json').read_bytes()
sha = hashlib.sha256(raw).hexdigest()
assert sha == 'c23f516cd9764e1eb6dec57f8ca5cb579c74f6c25008b25e6d242dfe1e14f78d'
p = json.loads(raw)
assert p['marker'] == 'CDXSS2A'
assert p['budget'] == {'max_rows_each': 6, 'DML_attempts_each': 33, 'DDL_B': 2, 'DDL_C': 6, 'SELECT_max_each': 160, 'HTTP': 0, 'business_writes': 0}
for lane, spec in p['lanes'].items():
    assert spec['table'] == ('cdx_ss7_2a261011' if lane == 'B' else 'ZHCT_APP.CDX_SS7_2A261011')
    assert len(spec['steps']) == 33 and len({s['label'] for s in spec['steps']}) == 33
    assert sum(s['expect_reject'] for s in spec['steps']) == 6
    for s in spec['steps']:
        assert s['SQL'].startswith(('INSERT INTO ' + spec['table'] + ' ', 'UPDATE ' + spec['table'] + ' '))
        assert s['SQL'].count('?') == len(s['binds']) == len(s['PDO_types'])
        assert s['PDO_types'] == [0 if v is None else 1 if type(v) is int else 2 for v in s['binds']]
        assert all(type(v) in (str, int, type(None)) for v in s['binds'])
        pk = s['binds'][0] if s['SQL'].startswith('INSERT') else s['binds'][-1]
        assert type(pk) is int and 1 <= pk <= 6
    assert len(spec['predicate_queries']) == (32 if lane == 'B' else 48)
    for q in spec['predicate_queries']:
        assert q['SQL'].startswith('SELECT ID FROM ' + spec['table']) and q['PDO_types'] == [2]
    assert len(spec['steps'][8]['binds'][2]) == 128
    assert len(spec['steps'][8]['binds'][2].encode()) == 512
    assert len(spec['steps'][16]['binds'][0]) == 36 and len(spec['steps'][16]['binds'][0].encode()) == 144
key = lambda v: None if v is None else (v.rstrip(' ').encode().hex().upper() or '#')
assert key(None) is None and key('') == key(' ') == '#'
assert key('A') != key('a') and key('A') == key('A ')
assert key('A\t') == key('A\t ') != key('A')
assert key('A\0') == key('A\0 ') != key('A')
assert key('A\0') != key('a\0')
assert len(key('😀' * 128)) == 1024
assert key('😀' * 128) != key('😀' * 127 + '😁')
assert key('é') != key('e\u0301')
c = p['lanes']['C']
assert "CASE WHEN DINGTALK_USERID IS NULL THEN NULL" in c['canonical_key_expression']
assert "NVL(RAWTOHEX(CHARTOBIN(RTRIM(DINGTALK_USERID,' '))),'#')" in c['canonical_key_expression']
assert 'VARCHAR(1024)' in c['canonical_key_expression']
assert c['create_trigger'].count(':= RTRIM(') == 2
assert 'UPDATE_TIME' not in c['create_trigger']
assert 'OR REPLACE' not in c['create_trigger']
runner = (r / 'probe2a-run.php').read_text()
assert "rtrim($v,' ')" in runner and "$reads<=160" in runner and "$dml<=33" in runner
assert "in_array($sql,$allowedDDL,true)" in runner and "$spec['PDO_types']" not in runner
assert "objects_remaining'=>0" in runner
print(json.dumps({'approval_plan_SHA': sha, 'pure_gate': True, 'steps_each': 33, 'reject_hypotheses_each': 6, 'counterexample_invariants': 11, 'planned_readonly_B_C': [86, 122], 'no_DB_connection_by_this_check': True}))
