Esempio n. 1
0
 def setUp(self):
     self.m = random.randint(1, 6)
     self.k = self.m - 1
     self.storage_manager = StorageManager()
     self.fec = FileFec(self.k, self.m)
     self.mapping = MappingConfigParser(create_random_dir(),
                                        generate_random_file_path())
     self.handler = DemerioConductor(self.mapping, self.fec,
                                     self.storage_manager)
Esempio n. 2
0
 def setUp(self):
     self.m = random.randint(1, 6)
     self.k = self.m - 1
     self.storage_manager = StorageManager()
     self.fec = FileFec(self.k, self.m)
     self.mapping = MappingConfigParser(create_random_dir(), generate_random_file_path())
     self.handler = DemerioConductor(self.mapping, self.fec, self.storage_manager)
Esempio n. 3
0
 def launch_daemon(self):
     self.ui.launch_btn.hide()
     self.hide()
     self.ui.account_tab.setEnabled(True)
     number_of_storages = self.storage_manager.get_number_of_storages()
     self.event_handler = DemerioConductor(Mapping(demerio_dir, config_file), FileFec(PARTS_NEEDED, number_of_storages), self.storage_manager, ignore_patterns = IGNORE_PATTERNS)
     self.event_handler.conductor_exception.connect(self.tray.conductor_problem)
     self.event_handler.event_started.connect(self.tray.event_started)
     self.event_handler.event_finished.connect(self.tray.event_finished)
     self.event_handler.reconstruct_started.connect(self.init_progress_bar)
     self.event_handler.reconstruct_finished.connect(self.end_progress_bar)
     self.event_handler.reconstruct_update.connect(self.update_progress_bar)
     observer = Observer()
     self.daemon = DemerioDaemon(self.event_handler, observer, demerio_dir, should_exit=False)
     self.daemon.start()
     self.open_demerio_folder()
Esempio n. 4
0
class TestDemerioHandler(unittest.TestCase):
    """
    This is an integration testCase, we use Mock as storage_manager and
    as split to only test mapping integration
    """

    def _mock_encode_path_in_dir(self, input_path, temp_dir):
        return [generate_random_file_name_in_dir(temp_dir) for i in range(self.m)]

    def _mock_storage_new_file(self, file_parts):
        return [ (generate_random_string(), file_part) for file_part in file_parts ]

    def setUp(self):
        self.m = random.randint(1, 6)
        self.k = self.m - 1
        self.storage_manager = StorageManager()
        self.fec = FileFec(self.k, self.m)
        self.mapping = MappingConfigParser(create_random_dir(), generate_random_file_path())
        self.handler = DemerioConductor(self.mapping, self.fec, self.storage_manager)

    def tearDown(self):
        delete_file(self.mapping.config_file_path)
        delete_dir(self.mapping.base_dir)

    def test_on_created_file_without_error(self):
        # Given
        new_file = generate_random_file_name_in_dir(self.mapping.base_dir)
        created_event = FileCreatedEvent(new_file)
        self.fec.encode_path_in_dir = self._mock_encode_path_in_dir
        self.storage_manager.new_file = self._mock_storage_new_file

        # When
        self.handler.on_created(created_event)

        # Then
        self.assertTrue(self.mapping.has_file(new_file))
        self.assertTrue(self.mapping.get_state(new_file) == STATE.ok)

    def test_on_created_file_with_split_error(self):
        # Given
        new_file = generate_random_file_name_in_dir(self.mapping.base_dir)
        created_event = FileCreatedEvent(new_file)
        self.fec.encode_path_in_dir = MagicMock(side_effect=DemerioSplitError(''))

        # When
        self.handler.on_created(created_event)

        # Then
        self.assertTrue(self.mapping.has_file(new_file))
        self.assertTrue(self.mapping.get_state(new_file) == STATE.detected)

    def test_after_reconstruct_i_have_the_same_number_of_files(self):
        # Given
        number_of_files = random.randint(1, 100)
        for file_number in range(number_of_files):
            file_path = generate_random_file_name_in_dir(self.mapping.base_dir)
            self.mapping.add_file(file_path, self.k, self.m)
            self.mapping.update_to_splitted_state(file_path, [generate_random_string() for i in range(self.m)])
        output_dir = create_random_dir()
        self.addCleanup(lambda: delete_dir(output_dir))
        self.storage_manager.download_file_chunks = mock_download_file_chunks
        self.fec.decode_path = mock_decode_path

        # When
        self.handler.reconstruct_dir(output_dir)

        # Then
        actual_number_of_files = count_files_recursively_in_dir(output_dir)
        self.assertEqual(number_of_files, actual_number_of_files)

    def test_reconstruct_with_subdirectories(self):
        # Given
        number_of_dir = random.randint(1, 10)
        number_of_files_in_dir = [random.randint(1, 100) for i in range(number_of_dir)]
        expected_number_of_files = sum(number_of_files_in_dir)
        for dir_number in range(number_of_dir):
            number_of_files_to_create = number_of_files_in_dir[dir_number]
            random_dir = create_random_dir(self.mapping.base_dir)
            for file_number in range(number_of_files_to_create):
                file_path = generate_random_file_name_in_dir(random_dir)
                self.mapping.add_file(file_path, self.k, self.m)
                self.mapping.update_to_splitted_state(file_path, [generate_random_string() for i in range(self.m)])
        output_dir = create_random_dir()
        self.addCleanup(lambda: delete_dir(output_dir))
        self.storage_manager.download_file_chunks = mock_download_file_chunks
        self.fec.decode_path = mock_decode_path

        # When
        self.handler.reconstruct_dir(output_dir)

        # Then
        actual_number_of_files = count_files_recursively_in_dir(output_dir)
        self.assertEqual(expected_number_of_files, actual_number_of_files)
Esempio n. 5
0
class TestDemerioHandler(unittest.TestCase):
    """
    This is an integration testCase, we use Mock as storage_manager and
    as split to only test mapping integration
    """
    def _mock_encode_path_in_dir(self, input_path, temp_dir):
        return [
            generate_random_file_name_in_dir(temp_dir) for i in range(self.m)
        ]

    def _mock_storage_new_file(self, file_parts):
        return [(generate_random_string(), file_part)
                for file_part in file_parts]

    def setUp(self):
        self.m = random.randint(1, 6)
        self.k = self.m - 1
        self.storage_manager = StorageManager()
        self.fec = FileFec(self.k, self.m)
        self.mapping = MappingConfigParser(create_random_dir(),
                                           generate_random_file_path())
        self.handler = DemerioConductor(self.mapping, self.fec,
                                        self.storage_manager)

    def tearDown(self):
        delete_file(self.mapping.config_file_path)
        delete_dir(self.mapping.base_dir)

    def test_on_created_file_without_error(self):
        # Given
        new_file = generate_random_file_name_in_dir(self.mapping.base_dir)
        created_event = FileCreatedEvent(new_file)
        self.fec.encode_path_in_dir = self._mock_encode_path_in_dir
        self.storage_manager.new_file = self._mock_storage_new_file

        # When
        self.handler.on_created(created_event)

        # Then
        self.assertTrue(self.mapping.has_file(new_file))
        self.assertTrue(self.mapping.get_state(new_file) == STATE.ok)

    def test_on_created_file_with_split_error(self):
        # Given
        new_file = generate_random_file_name_in_dir(self.mapping.base_dir)
        created_event = FileCreatedEvent(new_file)
        self.fec.encode_path_in_dir = MagicMock(
            side_effect=DemerioSplitError(''))

        # When
        self.handler.on_created(created_event)

        # Then
        self.assertTrue(self.mapping.has_file(new_file))
        self.assertTrue(self.mapping.get_state(new_file) == STATE.detected)

    def test_after_reconstruct_i_have_the_same_number_of_files(self):
        # Given
        number_of_files = random.randint(1, 100)
        for file_number in range(number_of_files):
            file_path = generate_random_file_name_in_dir(self.mapping.base_dir)
            self.mapping.add_file(file_path, self.k, self.m)
            self.mapping.update_to_splitted_state(
                file_path, [generate_random_string() for i in range(self.m)])
        output_dir = create_random_dir()
        self.addCleanup(lambda: delete_dir(output_dir))
        self.storage_manager.download_file_chunks = mock_download_file_chunks
        self.fec.decode_path = mock_decode_path

        # When
        self.handler.reconstruct_dir(output_dir)

        # Then
        actual_number_of_files = count_files_recursively_in_dir(output_dir)
        self.assertEqual(number_of_files, actual_number_of_files)

    def test_reconstruct_with_subdirectories(self):
        # Given
        number_of_dir = random.randint(1, 10)
        number_of_files_in_dir = [
            random.randint(1, 100) for i in range(number_of_dir)
        ]
        expected_number_of_files = sum(number_of_files_in_dir)
        for dir_number in range(number_of_dir):
            number_of_files_to_create = number_of_files_in_dir[dir_number]
            random_dir = create_random_dir(self.mapping.base_dir)
            for file_number in range(number_of_files_to_create):
                file_path = generate_random_file_name_in_dir(random_dir)
                self.mapping.add_file(file_path, self.k, self.m)
                self.mapping.update_to_splitted_state(
                    file_path,
                    [generate_random_string() for i in range(self.m)])
        output_dir = create_random_dir()
        self.addCleanup(lambda: delete_dir(output_dir))
        self.storage_manager.download_file_chunks = mock_download_file_chunks
        self.fec.decode_path = mock_decode_path

        # When
        self.handler.reconstruct_dir(output_dir)

        # Then
        actual_number_of_files = count_files_recursively_in_dir(output_dir)
        self.assertEqual(expected_number_of_files, actual_number_of_files)
Esempio n. 6
0
class MainWindow(QDialog):

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.ui = uic.loadUi(ui_full_path('main_window.ui'), self)
        self.ui.label_version.setText("Demerio version %s" % (get_versions()['version'],))
        self.ui.progress_bar.setVisible(False)
        self.ui.tabWidget.setCurrentIndex(0)
        self.ui.launch_btn.clicked.connect(self.launch_daemon)
        self.ui.output_btn.clicked.connect(self.validate)
        self.tray = SystemTray(self)
        self.tray.show()
        self.create_tray_actions()
        self.init_storage_manager()
        self.add_clouds_to_view()
        self.daemon = None
        self.check_if_already_connected()

    def create_tray_actions(self):
        self.tray.add_action("Open Demerio Folder", self.open_demerio_folder)
        self.tray.add_action("Preference", self.show)
        self.tray.add_separator()
        self.tray.add_action("Quit", self.quit_app)

    """
    should be done in cloud widget class with a proper model and view
    """
    def init_storage_manager(self):
        self.storage_manager = StorageManager()
        drive_api = GoogleDriveAPI(demerio_config_dir)
        self.storage_manager.add_storage("google_drive", drive_api)
        dropbox = DropboxAPI(demerio_config_dir)
        self.storage_manager.add_storage("dropbox", dropbox)
        box = BoxAPI(demerio_config_dir)
        self.storage_manager.add_storage("box", box)

    def add_clouds_to_view(self):
        self.ui.listWidget.setResizeMode(QListView.Adjust)
        for cloud_name in self.storage_manager.map_of_storage.keys():
            cloud_widget = CloudWidget(cloud_name, self)
            cloud_widget.pushed.connect(self.authenticate)
            item = QListWidgetItem()
            item.setSizeHint(cloud_widget.sizeHint())
            self.ui.listWidget.addItem(item)
            self.ui.listWidget.setItemWidget(item, cloud_widget)

    @pyqtSlot()
    def authenticate(self):
        cloud_storage = self.storage_manager.map_of_storage[self.sender().name]
        cloud_storage.authorize()
        if cloud_storage.is_connected():
            self.sender().ui.cloudAction.setEnabled(False)
        self.update_launch_btn_state()

    @pyqtSlot()
    def open_demerio_folder(self):
        QDesktopServices.openUrl(QUrl.fromLocalFile(demerio_dir))

    def update_launch_btn_state(self):
        for cloud in self.storage_manager.map_of_storage.values():
            if not cloud.is_connected():
                return False
        self.ui.launch_btn.setEnabled(True)
        self.ui.label.setText("")

    @pyqtSlot()
    def launch_daemon(self):
        self.ui.launch_btn.hide()
        self.hide()
        self.ui.account_tab.setEnabled(True)
        number_of_storages = self.storage_manager.get_number_of_storages()
        self.event_handler = DemerioConductor(Mapping(demerio_dir, config_file), FileFec(PARTS_NEEDED, number_of_storages), self.storage_manager, ignore_patterns = IGNORE_PATTERNS)
        self.event_handler.conductor_exception.connect(self.tray.conductor_problem)
        self.event_handler.event_started.connect(self.tray.event_started)
        self.event_handler.event_finished.connect(self.tray.event_finished)
        self.event_handler.reconstruct_started.connect(self.init_progress_bar)
        self.event_handler.reconstruct_finished.connect(self.end_progress_bar)
        self.event_handler.reconstruct_update.connect(self.update_progress_bar)
        observer = Observer()
        self.daemon = DemerioDaemon(self.event_handler, observer, demerio_dir, should_exit=False)
        self.daemon.start()
        self.open_demerio_folder()

    @pyqtSlot(int)
    def init_progress_bar(self, number_of_files):
        self.ui.progress_bar.setVisible(True)
        self.ui.progress_bar.setMaximum(number_of_files)
        self.ui.progress_bar.setTextVisible(True)

    @pyqtSlot(int)
    def update_progress_bar(self, value):
        self.ui.progress_bar.setValue(value)

    @pyqtSlot()
    def end_progress_bar(self):
        self.ui.progress_bar.setVisible(False)
        self.ui.start_label.setText("")

    @pyqtSlot()
    def validate(self):
        self.dir_selected = QFileDialog.getExistingDirectory(self, "Select Directory")
        self.ui.start_label.setText("Your datas will be reconstructed in : %s directory" %(self.dir_selected,))
        self.event_handler.reconstruct_dir(self.dir_selected)

    @pyqtSlot()
    def quit_app(self):
        if self.daemon is not None:
            self.daemon.should_exit = True
            self.daemon.join()
        QCoreApplication.instance().quit()

    def check_if_already_connected(self):
        QApplication.processEvents()
        for index in range(self.ui.listWidget.count()):
            QApplication.processEvents()
            cloud_widget = self.ui.listWidget.itemWidget(self.ui.listWidget.item(index))
            if self.storage_manager.map_of_storage[cloud_widget.name].is_connected():
                cloud_widget.ui.cloudAction.setEnabled(False)
                self.update_launch_btn_state()
        if self.ui.launch_btn.isEnabled():
            self.launch_daemon()
        else:
            self.show()