class TestEvaluationPlaneHandlerDefault(AsyncHTTPTestCase): @classmethod def setUpClass(cls): prefix = "__TestEvaluationPlaneHandlerDefault_" # create config file cls.config_file = tempfile.NamedTemporaryFile( mode="w+t", prefix=prefix, suffix=".conf", delete=False ) cls.config_file.write( "[TabPy]" ) 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.config_file.name) def get_app(self): self.app = TabPyApp(self.config_file.name) return self.app._create_tornado_web_app() def test_evaluation_default(self): response = self.fetch( "/evaluate", method="POST", body=self.script ) self.assertEqual(200, response.code)
class TestServiceInfoHandlerDefault(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() @classmethod def tearDownClass(cls): cls.patcher.stop() def get_app(self): self.app = TabPyApp() return self.app._create_tornado_web_app() def test_given_vanilla_tabpy_server_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)
class TestServiceInfoHandlerWithoutAuth(AsyncHTTPTestCase): @classmethod def setUpClass(cls): prefix = "__TestServiceInfoHandlerWithoutAuth_" # create state.ini dir and file cls.state_dir = tempfile.mkdtemp(prefix=prefix) with open(os.path.join(cls.state_dir, "state.ini"), "w+") as cls.state_file: 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, mode="w+") cls.config_file.write("[TabPy]\n" f"TABPY_STATE_PATH = {cls.state_dir}") cls.config_file.close() @classmethod def tearDownClass(cls): 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_tabpy_server_with_no_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({}, features)
class TestServiceInfoHandlerWithoutAuth(AsyncHTTPTestCase): @classmethod def setUpClass(cls): prefix = '__TestServiceInfoHandlerWithoutAuth_' # create state.ini dir and file cls.state_dir = tempfile.mkdtemp(prefix=prefix) with open(os.path.join(cls.state_dir, 'state.ini'), 'w+')\ as cls.state_file: 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, mode='w+') cls.config_file.write('[TabPy]\n' f'TABPY_STATE_PATH = {cls.state_dir}') cls.config_file.close() @classmethod def tearDownClass(cls): 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_tabpy_server_with_no_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({}, features)
class TestServiceInfoHandlerDefault(AsyncHTTPTestCase): def get_app(self): self.app = TabPyApp() return self.app._create_tornado_web_app() def test_given_vanilla_tabpy_server_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)
class TestEndpointHandlerWithoutAuth(AsyncHTTPTestCase): @classmethod def setUpClass(cls): _init_asyncio_patch() prefix = "__TestEndpointHandlerWithoutAuth_" # 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() @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( "/endpoints/", method="GET", headers={ "Authorization": "Basic {}".format( base64.b64encode("username:password".encode("utf-8")).decode( "utf-8" ) ) }, ) self.assertEqual(400, response.code)
class BaseTestServiceInfoHandler(AsyncHTTPTestCase): 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() @classmethod def tearDownClass(cls): os.remove(cls.state_file.name) os.remove(cls.config_file.name) os.rmdir(cls.state_dir) @classmethod def setUpClass(cls): # create state.ini dir and file cls.state_dir = tempfile.mkdtemp(prefix=cls.prefix) with open(os.path.join(cls.state_dir, "state.ini"), "w+") as cls.state_file: 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=cls.prefix, suffix=".conf", delete=False, mode='w') cls.config_file.write("[TabPy]\n") if hasattr(cls, 'tabpy_config'): for k in cls.tabpy_config: cls.config_file.write(k) cls.config_file.close()
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)
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)
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)
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 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)