devserver: Tests for CherryPy zero-port extensions.
This adds both unit tests, as well as extending integration tests, to
ensure that our CherryPy extensions module (cherrypy_ext) works as
intended.
BUG=chromium:322436
TEST=Unit + integration tests pass.
Change-Id: I93221d11d855cd4d78d39e34e587b5b24e9eb4d1
Reviewed-on: https://chromium-review.googlesource.com/186848
Tested-by: Gilad Arnold <garnold@chromium.org>
Reviewed-by: Chris Sosa <sosa@chromium.org>
Commit-Queue: Gilad Arnold <garnold@chromium.org>
diff --git a/devserver_integration_test.py b/devserver_integration_test.py
index 3dbddb6..755f2ce 100755
--- a/devserver_integration_test.py
+++ b/devserver_integration_test.py
@@ -26,6 +26,7 @@
import psutil
import shutil
import signal
+import socket
import subprocess
import tempfile
import time
@@ -66,6 +67,7 @@
DEVSERVER_START_TIMEOUT = 15
DEVSERVER_START_SLEEP = 1
+MAX_START_ATTEMPTS = 5
class DevserverFailedToStart(Exception):
@@ -286,6 +288,32 @@
self._StartServer()
+class DevserverStartTests(DevserverTestBase):
+ """Test that devserver starts up correctly."""
+
+ def testStartAnyPort(self):
+ """Starts the devserver, have it bind to an arbitrary available port."""
+ self._StartServer()
+
+ def testStartSpecificPort(self):
+ """Starts the devserver with a specific port."""
+ for _ in range(MAX_START_ATTEMPTS):
+ # This is a cheap hack to find an arbitrary unused port: we open a socket
+ # and bind it to port zero, then pull out the actual port number and
+ # close the socket. In all likelihood, this will leave us with an
+ # available port number that we can use for starting the devserver.
+ # However, this heuristic is susceptible to race conditions, hence the
+ # retry loop.
+ s = socket.socket()
+ s.bind(('', 0))
+ # s.getsockname() is definitely callable.
+ # pylint: disable=E1102
+ _, port = s.getsockname()
+ s.close()
+
+ self._StartServer(port=port)
+
+
class DevserverBasicTests(AutoStartDevserverTestBase):
"""Short running tests for the devserver (no remote deps).