1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
"""Tests federated SPARQL queries with a locally deployed triple store."""
import itertools as itt
import time
import unittest
from multiprocessing import Process
from typing import ClassVar
import uvicorn
from curies import Converter
from curies.mapping_service import get_fastapi_mapping_app
from curies.mapping_service.utils import (
get_sparql_record_so_tuples,
get_sparql_records,
require_service,
sparql_service_available,
)
from tests.test_mapping_service import PREFIX_MAP
BLAZEGRAPH_ENDPOINT = "http://localhost:9999/blazegraph/namespace/kb/sparql"
BLAZEGRAPH_JAR_URL = (
"https://github.com/blazegraph/database/releases/download/BLAZEGRAPH_2_1_6_RC/blazegraph.jar"
)
SPARQL_VALUES_FMT = """\
PREFIX owl: <http://www.w3.org/2002/07/owl#>
SELECT DISTINCT ?s ?o WHERE {{
SERVICE <{mapping_service}> {{
VALUES ?s {{ <http://purl.obolibrary.org/obo/CHEBI_24867> }}
?s owl:sameAs ?o
}}
}}
""".rstrip()
SPARQL_VALUES_FMT_2 = """\
PREFIX owl: <http://www.w3.org/2002/07/owl#>
SELECT DISTINCT ?s ?o WHERE {{
VALUES ?s {{ <http://purl.obolibrary.org/obo/CHEBI_24867> }}
SERVICE <{mapping_service}> {{
?s owl:sameAs ?o
}}
}}
""".rstrip()
SPARQL_VALUES_FMT_3 = """\
PREFIX owl: <http://www.w3.org/2002/07/owl#>
SELECT DISTINCT ?s ?o WHERE {{
SERVICE <{mapping_service}> {{
?s owl:sameAs ?o
}}
VALUES ?s {{ <http://purl.obolibrary.org/obo/CHEBI_24867> }}
}}
""".rstrip()
SPARQL_SIMPLE_FMT = """\
PREFIX owl: <http://www.w3.org/2002/07/owl#>
SELECT DISTINCT ?s ?o WHERE {{
SERVICE <{mapping_service}> {{
<http://purl.obolibrary.org/obo/CHEBI_24867> owl:sameAs ?o .
?s owl:sameAs ?o .
}}
}}
""".rstrip()
SPARQL_SIMPLE_FMT_2 = """\
PREFIX owl: <http://www.w3.org/2002/07/owl#>
SELECT DISTINCT ?s ?o WHERE {{
SERVICE <{mapping_service}> {{
?s owl:sameAs ?o .
<http://purl.obolibrary.org/obo/CHEBI_24867> owl:sameAs ?o .
}}
}}
""".rstrip()
# TODO test
SPARQL_SIMPLE_FMT_3 = """\
PREFIX owl: <http://www.w3.org/2002/07/owl#>
SELECT DISTINCT ?s ?o WHERE {{
<http://purl.obolibrary.org/obo/CHEBI_24867> owl:sameAs ?o .
SERVICE <{mapping_service}> {{
?s owl:sameAs ?o .
}}
}}
""".rstrip()
# TODO test
SPARQL_SIMPLE_FMT_4 = """\
PREFIX owl: <http://www.w3.org/2002/07/owl#>
SELECT DISTINCT ?s ?o WHERE {{
SERVICE <{mapping_service}> {{
?s owl:sameAs ?o .
}}
<http://purl.obolibrary.org/obo/CHEBI_24867> owl:sameAs ?o .
}}
""".rstrip()
class FederationMixin(unittest.TestCase):
"""A shared mixin for testing."""
def assert_service_works(self, endpoint: str):
"""Assert that a service is able to accept a simple SPARQL query."""
self.assertTrue(sparql_service_available(endpoint))
def _get_app():
converter = Converter.from_priority_prefix_map(PREFIX_MAP)
app = get_fastapi_mapping_app(converter)
return app
@require_service(BLAZEGRAPH_ENDPOINT, "Blazegraph")
class TestFederatedSparql(FederationMixin):
"""Test the identifier mapping service."""
endpoint: ClassVar[str] = BLAZEGRAPH_ENDPOINT
mimetypes: ClassVar[list[str]] = [
"application/sparql-results+json",
"application/sparql-results+xml",
"text/csv", # for some reason, Blazegraph wants this instead of application/sparql-results+csv
]
query_formats: ClassVar[list[str]] = [
SPARQL_VALUES_FMT,
SPARQL_VALUES_FMT_2,
SPARQL_VALUES_FMT_3,
SPARQL_SIMPLE_FMT,
SPARQL_SIMPLE_FMT_2,
]
host: ClassVar[str] = "localhost"
port: ClassVar[int] = 8000
mapping_service_process: Process
def setUp(self):
"""Set up the test case."""
# Start the curies mapping service SPARQL endpoint
self.mapping_service_process = Process(
target=uvicorn.run,
# uvicorn.run accepts a zero-argument callable that returns an app
args=(_get_app,),
kwargs={"host": self.host, "port": self.port, "log_level": "info"},
daemon=True,
)
self.mapping_service_process.start()
time.sleep(5)
self.mapping_service = f"http://{self.host}:{self.port}/sparql"
self.queries = [
query_format.format(mapping_service=self.mapping_service)
for query_format in self.query_formats
]
self.assert_service_works(self.mapping_service)
def tearDown(self):
"""Tear down the testing case."""
self.mapping_service_process.kill()
def test_federated_local(self):
"""Test sending a federated query to a local mapping service from a local service."""
for mimetype, sparql in itt.product(self.mimetypes, self.queries):
with self.subTest(mimetype=mimetype, sparql=sparql):
records = get_sparql_records(self.endpoint, sparql, accept=mimetype)
self.assertIn(
(
"http://purl.obolibrary.org/obo/CHEBI_24867",
"http://identifiers.org/chebi/24867",
),
get_sparql_record_so_tuples(records),
)
|