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

spec = importlib.util.spec_from_file_location("chunk_cache", Path(__file__).with_name("hdf5-chunk-cache.py"))
cache = importlib.util.module_from_spec(spec)
spec.loader.exec_module(cache)


class CacheTests(unittest.TestCase):
    def test_overlap_is_not_silently_counted(self):
        chunks = [{"offset": 100, "storedBytes": 20}]
        self.assertEqual(cache.raw_chunk_reads([{"offset": 100, "bytes": 20}], chunks), [0])
        self.assertEqual(cache.raw_chunk_reads([{"offset": 0, "bytes": 100}], chunks), [])
        self.assertEqual(cache.raw_chunk_reads([{"offset": 120, "bytes": 8}], chunks), [])
        for event in [{"offset": 99, "bytes": 22}, {"offset": 105, "bytes": 5},
                      {"offset": -1, "bytes": 4}, {"offset": 10, "bytes": -1}]:
            with self.assertRaises(ValueError):
                cache.raw_chunk_reads([event], chunks)

    def test_same_logical_selections(self):
        self.assertEqual(sorted(cache.access_trace("grouped")), sorted(cache.access_trace("round-robin")))
        self.assertEqual(len(set(cache.access_trace("grouped"))), 32)
        with self.assertRaises(ValueError):
            cache.access_trace("unknown")

    def test_invalid_repetitions(self):
        for value in [0, 21, -1, 1.5, True, "3"]:
            with self.assertRaises(ValueError):
                cache.run(value)

    def test_observed_controls_repeat(self):
        result = cache.run(2)
        expected = [32, 32, 4, 32, 32, 4]
        for repetition in (1, 2):
            rows = [row for row in result["observations"] if row["repetition"] == repetition]
            self.assertEqual([row["rawChunkReads"] for row in rows], expected)
            for row in rows:
                self.assertEqual(row["selectedBytes"], 128)
                self.assertEqual(row["chunkDecodeBytesInferred"], row["rawChunkReads"] * 4096)
                self.assertEqual(sum(len(s["rawChunkReads"]) for s in row["steps"]), row["rawChunkReads"])
        left = [{k: v for k, v in r.items() if k != "repetition"} for r in result["observations"][:6]]
        right = [{k: v for k, v in r.items() if k != "repetition"} for r in result["observations"][6:]]
        self.assertEqual(left, right)


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