'''
Baseline Unit Test
'''
import difflib
import os.path
import pprint
import unittest
from unittest.util import safe_repr

import fakeredis

from rsmq.rsmq import RedisSMQ


BASE_DIR = os.path.dirname(os.path.dirname(__file__))


class TestUnitTests(unittest.TestCase):
    ''' Unit Test RedisSMQ'''

    def setUp(self):
        ''' Setup '''

    def assertQueueAttributes(self, expected, actual, msg=None):
        ''' assert queue attributes are set '''
        self.assertIsInstance(
            expected, dict, 'First argument is not a dictionary')
        self.assertIsInstance(
            actual, dict, 'Second argument is not a dictionary')
        actual_short = {key: actual[key] for key in expected.keys()}
        if not expected.items() <= actual.items():
            diff = ('\n' + '\n'.join(difflib.ndiff(
                           pprint.pformat(expected).splitlines(),
                           pprint.pformat(actual_short).splitlines())))
            standardMsg = '%s !<= %s' % (
                safe_repr(expected), safe_repr(actual_short))
            standardMsg = self._truncateMessage(standardMsg, diff)
            msg = self._formatMessage(msg, standardMsg)
            raise AssertionError(msg)

    def test_unittest(self):
        ''' Check Unit Test Framework '''
        unittest_loaded = True
        self.assertTrue(unittest_loaded)

    def test_qname_good_validation(self):
        ''' Test Good QName validation '''
        client = fakeredis.FakeStrictRedis(decode_responses=True)
        client.flushall()
        queue = RedisSMQ(client=client, exceptions=False)
        GOOD_QUEUE_NAMES = ['simple', 'with_underscore', 'with-dash', '-start',
                            'with\x01\x02\x03binary']

        for qname in GOOD_QUEUE_NAMES:
            self.assertTrue(queue.getQueueAttributes().qname(qname).ready())

    def test_qname_bad_validation(self):
        ''' Test bad QName validation '''
        client = fakeredis.FakeStrictRedis(decode_responses=True)
        client.flushall()
        queue = RedisSMQ(client=client, exceptions=False)
        BAD_QUEUE_NAMES = ['', None, 'something:else',
                           ':', 'something:', ':else']

        for qname in BAD_QUEUE_NAMES:
            self.assertFalse(queue.getQueueAttributes().qname(qname).ready())

    def test_create_queue_default(self):
        ''' Test Creating of the Queue '''
        client = fakeredis.FakeStrictRedis(decode_responses=True)
        client.flushall()
        queue = RedisSMQ(client=client)
        queue_name = 'test-queue'
        queue_key = 'rsmq:%s:Q' % queue_name
        queue.createQueue().qname(queue_name).execute()
        keys = client.keys('*')
        self.assertListEqual(sorted([queue_key, 'rsmq:QUEUES']), sorted(keys))
        queues = client.smembers('rsmq:QUEUES')
        self.assertSetEqual(set([queue_name]), queues)
        queue_details = client.hgetall(queue_key)
        self.assertTrue(
            {'vt': '30', 'delay': '0', 'maxsize': '65565'}.items() <= queue_details.items())

    def test_create_queue_custom(self):
        ''' Test Creating of the Queue '''
        client = fakeredis.FakeStrictRedis(decode_responses=True)
        client.flushall()
        queue = RedisSMQ(client=client)
        queue_name = 'test-queue-2'
        queue_key = 'rsmq:%s:Q' % queue_name
        queue.createQueue(qname=queue_name, vt=15).delay(10).execute()
        keys = client.keys('*')
        self.assertListEqual(sorted([queue_key, 'rsmq:QUEUES']), sorted(keys))
        queues = client.smembers('rsmq:QUEUES')
        self.assertSetEqual(set([queue_name]), queues)
        queue_details = client.hgetall(queue_key)

        self.assertTrue(
            {'vt': '15', 'delay': '10', 'maxsize': '65565'}.items() <= queue_details.items())

    def test_delete_queue(self):
        ''' Test Deleting of the Queue '''
        client = fakeredis.FakeStrictRedis(decode_responses=True)
        client.flushall()
        queue = RedisSMQ(client=client)
        queue_name = 'test-queue-delete'
        queue_key = 'rsmq:%s:Q' % queue_name
        queue.createQueue().qname(queue_name).execute()
        keys = client.keys('*')
        self.assertListEqual(sorted([queue_key, 'rsmq:QUEUES']), sorted(keys))
        queues = client.smembers('rsmq:QUEUES')
        self.assertSetEqual(set([queue_name]), queues)
        queue_details = client.hgetall(queue_key)
        self.assertTrue(
            {'vt': '30', 'delay': '0', 'maxsize': '65565'}.items() <= queue_details.items())
        result = queue.deleteQueue(qname=queue_name).execute()
        self.assertEqual(result, True)
        queue_details = client.hgetall(queue_key)
        self.assertEqual(queue_details, {})

    def test_queue_attributes(self):
        ''' Test Getting/Setting of the Queue Attribues'''
        client = fakeredis.FakeStrictRedis(decode_responses=True)
        client.flushall()
        queue_name = 'test-queue-attr'
        queue = RedisSMQ(client=client, qname=queue_name)
        queue_key = 'rsmq:%s:Q' % queue_name
        queue.createQueue(vt=15, delay=10).execute()
        keys = client.keys('*')
        self.assertListEqual(sorted([queue_key, 'rsmq:QUEUES']), sorted(keys))
        queues = client.smembers('rsmq:QUEUES')
        self.assertSetEqual(set([queue_name]), queues)
        queue_details = client.hgetall(queue_key)
        self.assertQueueAttributes(
            {'vt': '15', 'delay': '10', 'maxsize': '65565'}, queue_details)
        attributes = queue.getQueueAttributes(qname=queue_name).execute()
        self.assertQueueAttributes({'vt': '15',
                                    'delay': '10',
                                    'maxsize': '65565',
                                    'totalrecv': 0,
                                    'totalsent': 0,
                                    'msgs': 0,
                                    'hiddenmsgs': 0}, attributes)
        attributes_1 = queue.setQueueAttributes(
            vt=30, maxsize=1024, delay=1).execute()
        attributes = queue.getQueueAttributes(qname=queue_name).execute()
        self.assertDictEqual(attributes, attributes_1)
        self.assertQueueAttributes({'vt': '30',
                                    'delay': '1',
                                    'maxsize': '1024',
                                    'totalrecv': 0,
                                    'totalsent': 0,
                                    'msgs': 0,
                                    'hiddenmsgs': 0}, attributes)

    def test_invalid_queue_attributes(self):
        ''' Test Getting/Setting of the Queue Attribues'''
        client = fakeredis.FakeStrictRedis(decode_responses=True)
        client.flushall()
        queue_name = 'test-queue-attr'
        queue = RedisSMQ(client=client, qname=queue_name)
        queue_key = 'rsmq:%s:Q' % queue_name
        queue.createQueue(vt=15, delay=10).execute()
        keys = client.keys('*')
        self.assertListEqual(sorted([queue_key, 'rsmq:QUEUES']), sorted(keys))
        queues = client.smembers('rsmq:QUEUES')
        self.assertSetEqual(set([queue_name]), queues)
        queue_details = client.hgetall(queue_key)
        self.assertQueueAttributes(
            {'vt': '15', 'delay': '10', 'maxsize': '65565'}, queue_details)
        attributes = queue.getQueueAttributes(qname=queue_name).execute()
        self.assertQueueAttributes({'vt': '15',
                                    'delay': '10',
                                    'maxsize': '65565',
                                    'totalrecv': 0,
                                    'totalsent': 0,
                                    'msgs': 0,
                                    'hiddenmsgs': 0}, attributes)
        attributes_1 = queue.setQueueAttributes(
            vt=-3, maxsize=-2, delay=-1).execute()
        attributes = queue.getQueueAttributes(qname=queue_name).execute()
        self.assertDictEqual(attributes, attributes_1)
        self.assertQueueAttributes({'vt': '15',
                                    'delay': '10',
                                    'maxsize': '65565',
                                    'totalrecv': 0,
                                    'totalsent': 0,
                                    'msgs': 0,
                                    'hiddenmsgs': 0}, attributes)


if __name__ == '__main__':
    unittest.main()
