def test_local_rename_top_level_folder(self): sb, ctl = self.sb_1, self.controller_1 local_client = LocalClient(self.local_test_folder_1) session = ctl.get_session() # Check top level folder self.assertTrue(local_client.exists(u'/Nuxeo Drive')) top_level_folder_info = local_client.get_info(u'/Nuxeo Drive') self.assertEquals(top_level_folder_info.name, u'Nuxeo Drive') self.assertEquals( top_level_folder_info.filepath, os.path.join(self.local_test_folder_1, u'Nuxeo Drive')) # Check top level folder state top_level_folder_state = session.query(LastKnownState).filter_by( local_name=u'Nuxeo Drive').one() self.assertEquals(top_level_folder_state.local_path, '/') self.assertEquals(top_level_folder_state.local_name, u'Nuxeo Drive') # Rename top level folder local_client.rename(u'/Nuxeo Drive', u'Nuxeo Drive renamed') top_level_folder_info = local_client.get_info(u'/Nuxeo Drive renamed') self.assertEquals(top_level_folder_info.name, u'Nuxeo Drive renamed') self.assertEquals( top_level_folder_info.filepath, os.path.join(self.local_test_folder_1, u'Nuxeo Drive renamed')) self.assertEquals(ctl.synchronizer.update_synchronize_server(sb), 1) # Check deleted server binding self.assertRaises(RuntimeError, ctl.get_server_binding, self.local_nxdrive_folder_1, raise_if_missing=True) # Check deleted pair state self.assertEquals(len(session.query(LastKnownState).all()), 0)
def test_local_rename_top_level_folder(self): sb, ctl = self.sb_1, self.controller_1 local_client = LocalClient(self.local_test_folder_1) session = ctl.get_session() # Check top level folder self.assertTrue(local_client.exists(u'/Nuxeo Drive')) top_level_folder_info = local_client.get_info(u'/Nuxeo Drive') self.assertEquals(top_level_folder_info.name, u'Nuxeo Drive') self.assertEquals(top_level_folder_info.filepath, os.path.join(self.local_test_folder_1, u'Nuxeo Drive')) # Check top level folder state top_level_folder_state = session.query(LastKnownState).filter_by( local_name=u'Nuxeo Drive').one() self.assertEquals(top_level_folder_state.local_path, '/') self.assertEquals(top_level_folder_state.local_name, u'Nuxeo Drive') # Rename top level folder local_client.rename(u'/Nuxeo Drive', u'Nuxeo Drive renamed') top_level_folder_info = local_client.get_info(u'/Nuxeo Drive renamed') self.assertEquals(top_level_folder_info.name, u'Nuxeo Drive renamed') self.assertEquals(top_level_folder_info.filepath, os.path.join(self.local_test_folder_1, u'Nuxeo Drive renamed')) self.assertEquals(ctl.synchronizer.update_synchronize_server(sb), 1) # Check deleted server binding self.assertRaises(RuntimeError, ctl.get_server_binding, self.local_nxdrive_folder_1, raise_if_missing=True) # Check deleted pair state self.assertEquals(len(session.query(LastKnownState).all()), 0)
def test_streaming_upload(self): remote_client = self.remote_document_client_1 # Create a document by streaming a text file file_path = remote_client.make_tmp_file("Some content.") doc_ref = remote_client.stream_file(self.workspace, 'Streamed text file', file_path, filename='My streamed file.txt') self.assertEquals(remote_client.get_info(doc_ref).name, 'Streamed text file') self.assertEquals(remote_client.get_content(doc_ref), "Some content.") # Update a document by streaming a new text file file_path = remote_client.make_tmp_file("Other content.") remote_client.stream_update(doc_ref, file_path, filename='My updated file.txt') self.assertEquals(remote_client.get_content(doc_ref), "Other content.") # Create a document by streaming a binary file file_path = os.path.join(self.upload_tmp_dir, 'testFile.pdf') copyfile('nxdrive/tests/resources/testFile.pdf', file_path) doc_ref = remote_client.stream_file(self.workspace, 'Streamed binary file', file_path) local_client = LocalClient(self.upload_tmp_dir) doc_info = remote_client.get_info(doc_ref) self.assertEquals(doc_info.name, 'Streamed binary file') self.assertEquals(doc_info.digest, local_client.get_info('/testFile.pdf').get_digest())
def test_streaming_upload(self): remote_client = self.remote_document_client_1 # Create a document by streaming a text file file_path = remote_client.make_tmp_file("Some content.") try: doc_ref = remote_client.stream_file(self.workspace, 'Streamed text file', file_path, filename='My streamed file.txt') finally: os.remove(file_path) self.assertEqual(remote_client.get_info(doc_ref).name, 'Streamed text file') self.assertEqual(remote_client.get_content(doc_ref), "Some content.") # Update a document by streaming a new text file file_path = remote_client.make_tmp_file("Other content.") try: remote_client.stream_update(doc_ref, file_path, filename='My updated file.txt') finally: os.remove(file_path) self.assertEqual(remote_client.get_content(doc_ref), "Other content.") # Create a document by streaming a binary file file_path = os.path.join(self.upload_tmp_dir, 'testFile.pdf') copyfile(self.location + '/resources/testFile.pdf', file_path) doc_ref = remote_client.stream_file(self.workspace, 'Streamed binary file', file_path) local_client = LocalClient(self.upload_tmp_dir) doc_info = remote_client.get_info(doc_ref) self.assertEqual(doc_info.name, 'Streamed binary file') self.assertEqual(doc_info.digest_algorithm, 'md5') self.assertEqual(doc_info.digest, local_client.get_info('/testFile.pdf').get_digest())
def test_streaming_upload(self): remote_client = self.remote_file_system_client_1 # Create a document by streaming a text file file_path = remote_client.make_tmp_file("Some content.") try: fs_item_info = remote_client.stream_file(self.workspace_id, file_path, filename='My streamed file.txt') finally: os.remove(file_path) fs_item_id = fs_item_info.uid self.assertEquals(fs_item_info.name, 'My streamed file.txt') self.assertEquals(remote_client.get_content(fs_item_id), "Some content.") # Update a document by streaming a new text file file_path = remote_client.make_tmp_file("Other content.") try: fs_item_info = remote_client.stream_update(fs_item_id, file_path, filename='My updated file.txt') finally: os.remove(file_path) self.assertEqual(fs_item_info.uid, fs_item_id) self.assertEquals(fs_item_info.name, 'My updated file.txt') self.assertEquals(remote_client.get_content(fs_item_id), "Other content.") # Create a document by streaming a binary file file_path = os.path.join(self.upload_tmp_dir, 'testFile.pdf') copyfile('nxdrive/tests/resources/testFile.pdf', file_path) fs_item_info = remote_client.stream_file(self.workspace_id, file_path) local_client = LocalClient(self.upload_tmp_dir) self.assertEquals(fs_item_info.name, 'testFile.pdf') self.assertEquals(fs_item_info.digest, local_client.get_info('/testFile.pdf').get_digest())
def test_streaming_upload(self): remote_client = self.remote_document_client_1 # Create a document by streaming a text file file_path = remote_client.make_tmp_file("Some content.") doc_ref = remote_client.stream_file( self.workspace, "Streamed text file", file_path, filename="My streamed file.txt" ) self.assertEquals(remote_client.get_info(doc_ref).name, "Streamed text file") self.assertEquals(remote_client.get_content(doc_ref), "Some content.") # Update a document by streaming a new text file file_path = remote_client.make_tmp_file("Other content.") remote_client.stream_update(doc_ref, file_path, filename="My updated file.txt") # As a workaround for https://jira.nuxeo.com/browse/NXP-10964, # wait for a while to ensure transaction is committed before # Blob response is serialized and sent to the client sleep(1.0) self.assertEquals(remote_client.get_content(doc_ref), "Other content.") # Create a document by streaming a binary file file_path = os.path.join(self.upload_tmp_dir, "testFile.pdf") copyfile("nxdrive/tests/resources/testFile.pdf", file_path) doc_ref = remote_client.stream_file(self.workspace, "Streamed binary file", file_path) local_client = LocalClient(self.upload_tmp_dir) doc_info = remote_client.get_info(doc_ref) self.assertEquals(doc_info.name, "Streamed binary file") self.assertEquals(doc_info.digest, local_client.get_info("/testFile.pdf").get_digest())
def _local_bind_root(self, server_binding, remote_info, nxclient, session): # Check that this workspace does not already exist locally # TODO: shall we handle deduplication for root names too? local_root = os.path.join(server_binding.local_folder, safe_filename(remote_info.name)) repository = nxclient.repository if not os.path.exists(local_root): os.makedirs(local_root) lcclient = LocalClient(local_root) local_info = lcclient.get_info('/') try: existing_binding = session.query(RootBinding).filter_by( local_root=local_root, ).one() if (existing_binding.remote_repo != repository or existing_binding.remote_root != remote_info.uid): raise RuntimeError( "%r is already bound to %r on repo %r of %r" % ( local_root, existing_binding.remote_root, existing_binding.remote_repo, existing_binding.server_binding.server_url)) except NoResultFound: # Register the new binding itself log.info("Binding local root '%s' to '%s' (id=%s) on server '%s'", local_root, remote_info.name, remote_info.uid, server_binding.server_url) session.add(RootBinding(local_root, repository, remote_info.uid)) # Initialize the metadata info by recursive walk on the remote # folder structure self._recursive_init(lcclient, local_info, nxclient, remote_info) session.commit()
def test_streaming_upload(self): remote_client = self.remote_file_system_client_1 # Create a document by streaming a text file file_path = remote_client.make_tmp_file("Some content.") try: fs_item_info = remote_client.stream_file( self.workspace_id, file_path, filename='My streamed file.txt') finally: os.remove(file_path) fs_item_id = fs_item_info.uid self.assertEquals(fs_item_info.name, 'My streamed file.txt') self.assertEquals(remote_client.get_content(fs_item_id), "Some content.") # Update a document by streaming a new text file file_path = remote_client.make_tmp_file("Other content.") try: fs_item_info = remote_client.stream_update( fs_item_id, file_path, filename='My updated file.txt') finally: os.remove(file_path) self.assertEqual(fs_item_info.uid, fs_item_id) self.assertEquals(fs_item_info.name, 'My updated file.txt') self.assertEquals(remote_client.get_content(fs_item_id), "Other content.") # Create a document by streaming a binary file file_path = os.path.join(self.upload_tmp_dir, 'testFile.pdf') copyfile('nxdrive/tests/resources/testFile.pdf', file_path) fs_item_info = remote_client.stream_file(self.workspace_id, file_path) local_client = LocalClient(self.upload_tmp_dir) self.assertEquals(fs_item_info.name, 'testFile.pdf') self.assertEquals(fs_item_info.digest, local_client.get_info('/testFile.pdf').get_digest())
def test_bad_mime_type(self): remote_client = self.remote_file_system_client_1 # Create a document by streaming a binary file file_path = os.path.join(self.upload_tmp_dir, "testFile.pdf") copyfile("nxdrive/tests/resources/testFile.pdf", file_path) fs_item_id = remote_client.stream_file(self.workspace_id, file_path, mime_type="pdf") local_client = LocalClient(self.upload_tmp_dir) fs_item_info = remote_client.get_info(fs_item_id) self.assertEquals(fs_item_info.name, "testFile.pdf") self.assertEquals(fs_item_info.digest, local_client.get_info("/testFile.pdf").get_digest())
def test_bad_mime_type(self): remote_client = self.remote_file_system_client_1 # Create a document by streaming a binary file file_path = os.path.join(self.upload_tmp_dir, 'testFile.pdf') copyfile(self.location + '/resources/testFile.pdf', file_path) fs_item_info = remote_client.stream_file(self.workspace_id, file_path, mime_type='pdf') local_client = LocalClient(self.upload_tmp_dir) self.assertEqual(fs_item_info.name, 'testFile.pdf') self.assertEqual(fs_item_info.digest, local_client.get_info('/testFile.pdf').get_digest())
def _add_top_level_state(self, server_binding, session): local_client = LocalClient(server_binding.local_folder) local_info = local_client.get_info(u'/') remote_client = self.get_remote_fs_client(server_binding) remote_info = remote_client.get_filesystem_root_info() state = LastKnownState(server_binding.local_folder, local_info=local_info, local_state='synchronized', remote_info=remote_info, remote_state='synchronized') session.add(state)
def test_bad_mime_type(self): remote_client = self.remote_document_client_1 # Create a document by streaming a binary file file_path = os.path.join(self.upload_tmp_dir, 'testFile.pdf') copyfile(self.location + '/resources/testFile.pdf', file_path) doc_ref = remote_client.stream_file(self.workspace, 'Streamed binary file', file_path, mime_type='pdf') local_client = LocalClient(self.upload_tmp_dir) doc_info = remote_client.get_info(doc_ref) self.assertEqual(doc_info.name, 'Streamed binary file') self.assertEqual(doc_info.digest, local_client.get_info('/testFile.pdf').get_digest(digest_func=doc_info.digest_algorithm))
def test_bad_mime_type(self): remote_client = self.remote_document_client_1 # Create a document by streaming a binary file file_path = os.path.join(self.upload_tmp_dir, 'testFile.pdf') copyfile('nxdrive/tests/resources/testFile.pdf', file_path) doc_ref = remote_client.stream_file(self.workspace, 'Streamed binary file', file_path, mime_type='pdf') local_client = LocalClient(self.upload_tmp_dir) doc_info = remote_client.get_info(doc_ref) self.assertEquals(doc_info.name, 'Streamed binary file') self.assertEquals(doc_info.digest, local_client.get_info('/testFile.pdf').get_digest())
def test_bad_mime_type(self): remote_client = self.remote_document_client_1 # Create a document by streaming a binary file file_path = os.path.join(self.upload_tmp_dir, 'testFile.pdf') copyfile('nxdrive/tests/resources/testFile.pdf', file_path) doc_ref = remote_client.stream_file(self.workspace, 'Streamed binary file', file_path, mime_type='pdf') # Wait to make sure transaction is commited # TODO: remove when https://jira.nuxeo.com/browse/NXP-10964 is # fixed sleep(1.0) local_client = LocalClient(self.upload_tmp_dir) doc_info = remote_client.get_info(doc_ref) self.assertEquals(doc_info.name, 'Streamed binary file') self.assertEquals(doc_info.digest, local_client.get_info('/testFile.pdf').get_digest())
def test_streaming_upload(self): remote_client = self.remote_document_client_1 # Create a document by streaming a text file file_path = remote_client.make_tmp_file("Some content.") doc_ref = remote_client.stream_file(self.workspace, 'Streamed text file', file_path, filename='My streamed file.txt') # Wait to make sure transaction is commited # TODO: remove when https://jira.nuxeo.com/browse/NXP-10964 is # fixed sleep(1.0) self.assertEquals( remote_client.get_info(doc_ref).name, 'Streamed text file') self.assertEquals(remote_client.get_content(doc_ref), "Some content.") # Update a document by streaming a new text file file_path = remote_client.make_tmp_file("Other content.") remote_client.stream_update(doc_ref, file_path, filename='My updated file.txt') # As a workaround for https://jira.nuxeo.com/browse/NXP-10964, # wait for a while to ensure transaction is committed before # Blob response is serialized and sent to the client sleep(1.0) self.assertEquals(remote_client.get_content(doc_ref), "Other content.") # Create a document by streaming a binary file file_path = os.path.join(self.upload_tmp_dir, 'testFile.pdf') copyfile('nxdrive/tests/resources/testFile.pdf', file_path) doc_ref = remote_client.stream_file(self.workspace, 'Streamed binary file', file_path) # Wait to make sure transaction is commited # TODO: remove when https://jira.nuxeo.com/browse/NXP-10964 is # fixed sleep(1.0) local_client = LocalClient(self.upload_tmp_dir) doc_info = remote_client.get_info(doc_ref) self.assertEquals(doc_info.name, 'Streamed binary file') self.assertEquals(doc_info.digest, local_client.get_info('/testFile.pdf').get_digest())
def test_streaming_upload(self): remote_client = self.remote_file_system_client_1 # Create a document by streaming a text file file_path = remote_client.make_tmp_file("Some content.") fs_item_id = remote_client.stream_file(self.workspace_id, file_path, filename="My streamed file.txt") self.assertEquals(remote_client.get_info(fs_item_id).name, "My streamed file.txt") self.assertEquals(remote_client.get_content(fs_item_id), "Some content.") # Update a document by streaming a new text file file_path = remote_client.make_tmp_file("Other content.") remote_client.stream_update(fs_item_id, file_path, filename="My updated file.txt") self.assertEquals(remote_client.get_info(fs_item_id).name, "My updated file.txt") self.assertEquals(remote_client.get_content(fs_item_id), "Other content.") # Create a document by streaming a binary file file_path = os.path.join(self.upload_tmp_dir, "testFile.pdf") copyfile("nxdrive/tests/resources/testFile.pdf", file_path) fs_item_id = remote_client.stream_file(self.workspace_id, file_path) local_client = LocalClient(self.upload_tmp_dir) fs_item_info = remote_client.get_info(fs_item_id) self.assertEquals(fs_item_info.name, "testFile.pdf") self.assertEquals(fs_item_info.digest, local_client.get_info("/testFile.pdf").get_digest())
def test_concurrent_file_access(self): """Test update/deletion of a locally locked file. This is to simulate downstream synchronization of a file opened (thus locked) by any program under Windows, typically MS Word. The file should be blacklisted and not prevent synchronization of other pending items. Once the file is unlocked and the cooldown period is over it should be synchronized. """ # Bind the server and root workspace ctl = self.controller_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) # 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 file in the remote root workspace remote.make_file('/', 'test_update.docx', 'Some content to update.') remote.make_file('/', 'test_delete.docx', 'Some content to delete.') # Launch first synchronization syn = ctl.synchronizer self._synchronize(syn) self.assertTrue(local.exists('/test_update.docx')) self.assertTrue(local.exists('/test_delete.docx')) # Open locally synchronized files to lock them and generate a # WindowsError when trying to update / delete them file1_path = local.get_info('/test_update.docx').filepath file1_desc = open(file1_path, 'rb') file2_path = local.get_info('/test_delete.docx').filepath file2_desc = open(file2_path, 'rb') # Update /delete existing remote files and create a new remote file remote.update_content('/test_update.docx', 'Updated content.') remote.delete('/test_delete.docx') remote.make_file('/', 'other.docx', 'Other content.') # Synchronize self._synchronize(syn) if sys.platform == 'win32': # As local file are locked, a WindowsError should occur during the # local update process, therefore: # - Temporary download file (.part) should be created locally but # not renamed # - Opened local files should still exist and not have been # modified # - Synchronization should not fail: doc pairs should be # blacklisted, there should be 2 pending items and other remote # modifications should be locally synchronized self.assertTrue(local.exists('/.test_update.docx.part')) self.assertTrue(local.exists('/test_update.docx')) self.assertEquals(local.get_content('/test_update.docx'), 'Some content to update.') self.assertTrue(local.exists('/test_delete.docx')) self.assertEquals(local.get_content('/test_delete.docx'), 'Some content to delete.') self.assertEquals(len(ctl.list_pending()), 2) self.assertTrue(local.exists('/other.docx')) self.assertEquals(local.get_content('/other.docx'), 'Other content.') # Synchronize again syn.loop(delay=0.1, max_loops=1) # Blacklisted files should be ignored as delay (300 seconds by # default) is not expired, nothing should have changed self.assertTrue(local.exists('/.test_update.docx.part')) self.assertTrue(local.exists('/test_update.docx')) self.assertEquals(local.get_content('/test_update.docx'), 'Some content to update.') self.assertTrue(local.exists('/test_delete.docx')) self.assertEquals(local.get_content('/test_delete.docx'), 'Some content to delete.') self.assertEquals(len(ctl.list_pending()), 2) # Release file locks by closing them file1_desc.close() file2_desc.close() # Reduce error skip delay to retry synchronization of pairs in # error syn.error_skip_period = 1.0 time.sleep(syn.error_skip_period) syn.loop(delay=0.1, max_loops=1) # Previously blacklisted files should be updated / deleted locally, # temporary download file should not be there anymore and there # should be no pending items left self.assertTrue(local.exists('/test_update.docx')) self.assertEquals(local.get_content('/test_update.docx'), 'Updated content.') self.assertFalse(local.exists('/.test_update.docx.part')) self.assertFalse(local.exists('/test_delete.docx')) self.assertEquals(len(ctl.list_pending()), 0) else: self.assertTrue(local.exists('/test_update.docx')) self.assertEquals(local.get_content('/test_update.docx'), 'Updated content.') self.assertFalse(local.exists('/.test_update.docx.part')) self.assertFalse(local.exists('/test_delete.docx')) self.assertEquals(len(ctl.list_pending()), 0)
def test_remote_rename_sync_root_folder(self): remote_client = self.remote_client_1 local_client = LocalClient(self.local_nxdrive_folder_1) # Rename a sync root folder remote_client.rename(self.workspace_id, u'Renamed Nuxeo Drive Test Workspace') self.assertEquals( remote_client.get_info(self.workspace_id).name, u'Renamed Nuxeo Drive Test Workspace') # Synchronize: only the sync root folder renaming is detected: all # the descendants are automatically realigned self.wait_sync(wait_for_async=True) # The client folder has been renamed self.assertFalse(local_client.exists(u'/Nuxeo Drive Test Workspace')) self.assertTrue( local_client.exists(u'/Renamed Nuxeo Drive Test Workspace')) renamed_workspace_path = os.path.join( self.local_nxdrive_folder_1, u'Renamed Nuxeo Drive Test Workspace') # The content of the renamed folder is left unchanged # Check child name self.assertTrue( local_client.exists( u'/Renamed Nuxeo Drive Test Workspace/Original File 1.txt')) file_1_local_info = local_client.get_info( u'/Renamed Nuxeo Drive Test Workspace/Original File 1.txt') file_1_parent_path = os.path.dirname(file_1_local_info.filepath) self.assertEquals(file_1_parent_path, renamed_workspace_path) # Check child state file_1_state = self._get_state(self.file_1_id) self.assertEquals( file_1_state.local_path, u'/Renamed Nuxeo Drive Test Workspace/Original File 1.txt') self.assertEquals(file_1_state.local_name, u'Original File 1.txt') # Check child name self.assertTrue( local_client.exists( u'/Renamed Nuxeo Drive Test Workspace/Original Folder 1')) folder_1_local_info = local_client.get_info( u'/Renamed Nuxeo Drive Test Workspace/Original Folder 1') folder_1_parent_path = os.path.dirname(folder_1_local_info.filepath) self.assertEquals(folder_1_parent_path, renamed_workspace_path) # Check child state folder_1_state = self._get_state(self.folder_1_id) self.assertEquals( folder_1_state.local_path, u'/Renamed Nuxeo Drive Test Workspace/Original Folder 1') self.assertEquals(folder_1_state.local_name, u'Original Folder 1') # Check child name self.assertTrue( local_client.exists(u'/Renamed Nuxeo Drive Test Workspace/' u'Original Folder 1/Sub-Folder 1.1')) folder_1_1_local_info = local_client.get_info( u'/Renamed Nuxeo Drive Test Workspace/' u'Original Folder 1/Sub-Folder 1.1') folder_1_1_parent_path = os.path.dirname( folder_1_1_local_info.filepath) self.assertEquals( folder_1_1_parent_path, os.path.join(renamed_workspace_path, u'Original Folder 1')) # Check child state folder_1_1_state = self._get_state(self.folder_1_1_id) self.assertEquals( folder_1_1_state.local_path, u'/Renamed Nuxeo Drive Test Workspace' '/Original Folder 1/Sub-Folder 1.1') self.assertEquals(folder_1_1_state.local_name, u'Sub-Folder 1.1') # Check child name self.assertTrue( local_client.exists(u'/Renamed Nuxeo Drive Test Workspace/' u'Original Folder 1/Original File 1.1.txt')) file_1_1_local_info = local_client.get_info( u'/Renamed Nuxeo Drive Test Workspace/' 'Original Folder 1/Original File 1.1.txt') file_1_1_parent_path = os.path.dirname(file_1_1_local_info.filepath) self.assertEquals( file_1_1_parent_path, os.path.join(renamed_workspace_path, u'Original Folder 1')) # Check child state file_1_1_state = self._get_state(self.file_1_1_id) self.assertEquals( file_1_1_state.local_path, u'/Renamed Nuxeo Drive Test Workspace' '/Original Folder 1/Original File 1.1.txt') self.assertEquals(file_1_1_state.local_name, u'Original File 1.1.txt')
def test_remote_rename_sync_root_folder(self): remote_client = self.remote_client_1 local_client = LocalClient(self.local_nxdrive_folder_1) # Rename a sync root folder remote_client.rename(self.workspace_id, u'Renamed Nuxeo Drive Test Workspace') self.assertEquals(remote_client.get_info(self.workspace_id).name, u'Renamed Nuxeo Drive Test Workspace') # Synchronize: only the sync root folder renaming is detected: all # the descendants are automatically realigned self.wait_sync(wait_for_async=True) # The client folder has been renamed self.assertFalse(local_client.exists(u'/Nuxeo Drive Test Workspace')) self.assertTrue(local_client.exists( u'/Renamed Nuxeo Drive Test Workspace')) renamed_workspace_path = os.path.join(self.local_nxdrive_folder_1, u'Renamed Nuxeo Drive Test Workspace') # The content of the renamed folder is left unchanged # Check child name self.assertTrue(local_client.exists( u'/Renamed Nuxeo Drive Test Workspace/Original File 1.txt')) file_1_local_info = local_client.get_info( u'/Renamed Nuxeo Drive Test Workspace/Original File 1.txt') file_1_parent_path = os.path.dirname(file_1_local_info.filepath) self.assertEquals(file_1_parent_path, renamed_workspace_path) # Check child state file_1_state = self._get_state(self.file_1_id) self.assertEquals(file_1_state.local_path, u'/Renamed Nuxeo Drive Test Workspace/Original File 1.txt') self.assertEquals(file_1_state.local_name, u'Original File 1.txt') # Check child name self.assertTrue(local_client.exists( u'/Renamed Nuxeo Drive Test Workspace/Original Folder 1')) folder_1_local_info = local_client.get_info( u'/Renamed Nuxeo Drive Test Workspace/Original Folder 1') folder_1_parent_path = os.path.dirname(folder_1_local_info.filepath) self.assertEquals(folder_1_parent_path, renamed_workspace_path) # Check child state folder_1_state = self._get_state(self.folder_1_id) self.assertEquals(folder_1_state.local_path, u'/Renamed Nuxeo Drive Test Workspace/Original Folder 1') self.assertEquals(folder_1_state.local_name, u'Original Folder 1') # Check child name self.assertTrue(local_client.exists( u'/Renamed Nuxeo Drive Test Workspace/' u'Original Folder 1/Sub-Folder 1.1')) folder_1_1_local_info = local_client.get_info( u'/Renamed Nuxeo Drive Test Workspace/' u'Original Folder 1/Sub-Folder 1.1') folder_1_1_parent_path = os.path.dirname( folder_1_1_local_info.filepath) self.assertEquals(folder_1_1_parent_path, os.path.join(renamed_workspace_path, u'Original Folder 1')) # Check child state folder_1_1_state = self._get_state(self.folder_1_1_id) self.assertEquals(folder_1_1_state.local_path, u'/Renamed Nuxeo Drive Test Workspace' '/Original Folder 1/Sub-Folder 1.1') self.assertEquals(folder_1_1_state.local_name, u'Sub-Folder 1.1') # Check child name self.assertTrue(local_client.exists( u'/Renamed Nuxeo Drive Test Workspace/' u'Original Folder 1/Original File 1.1.txt')) file_1_1_local_info = local_client.get_info( u'/Renamed Nuxeo Drive Test Workspace/' 'Original Folder 1/Original File 1.1.txt') file_1_1_parent_path = os.path.dirname(file_1_1_local_info.filepath) self.assertEquals(file_1_1_parent_path, os.path.join(renamed_workspace_path, u'Original Folder 1')) # Check child state file_1_1_state = self._get_state(self.file_1_1_id) self.assertEquals(file_1_1_state.local_path, u'/Renamed Nuxeo Drive Test Workspace' '/Original Folder 1/Original File 1.1.txt') self.assertEquals(file_1_1_state.local_name, u'Original File 1.1.txt')
def test_remote_rename_sync_root_folder(self): sb, ctl = self.sb_1, self.controller_1 remote_client = self.remote_client_1 local_client = LocalClient(self.local_nxdrive_folder_1) session = ctl.get_session() # Rename a sync root folder remote_client.rename(self.workspace_id, u'Renamed Nuxeo Drive Test Workspace') self.assertEquals(remote_client.get_info(self.workspace_id).name, u'Renamed Nuxeo Drive Test Workspace') # Synchronize: only the sync root folder renaming is detected: all # the descendants are automatically realigned time.sleep(self.AUDIT_CHANGE_FINDER_TIME_RESOLUTION) self.wait() self.assertEquals(ctl.synchronizer.update_synchronize_server(sb), 1) # The client folder has been renamed self.assertFalse(local_client.exists(u'/Nuxeo Drive Test Workspace')) self.assertTrue(local_client.exists( u'/Renamed Nuxeo Drive Test Workspace')) renamed_workspace_path = os.path.join(self.local_nxdrive_folder_1, u'Renamed Nuxeo Drive Test Workspace') # The content of the renamed folder is left unchanged # Check child name self.assertTrue(local_client.exists( u'/Renamed Nuxeo Drive Test Workspace/Original File 1.txt')) file_1_local_info = local_client.get_info( u'/Renamed Nuxeo Drive Test Workspace/Original File 1.txt') file_1_parent_path = os.path.dirname(file_1_local_info.filepath) self.assertEquals(file_1_parent_path, renamed_workspace_path) # Check child state file_1_state = session.query(LastKnownState).filter_by( remote_name=u'Original File 1.txt').one() self.assertEquals(file_1_state.local_path, u'/Renamed Nuxeo Drive Test Workspace/Original File 1.txt') self.assertEquals(file_1_state.local_name, u'Original File 1.txt') # Check child name self.assertTrue(local_client.exists( u'/Renamed Nuxeo Drive Test Workspace/Original Folder 1')) folder_1_local_info = local_client.get_info( u'/Renamed Nuxeo Drive Test Workspace/Original Folder 1') folder_1_parent_path = os.path.dirname(folder_1_local_info.filepath) self.assertEquals(folder_1_parent_path, renamed_workspace_path) # Check child state folder_1_state = session.query(LastKnownState).filter_by( remote_name=u'Original Folder 1').one() self.assertEquals(folder_1_state.local_path, u'/Renamed Nuxeo Drive Test Workspace/Original Folder 1') self.assertEquals(folder_1_state.local_name, u'Original Folder 1') # Check child name self.assertTrue(local_client.exists( u'/Renamed Nuxeo Drive Test Workspace/' u'Original Folder 1/Sub-Folder 1.1')) folder_1_1_local_info = local_client.get_info( u'/Renamed Nuxeo Drive Test Workspace/' u'Original Folder 1/Sub-Folder 1.1') folder_1_1_parent_path = os.path.dirname( folder_1_1_local_info.filepath) self.assertEquals(folder_1_1_parent_path, os.path.join(renamed_workspace_path, u'Original Folder 1')) # Check child state folder_1_1_state = session.query(LastKnownState).filter_by( remote_name=u'Sub-Folder 1.1').one() self.assertEquals(folder_1_1_state.local_path, u'/Renamed Nuxeo Drive Test Workspace' '/Original Folder 1/Sub-Folder 1.1') self.assertEquals(folder_1_1_state.local_name, u'Sub-Folder 1.1') # Check child name self.assertTrue(local_client.exists( u'/Renamed Nuxeo Drive Test Workspace/' u'Original Folder 1/Original File 1.1.txt')) file_1_1_local_info = local_client.get_info( u'/Renamed Nuxeo Drive Test Workspace/' 'Original Folder 1/Original File 1.1.txt') file_1_1_parent_path = os.path.dirname(file_1_1_local_info.filepath) self.assertEquals(file_1_1_parent_path, os.path.join(renamed_workspace_path, u'Original Folder 1')) # Check child state file_1_1_state = session.query(LastKnownState).filter_by( remote_name=u'Original File 1.1.txt').one() self.assertEquals(file_1_1_state.local_path, u'/Renamed Nuxeo Drive Test Workspace' '/Original Folder 1/Original File 1.1.txt') self.assertEquals(file_1_1_state.local_name, u'Original File 1.1.txt') # The more things change, the more they remain the same. time.sleep(self.AUDIT_CHANGE_FINDER_TIME_RESOLUTION) self.wait() self.assertEquals(ctl.synchronizer.update_synchronize_server(sb), 0)
def test_remote_rename_sync_root_folder(self): sb, ctl = self.sb_1, self.controller_1 remote_client = self.remote_client_1 local_client = LocalClient(self.local_nxdrive_folder_1) session = ctl.get_session() # Rename a sync root folder remote_client.rename(self.workspace_id, u'Renamed Nuxeo Drive Test Workspace') self.assertEquals( remote_client.get_info(self.workspace_id).name, u'Renamed Nuxeo Drive Test Workspace') # Synchronize: only the sync root folder renaming is detected: all # the descendants are automatically realigned self.wait_audit_change_finder_if_needed() self.wait() self.assertEquals(ctl.synchronizer.update_synchronize_server(sb), 1) # The client folder has been renamed self.assertFalse(local_client.exists(u'/Nuxeo Drive Test Workspace')) self.assertTrue( local_client.exists(u'/Renamed Nuxeo Drive Test Workspace')) renamed_workspace_path = os.path.join( self.local_nxdrive_folder_1, u'Renamed Nuxeo Drive Test Workspace') # The content of the renamed folder is left unchanged # Check child name self.assertTrue( local_client.exists( u'/Renamed Nuxeo Drive Test Workspace/Original File 1.txt')) file_1_local_info = local_client.get_info( u'/Renamed Nuxeo Drive Test Workspace/Original File 1.txt') file_1_parent_path = os.path.dirname(file_1_local_info.filepath) self.assertEquals(file_1_parent_path, renamed_workspace_path) # Check child state file_1_state = session.query(LastKnownState).filter_by( remote_name=u'Original File 1.txt').one() self.assertEquals( file_1_state.local_path, u'/Renamed Nuxeo Drive Test Workspace/Original File 1.txt') self.assertEquals(file_1_state.local_name, u'Original File 1.txt') # Check child name self.assertTrue( local_client.exists( u'/Renamed Nuxeo Drive Test Workspace/Original Folder 1')) folder_1_local_info = local_client.get_info( u'/Renamed Nuxeo Drive Test Workspace/Original Folder 1') folder_1_parent_path = os.path.dirname(folder_1_local_info.filepath) self.assertEquals(folder_1_parent_path, renamed_workspace_path) # Check child state folder_1_state = session.query(LastKnownState).filter_by( remote_name=u'Original Folder 1').one() self.assertEquals( folder_1_state.local_path, u'/Renamed Nuxeo Drive Test Workspace/Original Folder 1') self.assertEquals(folder_1_state.local_name, u'Original Folder 1') # Check child name self.assertTrue( local_client.exists(u'/Renamed Nuxeo Drive Test Workspace/' u'Original Folder 1/Sub-Folder 1.1')) folder_1_1_local_info = local_client.get_info( u'/Renamed Nuxeo Drive Test Workspace/' u'Original Folder 1/Sub-Folder 1.1') folder_1_1_parent_path = os.path.dirname( folder_1_1_local_info.filepath) self.assertEquals( folder_1_1_parent_path, os.path.join(renamed_workspace_path, u'Original Folder 1')) # Check child state folder_1_1_state = session.query(LastKnownState).filter_by( remote_name=u'Sub-Folder 1.1').one() self.assertEquals( folder_1_1_state.local_path, u'/Renamed Nuxeo Drive Test Workspace' '/Original Folder 1/Sub-Folder 1.1') self.assertEquals(folder_1_1_state.local_name, u'Sub-Folder 1.1') # Check child name self.assertTrue( local_client.exists(u'/Renamed Nuxeo Drive Test Workspace/' u'Original Folder 1/Original File 1.1.txt')) file_1_1_local_info = local_client.get_info( u'/Renamed Nuxeo Drive Test Workspace/' 'Original Folder 1/Original File 1.1.txt') file_1_1_parent_path = os.path.dirname(file_1_1_local_info.filepath) self.assertEquals( file_1_1_parent_path, os.path.join(renamed_workspace_path, u'Original Folder 1')) # Check child state file_1_1_state = session.query(LastKnownState).filter_by( remote_name=u'Original File 1.1.txt').one() self.assertEquals( file_1_1_state.local_path, u'/Renamed Nuxeo Drive Test Workspace' '/Original Folder 1/Original File 1.1.txt') self.assertEquals(file_1_1_state.local_name, u'Original File 1.1.txt') # The more things change, the more they remain the same. self.wait_audit_change_finder_if_needed() self.wait() self.assertEquals(ctl.synchronizer.update_synchronize_server(sb), 0)
def test_concurrent_file_access(self): """Test update/deletion of a locally locked file. This is to simulate downstream synchronization of a file opened (thus locked) by any program under Windows, typically MS Word. The file should be blacklisted and not prevent synchronization of other pending items. Once the file is unlocked and the cooldown period is over it should be synchronized. """ # Bind the server and root workspace ctl = self.controller_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) # 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 file in the remote root workspace remote.make_file('/', 'test_update.docx', 'Some content to update.') remote.make_file('/', 'test_delete.docx', 'Some content to delete.') # Launch first synchronization syn = ctl.synchronizer self._synchronize(syn) self.assertTrue(local.exists('/test_update.docx')) self.assertTrue(local.exists('/test_delete.docx')) # Open locally synchronized files to lock them and generate a # WindowsError when trying to update / delete them file1_path = local.get_info('/test_update.docx').filepath file1_desc = open(file1_path, 'rb') file2_path = local.get_info('/test_delete.docx').filepath file2_desc = open(file2_path, 'rb') # Update /delete existing remote files and create a new remote file remote.update_content('/test_update.docx', 'Updated content.') remote.delete('/test_delete.docx') remote.make_file('/', 'other.docx', 'Other content.') # Synchronize self._synchronize(syn) if sys.platform == 'win32': # As local file are locked, a WindowsError should occur during the # local update process, therefore: # - Temporary download file (.part) should be created locally but # not renamed # - Opened local files should still exist and not have been # modified # - Synchronization should not fail: doc pairs should be # blacklisted, there should be 2 pending items and other remote # modifications should be locally synchronized self.assertTrue(local.exists('/.test_update.docx.part')) self.assertTrue(local.exists('/test_update.docx')) self.assertEquals(local.get_content('/test_update.docx'), 'Some content to update.') self.assertTrue(local.exists('/test_delete.docx')) self.assertEquals(local.get_content('/test_delete.docx'), 'Some content to delete.') self.assertEquals(len(ctl.list_pending()), 2) self.assertTrue(local.exists('/other.docx')) self.assertEquals(local.get_content('/other.docx'), 'Other content.') # Synchronize again syn.loop(delay=0.1, max_loops=1) # Blacklisted files should be ignored as delay (300 seconds by # default) is not expired, nothing should have changed self.assertTrue(local.exists('/.test_update.docx.part')) self.assertTrue(local.exists('/test_update.docx')) self.assertEquals(local.get_content('/test_update.docx'), 'Some content to update.') self.assertTrue(local.exists('/test_delete.docx')) self.assertEquals(local.get_content('/test_delete.docx'), 'Some content to delete.') self.assertEquals(len(ctl.list_pending()), 2) # Release file locks by closing them file1_desc.close() file2_desc.close() # Reduce error skip delay to retry synchronization of pairs in # error syn.error_skip_period = 1.0 time.sleep(syn.error_skip_period) syn.loop(delay=0.1, max_loops=1) # Previously blacklisted files should be updated / deleted locally, # temporary download file should not be there anymore and there # should be no pending items left self.assertTrue(local.exists('/test_update.docx')) self.assertEquals(local.get_content('/test_update.docx'), 'Updated content.') self.assertFalse(local.exists('/.test_update.docx.part')) self.assertFalse(local.exists('/test_delete.docx')) self.assertEquals(len(ctl.list_pending()), 0) else: self.assertTrue(local.exists('/test_update.docx')) self.assertEquals(local.get_content('/test_update.docx'), 'Updated content.') self.assertFalse(local.exists('/.test_update.docx.part')) self.assertFalse(local.exists('/test_delete.docx')) self.assertEquals(len(ctl.list_pending()), 0)
def bind_server(self, local_folder, server_url, username, password): """Bind a local folder to a remote nuxeo server""" session = self.get_session() local_folder = normalized_path(local_folder) if not os.path.exists(local_folder): os.makedirs(local_folder) self.register_folder_link(local_folder) # check the connection to the server by issuing an authentication # request server_url = self._normalize_url(server_url) nxclient = self.remote_doc_client_factory( server_url, username, self.device_id, password) token = nxclient.request_token() if token is not None: # The server supports token based identification: do not store the # password in the DB password = None try: server_binding = session.query(ServerBinding).filter( ServerBinding.local_folder == local_folder).one() if (server_binding.remote_user != username or server_binding.server_url != server_url): raise RuntimeError( "%s is already bound to '%s' with user '%s'" % ( local_folder, server_binding.server_url, server_binding.remote_user)) if token is None and server_binding.remote_password != password: # Update password info if required server_binding.remote_password = password log.info("Updating password for user '%s' on server '%s'", username, server_url) if token is not None and server_binding.remote_token != token: log.info("Updating token for user '%s' on server '%s'", username, server_url) # Update the token info if required server_binding.remote_token = token # Ensure that the password is not stored in the DB if server_binding.remote_password is not None: server_binding.remote_password = None except NoResultFound: log.info("Binding '%s' to '%s' with account '%s'", local_folder, server_url, username) server_binding = ServerBinding(local_folder, server_url, username, remote_password=password, remote_token=token) session.add(server_binding) # Creating the toplevel state for the server binding local_client = LocalClient(server_binding.local_folder) local_info = local_client.get_info(u'/') remote_client = self.get_remote_fs_client(server_binding) remote_info = remote_client.get_filesystem_root_info() state = LastKnownState(server_binding.local_folder, local_info=local_info, local_state='synchronized', remote_info=remote_info, remote_state='synchronized') session.add(state) session.commit() return server_binding