def test_call_valid_call(self): """Test a valid call, that should return.""" # Bug the user if the server isn't running self.read_session_from_file() try: result = core.call(self.SERVER_NAME, "+", [1, 2, 3]) except Exception as e: _raise_unexpected(e) eq_(result, 6)
def test_http_squatter(self): """Test what happens when the call contacts the wrong HTTP process. The cache may be out of date. Most of the time, it will point to a dead socket, which is easy to deal with. In rare cases, a different TCP process may have started on that socket. This test checks that the call can cope with a cache that points to a different HTTP server. A server like that will still respond to HTTP requests, so it needs to be handled differently to an arbitrary TCP process. """ # Load the actual server's info session = self.read_session_from_file() # We ensure the session was loaded assert "port" in session, session # Cache it core._cache_session(self.SERVER_NAME, session) # Use a different port to the NC test, in case the NC process didn't end. two_ports_down = session["port"] - 2 assert distutils.spawn.find_executable( "nc"), "Netcat is needed to test TCP clashes. Could not find `nc`." # Open a dummy netcat HTTP server on the next port down. It's possible # to get a port clash here - if we do, that's ok. It doesn't mean # `core.py` is broken, it just means we were unlucky. Re-run # the tests a few times until you hit a free pair. if sys.version_info >= (3, ): http_process = subprocess.Popen( ["python3", "-m", "http.server", "{}".format(two_ports_down)]) else: http_process = subprocess.Popen([ "python2", "-m", "SimpleHTTPServer", "{}".format(two_ports_down) ]) # Give it a bit to start (HTTP servers are slow to start. This is an # unreliable heuristic - bump the number up if it's failing.) time.sleep(0.5) # Make sure it's running assert _check_ping( two_ports_down), "The HTTP server didn't seem to start." try: # Now modify the cache to point to the bad HTTP process. It should # connect, return an error, then retry successfully from disk. core._server_info_cache[self.SERVER_NAME]["port"] = two_ports_down result = core.call(self.SERVER_NAME, "+", [1, 2, 3]) finally: # Clean up the nc process http_process.kill() eq_(result, 6)
def test_wrong_port_in_cache(self): """Test an out of date cache, in this case a wrong port.""" # First, ensure the info is cached. session = self.read_session_from_file() # We ensure the session was loaded assert "port" in session, session core._cache_session(self.SERVER_NAME, session) # Now modify the cache to be wrong. It should fail to connect, then # reload from disk. core._server_info_cache[self.SERVER_NAME]["port"] -= 1 try: result = core.call(self.SERVER_NAME, "+", [1, 2, 3]) except Exception as e: _raise_unexpected(e) eq_(result, 6)
def test_wrong_username_in_cache(self): """Test an out of date cache, in this case a wrong username. This is designed to test out-of-date credentials in general. Porthole authorization itself is tested in the Elisp package. """ # First, ensure the info is cached. session = core._session_from_file(self.SERVER_NAME) # We ensure the session was loaded assert "username" in session, session core._cache_session(self.SERVER_NAME, session) # Now modify the cache to be wrong. It should fail to connect, then # reload from disk. core._server_info_cache[self.SERVER_NAME]["username"] = "******" try: result = core.call(self.SERVER_NAME, "+", [1, 2, 3]) except Exception as e: _raise_unexpected(e) eq_(result, 6)
def test_tcp_squatter(self): """Test what happens when the call contacts the wrong HTTP process. The cache may be out of date. Most of the time, it will point to a dead socket, which is easy to deal with. In rare cases, a different TCP process may have started on that socket. This test checks that the call can cope with a cache that points to a different TCP process. The new process may respond with mangled information, or it may time out. Either way, the session should be re-read from disk, at which point it should succeed. """ # Load the actual server's info session = self.read_session_from_file() # We ensure the session was loaded assert "port" in session, session # Cache it core._cache_session(self.SERVER_NAME, session) one_port_down = session["port"] - 1 assert distutils.spawn.find_executable( "nc"), "Netcat is needed to test TCP clashes. Could not find `nc`." # Open a dummy netcat TCP process on the next port down. It's possible # to get a port clash here - if we do, that's ok. It doesn't mean # `core.py` is broken, it just means we were unlucky. Re-run # the tests a few times until you hit a free pair. nc_process = subprocess.Popen(["nc", "-l", "{}".format(one_port_down)]) # Give it a bit to start time.sleep(0.5) # Make sure it's running assert _check_ping( one_port_down), "The nc server didn't seem to start." try: # Now modify the cache to point to the NC process. It should # connect, then fail, then retry successfully from disk. core._server_info_cache[self.SERVER_NAME]["port"] = one_port_down result = core.call(self.SERVER_NAME, "+", [1, 2, 3]) finally: # Clean up the nc process nc_process.kill() eq_(result, 6)
def test_call_hidden_function(self): """Test that `call` correctly receives JSON-RPC error responses. Other JSON-RPC errors won't be prompted. This is fine. """ # Bug the user if the server isn't running self.read_session_from_file() try: # Do this call twice. First, check the exception, then check the # response structure. assert_raises( core.json_rpc.MethodNotExposedError, core.call, self.SERVER_NAME, "insert", ["this is some text"], ) result = core.call(self.SERVER_NAME, "insert", ["this is some text"]) raise ValueError("Should never get here. Result: {}").format( result) except json_rpc.MethodNotExposedError as e: json_response = e.raw_response assert isinstance(json_response, dict), json_response assert "jsonrpc" in json_response, json_response assert json_response["jsonrpc"] == "2.0", json_response assert "error" in json_response, json_response assert json_response["error"] == e.error, e error = e.error assert isinstance(error, dict), json_response assert "data" in error, json_response assert "code" in error, json_response assert error["code"], json_response except Exception as e: _raise_unexpected(e)