Skip to content

Commit 29f47f3

Browse files
committed
test: add comprehensive testing for TierStore
This commit adds unit, integration, and FFI tests for the TierStore implementation: - Unit tests for TierStore core functionality - Integration tests for nodes built with tiered storage - Python FFI tests for foreign key-value store
1 parent 315a544 commit 29f47f3

File tree

6 files changed

+864
-233
lines changed

6 files changed

+864
-233
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import threading
2+
3+
from abc import ABC, abstractmethod
4+
from typing import List
5+
6+
from ldk_node import IoError
7+
8+
class AbstractKvStore(ABC):
9+
@abstractmethod
10+
async def list_async(self, primary_namespace: "str",secondary_namespace: "str") -> "typing.List[str]":
11+
pass
12+
13+
@abstractmethod
14+
def list_sync(self, primary_namespace: "str",secondary_namespace: "str") -> "typing.List[str]":
15+
pass
16+
17+
@abstractmethod
18+
async def read_async(self, primary_namespace: "str",secondary_namespace: "str",key: "str") -> "typing.List[int]":
19+
pass
20+
21+
@abstractmethod
22+
def read_sync(self, primary_namespace: "str",secondary_namespace: "str",key: "str") -> "typing.List[int]":
23+
pass
24+
25+
@abstractmethod
26+
async def remove_async(self, primary_namespace: "str",secondary_namespace: "str",key: "str",lazy: "bool") -> None:
27+
pass
28+
29+
@abstractmethod
30+
def remove_sync(self, primary_namespace: "str",secondary_namespace: "str",key: "str",lazy: "bool") -> None:
31+
pass
32+
33+
@abstractmethod
34+
async def write_async(self, primary_namespace: "str",secondary_namespace: "str",key: "str",buf: "typing.List[int]") -> None:
35+
pass
36+
37+
@abstractmethod
38+
def write_sync(self, primary_namespace: "str",secondary_namespace: "str",key: "str",buf: "typing.List[int]") -> None:
39+
pass
40+
41+
class TestKvStore(AbstractKvStore):
42+
def __init__(self, name: str):
43+
self.name = name
44+
# Storage structure: {(primary_ns, secondary_ns): {key: [bytes]}}
45+
self.storage = {}
46+
self._lock = threading.Lock()
47+
48+
def dump(self):
49+
print(f"\n[{self.name}] Store contents:")
50+
for (primary_ns, secondary_ns), keys_dict in self.storage.items():
51+
print(f" Namespace: ({primary_ns!r}, {secondary_ns!r})")
52+
for key, data in keys_dict.items():
53+
print(f" Key: {key!r} -> {len(data)} bytes")
54+
# Optionally show first few bytes
55+
preview = data[:20] if len(data) > 20 else data
56+
print(f" Data preview: {preview}...")
57+
58+
# KVStoreSync methods
59+
def list_sync(self, primary_namespace: str, secondary_namespace: str) -> List[str]:
60+
with self._lock:
61+
namespace_key = (primary_namespace, secondary_namespace)
62+
if namespace_key in self.storage:
63+
return list(self.storage[namespace_key].keys())
64+
return []
65+
66+
def read_sync(self, primary_namespace: str, secondary_namespace: str, key: str) -> List[int]:
67+
with self._lock:
68+
print(f"[{self.name}] READ: {primary_namespace}/{secondary_namespace}/{key}")
69+
namespace_key = (primary_namespace, secondary_namespace)
70+
71+
if namespace_key not in self.storage:
72+
print(f" -> namespace not found, keys: {list(self.storage.keys())}")
73+
raise IoError.NotFound(f"Namespace not found: {primary_namespace}/{secondary_namespace}")
74+
75+
if key not in self.storage[namespace_key]:
76+
print(f" -> key not found, keys: {list(self.storage[namespace_key].keys())}")
77+
raise IoError.NotFound(f"Key not found: {key}")
78+
79+
data = self.storage[namespace_key][key]
80+
print(f" -> returning {len(data)} bytes")
81+
return data
82+
83+
def write_sync(self, primary_namespace: str, secondary_namespace: str, key: str, buf: List[int]) -> None:
84+
with self._lock:
85+
namespace_key = (primary_namespace, secondary_namespace)
86+
if namespace_key not in self.storage:
87+
self.storage[namespace_key] = {}
88+
89+
self.storage[namespace_key][key] = buf.copy()
90+
91+
def remove_sync(self, primary_namespace: str, secondary_namespace: str, key: str, lazy: bool) -> None:
92+
with self._lock:
93+
namespace_key = (primary_namespace, secondary_namespace)
94+
if namespace_key not in self.storage:
95+
raise IoError.NotFound(f"Namespace not found: {primary_namespace}/{secondary_namespace}")
96+
97+
if key not in self.storage[namespace_key]:
98+
raise IoError.NotFound(f"Key not found: {key}")
99+
100+
del self.storage[namespace_key][key]
101+
102+
if not self.storage[namespace_key]:
103+
del self.storage[namespace_key]
104+
105+
# KVStore methods
106+
async def list_async(self, primary_namespace: str, secondary_namespace: str) -> List[str]:
107+
return self.list_sync(primary_namespace, secondary_namespace)
108+
109+
async def read_async(self, primary_namespace: str, secondary_namespace: str, key: str) -> List[int]:
110+
return self.read_sync(primary_namespace, secondary_namespace, key)
111+
112+
async def write_async(self, primary_namespace: str, secondary_namespace: str, key: str, buf: List[int]) -> None:
113+
self.write_sync(primary_namespace, secondary_namespace, key, buf)
114+
115+
async def remove_async(self, primary_namespace: str, secondary_namespace: str, key: str, lazy: bool) -> None:
116+
self.remove_sync(primary_namespace, secondary_namespace, key, lazy)
117+
118+

0 commit comments

Comments
 (0)