# SPDX-License-Identifier: CC0-1.0
import importlib.util
import json
from pathlib import Path
import tempfile
import unittest
from unittest.mock import patch

HERE = Path(__file__).resolve().parent
spec = importlib.util.spec_from_file_location("tee_lifetime", HERE / "tee-source-lifetime.py")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)


class TeeTests(unittest.TestCase):
    def test_buffered_control_keeps_both_copies(self):
        row = module.probe("buffered")
        self.assertEqual(row["first_consumer"]["uniform_byte"], "A")
        self.assertEqual(row["second_consumer"]["uniform_byte"], "A")
        self.assertTrue(row["consumer_hashes_equal"])

    def test_frozen_source_reference_observation(self):
        report = json.loads((HERE / "tee-source-lifetime.json").read_text())
        self.assertEqual(report["sourceSha256"], module.base.digest((HERE / "tee-source-lifetime.py").read_bytes()))
        self.assertEqual(report["helperSha256"], module.base.digest((HERE / "zero-copy-lifetime.py").read_bytes()))
        self.assertEqual(len(report["observations"]), 10)
        for row in report["observations"]:
            self.assertEqual(row["first_consumer"]["uniform_byte"], "A")
            self.assertEqual(row["second_consumer"]["uniform_byte"], "B" if row["mode"] == "sendfile" else "A")

    def test_tee_count_is_checked(self):
        with patch.object(module.libc, "tee", return_value=0):
            with self.assertRaisesRegex(RuntimeError, "short tee"):
                module.probe("buffered")

    def test_error_is_not_published_as_a_valid_observation(self):
        with patch.object(module.libc, "tee", return_value=-1):
            with self.assertRaises(OSError):
                module.probe("sendfile")

    def test_cleanup_and_invalid_input(self):
        with tempfile.TemporaryDirectory() as parent:
            report = module.run(1, parent)
            self.assertEqual(len(report["observations"]), 2)
            self.assertEqual(list(Path(parent).iterdir()), [])
        with self.assertRaises(ValueError):
            module.probe("other")
        with self.assertRaises(ValueError):
            module.run(0)


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