diff --git a/setup.py b/setup.py index cdd445ef..cea61f20 100644 --- a/setup.py +++ b/setup.py @@ -64,8 +64,9 @@ def read(path): ] }, extras_require=dict( - test=['zope.testing', - 'zc.customdoctests>=1.0.1'], + test=['zope.testing>=4,<5', + 'zc.customdoctests>=1.0.1,<2', + 'stopit>=1.1.2,<2'], sqlalchemy=['sqlalchemy>=1.0,<1.4', 'geojson>=2.5.0'] ), python_requires='>=3.4', diff --git a/src/crate/client/http.py b/src/crate/client/http.py index 1f81c631..02aa80bd 100644 --- a/src/crate/client/http.py +++ b/src/crate/client/http.py @@ -544,8 +544,8 @@ def _get_server(self): (ts, server, message)) else: self._active_servers.append(server) - logger.warn("Restored server %s into active pool", - server) + logger.warning("Restored server %s into active pool", + server) # if none is old enough, use oldest if not self._active_servers: diff --git a/src/crate/client/tests.py b/src/crate/client/tests.py index 2a4cc61c..574f1a7e 100644 --- a/src/crate/client/tests.py +++ b/src/crate/client/tests.py @@ -23,6 +23,7 @@ import json import os +import socket import unittest import doctest from pprint import pprint @@ -33,6 +34,8 @@ import threading import logging +import stopit + from crate.testing.layer import CrateLayer from crate.testing.tests import crate_path, docs_path from crate.client import connect @@ -108,15 +111,35 @@ def setUpMocked(test): crate_port = 44209 crate_transport_port = 44309 local = '127.0.0.1' -crate_layer = CrateLayer('crate', - crate_home=crate_path(), - port=crate_port, - host=local, - transport_port=crate_transport_port, - settings=settings) - crate_host = "{host}:{port}".format(host=local, port=crate_port) crate_uri = "http://%s" % crate_host +crate_layer = None + + +def ensure_cratedb_layer(): + """ + In order to skip individual tests by manually disabling them within + `def test_suite()`, it is crucial make the test layer not run on each + and every occasion. So, things like this will be possible:: + + ./bin/test -vvvv --ignore_dir=testing + + TODO: Through a subsequent patch, the possibility to individually + unselect specific tests might be added to `def test_suite()` + on behalf of environment variables. + A blueprint for this kind of logic can be found at + https://github.com/crate/crate/commit/414cd833. + """ + global crate_layer + + if crate_layer is None: + crate_layer = CrateLayer('crate', + crate_home=crate_path(), + port=crate_port, + host=local, + transport_port=crate_transport_port, + settings=settings) + return crate_layer def refresh(table): @@ -207,7 +230,7 @@ class Location(Base): test.globs['CrateDialect'] = CrateDialect -class HttpsTestServerLayer(object): +class HttpsTestServerLayer: PORT = 65534 HOST = "localhost" CERT_FILE = os.path.abspath(os.path.join(os.path.dirname(__file__), @@ -235,11 +258,11 @@ class HttpsHandler(BaseHTTPRequestHandler): def do_GET(self): self.send_response(200) - self.send_header("Content-Length", len(self.payload)) + payload = self.payload.encode('UTF-8') + self.send_header("Content-Length", len(payload)) self.send_header("Content-Type", "application/json; charset=UTF-8") self.end_headers() - self.wfile.write(self.payload.encode('UTF-8')) - return + self.wfile.write(payload) def __init__(self): self.server = self.HttpsServer( @@ -251,7 +274,7 @@ def setUp(self): thread = threading.Thread(target=self.serve_forever) thread.daemon = True # quit interpreter when only thread exists thread.start() - time.sleep(1) + self.waitForServer() def serve_forever(self): print("listening on", self.HOST, self.PORT) @@ -261,6 +284,29 @@ def serve_forever(self): def tearDown(self): self.server.shutdown() + def isUp(self): + """ + Test if a host is up. + """ + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + ex = s.connect_ex((self.HOST, self.PORT)) + s.close() + return ex == 0 + + def waitForServer(self, timeout=5): + """ + Wait for the host to be available. + """ + with stopit.ThreadingTimeout(timeout) as to_ctx_mgr: + while True: + if self.isUp(): + break + time.sleep(0.001) + + if not to_ctx_mgr: + raise TimeoutError("Could not properly start embedded webserver " + "within {} seconds".format(timeout)) + def setUpWithHttps(test): test.globs['HttpClient'] = http.Client @@ -348,7 +394,7 @@ def test_suite(): optionflags=flags, encoding='utf-8' ) - s.layer = crate_layer + s.layer = ensure_cratedb_layer() suite.addTest(s) s = doctest.DocFileSuite( @@ -362,7 +408,7 @@ def test_suite(): optionflags=flags, encoding='utf-8' ) - s.layer = crate_layer + s.layer = ensure_cratedb_layer() suite.addTest(s) s = doctest.DocFileSuite( @@ -372,7 +418,7 @@ def test_suite(): optionflags=flags, encoding='utf-8' ) - s.layer = crate_layer + s.layer = ensure_cratedb_layer() suite.addTest(s) return suite diff --git a/versions.cfg b/versions.cfg index 1ff59bf6..cd8759f6 100644 --- a/versions.cfg +++ b/versions.cfg @@ -24,6 +24,7 @@ zc.customdoctests = 1.0.1 zc.recipe.egg = 2.0.7 zc.recipe.testrunner = 2.2 zope.testing = 4.9 +stopit = 1.1.2 # Required by: # clint==0.5.1