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")
예제 #2
0
    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())
예제 #3
0
 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")
예제 #6
0
    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
예제 #7
0
    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])
예제 #10
0
    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}")
예제 #11
0
    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)