import unittest,json,subprocess,ast
from pathlib import Path
from mysql_encoding import PROBE_SQL,validate_encoding,SENTINEL,HEX
ROOT=Path(__file__).parent
class Encoding(unittest.TestCase):
 def query(self,charset):
  cmd=['docker','exec','foodsafe2-mysql8-stage-20261023','mysql','--defaults-extra-file=/run/secrets/client.cnf','--default-character-set='+charset,'--database=foodsafe2','--batch','--raw','--skip-column-names','-e',PROBE_SQL]
  return subprocess.run(cmd,capture_output=True,check=True)
 def test_live_utf8_roundtrip(self):
  rows=self.query('utf8mb4').stdout.decode('utf8','strict').splitlines();self.assertEqual(len(rows),1);r=validate_encoding(json.loads(rows[0]));self.assertEqual(r['text'].encode().hex().upper(),HEX);self.assertEqual(r['server_text'],SENTINEL)
 def test_live_latin1_fails_closed(self):
  p=self.query('latin1');r=json.loads(p.stdout.decode('utf8','replace'));self.assertRaises(RuntimeError,validate_encoding,r)
 def test_damaged_roundtrip_rejected(self):
  good={'__encoding_probe':1,'client':'utf8mb4','connection':'utf8mb4','results':'utf8mb4','text':SENTINEL,'server_text':SENTINEL,'hex':HEX}
  for key in ['text','server_text','hex']:
   self.assertRaises(RuntimeError,validate_encoding,{**good,key:'?????'})
  self.assertRaises(RuntimeError,validate_encoding,None)
 def test_every_script_explicit_flag_and_same_session_guard(self):
  for name in ['mysql-baseline.py','mysql-upgraded-baseline.py','export_original.py','export_upgraded.py','verify_original_preserved.py']:
   source=(ROOT/name).read_text();tree=ast.parse(source);lists=[n for n in ast.walk(tree) if isinstance(n,ast.List) and any(isinstance(c,ast.Constant) and c.value=='mysql' for c in n.elts)]
   self.assertEqual(len(lists),1)
   self.assertTrue(any(isinstance(c,ast.Constant) and c.value=='--default-character-set=utf8mb4' for c in lists[0].elts))
   self.assertIn('PROBE_SQL',source)
   self.assertIn('validate_encoding(rows[0])' if name.startswith('mysql-') else 'encoding=consume_probe(p)',source)
if __name__=='__main__':unittest.main()
