[INFO] [exec] FAIL nuxeo-drive-client/tests/test_bulk_remote_changes.py::TestBulkRemoteChanges::test_many_changes [INFO] [exec] =================================== FAILURES =================================== [INFO] [exec] ___________________ TestBulkRemoteChanges.test_many_changes ____________________ [INFO] [exec] self = <tests.test_bulk_remote_changes.TestBulkRemoteChanges testMethod=test_many_changes> [INFO] [exec] @patch.object(RemoteFileSystemClient, 'get_children_info', mock_get_children_info) [INFO] [exec] @patch.object(RemoteFileSystemClient, 'file_to_info', mock_file_to_info) [INFO] [exec] def test_many_changes(self): [INFO] [exec] """ [INFO] [exec] Objective: The objective is to make a lot of remote changes (including a folder modified) and [INFO] [exec] wait for nuxeo-drive to successfully sync even if network error happens [INFO] [exec] 1. Configure drive and wait for sync [INFO] [exec] 2. Create 3 folders folder1, folder2 and shared [INFO] [exec] 3. Create files inside the 3 folders: folder1/file1.txt, folder2/file2.txt, [INFO] [exec] shared/readme1.txt, shared/readme2.txt [INFO] [exec] 4. Wait for 3 folders, 4 folder to sync to local PC [INFO] [exec] 5. Check the 3 folders and 4 files are synced to local PC [INFO] [exec] 6. Trigger simulation of network error for GetChildren API using the mock (2 successive failures) [INFO] [exec] 7. Do the following changes in DM side in same order: [INFO] [exec] I. Create 'folder1/sample1.txt' [INFO] [exec] II. Delete 'shared' folder, and immediately restore 'shared' folder [INFO] [exec] IV. Restore 'shared/readme1.txt' [INFO] [exec] V. Create 'shared/readme3.txt' [INFO] [exec] VI. Create 'folder2/sample2.txt' [INFO] [exec] 8. Wait for remote changes to sync for unaffected folders folder1 and folder2 [INFO] [exec] 9. Check that folder1/sample1.txt and folder2/sample2.txt are synced to local PC [INFO] [exec] 10. Sleep for two remote scan attempts (to compenstate for two network failures) [INFO] [exec] 11. Check if two files 'shared/readme1.txt' and 'shared/readme3.txt' are synced to local PC [INFO] [exec] """ [INFO] [exec] global network_error [INFO] [exec] remote_client = self.remote_document_client_1 [INFO] [exec] local_client = self.local_client_1 [INFO] [exec] self.engine_1.start() [INFO] [exec] self.step("1. Configure drive and wait for sync") [INFO] [exec] self.wait_sync(wait_for_async=True) [INFO] [exec] # create some folders on the server [INFO] [exec] self.step("2. Create 3 folders folder1, folder2 and shared") [INFO] [exec] folder1 = remote_client.make_folder(self.workspace, u"folder1") [INFO] [exec] shared = remote_client.make_folder(self.workspace, u"shared") [INFO] [exec] folder2 = remote_client.make_folder(self.workspace, u"folder2") [INFO] [exec] self.step("3. Create files inside the 3 folders: folder1/file1.txt, folder2/file2.txt, shared/readme1.txt, shared/readme2.txt") [INFO] [exec] readme1 = remote_client.make_file(shared, "readme1.txt", "This is a readme file") [INFO] [exec] readme2 = remote_client.make_file(shared, "readme2.txt", "This is a readme file") [INFO] [exec] remote_client.make_file(folder1, "file1.txt", "This is a sample file1") [INFO] [exec] remote_client.make_file(folder2, "file2.txt", "This is a sample file2") [INFO] [exec] self.step("4. Wait for 3 folders, 4 folder to sync to local PC") [INFO] [exec] self.wait_sync(wait_for_async=True) [INFO] [exec] self.confirm("5. Check the 3 folders and 4 files are synced to local PC " + [INFO] [exec] "/folder1/file1.txt, /folder2/file2.txt, /shared/readme1.txt, /shared/readme2.txt") [INFO] [exec] self.assertTrue(local_client.exists('/folder1'), "'/folder1' should sync") [INFO] [exec] self.assertTrue(local_client.exists('/folder2'), "'/folder1' should sync") [INFO] [exec] self.assertTrue(local_client.exists('/shared'), "'/shared' folder should sync") [INFO] [exec] self.assertTrue(local_client.exists('/folder1/file1.txt'), "'/folder1/file1.txt' should sync") [INFO] [exec] self.assertTrue(local_client.exists('/folder2/file2.txt'), "'/folder2/file2.txt' should sync") [INFO] [exec] self.assertTrue(local_client.exists('/shared/readme1.txt'), "'/shared/readme1.txt' should sync") [INFO] [exec] self.assertTrue(local_client.exists('/shared/readme2.txt'), "'/shared/readme2.txt' should sync") [INFO] [exec] # Simulate network error for GetChildren API twice [INFO] [exec] # This is to ensure drive will eventually recover even after multiple failures of GetChildren API [INFO] [exec] self.step("6. Trigger simulation of network error for GetChildren API using the mock (2 successive failures)") [INFO] [exec] network_error = 2 [INFO] [exec] self.step("7. Do the following changes in DM side in this order => Create 'folder1/sample1.txt', " + [INFO] [exec] " Delete 'shared' folder, and immediately restore 'shared' folder, Restore 'shared/readme1.txt'" + [INFO] [exec] " Create 'shared/readme3.txt', Create 'folder2/sample2.txt'") [INFO] [exec] remote_client.make_file(folder1, "sample1.txt", "This is a another sample file1") [INFO] [exec] self.remote_document_client_2.register_as_root(shared) [INFO] [exec] # Delete folder 'shared' [INFO] [exec] remote_client.delete(shared) [INFO] [exec] # Restore folder 'shared' from trash [INFO] [exec] remote_client.undelete(shared) [INFO] [exec] # restore file 'shared/readme1.txt' from trash [INFO] [exec] > remote_client.undelete(readme1) [INFO] [exec] folder1 = 'b397a741-5ed8-4a1e-9572-bce67ac36d89' [INFO] [exec] folder2 = '7302f39a-f93a-494c-90a5-3164113c89d5' [INFO] [exec] local_client = <tests.mac_local_client.MacLocalClient object at 0x114d80b10> [INFO] [exec] readme1 = '313c9581-4042-49a0-9264-e9d0ccd285fc' [INFO] [exec] readme2 = 'd8e7c847-74ba-44fa-98b1-5ab5f5e24c47' [INFO] [exec] remote_client = <RemoteDocumentClient base_folder=None, blob_timeout=60, check_suspended=None,...UL3SF5V2PSVOUZC4CRBQLRIA/tmp/tmpRyv4gO-nxdrive-uploads', user_id='driveuser_1'> [INFO] [exec] self = <tests.test_bulk_remote_changes.TestBulkRemoteChanges testMethod=test_many_changes> [INFO] [exec] shared = '9569d608-710e-41d7-99ca-80dbbd173da9' [INFO] [exec] nuxeo-drive-client/tests/test_bulk_remote_changes.py:154: [INFO] [exec] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ [INFO] [exec] nuxeo-drive-client/nxdrive/client/remote_document_client.py:213: in undelete [INFO] [exec] value='undelete') [INFO] [exec] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ [INFO] [exec] self = <RemoteDocumentClient base_folder=None, blob_timeout=60, check_suspended=None,...UL3SF5V2PSVOUZC4CRBQLRIA/tmp/tmpRyv4gO-nxdrive-uploads', user_id='driveuser_1'> [INFO] [exec] command = 'Document.SetLifeCycle' [INFO] [exec] url = 'http://localhost:8080/nuxeo/site/automation/Document.SetLifeCycle' [INFO] [exec] op_input = 'doc:313c9581-4042-49a0-9264-e9d0ccd285fc', timeout = 20 [INFO] [exec] check_params = True, void_op = False, extra_headers = None, file_out = None [INFO] [exec] params = {'value': 'undelete'} [INFO] [exec] headers = {'Accept': 'application/json+nxentity, */*', 'Authorization': 'Basic ZHJpdmV1c2VyXzE6NGU0ODhl', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json+nxrequest', ...} [INFO] [exec] json_struct = {'input': 'doc:313c9581-4042-49a0-9264-e9d0ccd285fc', 'params': {'value': 'undelete'}} [INFO] [exec] k = 'value', v = 'undelete' [INFO] [exec] def execute(self, command, url=None, op_input=None, timeout=-1, [INFO] [exec] check_params=True, void_op=False, extra_headers=None, [INFO] [exec] file_out=None, **params): [INFO] [exec] """Execute an Automation operation""" [INFO] [exec] if check_params: [INFO] [exec] self._check_params(command, params) [INFO] [exec] if url is None: [INFO] [exec] url = self.automation_url + command [INFO] [exec] headers = { [INFO] [exec] "Content-Type": "application/json+nxrequest", [INFO] [exec] "Accept": "application/json+nxentity, */*", [INFO] [exec] "X-NXproperties": "*", [INFO] [exec] # Keep compatibility with old header name [INFO] [exec] "X-NXDocumentProperties": "*", [INFO] [exec] } [INFO] [exec] if void_op: [INFO] [exec] headers.update({"X-NXVoidOperation": "true"}) [INFO] [exec] if self.repository != DEFAULT_REPOSITORY_NAME: [INFO] [exec] headers.update({"X-NXRepository": self.repository}) [INFO] [exec] if extra_headers is not None: [INFO] [exec] headers.update(extra_headers) [INFO] [exec] headers.update(self._get_common_headers()) [INFO] [exec] json_struct = {'params': {}} [INFO] [exec] for k, v in params.items(): [INFO] [exec] if v is None: [INFO] [exec] continue [INFO] [exec] if k == 'properties': [INFO] [exec] s = "" [INFO] [exec] for propname, propvalue in v.items(): [INFO] [exec] s += "%s=%s\n" % (propname, propvalue) [INFO] [exec] json_struct['params'][k] = s.strip() [INFO] [exec] else: [INFO] [exec] json_struct['params'][k] = v [INFO] [exec] if op_input: [INFO] [exec] json_struct['input'] = op_input [INFO] [exec] data = json.dumps(json_struct) [INFO] [exec] cookies = self._get_cookies() [INFO] [exec] log.trace("Calling %s with headers %r, cookies %r" [INFO] [exec] " and JSON payload %r", [INFO] [exec] url, headers, cookies, data) [INFO] [exec] req = urllib2.Request(url, data, headers) [INFO] [exec] timeout = self.timeout if timeout == -1 else timeout [INFO] [exec] try: [INFO] [exec] resp = self.opener.open(req, timeout=timeout) [INFO] [exec] except Exception as e: [INFO] [exec] log_details = self._log_details(e) [INFO] [exec] if isinstance(log_details, tuple): [INFO] [exec] _, _, _, error = log_details [INFO] [exec] if error and error.startswith("Unable to find batch"): [INFO] [exec] raise InvalidBatchException() [INFO] [exec] > raise e [INFO] [exec] E HTTPError: HTTP Error 500: Erreur Interne de Servlet [INFO] [exec] _ = 'Failed to invoke operation: Document.FollowLifecycleTransition' [INFO] [exec] check_params = True [INFO] [exec] command = 'Document.SetLifeCycle' [INFO] [exec] cookies = [] [INFO] [exec] data = '{"input": "doc:313c9581-4042-49a0-9264-e9d0ccd285fc", "params": {"value": "undelete"}}' [INFO] [exec] e = HTTPError() [INFO] [exec] error = None [INFO] [exec] extra_headers = None [INFO] [exec] file_out = None [INFO] [exec] headers = {'Accept': 'application/json+nxentity, */*', 'Authorization': 'Basic ZHJpdmV1c2VyXzE6NGU0ODhl', 'Cache-Control': 'no-cache', 'Content-Type': 'application/json+nxrequest', ...} [INFO] [exec] json_struct = {'input': 'doc:313c9581-4042-49a0-9264-e9d0ccd285fc', 'params': {'value': 'undelete'}} [INFO] [exec] k = 'value' [INFO] [exec] log_details = (500, 'org.nuxeo.ecm.automation.OperationException', 'Failed to invoke operation: Document.FollowLifecycleTransition', None) [INFO] [exec] op_input = 'doc:313c9581-4042-49a0-9264-e9d0ccd285fc' [INFO] [exec] params = {'value': 'undelete'} [INFO] [exec] req = <urllib2.Request instance at 0x114d7e6c8> [INFO] [exec] self = <RemoteDocumentClient base_folder=None, blob_timeout=60, check_suspended=None,...UL3SF5V2PSVOUZC4CRBQLRIA/tmp/tmpRyv4gO-nxdrive-uploads', user_id='driveuser_1'> [INFO] [exec] timeout = 20 [INFO] [exec] url = 'http://localhost:8080/nuxeo/site/automation/Document.SetLifeCycle' [INFO] [exec] v = 'undelete' [INFO] [exec] void_op = False [INFO] [exec] nuxeo-drive-client/nxdrive/client/base_automation_client.py:369: HTTPError