def test_message_delete_pagination(self): def make_messages(channel_id, count): m = [] t = self._nstime() ttl = int(time.time()) + 200 for i in range(count): m.append( (self.uaid, channel_id, str(uuid.uuid4()), ttl, {}, t + i)) return m chid = str(uuid.uuid4()) m = get_rotating_message_table() message = Message(m, SinkMetrics()) message.register_channel(self.uaid, chid) # Shove 80 messages in for message_args in make_messages(chid, 80): message.store_message(*message_args) # Verify we can see them all all_messages = list(message.fetch_messages(self.uaid, limit=100)) eq_(len(all_messages), 80) # Delete them all message.delete_messages_for_channel(self.uaid, chid) # Verify they're gone all_messages = list(message.fetch_messages(self.uaid, limit=100)) eq_(len(all_messages), 0)
def update_rotating_tables(self): """This method is intended to be tasked to run periodically off the twisted event hub to rotate tables. When today is a new month from yesterday, then we swap out all the table objects on the settings object. """ today = datetime.date.today() tomorrow = self._tomorrow() if ((tomorrow.month != today.month) and sorted(self.message_tables.keys())[-1] != tomorrow.month): next_month = yield deferToThread(get_rotating_message_table, self._message_prefix, 0, tomorrow) self.message_tables[next_month.table_name] = Message( next_month, self.metrics) if today.month == self.current_month: # No change in month, we're fine. returnValue(False) # Get tables for the new month, and verify they exist before we try to # switch over message_table = yield deferToThread(get_rotating_message_table, self._message_prefix) # Both tables found, safe to switch-over self.current_month = today.month self.current_msg_month = message_table.table_name self.message_tables[self.current_msg_month] = \ Message(message_table, self.metrics) returnValue(True)
def test_register(self): chid = str(uuid.uuid4()) m = get_rotating_message_table() message = Message(m, SinkMetrics()) message.register_channel(self.uaid, chid) # Verify its in the db rows = m.query_2(uaid__eq=self.uaid, chidmessageid__eq=" ") results = list(rows) assert (len(results) == 1)
def test_register(self): chid = str(uuid.uuid4()) m = get_rotating_message_table() message = Message(m, SinkMetrics()) message.register_channel(self.uaid, chid) # Verify its in the db rows = m.query_2(uaid__eq=self.uaid, chidmessageid__eq=" ") results = list(rows) assert len(results) == 1
def test_message_delete_pagination(self): def make_messages(channel_id, count): m = [] t = self._nstime() ttl = int(time.time()) + 200 for i in range(count): m.append((self.uaid, channel_id, str(uuid.uuid4()), ttl, {}, t + i)) return m chid = str(uuid.uuid4()) m = get_rotating_message_table() message = Message(m, SinkMetrics()) message.register_channel(self.uaid, chid) # Shove 80 messages in for message_args in make_messages(chid, 80): message.store_message(*message_args) # Verify we can see them all all_messages = list(message.fetch_messages(self.uaid, limit=100)) eq_(len(all_messages), 80) # Delete them all message.delete_messages_for_channel(self.uaid, chid) # Verify they're gone all_messages = list(message.fetch_messages(self.uaid, limit=100)) eq_(len(all_messages), 0)
def test_preflight_check(self): router = Router(get_router_table(), SinkMetrics()) message = Message(get_rotating_message_table(), SinkMetrics()) pf_uaid = "deadbeef00000000deadbeef01010101" preflight_check(message, router, pf_uaid) # now check that the database reports no entries. _, notifs = message.fetch_messages(uuid.UUID(pf_uaid)) assert len(notifs) == 0 with pytest.raises(ItemNotFound): router.get_uaid(pf_uaid)
def test_message_delete_fail_condition(self): m = get_rotating_message_table() message = Message(m, SinkMetrics()) def raise_condition(*args, **kwargs): raise ConditionalCheckFailedException(None, None) message.table = Mock() message.table.delete_item.side_effect = raise_condition result = message.delete_message(uaid="asdf", channel_id="asdf", message_id="asdf", updateid="asdf") eq_(result, False)
def test_update_message_fail(self): message = Message(get_rotating_message_table(), SinkMetrics) message.store_message(self.uaid, uuid.uuid4().hex, self._nstime(), str(uuid.uuid4()), {}) u = message.table.connection.update_item = Mock() def raise_condition(*args, **kwargs): raise ConditionalCheckFailedException(None, None) u.side_effect = raise_condition b = message.update_message(self.uaid, uuid.uuid4().hex, self._nstime(), str(uuid.uuid4()), {}) eq_(b, False)
def test_message_delete_fail_condition(self): notif = make_webpush_notification(dummy_uaid, dummy_chid) notif.message_id = notif.update_id = dummy_uaid m = get_rotating_message_table() message = Message(m, SinkMetrics()) def raise_condition(*args, **kwargs): raise ClientError({}, 'delete_item') message.table = Mock() message.table.delete_item.side_effect = raise_condition result = message.delete_message(notif) assert result is False
def test_all_channels_fail(self): m = get_rotating_message_table() message = Message(m, SinkMetrics()) message.table.get_item = Mock() message.table.get_item.return_value = { "ResponseMetadata": { "HTTPStatusCode": 400 }, } res = message.all_channels(self.uaid) assert res == (False, set([]))
def test_save_channels(self): chid = str(uuid.uuid4()) chid2 = str(uuid.uuid4()) m = get_rotating_message_tablename(boto_resource=self.resource) message = Message(m, boto_resource=self.resource) message.register_channel(self.uaid, chid) message.register_channel(self.uaid, chid2) exists, chans = message.all_channels(self.uaid) new_uaid = uuid.uuid4().hex message.save_channels(new_uaid, chans) _, new_chans = message.all_channels(new_uaid) assert chans == new_chans
def test_save_channels(self): chid = str(uuid.uuid4()) chid2 = str(uuid.uuid4()) m = get_rotating_message_table() message = Message(m, SinkMetrics()) message.register_channel(self.uaid, chid) message.register_channel(self.uaid, chid2) exists, chans = message.all_channels(self.uaid) new_uaid = uuid.uuid4().hex message.save_channels(new_uaid, chans) _, new_chans = message.all_channels(new_uaid) eq_(chans, new_chans)
def test_preflight_check(self): global test_router message = Message( get_rotating_message_tablename(boto_resource=self.resource), boto_resource=self.resource) pf_uaid = "deadbeef00000000deadbeef01010101" preflight_check(message, test_router, pf_uaid) # now check that the database reports no entries. _, notifs = message.fetch_messages(uuid.UUID(pf_uaid)) assert len(notifs) == 0 with pytest.raises(ItemNotFound): self.router.get_uaid(pf_uaid)
def test_message_delete_fail_condition(self): notif = make_webpush_notification(dummy_uaid, dummy_chid) notif.message_id = notif.update_id = dummy_uaid m = get_rotating_message_table() message = Message(m, SinkMetrics()) def raise_condition(*args, **kwargs): raise ConditionalCheckFailedException(None, None) message.table = Mock() message.table.delete_item.side_effect = raise_condition result = message.delete_message(notif) eq_(result, False)
def test_preflight_check_wait(self): router = Router(get_router_table(), SinkMetrics()) message = Message(get_rotating_message_table(), SinkMetrics()) values = ["PENDING", "ACTIVE"] message.table_status = Mock(side_effect=values) pf_uaid = "deadbeef00000000deadbeef01010101" preflight_check(message, router, pf_uaid) # now check that the database reports no entries. _, notifs = message.fetch_messages(uuid.UUID(pf_uaid)) assert len(notifs) == 0 with pytest.raises(ItemNotFound): router.get_uaid(pf_uaid)
def test_message_delete_fail_condition(self): m = get_rotating_message_table() message = Message(m, SinkMetrics()) def raise_condition(*args, **kwargs): raise ConditionalCheckFailedException(None, None) message.table = Mock() message.table.delete_item.side_effect = raise_condition result = message.delete_message(uaid=dummy_uaid, channel_id=dummy_chid, message_id="asdf", updateid="asdf") eq_(result, False)
def test_message_delete_fail_condition(self): notif = make_webpush_notification(dummy_uaid, dummy_chid) notif.message_id = notif.update_id = dummy_uaid m = get_rotating_message_tablename(boto_resource=self.resource) message = Message(m, boto_resource=self.resource) def raise_condition(*args, **kwargs): raise ClientError({}, 'delete_item') m_de = Mock() m_de.delete_item = Mock(side_effect=raise_condition) message.table = m_de result = message.delete_message(notif) assert result is False
def test_all_channels_fail(self): m = get_rotating_message_tablename(boto_resource=self.resource) message = Message(m, boto_resource=self.resource) mtable = Mock() mtable.get_item.return_value = { "ResponseMetadata": { "HTTPStatusCode": 400 }, } message.table = mtable res = message.all_channels(self.uaid) assert res == (False, set([]))
def run(self): match = PUSH_RE.search(self._endpoint) if not match: return "Not a valid endpoint" md = match.groupdict() api_ver, token = md.get("api_ver", "v1"), md["token"] parsed = self._conf.parse_endpoint( self.db.metrics, token=token, version=api_ver, ) uaid, chid = parsed["uaid"], parsed["chid"] print("UAID: {}\nCHID: {}\n".format(uaid, chid)) rec = self.db.router.get_uaid(uaid) print("Router record:") self._pp.pprint(rec._data) print("\n") if "current_month" in rec: chans = Message(rec["current_month"], boto_resource=self.db.resource).all_channels(uaid) print("Channels in message table:") self._pp.pprint(chans)
def test_all_channels(self): chid = str(uuid.uuid4()) chid2 = str(uuid.uuid4()) m = get_rotating_message_table() message = Message(m, SinkMetrics()) message.register_channel(self.uaid, chid) message.register_channel(self.uaid, chid2) _, chans = message.all_channels(self.uaid) assert (chid in chans) assert (chid2 in chans) message.unregister_channel(self.uaid, chid2) _, chans = message.all_channels(self.uaid) assert (chid2 not in chans) assert (chid in chans)
def test_all_channels(self): chid = str(uuid.uuid4()) chid2 = str(uuid.uuid4()) m = get_rotating_message_tablename(boto_resource=self.resource) message = Message(m, boto_resource=self.resource) message.register_channel(self.uaid, chid) message.register_channel(self.uaid, chid2) _, chans = message.all_channels(self.uaid) assert chid in chans assert chid2 in chans message.unregister_channel(self.uaid, chid2) _, chans = message.all_channels(self.uaid) assert chid2 not in chans assert chid in chans
def test_non_rotating_tables(self): message_tablename = "message_int_test" table_name = self.resource.get_latest_message_tablename( prefix=message_tablename) message = Message(table_name, boto_resource=self.resource) assert message.tablename == table_name
def test_unregister(self): chid = str(uuid.uuid4()) m = get_rotating_message_tablename(boto_resource=self.resource) message = Message(m, boto_resource=self.resource) message.register_channel(self.uaid, chid) # Verify its in the db lm = self.resource.Table(m) # Verify it's in the db response = lm.query( KeyConditions={ 'uaid': { 'AttributeValueList': [self.uaid], 'ComparisonOperator': 'EQ' }, 'chidmessageid': { 'AttributeValueList': [" "], 'ComparisonOperator': 'EQ' }, }, ConsistentRead=True, ) results = list(response.get('Items')) assert len(results) == 1 assert results[0]["chids"] == {chid} message.unregister_channel(self.uaid, chid) # Verify its not in the db response = lm.query( KeyConditions={ 'uaid': { 'AttributeValueList': [self.uaid], 'ComparisonOperator': 'EQ' }, 'chidmessageid': { 'AttributeValueList': [" "], 'ComparisonOperator': 'EQ' }, }, ConsistentRead=True, ) results = list(response.get('Items')) assert len(results) == 1 assert results[0].get("chids") is None # Test for the very unlikely case that there's no 'chid' mtable = Mock() mtable.update_item = Mock(return_value={ 'Attributes': { 'uaid': self.uaid }, 'ResponseMetaData': {} }) message.table = mtable r = message.unregister_channel(self.uaid, dummy_chid) assert r is False
def test_unregister(self): chid = str(uuid.uuid4()) m = get_rotating_message_table() message = Message(m, SinkMetrics()) message.register_channel(self.uaid, chid) # Verify its in the db rows = m.query_2(uaid__eq=self.uaid, chidmessageid__eq=" ") results = list(rows) assert (len(results) == 1) eq_(results[0]["chids"], set([chid])) message.unregister_channel(self.uaid, chid) # Verify its not in the db rows = m.query_2(uaid__eq=self.uaid, chidmessageid__eq=" ") results = list(rows) assert (len(results) == 1) eq_(results[0]["chids"], set([])) # Test for the very unlikely case that there's no 'chid' m.connection.update_item = Mock() m.connection.update_item.return_value = { 'Attributes': { 'uaid': { 'S': self.uaid } }, 'ConsumedCapacityUnits': 0.5 } r = message.unregister_channel(self.uaid, dummy_chid) eq_(r, False)
def test_unregister(self): chid = str(uuid.uuid4()) m = get_message_table() message = Message(m, SinkMetrics()) message.register_channel(self.uaid, chid) # Verify its in the db rows = m.query_2(uaid__eq=self.uaid, chidmessageid__eq=" ") results = list(rows) assert(len(results) == 1) eq_(results[0]["chids"], set([chid])) message.unregister_channel(self.uaid, chid) # Verify its not in the db rows = m.query_2(uaid__eq=self.uaid, chidmessageid__eq=" ") results = list(rows) assert(len(results) == 1) eq_(results[0]["chids"], set([]))
def test_all_channels(self): chid = str(uuid.uuid4()) chid2 = str(uuid.uuid4()) m = get_rotating_message_table() message = Message(m, SinkMetrics()) message.register_channel(self.uaid, chid) message.register_channel(self.uaid, chid2) _, chans = message.all_channels(self.uaid) assert chid in chans assert chid2 in chans message.unregister_channel(self.uaid, chid2) _, chans = message.all_channels(self.uaid) assert chid2 not in chans assert chid in chans
def create_initial_message_tables(self): """Initializes a dict of the initial rotating messages tables. An entry for last months table, an entry for this months table, an entry for tomorrow, if tomorrow is a new month. """ today = datetime.date.today() last_month = get_rotating_message_table(self._message_prefix, -1) this_month = get_rotating_message_table(self._message_prefix) self.current_month = today.month self.current_msg_month = this_month.table_name self.message_tables = { last_month.table_name: Message(last_month, self.metrics), this_month.table_name: Message(this_month, self.metrics) } if self._tomorrow().month != today.month: next_month = get_rotating_message_table(delta=1) self.message_tables[next_month.table_name] = Message( next_month, self.metrics)
def test_register(self): chid = str(uuid.uuid4()) m = get_rotating_message_table() message = Message(m, SinkMetrics()) message.register_channel(self.uaid, chid) # Verify it's in the db response = m.query( KeyConditions={ 'uaid': { 'AttributeValueList': [self.uaid], 'ComparisonOperator': 'EQ' }, 'chidmessageid': { 'AttributeValueList': ['02'], 'ComparisonOperator': 'LT' } }, ConsistentRead=True, ) assert len(response.get('Items'))
def test_preflight_check_fail(self): router = Router(get_router_table(), SinkMetrics()) message = Message(get_rotating_message_table(), SinkMetrics()) def raise_exc(*args, **kwargs): # pragma: no cover raise Exception("Oops") router.clear_node = Mock() router.clear_node.side_effect = raise_exc with pytest.raises(Exception): preflight_check(message, router)
def test_unregister(self): chid = str(uuid.uuid4()) m = get_rotating_message_table() message = Message(m, SinkMetrics()) message.register_channel(self.uaid, chid) # Verify its in the db rows = m.query_2(uaid__eq=self.uaid, chidmessageid__eq=" ") results = list(rows) assert len(results) == 1 eq_(results[0]["chids"], set([chid])) message.unregister_channel(self.uaid, chid) # Verify its not in the db rows = m.query_2(uaid__eq=self.uaid, chidmessageid__eq=" ") results = list(rows) assert len(results) == 1 eq_(results[0]["chids"], set([])) # Test for the very unlikely case that there's no 'chid' m.connection.update_item = Mock() m.connection.update_item.return_value = {"Attributes": {"uaid": {"S": self.uaid}}, "ConsumedCapacityUnits": 0.5} r = message.unregister_channel(self.uaid, "test") eq_(r, False)
def test_message_storage(self): chid = str(uuid.uuid4()) chid2 = str(uuid.uuid4()) m = get_rotating_message_tablename(boto_resource=self.resource) message = Message(m, boto_resource=self.resource) message.register_channel(self.uaid, chid) message.register_channel(self.uaid, chid2) # Ensure that sort keys are fetched from DB in order. notifs = [make_webpush_notification(self.uaid, chid) for x in range(3)] keys = [notif.sort_key for notif in notifs] for msg in notifs: message.store_message(msg) _, all_messages = message.fetch_timestamp_messages( uuid.UUID(self.uaid), " ") assert len(all_messages) == len(notifs) assert keys == [msg.sort_key for msg in all_messages]
def test_preflight_check_fail(self): router = Router(self.table_conf, SinkMetrics(), resource=self.resource) message = Message( get_rotating_message_tablename(boto_resource=self.resource), boto_resource=self.resource) def raise_exc(*args, **kwargs): # pragma: no cover raise Exception("Oops") router.clear_node = Mock() router.clear_node.side_effect = raise_exc with pytest.raises(Exception): preflight_check(message, router, self.resource)
def test_update_message(self): chid = uuid.uuid4().hex m = get_rotating_message_table() message = Message(m, SinkMetrics()) data1 = str(uuid.uuid4()) data2 = str(uuid.uuid4()) time1 = self._nstime() time2 = self._nstime() + 100 ttl = self._nstime() + 1000 message.store_message(self.uaid, chid, time1, ttl, data1, {}) message.update_message(self.uaid, chid, time2, ttl, data2, {}) messages = list(message.fetch_messages(self.uaid)) eq_(data2, messages[0]['#dd'])
def test_update_message(self): chid = uuid.uuid4().hex m = get_rotating_message_table() message = Message(m, SinkMetrics()) data1 = str(uuid.uuid4()) data2 = str(uuid.uuid4()) time1 = self._nstime() time2 = self._nstime() + 100 ttl = self._nstime() + 1000 message.store_message(self.uaid, chid, time1, ttl, data1, {}) message.update_message(self.uaid, chid, time2, ttl, data2, {}) messages = list(message.fetch_messages(self.uaid)) eq_(data2, messages[0]["#dd"])
def run(self): match = PUSH_RE.search(self._endpoint) if not match: return "Not a valid endpoint" md = match.groupdict() api_ver, token = md.get("api_ver", "v1"), md["token"] try: parsed = self._conf.parse_endpoint( self.db.metrics, token=token, version=api_ver, ) uaid, chid = parsed["uaid"], parsed["chid"] except (InvalidTokenException, InvalidToken) as ex: print(("Token could not be deciphered: {}. " "Are you using the correct configuration or platform?") .format(ex)) return "Invalid Token" print("UAID: {}\nCHID: {}\n".format(uaid, chid)) try: rec = self.db.router.get_uaid(uaid) print("Router record:") self._pp.pprint(rec) if "current_month" in rec: chans = Message(rec["current_month"], boto_resource=self.db.resource).all_channels( uaid) print("Channels in message table:") self._pp.pprint(chans) except ItemNotFound as ex: print("Item Missing from database: {}".format(ex)) return "Not Found" print("\n")
def test_unregister(self): chid = str(uuid.uuid4()) m = get_message_table() message = Message(m, SinkMetrics()) message.register_channel(self.uaid, chid) # Verify its in the db rows = m.query_2(uaid__eq=self.uaid, chidmessageid__eq=" ") results = list(rows) assert (len(results) == 1) eq_(results[0]["chids"], set([chid])) message.unregister_channel(self.uaid, chid) # Verify its not in the db rows = m.query_2(uaid__eq=self.uaid, chidmessageid__eq=" ") results = list(rows) assert (len(results) == 1) eq_(results[0]["chids"], set([]))
def test_message_storage_overwrite(self): """Test that store_message can overwrite existing messages which can occur in some reconnect cases but shouldn't error""" chid = str(uuid.uuid4()) chid2 = str(uuid.uuid4()) notif1 = make_webpush_notification(self.uaid, chid) notif2 = make_webpush_notification(self.uaid, chid) notif3 = make_webpush_notification(self.uaid, chid2) notif2.message_id = notif1.message_id m = get_rotating_message_tablename(boto_resource=self.resource) message = Message(m, boto_resource=self.resource) message.register_channel(self.uaid, chid) message.register_channel(self.uaid, chid2) message.store_message(notif1) message.store_message(notif2) message.store_message(notif3) all_messages = list(message.fetch_messages(uuid.UUID(self.uaid))) assert len(all_messages) == 2
def test_delete_user(self): chid = str(uuid.uuid4()) chid2 = str(uuid.uuid4()) m = get_rotating_message_table() message = Message(m, SinkMetrics()) message.register_channel(self.uaid, chid) message.register_channel(self.uaid, chid2) data1 = str(uuid.uuid4()) data2 = str(uuid.uuid4()) ttl = int(time.time()) + 100 time1, time2, time3 = self._nstime(), self._nstime(), self._nstime() + 1 message.store_message(self.uaid, chid, time1, ttl, data1, {}) message.store_message(self.uaid, chid2, time2, ttl, data2, {}) message.store_message(self.uaid, chid2, time3, ttl, data1, {}) message.delete_user(self.uaid) all_messages = list(message.fetch_messages(self.uaid)) eq_(len(all_messages), 0)
def test_all_channels_no_uaid(self): m = get_rotating_message_table() message = Message(m, SinkMetrics()) exists, chans = message.all_channels("asdf") assert chans == set([])
def test_all_channels_no_uaid(self): m = get_message_table() message = Message(m, SinkMetrics()) assert(message.all_channels("asdf") == set([]))