import json
from pathlib import Path
import tempfile
import unittest
from deployment_kit.core import KitError, relative, write_json, sha256, lock
from deployment_kit.storage import capture, check_entry

class SafetyTests(unittest.TestCase):
    def test_archive_paths(self):
        for path in ('../secret', '/etc/passwd', 'a//b', 'a/./b', 'a\\b', 'a\nb'):
            with self.subTest(path=path), self.assertRaises(KitError): relative(path)
        self.assertEqual(relative('app/main.py'), 'app/main.py')
    def test_cas_and_exclusive(self):
        with tempfile.TemporaryDirectory() as d:
            p = Path(d) / 'state.json'
            write_json(p, {'a':1}, new=True)
            old = sha256(p)
            with self.assertRaises(KitError): write_json(p, {}, new=True)
            write_json(p, {'a':2}, expected=old)
            with self.assertRaises(KitError): write_json(p, {}, expected=old)
    def test_mount_fallback(self):
        entry = {'physical':'/backup/contextra/artifacts','logical':'/data/contextra/artifacts',
                 'container':'/data/contextra/artifacts',
                 'expected': {'target':'/backup','source':'/dev/sda1','fstype':'ext4','uuid':'hdd'}}
        def fake(_): return 0, json.dumps({'filesystems':[{'target':'/','source':'/dev/mapper/root','fstype':'ext4','uuid':'ssd','options':'rw'}]})
        with self.assertRaises(KitError) as c: check_entry(entry, runner=fake)
        self.assertEqual(c.exception.code, 'STORAGE_MOUNT_MISMATCH')
    def test_initial_missing_disk_not_approved(self):
        def fake(_): return 0, json.dumps({'filesystems':[{'target':'/','source':'/dev/root','fstype':'ext4','uuid':'root','options':'rw'}]})
        with self.assertRaises(KitError): capture('artifacts','/backup/x','/data/contextra',runner=fake)
        self.assertTrue(capture('site','/data/contextra/site','/data/contextra',runner=fake,allow_root=True)['allow_root'])
    def test_lock(self):
        with tempfile.TemporaryDirectory() as d:
            with lock(d):
                with self.assertRaises(KitError):
                    with lock(d): pass

if __name__ == '__main__': unittest.main()
