'''Test the queue functionality'''

from common import TestQless

class TestJobs(TestQless):
    '''We should be able to list jobs in various states for a given queue'''
    def test_malformed(self):
        '''Enumerate all the ways that the input can be malformed'''
        self.assertMalformed(self.lua, [
            ('jobs', 0, 'complete', 'foo'),
            ('jobs', 0, 'complete', 0, 'foo'),
            ('jobs', 0, 'running'),
            ('jobs', 0, 'running', 'queue', 'foo'),
            ('jobs', 0, 'running', 'queue', 0, 'foo'),
            ('jobs', 0, 'stalled'),
            ('jobs', 0, 'stalled`', 'queue', 'foo'),
            ('jobs', 0, 'stalled', 'queue', 0, 'foo'),
            ('jobs', 0, 'scheduled'),
            ('jobs', 0, 'scheduled', 'queue', 'foo'),
            ('jobs', 0, 'scheduled', 'queue', 0, 'foo'),
            ('jobs', 0, 'depends'),
            ('jobs', 0, 'depends', 'queue', 'foo'),
            ('jobs', 0, 'depends', 'queue', 0, 'foo'),
            ('jobs', 0, 'recurring'),
            ('jobs', 0, 'recurring', 'queue', 'foo'),
            ('jobs', 0, 'recurring', 'queue', 0, 'foo'),
            ('jobs', 0, 'foo', 'queue', 0, 25)
        ])

    def test_complete(self):
        '''Verify we can list complete jobs'''
        jids = map(str, range(10))
        for jid in jids:
            self.lua('put', jid, 'worker', 'queue', jid, 'klass', {}, 0)
            self.lua('pop', jid, 'queue', 'worker', 10)
            self.lua('complete', jid, jid, 'worker', 'queue', {})
            complete = self.lua('jobs', jid, 'complete')
            self.assertEqual(len(complete), int(jid) + 1)
            self.assertEqual(complete[0], jid)

    def test_running(self):
        '''Verify that we can get a list of running jobs in a queue'''
        jids = map(str, range(10))
        for jid in jids:
            self.lua('put', jid, 'worker', 'queue', jid, 'klass', {}, 0)
            self.lua('pop', jid, 'queue', 'worker', 10)
            running = self.lua('jobs', jid, 'running', 'queue')
            self.assertEqual(len(running), int(jid) + 1)
            self.assertEqual(running[-1], jid)

    def test_stalled(self):
        '''Verify that we can get a list of stalled jobs in a queue'''
        self.lua('config.set', 0, 'heartbeat', 10)
        jids = map(str, range(10))
        for jid in jids:
            self.lua('put', jid, 'worker', 'queue', jid, 'klass', {}, 0)
            self.lua('pop', jid, 'queue', 'worker', 10)
            stalled = self.lua('jobs', int(jid) + 20, 'stalled', 'queue')
            self.assertEqual(len(stalled), int(jid) + 1)
            self.assertEqual(stalled[-1], jid)

    def test_scheduled(self):
        '''Verify that we can get a list of scheduled jobs in a queue'''
        jids = map(str, range(1, 11))
        for jid in jids:
            self.lua('put', jid, 'worker', 'queue', jid, 'klass', {}, jid)
            scheduled = self.lua('jobs', 0, 'scheduled', 'queue')
            self.assertEqual(len(scheduled), int(jid))
            self.assertEqual(scheduled[-1], jid)

    def test_depends(self):
        '''Verify that we can get a list of dependent jobs in a queue'''
        self.lua('put', 0, 'worker', 'queue', 'a', 'klass', {}, 0)
        jids = map(str, range(0, 10))
        for jid in jids:
            self.lua(
                'put', jid, 'worker', 'queue', jid, 'klass', {}, 0, 'depends', ['a'])
            depends = self.lua('jobs', 0, 'depends', 'queue')
            self.assertEqual(len(depends), int(jid) + 1)
            self.assertEqual(depends[-1], jid)

    def test_recurring(self):
        '''Verify that we can get a list of recurring jobs in a queue'''
        jids = map(str, range(0, 10))
        for jid in jids:
            self.lua(
                'recur', jid, 'queue', jid, 'klass', {}, 'interval', 60, 0)
            recurring = self.lua('jobs', 0, 'recurring', 'queue')
            self.assertEqual(len(recurring), int(jid) + 1)
            self.assertEqual(recurring[-1], jid)

    def test_recurring_offset(self):
        '''Recurring jobs with a future offset should be included'''
        jids = map(str, range(0, 10))
        for jid in jids:
            self.lua(
                'recur', jid, 'queue', jid, 'klass', {}, 'interval', 60, 10)
            recurring = self.lua('jobs', 0, 'recurring', 'queue')
            self.assertEqual(len(recurring), int(jid) + 1)
            self.assertEqual(recurring[-1], jid)

    def test_scheduled_waiting(self):
        '''Jobs that were scheduled but are ready shouldn't be in scheduled'''
        self.lua('put', 0, 'worker', 'queue', 'jid', 'klass', {}, 10)
        self.assertEqual(len(self.lua('jobs', 20, 'scheduled', 'queue')), 0)

    def test_pagination_complete(self):
        '''Jobs should be able to provide paginated results for complete'''
        jids = map(str, range(100))
        for jid in jids:
            self.lua('put', jid, 'worker', 'queue', jid, 'klass', {}, 0)
            self.lua('pop', jid, 'queue', 'worker', 10)
            self.lua('complete', jid, jid, 'worker', 'queue', {})
        # Get two pages and ensure they're what we expect
        jids = list(reversed(jids))
        self.assertEqual(
            self.lua('jobs', 0, 'complete',  0, 50), jids[:50])
        self.assertEqual(
            self.lua('jobs', 0, 'complete', 50, 50), jids[50:])

    def test_pagination_running(self):
        '''Jobs should be able to provide paginated result for running'''
        jids = map(str, range(100))
        self.lua('config.set', 0, 'heartbeat', 1000)
        for jid in jids:
            self.lua('put', jid, 'worker', 'queue', jid, 'klass', {}, 0)
            self.lua('pop', jid, 'queue', 'worker', 10)
        # Get two pages and ensure they're what we expect
        self.assertEqual(
            self.lua('jobs', 100, 'running', 'queue',  0, 50), jids[:50])
        self.assertEqual(
            self.lua('jobs', 100, 'running', 'queue', 50, 50), jids[50:])


class TestQueue(TestQless):
    '''Test queue info tests'''
    expected = {
        'name': 'queue',
        'paused': False,
        'stalled': 0,
        'waiting': 0,
        'running': 0,
        'depends': 0,
        'scheduled': 0,
        'recurring': 0,
        'throttled': 0
    }

    def setUp(self):
        TestQless.setUp(self)
        # No grace period
        self.lua('config.set', 0, 'grace-period', 0)

    def test_stalled(self):
        '''Discern stalled job counts correctly'''
        expected = dict(self.expected)
        expected['stalled'] = 1
        self.lua('put', 0, 'worker', 'queue', 'jid', 'klass', {}, 0)
        job = self.lua('pop', 1, 'queue', 'worker', 10)[0]
        expires = job['expires'] + 10
        self.assertEqual(self.lua('queues', expires, 'queue'), expected)
        self.assertEqual(self.lua('queues', expires), [expected])

    def test_throttled(self):
        '''Discern throttled job counts correctly'''
        expected = dict(self.expected)
        expected['throttled'] = 1
        expected['running'] = 1
        self.lua('throttle.set', 0, 'ql:q:queue', 1)
        self.lua('put', 1, 'worker', 'queue', 'jid1', 'klass', {}, 0)
        self.lua('put', 2, 'worker', 'queue', 'jid2', 'klass', {}, 0)