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: content-type handling with SPARQLStore + CONSTRUCT queries #2092

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
17 changes: 17 additions & 0 deletions test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

pytest.register_assert_rewrite("test.utils")

from typing import Generator # noqa: E402

from rdflib import Graph

from .data import TEST_DATA_DIR
from .utils.earl import EARLReporter # noqa: E402
from .utils.httpservermock import ServedBaseHTTPServerMock # noqa: E402

pytest_plugins = [EARLReporter.__module__]

Expand All @@ -16,3 +19,17 @@
@pytest.fixture(scope="session")
def rdfs_graph() -> Graph:
return Graph().parse(TEST_DATA_DIR / "defined_namespaces/rdfs.ttl", format="turtle")


@pytest.fixture(scope="session")
def session_httpmock() -> Generator[ServedBaseHTTPServerMock, None, None]:
with ServedBaseHTTPServerMock() as httpmock:
yield httpmock


@pytest.fixture(scope="function")
def function_httpmock(
session_httpmock: ServedBaseHTTPServerMock,
) -> Generator[ServedBaseHTTPServerMock, None, None]:
session_httpmock.reset()
yield session_httpmock
25 changes: 5 additions & 20 deletions test/test_graph/test_graph_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
ServedBaseHTTPServerMock,
ctx_http_server,
)
from typing import Generator
from urllib.error import HTTPError

import pytest
Expand Down Expand Up @@ -232,24 +231,10 @@ def test_5xx(self):
assert raised.value.code == 500


@pytest.fixture(scope="module")
def module_httpmock() -> Generator[ServedBaseHTTPServerMock, None, None]:
with ServedBaseHTTPServerMock() as httpmock:
yield httpmock


@pytest.fixture(scope="function")
def httpmock(
module_httpmock: ServedBaseHTTPServerMock,
) -> Generator[ServedBaseHTTPServerMock, None, None]:
module_httpmock.reset()
yield module_httpmock


def test_iri_source(httpmock: ServedBaseHTTPServerMock) -> None:
def test_iri_source(function_httpmock: ServedBaseHTTPServerMock) -> None:
diverse_triples_path = TEST_DATA_DIR / "variants/diverse_triples.ttl"

httpmock.responses[MethodName.GET].append(
function_httpmock.responses[MethodName.GET].append(
MockHTTPResponse(
200,
"OK",
Expand All @@ -258,9 +243,9 @@ def test_iri_source(httpmock: ServedBaseHTTPServerMock) -> None:
)
)
g = Graph()
g.parse(f"{httpmock.url}/resource/Almería")
assert httpmock.call_count == 1
g.parse(f"{function_httpmock.url}/resource/Almería")
assert function_httpmock.call_count == 1
GraphHelper.assert_triple_sets_equals(cached_graph((diverse_triples_path,)), g)

req = httpmock.requests[MethodName.GET].pop(0)
req = function_httpmock.requests[MethodName.GET].pop(0)
assert req.path == "/resource/Almer%C3%ADa"
21 changes: 3 additions & 18 deletions test/test_sparql/test_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from typing import (
Dict,
FrozenSet,
Generator,
List,
Mapping,
Optional,
Expand Down Expand Up @@ -223,20 +222,6 @@ def test_service_node_types():
assert expected == freeze_bindings(results.bindings)


@pytest.fixture(scope="module")
def module_httpmock() -> Generator[ServedBaseHTTPServerMock, None, None]:
with ServedBaseHTTPServerMock() as httpmock:
yield httpmock


@pytest.fixture(scope="function")
def httpmock(
module_httpmock: ServedBaseHTTPServerMock,
) -> Generator[ServedBaseHTTPServerMock, None, None]:
module_httpmock.reset()
yield module_httpmock


@pytest.mark.parametrize(
("response_bindings", "expected_result"),
[
Expand Down Expand Up @@ -278,7 +263,7 @@ def httpmock(
],
)
def test_with_mock(
httpmock: ServedBaseHTTPServerMock,
function_httpmock: ServedBaseHTTPServerMock,
response_bindings: List[Dict[str, str]],
expected_result: Union[List[Identifier], Type[Exception]],
) -> None:
Expand All @@ -295,12 +280,12 @@ def test_with_mock(
}
}
"""
query = query.replace("REMOTE_URL", httpmock.url)
query = query.replace("REMOTE_URL", function_httpmock.url)
response = {
"head": {"vars": ["var"]},
"results": {"bindings": [{"var": item} for item in response_bindings]},
}
httpmock.responses[MethodName.GET].append(
function_httpmock.responses[MethodName.GET].append(
MockHTTPResponse(
200,
"OK",
Expand Down
132 changes: 132 additions & 0 deletions test/test_store/test_store_sparqlstore_query.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
from __future__ import annotations

import itertools
import logging
from test.utils import GraphHelper
from test.utils.httpservermock import (
MethodName,
MockHTTPResponse,
ServedBaseHTTPServerMock,
)
from typing import Dict, Iterable, List, Optional, Set, Tuple

import pytest
from _pytest.mark.structures import ParameterSet

from rdflib.graph import Graph


def make_test_query_construct_format_cases() -> Iterable[ParameterSet]:
"""
This only tests with application/rdf+xml as other result formats are not
supported.
"""
graphs: List[Tuple[str, Graph]] = [
(
"basic",
Graph().parse(
format="turtle",
data="""
@prefix egdc: <http://example.com/> .

egdc:s0 egdc:p0 egdc:o0;
egdc:p1 egdc:o1;
egdc:p2 "o2";
egdc:p3 _:o3.


egdc:s1 egdc:p4 egdc:o4;
egdc:p5 egdc:o5;
egdc:p6 "o6";
egdc:p7 _:o7;
egdc:p8 _:03.
""",
),
)
]
response_format_encodings: List[Tuple[str, str, Set[Optional[str]]]] = [
(
"application/rdf+xml",
"utf-8",
{
"application/rdf+xml",
"application/rdf+xml;charset=utf-8",
"application/rdf+xml; charset=utf-8",
"application/rdf+xml; charset=UTF-8",
},
),
]
for (mime_type, encoding, content_types), (
graph_label,
expected_graph,
) in itertools.product(response_format_encodings, graphs):
response_body = expected_graph.serialize(format=mime_type, encoding=encoding)

for content_type in content_types:
if content_type is None:
content_type = f"{mime_type};charset={encoding}"
response_headers: Dict[str, List[str]] = {"Content-Type": [content_type]}
yield pytest.param(
expected_graph,
response_body,
response_headers,
id=f"{mime_type}-{encoding}-{graph_label}-ContentType_{content_type}",
)


@pytest.mark.parametrize(
[
"expected_graph",
"response_body",
"response_headers",
],
make_test_query_construct_format_cases(),
)
def test_query_construct_format(
function_httpmock: ServedBaseHTTPServerMock,
expected_graph: Graph,
response_body: bytes,
response_headers: Dict[str, List[str]],
) -> None:
"""
This tests that bindings for a variable named var
"""
logging.debug("response_headers = %s", response_headers)
graph = Graph(
# store_factory(mime_type),
"SPARQLStore",
identifier="http://example.com",
bind_namespaces="none",
)
url = f"{function_httpmock.url}/query"
logging.debug("opening %s", url)
graph.open(url)
query = """
CONSTRUCT {
?s ?p ?o
}
WHERE {
?s ?p ?o
}
"""

function_httpmock.responses[MethodName.GET].append(
MockHTTPResponse(
200,
"OK",
response_body,
response_headers,
)
)

logging.debug("sending query %s", query)
result = graph.query(query)
logging.debug("result = %s", result)
assert result.type == "CONSTRUCT"
assert result.graph is not None
GraphHelper.assert_isomorphic(expected_graph, result.graph)

request = function_httpmock.requests[MethodName.GET].pop()
logging.debug("request = %s", request)
logging.debug("request.headers = %s", request.headers.as_string())
assert request.path_query["query"][0] == query