Пример #1
0
    def setUp(self):

        self.saved_search = SavedSearch.objects.all()[0]

        self.alert_def = AlertDefinition(name='alert_def',
                                         search=self.saved_search)
        self.alert_def.save()

        self.producer = EmailProducer(sender='goldstone',
                                      receiver='someone-else',
                                      alert_def=self.alert_def)
        self.producer.save()

        self.alert = Alert(short_message='test', long_message='test123',
                           alert_def=self.alert_def)
        self.alert.save()
Пример #2
0
 def test_parent_producer_send_fail(self):
     """ Calling send on the parent-producer's send:
       This should throw an exception """
     alert_search = AlertSearch()
     alert_search.save()
     producer_inst = EmailProducer(query=alert_search,
                                   sender='*****@*****.**',
                                   receiver='*****@*****.**')
     producer_inst.save()
     try:
         rv = super(EmailProducer, producer_inst).send(producer_inst)
     except Exception as e:
         self.assertEqual(str(e),
                          str(NotImplementedError(
                              'Producer must implement send.',)))
     alert_search.delete()
     producer_inst.delete()
Пример #3
0
    def test_send_email_success(self):
        """ Tests that sending out an email returns an integer value
            rv <= 0 failure to send or error
            rv >=1 success in send, rv corresponds to number of recipients
        """

        EmailProducer.send = mock.Mock(return_value=1)
        self.assertEqual(EmailProducer.send('title', 'body', '*****@*****.**',
                                            list('*****@*****.**')), 1)
        self.assertEqual(EmailProducer.send.call_count, 1)
Пример #4
0
    def setUp(self):
        self.saved_search = SavedSearch.objects.all()[0]

        self.alert_def = AlertDefinition(name='alert_def',
                                         search=self.saved_search)
        self.alert_def.save()

        self.alert = Alert(short_message='test',
                           long_message='test123',
                           alert_def=self.alert_def)
        self.alert.save()

        self.producer = EmailProducer(sender='me', receiver='you',
                                      alert_def=self.alert_def)
        self.producer.save()

        self.basic_post_body = {
            "sender": "bell@localhost",
            "receiver": "watson@localhost",
            "alert_def": self.alert_def.uuid
        }
Пример #5
0
    def setUp(self):
        self.saved_search = SavedSearch.objects.all()[0]

        self.alert_def = AlertDefinition(name='alert_def',
                                         search=self.saved_search)
        self.alert_def.save()

        self.alert = Alert(short_message='test',
                           long_message='test123',
                           alert_def=self.alert_def)
        self.alert.save()

        self.producer = EmailProducer(sender='me@localhost',
                                      receiver='you@localhost',
                                      alert_def=self.alert_def)
        self.producer.save()

        self.basic_post_body = {
            'sender': '*****@*****.**',
            'receiver': '*****@*****.**',
            'alert_def': self.alert_def.uuid
        }
Пример #6
0
    def test_inner_send_mail_function(self):

        as_obj = AlertSearch()
        as_obj.save()
        new_alert = Alert(owner='core',
                          created='2015-09-01T13:20:30+03:00',
                          msg_title='Alert : openstack syslog errors',
                          msg_body='There are 23 incidents of syslog errors',
                          query_id=as_obj.pk)
        new_alert.save()
        with mock.patch("django.core.mail.send_mail") \
                as sm_mock:
                sm_mock.return_value = 1

                producer_inst = EmailProducer(query=as_obj,
                                              sender='*****@*****.**',
                                              receiver='*****@*****.**')
                producer_inst.save()
                rv = producer_inst.send(new_alert)
                self.assertEqual(rv, sm_mock.return_value)

        as_obj.delete()
        new_alert.delete()
Пример #7
0
    def setUp(self):

        self.saved_search = SavedSearch.objects.all()[0]

        self.alert_def = AlertDefinition(name='alert_def',
                                         search=self.saved_search)
        self.alert_def.save()

        self.producer = EmailProducer(sender='goldstone',
                                      receiver='someone-else',
                                      alert_def=self.alert_def)
        self.producer.save()

        self.alert = Alert(short_message='test', long_message='test123',
                           alert_def=self.alert_def)
        self.alert.save()
Пример #8
0
class ModelTests(TestCase):
    """ Test EmailProducer class model"""

    fixtures = ['core_initial_data.yaml']

    def setUp(self):

        self.saved_search = SavedSearch.objects.all()[0]

        self.alert_def = AlertDefinition(name='alert_def',
                                         search=self.saved_search)
        self.alert_def.save()

        self.producer = EmailProducer(sender='goldstone',
                                      receiver='someone-else',
                                      alert_def=self.alert_def)
        self.producer.save()

        self.alert = Alert(short_message='test', long_message='test123',
                           alert_def=self.alert_def)
        self.alert.save()

    def assertWithinASecond(self, datetime1, datetime2):
        ts1 = arrow.get(datetime1).timestamp / 1000.0
        ts2 = arrow.get(datetime2).timestamp / 1000.0
        self.assertAlmostEqual(ts1, ts2, places=0)

    def test_producer_superclass_raises(self):
        """ Calling send on the Producer superclass should raise an exception
        """

        with self.assertRaises(NotImplementedError):
            super(EmailProducer, self.producer).produce(self.alert)

    # @patch("django.core.mail.send_mail")
    @patch('goldstone.core.models.send_mail')
    def test_producer_produce(self, mock_send_mail):
        """ The return value from send_mail will be the number of successfully
        delivered messages (which can be 0 or 1 since it can only send one
        message).  It could also raise a SMTPException.

        Produce should just pass those through to the caller.
        """

        mock_send_mail.return_value = 1
        rv = self.producer.produce(self.alert)
        self.assertEqual(mock_send_mail.call_count, 1)
        self.assertEqual(rv, 1)

        mock_send_mail.return_value = 0
        rv = self.producer.produce(self.alert)
        self.assertEqual(mock_send_mail.call_count, 2)
        self.assertEqual(rv, 0)

        mock_send_mail.side_effect = SMTPException
        with self.assertRaises(SMTPException):
            self.producer.produce(self.alert)
            self.assertEqual(mock_send_mail.call_count, 3)

    def test_search(self):
        """The search method of a SavedSearch should return an ES search"""

        search = self.saved_search.search()
        self.assertIsInstance(search, Search)

    def test_search_recent(self):
        """The search_recent method of a SavedSearch should return an ES search
        a start datetime, and an end datetime.  The initial start datetime
        should be roughly the creation time of the object, and the initial end
        datetime should be roughly the creation time of the object.

        After a call to update_recent_search_window, the last_start and
        last_end dates should be adjusted to reflect the previous search_recent
        call.

        The search will a range clause on the SavedSearch.timestamp_field with
        a start of the last_end and an end of approximately now.

        Finally, if the SavedSearch.timestamp_field is None a search that is
        the same as the result of search() will be returned along with Nones
        for start and end.
        """

        #
        # first pass we should have initialized start/end times
        #
        search, start1, end1 = self.saved_search.search_recent()
        self.assertIsInstance(search, Search)
        self.assertIsInstance(start1, datetime)
        self.assertIsInstance(end1, datetime)
        self.assertWithinASecond(start1, end1)

        def find_range_dict(a, z):
            """Helper function that extracts the dict with range key."""
            if 'range' in z \
                    and self.saved_search.timestamp_field in z['range']:
                return z
            else:
                return a

        range_dict = reduce(lambda a, z: find_range_dict(a, z),
                            search.to_dict()['query']['bool']['must'],
                            None)

        # validate that the range block was added to the search
        self.assertIsNotNone(range_dict)

        # and that it has the expected start and end times
        self.assertDictContainsSubset(
            {'gte': start1.isoformat()},
            range_dict['range'][self.saved_search.timestamp_field])
        self.assertDictContainsSubset(
            {'lt': end1.isoformat()},
            range_dict['range'][self.saved_search.timestamp_field])

        self.saved_search.update_recent_search_window(start1, end1)

        #
        # let's get the persisted version of our object and test that
        # update_recent_search_window updated the last_start and last_end
        # fields of the object.
        #
        self.saved_search = SavedSearch.objects.get(
            uuid=self.saved_search.uuid)

        self.assertEqual(self.saved_search.last_start, start1)
        self.assertEqual(self.saved_search.last_end, end1)

        #
        # finally, let's run recent_search again and make sure we get updated
        # times.
        #
        search, start2, end2 = self.saved_search.search_recent()
        self.assertIsInstance(start2, datetime)
        self.assertIsInstance(end2, datetime)
        self.assertTrue(start2 == end1)
        self.assertTrue(start2 <= end2)

        range_dict = reduce(lambda a, z: find_range_dict(a, z),
                            search.to_dict()['query']['bool']['must'],
                            None)

        # validate that the range block was added to the search
        self.assertIsNotNone(range_dict)

        # and that it has the expected start and end times
        self.assertDictContainsSubset(
            {'gte': start2.isoformat()},
            range_dict['range'][self.saved_search.timestamp_field])
        self.assertDictContainsSubset(
            {'lt': end2.isoformat()},
            range_dict['range'][self.saved_search.timestamp_field])

        # doctype should not be set in the search if the SavedSearch doesn't
        # have one, and the result of search_recent() should be the same as
        # that of search() if there is no timestamp_field set.
        self.saved_search.timestamp_field = None
        self.saved_search.doc_type = None

        search = self.saved_search.search()
        search_recent = self.saved_search.search_recent()
        self.assertDictEqual(search.to_dict(), search_recent.to_dict())
        self.assertEqual(search._doc_type, [])

    @patch('goldstone.core.models.Alert')
    def test_alert_def_evaluate(self, mock_alert):
        """tests that alert definitions properly create alerts, and produce
        notifications."""

        # mock out a search_result to trigger the alert condition
        hit_count = 99
        search, start, end = self.saved_search.search_recent()
        search_result = {'hits': {'total': hit_count}}
        self.alert_def.evaluate(search_result, start, end)
        self.assertTrue(mock_alert.called)

        # should be called with *args and **kwargs
        self.assertEqual(len(mock_alert.call_args), 2)

        # interested in kwargs
        expected_short = 'Alert: \'%s\' triggered at %s' % \
            (self.alert_def.name, end)

        expected_long = 'There were %d instances of \'%s\' from ' \
                        '%s to %s.\nAlert Definition: %s' % \
                        (hit_count, self.alert_def.name,
                         start, end, self.alert_def.uuid)

        self.assertIs(mock_alert.call_args[1]['alert_def'], self.alert_def)
        self.assertEqual(mock_alert.call_args[1]['short_message'],
                         expected_short)
        self.assertEqual(mock_alert.call_args[1]['long_message'],
                         expected_long)
Пример #9
0
class ModelTests(TestCase):
    """ Test EmailProducer class model"""

    fixtures = ['core_initial_data.yaml']

    def setUp(self):

        self.saved_search = SavedSearch.objects.all()[0]

        self.alert_def = AlertDefinition(name='alert_def',
                                         search=self.saved_search)
        self.alert_def.save()

        self.producer = EmailProducer(sender='goldstone',
                                      receiver='someone-else',
                                      alert_def=self.alert_def)
        self.producer.save()

        self.alert = Alert(short_message='test',
                           long_message='test123',
                           alert_def=self.alert_def)
        self.alert.save()

    def assertWithinASecond(self, datetime1, datetime2):
        ts1 = arrow.get(datetime1).timestamp / 1000.0
        ts2 = arrow.get(datetime2).timestamp / 1000.0
        self.assertAlmostEqual(ts1, ts2, places=0)

    def test_producer_superclass_raises(self):
        """ Calling send on the Producer superclass should raise an exception
        """

        with self.assertRaises(NotImplementedError):
            super(EmailProducer, self.producer).produce(self.alert)

    # @patch("django.core.mail.send_mail")
    @patch('goldstone.core.models.send_mail')
    def test_producer_produce(self, mock_send_mail):
        """ The return value from send_mail will be the number of successfully
        delivered messages (which can be 0 or 1 since it can only send one
        message).  It could also raise a SMTPException.

        Produce should just pass those through to the caller.
        """

        mock_send_mail.return_value = 1
        rv = self.producer.produce(self.alert)
        self.assertEqual(mock_send_mail.call_count, 1)
        self.assertEqual(rv, 1)

        mock_send_mail.return_value = 0
        rv = self.producer.produce(self.alert)
        self.assertEqual(mock_send_mail.call_count, 2)
        self.assertEqual(rv, 0)

        mock_send_mail.side_effect = SMTPException
        with self.assertRaises(SMTPException):
            self.producer.produce(self.alert)
            self.assertEqual(mock_send_mail.call_count, 3)

    def test_search(self):
        """The search method of a SavedSearch should return an ES search"""

        search = self.saved_search.search()
        self.assertIsInstance(search, Search)

    def test_search_recent(self):
        """The search_recent method of a SavedSearch should return an ES search
        a start datetime, and an end datetime.  The initial start datetime
        should be roughly the creation time of the object, and the initial end
        datetime should be roughly the creation time of the object.

        After a call to update_recent_search_window, the last_start and
        last_end dates should be adjusted to reflect the previous search_recent
        call.

        The search will a range clause on the SavedSearch.timestamp_field with
        a start of the last_end and an end of approximately now.

        Finally, if the SavedSearch.timestamp_field is None a search that is
        the same as the result of search() will be returned along with Nones
        for start and end.
        """

        #
        # first pass we should have initialized start/end times
        #
        search, start1, end1 = self.saved_search.search_recent()
        self.assertIsInstance(search, Search)
        self.assertIsInstance(start1, datetime)
        self.assertIsInstance(end1, datetime)
        self.assertWithinASecond(start1, end1)

        def find_range_dict(a, z):
            """Helper function that extracts the dict with range key."""
            if 'range' in z \
                    and self.saved_search.timestamp_field in z['range']:
                return z
            else:
                return a

        range_dict = reduce(lambda a, z: find_range_dict(a, z),
                            search.to_dict()['query']['bool']['must'], None)

        # validate that the range block was added to the search
        self.assertIsNotNone(range_dict)

        # and that it has the expected start and end times
        self.assertDictContainsSubset(
            {'gte': start1.isoformat()},
            range_dict['range'][self.saved_search.timestamp_field])
        self.assertDictContainsSubset(
            {'lt': end1.isoformat()},
            range_dict['range'][self.saved_search.timestamp_field])

        self.saved_search.update_recent_search_window(start1, end1)

        #
        # let's get the persisted version of our object and test that
        # update_recent_search_window updated the last_start and last_end
        # fields of the object.
        #
        self.saved_search = SavedSearch.objects.get(
            uuid=self.saved_search.uuid)

        self.assertEqual(self.saved_search.last_start, start1)
        self.assertEqual(self.saved_search.last_end, end1)

        #
        # finally, let's run recent_search again and make sure we get updated
        # times.
        #
        search, start2, end2 = self.saved_search.search_recent()
        self.assertIsInstance(start2, datetime)
        self.assertIsInstance(end2, datetime)
        self.assertTrue(start2 == end1)
        self.assertTrue(start2 <= end2)

        range_dict = reduce(lambda a, z: find_range_dict(a, z),
                            search.to_dict()['query']['bool']['must'], None)

        # validate that the range block was added to the search
        self.assertIsNotNone(range_dict)

        # and that it has the expected start and end times
        self.assertDictContainsSubset(
            {'gte': start2.isoformat()},
            range_dict['range'][self.saved_search.timestamp_field])
        self.assertDictContainsSubset(
            {'lt': end2.isoformat()},
            range_dict['range'][self.saved_search.timestamp_field])

        # doctype should not be set in the search if the SavedSearch doesn't
        # have one, and the result of search_recent() should be the same as
        # that of search() if there is no timestamp_field set.
        self.saved_search.timestamp_field = None
        self.saved_search.doc_type = None

        search = self.saved_search.search()
        search_recent = self.saved_search.search_recent()
        self.assertDictEqual(search.to_dict(), search_recent.to_dict())
        self.assertEqual(search._doc_type, [])

    @patch('goldstone.core.models.Alert')
    def test_alert_def_evaluate(self, mock_alert):
        """tests that alert definitions properly create alerts, and produce
        notifications."""

        # mock out a search_result to trigger the alert condition
        hit_count = 99
        search, start, end = self.saved_search.search_recent()
        search_result = {'hits': {'total': hit_count}}
        self.alert_def.evaluate(search_result, start, end)
        self.assertTrue(mock_alert.called)

        # should be called with *args and **kwargs
        self.assertEqual(len(mock_alert.call_args), 2)

        # interested in kwargs
        expected_short = 'Alert: \'%s\' triggered at %s' % \
            (self.alert_def.name, end)

        expected_long = 'There were %d instances of \'%s\' from ' \
                        '%s to %s.\nAlert Definition: %s' % \
                        (hit_count, self.alert_def.name,
                         start, end, self.alert_def.uuid)

        self.assertIs(mock_alert.call_args[1]['alert_def'], self.alert_def)
        self.assertEqual(mock_alert.call_args[1]['short_message'],
                         expected_short)
        self.assertEqual(mock_alert.call_args[1]['long_message'],
                         expected_long)
Пример #10
0
class ProducerViewTests(APITestCase):
    """ Test Producer API """

    fixtures = ['core_initial_data.yaml']

    def setUp(self):
        self.saved_search = SavedSearch.objects.all()[0]

        self.alert_def = AlertDefinition(name='alert_def',
                                         search=self.saved_search)
        self.alert_def.save()

        self.alert = Alert(short_message='test',
                           long_message='test123',
                           alert_def=self.alert_def)
        self.alert.save()

        self.producer = EmailProducer(sender='me@localhost',
                                      receiver='you@localhost',
                                      alert_def=self.alert_def)
        self.producer.save()

        self.basic_post_body = {
            'sender': '*****@*****.**',
            'receiver': '*****@*****.**',
            'alert_def': self.alert_def.uuid
        }

    def test_not_logged_in(self):
        """All operations should fail when not logged in."""

        # Try getting resource with no token.
        response = self.client.get(PRODUCER_URL)

        self.assertContains(response,
                            CONTENT_NO_CREDENTIALS,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try getting resource a bogus token.
        response = self.client.get(
            PRODUCER_URL,
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % BAD_TOKEN)

        self.assertContains(response,
                            CONTENT_BAD_TOKEN,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try creating resource with no token.
        response = self.client.post(PRODUCER_URL,
                                    json.dumps(self.basic_post_body),
                                    content_type="application/json")

        self.assertContains(response,
                            CONTENT_NO_CREDENTIALS,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try creating resource with a bogus token.
        response = self.client.post(
            PRODUCER_URL,
            json.dumps(self.basic_post_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % BAD_TOKEN)

        self.assertContains(response,
                            CONTENT_BAD_TOKEN,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try updating resource with no token.
        response = self.client.put(
            PRODUCER_URL + self.alert_def.uuid + '/',
            json.dumps(self.basic_post_body),
            content_type="application/json")

        self.assertContains(response,
                            CONTENT_NO_CREDENTIALS,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try updating resource with a bogus token.
        response = self.client.put(
            PRODUCER_URL + self.alert_def.uuid + '/',
            json.dumps(self.basic_post_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % BAD_TOKEN)

        self.assertContains(response,
                            CONTENT_BAD_TOKEN,
                            status_code=status.HTTP_401_UNAUTHORIZED)

    def test_post_not_allowed(self):
        """POST operation tests"""

        # Create a user and get the authorization token. Then do the test.
        token = create_and_login()

        # Try creating resource with a valid token.
        response = self.client.post(
            PRODUCER_URL,
            json.dumps(self.basic_post_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        # pylint: disable=E1101
        self.assertEqual(response.status_code,
                         status.HTTP_405_METHOD_NOT_ALLOWED)

    def test_get(self):
        """GET operation tests"""

        # Create a user and get the authorization token. Then do the test.
        token = create_and_login()

        # We should have at least one result in our list, but could have more
        response = self.client.get(
            PRODUCER_URL,
            accept="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        content = json.loads(response.content)
        self.assertIn('count', content)
        self.assertIn('next', content)
        self.assertIn('previous', content)
        self.assertIn('results', content)
        self.assertIsInstance(content['results'], list)
        self.assertGreater(len(content['results']), 0)

        # test the structure of the one we loaded

        response = self.client.get(
            PRODUCER_URL + "%s/" % self.producer.uuid,
            accept="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        content = json.loads(response.content)
        self.assertIn('uuid', content)
        self.assertIn('alert_def', content)
        self.assertIn('created', content)
        self.assertIn('updated', content)
        self.assertIn('sender', content)
        self.assertIn('receiver', content)

    def test_delete_not_allowed(self):
        """DELETE operation tests"""
        # Create a user and get the authorization token. Then do the test.
        token = create_and_login()

        # Try creating resource with a valid token.
        response = self.client.delete(
            PRODUCER_URL + '%s/' % self.alert_def.uuid,
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code,
                         status.HTTP_405_METHOD_NOT_ALLOWED)

    def test_put_not_allowed(self):
        """PUT operation tests"""
        # Create a user and get the authorization token. Then do the test.
        token = create_and_login()

        # Try creating resource with a valid token.
        response = self.client.put(
            PRODUCER_URL + '%s/' % self.alert_def.uuid,
            json.dumps(self.basic_post_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code,
                         status.HTTP_405_METHOD_NOT_ALLOWED)

    def test_patch_not_allowed(self):
        """PATCH operation tests"""
        # Create a user and get the authorization token. Then do the test.
        token = create_and_login()

        # Try creating resource with a valid token.
        response = self.client.put(
            PRODUCER_URL + '%s/' % self.alert_def.uuid,
            json.dumps(self.basic_post_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code,
                         status.HTTP_405_METHOD_NOT_ALLOWED)
Пример #11
0
class EmailProducerViewTests(APITestCase):
    """ Test Email Producer API """

    fixtures = ['core_initial_data.yaml']

    def setUp(self):
        self.saved_search = SavedSearch.objects.all()[0]

        self.alert_def = AlertDefinition(name='alert_def',
                                         search=self.saved_search)
        self.alert_def.save()

        self.alert = Alert(short_message='test',
                           long_message='test123',
                           alert_def=self.alert_def)
        self.alert.save()

        self.producer = EmailProducer(sender='me', receiver='you',
                                      alert_def=self.alert_def)
        self.producer.save()

        self.basic_post_body = {
            "sender": "bell@localhost",
            "receiver": "watson@localhost",
            "alert_def": self.alert_def.uuid
        }

    def test_not_logged_in(self):
        """All operations should fail when not logged in."""

        # Try getting resource with no token.
        response = self.client.get(EMAIL_PRODUCER_URL)

        self.assertContains(response,
                            CONTENT_NO_CREDENTIALS,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try getting resource a bogus token.
        response = self.client.get(
            EMAIL_PRODUCER_URL,
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % BAD_TOKEN)

        self.assertContains(response,
                            CONTENT_BAD_TOKEN,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try creating resource with no token.
        response = self.client.post(EMAIL_PRODUCER_URL,
                                    json.dumps(self.basic_post_body),
                                    content_type="application/json")

        self.assertContains(response,
                            CONTENT_NO_CREDENTIALS,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try creating resource with a bogus token.
        response = self.client.post(
            EMAIL_PRODUCER_URL,
            json.dumps(self.basic_post_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % BAD_TOKEN)

        self.assertContains(response,
                            CONTENT_BAD_TOKEN,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try updating resource with no token.
        response = self.client.put(
            EMAIL_PRODUCER_URL + self.alert_def.uuid + '/',
            json.dumps(self.basic_post_body),
            content_type="application/json")

        self.assertContains(response,
                            CONTENT_NO_CREDENTIALS,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try updating resource with a bogus token.
        response = self.client.put(
            EMAIL_PRODUCER_URL + self.alert_def.uuid + '/',
            json.dumps(self.basic_post_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % BAD_TOKEN)

        self.assertContains(response,
                            CONTENT_BAD_TOKEN,
                            status_code=status.HTTP_401_UNAUTHORIZED)

    def test_crud(self):
        """POST operation tests"""

        # Create a user and get the authorization token. Then do the test.
        token = create_and_login()

        # Try creating resource with a valid token.
        response = self.client.post(
            EMAIL_PRODUCER_URL,
            json.dumps(self.basic_post_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code,
                         status.HTTP_201_CREATED)

        # Quick test of a filtered GET of the new resource
        response = self.client.get(
            EMAIL_PRODUCER_URL + "?sender=bell@localhost",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        content = json.loads(response.content)

        self.assertIn('count', content)
        self.assertIn('next', content)
        self.assertIn('previous', content)
        self.assertIn('results', content)
        self.assertIsInstance(content['results'], list)
        self.assertGreater(len(content['results']), 0)

        self.bell_uuid = content['results'][0]['uuid']

        # test the structure of the record we posted

        response = self.client.get(
            EMAIL_PRODUCER_URL + "%s/" % self.bell_uuid,
            accept="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        content = json.loads(response.content)
        self.assertIn('uuid', content)
        self.assertIn('alert_def', content)
        self.assertIn('created', content)
        self.assertIn('updated', content)
        self.assertIn('sender', content)
        self.assertIn('receiver', content)
        self.assertEqual(content['sender'], 'bell@localhost')
        self.assertEqual(content['receiver'], 'watson@localhost')
        self.bell_content = content

        put_body = self.bell_content
        put_body['receiver'] = 'howell@localhost'

        # Try updating resource with a valid token.
        response = self.client.put(
            EMAIL_PRODUCER_URL + '%s/' % self.bell_uuid,
            json.dumps(put_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code,
                         status.HTTP_200_OK)

        # Try patching resource with a valid token.
        response = self.client.patch(
            EMAIL_PRODUCER_URL + '%s/' % self.bell_uuid,
            json.dumps({'receiver': 'watson@localhost'}),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code,
                         status.HTTP_200_OK)

        # Try deleting resource with a valid token.
        response = self.client.delete(
            EMAIL_PRODUCER_URL + '%s/' % self.bell_uuid,
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code,
                         status.HTTP_204_NO_CONTENT)