"""Real binary integration and path-boundary tests. No simulated detection engine."""
import os, pathlib, tempfile, subprocess, importlib.util, unittest, hashlib, uuid, json, socket, time
ROOT=pathlib.Path(__file__).resolve().parents[2]
EICAR=b'X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*'
class ScannerTests(unittest.TestCase):
 @classmethod
 def setUpClass(cls):
  cls.temp=tempfile.TemporaryDirectory();cls.base=pathlib.Path(cls.temp.name);cls.q=cls.base/'quarantine';cls.q.mkdir();db=cls.base/'db';db.mkdir()
  # A deterministic ClamAV HDB fixture verifies real libclamav matching. It is
  # isolated to tests; production must use fresh official databases.
  (db/'eicar.hdb').write_text(f'{hashlib.md5(EICAR).hexdigest()}:{len(EICAR)}:Eicar-Test-Fixture\n')
  cls.rules=cls.base/'rules.yarc';subprocess.run([os.environ.get('YARAC_BIN','yarac'),str(ROOT/'scanner/rules/multiscan.yar'),str(cls.rules)],check=True)
  os.environ.update(QUARANTINE_PATH=str(cls.q),CLAM_DATABASE=str(db),YARA_RULES=str(cls.rules),SCANNER_SOCKET=str(cls.base/'scanner.sock'))
  spec=importlib.util.spec_from_file_location('multiscan_daemon',ROOT/'scanner/daemon.py');cls.mod=importlib.util.module_from_spec(spec);spec.loader.exec_module(cls.mod)
 @classmethod
 def tearDownClass(cls):cls.temp.cleanup()
 def file(self,content):
  n=str(uuid.uuid4())+'.bin';(self.q/n).write_bytes(content);return n
 def test_01_clamav_detects_eicar(self):
  r=self.mod.execute({'engine':'clamav','file':self.file(EICAR)});self.assertEqual('malicious',r['verdict']);self.assertIn('Eicar',r['threat'])
 def test_02_clamav_benign(self):self.assertEqual('undetected',self.mod.execute({'engine':'clamav','file':self.file(b'ordinary harmless text')})['verdict'])
 def test_03_yara_detects_eicar(self):self.assertIn('EICAR_Test_File',self.mod.execute({'engine':'yara','file':self.file(EICAR)})['threat'])
 def test_04_yara_benign(self):self.assertEqual('undetected',self.mod.execute({'engine':'yara','file':self.file(b'ordinary document')})['verdict'])
 def test_05_yara_webshell_rule(self):self.assertIn('PHP_Webshell',self.mod.execute({'engine':'yara','file':self.file(b'<?php system($_GET["cmd"]);')})['threat'])
 def test_06_traversal_rejected(self):
  with self.assertRaises(ValueError):self.mod.execute({'engine':'yara','file':'../../etc/passwd'})
 def test_07_symlink_rejected(self):
  n=str(uuid.uuid4())+'.bin';(self.q/n).symlink_to('/etc/passwd')
  with self.assertRaises(OSError):self.mod.execute({'engine':'yara','file':n})
 def test_08_hardlink_rejected(self):
  source=self.q/self.file(b'hello');n=str(uuid.uuid4())+'.bin';os.link(source,self.q/n)
  with self.assertRaises(ValueError):self.mod.execute({'engine':'yara','file':n})
 def test_09_unknown_engine_rejected(self):
  with self.assertRaises(ValueError):self.mod.execute({'engine':'bash','file':self.file(b'foo')})
 def test_10_actual_unix_socket_protocol(self):
  try:
   probe=socket.socket(socket.AF_UNIX);probe.close()
  except OSError as e:self.skipTest('Unix sockets unavailable in this build environment: '+str(e))
  p=subprocess.Popen([os.environ.get('PYTHON_BIN','python3'),str(ROOT/'scanner/daemon.py')],stdout=subprocess.DEVNULL,stderr=subprocess.PIPE)
  try:
   for _ in range(50):
    if pathlib.Path(os.environ['SCANNER_SOCKET']).exists():break
    time.sleep(.05)
   with socket.socket(socket.AF_UNIX) as sock:
    sock.connect(os.environ['SCANNER_SOCKET']);sock.sendall(json.dumps({'engine':'yara','file':self.file(EICAR)}).encode()+b'\n');r=json.loads(sock.recv(65536));self.assertEqual('malicious',r['verdict'])
  finally:p.terminate();p.wait(timeout=5)
if __name__=='__main__':unittest.main(verbosity=2)
