Skip to content

Commit d9c1a07

Browse files
committed
test(deterministic): add WL blank-node and no-bnode edge case tests
Signed-off-by: jdsika <carlo.van-driesten@bmw.de>
1 parent 8016a4b commit d9c1a07

1 file changed

Lines changed: 61 additions & 0 deletions

File tree

tests/linkml/test_generators/test_deterministic_output.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,67 @@ def test_non_deterministic_is_default():
260260
assert gen.deterministic is False
261261

262262

263+
def test_wl_handles_structurally_similar_bnodes():
264+
"""Blank nodes with identical local structure but different named neighbours
265+
must receive different WL signatures and thus different stable labels.
266+
267+
This tests the core WL property: two BNodes that differ only in their
268+
connected named nodes (URIs/literals) must be distinguishable.
269+
"""
270+
from rdflib import BNode, Graph, Literal, Namespace, URIRef
271+
272+
from linkml.utils.generator import deterministic_turtle
273+
274+
EX = Namespace("http://example.org/")
275+
g = Graph()
276+
277+
# Two restrictions with same structure but different property URIs
278+
r1 = BNode()
279+
g.add((r1, URIRef("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),
280+
URIRef("http://www.w3.org/2002/07/owl#Restriction")))
281+
g.add((r1, URIRef("http://www.w3.org/2002/07/owl#onProperty"), EX.alpha))
282+
g.add((r1, URIRef("http://www.w3.org/2002/07/owl#allValuesFrom"), EX.Target1))
283+
284+
r2 = BNode()
285+
g.add((r2, URIRef("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),
286+
URIRef("http://www.w3.org/2002/07/owl#Restriction")))
287+
g.add((r2, URIRef("http://www.w3.org/2002/07/owl#onProperty"), EX.beta))
288+
g.add((r2, URIRef("http://www.w3.org/2002/07/owl#allValuesFrom"), EX.Target2))
289+
290+
g.add((EX.MyClass, URIRef("http://www.w3.org/2000/01/rdf-schema#subClassOf"), r1))
291+
g.add((EX.MyClass, URIRef("http://www.w3.org/2000/01/rdf-schema#subClassOf"), r2))
292+
293+
# Must be deterministic across runs
294+
out1 = deterministic_turtle(g)
295+
out2 = deterministic_turtle(g)
296+
assert out1 == out2, "WL-based serializer is not deterministic for similar BNodes"
297+
298+
# Both restrictions must appear (not collapsed)
299+
assert "alpha" in out1
300+
assert "beta" in out1
301+
302+
303+
def test_deterministic_turtle_no_bnodes():
304+
"""Graphs with no blank nodes should still produce sorted, deterministic output."""
305+
from rdflib import Graph, Literal, Namespace, URIRef
306+
307+
from linkml.utils.generator import deterministic_turtle
308+
309+
EX = Namespace("http://example.org/")
310+
g = Graph()
311+
g.add((EX.B, URIRef("http://www.w3.org/2000/01/rdf-schema#label"), Literal("B")))
312+
g.add((EX.A, URIRef("http://www.w3.org/2000/01/rdf-schema#label"), Literal("A")))
313+
314+
out1 = deterministic_turtle(g)
315+
out2 = deterministic_turtle(g)
316+
assert out1 == out2
317+
318+
# A should appear before B (sorted)
319+
a_pos = out1.find("example.org/A")
320+
b_pos = out1.find("example.org/B")
321+
assert a_pos < b_pos, "Triples should be sorted: A before B"
322+
323+
263324
@pytest.mark.xfail(
264325
reason=(
265326
"Collection sorting (owl:oneOf, sh:in) in deterministic mode intentionally "

0 commit comments

Comments
 (0)