def connect_client(host, port, http, username, password): client = RpcClient(host, port) if http: client.enable_http() if username and password: client.enable_http_basic_auth(username, password) return client
def test_twisted_server_tls_cert_file_not_found(self): client = RpcClient('localhost', 5500) error = None with self.assertRaises(IOError) as cm: client.enable_tls('/file/that/does/not/exist') self.assertEqual(cm.exception.errno, errno.ENOENT) self.assertEqual(cm.exception.filename, '/file/that/does/not/exist')
def test_twisted_server_tls_non_tls_client_fail(self): server = ServerRunner('../examples/servertls.py', 5500) server.run() client = RpcClient('localhost', 5500) try: with self.assertRaises(NetworkError) as cm: client.rpc_call('echo', 'Hello Server') self.assertEqual(cm.exception.real_exception, "Non-JSON content received") finally: client.close_connection() server.stop()
def test_client_simple(self): server = FakeServer('localhost', 5500) server.add_reply('{"error": null, "result": "Hello Server", "id": 1}') server.run() client = RpcClient('localhost', 5500) try: result = client.rpc_call('echo', 'Hello Server') server.stop() request = server.requests.pop() expected = {'method': 'echo', 'params': ['Hello Server'], 'id': 1} self.assertEqual(json.loads(request), expected) self.assertEqual(result, 'Hello Server') finally: client.close_connection()
def test_twisted_server_http_basic_auth(self): server = ServerRunner('../examples/serverhttp_basic_auth.py', 5500) server.run() client = RpcClient('localhost', 5500) client.enable_http() client.enable_http_basic_auth('testuser', '123456') try: authenticated = client.rpc_call('is_authenticated') username = client.rpc_call('get_username') self.assertEqual(authenticated, True) self.assertEqual(username, 'testuser') finally: client.close_connection() server.stop()
def test_twisted_server_http_basic_auth_wrong_password(self): server = ServerRunner('../examples/serverhttp_basic_auth.py', 5500) server.run() client = RpcClient('localhost', 5500) client.enable_http() client.enable_http_basic_auth('testuser', 'wrongpassword') try: with self.assertRaises(HttpException) as cm: client.rpc_call('is_authenticated') self.assertEqual(cm.exception.message, "Expected status code '200' but got '401'") self.assertEqual(cm.exception.status, '401') finally: client.close_connection() server.stop()
def test_twisted_server_tls_client_auth_username(self): server = ServerRunner('../examples/servertls_clientauth.py', 5500) server.run() client = RpcClient('localhost', 5500) try: client.enable_tls('../examples/certs/rootCA.crt', False) client.enable_client_auth('../examples/certs/client.crt', '../examples/certs/client.key') authenticated = client.rpc_call('is_authenticated') username = client.rpc_call('get_username') self.assertEqual(authenticated, True) self.assertEqual(username, 'example-username') finally: client.close_connection() server.stop()
def test_twisted_server_tls_client_auth(self): server = ServerRunner('../examples/servertls_clientauth.py', 5500) server.run() client = RpcClient('localhost', 5500) try: client.enable_tls('../examples/certs/rootCA.crt', False) client.enable_client_auth('../examples/certs/client.crt', '../examples/certs/client.key') result = client.rpc_call('echo', 'Hello Server') self.assertEqual(result, "Hello Server") finally: client.close_connection() server.stop()
def test_concurrency_http(self): server = ServerRunner('../examples/concurrency-http.py', 5500) server.run() client1 = RpcClient('localhost', 5500) client1.enable_http() client2 = RpcClient('localhost', 5500) client2.enable_http() results = [] def t1_func(): result = client1.rpc_call('slow_operation') results.append(result) def t2_func(): time.sleep(0.5) result = client2.rpc_call('fast_operation') results.append(result) try: t1 = threading.Thread(target = t1_func, args = ()) t1.start() t2 = threading.Thread(target = t2_func, args = ()) t2.start() t1.join() if t1.is_alive(): raise RuntimeError("Failed to join on thread 1") t2.join() if t2.is_alive(): raise RuntimeError("Failed to join on thread 2") # slow_operation (value 42) must finish last self.assertEqual(results[0], 41) self.assertEqual(results[1], 42) finally: client1.close_connection() client2.close_connection() server.stop()
def test_twisted_server_tls_client_auth_wrong_client_cert(self): server = ServerRunner('../examples/servertls_clientauth.py', 5500) server.run() client = RpcClient('localhost', 5500) try: client.enable_tls('../examples/certs/rootCA.crt', False) client.enable_client_auth('../examples/certs/wrong-client.crt', '../examples/certs/wrong-client.key') with self.assertRaises(NetworkError) as cm: result = client.rpc_call('echo', 'Hello Server') self.assertTrue( 'alert decrypt error' in str(cm.exception.real_exception)) finally: client.close_connection() server.stop()
def test_concurrency_error_handling_http(self): server = ServerRunner('../examples/concurrency-http.py', 5500) server.run() client = RpcClient('localhost', 5500) client.enable_http() try: with self.assertRaises(RpcError) as cm: client.rpc_call('deferred_error') self.assertEqual(cm.exception.json['name'], "JsonRpcError") self.assertEqual(cm.exception.json['message'], "You wanted an error, here you have it!") with self.assertRaises(RpcError) as cm: result = client.rpc_call('deferred_internal_error') self.assertEqual(cm.exception.json['name'], "InternalError") self.assertEqual(cm.exception.json['message'], "Internal error") finally: client.close_connection() server.stop()
def test_twisted_server_http(self): server = ServerRunner('../examples/serverhttp.py', 5500) server.run() client = RpcClient('localhost', 5500) client.enable_http() try: result = client.rpc_call('echo', 'Hello Server') self.assertEqual(result, 'Hello Server') finally: client.close_connection() server.stop()
def test_twisted_server_tls_client_auth_wrong_client_cert(self): server = ServerRunner('../examples/servertls_clientauth.py', 5500) server.run() client = RpcClient('localhost', 5500) try: client.enable_tls('../examples/certs/rootCA.crt', False) client.enable_client_auth('../examples/certs/wrong-client.crt', '../examples/certs/wrong-client.key') with self.assertRaises(NetworkError) as cm: result = client.rpc_call('echo', 'Hello Server') self.assertTrue('alert decrypt error' in str(cm.exception.real_exception)) finally: client.close_connection() server.stop()
def test_client_http_invalid_answer(self): server = FakeServer('localhost', 5500) server.add_reply('{"error": null, "result": "Hello Server", "id": 1}') server.run() client = RpcClient('localhost', 5500) client.enable_http() try: with self.assertRaises(HttpException) as cm: client.rpc_call('echo', 'Hello Server') self.assertEqual( cm.exception.message, "Received invalid HTTP response: Couldn't find a HTTP header") server.stop() finally: client.close_connection()
def test_unix_socket(self): server = ServerRunner('../examples/serverunixsocket.py', '/tmp/reflectrpc.sock') server.run() client = RpcClient('unix:///tmp/reflectrpc.sock', 0) try: result = client.rpc_call('echo', 'Hello Server') client.close_connection() self.assertEqual(result, 'Hello Server') finally: client.close_connection() server.stop()
def test_client_http_invalid_answer(self): server = FakeServer('localhost', 5500) server.add_reply('{"error": null, "result": "Hello Server", "id": 1}') server.run() client = RpcClient('localhost', 5500) client.enable_http() try: with self.assertRaises(HttpException) as cm: client.rpc_call('echo', 'Hello Server') self.assertEqual(cm.exception.message, "Received invalid HTTP response: Couldn't find a HTTP header") server.stop() finally: client.close_connection()
def connect_client(parser, args): """ Create and connect an RpcClient object based on parsed command-line args Args: parser (argparse.Parser): Parser (only used for printing help in case of error) args (argparse.Namespace): Parsed command-line args Returns: reflectrpc.RpcClient: Connected RpcClient client """ client = RpcClient(args.host, args.port) if args.http: if args.http_path: client.enable_http(args.http_path) else: client.enable_http() if args.tls: client.enable_tls(args.ca, args.check_hostname) if args.cert or args.key: if not args.key: parser.print_help() print("--cert also requires --key\n") sys.exit(1) if not args.cert: parser.print_help() print("--key also requires --cert\n") sys.exit(1) if not args.ca: parser.print_help() print("Client auth requires --ca\n") sys.exit(1) client.enable_client_auth(args.cert, args.key) if args.http_basic_user: password = getpass.getpass() client.enable_http_basic_auth(args.http_basic_user, password) return client
def test_concurrency(self): server = ServerRunner('../examples/concurrency.py', 5500) server.run() client1 = RpcClient('localhost', 5500) client2 = RpcClient('localhost', 5500) results = [] def t1_func(): result = client1.rpc_call('slow_operation') results.append(result) def t2_func(): time.sleep(0.5) result = client2.rpc_call('fast_operation') results.append(result) try: t1 = threading.Thread(target=t1_func, args=()) t1.start() t2 = threading.Thread(target=t2_func, args=()) t2.start() t1.join() if t1.is_alive(): raise RuntimeError("Failed to join on thread 1") t2.join() if t2.is_alive(): raise RuntimeError("Failed to join on thread 2") # slow_operation (value 42) must finish last self.assertEqual(results[0], 41) self.assertEqual(results[1], 42) finally: client1.close_connection() client2.close_connection() server.stop()
def test_twisted_server_tls_hostname_check(self): server = ServerRunner('../examples/servertls.py', 5500) server.run() client = RpcClient('localhost', 5500) try: client.enable_tls('../examples/certs/rootCA.crt') with self.assertRaises(NetworkError) as cm: result = client.rpc_call('echo', 'Hello Server') self.assertEqual( str(cm.exception.real_exception), "TLSHostnameError: Host name 'localhost' doesn't match certificate host 'reflectrpc'" ) finally: client.close_connection() server.stop()
def test_twisted_server_tls_client_auth_no_client_cert(self): server = ServerRunner('../examples/servertls_clientauth.py', 5500) server.run() client = RpcClient('localhost', 5500) try: client.enable_tls('../examples/certs/rootCA.crt') with self.assertRaises(NetworkError) as cm: result = client.rpc_call('echo', 'Hello Server') python2_check = 'alert handshake failure' in str( cm.exception.real_exception) python3_check = str(cm.exception.real_exception).startswith( "[SSL: SSLV3_ALERT_HANDSHAKE_FAILURE]") self.assertTrue(python2_check or python3_check) finally: client.close_connection() server.stop()
def test_twisted_server_tls_server_check(self): server = ServerRunner('../examples/servertls.py', 5500) server.run() client = RpcClient('localhost', 5500) try: client.enable_tls('../examples/certs/wrongCA.crt') with self.assertRaises(NetworkError) as cm: result = client.rpc_call('echo', 'Hello Server') python2_check = str( cm.exception.real_exception).startswith('[Errno 1]') python3_check = str(cm.exception.real_exception).startswith( '[SSL: CERTIFICATE_VERIFY_FAILED]') self.assertTrue(python2_check or python3_check) finally: client.close_connection() server.stop()
def test_twisted_server_tls_hostname_check(self): server = ServerRunner('../examples/servertls.py', 5500) server.run() client = RpcClient('localhost', 5500) try: client.enable_tls('../examples/certs/rootCA.crt') with self.assertRaises(NetworkError) as cm: result = client.rpc_call('echo', 'Hello Server') self.assertEqual(str(cm.exception.real_exception), "TLSHostnameError: Host name 'localhost' doesn't match certificate host 'reflectrpc'") finally: client.close_connection() server.stop()
def test_twisted_server_tls_client_auth_no_client_cert(self): server = ServerRunner('../examples/servertls_clientauth.py', 5500) server.run() client = RpcClient('localhost', 5500) try: client.enable_tls('../examples/certs/rootCA.crt') with self.assertRaises(NetworkError) as cm: result = client.rpc_call('echo', 'Hello Server') python2_check = 'alert handshake failure' in str(cm.exception.real_exception) python3_check = str(cm.exception.real_exception).startswith( "[SSL: SSLV3_ALERT_HANDSHAKE_FAILURE]") self.assertTrue(python2_check or python3_check) finally: client.close_connection() server.stop()
def test_twisted_server_tls_server_check(self): server = ServerRunner('../examples/servertls.py', 5500) server.run() client = RpcClient('localhost', 5500) try: client.enable_tls('../examples/certs/wrongCA.crt') with self.assertRaises(NetworkError) as cm: result = client.rpc_call('echo', 'Hello Server') python2_check = str(cm.exception.real_exception).startswith( '[Errno 1]') python3_check = str(cm.exception.real_exception).startswith( '[SSL: CERTIFICATE_VERIFY_FAILED]') self.assertTrue(python2_check or python3_check) finally: client.close_connection() server.stop()
def test_conformance(self): global server_program funcs_description = [{'description': 'Returns the message it was sent', 'name': 'echo', 'params': [{'description': 'The message we will send back', 'name': 'message', 'type': 'string'}], 'result_desc': 'The message previously received', 'result_type': 'string'}, {'description': 'Adds two numbers', 'name': 'add', 'params': [{'description': 'First number to add', 'name': 'a', 'type': 'int'}, {'description': 'Second number to add', 'name': 'b', 'type': 'int'}], 'result_desc': 'Sum of the two numbers', 'result_type': 'int'}, {'description': 'Subtracts one number from another', 'name': 'sub', 'params': [{'description': 'Number to subtract from', 'name': 'a', 'type': 'int'}, {'description': 'Number to subtract', 'name': 'b', 'type': 'int'}], 'result_desc': 'Difference of the two numbers', 'result_type': 'int'}, {'description': 'Multiplies two numbers', 'name': 'mul', 'params': [{'description': 'First factor', 'name': 'a', 'type': 'int'}, {'description': 'Second factor', 'name': 'b', 'type': 'int'}], 'result_desc': 'Product of the two numbers', 'result_type': 'int'}, {'description': 'Divide a number by another number', 'name': 'div', 'params': [{'description': 'Dividend', 'name': 'a', 'type': 'float'}, {'description': 'Divisor', 'name': 'b', 'type': 'float'}], 'result_desc': 'Ratio of the two numbers', 'result_type': 'float'}, {'description': 'Test the phone type enum', 'name': 'enum_echo', 'params': [{'description': 'Type of phone number', 'name': 'phone_type', 'type': 'PhoneType'}], 'result_desc': 'Phone type', 'result_type': 'int'}, {'description': 'Test the address hash type', 'name': 'hash_echo', 'params': [{'description': 'Address hash', 'name': 'address', 'type': 'Address'}], 'result_desc': 'Address hash', 'result_type': 'hash'}, {'description': 'Test function for notify requests', 'name': 'notify', 'params': [{'description': 'A value to print on the server side', 'name': 'value', 'type': 'string'}], 'result_desc': '', 'result_type': 'bool'}, {'description': 'Checks if we have an authenticated connection', 'name': 'is_authenticated', 'params': [], 'result_desc': 'The authentication status', 'result_type': 'bool'}, {'description': 'Gets the username of the logged in user', 'name': 'get_username', 'params': [], 'result_desc': 'The username of the logged in user', 'result_type': 'string'}] types_description = [{'description': 'Type of a phone number', 'name': 'PhoneType', 'type': 'enum', 'values': [{'description': 'Home phone', 'intvalue': 0, 'name': 'HOME'}, {'description': 'Work phone', 'intvalue': 1, 'name': 'WORK'}, {'description': 'Mobile phone', 'intvalue': 2, 'name': 'MOBILE'}, {'description': 'FAX number', 'intvalue': 3, 'name': 'FAX'}]}, {'description': 'Street address', 'fields': [{'description': 'First name', 'name': 'firstname', 'type': 'string'}, {'description': 'Last name', 'name': 'lastname', 'type': 'string'}, {'description': 'First address line', 'name': 'street1', 'type': 'string'}, {'description': 'Second address line', 'name': 'street2', 'type': 'string'}, {'description': 'Zip code', 'name': 'zipcode', 'type': 'string'}, {'description': 'City', 'name': 'city', 'type': 'string'}], 'name': 'Address', 'type': 'hash'}] tests = [ ['{"method": "echo", "params": ["Hello Server"], "id": 1}', '{"result": "Hello Server", "error": null, "id": 1}'], ['{"method": "add", "params": [5, 6], "id": 2}', '{"result": 11, "error": null, "id": 2}'], # test non-int IDs ['{"method": "echo", "params": ["Hello"], "id": "abcd1234"}', '{"result": "Hello", "error": null, "id": "abcd1234"}'], ['{"method": "add", "params": [34, 67], "id": 3.14}', '{"result": 101, "error": null, "id": 3.14}'], # test descriptions ['{"method": "__describe_service", "params": [], "id": 3}', '{"result": {"version": "1.0", "name": "Example RPC Service", "description": "This is an example service for ReflectRPC", "custom_fields": {}}, "error": null, "id": 3}'], ['{"method": "__describe_functions", "params": [], "id": 4}', '{"result": %s, "error": null, "id": 4}' % (json.dumps(funcs_description))], ['{"method": "__describe_custom_types", "params": [], "id": 5}', '{"result": %s, "error": null, "id": 5}' % (json.dumps(types_description))] ] server = ServerRunner(server_program, 5500) server.run() client = RpcClient('localhost', 5500) self.maxDiff = None request = None expected_result = None result_str = None i = 0 try: for test in tests: i += 1 request = test[0] expected_result = json.loads(test[1]) result_str = client.rpc_call_raw(request) result_dict = json.loads(result_str) self.assertEqual(result_dict, expected_result) except AssertionError as e: print("Test number %d failed: " % (i)) print(request) raise e finally: server.stop()
import sys import time import unittest from reflectrpc.client import RpcClient from reflectrpc.testing import ServerRunner parser = argparse.ArgumentParser( description="ReflectRPC benchmark to run against a server program that listens on localhost:5500") args = parser.parse_args() # reset argv so unittest.main() does not try to interpret our arguments sys.argv = [sys.argv[0]] client = RpcClient('localhost', 5500) # ensure we are alread connected when the benchmark starts client.rpc_call_raw('{"method": "echo", "params": ["Hello Server"], "id": 1}') millis_start = int(round(time.time() * 1000)) num_requests = 5000 for i in range(num_requests): result = client.rpc_call_raw('{"method": "echo", "params": ["Hello Server"], "id": 1}') millis_stop = int(round(time.time() * 1000)) millis_spent = millis_stop - millis_start print("Requests: %d" % (num_requests)) print("Time: %d ms" % (millis_spent))
import unittest from reflectrpc.client import RpcClient from reflectrpc.testing import ServerRunner parser = argparse.ArgumentParser( description= "ReflectRPC benchmark to run against a server program that listens on localhost:5500" ) args = parser.parse_args() # reset argv so unittest.main() does not try to interpret our arguments sys.argv = [sys.argv[0]] client = RpcClient('localhost', 5500) # ensure we are alread connected when the benchmark starts client.rpc_call_raw('{"method": "echo", "params": ["Hello Server"], "id": 1}') millis_start = int(round(time.time() * 1000)) num_requests = 5000 for i in range(num_requests): result = client.rpc_call_raw( '{"method": "echo", "params": ["Hello Server"], "id": 1}') millis_stop = int(round(time.time() * 1000)) millis_spent = millis_stop - millis_start print("Requests: %d" % (num_requests))