def test_get_feed_with_heartbeat(self): """ Test getting content back for a feed with a heartbeat """ feed = Feed(self.client, feed='continuous', since='now', heartbeat=1000) changes = list() heartbeats = 0 for change in feed: if not change: self.assertIsNone(change) heartbeats += 1 if heartbeats < 4: self.create_dbs(1) else: self.assertTrue(all(x in change for x in ('seq', 'type'))) if len(changes) < 3: changes.append(change) if heartbeats >= 3 and len(changes) == 3: feed.stop() self.assertTrue( changes[0]['seq'] < changes[1]['seq'] < changes[2]['seq']) self.assertIsNone(feed.last_seq)
def test_get_raw_feed_with_heartbeat(self): """ Test getting raw content back for a feed with a heartbeat """ feed = Feed(self.client, raw_data=True, feed='continuous', since='now', heartbeat=1000) raw_content = list() heartbeats = 0 for raw_line in feed: if not raw_line: self.assertEqual(len(raw_line), 0) heartbeats += 1 if heartbeats < 4: self.create_dbs(1) else: self.assertIsInstance(raw_line, BYTETYPE) raw_content.append(raw_line) if heartbeats >= 3 and len(raw_content) >= 3: feed.stop() changes = [json.loads(unicode_(x)) for x in raw_content] self.assertTrue( changes[0]['seq'] < changes[1]['seq'] < changes[2]['seq']) self.assertIsNone(feed.last_seq)
def test_stop_iteration_of_continuous_feed_with_heartbeat(self): """ Test stopping the iteration, test a continuous feed, and test heartbeat functionality. """ feed = Feed(self.client, feed='continuous', timeout=100) changes = list() for change in feed: if not change: if not self.new_dbs: self.create_dbs(5) else: continue else: changes.append(change) if len(changes) == 3: feed.stop() self.assertEqual(len(self.new_dbs), 5) self.assertEqual(len(changes), 3) self.assertDictEqual(changes[0], { 'db_name': self.new_dbs[0].database_name, 'type': 'created' }) self.assertDictEqual(changes[1], { 'db_name': self.new_dbs[1].database_name, 'type': 'created' }) self.assertDictEqual(changes[2], { 'db_name': self.new_dbs[2].database_name, 'type': 'created' })
def test_stop_iteration_of_continuous_feed_with_heartbeat(self): """ Test stopping the iteration, test a continuous feed, and test heartbeat functionality. """ feed = Feed(self.client, feed='continuous', timeout=100) changes = list() for change in feed: if not change: if not self.new_dbs: self.create_dbs(5) else: continue else: changes.append(change) if len(changes) == 3: feed.stop() self.assertEqual(len(self.new_dbs), 5) self.assertEqual(len(changes), 3) self.assertDictEqual( changes[0], {'db_name': self.new_dbs[0].database_name, 'type': 'created'}) self.assertDictEqual( changes[1], {'db_name': self.new_dbs[1].database_name, 'type': 'created'}) self.assertDictEqual( changes[2], {'db_name': self.new_dbs[2].database_name, 'type': 'created'})
def test_get_feed_using_since_now(self): """ Test getting content back for a feed using since set to "now" """ self.populate_db_with_documents(3) feed = Feed(self.db, feed='continuous', heartbeat=1000, since='now') changes = list() first_pass = True beats = 0 for change in feed: if first_pass and not change: self.populate_db_with_documents(3, off_set=3) first_pass = False continue elif change: self.assertSetEqual(set(change.keys()), set(['seq', 'changes', 'id'])) changes.append(change) beats = 0 else: beats += 1 if beats == 15 or len(changes) == 3: feed.stop() expected = set(['julia003', 'julia004', 'julia005']) self.assertSetEqual(set([x['id'] for x in changes]), expected)
def test_get_raw_content(self): """ Test getting raw feed content """ feed = Feed(self.client, raw_data='True', feed='continuous', timeout=100) raw_content = list() for raw_line in feed: self.assertIsInstance(raw_line, BYTETYPE) if not raw_line: self.create_dbs(3) else: raw_content.append(raw_line) if len(raw_content) == 3: feed.stop() changes = [json.loads(unicode_(x)) for x in raw_content] self.assertDictEqual(changes[0], { 'db_name': self.new_dbs[0].database_name, 'type': 'created' }) self.assertDictEqual(changes[1], { 'db_name': self.new_dbs[1].database_name, 'type': 'created' }) self.assertDictEqual(changes[2], { 'db_name': self.new_dbs[2].database_name, 'type': 'created' })
def test_get_feed_with_custom_filter_query_params(self): """ Test using feed with custom filter query parameters. """ feed = Feed( self.db, filter='mailbox/new_mail', foo='bar', # query parameters to a custom filter include_docs=False) params = feed._translate(feed._options) self.assertEqual(params['filter'], 'mailbox/new_mail') self.assertEqual(params['foo'], 'bar') self.assertEqual(params['include_docs'], 'false')
def create_dbs(self): self.db_names = [self.dbname() for x in range(2)] self.new_dbs += [self.client.create_database(dbname) for dbname in self.db_names] # Verify that all created databases are listed in _db_updates all_dbs_exist = False while not all_dbs_exist: changes = list() feed = Feed(self.client, timeout=1000) for change in feed: changes.append(change) if len(changes) == 3: all_dbs_exist = True feed.stop()
def test_get_raw_content(self): """ Test getting raw feed content """ feed = Feed(self.client, raw_data=True, feed='continuous', timeout=100) raw_content = list() for raw_line in feed: self.assertIsInstance(raw_line, BYTETYPE) raw_content.append(raw_line) if len(raw_content) == 3: feed.stop() changes = [json.loads(unicode_(x)) for x in raw_content] self.assert_changes_in_db_updates_feed(changes)
def test_stop_iteration_of_continuous_feed_with_heartbeat(self): """ Test stopping the iteration, test a continuous feed, and test heartbeat functionality. """ feed = Feed(self.client, feed='continuous', timeout=100) changes = list() for change in feed: changes.append(change) if len(changes) == 3: feed.stop() self.assert_changes_in_db_updates_feed(changes) self.assertEqual(len(changes), 3)
def test_get_feed_using_since(self): """ Test getting content back for a feed using the since option """ self.create_dbs(1) feed = Feed(self.client, since='now') [x for x in feed] last_seq = feed.last_seq self.create_dbs(3) feed = Feed(self.client, since=last_seq) for change in feed: self.assertTrue(all(x in change for x in ('seq', 'type'))) self.assertTrue(feed.last_seq > last_seq)
def test_invalid_argument(self): """ Test that an invalid argument is caught and an exception is raised """ feed = Feed(self.client, foo='bar') with self.assertRaises(CloudantArgumentError) as cm: invalid_feed = [x for x in feed] self.assertEqual(str(cm.exception), 'Invalid argument foo') feed = Feed(self.client, style='all_docs') with self.assertRaises(CloudantArgumentError) as cm: invalid_feed = [x for x in feed] self.assertEqual(str(cm.exception), 'Invalid argument style')
def test_get_continuous_with_timeout(self): """ Test getting content back for a "continuous" feed with timeout set and no heartbeat """ feed = Feed(self.client, feed='continuous', heartbeat=False, timeout=1000) changes = list() for change in feed: self.assertIsNotNone(change) changes.append(change) if len(changes) == 3: feed.stop() self.assert_changes_in_db_updates_feed(changes) self.assertEqual(len(changes), 3)
def test_invalid_feed_value(self): """ Test that an invalid feed argument value is caught and an exception is raised """ feed = Feed(self.client, feed='foo') with self.assertRaises(CloudantArgumentError) as cm: invalid_feed = [x for x in feed] self.assertTrue(str(cm.exception).startswith( 'Invalid value (foo) for feed option.')) feed = Feed(self.client, feed='normal') with self.assertRaises(CloudantArgumentError) as cm: invalid_feed = [x for x in feed] self.assertTrue(str(cm.exception).startswith( 'Invalid value (normal) for feed option.'))
def test_get_raw_content(self): """ Test getting raw feed content """ self.populate_db_with_documents(3) feed = Feed(self.db, raw_data=True) raw_content = list() for raw_line in feed: self.assertIsInstance(raw_line, BYTETYPE) raw_content.append(raw_line) changes = json.loads(''.join([unicode_(x) for x in raw_content])) if self.cloudant_test: self.assertSetEqual(set(changes.keys()), set(['results', 'last_seq', 'pending'])) else: self.assertSetEqual(set(changes.keys()), set(['results', 'last_seq'])) results = list() for result in changes['results']: self.assertSetEqual(set(result.keys()), set(['seq', 'changes', 'id'])) results.append(result) expected = set(['julia000', 'julia001', 'julia002']) self.assertSetEqual(set([x['id'] for x in results]), expected) self.assertTrue(str(changes['last_seq']).startswith('3')) self.assertIsNone(feed.last_seq)
def test_get_feed_descending(self): """ Test getting content back for a descending feed. When testing, the sequence identifier is in the form of <number prefix>-<random char seq>. Often times the number prefix sorts as expected when using descending but sometimes the number prefix is repeated. """ self.populate_db_with_documents(50) feed = Feed(self.db, descending=True) seq_list = list() last_seq = None for change in feed: if last_seq: if self.is_couchdb_1x_version() is True: self.assertTrue(change['seq'] < last_seq) else: current = int(change['seq'][0:change['seq'].find('-')]) last = int(last_seq[0:last_seq.find('-')]) try: self.assertTrue(current < last) except AssertionError: self.assertEqual(current, last) seq_list.append(change['seq']) last_seq = change['seq'] self.assertEqual(len(seq_list), 50) self.assertEqual(feed.last_seq, last_seq)
def test_infinite_feed(self): """ Test that an infinite feed will continue to issue multiple requests until stopped. This check is performed in combination by creating documents 3 separate times and checking that the "_start" method on the InfiniteFeed object was called 3 times as well. """ self.populate_db_with_documents() feed = InfiniteFeed(self.db, timeout=100) # Create a proxy for the feed._start method so that we can track how # many times it has been called. feed._start = MethodCallCount(feed._start) changes = list() for change in feed: self.assertSetEqual(set(change.keys()), set(['seq', 'changes', 'id'])) changes.append(change) if len(changes) in (100, 200): sleep(1) # 1 second > .1 second (timeout) self.populate_db_with_documents(off_set=len(changes)) elif len(changes) == 300: feed.stop() expected = set(['julia{0:03d}'.format(i) for i in range(300)]) self.assertSetEqual(set([x['id'] for x in changes]), expected) self.assertIsNone(feed.last_seq) # Compare infinite/continuous with normal normal = Feed(self.db) self.assertSetEqual(set([x['id'] for x in changes]), set([n['id'] for n in normal])) # Ensuring that the feed._start method was called 3 times, verifies that # the continuous feed was started/restarted 3 separate times. self.assertEqual(feed._start.called_count, 3)
def test_get_feed_descending(self): """ Test getting content back for a descending feed. When testing with Cloudant the sequence identifier is in the form of <number prefix>-<random char seq>. Often times the number prefix sorts as expected when using descending but sometimes the number prefix is repeated. In these cases the check is to see if the following random character sequence suffix is longer than its predecessor. """ self.populate_db_with_documents(50) feed = Feed(self.db, descending=True) seq_list = list() last_seq = None for change in feed: if last_seq: if self.cloudant_test: current = int(change['seq'][0:change['seq'].find('-')]) last = int(last_seq[0:last_seq.find('-')]) try: self.assertTrue(current < last) except AssertionError: self.assertEqual(current, last) self.assertTrue(len(change['seq']) > len(last_seq)) else: self.assertTrue(change['seq'] < last_seq) seq_list.append(change['seq']) last_seq = change['seq'] self.assertEqual(len(seq_list), 50) self.assertEqual(feed.last_seq, last_seq)
def test_get_last_seq(self): """ Test getting the last sequence identifier """ self.populate_db_with_documents(10) feed = Feed(self.db) changes = [x for x in feed] self.assertTrue(str(feed.last_seq).startswith('10'))
def test_get_feed_using_since(self): """ Test getting content back for a feed using the since option """ self.populate_db_with_documents(3) feed = Feed(self.db) changes = [change for change in feed] last_seq = feed.last_seq self.populate_db_with_documents(3, off_set=3) feed = Feed(self.db, since=last_seq) changes = list() for change in feed: self.assertSetEqual(set(change.keys()), set(['seq', 'changes', 'id'])) changes.append(change) expected = set(['julia003', 'julia004', 'julia005']) self.assertSetEqual(set([x['id'] for x in changes]), expected) self.assertTrue(str(feed.last_seq).startswith('6'))
def test_stop_iteration_of_continuous_feed_using_since_now(self): """ Test stopping the iteration, test continuous feed functionality, test using since='now' option. """ feed = Feed(self.client, feed='continuous', since='now') count = 0 changes = list() for change in feed: self.assertTrue(all(x in change for x in ('seq', 'type'))) changes.append(change) count += 1 if count == 2: feed.stop() self.assertEqual(len(changes), 2) self.assertTrue(changes[0]['seq'] < changes[1]['seq']) self.assertIsNone(feed.last_seq)
def test_get_feed_using_timeout(self): """ Test getting content back for a feed using timeout """ self.populate_db_with_documents() feed = Feed(self.db, feed='continuous', timeout=100) changes = list() for change in feed: self.assertSetEqual(set(change.keys()), set(['seq', 'changes', 'id'])) changes.append(change) expected = set(['julia{0:03d}'.format(i) for i in range(100)]) self.assertSetEqual(set([x['id'] for x in changes]), expected) self.assertTrue(str(feed.last_seq).startswith('100')) # Compare continuous with normal normal = Feed(self.db) self.assertSetEqual( set([x['id'] for x in changes]), set([n['id'] for n in normal]))
def test_stop_iteration(self): """ Test stopping the iteration """ self.populate_db_with_documents(10) feed = Feed(self.db, feed='continuous') count = 0 changes = list() for change in feed: changes.append(change) count += 1 if count == 3: feed.stop() self.assertEqual(len(change), 3) self.assertTrue(str(changes[0]['seq']).startswith('1')) self.assertTrue(str(changes[1]['seq']).startswith('2')) self.assertTrue(str(changes[2]['seq']).startswith('3')) self.assertIsNone(feed.last_seq)
def test_get_last_seq(self): """ Test getting the last sequence identifier """ self.create_dbs(1) feed = Feed(self.client, since='now') self.assertIsNone(feed.last_seq) [x for x in feed] self.assertIsNotNone(feed.last_seq)
def test_stop_iteration_of_continuous_feed_using_since_now(self): """ Test stopping the iteration, test continuous feed functionality, test using since='now' option. """ feed = Feed(self.client, feed='continuous', since='now') count = 0 changes = list() self.create_dbs(3) for change in feed: self.assertTrue(all(x in change for x in ('seq', 'type'))) changes.append(change) count += 1 if count == 2: feed.stop() self.assertEqual(len(changes), 2) self.assertTrue(changes[0]['seq'] < changes[1]['seq']) self.assertIsNone(feed.last_seq)
def test_constructor_changes(self): """ Test constructing a _changes feed """ feed = Feed(self.db, raw_data=True, chunk_size=1, feed='continuous') self.assertEqual(feed._url, '/'.join([self.db.database_url, '_changes'])) self.assertIsInstance(feed._r_session, Session) self.assertTrue(feed._raw_data) self.assertDictEqual(feed._options, {'feed': 'continuous'}) self.assertEqual(feed._chunk_size, 1)
def tearDown(self): """ Reset test attributes """ test_dbs_deleted = False changes = list() [db.delete() for db in self.new_dbs] # Check the changes in the _db_updates feed to assert that the test databases are deleted while not test_dbs_deleted: feed = Feed(self.client, timeout=1000) for change in feed: if change['db_name'] in self.db_names and change['type'] == 'deleted': changes.append(change) if len(changes) == 2: test_dbs_deleted = True feed.stop() self.delete_db_updates() self.client.disconnect() super(DbUpdatesTestsBase, self).tearDown()
def test_get_continuous_feed(self): """ Test getting content back for a "continuous" feed """ self.populate_db_with_documents() feed = Feed(self.db, feed='continuous') changes = list() for change in feed: self.assertSetEqual(set(change.keys()), set(['seq', 'changes', 'id'])) changes.append(change) if len(changes) == 100: feed.stop() expected = set(['julia{0:03d}'.format(i) for i in range(100)]) self.assertSetEqual(set([x['id'] for x in changes]), expected) self.assertIsNone(feed.last_seq) # Compare continuous with normal normal = Feed(self.db) self.assertSetEqual( set([x['id'] for x in changes]), set([n['id'] for n in normal]))
def test_get_continuous_with_timeout(self): """ Test getting content back for a "continuous" feed with timeout set and no heartbeat """ feed = Feed(self.client, feed='continuous', heartbeat=False, timeout=1000) self.assertListEqual([x for x in feed], [])
def test_invalid_non_positive_integer_argument(self): """ Test that an invalid integer argument type is caught and an exception is raised """ feed = Feed(self.db, limit=-1) with self.assertRaises(CloudantArgumentError) as cm: invalid_feed = [x for x in feed] self.assertEqual(str(cm.exception), 'Argument limit must be > 0. Found: -1')
def test_invalid_argument_type(self): """ Test that an invalid argument type is caught and an exception is raised """ feed = Feed(self.db, conflicts=0) with self.assertRaises(CloudantArgumentError) as cm: invalid_feed = [x for x in feed] self.assertTrue( str(cm.exception).startswith( 'Argument conflicts not instance of expected type:'))
def test_get_longpoll_feed_as_default(self): """ Test getting content back for a "longpoll" feed """ feed = Feed(self.client, timeout=1000) changes = list() for change in feed: self.assertIsNone(change) changes.append(change) self.assertEqual(len(changes), 1) self.assertIsNone(changes[0])
def test_get_feed_with_heartbeat(self): """ Test getting content back for a feed with a heartbeat """ self.populate_db_with_documents() feed = Feed(self.db, feed='continuous', heartbeat=10) changes = list() heartbeats = 0 for change in feed: if not change: self.assertIsNone(change) heartbeats += 1 else: self.assertSetEqual(set(change.keys()), set(['seq', 'changes', 'id'])) changes.append(change) if heartbeats == 3: feed.stop() expected = set(['julia{0:03d}'.format(i) for i in range(100)]) self.assertSetEqual(set([x['id'] for x in changes]), expected) self.assertIsNone(feed.last_seq)
def test_get_raw_content(self): """ Test getting raw feed content """ feed = Feed(self.client, raw_data='True', feed='continuous', timeout=100) raw_content = list() for raw_line in feed: self.assertIsInstance(raw_line, BYTETYPE) if not raw_line: self.create_dbs(3) else: raw_content.append(raw_line) if len(raw_content) == 3: feed.stop() changes = [json.loads(unicode_(x)) for x in raw_content] self.assertDictEqual( changes[0], {'db_name': self.new_dbs[0].database_name, 'type': 'created'}) self.assertDictEqual( changes[1], {'db_name': self.new_dbs[1].database_name, 'type': 'created'}) self.assertDictEqual( changes[2], {'db_name': self.new_dbs[2].database_name, 'type': 'created'})
def test_get_raw_feed_with_heartbeat(self): """ Test getting raw content back for a feed with a heartbeat """ self.populate_db_with_documents() feed = Feed(self.db, raw_data=True, feed='continuous', heartbeat=10) raw_content = list() heartbeats = 0 for raw_line in feed: if not raw_line: self.assertEqual(len(raw_line), 0) heartbeats += 1 else: self.assertIsInstance(raw_line, BYTETYPE) raw_content.append(raw_line) if heartbeats == 3: feed.stop() changes = [json.loads(unicode_(x)) for x in raw_content] expected = set(['julia{0:03d}'.format(i) for i in range(100)]) self.assertSetEqual(set([x['id'] for x in changes]), expected) self.assertIsNone(feed.last_seq)
def test_get_feed_with_heartbeat(self): """ Test getting content back for a feed with a heartbeat """ feed = Feed(self.client, feed='continuous', since='now', heartbeat=1000) changes = list() heartbeats = 0 for change in feed: if not change: self.assertIsNone(change) heartbeats += 1 if heartbeats < 4: self.create_dbs(1) else: self.assertTrue(all(x in change for x in ('seq', 'type'))) if len(changes) < 3: changes.append(change) if heartbeats >= 3 and len(changes) == 3: feed.stop() self.assertTrue(changes[0]['seq'] < changes[1]['seq'] < changes[2]['seq']) self.assertIsNone(feed.last_seq)
def test_get_feed_using_timeout(self): """ Test getting content back for a feed using timeout. Since we do not have control over updates happening within the account as we do within a database, this test is stopped after 15 changes are received which should theoretically not happen but we still need a way to break out of the test if necessary. """ feed = Feed(self.client, feed='continuous', since='now', timeout=1000) count = 0 self.create_dbs(1) for change in feed: self.assertTrue(all(x in change for x in ('seq', 'type'))) count += 1 if count == 15: feed.stop() # The test is considered a success if the last_seq value exists on the # feed object. One would not exist if the feed was stopped via .stop(). # If failure occurs it does not necessarily mean that the InfiniteFeed # is not functioning as expected, it might also mean that we reached the # changes limit threshold of 15 before a timeout could happen. self.assertIsNotNone(feed.last_seq)
def test_get_raw_feed_with_heartbeat(self): """ Test getting raw content back for a feed with a heartbeat """ feed = Feed(self.client, raw_data=True, feed='continuous', since='now', heartbeat=1000) raw_content = list() heartbeats = 0 for raw_line in feed: if not raw_line: self.assertEqual(len(raw_line), 0) heartbeats += 1 if heartbeats < 4: self.create_dbs(1) else: self.assertIsInstance(raw_line, BYTETYPE) raw_content.append(raw_line) if heartbeats >= 3 and len(raw_content) >= 3: feed.stop() changes = [json.loads(unicode_(x)) for x in raw_content] self.assertTrue(changes[0]['seq'] < changes[1]['seq'] < changes[2]['seq']) self.assertIsNone(feed.last_seq)