def test_CompilationHandler_compile__unexpected_exception_handling_upload_path_undeclared( self): handler = NonAbstractCompilationHandler(self.mock_language, self.mock_root_upload_path) mock_request = { "base_url": "http://127.0.0.1:8080", "path": "/api/test/compile/method", "data": { "code": (self.c_source_code_snippet_hello_c, ".././hello.c"), "compilation_options": '{}', }, } with self.assertLogs(app.logger, level="INFO") as logs_list: with app.test_request_context(**mock_request): response, response_status = handler.compile( request.files["code"], request.form["compilation_options"], store=True) self.assertEqual(response_status, 500) self.assertEqual(response.headers.get("Content-Type"), "application/json") self.assertEqual( response.response[0], b"{\"message\":\"Internal Unexpected Error\",\"type\":\"UnexpectedException\"}\n" ) root_upload_path_list = os.listdir(self.mock_root_upload_path) self.assertEqual( root_upload_path_list, [], msg="Path {path} is not empty: {root_upload_path_list}".format( path=self.mock_root_upload_path, root_upload_path_list=root_upload_path_list)) test_all_files = file_model.SourceCodeFile.get_all_files() self.assertEqual( test_all_files, [], msg="Table sourcecodefiles in DB is not empty: {files}".format( files=test_all_files)) self.assertEqual( len(logs_list.output), 3, msg="There are expected exactly 3 log messages: {logs_list}". format(logs_list=logs_list)) self.assertIn("ERROR:", logs_list.output[0]) self.assertIn("Unexpected error occured during compile()", logs_list.output[0]) self.assertIn("WARNING:", logs_list.output[1]) self.assertIn("Asserting that no orphaned directory is created...", logs_list.output[1]) self.assertIn("INFO:", logs_list.output[2]) self.assertIn("No orphaned directory is created", logs_list.output[2])
def test_authentication_authentication_required__authorization_header_missing( self): with app.test_request_context(): response = authentication.Authentication.authentication_required( self.dummy_function)(1) self.assertEqual(response._status, "401 UNAUTHORIZED") self.assertEqual(response.headers.get("Content-Type"), "application/json") self.assertEqual( response.headers.get("WWW-Authenticate"), "Bearer realm=\"Access to user specific resources\"") self.assertEqual( response.response[0], b'{"message":"Authorization Header is missing","type":"AuthorizationViolation"}\n' )
def test_authentication_authentication_required__authorized(self): mock_request_authorization_valid_token = { "headers": { "Authorization": "Bearer " + self.token_valid }, } with app.test_request_context( **mock_request_authorization_valid_token): result = authentication.Authentication.authentication_required( self.dummy_function)(1) self.assertEqual( result, "Real parameter is 1 but dummy_function always returns 42") self.assertEqual(g.user, {"id": self.decoded_token_valid})
def test_authentication_authentication_required__incorrect_shema(self): mock_request = {"headers": {"Authorization": "string_1 string_2"}} with app.test_request_context(**mock_request): response = authentication.Authentication.authentication_required( self.dummy_function)(1) self.assertEqual(response._status, "401 UNAUTHORIZED") self.assertEqual(response.headers.get("Content-Type"), "application/json") self.assertEqual( response.headers.get("WWW-Authenticate"), "Bearer realm=\"Access to user specific resources\"") self.assertEqual( response.response[0], '{"message":"Authorization Schema string_1 is incorrect","type":"AuthorizationSchemaViolation"}\n' .encode("utf-8"))
def test_CompilationHandler_compile__invalid_compilation_options(self): handler = MockedCompilationHandlerWStdout(self.mock_language, self.mock_root_upload_path) compilation_options_json_list = [ 'key: rue', '{', '{key: value}', '{"key": "value}', '{"key": v"alue}', '{"key": True}', '{"key": }', ] for compilation_options_json in compilation_options_json_list: mock_request = { "base_url": "http://127.0.0.1:8080", "path": "/api/test/compile/method", "data": { "code": (self.c_source_code_snippet_hello_c, "hello.c"), "compilation_options": compilation_options_json, }, } with self.assertLogs(app.logger, level="INFO") as logs_list: with app.test_request_context(**mock_request): response, response_status = handler.compile( request.files["code"], request.form["compilation_options"]) self.assertEqual(response_status, 400) self.assertEqual(response.headers.get("Content-Type"), "application/json") self.assertEqual( response.response[0], b"{\"message\":\"Bad JSON Format Error\",\"type\":\"JSONParseError\"}\n" ) self.assertEqual( len(logs_list.output), 1, msg="There are expected exactly 1 log messages: {logs_list}". format(logs_list=logs_list)) self.assertIn("INFO:", logs_list.output[0]) self.assertIn( "An error occured while loading incorrect compilation options json", logs_list.output[0])
def test_authentication_authentication_required__invalid_token(self): mock_request = { "headers": { "Authorization": "Bearer " + self.token_invalid } } with app.test_request_context(**mock_request): response = authentication.Authentication.authentication_required( self.dummy_function)(1) self.assertEqual(response._status, "401 UNAUTHORIZED") self.assertEqual(response.headers.get("Content-Type"), "application/json") self.assertEqual( response.headers.get("WWW-Authenticate"), "Bearer realm=\"Access to user specific resources\"") self.assertEqual( response.response[0], '{{"message":"{payload}","type":"AuthorizationJWTViolation"}}\n' .format(payload=self.decoded_token_invalid).encode("utf-8"))
def test_authentication_authentication_required__authorization_header_malformed( self): malformed_authorization_header_list = [ "", self.token_valid, "random_string", "Bearer", "Bearer" + self.token_valid, "Bearer ", "Bearer string_1 ", "Bearer string_1 string_2", "Bearer " + self.token_valid + " ", "Bearer " + self.token_valid + " " + self.token_valid, "Bearer Bearer Bearer", ] for malformed_authorization_header in malformed_authorization_header_list: mock_request = { "headers": { "Authorization": malformed_authorization_header } } with app.test_request_context(**mock_request): response = authentication.Authentication.authentication_required( self.dummy_function)(1) self.assertEqual(response._status, "401 UNAUTHORIZED") self.assertEqual(response.headers.get("Content-Type"), "application/json") self.assertEqual( response.headers.get("WWW-Authenticate"), "Bearer realm=\"Access to user specific resources\"") self.assertEqual( response.response[0], '{{"message":"Authorization Header {header} is incorrect","type":"AuthorizationViolation"}}\n' .format( header=malformed_authorization_header).encode("utf-8"))
def test_debug_request(self): mock_request = { "base_url": "https://127.0.0.1:8080", "path": "/api/test/debug_message", "method": "POST", "headers": { "Origin": "http://localhost:3535" }, "data": { "code": (io.BytesIO(b'this is some dummy test content'), 'test.txt'), "compilation_options": '{"optimization_level": "O2", "iso_standard": "gnu11", "suppress_warnings": true, "output_filename": "-----hello"}' }, } with app.test_request_context(**mock_request): debug_request_msg = common.debug_request(request) self.assertIn("<Request 'https://127.0.0.1:8080/api/test/debug_message' [POST]>", debug_request_msg) self.assertIn("Host: 127.0.0.1:8080", debug_request_msg) self.assertIn("Content-Type: multipart/form-data; boundary=", debug_request_msg) self.assertIn("Origin: http://localhost:3535", debug_request_msg) self.assertIn("ImmutableMultiDict([('code', <FileStorage: 'test.txt' ('text/plain')>)])", debug_request_msg) self.assertIn("ImmutableMultiDict([('compilation_options', '{\"optimization_level\": \"O2\", \"iso_standard\": \"gnu11\", \"suppress_warnings\": true, \"output_filename\": \"-----hello\"}')])", debug_request_msg) self.assertIn("None", debug_request_msg)
def test_CompilationHandler_compile__subpath_exists(self): handler = MockedCompilationHandlerWStdout(self.mock_language, self.mock_root_upload_path) existing_path = handler._format_full_file_path("unknown", "mock_subpath") os.makedirs(existing_path) mock_request = { "base_url": "http://127.0.0.1:8080", "path": "/api/test/compile/method", "data": { "code": (self.c_source_code_snippet_hello_c, "hello.c"), "compilation_options": '{}', }, } with self.assertLogs(app.logger, level="INFO") as logs_list: with app.test_request_context(**mock_request): response, response_status = handler.compile( request.files["code"], request.form["compilation_options"]) self.assertEqual(response_status, 400) self.assertEqual(response.headers.get("Content-Type"), "application/json") self.assertEqual( response.response[0], b"{\"message\":\"The uploaded file already exists\",\"type\":\"FileExistsError\"}\n" ) self.assertEqual( len(logs_list.output), 1, msg="There are expected exactly 1 log messages: {logs_list}". format(logs_list=logs_list)) self.assertIn("ERROR:", logs_list.output[0]) self.assertIn("Path exists: " + existing_path, logs_list.output[0])
def test_authentication_authentication_required__expired_token(self): mock_request = { "headers": { "Authorization": "Bearer " + self.token_expired } } with app.test_request_context(**mock_request): # Sleep is needed to make sure that the token is expired. # The token is instantly expired thus 1 second is enough. time.sleep(1) response = authentication.Authentication.authentication_required( self.dummy_function)(1) self.assertEqual(response._status, "401 UNAUTHORIZED") self.assertEqual(response.headers.get("Content-Type"), "application/json") self.assertEqual( response.headers.get("WWW-Authenticate"), "Bearer realm=\"Access to user specific resources\"") self.assertEqual( response.response[0], '{{"message":"{payload}","type":"AuthorizationJWTViolation"}}\n' .format(payload=self.decoded_token_expired).encode("utf-8"))
def test_CompilationHandler_compile__unexpected_exception_handling_upload_path_created( self): handler = NonAbstractCompilationHandler(self.mock_language, self.mock_root_upload_path) mock_request = { "base_url": "http://127.0.0.1:8080", "path": "/api/test/compile/method", "data": { "code": (self.c_source_code_snippet_hello_c, ".././hello.c"), "compilation_options": '{}', }, } with self.assertLogs(app.logger, level="INFO") as logs_list: with app.test_request_context(**mock_request): response, response_status = handler.compile( request.files["code"], request.form["compilation_options"]) self.assertEqual(response_status, 500) self.assertEqual(response.headers.get("Content-Type"), "application/json") self.assertEqual( response.response[0], b"{\"message\":\"Internal Unexpected Error\",\"type\":\"UnexpectedException\"}\n" ) root_upload_path_list = os.listdir(self.mock_root_upload_path) self.assertEqual( root_upload_path_list, ["unknown"], msg= "Path {path} does not contain only the unknown folder: {root_upload_path_list}" .format(path=self.mock_root_upload_path, root_upload_path_list=root_upload_path_list)) unknown_directory = self.mock_root_upload_path + "/unknown" unknown_directory_list = os.listdir(unknown_directory) self.assertEqual( unknown_directory_list, ["e17"], msg= "Path {path} does not contain only the e17 file directory: {entry_list}" .format(path=unknown_directory, entry_list=unknown_directory_list)) unknown_directory_level_1 = unknown_directory + "/e17" unknown_directory_level_1_list = os.listdir(unknown_directory_level_1) self.assertEqual(unknown_directory_level_1_list, [], msg="Path {path} is not empty: {entry_list}".format( path=unknown_directory_level_1, entry_list=unknown_directory_level_1_list)) test_all_files = file_model.SourceCodeFile.get_all_files() self.assertEqual( test_all_files, [], msg="Table sourcecodefiles in DB is not empty: {files}".format( files=test_all_files)) self.assertEqual( len(logs_list.output), 5, msg="There are expected exactly 5 log messages: {logs_list}". format(logs_list=logs_list)) self.assertIn("INFO:", logs_list.output[0]) self.assertIn("Path generated: ", logs_list.output[0]) generated_path = logs_list.output[0].split(" ")[2] self.assertIn("ERROR:", logs_list.output[1]) self.assertIn("Unexpected error occured during compile()", logs_list.output[1]) self.assertIn("WARNING:", logs_list.output[2]) self.assertIn("Asserting that no orphaned directory is created...", logs_list.output[2]) self.assertIn("WARNING:", logs_list.output[3]) self.assertIn( "Detected orphaned directory: {path}".format(path=generated_path), logs_list.output[3]) self.assertIn("INFO:", logs_list.output[4]) self.assertIn( "Orphaned directory deleted: {path}".format(path=generated_path), logs_list.output[4])
def test_CompilationHandler_compile__store_erroneous_command(self): handler = MockedCompilationHandlerWStderr(self.mock_language, self.mock_root_upload_path) mock_request = { "base_url": "http://127.0.0.1:8080", "path": "/api/test/compile/method", "data": { "code": (self.c_source_code_snippet_hello_c, ".././-h../ello.c"), "compilation_options": '{}', }, } with self.assertLogs(app.logger, level="INFO") as logs_list: with app.test_request_context(**mock_request): g.user = {"id": self.user_info["id"]} response = handler.compile(request.files["code"], request.form["compilation_options"], store=True) self.assertEqual(response._status, "400 BAD REQUEST") self.assertEqual(response.headers.get("Content-Type"), "application/zip") self.assertEqual(response.headers.get("Content-Disposition"), "attachment; filename=results.zip") root_upload_path_list = os.listdir(self.mock_root_upload_path) self.assertEqual( root_upload_path_list, [str(self.user_info["id"])], msg= "Path {path} does not contain only the {user_id} folder: {root_upload_path_list}" .format(path=self.mock_root_upload_path, user_id=self.user_info["id"], root_upload_path_list=root_upload_path_list)) user_directory = self.mock_root_upload_path + "/" + str( self.user_info["id"]) user_directory_list = os.listdir(user_directory) self.assertEqual( user_directory_list, ["ath"], msg= "Path {path} does not contain only the ath file directory: {entry_list}" .format(path=user_directory, entry_list=user_directory_list)) user_directory_level_1 = user_directory + "/ath" user_directory_level_1_list = os.listdir(user_directory_level_1) self.assertEqual( user_directory_level_1_list, ["mock_subpath"], msg= "Path {path} does not contain only the mock_subpath file directory: {entry_list}" .format(path=user_directory_level_1, entry_list=user_directory_level_1_list)) uploaded_file_directory = user_directory_level_1 + "/mock_subpath" uploaded_file_directory_list = sorted( os.listdir(uploaded_file_directory)) self.assertEqual( uploaded_file_directory_list, ["-h.._ello.c", "results.zip", "stderr.txt"], msg="Path {path} does not contain exactly 3 files: {entry_list}". format(path=uploaded_file_directory, entry_list=uploaded_file_directory_list)) self.assertTrue( filecmp.cmp(uploaded_file_directory + "/-h.._ello.c", self.c_source_code_snippet_hello_c)) with open(uploaded_file_directory + "/stderr.txt", "r") as stderr_file: self.assertEqual( stderr_file.read(), "ls: cannot access 'non-existing-path': No such file or directory\n\n" ) with ZipFile(file=uploaded_file_directory + "/results.zip", mode="r") as file_system_zip: self.assertIsNone(file_system_zip.testzip()) self.assertEqual(file_system_zip.namelist(), ["stderr.txt"]) file_system_zip_infolist = file_system_zip.infolist() self.assertEqual( os.stat(uploaded_file_directory + "/stderr.txt").st_size, file_system_zip_infolist[0].file_size) with ZipFile(response.response.file, 'r') as response_zip: self.assertIsNone(response_zip.testzip()) self.assertEqual(response_zip.namelist(), ["stderr.txt"]) response_zip_infolist = response_zip.infolist() self.assertEqual( file_system_zip_infolist[0].file_size, response_zip_infolist[0].file_size, msg= "STDERR files do not have the same size inside the two zip files" ) test_all_files = file_model.SourceCodeFile.get_all_files() self.assertEqual( len(test_all_files), 1, msg= "Table sourcecodefiles in DB does not contain exactly one file: {files}" .format(files=test_all_files)) test_file = test_all_files[0] self.assertEqual(test_file.user_id, self.user_info["id"]) self.assertEqual(test_file.name, "-h.._ello.c") self.assertEqual(test_file.directory, "mock_subpath") self.assertEqual(test_file.compilation_options, ["mock_option_1", "mock_option_2"]) self.assertEqual(test_file.language, self.mock_language) self.assertEqual(test_file.status, "Erroneous") self.assertEqual( len(logs_list.output), 3, msg="There are expected exactly 3 log messages: {logs_list}". format(logs_list=logs_list)) self.assertIn("INFO:", logs_list.output[0]) self.assertIn( "Path generated: {path}".format(path=uploaded_file_directory), logs_list.output[0]) self.assertIn("INFO:", logs_list.output[1]) self.assertIn( "Compilation return code in path {path}: 2".format( path=uploaded_file_directory), logs_list.output[1]) self.assertIn("INFO:", logs_list.output[2]) self.assertIn( "File in path {path} is saved in DB".format( path=uploaded_file_directory), logs_list.output[2])
def test_CompilationHandler_compile__with_stdout_and_stderr(self): handler = MockedCompilationHandlerWStdoutWStderr( self.mock_language, self.mock_root_upload_path) mock_request = { "base_url": "http://127.0.0.1:8080", "path": "/api/test/compile/method", "data": { "code": (self.c_source_code_snippet_hello_c, "hello.c"), "compilation_options": '{}', }, } with self.assertLogs(app.logger, level="INFO") as logs_list: with app.test_request_context(**mock_request): response = handler.compile(request.files["code"], request.form["compilation_options"]) self.assertEqual(response._status, "400 BAD REQUEST") self.assertEqual(response.headers.get("Content-Type"), "application/zip") self.assertEqual(response.headers.get("Content-Disposition"), "attachment; filename=results.zip") root_upload_path_list = os.listdir(self.mock_root_upload_path) self.assertEqual( root_upload_path_list, ["unknown"], msg= "Path {path} does not contain only the unknown folder: {root_upload_path_list}" .format(path=self.mock_root_upload_path, root_upload_path_list=root_upload_path_list)) unknown_directory = self.mock_root_upload_path + "/unknown" unknown_directory_list = os.listdir(unknown_directory) self.assertEqual( unknown_directory_list, ["ath"], msg= "Path {path} does not contain only the ath file directory: {entry_list}" .format(path=unknown_directory, entry_list=unknown_directory_list)) unknown_directory_level_1 = unknown_directory + "/ath" unknown_directory_level_1_list = os.listdir(unknown_directory_level_1) self.assertEqual( unknown_directory_level_1_list, ["mock_subpath"], msg= "Path {path} does not contain only the mock_subpath file directory: {entry_list}" .format(path=unknown_directory_level_1, entry_list=unknown_directory_level_1_list)) uploaded_file_directory = unknown_directory_level_1 + "/mock_subpath" uploaded_file_directory_list = sorted( os.listdir(uploaded_file_directory)) self.assertEqual( uploaded_file_directory_list, ["hello.c", "results.zip", "stderr.txt", "stdout.txt"], msg="Path {path} does not contain exactly 4 files: {entry_list}". format(path=uploaded_file_directory, entry_list=uploaded_file_directory_list)) self.assertTrue( filecmp.cmp(uploaded_file_directory + "/hello.c", self.c_source_code_snippet_hello_c)) with open(uploaded_file_directory + "/stdout.txt", "r") as stdout_file: self.assertEqual(stdout_file.read(), CURRENT_TEST_FILE_PATH + "\n\n") with open(uploaded_file_directory + "/stderr.txt", "r") as stderr_file: self.assertEqual( stderr_file.read(), "ls: cannot access 'non-existing-path': No such file or directory\n\n" ) with ZipFile(file=uploaded_file_directory + "/results.zip", mode="r") as file_system_zip: self.assertIsNone(file_system_zip.testzip()) self.assertEqual(file_system_zip.namelist(), ["stdout.txt", "stderr.txt"]) file_system_zip_infolist = file_system_zip.infolist() self.assertEqual( os.stat(uploaded_file_directory + "/stdout.txt").st_size, file_system_zip_infolist[0].file_size) self.assertEqual( os.stat(uploaded_file_directory + "/stderr.txt").st_size, file_system_zip_infolist[1].file_size) with ZipFile(response.response.file, 'r') as response_zip: self.assertIsNone(response_zip.testzip()) self.assertEqual(response_zip.namelist(), ["stdout.txt", "stderr.txt"]) response_zip_infolist = response_zip.infolist() self.assertEqual( file_system_zip_infolist[0].file_size, response_zip_infolist[0].file_size, msg= "STDOUT files do not have the same size inside the two zip files" ) self.assertEqual( file_system_zip_infolist[1].file_size, response_zip_infolist[1].file_size, msg= "STDERR files do not have the same size inside the two zip files" ) test_all_files = file_model.SourceCodeFile.get_all_files() self.assertEqual( test_all_files, [], msg="Table sourcecodefiles in DB is not empty: {files}".format( files=test_all_files)) self.assertEqual( len(logs_list.output), 2, msg="There are expected exactly 2 log messages: {logs_list}". format(logs_list=logs_list)) self.assertIn("INFO:", logs_list.output[0]) self.assertIn( "Path generated: {path}".format(path=uploaded_file_directory), logs_list.output[0]) self.assertIn("INFO:", logs_list.output[1]) self.assertIn( "Compilation return code in path {path}: 2".format( path=uploaded_file_directory), logs_list.output[1])