Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: honour lax cardinality from test manifests #2074

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 0 additions & 3 deletions test/test_w3c_spec/test_sparql10_w3c.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@
f"{REMOTE_BASE_IRI}optional-filter/manifest#dawg-optional-filter-005-simplified": pytest.mark.xfail(
reason="one row is missing a column"
),
f"{REMOTE_BASE_IRI}reduced/manifest#reduced-2": pytest.mark.xfail(
reason="fails 2/3rds or the time"
),
f"{REMOTE_BASE_IRI}syntax-sparql1/manifest#syntax-bnodes-03": pytest.mark.xfail(
reason="Issue with bnodes in query."
),
Expand Down
4 changes: 4 additions & 0 deletions test/utils/dawg_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class ManifestEntry:
type: IdentifiedNode = field(init=False)
action: Optional[IdentifiedNode] = field(init=False)
result: Optional[IdentifiedNode] = field(init=False)
result_cardinality: Optional[URIRef] = field(init=False)

def __post_init__(self) -> None:
type = self.value(RDF.type, IdentifiedNode)
Expand All @@ -51,6 +52,9 @@ def __post_init__(self) -> None:

self.action = self.value(MF.action, IdentifiedNode)
self.result = self.value(MF.result, IdentifiedNode)
self.result_cardinality = self.value(MF.resultCardinality, URIRef)
if self.result_cardinality is not None:
assert self.result_cardinality == MF.LaxCardinality

@property
def graph(self) -> Graph:
Expand Down
48 changes: 36 additions & 12 deletions test/utils/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import pprint
from dataclasses import dataclass
from functools import lru_cache
from typing import Dict, FrozenSet, Mapping, Optional, Sequence, Set, Tuple, Union
from typing import Collection, Dict, FrozenSet, Mapping, Optional, Set, Tuple, Union

from rdflib.term import BNode, Identifier, Literal, Variable

Expand Down Expand Up @@ -54,14 +54,14 @@ def make_dict(cls, *items: "ResultTypeInfo") -> ResultTypeInfoDict:


BindingsType = Mapping[Variable, Optional[Identifier]]
BindingsSequenceType = Sequence[BindingsType]
BindingsCollectionType = Collection[BindingsType]
CLiteralType = Union["CLiteral", "CLiteral"]


CIdentifier = Union[Identifier, CLiteralType]
CBindingSetType = FrozenSet[Tuple[Variable, CIdentifier]]
CBindingsType = Mapping[Variable, Optional[CIdentifier]]
CBindingsSequenceType = Sequence[CBindingsType]
CBindingsCollectionType = Collection[CBindingsType]


@dataclass
Expand Down Expand Up @@ -98,8 +98,8 @@ def comparable_bindings(


def bindings_diff(
lhs: CBindingsSequenceType, rhs: CBindingsSequenceType
) -> Tuple[CBindingsSequenceType, CBindingsSequenceType, CBindingsSequenceType]:
lhs: CBindingsCollectionType, rhs: CBindingsCollectionType
) -> Tuple[CBindingsCollectionType, CBindingsCollectionType, CBindingsCollectionType]:
rhs_only = []
common = []
lhs_matched = set()
Expand All @@ -126,25 +126,49 @@ def bindings_diff(
return lhs_only, rhs_only, common


def assert_bindings_sequences_equal(
lhs: BindingsSequenceType,
rhs: BindingsSequenceType,
def comparable_collection(
bcollection: BindingsCollectionType, skip_duplicates: bool = False
) -> CBindingsCollectionType:
result = []
for bindings in bcollection:
cbindings = comparable_bindings(bindings)
if skip_duplicates:
if cbindings in result:
continue
result.append(cbindings)
return result


def assert_bindings_collections_equal(
lhs: BindingsCollectionType,
rhs: BindingsCollectionType,
invert: bool = False,
skip_duplicates: bool = False,
) -> None:
clhs = [comparable_bindings(item) for item in lhs]
crhs = [comparable_bindings(item) for item in rhs]
clhs = comparable_collection(lhs, skip_duplicates=skip_duplicates)
crhs = comparable_collection(rhs, skip_duplicates=skip_duplicates)
if skip_duplicates:
if len(lhs) > 0:
assert len(clhs) > 0
if len(rhs) > 0:
assert len(crhs) > 0
assert len(clhs) < len(lhs)
assert len(crhs) < len(rhs)
else:
assert len(lhs) == len(clhs)
assert len(rhs) == len(crhs)
lhs_only, rhs_only, common = bindings_diff(clhs, crhs)
if logger.isEnabledFor(logging.DEBUG):
logging.debug("common = \n%s", pprint.pformat(common, indent=1, width=80))
logging.debug("lhs_only = \n%s", pprint.pformat(lhs_only, indent=1, width=80))
logging.debug("rhs_only = \n%s", pprint.pformat(rhs_only, indent=1, width=80))
if invert:
assert lhs_only != [] or rhs_only != []
assert (len(common) != len(lhs)) or (len(common) != len(rhs))
assert (len(common) != len(clhs)) or (len(common) != len(crhs))
else:
assert lhs_only == []
assert rhs_only == []
assert (len(common) == len(lhs)) and (len(common) == len(rhs))
assert (len(common) == len(clhs)) and (len(common) == len(crhs))


ResultFormatInfoDict = Dict["ResultFormat", "ResultFormatInfo"]
Expand Down
12 changes: 9 additions & 3 deletions test/utils/sparql_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from test.utils.dawg_manifest import Manifest, ManifestEntry
from test.utils.iri import URIMapper
from test.utils.namespace import MF, QT, UT
from test.utils.result import ResultType, assert_bindings_sequences_equal
from test.utils.result import ResultType, assert_bindings_collections_equal
from typing import Any, Callable, Dict, Generator, Optional, Set, Tuple, Type, Union
from urllib.parse import urljoin

Expand Down Expand Up @@ -375,7 +375,8 @@ def check_query(monkeypatch: MonkeyPatch, entry: SPARQLEntry) -> None:
if result.type == ResultType.SELECT:
if logger.isEnabledFor(logging.DEBUG):
logging.debug(
"result.bindings = \n%s",
"entry.result_cardinality = %s, result.bindings = \n%s",
entry.result_cardinality,
pprint.pformat(result.bindings, indent=2, width=80),
)
if expected_result_format == "csv":
Expand All @@ -387,7 +388,12 @@ def check_query(monkeypatch: MonkeyPatch, entry: SPARQLEntry) -> None:
bio.getvalue().decode("utf-8"),
)
result = Result.parse(bio, format="csv")
assert_bindings_sequences_equal(expected_result.bindings, result.bindings)
lax_cardinality = entry.result_cardinality == MF.LaxCardinality
assert_bindings_collections_equal(
expected_result.bindings,
result.bindings,
skip_duplicates=lax_cardinality,
)
elif result.type == ResultType.ASK:
assert expected_result.askAnswer == result.askAnswer
else:
Expand Down
8 changes: 4 additions & 4 deletions test/utils/test/test_result.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from contextlib import ExitStack
from test.utils.result import BindingsSequenceType, assert_bindings_sequences_equal
from test.utils.result import BindingsCollectionType, assert_bindings_collections_equal
from typing import Type, Union

import pytest
Expand Down Expand Up @@ -227,15 +227,15 @@
],
)
def test_bindings_equal(
lhs: BindingsSequenceType,
rhs: BindingsSequenceType,
lhs: BindingsCollectionType,
rhs: BindingsCollectionType,
expected_result: Union[bool, Type[Exception]],
) -> None:
catcher: Optional[pytest.ExceptionInfo[Exception]] = None

with ExitStack() as xstack:
if isinstance(expected_result, type) and issubclass(expected_result, Exception):
catcher = xstack.enter_context(pytest.raises(expected_result))
assert_bindings_sequences_equal(lhs, rhs, not expected_result)
assert_bindings_collections_equal(lhs, rhs, not expected_result)
if catcher is not None:
assert isinstance(catcher.value, Exception)
2 changes: 1 addition & 1 deletion test_reports/rdflib_w3c_sparql10-HEAD.ttl
Original file line number Diff line number Diff line change
Expand Up @@ -1483,7 +1483,7 @@
earl:assertedBy <https://github.com/RDFLib/rdflib> ;
earl:mode earl:automatic ;
earl:result [ a earl:TestResult ;
earl:outcome earl:failed ] ;
earl:outcome earl:passed ] ;
earl:subject <https://github.com/RDFLib/rdflib> ;
earl:test <http://www.w3.org/2001/sw/DataAccess/tests/data-r2/reduced/manifest#reduced-2> .

Expand Down