def test_synchronize_paged_delete_detection(self): # Initialize a controller with page size = 1 for deleted items # detection query ctl = Controller(self.nxdrive_conf_folder_1, page_size=1) ctl.bind_server(self.local_nxdrive_folder_1, self.nuxeo_url, self.user_1, self.password_1) ctl.bind_root(self.local_nxdrive_folder_1, self.workspace) # Launch first synchronization time.sleep(self.AUDIT_CHANGE_FINDER_TIME_RESOLUTION) self.wait() syn = ctl.synchronizer syn.loop(delay=0.1, max_loops=1) # Get local and remote clients local = LocalClient(os.path.join(self.local_nxdrive_folder_1, self.workspace_title)) remote = self.remote_document_client_1 # Create a remote folder with 2 children then synchronize remote.make_folder('/', 'Remote folder',) remote.make_file('/Remote folder', 'Remote file 1.odt', 'Some content.') remote.make_file('/Remote folder', 'Remote file 2.odt', 'Other content.') time.sleep(self.AUDIT_CHANGE_FINDER_TIME_RESOLUTION) self.wait() syn.loop(delay=0.1, max_loops=1) self.assertTrue(local.exists('/Remote folder')) self.assertTrue(local.exists('/Remote folder/Remote file 1.odt')) self.assertTrue(local.exists('/Remote folder/Remote file 2.odt')) # Delete remote folder then synchronize remote.delete('/Remote folder') time.sleep(self.AUDIT_CHANGE_FINDER_TIME_RESOLUTION) self.wait() syn.loop(delay=0.1, max_loops=1) self.assertFalse(local.exists('/Remote folder')) self.assertFalse(local.exists('/Remote folder/Remote file 1.odt')) self.assertFalse(local.exists('/Remote folder/Remote file 2.odt')) # Create a local folder with 2 children then synchronize local.make_folder('/', 'Local folder') local.make_file('/Local folder', 'Local file 1.odt', 'Some content.') local.make_file('/Local folder', 'Local file 2.odt', 'Other content.') syn.loop(delay=0.1, max_loops=1) self.assertTrue(remote.exists('/Local folder')) self.assertTrue(remote.exists('/Local folder/Local file 1.odt')) self.assertTrue(remote.exists('/Local folder/Local file 2.odt')) # Delete local folder then synchronize time.sleep(self.OS_STAT_MTIME_RESOLUTION) local.delete('/Local folder') syn.loop(delay=0.1, max_loops=1) self.assertFalse(remote.exists('/Local folder')) self.assertFalse(remote.exists('/Local folder/Local file 1.odt')) self.assertFalse(remote.exists('/Local folder/Local file 2.odt')) # Dispose dedicated Controller instantiated for this test ctl.dispose()
class TestIntegrationReinitDatabase(IntegrationTestCase): def setUp(self): super(TestIntegrationReinitDatabase, self).setUp() self.syn, self.local, self.remote = self.init_default_drive() self.ctl = self.controller_1 # Make a folder and a file self.remote.make_folder('/', 'Test folder') self.remote.make_file('/Test folder', 'Test.txt', 'This is some content') self.test_remote_folder_id = self.remote.get_info('/Test folder').uid # Wait for synchro self._synchronize() # Verify that all is synchronize self.assertTrue(self.local.exists('/Test folder'), 'Local folder should exist') self.assertTrue(self.local.exists('/Test folder/Test.txt'), 'Local file should exist') # Destroy database self._reinit_database() def tearDown(self): # Dispose dedicated Controller instantiated for this test # in _reinit_database() self.ctl.dispose() super(TestIntegrationReinitDatabase, self).tearDown() def _check_states(self): rows = self.controller_1.get_session().query(LastKnownState).all() for row in rows: self.assertEquals(row.pair_state, 'synchronized') def _reinit_database(self): # Close database self.ctl.dispose() # Destroy configuration folder shutil.rmtree(self.nxdrive_conf_folder_1) os.mkdir(self.nxdrive_conf_folder_1) # Recreate a controller self.ctl = Controller(self.nxdrive_conf_folder_1) self.ctl.bind_server(self.local_nxdrive_folder_1, self.nuxeo_url, self.user_1, self.password_1) self.ctl.bind_root(self.local_nxdrive_folder_1, self.workspace) self.syn = self.ctl.synchronizer def _synchronize(self, loops=1): super(TestIntegrationReinitDatabase, self)._synchronize(self.syn, loops) def _check_conflict_locally_handled(self): # As a conflict has been raised 2 files should be present locally self.assertEqual(len(self.local.get_children_info("/Test folder")), 2) self.assertEqual(len(self.remote.get_children_info( self.test_remote_folder_id)), 1) def _check_conflict_locally_and_remotely_handled(self): # End the conflict handling by uploading the second local file to # the server self.assertEqual(len(self.local.get_children_info("/Test folder")), 2) self.assertEqual(len(self.remote.get_children_info( self.test_remote_folder_id, types=('File', 'Note'))), 2) def test_synchronize_folderish_and_same_digest(self): # Reload sync self._synchronize() # Check everything is synchronized self._check_states() def test_synchronize_remote_change(self): # Modify the remote file self.remote.update_content('/Test folder/Test.txt', 'Content has changed') # Sync self._synchronize() # Check a conflict is detected and handled locally self._check_conflict_locally_handled() # Assert content of the original file has changed self.assertEquals(self.local.get_content('/Test folder/Test.txt'), 'Content has changed', 'Local content should be the same as the remote one') # Sync again self._synchronize(3) # Check a conflict is handled locally and remotely self._check_conflict_locally_and_remotely_handled() # Check everything is synchronized self._check_states() def test_synchronize_local_change(self): # Modify the local file time.sleep(self.OS_STAT_MTIME_RESOLUTION) self.local.update_content('/Test folder/Test.txt', 'Content has changed') # Sync self._synchronize() # Check a conflict is detected and handled locally self._check_conflict_locally_handled() # Assert content of the original file has not changed self.assertEquals(self.local.get_content('/Test folder/Test.txt'), 'This is some content', 'Local content should be the same as the remote one') # Sync again self._synchronize(3) # Check a conflict is handled locally and remotely self._check_conflict_locally_and_remotely_handled() # Assert content has changed self.assertEquals(self.remote.get_content('/Test folder/Test.txt'), 'This is some content', 'Remote content should not have changed') # Check everything is synchronized self._check_states() def test_synchronize_remote_and_local_change(self): # Modify the remote file self.remote.update_content('/Test folder/Test.txt', 'Content has remote changed') # Modify the local file time.sleep(self.OS_STAT_MTIME_RESOLUTION) self.local.update_content('/Test folder/Test.txt', 'Content has local changed') # Sync self._synchronize() # Check a conflict is detected and handled locally self._check_conflict_locally_handled() # Assert content of the original file has not changed self.assertEquals(self.local.get_content('/Test folder/Test.txt'), 'Content has remote changed', 'Local content should be the same as remote one') # Sync again self._synchronize(3) # Check a conflict is handled locally and remotely self._check_conflict_locally_and_remotely_handled() # Assert content has changed self.assertEquals(self.local.get_content('/Test folder/Test.txt'), 'Content has remote changed', 'Remote changed content should not have changed again') # Check everything is synchronized self._check_states()
class CliHandler(object): """Command Line Interface handler: parse options and execute operation""" def __init__(self): self.parser = make_cli_parser() def handle(self, args): # use the CLI parser to check that the first args is a valid command options = self.parser.parse_args(args) if options.debug: # Install Post-Mortem debugger hook def info(type, value, tb): traceback.print_exception(type, value, tb) print debugger.pm() sys.excepthook = info filename = options.log_filename if filename is None: filename = os.path.join( options.nxdrive_home, 'logs', 'nxdrive.log') configure( filename, file_level=options.log_level_file, console_level=options.log_level_console, process_name=options.command, ) self.controller = Controller(options.nxdrive_home) handler = getattr(self, options.command, None) if handler is None: raise NotImplementedError( 'No handler implemented for command ' + options.command) return handler(options) def start(self, options=None): self.controller.start() return 0 def stop(self, options=None): self.controller.stop() return 0 def console(self, options): fault_tolerant = not options.stop_on_error self.controller.loop(fault_tolerant=fault_tolerant, delay=options.delay) return 0 def status(self, options): states = self.controller.status(options.files) for filename, status in states: print status + '\t' + filename return 0 def bind_server(self, options): if options.password is None: password = getpass() else: password = options.password self.controller.bind_server(options.local_folder, options.nuxeo_url, options.username, password) for root in options.remote_roots: self.controller.bind_root(options.local_folder, root, repository=options.remote_repo) return 0 def unbind_server(self, options): self.controller.unbind_server(options.local_folder) return 0 def bind_root(self, options): self.controller.bind_root(options.local_folder, options.remote_root, repository=options.remote_repo) return 0 def unbind_root(self, options): self.controller.unbind_root(options.local_root) return 0 def test(self, options): import nose # Monkeypatch nose usage message as it's complicated to include # the missing text resource in the frozen binary package nose.core.TestProgram.usage = lambda cls: "" argv = [''] if options.with_coverage: argv += [ '--with-coverage', '--cover-package=nxdrive', '--cover-html', '--cover-html-dir=coverage', ] if options.with_profile: argv += [ '--with-profile', '--profile-restrict=nxdrive', ] # List the test modules explicitly as recursive discovery is broken # when the app is frozen. argv += [ "nxdrive.tests.test_controller", "nxdrive.tests.test_filesystem_client", "nxdrive.tests.test_integration_nuxeo_client", "nxdrive.tests.test_integration_synchronization", ] return 0 if nose.run(argv=argv) else 1