def tearDown(self): with cloudant(self.user, self.passwd, account=self.user) as c: replicator = Replicator(c) while self.replication_ids: replicator.stop_replication(self.replication_ids.pop()) while self.dbs: c.delete_database(self.dbs.pop())
def configure_replicator(client, source_db, target_db): """ Currently we try and start a replication, if that fails that means one already exists. So we stop it and create a new one. https://python-cloudant.readthedocs.io/en/latest/replicator.html#module-cloudant.replicator How can we configure couchdb to delete this data... """ replicator = Replicator(client) replication_id = f"{source_db.database_name}_to_{target_db.database_name}" try: replication_doc = start_replication(replicator, source_db, target_db, replication_id) except: replicator.stop_replication(repl_id=replication_id) replication_doc = start_replication(replicator, source_db, target_db, replication_id)
def test_stop_replication(self): """test stop_replication call""" repl = Replicator(self.mock_account) mock_doc = mock.Mock() mock_doc.fetch = mock.Mock() mock_doc.delete = mock.Mock() repl.database['replication_1'] = mock_doc repl.stop_replication('replication_1') self.assertTrue(mock_doc.fetch.called) self.assertTrue(mock_doc.delete.called) with mock.patch('cloudant.database.CouchDatabase.__getitem__') as mock_gi: mock_gi.side_effect = KeyError("womp") self.assertRaises( CloudantException, repl.stop_replication, 'replication_2' )
class ReplicatorTests(UnitTestDbBase): """ Replicator unit tests """ def setUp(self): """ Set up test attributes """ super(ReplicatorTests, self).setUp() self.db_set_up() self.test_target_dbname = self.dbname() self.target_db = self.client._DATABASE_CLASS( self.client, self.test_target_dbname ) self.target_db.create() self.replicator = Replicator(self.client) self.replication_ids = [] def tearDown(self): """ Reset test attributes """ self.target_db.delete() del self.test_target_dbname del self.target_db for rep_id in self.replication_ids: max_retry = 5 while True: try: self.replicator.stop_replication(rep_id) break except requests.HTTPError as ex: # Retry failed attempt to delete replication document. It's # likely in an error state and receiving constant updates # via the replicator. max_retry -= 1 if ex.response.status_code != 409 or max_retry == 0: raise del self.replicator self.db_tear_down() super(ReplicatorTests, self).tearDown() def test_constructor(self): """ Test constructing a Replicator """ self.assertIsInstance(self.replicator, Replicator) self.assertIsInstance( self.replicator.database, self.client._DATABASE_CLASS ) self.assertEqual(self.replicator.database, self.client['_replicator']) def test_constructor_failure(self): """ Test that constructing a Replicator will not work without a valid client. """ repl = None try: self.client.disconnect() repl = Replicator(self.client) self.fail('Above statement should raise a CloudantException') except CloudantClientException as err: self.assertEqual( str(err), 'Database _replicator does not exist. ' 'Verify that the client is valid and try again.' ) finally: self.assertIsNone(repl) self.client.connect() def test_replication_with_generated_id(self): clone = Replicator(self.client) repl_id = clone.create_replication( self.db, self.target_db ) self.replication_ids.append(repl_id['_id']) @flaky(max_runs=3) def test_create_replication(self): """ Test that the replication document gets created and that the replication is successful. """ self.populate_db_with_documents(3) repl_id = 'test-repl-{}'.format(unicode_(uuid.uuid4())) repl_doc = self.replicator.create_replication( self.db, self.target_db, repl_id ) self.replication_ids.append(repl_id) # Test that the replication document was created expected_keys = ['_id', '_rev', 'source', 'target', 'user_ctx'] # If Admin Party mode then user_ctx will not be in the key list if self.client.admin_party or self.client.is_iam_authenticated: expected_keys.pop() self.assertTrue(all(x in list(repl_doc.keys()) for x in expected_keys)) self.assertEqual(repl_doc['_id'], repl_id) self.assertTrue(repl_doc['_rev'].startswith('1-')) # Now that we know that the replication document was created, # check that the replication occurred. repl_doc = Document(self.replicator.database, repl_id) repl_doc.fetch() if repl_doc.get('_replication_state') not in ('completed', 'error'): changes = self.replicator.database.changes( feed='continuous', heartbeat=1000) beats = 0 for change in changes: if beats == 300: changes.stop() if not change: beats += 1 continue elif change.get('id') == repl_id: beats = 0 repl_doc = Document(self.replicator.database, repl_id) repl_doc.fetch() if repl_doc.get('_replication_state') in ('completed', 'error'): changes.stop() self.assertEqual(repl_doc.get('_replication_state'), 'completed') self.assertEqual(self.db.all_docs(), self.target_db.all_docs()) self.assertTrue( all(x in self.target_db.keys(True) for x in [ 'julia000', 'julia001', 'julia002' ]) ) def test_timeout_in_create_replication(self): """ Test that a read timeout exception is thrown when creating a replicator with a timeout value of 500 ms. """ # Setup client with a timeout self.set_up_client(auto_connect=True, timeout=.5) self.db = self.client[self.test_target_dbname] self.target_db = self.client[self.test_dbname] # Construct a replicator with the updated client self.replicator = Replicator(self.client) repl_id = 'test-repl-{}'.format(unicode_(uuid.uuid4())) repl_doc = self.replicator.create_replication( self.db, self.target_db, repl_id ) self.replication_ids.append(repl_id) # Test that the replication document was created expected_keys = ['_id', '_rev', 'source', 'target', 'user_ctx'] # If Admin Party mode then user_ctx will not be in the key list if self.client.admin_party or self.client.is_iam_authenticated: expected_keys.pop() self.assertTrue(all(x in list(repl_doc.keys()) for x in expected_keys)) self.assertEqual(repl_doc['_id'], repl_id) self.assertTrue(repl_doc['_rev'].startswith('1-')) # Now that we know that the replication document was created, # check that the replication timed out. repl_doc = Document(self.replicator.database, repl_id) repl_doc.fetch() if repl_doc.get('_replication_state') not in ('completed', 'error'): # assert that a connection error is thrown because the read timed out with self.assertRaises(ConnectionError) as cm: changes = self.replicator.database.changes( feed='continuous') for change in changes: continue self.assertTrue(str(cm.exception).endswith('Read timed out.')) def test_create_replication_without_a_source(self): """ Test that the replication document is not created and fails as expected when no source database is provided. """ try: repl_doc = self.replicator.create_replication() self.fail('Above statement should raise a CloudantException') except CloudantReplicatorException as err: self.assertEqual( str(err), 'You must specify either a source_db Database ' 'object or a manually composed \'source\' string/dict.' ) def test_create_replication_without_a_target(self): """ Test that the replication document is not created and fails as expected when no target database is provided. """ try: repl_doc = self.replicator.create_replication(self.db) self.fail('Above statement should raise a CloudantException') except CloudantReplicatorException as err: self.assertEqual( str(err), 'You must specify either a target_db Database ' 'object or a manually composed \'target\' string/dict.' ) def test_list_replications(self): """ Test that a list of Document wrapped objects are returned. """ self.populate_db_with_documents(3) repl_ids = ['test-repl-{}'.format( unicode_(uuid.uuid4()) ) for _ in range(3)] repl_docs = [self.replicator.create_replication( self.db, self.target_db, repl_id ) for repl_id in repl_ids] self.replication_ids.extend(repl_ids) replications = self.replicator.list_replications() all_repl_ids = [doc['_id'] for doc in replications] match = [repl_id for repl_id in all_repl_ids if repl_id in repl_ids] self.assertEqual(set(repl_ids), set(match)) def test_retrieve_replication_state(self): """ Test that the replication state can be retrieved for a replication """ self.populate_db_with_documents(3) repl_id = "test-repl-{}".format(unicode_(uuid.uuid4())) repl_doc = self.replicator.create_replication( self.db, self.target_db, repl_id ) self.replication_ids.append(repl_id) repl_state = None valid_states = ['completed', 'error', 'triggered', 'running', None] finished = False for _ in range(300): repl_state = self.replicator.replication_state(repl_id) self.assertTrue(repl_state in valid_states) if repl_state in ('error', 'completed'): finished = True break time.sleep(1) self.assertTrue(finished) def test_retrieve_replication_state_using_invalid_id(self): """ Test that replication_state(...) raises an exception as expected when an invalid replication id is provided. """ repl_id = 'fake-repl-id-{}'.format(unicode_(uuid.uuid4())) repl_state = None try: self.replicator.replication_state(repl_id) self.fail('Above statement should raise a CloudantException') except CloudantReplicatorException as err: self.assertEqual( str(err), 'Replication with id {} not found.'.format(repl_id) ) self.assertIsNone(repl_state) def test_stop_replication(self): """ Test that a replication can be stopped. """ self.populate_db_with_documents(3) repl_id = "test-repl-{}".format(unicode_(uuid.uuid4())) repl_doc = self.replicator.create_replication( self.db, self.target_db, repl_id ) max_retry = 3 while True: try: max_retry -= 1 self.replicator.stop_replication(repl_id) break except requests.HTTPError as err: self.assertEqual(err.response.status_code, 409) if max_retry == 0: self.fail('Failed to stop replication: {0}'.format(err)) try: # The .fetch() will fail since the replication has been stopped # and the replication document has been removed from the db. repl_doc.fetch() self.fail('Above statement should raise a CloudantException') except requests.HTTPError as err: self.assertEqual(err.response.status_code, 404) def test_stop_replication_using_invalid_id(self): """ Test that stop_replication(...) raises an exception as expected when an invalid replication id is provided. """ repl_id = 'fake-repl-id-{}'.format(unicode_(uuid.uuid4())) try: self.replicator.stop_replication(repl_id) self.fail('Above statement should raise a CloudantException') except CloudantReplicatorException as err: self.assertEqual( str(err), 'Replication with id {} not found.'.format(repl_id) ) def test_follow_replication(self): """ Test that follow_replication(...) properly iterates updated replication documents while the replication is executing. """ self.populate_db_with_documents(3) repl_id = "test-repl-{}".format(unicode_(uuid.uuid4())) repl_doc = self.replicator.create_replication( self.db, self.target_db, repl_id ) self.replication_ids.append(repl_id) valid_states = ('completed', 'error', 'triggered', 'running', None) repl_states = [] if 'scheduler' in self.client.features(): state_key = 'state' else: state_key = '_replication_state' for doc in self.replicator.follow_replication(repl_id): self.assertIn(doc.get(state_key), valid_states) repl_states.append(doc.get(state_key)) self.assertTrue(len(repl_states) > 0) self.assertEqual(repl_states[-1], 'completed') self.assertNotIn('error', repl_states)
class ReplicatorTests(UnitTestDbBase): """ Replicator unit tests """ def setUp(self): """ Set up test attributes """ super(ReplicatorTests, self).setUp() self.db_set_up() self.test_target_dbname = self.dbname() self.target_db = self.client._DATABASE_CLASS(self.client, self.test_target_dbname) self.target_db.create() self.replicator = Replicator(self.client) self.replication_ids = [] def tearDown(self): """ Reset test attributes """ self.target_db.delete() del self.test_target_dbname del self.target_db while self.replication_ids: self.replicator.stop_replication(self.replication_ids.pop()) del self.replicator self.db_tear_down() super(ReplicatorTests, self).tearDown() def test_constructor(self): """ Test constructing a Replicator """ self.assertIsInstance(self.replicator, Replicator) self.assertIsInstance(self.replicator.database, self.client._DATABASE_CLASS) self.assertEqual(self.replicator.database, self.client['_replicator']) def test_constructor_failure(self): """ Test that constructing a Replicator will not work without a valid client. """ repl = None try: self.client.disconnect() repl = Replicator(self.client) self.fail('Above statement should raise a CloudantException') except CloudantException as err: self.assertEqual( str(err), 'Unable to acquire _replicator database. ' 'Verify that the client is valid and try again.') finally: self.assertIsNone(repl) self.client.connect() def test_create_replication(self): """ Test that the replication document gets created and that the replication is successful. """ self.populate_db_with_documents(3) repl_id = 'test-repl-{}'.format(unicode_(uuid.uuid4())) repl_doc = self.replicator.create_replication(self.db, self.target_db, repl_id) self.replication_ids.append(repl_id) # Test that the replication document was created expected_keys = ['_id', '_rev', 'source', 'target', 'user_ctx'] # If Admin Party mode then user_ctx will not be in the key list if self.client.admin_party: expected_keys.pop() self.assertTrue(all(x in list(repl_doc.keys()) for x in expected_keys)) self.assertEqual(repl_doc['_id'], repl_id) self.assertTrue(repl_doc['_rev'].startswith('1-')) # Now that we know that the replication document was created, # check that the replication occurred. repl_doc = Document(self.replicator.database, repl_id) repl_doc.fetch() if repl_doc.get('_replication_state') not in ('completed', 'error'): changes = self.replicator.database.changes(feed='continuous', heartbeat=1000) beats = 0 for change in changes: if beats == 300: changes.stop() if not change: beats += 1 continue elif change.get('id') == repl_id: beats = 0 repl_doc = Document(self.replicator.database, repl_id) repl_doc.fetch() if repl_doc.get('_replication_state') in ('completed', 'error'): changes.stop() self.assertEqual(repl_doc.get('_replication_state'), 'completed') self.assertEqual(self.db.all_docs(), self.target_db.all_docs()) self.assertTrue( all(x in self.target_db.keys(True) for x in ['julia000', 'julia001', 'julia002'])) def test_create_replication_without_a_source(self): """ Test that the replication document is not created and fails as expected when no source database is provided. """ try: repl_doc = self.replicator.create_replication() self.fail('Above statement should raise a CloudantException') except CloudantException as err: self.assertEqual( str(err), 'You must specify either a source_db Database ' 'object or a manually composed \'source\' string/dict.') def test_create_replication_without_a_target(self): """ Test that the replication document is not created and fails as expected when no target database is provided. """ try: repl_doc = self.replicator.create_replication(self.db) self.fail('Above statement should raise a CloudantException') except CloudantException as err: self.assertEqual( str(err), 'You must specify either a target_db Database ' 'object or a manually composed \'target\' string/dict.') def test_list_replications(self): """ Test that a list of Document wrapped objects are returned. """ self.populate_db_with_documents(3) repl_ids = [ 'test-repl-{}'.format(unicode_(uuid.uuid4())) for _ in range(3) ] repl_docs = [ self.replicator.create_replication(self.db, self.target_db, repl_id) for repl_id in repl_ids ] self.replication_ids.extend(repl_ids) replications = self.replicator.list_replications() all_repl_ids = [doc['_id'] for doc in replications] match = [repl_id for repl_id in all_repl_ids if repl_id in repl_ids] self.assertEqual(set(repl_ids), set(match)) def test_retrieve_replication_state(self): """ Test that the replication state can be retrieved for a replication """ self.populate_db_with_documents(3) repl_id = "test-repl-{}".format(unicode_(uuid.uuid4())) repl_doc = self.replicator.create_replication(self.db, self.target_db, repl_id) self.replication_ids.append(repl_id) repl_state = None valid_states = ['completed', 'error', 'triggered', None] finished = False for _ in range(300): repl_state = self.replicator.replication_state(repl_id) self.assertTrue(repl_state in valid_states) if repl_state in ('error', 'completed'): finished = True break time.sleep(1) self.assertTrue(finished) def test_retrieve_replication_state_using_invalid_id(self): """ Test that replication_state(...) raises an exception as expected when an invalid replication id is provided. """ repl_id = 'fake-repl-id-{}'.format(unicode_(uuid.uuid4())) repl_state = None try: self.replicator.replication_state(repl_id) self.fail('Above statement should raise a CloudantException') except CloudantException as err: self.assertEqual(str(err), 'Replication {} not found'.format(repl_id)) self.assertIsNone(repl_state) def test_stop_replication(self): """ Test that a replication can be stopped. """ self.populate_db_with_documents(3) repl_id = "test-repl-{}".format(unicode_(uuid.uuid4())) repl_doc = self.replicator.create_replication(self.db, self.target_db, repl_id) self.replicator.stop_replication(repl_id) try: # The .fetch() will fail since the replication has been stopped # and the replication document has been removed from the db. repl_doc.fetch() self.fail('Above statement should raise a CloudantException') except requests.HTTPError as err: self.assertEqual(err.response.status_code, 404) def test_stop_replication_using_invalid_id(self): """ Test that stop_replication(...) raises an exception as expected when an invalid replication id is provided. """ repl_id = 'fake-repl-id-{}'.format(unicode_(uuid.uuid4())) try: self.replicator.stop_replication(repl_id) self.fail('Above statement should raise a CloudantException') except CloudantException as err: self.assertEqual( str(err), 'Could not find replication with id {}'.format(repl_id)) def test_follow_replication(self): """ Test that follow_replication(...) properly iterates updated replication documents while the replication is executing. """ self.populate_db_with_documents(3) repl_id = "test-repl-{}".format(unicode_(uuid.uuid4())) repl_doc = self.replicator.create_replication(self.db, self.target_db, repl_id) self.replication_ids.append(repl_id) valid_states = ('completed', 'error', 'triggered', None) repl_states = [] for doc in self.replicator.follow_replication(repl_id): self.assertIn(doc.get('_replication_state'), valid_states) repl_states.append(doc.get('_replication_state')) self.assertTrue(len(repl_states) > 0) self.assertEqual(repl_states[-1], 'completed') self.assertNotIn('error', repl_states)
class ReplicatorTests(UnitTestDbBase): """ Replicator unit tests """ def setUp(self): """ Set up test attributes """ super(ReplicatorTests, self).setUp() self.db_set_up() self.test_target_dbname = self.dbname() self.target_db = self.client._DATABASE_CLASS( self.client, self.test_target_dbname ) self.target_db.create() self.replicator = Replicator(self.client) self.replication_ids = [] def tearDown(self): """ Reset test attributes """ self.target_db.delete() del self.test_target_dbname del self.target_db while self.replication_ids: self.replicator.stop_replication(self.replication_ids.pop()) del self.replicator self.db_tear_down() super(ReplicatorTests, self).tearDown() def test_constructor(self): """ Test constructing a Replicator """ self.assertIsInstance(self.replicator, Replicator) self.assertIsInstance( self.replicator.database, self.client._DATABASE_CLASS ) self.assertEqual(self.replicator.database, self.client['_replicator']) def test_constructor_failure(self): """ Test that constructing a Replicator will not work without a valid account. """ repl = None try: self.client.disconnect() repl = Replicator(self.client) self.fail('Above statement should raise a CloudantException') except CloudantException, err: self.assertEqual( str(err), 'Unable to acquire _replicator database. ' 'Verify that the account client is valid and try again.' ) finally:
class ReplicatorTests(UnitTestDbBase): """ Replicator unit tests """ def setUp(self): """ Set up test attributes """ super(ReplicatorTests, self).setUp() self.db_set_up() self.test_target_dbname = self.dbname() self.target_db = self.client._DATABASE_CLASS( self.client, self.test_target_dbname ) self.target_db.create() self.replicator = Replicator(self.client) self.replication_ids = [] def tearDown(self): """ Reset test attributes """ self.target_db.delete() del self.test_target_dbname del self.target_db for rep_id in self.replication_ids: max_retry = 5 while True: try: self.replicator.stop_replication(rep_id) break except requests.HTTPError as ex: # Retry failed attempt to delete replication document. It's # likely in an error state and receiving constant updates # via the replicator. max_retry -= 1 if ex.response.status_code != 409 or max_retry == 0: raise del self.replicator self.db_tear_down() super(ReplicatorTests, self).tearDown() def test_constructor(self): """ Test constructing a Replicator """ self.assertIsInstance(self.replicator, Replicator) self.assertIsInstance( self.replicator.database, self.client._DATABASE_CLASS ) self.assertEqual(self.replicator.database, self.client['_replicator']) def test_constructor_failure(self): """ Test that constructing a Replicator will not work without a valid client. """ repl = None try: self.client.disconnect() repl = Replicator(self.client) self.fail('Above statement should raise a CloudantException') except CloudantClientException as err: self.assertEqual( str(err), 'Database _replicator does not exist. ' 'Verify that the client is valid and try again.' ) finally: self.assertIsNone(repl) self.client.connect() def test_replication_with_generated_id(self): clone = Replicator(self.client) clone.create_replication(self.db, self.target_db) @flaky(max_runs=3) def test_create_replication(self): """ Test that the replication document gets created and that the replication is successful. """ self.populate_db_with_documents(3) repl_id = 'test-repl-{}'.format(unicode_(uuid.uuid4())) repl_doc = self.replicator.create_replication( self.db, self.target_db, repl_id ) self.replication_ids.append(repl_id) # Test that the replication document was created expected_keys = ['_id', '_rev', 'source', 'target', 'user_ctx'] # If Admin Party mode then user_ctx will not be in the key list if self.client.admin_party: expected_keys.pop() self.assertTrue(all(x in list(repl_doc.keys()) for x in expected_keys)) self.assertEqual(repl_doc['_id'], repl_id) self.assertTrue(repl_doc['_rev'].startswith('1-')) # Now that we know that the replication document was created, # check that the replication occurred. repl_doc = Document(self.replicator.database, repl_id) repl_doc.fetch() if repl_doc.get('_replication_state') not in ('completed', 'error'): changes = self.replicator.database.changes( feed='continuous', heartbeat=1000) beats = 0 for change in changes: if beats == 300: changes.stop() if not change: beats += 1 continue elif change.get('id') == repl_id: beats = 0 repl_doc = Document(self.replicator.database, repl_id) repl_doc.fetch() if repl_doc.get('_replication_state') in ('completed', 'error'): changes.stop() self.assertEqual(repl_doc.get('_replication_state'), 'completed') self.assertEqual(self.db.all_docs(), self.target_db.all_docs()) self.assertTrue( all(x in self.target_db.keys(True) for x in [ 'julia000', 'julia001', 'julia002' ]) ) def test_timeout_in_create_replication(self): """ Test that a read timeout exception is thrown when creating a replicator with a timeout value of 500 ms. """ # Setup client with a timeout self.set_up_client(auto_connect=True, timeout=.5) self.db = self.client[self.test_target_dbname] self.target_db = self.client[self.test_dbname] # Construct a replicator with the updated client self.replicator = Replicator(self.client) repl_id = 'test-repl-{}'.format(unicode_(uuid.uuid4())) repl_doc = self.replicator.create_replication( self.db, self.target_db, repl_id ) self.replication_ids.append(repl_id) # Test that the replication document was created expected_keys = ['_id', '_rev', 'source', 'target', 'user_ctx'] # If Admin Party mode then user_ctx will not be in the key list if self.client.admin_party: expected_keys.pop() self.assertTrue(all(x in list(repl_doc.keys()) for x in expected_keys)) self.assertEqual(repl_doc['_id'], repl_id) self.assertTrue(repl_doc['_rev'].startswith('1-')) # Now that we know that the replication document was created, # check that the replication timed out. repl_doc = Document(self.replicator.database, repl_id) repl_doc.fetch() if repl_doc.get('_replication_state') not in ('completed', 'error'): # assert that a connection error is thrown because the read timed out with self.assertRaises(ConnectionError) as cm: changes = self.replicator.database.changes( feed='continuous') for change in changes: continue self.assertTrue(str(cm.exception).endswith('Read timed out.')) def test_create_replication_without_a_source(self): """ Test that the replication document is not created and fails as expected when no source database is provided. """ try: repl_doc = self.replicator.create_replication() self.fail('Above statement should raise a CloudantException') except CloudantReplicatorException as err: self.assertEqual( str(err), 'You must specify either a source_db Database ' 'object or a manually composed \'source\' string/dict.' ) def test_create_replication_without_a_target(self): """ Test that the replication document is not created and fails as expected when no target database is provided. """ try: repl_doc = self.replicator.create_replication(self.db) self.fail('Above statement should raise a CloudantException') except CloudantReplicatorException as err: self.assertEqual( str(err), 'You must specify either a target_db Database ' 'object or a manually composed \'target\' string/dict.' ) def test_list_replications(self): """ Test that a list of Document wrapped objects are returned. """ self.populate_db_with_documents(3) repl_ids = ['test-repl-{}'.format( unicode_(uuid.uuid4()) ) for _ in range(3)] repl_docs = [self.replicator.create_replication( self.db, self.target_db, repl_id ) for repl_id in repl_ids] self.replication_ids.extend(repl_ids) replications = self.replicator.list_replications() all_repl_ids = [doc['_id'] for doc in replications] match = [repl_id for repl_id in all_repl_ids if repl_id in repl_ids] self.assertEqual(set(repl_ids), set(match)) def test_retrieve_replication_state(self): """ Test that the replication state can be retrieved for a replication """ self.populate_db_with_documents(3) repl_id = "test-repl-{}".format(unicode_(uuid.uuid4())) repl_doc = self.replicator.create_replication( self.db, self.target_db, repl_id ) self.replication_ids.append(repl_id) repl_state = None valid_states = ['completed', 'error', 'triggered', None] finished = False for _ in range(300): repl_state = self.replicator.replication_state(repl_id) self.assertTrue(repl_state in valid_states) if repl_state in ('error', 'completed'): finished = True break time.sleep(1) self.assertTrue(finished) def test_retrieve_replication_state_using_invalid_id(self): """ Test that replication_state(...) raises an exception as expected when an invalid replication id is provided. """ repl_id = 'fake-repl-id-{}'.format(unicode_(uuid.uuid4())) repl_state = None try: self.replicator.replication_state(repl_id) self.fail('Above statement should raise a CloudantException') except CloudantReplicatorException as err: self.assertEqual( str(err), 'Replication with id {} not found.'.format(repl_id) ) self.assertIsNone(repl_state) def test_stop_replication(self): """ Test that a replication can be stopped. """ self.populate_db_with_documents(3) repl_id = "test-repl-{}".format(unicode_(uuid.uuid4())) repl_doc = self.replicator.create_replication( self.db, self.target_db, repl_id ) self.replicator.stop_replication(repl_id) try: # The .fetch() will fail since the replication has been stopped # and the replication document has been removed from the db. repl_doc.fetch() self.fail('Above statement should raise a CloudantException') except requests.HTTPError as err: self.assertEqual(err.response.status_code, 404) def test_stop_replication_using_invalid_id(self): """ Test that stop_replication(...) raises an exception as expected when an invalid replication id is provided. """ repl_id = 'fake-repl-id-{}'.format(unicode_(uuid.uuid4())) try: self.replicator.stop_replication(repl_id) self.fail('Above statement should raise a CloudantException') except CloudantReplicatorException as err: self.assertEqual( str(err), 'Replication with id {} not found.'.format(repl_id) ) def test_follow_replication(self): """ Test that follow_replication(...) properly iterates updated replication documents while the replication is executing. """ self.populate_db_with_documents(3) repl_id = "test-repl-{}".format(unicode_(uuid.uuid4())) repl_doc = self.replicator.create_replication( self.db, self.target_db, repl_id ) self.replication_ids.append(repl_id) valid_states = ('completed', 'error', 'triggered', None) repl_states = [] for doc in self.replicator.follow_replication(repl_id): self.assertIn(doc.get('_replication_state'), valid_states) repl_states.append(doc.get('_replication_state')) self.assertTrue(len(repl_states) > 0) self.assertEqual(repl_states[-1], 'completed') self.assertNotIn('error', repl_states)