Skip to content

Commit

Permalink
test: content-type handling with SPARQLStore + CONSTRUCT queries (#2092)
Browse files Browse the repository at this point in the history
Confirm various content type values are handled correctly with CONSTRUCT
queries and SPARQLStore.

This aims to confirm that #1195 is fixed.
  • Loading branch information
aucampia committed Aug 23, 2022
1 parent 3a9076d commit 2ce4e2b
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 38 deletions.
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 @@ -258,20 +257,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 @@ -313,7 +298,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 @@ -330,12 +315,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

0 comments on commit 2ce4e2b

Please sign in to comment.