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

Improved mock HTTP Server #1888

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
60 changes: 33 additions & 27 deletions test/test_graph/test_graph_http.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import unittest
from http.server import BaseHTTPRequestHandler
from test.utils import GraphHelper, MockHTTPResponse, SimpleHTTPMock, ctx_http_server
from test.utils import GraphHelper
from test.utils.httpservermock import (
MethodName,
MockHTTPResponse,
ServedBaseHTTPServerMock,
ctx_http_server,
)
from urllib.error import HTTPError

from rdflib import Graph, Namespace
Expand Down Expand Up @@ -122,12 +128,10 @@ def test_source(self) -> None:
expected.add((EG["a"], EG["b"], EG["c"]))
expected_triples = GraphHelper.triple_set(expected)

httpmock = SimpleHTTPMock()
with ctx_http_server(httpmock.Handler) as server:
(host, port) = server.server_address
url = f"http://{host}:{port}/"
with ServedBaseHTTPServerMock() as httpmock:
url = httpmock.url

httpmock.do_get_responses.append(
httpmock.responses[MethodName.GET].append(
MockHTTPResponse(
200,
"OK",
Expand All @@ -145,37 +149,38 @@ def test_3xx(self) -> None:
expected.add((EG["a"], EG["b"], EG["c"]))
expected_triples = GraphHelper.triple_set(expected)

httpmock = SimpleHTTPMock()
with ctx_http_server(httpmock.Handler) as server:
(host, port) = server.server_address
url = f"http://{host}:{port}/"
with ServedBaseHTTPServerMock() as httpmock:
url = httpmock.url

for idx in range(3):
httpmock.do_get_responses.append(
httpmock.responses[MethodName.GET].append(
MockHTTPResponse(
302, "FOUND", "".encode(), {"Location": [f"{url}loc/302/{idx}"]}
302,
"FOUND",
"".encode(),
{"Location": [f"{url}/loc/302/{idx}"]},
)
)
for idx in range(3):
httpmock.do_get_responses.append(
httpmock.responses[MethodName.GET].append(
MockHTTPResponse(
303,
"See Other",
"".encode(),
{"Location": [f"{url}loc/303/{idx}"]},
{"Location": [f"{url}/loc/303/{idx}"]},
)
)
for idx in range(3):
httpmock.do_get_responses.append(
httpmock.responses[MethodName.GET].append(
MockHTTPResponse(
308,
"Permanent Redirect",
"".encode(),
{"Location": [f"{url}loc/308/{idx}"]},
{"Location": [f"{url}/loc/308/{idx}"]},
)
)

httpmock.do_get_responses.append(
httpmock.responses[MethodName.GET].append(
MockHTTPResponse(
200,
"OK",
Expand All @@ -188,12 +193,14 @@ def test_3xx(self) -> None:
graph.parse(location=url, format="turtle")
self.assertEqual(expected_triples, GraphHelper.triple_set(graph))

httpmock.do_get_mock.assert_called()
assert len(httpmock.do_get_requests) == 10
for request in httpmock.do_get_requests:
httpmock.mocks[MethodName.GET].assert_called()
assert len(httpmock.requests[MethodName.GET]) == 10
for request in httpmock.requests[MethodName.GET]:
self.assertRegex(request.headers.get("Accept"), "text/turtle")

request_paths = [request.path for request in httpmock.do_get_requests]
request_paths = [
request.path for request in httpmock.requests[MethodName.GET]
]
self.assertEqual(
request_paths,
[
Expand All @@ -211,12 +218,11 @@ def test_3xx(self) -> None:
)

def test_5xx(self):
httpmock = SimpleHTTPMock()
with ctx_http_server(httpmock.Handler) as server:
(host, port) = server.server_address
url = f"http://{host}:{port}/"
response = MockHTTPResponse(500, "Internal Server Error", "".encode(), {})
httpmock.do_get_responses.append(response)
with ServedBaseHTTPServerMock() as httpmock:
url = httpmock.url
httpmock.responses[MethodName.GET].append(
MockHTTPResponse(500, "Internal Server Error", "".encode(), {})
)

graph = Graph()

Expand Down
59 changes: 32 additions & 27 deletions test/test_store/test_store_sparqlstore.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
import socket
import unittest
from http.server import BaseHTTPRequestHandler, HTTPServer
from test.utils import MockHTTPResponse, ServedSimpleHTTPMock, helper
from test.utils import helper
from test.utils.httpservermock import (
MethodName,
MockHTTPResponse,
ServedBaseHTTPServerMock,
)
from threading import Thread
from typing import Callable, ClassVar, Type
from unittest.mock import patch
Expand Down Expand Up @@ -53,12 +58,12 @@ def test_graph_modify_fails(
class SPARQLStoreFakeDBPediaTestCase(unittest.TestCase):
store_name = "SPARQLStore"
path: ClassVar[str]
httpmock: ClassVar[ServedSimpleHTTPMock]
httpmock: ClassVar[ServedBaseHTTPServerMock]

@classmethod
def setUpClass(cls) -> None:
super().setUpClass()
cls.httpmock = ServedSimpleHTTPMock()
cls.httpmock = ServedBaseHTTPServerMock()
cls.path = f"{cls.httpmock.url}/sparql"

@classmethod
Expand All @@ -79,7 +84,7 @@ def tearDown(self):
def test_Query(self):
query = "select distinct ?Concept where {[] a ?Concept} LIMIT 1"
_query = SPARQLConnector.query
self.httpmock.do_get_responses.append(
self.httpmock.responses[MethodName.GET].append(
MockHTTPResponse(
200,
"OK",
Expand Down Expand Up @@ -116,8 +121,8 @@ def unpacker(query, default_graph=None, named_graph=None):
(mquery, _, _) = unpacker(*args, *kwargs)
for _, uri in self.graph.namespaces():
assert mquery.count(f"<{uri}>") == 1
self.assertEqual(self.httpmock.do_get_mock.call_count, 1)
req = self.httpmock.do_get_requests.pop(0)
self.assertEqual(self.httpmock.mocks[MethodName.GET].call_count, 1)
req = self.httpmock.requests[MethodName.GET].pop(0)
self.assertRegex(req.path, r"^/sparql")
self.assertIn(query, req.path_query["query"][0])

Expand All @@ -126,7 +131,7 @@ def test_initNs(self):
SELECT ?label WHERE
{ ?s a xyzzy:Concept ; xyzzy:prefLabel ?label . } LIMIT 10
"""
self.httpmock.do_get_responses.append(
self.httpmock.responses[MethodName.GET].append(
MockHTTPResponse(
200,
"OK",
Expand Down Expand Up @@ -179,8 +184,8 @@ def test_initNs(self):
for i in res:
assert type(i[0]) == Literal, i[0].n3()

self.assertEqual(self.httpmock.do_get_mock.call_count, 1)
req = self.httpmock.do_get_requests.pop(0)
self.assertEqual(self.httpmock.mocks[MethodName.GET].call_count, 1)
req = self.httpmock.requests[MethodName.GET].pop(0)
self.assertRegex(req.path, r"^/sparql")
self.assertIn(query, req.path_query["query"][0])

Expand All @@ -189,7 +194,7 @@ def test_noinitNs(self):
SELECT ?label WHERE
{ ?s a xyzzy:Concept ; xyzzy:prefLabel ?label . } LIMIT 10
"""
self.httpmock.do_get_responses.append(
self.httpmock.responses[MethodName.GET].append(
MockHTTPResponse(
400,
"Bad Request",
Expand All @@ -203,8 +208,8 @@ def test_noinitNs(self):
)
with self.assertRaises(ValueError):
self.graph.query(query)
self.assertEqual(self.httpmock.do_get_mock.call_count, 1)
req = self.httpmock.do_get_requests.pop(0)
self.assertEqual(self.httpmock.mocks[MethodName.GET].call_count, 1)
req = self.httpmock.requests[MethodName.GET].pop(0)
self.assertRegex(req.path, r"^/sparql")
self.assertIn(query, req.path_query["query"][0])

Expand All @@ -216,7 +221,7 @@ def test_query_with_added_prolog(self):
SELECT ?label WHERE
{ ?s a xyzzy:Concept ; xyzzy:prefLabel ?label . } LIMIT 10
"""
self.httpmock.do_get_responses.append(
self.httpmock.responses[MethodName.GET].append(
MockHTTPResponse(
200,
"OK",
Expand Down Expand Up @@ -266,8 +271,8 @@ def test_query_with_added_prolog(self):
res = helper.query_with_retry(self.graph, prologue + query)
for i in res:
assert type(i[0]) == Literal, i[0].n3()
self.assertEqual(self.httpmock.do_get_mock.call_count, 1)
req = self.httpmock.do_get_requests.pop(0)
self.assertEqual(self.httpmock.mocks[MethodName.GET].call_count, 1)
req = self.httpmock.requests[MethodName.GET].pop(0)
self.assertRegex(req.path, r"^/sparql")
self.assertIn(query, req.path_query["query"][0])

Expand All @@ -280,7 +285,7 @@ def test_query_with_added_rdf_prolog(self):
SELECT ?label WHERE
{ ?s a xyzzy:Concept ; xyzzy:prefLabel ?label . } LIMIT 10
"""
self.httpmock.do_get_responses.append(
self.httpmock.responses[MethodName.GET].append(
MockHTTPResponse(
200,
"OK",
Expand Down Expand Up @@ -330,8 +335,8 @@ def test_query_with_added_rdf_prolog(self):
res = helper.query_with_retry(self.graph, prologue + query)
for i in res:
assert type(i[0]) == Literal, i[0].n3()
self.assertEqual(self.httpmock.do_get_mock.call_count, 1)
req = self.httpmock.do_get_requests.pop(0)
self.assertEqual(self.httpmock.mocks[MethodName.GET].call_count, 1)
req = self.httpmock.requests[MethodName.GET].pop(0)
self.assertRegex(req.path, r"^/sparql")
self.assertIn(query, req.path_query["query"][0])

Expand Down Expand Up @@ -377,7 +382,7 @@ def test_counting_graph_and_store_queries(self):
{"Content-Type": ["application/sparql-results+xml; charset=UTF-8"]},
)

self.httpmock.do_get_responses.append(response)
self.httpmock.responses[MethodName.GET].append(response)

result = g.query(query)
for _ in result:
Expand All @@ -389,16 +394,16 @@ def test_counting_graph_and_store_queries(self):

st = SPARQLStore(query_endpoint=self.path)
count = 0
self.httpmock.do_get_responses.append(response)
self.httpmock.responses[MethodName.GET].append(response)
result = st.query(query)
for _ in result:
count += 1

assert count == 5, "SPARQLStore() didn't return 5 records"

self.assertEqual(self.httpmock.do_get_mock.call_count, 2)
self.assertEqual(self.httpmock.mocks[MethodName.GET].call_count, 2)
for _ in range(2):
req = self.httpmock.do_get_requests.pop(0)
req = self.httpmock.requests[MethodName.GET].pop(0)
self.assertRegex(req.path, r"^/sparql")
self.assertIn(query, req.path_query["query"][0])

Expand Down Expand Up @@ -514,8 +519,8 @@ def test_query(self):

assert len(list(graph.namespaces())) >= 4

with ServedSimpleHTTPMock() as httpmock:
httpmock.do_get_responses.append(response)
with ServedBaseHTTPServerMock() as httpmock:
httpmock.responses[MethodName.GET].append(response)
url = f"{httpmock.url}/query"
graph.open(url)
query_result = graph.query("SELECT ?s ?p ?o WHERE { ?s ?p ?o }")
Expand All @@ -525,9 +530,9 @@ def test_query(self):
for triple in triples:
assert triple in rows

httpmock.do_get_mock.assert_called_once()
assert len(httpmock.do_get_requests) == 1
request = httpmock.do_get_requests.pop()
httpmock.mocks[MethodName.GET].assert_called_once()
assert len(httpmock.requests[MethodName.GET]) == 1
request = httpmock.requests[MethodName.GET].pop()
assert len(request.path_query["query"]) == 1
query = request.path_query["query"][0]

Expand Down
14 changes: 9 additions & 5 deletions test/test_store/test_store_sparqlupdatestore_mock.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import unittest
from test.utils import MockHTTPResponse, ServedSimpleHTTPMock
from test.utils.httpservermock import (
MethodName,
MockHTTPResponse,
ServedBaseHTTPServerMock,
)
from typing import ClassVar

from rdflib import Namespace
Expand All @@ -13,12 +17,12 @@ class TestSPARQLConnector(unittest.TestCase):
query_endpoint: ClassVar[str]
update_path: ClassVar[str]
update_endpoint: ClassVar[str]
httpmock: ClassVar[ServedSimpleHTTPMock]
httpmock: ClassVar[ServedBaseHTTPServerMock]

@classmethod
def setUpClass(cls) -> None:
super().setUpClass()
cls.httpmock = ServedSimpleHTTPMock()
cls.httpmock = ServedBaseHTTPServerMock()
cls.query_path = "/db/sparql"
cls.query_endpoint = f"{cls.httpmock.url}{cls.query_path}"
cls.update_path = "/db/update"
Expand All @@ -40,7 +44,7 @@ def test_graph_update(self):
graph.open((self.query_endpoint, self.update_endpoint))
update_statement = f"INSERT DATA {{ {EG['subj']} {EG['pred']} {EG['obj']}. }}"

self.httpmock.do_post_responses.append(
self.httpmock.responses[MethodName.POST].append(
MockHTTPResponse(
200,
"OK",
Expand All @@ -54,6 +58,6 @@ def test_graph_update(self):
# to do updates.
graph.update(update_statement)
self.assertEqual(self.httpmock.call_count, 1)
req = self.httpmock.do_post_requests.pop(0)
req = self.httpmock.requests[MethodName.POST].pop(0)
self.assertEqual(req.parsed_path.path, self.update_path)
self.assertIn("application/sparql-update", req.headers.get("content-type"))