class TestEndpointsHandlerWithAuth(AsyncHTTPTestCase): @classmethod def setUpClass(cls): prefix = "__TestEndpointsHandlerWithAuth_" # create password file cls.pwd_file = tempfile.NamedTemporaryFile(mode="w+t", prefix=prefix, suffix=".txt", delete=False) username = "******" password = "******" cls.pwd_file.write(f"{username} {hash_password(username, password)}") cls.pwd_file.close() # create state.ini dir and file cls.state_dir = tempfile.mkdtemp(prefix=prefix) cls.state_file = open(os.path.join(cls.state_dir, "state.ini"), "w+") cls.state_file.write("[Service Info]\n" "Name = TabPy Serve\n" "Description = \n" "Creation Time = 0\n" "Access-Control-Allow-Origin = \n" "Access-Control-Allow-Headers = \n" "Access-Control-Allow-Methods = \n" "\n" "[Query Objects Service Versions]\n" "\n" "[Query Objects Docstrings]\n" "\n" "[Meta]\n" "Revision Number = 1\n") cls.state_file.close() # create config file cls.config_file = tempfile.NamedTemporaryFile(mode="w+t", prefix=prefix, suffix=".conf", delete=False) cls.config_file.write("[TabPy]\n" f"TABPY_PWD_FILE = {cls.pwd_file.name}\n" f"TABPY_STATE_PATH = {cls.state_dir}") cls.config_file.close() @classmethod def tearDownClass(cls): os.remove(cls.pwd_file.name) os.remove(cls.state_file.name) os.remove(cls.config_file.name) os.rmdir(cls.state_dir) def get_app(self): self.app = TabPyApp(self.config_file.name) return self.app._create_tornado_web_app() def test_no_creds_required_auth_fails(self): response = self.fetch("/endpoints") self.assertEqual(401, response.code) def test_invalid_creds_fails(self): response = self.fetch( "/endpoints", method="GET", headers={ "Authorization": "Basic {}".format( base64.b64encode( "user:wrong_password".encode("utf-8")).decode("utf-8")) }, ) self.assertEqual(401, response.code) def test_valid_creds_pass(self): response = self.fetch( "/endpoints", method="GET", headers={ "Authorization": "Basic {}".format( base64.b64encode( "username:password".encode("utf-8")).decode("utf-8")) }, ) self.assertEqual(200, response.code)
def get_app(self): if hasattr(self, 'config_file') and hasattr(self.config_file, 'name'): self.app = TabPyApp(self.config_file.name) else: self.app = TabPyApp() return self.app._create_tornado_web_app()
def get_app(self): self.app = TabPyApp(None) return self.app._create_tornado_web_app()
def get_app(self): self.app = TabPyApp(self.config_file.name) return self.app._create_tornado_web_app()
class TestServiceInfoHandlerWithAuth(AsyncHTTPTestCase): @classmethod def setUpClass(cls): prefix = "__TestServiceInfoHandlerWithAuth_" # create password file cls.pwd_file = tempfile.NamedTemporaryFile(prefix=prefix, suffix=".txt", delete=False) cls.pwd_file.write(b"username password") cls.pwd_file.close() # create state.ini dir and file cls.state_dir = tempfile.mkdtemp(prefix=prefix) cls.state_file = open(os.path.join(cls.state_dir, "state.ini"), "w+") cls.state_file.write("[Service Info]\n" "Name = TabPy Serve\n" "Description = \n" "Creation Time = 0\n" "Access-Control-Allow-Origin = \n" "Access-Control-Allow-Headers = \n" "Access-Control-Allow-Methods = \n" "\n" "[Query Objects Service Versions]\n" "\n" "[Query Objects Docstrings]\n" "\n" "[Meta]\n" "Revision Number = 1\n") cls.state_file.close() # create config file cls.config_file = tempfile.NamedTemporaryFile(prefix=prefix, suffix=".conf", delete=False) cls.config_file.write( bytes( "[TabPy]\n" f"TABPY_PWD_FILE = {cls.pwd_file.name}\n" f"TABPY_STATE_PATH = {cls.state_dir}", "utf-8", )) cls.config_file.close() @classmethod def tearDownClass(cls): os.remove(cls.pwd_file.name) os.remove(cls.state_file.name) os.remove(cls.config_file.name) os.rmdir(cls.state_dir) def get_app(self): self.app = TabPyApp(self.config_file.name) return self.app._create_tornado_web_app() def test_given_tabpy_server_with_auth_expect_correct_info_response(self): response = self.fetch("/info") self.assertEqual(response.code, 200) actual_response = json.loads(response.body) expected_response = _create_expected_info_response( self.app.settings, self.app.tabpy_state) self.assertDictEqual(actual_response, expected_response) self.assertTrue("versions" in actual_response) versions = actual_response["versions"] self.assertTrue("v1" in versions) v1 = versions["v1"] self.assertTrue("features" in v1) features = v1["features"] self.assertDictEqual( { "authentication": { "methods": { "basic-auth": {} }, "required": True } }, features, )
class TestEvaluationPlainHandlerWithAuth(AsyncHTTPTestCase): @classmethod def setUpClass(cls): cls.patcher = patch( "tabpy.tabpy_server.app.app.TabPyApp._parse_cli_arguments", return_value=Namespace(config=None), ) cls.patcher.start() prefix = "__TestEvaluationPlainHandlerWithAuth_" # create password file cls.pwd_file = tempfile.NamedTemporaryFile( mode="w+t", prefix=prefix, suffix=".txt", delete=False ) username = "******" password = "******" cls.pwd_file.write(f"{username} {hash_password(username, password)}\n") cls.pwd_file.close() # create state.ini dir and file cls.state_dir = tempfile.mkdtemp(prefix=prefix) cls.state_file = open(os.path.join(cls.state_dir, "state.ini"), "w+") cls.state_file.write( "[Service Info]\n" "Name = TabPy Serve\n" "Description = \n" "Creation Time = 0\n" "Access-Control-Allow-Origin = \n" "Access-Control-Allow-Headers = \n" "Access-Control-Allow-Methods = \n" "\n" "[Query Objects Service Versions]\n" "\n" "[Query Objects Docstrings]\n" "\n" "[Meta]\n" "Revision Number = 1\n" ) cls.state_file.close() # create config file cls.config_file = tempfile.NamedTemporaryFile( mode="w+t", prefix=prefix, suffix=".conf", delete=False ) cls.config_file.write( "[TabPy]\n" f"TABPY_PWD_FILE = {cls.pwd_file.name}\n" f"TABPY_STATE_PATH = {cls.state_dir}" ) cls.config_file.close() cls.script = ( '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},' '"script":"res=[]\\nfor i in range(len(_arg1)):\\n ' 'res.append(_arg1[i] * _arg2[i])\\nreturn res"}' ) cls.script_not_present = ( '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},' '"":"res=[]\\nfor i in range(len(_arg1)):\\n ' 'res.append(_arg1[i] * _arg2[i])\\nreturn res"}' ) cls.args_not_present = ( '{"script":"res=[]\\nfor i in range(len(_arg1)):\\n ' 'res.append(_arg1[i] * _arg2[i])\\nreturn res"}' ) cls.args_not_sequential = ( '{"data":{"_arg1":[2,3],"_arg3":[3,-1]},' '"script":"res=[]\\nfor i in range(len(_arg1)):\\n ' 'res.append(_arg1[i] * _arg3[i])\\nreturn res"}' ) cls.nan_coverts_to_null =\ '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},'\ '"script":"return [float(1), float(\\"NaN\\"), float(2)]"}' cls.script_returns_none = ( '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},' '"script":"return None"}' ) @classmethod def tearDownClass(cls): cls.patcher.stop() os.remove(cls.pwd_file.name) os.remove(cls.state_file.name) os.remove(cls.config_file.name) os.rmdir(cls.state_dir) def get_app(self): self.app = TabPyApp(self.config_file.name) return self.app._create_tornado_web_app() def test_no_creds_required_auth_fails(self): response = self.fetch("/evaluate", method="POST", body=self.script) self.assertEqual(401, response.code) def test_invalid_creds_fails(self): response = self.fetch( "/evaluate", method="POST", body=self.script, headers={ "Authorization": "Basic {}".format( base64.b64encode("user:wrong_password".encode("utf-8")).decode( "utf-8" ) ) }, ) self.assertEqual(401, response.code) def test_valid_creds_pass(self): response = self.fetch( "/evaluate", method="POST", body=self.script, headers={ "Authorization": "Basic {}".format( base64.b64encode("username:password".encode("utf-8")).decode( "utf-8" ) ) }, ) self.assertEqual(200, response.code) def test_null_request(self): response = self.fetch("") self.assertEqual(404, response.code) def test_script_not_present(self): response = self.fetch( "/evaluate", method="POST", body=self.script_not_present, headers={ "Authorization": "Basic {}".format( base64.b64encode("username:password".encode("utf-8")).decode( "utf-8" ) ) }, ) self.assertEqual(400, response.code) def test_arguments_not_present(self): response = self.fetch( "/evaluate", method="POST", body=self.args_not_present, headers={ "Authorization": "Basic {}".format( base64.b64encode("username:password".encode("utf-8")).decode( "utf-8" ) ) }, ) self.assertEqual(500, response.code) def test_arguments_not_sequential(self): response = self.fetch( "/evaluate", method="POST", body=self.args_not_sequential, headers={ "Authorization": "Basic {}".format( base64.b64encode("username:password".encode("utf-8")).decode( "utf-8" ) ) }, ) self.assertEqual(400, response.code) def test_nan_converts_to_null(self): response = self.fetch( '/evaluate', method='POST', body=self.nan_coverts_to_null, headers={ 'Authorization': 'Basic {}'. format( base64.b64encode('username:password'.encode('utf-8')). decode('utf-8')) }) self.assertEqual(200, response.code) self.assertEqual(b'[1.0, null, 2.0]', response.body) def test_script_returns_none(self): response = self.fetch( '/evaluate', method='POST', body=self.script_returns_none, headers={ 'Authorization': 'Basic {}'. format( base64.b64encode('username:password'.encode('utf-8')). decode('utf-8')) }) self.assertEqual(200, response.code) self.assertEqual(b'null', response.body)
def assertTabPyAppRaisesRuntimeError(self, expected_message): with self.assertRaises(RuntimeError) as err: TabPyApp(self.fp.name) self.assertEqual(err.exception.args[0], expected_message)
def test_http(self): self.fp.write("[TabPy]\n" "TABPY_TRANSFER_PROTOCOL = http") self.fp.close() app = TabPyApp(self.fp.name) self.assertEqual(app.settings["transfer_protocol"], "http")
class TestEvaluationPlaneHandlerWithoutAuth(AsyncHTTPTestCase): @classmethod def setUpClass(cls): prefix = "__TestEvaluationPlaneHandlerWithoutAuth_" # create state.ini dir and file cls.state_dir = tempfile.mkdtemp(prefix=prefix) cls.state_file = open(os.path.join(cls.state_dir, "state.ini"), "w+") cls.state_file.write( "[Service Info]\n" "Name = TabPy Serve\n" "Description = \n" "Creation Time = 0\n" "Access-Control-Allow-Origin = \n" "Access-Control-Allow-Headers = \n" "Access-Control-Allow-Methods = \n" "\n" "[Query Objects Service Versions]\n" "\n" "[Query Objects Docstrings]\n" "\n" "[Meta]\n" "Revision Number = 1\n" ) cls.state_file.close() cls.script = ( '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},' '"script":"res=[]\\nfor i in range(len(_arg1)):\\n ' 'res.append(_arg1[i] * _arg2[i])\\nreturn res"}' ) cls.script_not_present = ( '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},' '"":"res=[]\\nfor i in range(len(_arg1)):\\n ' 'res.append(_arg1[i] * _arg2[i])\\nreturn res"}' ) cls.args_not_present = ( '{"script":"res=[]\\nfor i in range(len(_arg1)):\\n ' 'res.append(_arg1[i] * _arg2[i])\\nreturn res"}' ) cls.args_not_sequential = ( '{"data":{"_arg1":[2,3],"_arg3":[3,-1]},' '"script":"res=[]\\nfor i in range(len(_arg1)):\\n ' 'res.append(_arg1[i] * _arg3[i])\\nreturn res"}' ) cls.nan_coverts_to_null =\ '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},'\ '"script":"return [float(1), float(\\"NaN\\"), float(2)]"}' cls.script_returns_none = ( '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},' '"script":"return None"}' ) @classmethod def tearDownClass(cls): os.remove(cls.state_file.name) os.rmdir(cls.state_dir) def get_app(self): self.app = TabPyApp(None) return self.app._create_tornado_web_app() def test_creds_no_auth_fails(self): response = self.fetch( "/evaluate", method="POST", body=self.script, headers={ "Authorization": "Basic {}".format( base64.b64encode("username:password".encode("utf-8")).decode( "utf-8" ) ) }, ) self.assertEqual(406, response.code)
class TestEvaluationPlaneHandlerDisabledWithAuth(AsyncHTTPTestCase): @classmethod def setUpClass(cls): prefix = "__TestEvaluationPlaneHandlerDisabledWithAuth_" # create password file cls.pwd_file = tempfile.NamedTemporaryFile( mode="w+t", prefix=prefix, suffix=".txt", delete=False ) username = "******" password = "******" cls.pwd_file.write(f"{username} {hash_password(username, password)}\n") cls.pwd_file.close() # create state.ini dir and file cls.state_dir = tempfile.mkdtemp(prefix=prefix) cls.state_file = open(os.path.join(cls.state_dir, "state.ini"), "w+") cls.state_file.write( "[Service Info]\n" "Name = TabPy Serve\n" "Description = \n" "Creation Time = 0\n" "Access-Control-Allow-Origin = \n" "Access-Control-Allow-Headers = \n" "Access-Control-Allow-Methods = \n" "\n" "[Query Objects Service Versions]\n" "\n" "[Query Objects Docstrings]\n" "\n" "[Meta]\n" "Revision Number = 1\n" ) cls.state_file.close() # create config file cls.config_file = tempfile.NamedTemporaryFile( mode="w+t", prefix=prefix, suffix=".conf", delete=False ) cls.config_file.write( "[TabPy]\n" f"TABPY_PWD_FILE = {cls.pwd_file.name}\n" f"TABPY_STATE_PATH = {cls.state_dir}\n" f"TABPY_EVALUATE_ENABLE = false" ) cls.config_file.close() cls.script = ( '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},' '"script":"res=[]\\nfor i in range(len(_arg1)):\\n ' 'res.append(_arg1[i] * _arg2[i])\\nreturn res"}' ) @classmethod def tearDownClass(cls): os.remove(cls.pwd_file.name) os.remove(cls.state_file.name) os.remove(cls.config_file.name) os.rmdir(cls.state_dir) def get_app(self): self.app = TabPyApp(self.config_file.name) return self.app._create_tornado_web_app() def test_evaluation_disabled_fails_with_invalid_creds(self): response = self.fetch( "/evaluate", method="POST", body=self.script, headers={ "Authorization": "Basic {}".format( base64.b64encode("user:wrong_password".encode("utf-8")).decode( "utf-8" ) ) }, ) self.assertEqual(401, response.code) def test_evaluation_disabled_fails_with_valid_creds(self): response = self.fetch( "/evaluate", method="POST", body=self.script, headers={ "Authorization": "Basic {}".format( base64.b64encode("username:password".encode("utf-8")).decode( "utf-8" ) ) }, ) self.assertEqual(404, response.code)
def main(): from tabpy.tabpy_server.app.app import TabPyApp app = TabPyApp() app.run()
class TestServiceInfoHandlerWithAuth(AsyncHTTPTestCase): @classmethod def setUpClass(cls): prefix = '__TestServiceInfoHandlerWithAuth_' # create password file cls.pwd_file = tempfile.NamedTemporaryFile(prefix=prefix, suffix='.txt', delete=False) cls.pwd_file.write(b'username password') cls.pwd_file.close() # create state.ini dir and file cls.state_dir = tempfile.mkdtemp(prefix=prefix) cls.state_file = open(os.path.join(cls.state_dir, 'state.ini'), 'w+') cls.state_file.write('[Service Info]\n' 'Name = TabPy Serve\n' 'Description = \n' 'Creation Time = 0\n' 'Access-Control-Allow-Origin = \n' 'Access-Control-Allow-Headers = \n' 'Access-Control-Allow-Methods = \n' '\n' '[Query Objects Service Versions]\n' '\n' '[Query Objects Docstrings]\n' '\n' '[Meta]\n' 'Revision Number = 1\n') cls.state_file.close() # create config file cls.config_file = tempfile.NamedTemporaryFile(prefix=prefix, suffix='.conf', delete=False) cls.config_file.write( bytes( '[TabPy]\n' f'TABPY_PWD_FILE = {cls.pwd_file.name}\n' f'TABPY_STATE_PATH = {cls.state_dir}', 'utf-8')) cls.config_file.close() @classmethod def tearDownClass(cls): os.remove(cls.pwd_file.name) os.remove(cls.state_file.name) os.remove(cls.config_file.name) os.rmdir(cls.state_dir) def get_app(self): self.app = TabPyApp(self.config_file.name) return self.app._create_tornado_web_app() def test_given_tabpy_server_with_auth_expect_correct_info_response(self): response = self.fetch('/info') self.assertEqual(response.code, 200) actual_response = json.loads(response.body) expected_response = _create_expected_info_response( self.app.settings, self.app.tabpy_state) self.assertDictEqual(actual_response, expected_response) self.assertTrue('versions' in actual_response) versions = actual_response['versions'] self.assertTrue('v1' in versions) v1 = versions['v1'] self.assertTrue('features' in v1) features = v1['features'] self.assertDictEqual( { 'authentication': { 'methods': { 'basic-auth': {} }, 'required': True, } }, features)
def test_no_state_ini_file_or_state_dir(self, mock_os, mock_path_exists, mock_psws, mock_management_util, mock_tabpy_state, mock_parse_arguments): TabPyApp(None) self.assertEqual(len(mock_os.makedirs.mock_calls), 1)
class TestEndpointHandlerWithAuth(AsyncHTTPTestCase): @classmethod def setUpClass(cls): cls.patcher = patch( 'tabpy.tabpy_server.app.app.TabPyApp._parse_cli_arguments', return_value=Namespace(config=None)) cls.patcher.start() prefix = '__TestEndpointHandlerWithAuth_' # create password file cls.pwd_file = tempfile.NamedTemporaryFile(mode='w+t', prefix=prefix, suffix='.txt', delete=False) username = '******' password = '******' cls.pwd_file.write(f'{username} {hash_password(username, password)}') cls.pwd_file.close() # create state.ini dir and file cls.state_dir = tempfile.mkdtemp(prefix=prefix) cls.state_file = open(os.path.join(cls.state_dir, 'state.ini'), 'w+') cls.state_file.write('[Service Info]\n' 'Name = TabPy Serve\n' 'Description = \n' 'Creation Time = 0\n' 'Access-Control-Allow-Origin = \n' 'Access-Control-Allow-Headers = \n' 'Access-Control-Allow-Methods = \n' '\n' '[Query Objects Service Versions]\n' '\n' '[Query Objects Docstrings]\n' '\n' '[Meta]\n' 'Revision Number = 1\n') cls.state_file.close() # create config file cls.config_file = tempfile.NamedTemporaryFile(mode='w+t', prefix=prefix, suffix='.conf', delete=False) cls.config_file.write('[TabPy]\n' f'TABPY_PWD_FILE = {cls.pwd_file.name}\n' f'TABPY_STATE_PATH = {cls.state_dir}') cls.config_file.close() @classmethod def tearDownClass(cls): cls.patcher.stop() os.remove(cls.pwd_file.name) os.remove(cls.state_file.name) os.remove(cls.config_file.name) os.rmdir(cls.state_dir) def get_app(self): self.app = TabPyApp(self.config_file.name) return self.app._create_tornado_web_app() def test_no_creds_required_auth_fails(self): response = self.fetch('/endpoints/anything') self.assertEqual(401, response.code) def test_invalid_creds_fails(self): response = self.fetch( '/endpoints/anything', method='GET', headers={ 'Authorization': 'Basic {}'.format( base64.b64encode( 'user:wrong_password'.encode('utf-8')).decode('utf-8')) }) self.assertEqual(401, response.code) def test_valid_creds_pass(self): response = self.fetch( '/endpoints/', method='GET', headers={ 'Authorization': 'Basic {}'.format( base64.b64encode( 'username:password'.encode('utf-8')).decode('utf-8')) }) self.assertEqual(200, response.code) def test_valid_creds_unknown_endpoint_fails(self): response = self.fetch( '/endpoints/unknown_endpoint', method='GET', headers={ 'Authorization': 'Basic {}'.format( base64.b64encode( 'username:password'.encode('utf-8')).decode('utf-8')) }) self.assertEqual(404, response.code)
class TestEvaluationPlainHandlerWithAuth(AsyncHTTPTestCase): @classmethod def setUpClass(cls): cls.patcher = patch( 'tabpy.tabpy_server.app.app.TabPyApp._parse_cli_arguments', return_value=Namespace( config=None)) cls.patcher.start() prefix = '__TestEvaluationPlainHandlerWithAuth_' # create password file cls.pwd_file = tempfile.NamedTemporaryFile( mode='w+t', prefix=prefix, suffix='.txt', delete=False) username = '******' password = '******' cls.pwd_file.write(f'{username} {hash_password(username, password)}\n') cls.pwd_file.close() # create state.ini dir and file cls.state_dir = tempfile.mkdtemp(prefix=prefix) cls.state_file = open(os.path.join(cls.state_dir, 'state.ini'), 'w+') cls.state_file.write('[Service Info]\n' 'Name = TabPy Serve\n' 'Description = \n' 'Creation Time = 0\n' 'Access-Control-Allow-Origin = \n' 'Access-Control-Allow-Headers = \n' 'Access-Control-Allow-Methods = \n' '\n' '[Query Objects Service Versions]\n' '\n' '[Query Objects Docstrings]\n' '\n' '[Meta]\n' 'Revision Number = 1\n') cls.state_file.close() # create config file cls.config_file = tempfile.NamedTemporaryFile( mode='w+t', prefix=prefix, suffix='.conf', delete=False) cls.config_file.write( '[TabPy]\n' f'TABPY_PWD_FILE = {cls.pwd_file.name}\n' f'TABPY_STATE_PATH = {cls.state_dir}') cls.config_file.close() cls.script =\ '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},'\ '"script":"res=[]\\nfor i in range(len(_arg1)):\\n '\ 'res.append(_arg1[i] * _arg2[i])\\nreturn res"}' cls.script_not_present =\ '{"data":{"_arg1":[2,3],"_arg2":[3,-1]},'\ '"":"res=[]\\nfor i in range(len(_arg1)):\\n '\ 'res.append(_arg1[i] * _arg2[i])\\nreturn res"}' cls.args_not_present =\ '{"script":"res=[]\\nfor i in range(len(_arg1)):\\n '\ 'res.append(_arg1[i] * _arg2[i])\\nreturn res"}' cls.args_not_sequential =\ '{"data":{"_arg1":[2,3],"_arg3":[3,-1]},'\ '"script":"res=[]\\nfor i in range(len(_arg1)):\\n '\ 'res.append(_arg1[i] * _arg3[i])\\nreturn res"}' @classmethod def tearDownClass(cls): cls.patcher.stop() os.remove(cls.pwd_file.name) os.remove(cls.state_file.name) os.remove(cls.config_file.name) os.rmdir(cls.state_dir) def get_app(self): self.app = TabPyApp(self.config_file.name) return self.app._create_tornado_web_app() def test_no_creds_required_auth_fails(self): response = self.fetch( '/evaluate', method='POST', body=self.script) self.assertEqual(401, response.code) def test_invalid_creds_fails(self): response = self.fetch( '/evaluate', method='POST', body=self.script, headers={ 'Authorization': 'Basic {}'. format( base64.b64encode('user:wrong_password'.encode('utf-8')). decode('utf-8')) }) self.assertEqual(401, response.code) def test_valid_creds_pass(self): response = self.fetch( '/evaluate', method='POST', body=self.script, headers={ 'Authorization': 'Basic {}'. format( base64.b64encode('username:password'.encode('utf-8')). decode('utf-8')) }) self.assertEqual(200, response.code) def test_null_request(self): response = self.fetch('') self.assertEqual(404, response.code) def test_script_not_present(self): response = self.fetch( '/evaluate', method='POST', body=self.script_not_present, headers={ 'Authorization': 'Basic {}'. format( base64.b64encode('username:password'.encode('utf-8')). decode('utf-8')) }) self.assertEqual(400, response.code) def test_arguments_not_present(self): response = self.fetch( '/evaluate', method='POST', body=self.args_not_present, headers={ 'Authorization': 'Basic {}'. format( base64.b64encode('username:password'.encode('utf-8')). decode('utf-8')) }) self.assertEqual(500, response.code) def test_arguments_not_sequential(self): response = self.fetch( '/evaluate', method='POST', body=self.args_not_sequential, headers={ 'Authorization': 'Basic {}'. format( base64.b64encode('username:password'.encode('utf-8')). decode('utf-8')) }) self.assertEqual(400, response.code)