Bound adapter assemblies and extraction caches
This commit is contained in:
parent
9cd7c4e424
commit
f00aa65a73
4 changed files with 232 additions and 8 deletions
102
tests/test_incremental_cache.py
Normal file
102
tests/test_incremental_cache.py
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import os
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from docforge.errors import DocForgeError
|
||||
from docforge.incremental import (
|
||||
CachedSource,
|
||||
ExtractionCache,
|
||||
load_extraction_cache,
|
||||
write_extraction_cache,
|
||||
)
|
||||
|
||||
|
||||
class ExtractionCacheBoundsTests(unittest.TestCase):
|
||||
@staticmethod
|
||||
def cache(*, payload: str = "ok", count: int = 1) -> ExtractionCache:
|
||||
sources = tuple(
|
||||
CachedSource(
|
||||
source_id=f"source-{index}",
|
||||
source_path=f"src/{index}.txt",
|
||||
fingerprint=hashlib.sha256(str(index).encode()).hexdigest(),
|
||||
extractor_version="fixture@1",
|
||||
dependencies=(),
|
||||
payload={"content": payload},
|
||||
)
|
||||
for index in range(count)
|
||||
)
|
||||
return ExtractionCache("fixture", "fixture-adapter", "1", sources)
|
||||
|
||||
def test_bounded_round_trip_and_oversized_read_is_a_cache_miss(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
path = Path(directory) / "extractions.json"
|
||||
write_extraction_cache(path, self.cache(), max_bytes=1_000, max_sources=2)
|
||||
loaded = load_extraction_cache(
|
||||
path,
|
||||
project_id="fixture",
|
||||
adapter_id="fixture-adapter",
|
||||
adapter_version="1",
|
||||
max_bytes=1_000,
|
||||
max_sources=2,
|
||||
)
|
||||
self.assertEqual(self.cache(), loaded)
|
||||
|
||||
with path.open("ab") as handle:
|
||||
handle.write(b" " * 1_000)
|
||||
self.assertIsNone(
|
||||
load_extraction_cache(
|
||||
path,
|
||||
project_id="fixture",
|
||||
adapter_id="fixture-adapter",
|
||||
adapter_version="1",
|
||||
max_bytes=1_000,
|
||||
max_sources=2,
|
||||
)
|
||||
)
|
||||
|
||||
def test_write_rejects_byte_and_source_limits_without_replacing_target(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
path = Path(directory) / "extractions.json"
|
||||
path.write_bytes(b"preserved\n")
|
||||
for cache, maximum_bytes, maximum_sources in (
|
||||
(self.cache(payload="x" * 500), 100, 2),
|
||||
(self.cache(count=2), 1_000, 1),
|
||||
):
|
||||
with self.assertRaises(DocForgeError) as captured:
|
||||
write_extraction_cache(
|
||||
path,
|
||||
cache,
|
||||
max_bytes=maximum_bytes,
|
||||
max_sources=maximum_sources,
|
||||
)
|
||||
self.assertEqual("cache_limit", captured.exception.code)
|
||||
self.assertEqual(b"preserved\n", path.read_bytes())
|
||||
|
||||
def test_symlink_and_non_regular_targets_are_cache_misses(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory)
|
||||
real = root / "real.json"
|
||||
write_extraction_cache(real, self.cache(), max_bytes=1_000, max_sources=2)
|
||||
linked = root / "linked.json"
|
||||
linked.symlink_to(real)
|
||||
fifo = root / "fifo"
|
||||
os.mkfifo(fifo)
|
||||
for path in (linked, fifo):
|
||||
self.assertIsNone(
|
||||
load_extraction_cache(
|
||||
path,
|
||||
project_id="fixture",
|
||||
adapter_id="fixture-adapter",
|
||||
adapter_version="1",
|
||||
max_bytes=1_000,
|
||||
max_sources=2,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue