Files
fn_registry/python/functions/infra/cache_to_sqlite_test.py
T
egutierrez 5a324f6554 feat: funciones Python infra y tipos Python (core, datascience, infra)
Infra: cache_to_file, cache_to_sqlite, http_download_file, http_get_json,
http_post_json, read_file_with_encoding, safe_extract_zip, scan_directory,
setup_logger, normalize_zip_filenames.
Tipos: 30+ tipos core (agent_action, context, task, message, parse_result...),
6 tipos datascience (entity_candidate, extraction_result...), 2 tipos infra.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 17:11:43 +02:00

115 lines
2.6 KiB
Python

"""Tests para cache_to_sqlite."""
import os
import tempfile
import threading
import time
import pytest
from .cache_to_sqlite import cache_to_sqlite
@pytest.fixture
def store(tmp_path):
db = str(tmp_path / "test.db")
return cache_to_sqlite(db)
@pytest.fixture
def store2(tmp_path):
"""Segundo namespace en la misma BD."""
db = str(tmp_path / "test.db")
return cache_to_sqlite(db, namespace="other")
@pytest.fixture
def store_and_other(tmp_path):
db = str(tmp_path / "test.db")
s1 = cache_to_sqlite(db, namespace="ns1")
s2 = cache_to_sqlite(db, namespace="ns2")
return s1, s2
def test_set_y_get_basico(store):
store.set("foo", {"x": 1})
assert store.get("foo") == {"x": 1}
def test_ttl_expirado_retorna_none(store):
store.set("expiring", "hello", ttl=0.05)
time.sleep(0.1)
assert store.get("expiring") is None
def test_ttl_cero_nunca_expira(store):
store.set("forever", 42, ttl=0)
time.sleep(0.05)
assert store.get("forever") == 42
def test_get_or_set_factory_solo_se_llama_en_miss(store):
calls = []
def factory():
calls.append(1)
return "computed"
result1 = store.get_or_set("key", factory, ttl=10)
result2 = store.get_or_set("key", factory, ttl=10)
assert result1 == "computed"
assert result2 == "computed"
assert len(calls) == 1
def test_namespaces_independientes(store_and_other):
s1, s2 = store_and_other
s1.set("k", "from_ns1")
assert s2.get("k") is None
s2.set("k", "from_ns2")
assert s1.get("k") == "from_ns1"
assert s2.get("k") == "from_ns2"
def test_clear_elimina_solo_el_namespace(store_and_other):
s1, s2 = store_and_other
s1.set("a", 1)
s2.set("b", 2)
removed = s1.clear()
assert removed == 1
assert s1.get("a") is None
assert s2.get("b") == 2
def test_stats_contadores_correctos(store):
store.set("x", 10)
store.get("x") # hit
store.get("x") # hit
store.get("z") # miss
s = store.stats()
assert s["hits"] == 2
assert s["misses"] == 1
assert s["size"] == 1
def test_concurrencia(tmp_path):
db = str(tmp_path / "concurrent.db")
s = cache_to_sqlite(db, "parallel")
errors = []
def worker(i):
try:
s.set(f"key_{i}", i)
val = s.get(f"key_{i}")
assert val == i
except Exception as e:
errors.append(e)
threads = [threading.Thread(target=worker, args=(i,)) for i in range(20)]
for t in threads:
t.start()
for t in threads:
t.join()
assert errors == [], f"Errors in threads: {errors}"