def test_get_file_list_returns_all_non_full_files(self, dispatchResponseMock, fakeAPIFactory): fakeCloudAPI = MagicMock() fakeGetFileListResponse = [ FilePart(filename="full_file__1__1.enc", modified=1, size=32, path="", fullPath="full_file__1__1.enc", storingAccountID=1), FilePart(filename="partial_file__1__2.enc", modified=1, size=48, path="subDir", fullPath="subDir/partial_file__1__2.enc", storingAccountID=1) ] fakeCloudAPI.getFileList.return_value = fakeGetFileListResponse self.fakeDB.getAllAccounts.return_value = [ AccountData(id=1, identifier="testAccountID", accountType=AccountTypes.Dropbox, cryptoKey="sixteen byte key", data={"apiToken": "testApitoken"}) ] fakeAPIFactory.return_value = fakeCloudAPI testTask = Task(taskType=MessageTypes.SYNC_FILES, uuid=uuid4().hex) testHandler = GetFileListHandler(self.fakeDB) testHandler.setTask(testTask) testHandler.handle() self.assertEqual(fakeCloudAPI.getFileList.call_count, 1) self.assertEqual(fakeAPIFactory.call_count, 1) self.assertEqual( dispatchResponseMock.call_args[0][0].header.messageType, MessageTypes.RESPONSE) self.assertEqual(dispatchResponseMock.call_args[0][0].header.uuid, testTask.uuid) self.assertEqual(len(dispatchResponseMock.call_args[0][0].data), 1) self.assertEqual( dispatchResponseMock.call_args[0][0].data[0]["filename"], "full_file") self.assertEqual( dispatchResponseMock.call_args[0][0].data[0]["modified"], fakeGetFileListResponse[0].modified) self.assertEqual(dispatchResponseMock.call_args[0][0].data[0]["size"], fakeGetFileListResponse[0].size - 16) self.assertEqual(dispatchResponseMock.call_args[0][0].data[0]["path"], fakeGetFileListResponse[0].path) self.assertEqual( dispatchResponseMock.call_args[0][0].data[0]["fullPath"], "full_file")
def test_download_file_does_nothing_if_task_is_stale(self, mockRequest): secretData = b"secret test data" testEncoder = AES.new(self.testAccountData.cryptoKey.encode(), AES.MODE_CFB) testIV = testEncoder.iv ivResponse = MagicMock() ivResponse.content = testIV encryptedDataResponse = MagicMock() encryptedDataResponse.content = testEncoder.encrypt(secretData) mockRequest.side_effect = [ivResponse, encryptedDataResponse] testDownloadFileHandle = BytesIO() testFilePartInfo = FilePart( filename="apple.txt__1__1.enc", modified=int( datetime.datetime(2020, 1, 1, 10, 10, 30).timestamp()), size=len(encryptedDataResponse.content) + len(testIV), path="", fullPath="apple.txt__1__1.enc", storingAccountID=self.testAccountData.id, extraInfo={}) testDownloadFileTask = Task(taskType=MessageTypes.DOWNLOAD_FILE, stale=True) cloudAccount = DropboxAccountWrapper(self.testAccountData) cloudAccount.download(testDownloadFileHandle, testFilePartInfo, testDownloadFileTask) testDownloadFileHandle.seek(0) self.assertEqual(b"", testDownloadFileHandle.read())
def __toFilePart(self, entry): return FilePart(filename=entry.name, modified=int(entry.client_modified.timestamp()), size=entry.size, path=entry.path_display.replace(f"/{entry.name}", "").lstrip("/"), fullPath=entry.path_display.lstrip("/"), storingAccountID=self.accountData.id)
def test_stops_download_and_does_not_send_response_and_cleans_up_if_file_download_is_interrupted( self, openMock, cloudApiMock, getFileMock, dispatchResponseMock, os_removeMock): openMock.return_value = BytesIO() testFileData = FileData(filename="apple.txt", modified=10, size=10, path="subDir", fullPath="subDir/apple.txt") testFilePart = FilePart(filename="apple.txt__1__1.enc", modified=10, size=testFileData.size + 16, path="subDir", fullPath="subDir/apple.txt__1__1.enc", storingAccountID=1) fakeAccounts = [ AccountData(id=1, identifier="testAccountID1", accountType=AccountTypes.Dropbox, cryptoKey="sixteen byte key", data={"apiToken": "testApitoken1"}), AccountData(id=2, identifier="testAccountID2", accountType=AccountTypes.Dropbox, cryptoKey="sixteen byte key", data={"apiToken": "testApitoken2"}) ] self.fakeDB.getAllAccounts.return_value = fakeAccounts testCachedFileInfo = CachedFileData( data=testFileData, availablePartCount=1, totalPartCount=1, parts={"subDir/apple.txt__1__1.enc": testFilePart}) getFileMock.return_value = testCachedFileInfo testTask = Task(taskType=MessageTypes.DOWNLOAD_FILE, data=testFileData.serialize(), uuid=uuid4().hex, stale=True) testHandler = DownloadFileHandler(self.fakeDB) testHandler.setTask(testTask) testHandler.handle() self.assertEqual(openMock.call_count, 1) self.assertEqual(openMock.call_args[0][0], f"testWorkspace/server/{testTask.uuid}") self.assertEqual(openMock.call_args[0][1], "wb") self.assertEqual(dispatchResponseMock.call_count, 0) self.assertEqual(os_removeMock.call_count, 1) self.assertEqual(os_removeMock.call_args[0][0], f"testWorkspace/server/{testTask.uuid}")
def test_uploads_file_to_all_accounts_if_per_accounts_size_is_greater_than_one( self, openMock, cloudApiMock, insertFilePartMock, getFileMock, os_unlinkMock, dispatchResponseMock): fakeFile = BytesIO(b"Lorem ipsum") openMock.return_value = fakeFile fakeAccounts = [ AccountData(id=1, identifier="testAccountID1", accountType=AccountTypes.Dropbox, cryptoKey="sixteen byte key", data={"apiToken": "testApitoken1"}), AccountData(id=2, identifier="testAccountID2", accountType=AccountTypes.Dropbox, cryptoKey="sixteen byte key", data={"apiToken": "testApitoken2"}) ] self.fakeDB.getAllAccounts.return_value = fakeAccounts getFileMock.return_value = None testTaskData = { "filename": "apple.txt", "size": 10, "fullPath": "subDir/apple.txt", "status": None, "utcModified": 10, "path": "subDir" } fakeUploadResult = FilePart(filename=testTaskData["filename"], modified=testTaskData["utcModified"], size=testTaskData["size"], path=testTaskData["path"], fullPath=testTaskData["fullPath"], storingAccountID=fakeAccounts[0].id) fakeCloudAccount1 = MagicMock() fakeCloudAccount2 = MagicMock() cloudApiMock.side_effect = [fakeCloudAccount1, fakeCloudAccount2] testTask = Task(taskType=MessageTypes.UPLOAD_FILE, data=testTaskData, uuid=uuid4().hex) testHandler = UploadFileHandler(self.fakeDB) testHandler.setTask(testTask) testHandler.handle() self.assertEqual(fakeCloudAccount1.upload.call_count, 1) self.assertEqual(fakeCloudAccount1.upload.call_args[0][2], f"{testTaskData['filename']}__1__2.enc") self.assertEqual(fakeCloudAccount2.upload.call_count, 1) self.assertEqual(fakeCloudAccount2.upload.call_args[0][2], f"{testTaskData['filename']}__2__2.enc")
def __toFilePart(self, entry): filename = entry["name"].split("/")[-1] path = entry["name"].replace(filename, "").rstrip("/") fullPath = entry["name"] unawareModifiedTime = time.strptime(entry["modifiedTime"], "%Y-%m-%dT%H:%M:%S.000Z") modifiedTime = datetime(*unawareModifiedTime[:6], tzinfo=timezone.utc) filePart = FilePart(filename=filename, modified=int(modifiedTime.timestamp()), size=int(entry["size"]), path=path, fullPath=fullPath, storingAccountID=self.accountData.id, extraInfo={"id": entry["id"]}) return filePart
def test_deleteFile_delegates_call_properly(self, mockDropbox): mockDropbox.return_value.files_delete = MagicMock() testFilePartInfo = FilePart(filename="apple.txt__1__1.enc", modified=int( datetime.datetime( 2020, 1, 1, 10, 10, 30).timestamp()), size=32, path="subDir", fullPath="subDir/apple.txt__1__1.enc", storingAccountID=self.testAccountData.id, extraInfo={}) cloudAccount = DropboxAccountWrapper(self.testAccountData) cloudAccount.deleteFile(testFilePartInfo) self.assertEqual(mockDropbox.return_value.files_delete.call_count, 1) self.assertEqual(mockDropbox.return_value.files_delete.call_args[0][0], f"/{testFilePartInfo.fullPath}")
def test_removes_destination_path_on_all_accounts_then_tries_to_move_unsynced_files_and_sends_unsuccessful_response( self, getFileMock, cloudApiMock, removeFileMock, dispatchResponseMock, moveFileMock): testSourceFileData = FileData(filename="apple.txt", modified=10, size=10, path="", fullPath="apple.txt") testTargetFileData = FileData(filename="apple.txt", modified=10, size=20, path="subDir", fullPath="subDir/apple.txt") testTask = Task(taskType=MessageTypes.MOVE_FILE, data={ "source": "apple.txt", "target": testTargetFileData.serialize() }) fakeAccounts = [ AccountData(id=1, identifier="testAccountID1", accountType=AccountTypes.Dropbox, cryptoKey="sixteen byte key", data={"apiToken": "testApitoken1"}), AccountData(id=2, identifier="testAccountID2", accountType=AccountTypes.Dropbox, cryptoKey="sixteen byte key", data={"apiToken": "testApitoken2"}) ] self.fakeDB.getAllAccounts.return_value = fakeAccounts testSourceFileParts = [ FilePart(filename="apple.txt__1__2.enc", modified=10, size=21, path="", fullPath="apple.txt__1__2.enc", storingAccountID=1), ] testTargetFileParts = [ FilePart(filename="apple.txt__1__2.enc", modified=15, size=26, path="subDir", fullPath="subDir/apple.txt__1__2.enc", storingAccountID=1), FilePart(filename="apple.txt__2__2.enc", modified=15, size=26, path="subDir", fullPath="subDir/apple.txt__2__2.enc", storingAccountID=2) ] testSourceCachedFileInfo = CachedFileData( data=testSourceFileData, availablePartCount=1, totalPartCount=2, parts={ filepart.filename: filepart for filepart in testSourceFileParts }) testTargetCachedFileInfo = CachedFileData( data=testTargetFileData, availablePartCount=2, totalPartCount=2, parts={ filepart.filename: filepart for filepart in testTargetFileParts }) getFileMock.side_effect = [ testTargetCachedFileInfo, testSourceCachedFileInfo ] fakeCloudAccount1 = MagicMock() fakeCloudAccount1.accountData = fakeAccounts[0] fakeCloudAccount2 = MagicMock() fakeCloudAccount2.accountData = fakeAccounts[1] cloudApiMock.side_effect = [ fakeCloudAccount1, fakeCloudAccount2, fakeCloudAccount1, fakeCloudAccount2 ] testHandler = MoveFileHandler(self.fakeDB) testHandler.setTask(testTask) testHandler.handle() self.assertEqual(fakeCloudAccount1.deleteFile.call_count, 2) self.assertEqual(fakeCloudAccount2.deleteFile.call_count, 1) self.assertEqual(fakeCloudAccount1.moveFile.call_count, 0) self.assertEqual(fakeCloudAccount2.moveFile.call_count, 0) self.assertEqual(getFileMock.call_count, 2) self.assertEqual(removeFileMock.call_count, 2) self.assertEqual(dispatchResponseMock.call_count, 1) self.assertEqual(moveFileMock.call_count, 0) self.assertEqual(fakeCloudAccount1.deleteFile.call_args[0][0], testSourceFileParts[0]) self.assertEqual(fakeCloudAccount2.deleteFile.call_args[0][0], testTargetFileParts[1]) self.assertEqual(getFileMock.call_args_list[0][0][0], testTargetFileData.fullPath) self.assertEqual(removeFileMock.call_args[0][0], testSourceFileData.fullPath) self.assertEqual( dispatchResponseMock.call_args[0][0].header.messageType, MessageTypes.RESPONSE) self.assertEqual( dispatchResponseMock.call_args[0][0].data, { "moveSuccessful": False, "from": "apple.txt", "to": testTargetFileData.fullPath })
def test_delete_file_handler_removes_filedata_from_all_accounts( self, getFileMock, cloudApiMock, removeFileMock): testFileData = FileData(filename="apple.txt", modified=10, size=10, path="subDir", fullPath="subDir/apple.txt") testTask = Task(taskType=MessageTypes.DELETE_FILE, data={"fullPath": "apple.txt"}) fakeAccounts = [ AccountData(id=1, identifier="testAccountID1", accountType=AccountTypes.Dropbox, cryptoKey="sixteen byte key", data={"apiToken": "testApitoken1"}), AccountData(id=2, identifier="testAccountID2", accountType=AccountTypes.Dropbox, cryptoKey="sixteen byte key", data={"apiToken": "testApitoken2"}) ] self.fakeDB.getAllAccounts.return_value = fakeAccounts testFileParts = [ FilePart(filename="apple.txt__1__2.enc", modified=10, size=21, path="subDir", fullPath="subDir/apple.txt__1__2.enc", storingAccountID=1), FilePart(filename="apple.txt__2__2.enc", modified=10, size=21, path="subDir", fullPath="subDir/apple.txt__2__2.enc", storingAccountID=2) ] testCachedFileInfo = CachedFileData( data=testFileData, availablePartCount=2, totalPartCount=2, parts={filepart.filename: filepart for filepart in testFileParts}) getFileMock.return_value = testCachedFileInfo fakeCloudAccount1 = MagicMock() fakeCloudAccount2 = MagicMock() cloudApiMock.side_effect = [fakeCloudAccount1, fakeCloudAccount2] testHandler = DeleteFileHandler(self.fakeDB) testHandler.setTask(testTask) testHandler.handle() self.assertEqual(getFileMock.call_count, 1) self.assertEqual(getFileMock.call_args[0][0], testTask.data["fullPath"]) self.assertEqual(cloudApiMock.call_count, 2) self.assertEqual(cloudApiMock.call_args_list[0][0][0], fakeAccounts[0]) self.assertEqual(cloudApiMock.call_args_list[1][0][0], fakeAccounts[1]) self.assertEqual(removeFileMock.call_count, 1) self.assertEqual(removeFileMock.call_args[0][0], testTask.data["fullPath"]) self.assertEqual(fakeCloudAccount1.deleteFile.call_count, 1) self.assertEqual(fakeCloudAccount1.deleteFile.call_args[0][0], testFileParts[0]) self.assertEqual(fakeCloudAccount2.deleteFile.call_count, 1) self.assertEqual(fakeCloudAccount2.deleteFile.call_args[0][0], testFileParts[1])
def test_downloads_file_and_moves_it_to_client_workspace_and_sends_response( self, openMock, cloudApiMock, getFileMock, dispatchResponseMock, os_renameMock): openMock.return_value = BytesIO() testFileData = FileData(filename="apple.txt", modified=10, size=10, path="subDir", fullPath="subDir/apple.txt") testFilePart = FilePart(filename="apple.txt__1__1.enc", modified=10, size=testFileData.size + 16, path="subDir", fullPath="subDir/apple.txt__1__1.enc", storingAccountID=1) fakeAccounts = [ AccountData(id=1, identifier="testAccountID1", accountType=AccountTypes.Dropbox, cryptoKey="sixteen byte key", data={"apiToken": "testApitoken1"}), AccountData(id=2, identifier="testAccountID2", accountType=AccountTypes.Dropbox, cryptoKey="sixteen byte key", data={"apiToken": "testApitoken2"}) ] self.fakeDB.getAllAccounts.return_value = fakeAccounts testCachedFileInfo = CachedFileData( data=testFileData, availablePartCount=1, totalPartCount=1, parts={"subDir/apple.txt__1__1.enc": testFilePart}) getFileMock.return_value = testCachedFileInfo testTask = Task(taskType=MessageTypes.DOWNLOAD_FILE, data=testFileData.serialize(), uuid=uuid4().hex) testHandler = DownloadFileHandler(self.fakeDB) testHandler.setTask(testTask) testHandler.handle() self.assertEqual(openMock.call_count, 1) self.assertEqual(openMock.call_args[0][0], f"testWorkspace/server/{testTask.uuid}") self.assertEqual(openMock.call_args[0][1], "wb") self.assertEqual(cloudApiMock.call_count, 1) self.assertEqual(cloudApiMock.call_args[0][0], fakeAccounts[0]) self.assertEqual(getFileMock.call_count, 1) self.assertEqual(getFileMock.call_args[0][0], testFileData.fullPath) self.assertEqual(dispatchResponseMock.call_count, 1) self.assertEqual( dispatchResponseMock.call_args[0][0].header.messageType, MessageTypes.FILE_STATUS_UPDATE) self.assertEqual(dispatchResponseMock.call_args[0][0].header.uuid, testTask.uuid) self.assertEqual(dispatchResponseMock.call_args[0][0].data["filename"], testFileData.filename) self.assertEqual(dispatchResponseMock.call_args[0][0].data["path"], testFileData.path) self.assertEqual(dispatchResponseMock.call_args[0][0].data["fullPath"], testFileData.fullPath) self.assertEqual(dispatchResponseMock.call_args[0][0].data["modified"], testFileData.modified) self.assertEqual(dispatchResponseMock.call_args[0][0].data["size"], testFileData.size) self.assertEqual(dispatchResponseMock.call_args[0][0].data["status"], FileStatuses.DOWNLOADING_TO_LOCAL) self.assertEqual(os_renameMock.call_count, 1) self.assertEqual(os_renameMock.call_args[0][0], f"testWorkspace/server/{testTask.uuid}") self.assertEqual(os_renameMock.call_args[0][1], f"testWorkspace/client/{testTask.uuid}")
def test_uploads_file_to_single_account_and_cleans_up_server_side_file_and_creates_new_filescache_entry_and_sends_response( self, openMock, cloudApiMock, insertFilePartMock, getFileMock, os_unlinkMock, dispatchResponseMock): fakeFile = BytesIO(b"Lorem ipsum") openMock.return_value = fakeFile fakeAccounts = [ AccountData(id=1, identifier="testAccountID", accountType=AccountTypes.Dropbox, cryptoKey="sixteen byte key", data={"apiToken": "testApitoken"}) ] self.fakeDB.getAllAccounts.return_value = fakeAccounts getFileMock.return_value = None testTaskData = { "filename": "apple.txt", "size": 11, "fullPath": "subDir/apple.txt", "status": None, "utcModified": 10, "path": "subDir" } fakeUploadResult = FilePart(filename=testTaskData["filename"], modified=testTaskData["utcModified"], size=testTaskData["size"], path=testTaskData["path"], fullPath=testTaskData["fullPath"], storingAccountID=fakeAccounts[0].id) cloudApiMock.return_value.upload.return_value = fakeUploadResult testTask = Task(taskType=MessageTypes.UPLOAD_FILE, data=testTaskData, uuid=uuid4().hex) testHandler = UploadFileHandler(self.fakeDB) testHandler.setTask(testTask) testHandler.handle() self.assertEqual(openMock.call_count, 1) self.assertEqual(openMock.call_args[0][0], f"testWorkspace/server/{testTask.uuid}") self.assertEqual(openMock.call_args[0][1], "rb") self.assertEqual(cloudApiMock.call_count, 1) self.assertEqual(cloudApiMock.call_args[0][0], fakeAccounts[0]) self.assertEqual(cloudApiMock.return_value.upload.call_count, 1) self.assertEqual(cloudApiMock.return_value.upload.call_args[0][0], fakeFile) self.assertEqual(cloudApiMock.return_value.upload.call_args[0][1], testTaskData["size"]) self.assertEqual(cloudApiMock.return_value.upload.call_args[0][2], f"{testTaskData['filename']}__1__1.enc") self.assertEqual(insertFilePartMock.call_count, 1) self.assertEqual(insertFilePartMock.call_args[0][0], fakeUploadResult) self.assertEqual(getFileMock.call_count, 1) self.assertEqual(getFileMock.call_args[0][0], testTaskData["fullPath"]) self.assertEqual(os_unlinkMock.call_count, 1) self.assertEqual(os_unlinkMock.call_args[0][0], f"testWorkspace/server/{testTask.uuid}") self.assertEqual(dispatchResponseMock.call_count, 1) self.assertEqual( dispatchResponseMock.call_args[0][0].header.messageType, MessageTypes.FILE_STATUS_UPDATE) self.assertEqual(dispatchResponseMock.call_args[0][0].data["filename"], testTaskData["filename"]) self.assertEqual(dispatchResponseMock.call_args[0][0].data["path"], testTaskData["path"]) self.assertEqual(dispatchResponseMock.call_args[0][0].data["fullPath"], testTaskData["fullPath"]) self.assertEqual(dispatchResponseMock.call_args[0][0].data["size"], testTaskData["size"]) self.assertEqual(dispatchResponseMock.call_args[0][0].data["modified"], testTaskData["utcModified"]) self.assertEqual(dispatchResponseMock.call_args[0][0].data["status"], FileStatuses.SYNCED)