class UploadFileRequestHandlerInvalidSessionTest( tornado.testing.AsyncHTTPTestCase): """Tests the /upload_file endpoint.""" def get_app(self): self.file_mgr = UploadedFileManager() self._get_session_info = lambda x: None return tornado.web.Application([ ( UPLOAD_FILE_ROUTE, UploadFileRequestHandler, dict( file_mgr=self.file_mgr, get_session_info=self._get_session_info, ), ), ]) def _upload_files(self, params): # We use requests.Request to construct our multipart/form-data request # here, because they are absurdly fiddly to compose, and Tornado # doesn't include a utility for building them. We then use self.fetch() # to actually send the request to the test server. req = requests.Request(method="POST", url=self.get_url("/upload_file"), files=params).prepare() return self.fetch("/upload_file", method=req.method, headers=req.headers, body=req.body) def test_upload_one_file(self): """Upload should fail if the sessionId doesn't exist.""" file = MockFile("filename", b"123") params = { file.name: file.data, "sessionId": (None, "mockSessionId"), "widgetId": (None, "mockWidgetId"), } response = self._upload_files(params) self.assertEqual(400, response.code) self.assertIn("Invalid session_id: 'mockSessionId'", response.reason) self.assertEqual( self.file_mgr.get_all_files("mockSessionId", "mockWidgetId"), [])
class UploadedFileManagerTest(unittest.TestCase): def setUp(self): self.mgr = UploadedFileManager() self.filemgr_events = [] self.mgr.on_files_updated.connect(self._on_files_updated) def _on_files_updated(self, file_list, **kwargs): self.filemgr_events.append(file_list) def test_added_file_id(self): """An added file should have a unique ID.""" f1 = self.mgr.add_file("session", "widget", FILE_1) f2 = self.mgr.add_file("session", "widget", FILE_1) self.assertNotEqual(FILE_1.id, f1.id) self.assertNotEqual(f1.id, f2.id) def test_added_file_properties(self): """An added file should maintain all its source properties except its ID.""" added = self.mgr.add_file("session", "widget", FILE_1) self.assertNotEqual(added.id, FILE_1.id) self.assertEqual(added.name, FILE_1.name) self.assertEqual(added.type, FILE_1.type) self.assertEqual(added.data, FILE_1.data) def test_retrieve_added_file(self): """After adding a file to the mgr, we should be able to get it back.""" self.assertEqual([], self.mgr.get_all_files("non-report", "non-widget")) file_1 = self.mgr.add_file("session", "widget", FILE_1) self.assertEqual([file_1], self.mgr.get_all_files("session", "widget")) self.assertEqual([file_1], self.mgr.get_files("session", "widget", [file_1.id])) self.assertEqual(len(self.filemgr_events), 1) # Add another file file_2 = self.mgr.add_file("session", "widget", FILE_2) self.assertEqual([file_1, file_2], self.mgr.get_all_files("session", "widget")) self.assertEqual([file_1], self.mgr.get_files("session", "widget", [file_1.id])) self.assertEqual([file_2], self.mgr.get_files("session", "widget", [file_2.id])) self.assertEqual(len(self.filemgr_events), 2) def test_remove_file(self): # This should not error. self.mgr.remove_files("non-report", "non-widget") f1 = self.mgr.add_file("session", "widget", FILE_1) self.mgr.remove_file("session", "widget", f1.id) self.assertEqual([], self.mgr.get_all_files("session", "widget")) # Remove the file again. It doesn't exist, but this isn't an error. self.mgr.remove_file("session", "widget", f1.id) self.assertEqual([], self.mgr.get_all_files("session", "widget")) f1 = self.mgr.add_file("session", "widget", FILE_1) f2 = self.mgr.add_file("session", "widget", FILE_2) self.mgr.remove_file("session", "widget", f1.id) self.assertEqual([f2], self.mgr.get_all_files("session", "widget")) def test_remove_widget_files(self): # This should not error. self.mgr.remove_session_files("non-report") # Add two files with different session IDs, but the same widget ID. f1 = self.mgr.add_file("session1", "widget", FILE_1) f2 = self.mgr.add_file("session2", "widget", FILE_1) self.mgr.remove_files("session1", "widget") self.assertEqual([], self.mgr.get_all_files("session1", "widget")) self.assertEqual([f2], self.mgr.get_all_files("session2", "widget")) def test_remove_session_files(self): # This should not error. self.mgr.remove_session_files("non-report") # Add two files with different session IDs, but the same widget ID. f1 = self.mgr.add_file("session1", "widget1", FILE_1) f2 = self.mgr.add_file("session1", "widget2", FILE_1) f3 = self.mgr.add_file("session2", "widget", FILE_1) self.mgr.remove_session_files("session1") self.assertEqual([], self.mgr.get_all_files("session1", "widget1")) self.assertEqual([], self.mgr.get_all_files("session1", "widget2")) self.assertEqual([f3], self.mgr.get_all_files("session2", "widget")) def test_remove_orphaned_files(self): """Test the remove_orphaned_files behavior""" f1 = self.mgr.add_file("session1", "widget1", FILE_1) f2 = self.mgr.add_file("session1", "widget1", FILE_1) f3 = self.mgr.add_file("session1", "widget1", FILE_1) self.assertEqual([f1, f2, f3], self.mgr.get_all_files("session1", "widget1")) # Nothing should be removed here (all files are active). self.mgr.remove_orphaned_files( "session1", "widget1", newest_file_id=f3.id, active_file_ids=[f1.id, f2.id, f3.id], ) self.assertEqual([f1, f2, f3], self.mgr.get_all_files("session1", "widget1")) # Nothing should be removed here (no files are active, but they're all # "newer" than newest_file_id). self.mgr.remove_orphaned_files("session1", "widget1", newest_file_id=f1.id - 1, active_file_ids=[]) self.assertEqual([f1, f2, f3], self.mgr.get_all_files("session1", "widget1")) # f2 should be removed here (it's not in the active file list) self.mgr.remove_orphaned_files("session1", "widget1", newest_file_id=f3.id, active_file_ids=[f1.id, f3.id]) self.assertEqual([f1, f3], self.mgr.get_all_files("session1", "widget1")) # remove_orphaned_files on an untracked session/widget should not error self.mgr.remove_orphaned_files("no_session", "no_widget", newest_file_id=0, active_file_ids=[])
class UploadFileRequestHandlerTest(tornado.testing.AsyncHTTPTestCase): """Tests the /upload_file endpoint.""" def get_app(self): self.file_mgr = UploadedFileManager() self._get_session_info = lambda x: True return tornado.web.Application([ ( UPLOAD_FILE_ROUTE, UploadFileRequestHandler, dict( file_mgr=self.file_mgr, get_session_info=self._get_session_info, ), ), ]) def _upload_files(self, params): # We use requests.Request to construct our multipart/form-data request # here, because they are absurdly fiddly to compose, and Tornado # doesn't include a utility for building them. We then use self.fetch() # to actually send the request to the test server. req = requests.Request(method="POST", url=self.get_url("/upload_file"), files=params).prepare() return self.fetch("/upload_file", method=req.method, headers=req.headers, body=req.body) def test_upload_one_file(self): """Uploading a file should populate our file_mgr.""" file = MockFile("filename", b"123") params = { file.name: file.data, "sessionId": (None, "mockSessionId"), "widgetId": (None, "mockWidgetId"), } response = self._upload_files(params) self.assertEqual(200, response.code, response.reason) file_id = int(response.body) self.assertEqual( [(file_id, file.name, file.data)], [(rec.id, rec.name, rec.data) for rec in self.file_mgr.get_all_files("mockSessionId", "mockWidgetId")], ) def test_upload_multiple_files_error(self): """Uploading multiple files will error""" file_1 = MockFile("file1", b"123") file_2 = MockFile("file2", b"456") params = { file_1.name: file_1.data, file_2.name: file_2.data, "sessionId": (None, "mockSessionId"), "widgetId": (None, "mockWidgetId"), } response = self._upload_files(params) self.assertEqual(400, response.code) self.assertIn("Expected 1 file, but got 2", response.reason) def test_upload_missing_params_error(self): """Missing params in the body should fail with 400 status.""" params = { "image.png": ("image.png", b"1234"), "fileId": (None, "123"), "sessionId": (None, "mockSessionId"), # "widgetId": (None, 'mockWidgetId'), } response = self._upload_files(params) self.assertEqual(400, response.code) self.assertIn("Missing 'widgetId'", response.reason) def test_upload_missing_file_error(self): """Missing file should fail with 400 status.""" params = { # "image.png": ("image.png", b"1234"), "fileId": (None, "123"), "sessionId": (None, "mockSessionId"), "widgetId": (None, "mockWidgetId"), } response = self._upload_files(params) self.assertEqual(400, response.code) self.assertIn("Expected 1 file, but got 0", response.reason)