class UploadedFileManagerTest(unittest.TestCase): def setUp(self): self.mgr = UploadedFileManager() self.filemgr_events = [] self.mgr.on_files_added.connect(self._on_files_added) def _on_files_added(self, file_list, **kwargs): self.filemgr_events.append(file_list) def test_add_file(self): self.assertIsNone(self.mgr.get_files("non-report", "non-widget")) event1 = UploadedFileList("session", "widget", [file1]) event2 = UploadedFileList("session", "widget", [file2]) self.mgr.add_files("session", "widget", [file1]) self.assertEqual([file1], self.mgr.get_files("session", "widget")) self.assertEqual([event1], self.filemgr_events) # Add another file with the same ID self.mgr.add_files("session", "widget", [file2]) self.assertEqual([file2], self.mgr.get_files("session", "widget")) self.assertEqual([event1, event2], self.filemgr_events) def test_remove_file(self): # This should not error. self.mgr.remove_files("non-report", "non-widget") self.mgr.add_files("session", "widget", [file1]) self.assertEqual([file1], self.mgr.get_files("session", "widget")) self.mgr.remove_files("session", "widget") self.assertIsNone(self.mgr.get_files("session", "widget")) def test_remove_all_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. self.mgr.add_files("session1", "widget", [file1]) self.mgr.add_files("session2", "widget", [file1]) event1 = UploadedFileList("session1", "widget", [file1]) event2 = UploadedFileList("session2", "widget", [file1]) self.mgr.remove_session_files("session1") self.assertIsNone(self.mgr.get_files("session1", "widget")) self.assertEqual([file1], self.mgr.get_files("session2", "widget")) self.assertEqual([event1, event2], self.filemgr_events)
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, "fooReport"), "widgetId": (None, "barWidget"), "totalFiles": (None, "1"), } response = self._upload_files(params) self.assertEqual(200, response.code) self.assertEqual( [(file.name, file.data)], [(rec.name, rec.data) for rec in self.file_mgr.get_files("fooReport", "barWidget")], ) def test_upload_multiple_files(self): file_1 = MockFile("file1", b"123") file_2 = MockFile("file2", b"456") file_3 = MockFile("file3", b"789") params = { file_1.name: file_1.data, file_2.name: file_2.data, file_3.name: file_3.data, "sessionId": (None, "fooReport"), "widgetId": (None, "barWidget"), "totalFiles": (None, "1"), } response = self._upload_files(params) self.assertEqual(200, response.code) self.assertEqual( sorted([file_1, file_2, file_3]), sorted([ (rec.name, rec.data) for rec in self.file_mgr.get_files("fooReport", "barWidget") ]), ) def test_upload_missing_params(self): """Missing params in the body should fail with 400 status.""" params = { "image.png": ("image.png", b"1234"), "sessionId": (None, "fooReport"), # "widgetId": (None, 'barWidget'), "totalFiles": (None, "1"), } response = self._upload_files(params) self.assertEqual(400, response.code) self.assertIn("Missing 'widgetId'", response.reason) def test_upload_missing_file(self): """Missing file should fail with 400 status.""" params = { # "image.png": ("image.png", b"1234"), "sessionId": (None, "fooReport"), "widgetId": (None, "barWidget"), "totalFiles": (None, "1"), } response = self._upload_files(params) self.assertEqual(400, response.code) self.assertIn("Expected at least 1 file, but got 0", response.reason) def test_delete_file(self): """File should be able to be deleted successfully""" file1 = UploadedFileRec("1234", "name", "type", b"1234") file2 = UploadedFileRec("4567", "name", "type", b"1234") self.file_mgr.add_files("session1", "widget1", [file1]) self.file_mgr.add_files("session2", "widget2", [file2]) response = self.fetch(f"/upload_file/session1/widget1/1234", method="DELETE") self.assertEqual(200, response.code) self.assertFalse(len(self.file_mgr.get_files("session1", "widget1"))) self.assertTrue(len(self.file_mgr.get_files("session2", "widget2"))) def test_delete_file_across_sessions(self): """Deleting file param mismatch should fail with 404 status.""" file1 = UploadedFileRec("1234", "name", "type", b"1234") file2 = UploadedFileRec("4567", "name", "type", b"1234") self.file_mgr.add_files("session1", "widget1", [file1]) self.file_mgr.add_files("session2", "widget2", [file2]) response = self.fetch(f"/upload_file/session2/widget1/1234", method="DELETE") self.assertEqual(404, response.code) self.assertTrue(len(self.file_mgr.get_files("session1", "widget1"))) self.assertTrue(len(self.file_mgr.get_files("session2", "widget2"))) @parameterized.expand([ (None, "widget_id", "123"), ("session_id", None, "123"), ("session_id", "widget_id", None), ]) def test_delete_missing_param(self, session_id, widget_id, file_id): """Missing param should fail with 404 status.""" response = self.fetch( f"/upload_file/{session_id}/{widget_id}/{file_id}", method="DELETE") self.assertEqual(404, response.code)
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): """Uploading a file should populate our file_mgr.""" file = MockFile("filename", b"123") params = { file.name: file.data, "sessionId": (None, "fooReport"), "widgetId": (None, "barWidget"), "totalFiles": (None, "1"), } response = self._upload_files(params) self.assertEqual(400, response.code) self.assertIsNone(self.file_mgr.get_files("fooReport", "barWidget")) def test_upload_multiple_files(self): file_1 = MockFile("file1", b"123") file_2 = MockFile("file2", b"456") file_3 = MockFile("file3", b"789") params = { file_1.name: file_1.data, file_2.name: file_2.data, file_3.name: file_3.data, "sessionId": (None, "fooReport"), "widgetId": (None, "barWidget"), "totalFiles": (None, "1"), } response = self._upload_files(params) self.assertEqual(400, response.code) self.assertIsNone(self.file_mgr.get_files("fooReport", "barWidget")) def test_delete_file(self): """File should be able to be deleted successfully""" file1 = UploadedFileRec("1234", "name", "type", b"1234") file2 = UploadedFileRec("4567", "name", "type", b"1234") self.file_mgr.add_files("session1", "widget1", [file1]) self.file_mgr.add_files("session2", "widget2", [file2]) response = self.fetch(f"/upload_file/session1/widget1/1234", method="DELETE") self.assertEqual(404, response.code)
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() return tornado.web.Application([("/upload_file", UploadFileRequestHandler, dict(file_mgr=self.file_mgr))]) 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 = UploadedFile("image.png", b"123") params = { file.name: file, "sessionId": (None, "fooReport"), "widgetId": (None, "barWidget"), } response = self._upload_files(params) self.assertEqual(200, response.code) self.assertEqual([file], self.file_mgr.get_files("fooReport", "barWidget")) def test_upload_multiple_files(self): file1 = UploadedFile("image1.png", b"123") file2 = UploadedFile("image2.png", b"456") file3 = UploadedFile("image3.png", b"789") params = { file1.name: file1, file2.name: file2, file3.name: file3, "sessionId": (None, "fooReport"), "widgetId": (None, "barWidget"), } response = self._upload_files(params) self.assertEqual(200, response.code) self.assertEqual( sorted([file1, file2, file3], key=_get_filename), sorted(self.file_mgr.get_files("fooReport", "barWidget"), key=_get_filename), ) def test_missing_params(self): """Missing params in the body should fail with 400 status.""" params = { "image.png": ("image.png", b"1234"), "sessionId": (None, "fooReport"), # "widgetId": (None, 'barWidget'), } response = self._upload_files(params) self.assertEqual(400, response.code) self.assertIn("Missing 'widgetId'", response.reason) def test_missing_file(self): """Missing file should fail with 400 status.""" params = { # "image.png": ("image.png", b"1234"), "sessionId": (None, "fooReport"), "widgetId": (None, "barWidget"), } response = self._upload_files(params) self.assertEqual(400, response.code) self.assertIn("Expected at least 1 file, but got 0", response.reason)
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_add_file(self): self.assertIsNone(self.mgr.get_files("non-report", "non-widget")) self.mgr.update_file_count("session", "widget", 1) self.mgr.add_files("session", "widget", [file1]) self.assertEqual([file1], self.mgr.get_files("session", "widget")) self.assertEqual(len(self.filemgr_events), 1) # Add another file with the same ID self.mgr.update_file_count("session", "widget", 2) self.mgr.add_files("session", "widget", [file2]) self.assertEqual([file1, file2], self.mgr.get_files("session", "widget")) self.assertEqual(len(self.filemgr_events), 2) def test_remove_file(self): # This should not error. self.mgr.remove_files("non-report", "non-widget") self.mgr.add_files("session", "widget", [file1]) self.mgr.remove_file("session", "widget", file1.id) self.assertEqual([], self.mgr.get_files("session", "widget")) self.mgr.remove_file("session", "widget", file1.id) self.assertEqual([], self.mgr.get_files("session", "widget")) self.mgr.add_files("session", "widget", [file1]) self.mgr.add_files("session", "widget", [file2]) self.mgr.remove_file("session", "widget", file1.id) self.assertEqual([file2], self.mgr.get_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. self.mgr.add_files("session1", "widget", [file1]) self.mgr.add_files("session2", "widget", [file1]) self.mgr.remove_files("session1", "widget") self.assertIsNone(self.mgr.get_files("session1", "widget")) self.assertEqual([file1], self.mgr.get_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. self.mgr.add_files("session1", "widget1", [file1]) self.mgr.add_files("session1", "widget2", [file1]) self.mgr.add_files("session2", "widget", [file1]) self.mgr.remove_session_files("session1") self.assertIsNone(self.mgr.get_files("session1", "widget1")) self.assertIsNone(self.mgr.get_files("session1", "widget2")) self.assertEqual([file1], self.mgr.get_files("session2", "widget")) def test_replace_widget_files(self): self.mgr.add_files("session1", "widget", [file1]) self.mgr.replace_files("session1", "widget", [file2]) self.assertEqual(len(self.mgr.get_files("session1", "widget")), 1) self.assertEqual([file2], self.mgr.get_files("session1", "widget"))