Skip to content

Commit 1ddb0a7

Browse files
committed
feat(ingest): add tests command
1 parent be32902 commit 1ddb0a7

File tree

5 files changed

+185
-192
lines changed

5 files changed

+185
-192
lines changed

pychunkedgraph/debug/cross_edge_test.py

Lines changed: 0 additions & 60 deletions
This file was deleted.

pychunkedgraph/debug/existence_test.py

Lines changed: 0 additions & 78 deletions
This file was deleted.

pychunkedgraph/debug/family_test.py

Lines changed: 0 additions & 54 deletions
This file was deleted.

pychunkedgraph/ingest/cli.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from .manager import IngestionManager
1919
from .utils import bootstrap
2020
from .utils import chunk_id_str
21+
from .simple_tests import run_all
2122
from .create.abstract_layers import add_layer
2223
from ..graph.chunkedgraph import ChunkedGraph
2324
from ..utils.redis import get_redis_connection
@@ -186,3 +187,9 @@ def ingest_chunk_local(graph_id: str, chunk_info, n_threads: int):
186187
"""Manually ingest a chunk on a local machine."""
187188
cg = ChunkedGraph(graph_id=graph_id)
188189
add_layer(cg, chunk_info[0], chunk_info[1:], n_threads=n_threads)
190+
191+
192+
@ingest_cli.command("run_tests")
193+
@click.argument("graph_id", type=str)
194+
def run_tests(graph_id):
195+
run_all(ChunkedGraph(graph_id=graph_id))
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
# pylint: disable=invalid-name, missing-function-docstring, broad-exception-caught
2+
3+
"""
4+
Some sanity tests to ensure chunkedgraph was created properly.
5+
"""
6+
7+
from datetime import datetime
8+
import numpy as np
9+
10+
from pychunkedgraph.graph import ChunkedGraph
11+
from pychunkedgraph.graph import attributes
12+
13+
14+
def family(cg: ChunkedGraph):
15+
np.random.seed(42)
16+
n_chunks = 100
17+
n_segments_per_chunk = 200
18+
timestamp = datetime.utcnow()
19+
20+
node_ids = []
21+
for layer in range(2, cg.meta.layer_count - 1):
22+
for _ in range(n_chunks):
23+
c_x = np.random.randint(0, cg.meta.layer_chunk_bounds[layer][0])
24+
c_y = np.random.randint(0, cg.meta.layer_chunk_bounds[layer][1])
25+
c_z = np.random.randint(0, cg.meta.layer_chunk_bounds[layer][2])
26+
chunk_id = cg.get_chunk_id(layer=layer, x=c_x, y=c_y, z=c_z)
27+
max_segment_id = cg.get_segment_id(cg.id_client.get_max_node_id(chunk_id))
28+
if max_segment_id < 10:
29+
continue
30+
31+
segment_ids = np.random.randint(1, max_segment_id, n_segments_per_chunk)
32+
for segment_id in segment_ids:
33+
node_ids.append(
34+
cg.get_node_id(np.uint64(segment_id), np.uint64(chunk_id))
35+
)
36+
37+
rows = cg.client.read_nodes(
38+
node_ids=node_ids, end_time=timestamp, properties=attributes.Hierarchy.Parent
39+
)
40+
valid_node_ids = []
41+
non_valid_node_ids = []
42+
for k in rows.keys():
43+
if len(rows[k]) > 0:
44+
valid_node_ids.append(k)
45+
else:
46+
non_valid_node_ids.append(k)
47+
48+
parents = cg.get_parents(valid_node_ids, time_stamp=timestamp)
49+
children_dict = cg.get_children(parents)
50+
for child, parent in zip(valid_node_ids, parents):
51+
assert child in children_dict[parent]
52+
print("success")
53+
54+
55+
def existence(cg: ChunkedGraph):
56+
np.random.seed(42)
57+
layer = 2
58+
n_chunks = 100
59+
n_segments_per_chunk = 200
60+
timestamp = datetime.utcnow()
61+
node_ids = []
62+
for _ in range(n_chunks):
63+
c_x = np.random.randint(0, cg.meta.layer_chunk_bounds[layer][0])
64+
c_y = np.random.randint(0, cg.meta.layer_chunk_bounds[layer][1])
65+
c_z = np.random.randint(0, cg.meta.layer_chunk_bounds[layer][2])
66+
chunk_id = cg.get_chunk_id(layer=layer, x=c_x, y=c_y, z=c_z)
67+
max_segment_id = cg.get_segment_id(cg.id_client.get_max_node_id(chunk_id))
68+
if max_segment_id < 10:
69+
continue
70+
71+
segment_ids = np.random.randint(1, max_segment_id, n_segments_per_chunk)
72+
for segment_id in segment_ids:
73+
node_ids.append(cg.get_node_id(np.uint64(segment_id), np.uint64(chunk_id)))
74+
75+
rows = cg.client.read_nodes(
76+
node_ids=node_ids, end_time=timestamp, properties=attributes.Hierarchy.Parent
77+
)
78+
valid_node_ids = []
79+
non_valid_node_ids = []
80+
for k in rows.keys():
81+
if len(rows[k]) > 0:
82+
valid_node_ids.append(k)
83+
else:
84+
non_valid_node_ids.append(k)
85+
86+
roots = []
87+
try:
88+
roots = cg.get_roots(valid_node_ids)
89+
assert len(roots) == len(valid_node_ids)
90+
print("success")
91+
except Exception as e:
92+
print(f"Something went wrong: {e}")
93+
print("At least one node failed. Checking nodes one by one:")
94+
95+
if len(roots) != len(valid_node_ids):
96+
log_dict = {}
97+
success_dict = {}
98+
for node_id in valid_node_ids:
99+
try:
100+
_ = cg.get_root(node_id, time_stamp=timestamp)
101+
print(f"Success: {node_id} from chunk {cg.get_chunk_id(node_id)}")
102+
success_dict[node_id] = True
103+
except Exception as e:
104+
print(f"{node_id} - chunk {cg.get_chunk_id(node_id)} failed: {e}")
105+
success_dict[node_id] = False
106+
t_id = node_id
107+
while t_id is not None:
108+
last_working_chunk = cg.get_chunk_id(t_id)
109+
t_id = cg.get_parent(t_id)
110+
111+
layer = cg.get_chunk_layer(last_working_chunk)
112+
print(f"Failed on layer {layer} in chunk {last_working_chunk}")
113+
log_dict[node_id] = last_working_chunk
114+
115+
116+
def cross_edges(cg: ChunkedGraph):
117+
np.random.seed(42)
118+
layer = 2
119+
n_chunks = 10
120+
n_segments_per_chunk = 200
121+
timestamp = datetime.utcnow()
122+
node_ids = []
123+
for _ in range(n_chunks):
124+
c_x = np.random.randint(0, cg.meta.layer_chunk_bounds[layer][0])
125+
c_y = np.random.randint(0, cg.meta.layer_chunk_bounds[layer][1])
126+
c_z = np.random.randint(0, cg.meta.layer_chunk_bounds[layer][2])
127+
chunk_id = cg.get_chunk_id(layer=layer, x=c_x, y=c_y, z=c_z)
128+
max_segment_id = cg.get_segment_id(cg.id_client.get_max_node_id(chunk_id))
129+
if max_segment_id < 10:
130+
continue
131+
132+
segment_ids = np.random.randint(1, max_segment_id, n_segments_per_chunk)
133+
for segment_id in segment_ids:
134+
node_ids.append(cg.get_node_id(np.uint64(segment_id), np.uint64(chunk_id)))
135+
136+
rows = cg.client.read_nodes(
137+
node_ids=node_ids, end_time=timestamp, properties=attributes.Hierarchy.Parent
138+
)
139+
valid_node_ids = []
140+
non_valid_node_ids = []
141+
for k in rows.keys():
142+
if len(rows[k]) > 0:
143+
valid_node_ids.append(k)
144+
else:
145+
non_valid_node_ids.append(k)
146+
147+
cc_edges = cg.get_atomic_cross_edges(valid_node_ids)
148+
cc_ids = np.unique(
149+
np.concatenate(
150+
[
151+
np.concatenate(list(v.values()))
152+
for v in list(cc_edges.values())
153+
if len(v.values())
154+
]
155+
)
156+
)
157+
158+
roots = cg.get_roots(cc_ids)
159+
root_dict = dict(zip(cc_ids, roots))
160+
root_dict_vec = np.vectorize(root_dict.get)
161+
162+
for k in cc_edges:
163+
if len(cc_edges[k]) == 0:
164+
continue
165+
local_ids = np.unique(np.concatenate(list(cc_edges[k].values())))
166+
assert len(np.unique(root_dict_vec(local_ids)))
167+
print("success")
168+
169+
170+
def run_all(cg: ChunkedGraph):
171+
print("Running family tests:")
172+
family(cg)
173+
174+
print("\nRunning existence tests:")
175+
existence(cg)
176+
177+
print("\nRunning cross_edges tests:")
178+
cross_edges(cg)

0 commit comments

Comments
 (0)