class MozillaNagiosStatusTest(unittest.TestCase):
    tc = None

    def setUp(self):
        self.event = Mock()
        self.event.source = 'rtucker'
        self.event.target = '#sysadmins'
        self.connection = Mock()
        self.tc = MozillaNagiosStatus(self.connection, [])
        self.my_nick = self.event.source
        self.service_line = '[1318882274] SERVICE NOTIFICATION: sysalertslist;fake-host.mozilla.org;root partition;CRITICAL;notify-by-email;DISK CRITICAL - free space: / 5294 MB (5% inode=99%):'
        self.ack_line = '[1318870432] SERVICE NOTIFICATION: socorroalertlist;fake-host.mozilla.org;Disk Space /;ACKNOWLEDGEMENT (WARNING);notify-by-email;DISK WARNING - free space: / 60658 MB (29% inode=97%):;ashish;bug 689547'
        self.host_line = "[1313158996] HOST NOTIFICATION: sysalertslist;fake-host.mozilla.org;DOWN;host-notify-by-email;PING CRITICAL - Packet loss = 100%"
        self.ack_host_line = "[1319720894] HOST NOTIFICATION: sysalertslist;fake-host.mozilla.org;ACKNOWLEDGEMENT (DOWN);host-notify-by-email;PING CRITICAL - Packet loss = 100%;rtucker;known"

    def test_get_environment_vars(self):
        self.assertEqual(self.tc.list_offset, 100)
        self.assertEqual(self.tc.list_size, 100)

    def test_ackable_list_bad_host(self):
        self.assertEqual(len(self.tc.ackable_list), 100)
        self.tc.ackable('Test Host-Not Found', 'Test Service', 'CRITICAL', 'Test Message')
        self.assertEqual(self.tc.get_ack_number(), 100)
        self.assertEqual(len(self.tc.ackable_list), 100)
        self.assertEqual(self.tc.ackable_list[0]['host'], 'Test Host-Not Found')
        self.assertEqual(self.tc.ackable_list[0]['service'], 'Test Service')
        self.assertEqual(self.tc.ackable_list[0]['state'], 'CRITICAL')
        self.assertEqual(self.tc.ackable_list[0]['message'], 'Test Message')

    def test_downtime_by_index_bad_host(self):
        self.tc.ackable('Test Host-Not Found', 'Test Service', 'CRITICAL', 'Test Message')
        self.assertEqual(self.tc.get_ack_number(), 100)
        message = 'downtime 100 1m blah blah'
        m = re.search('^downtime\s+(\d+)\s+(\d+[dhms])\s+(.*)\s*$', message)
        target, message = self.tc.downtime_by_index(self.event, message, m)
        self.assertEqual(target, '#sysadmins')
        self.assertEqual(message, '%s: Unable to find host' % self.my_nick)

    def test_downtime_by_host_only(self):
        self.tc.ackable('test-host.fake.mozilla.com', None, 'CRITICAL', 'Test Message')
        self.assertEqual(self.tc.get_ack_number(), 100)
        message = 'downtime test-host.fake.mozilla.com 1m blah blah'
        m = re.search('^downtime\s+([^: ]+)(?::(.*))?\s+(\d+[dhms])\s+(.*)\s*$', message)
        target, message = self.tc.downtime(self.event, message, m)
        self.assertEqual(target, '#sysadmins')
        self.assertEqual(message, '%s: Downtime for test-host.fake.mozilla.com scheduled for 0:01:00' % (self.my_nick) )

    def test_downtime_by_host_only_cmd_return(self):
        self.tc.ackable('test-host.fake.mozilla.com', None, 'CRITICAL', 'Test Message')
        self.assertEqual(self.tc.get_ack_number(), 100)
        message = 'downtime test-host.fake.mozilla.com 1m blah blah'
        m = re.search('^downtime\s+([^: ]+)(?::(.*))?\s+(\d+[dhms])\s+(.*)\s*$', message)
        cmd = self.tc.downtime(self.event, message, m, return_cmd=True)
        ### fixup timestamp vars in response
        ### Replace the execution timestamp
        cmd = re.sub('\[\d+\]', '[000000]', cmd)
        ### Replace the start and end timestamp
        cmd = re.sub('\.com;\d+;\d+;', '.com;1234;5678;', cmd)
        ### Confirm that the syntax is correct per:

        self.assertEqual(cmd, '[000000] SCHEDULE_HOST_DOWNTIME;test-host.fake.mozilla.com;1234;5678;2;0;60;%s;blah blah\n' % (self.my_nick ))

    def test_downtime_by_index_host_only(self):
        self.tc.ackable('test-host.fake.mozilla.com', None, 'CRITICAL', 'Test Message')
        self.assertEqual(self.tc.get_ack_number(), 100)
        message = 'downtime 100 1m blah blah'
        m = re.search('^downtime\s+(\d+)\s+(\d+[dhms])\s+(.*)\s*$', message)
        target, message = self.tc.downtime_by_index(self.event, message, m)
        self.assertEqual(target, '#sysadmins')
        self.assertEqual(message, '%s: Downtime for test-host.fake.mozilla.com scheduled for 0:01:00' % (self.my_nick) )

    def test_downtime_by_index_with_service(self):
        self.tc.ackable('test-host.fake.mozilla.com', 'Test Service', 'CRITICAL', 'Test Message')
        self.assertEqual(self.tc.get_ack_number(), 100)
        message = 'downtime 100 1m blah blah'
        m = re.search('^downtime\s+(\d+)\s+(\d+[dhms])\s+(.*)\s*$', message)
        target, message = self.tc.downtime_by_index(self.event, message, m)
        self.assertEqual(target, '#sysadmins')
        self.assertEqual(message, '%s: Downtime for test-host.fake.mozilla.com:Test Service scheduled for 0:01:00' % (self.my_nick) )

    def test_increment_ackable_list_correctly(self):
        self.tc.ackable('test-host.fake.mozilla.com', 'Test Service', 'CRITICAL', 'Test Message')
        self.assertEqual(self.tc.get_ack_number(), 100)
        self.assertEqual(len(self.tc.ackable_list), 100)
        self.assertEqual(self.tc.ackable_list[0]['service'], 'Test Service')
        self.tc.ackable('test-host.fake.mozilla.com', 'Test Service 2', 'CRITICAL', 'Test Message')
        self.assertEqual(self.tc.ackable_list[0]['service'], 'Test Service')
        self.assertEqual(self.tc.ackable_list[1]['service'], 'Test Service 2')

    def test_downtime_by_hostname_with_service(self):
        self.tc.ackable('test-host.fake.mozilla.com', 'Test Service', 'CRITICAL', 'Test Message')
        self.assertEqual(self.tc.get_ack_number(), 100)
        message = 'downtime 100 1m blah blah'
        m = re.search('^downtime\s+(\d+)\s+(\d+[dhms])\s+(.*)\s*$', message)
        target, message = self.tc.downtime_by_index(self.event, message, m)
        self.assertEqual(target, '#sysadmins')
        self.assertEqual(message, '%s: Downtime for test-host.fake.mozilla.com:Test Service scheduled for 0:01:00' % (self.my_nick) )

    def test_downtime_by_hostname(self):
        self.tc.ackable('test-host.fake.mozilla.com', None, 'CRITICAL', 'Test Message')
        self.assertEqual(self.tc.get_ack_number(), 100)
        message = 'downtime test-host.fake.mozilla.com 1m blah blah'
        m = re.search('^downtime\s+([^: ]+)(?::(.*))?\s+(\d+[dhms])\s+(.*)\s*$', message)
        target, message = self.tc.downtime(self.event, message, m)
        self.assertEqual(target, '#sysadmins')
        self.assertEqual(message, '%s: Downtime for test-host.fake.mozilla.com scheduled for 0:01:00' % (self.my_nick) )

    def test_mute(self):
        message = "mute"
        m = None
        target, message = self.tc.mute(self.event, message, m)
        self.assertEqual(target, "#sysadmins")
        self.assertEqual(message, "%s: OK I'll mute" % (self.my_nick) )

    def test_already_muted(self):
        message = "mute"
        m = None
        target, message = self.tc.mute(self.event, message, m)
        target, message = self.tc.mute(self.event, message, m)
        self.assertEqual(target, "#sysadmins")
        self.assertEqual(message, "%s: I'm already muted" % (self.my_nick) )

    def test_already_muted_unmute(self):
        message = "mute"
        m = None
        target, message = self.tc.mute(self.event, message, m)
        message = "unmute"
        target, message = self.tc.unmute(self.event, message, m)
        self.assertEqual(target, "#sysadmins")
        self.assertEqual(message, "%s: OK I'll unmute" % (self.my_nick) )

    def test_unmute_when_not_previously_muted(self):
        m = None
        message = "unmute"
        target, message = self.tc.unmute(self.event, message, m)
        self.assertEqual(target, "#sysadmins")
        self.assertEqual(message, "%s: OK I'm not muted" % (self.my_nick) )

    def test_oncall(self):
        m = None
        message = "whoisoncall"
        target, message = self.tc.get_oncall(self.event, message, m)
        self.assertEqual(target, "#sysadmins")
        self.assertEqual(message, "%s: unknown currently has the pager" % (self.my_nick) )

    def test_unack_host(self):
        message = "unack test-host.fake.mozilla.com"
        m = re.search('^unack ([^:]+)\s*$', message)
        target, message = self.tc.unack_by_host(self.event, message, m)
        self.assertEqual(target, "#sysadmins")
        self.assertEqual(message, "%s: ok, acknowledgment (if any) for test-host.fake.mozilla.com has been removed." % (self.my_nick) )

    def test_ack_host_with_service(self):
        message = "ack test-host.fake.mozilla.com:asdf test message"
        m = re.search('^\s*ack ([^:]+):([^:]+)\s(.*)$', message)
        target, message = self.tc.ack_by_host_with_service(self.event, message, m)
        self.assertEqual(target, "#sysadmins")
        self.assertEqual(message, "%s: The Service test-host.fake.mozilla.com:asdf test has been ack'd" % (self.my_nick) )

    def test_ack_host(self):
        message = "ack test-host.fake.mozilla.com test message"
        m = re.search('^\s*ack ([^:]+)\s(.*)$', message)
        target, message = self.tc.ack_by_host(self.event, message, m)
        self.assertEqual(target, "#sysadmins")
        self.assertEqual(message, "%s: The Host test-host.fake.mozilla.com test has been ack'd" % (self.my_nick) )

    def test_ack_host_by_index(self):
        self.tc.process_line(self.host_line, True)
        self.assertEqual(self.tc.get_ack_number(), 100)
        message = "ack 100 test message"
        m = re.search('^(?:\s*ack\s*)?(\d+)(?:\s*ack\s*)?[:\s]+([^:]+)\s*$', message)
        target, message = self.tc.ack(self.event, message, m)
        self.assertEqual(target, "#sysadmins")
        self.assertEqual(message, "%s: The Host fake-host.mozilla.org has been ack'd" % (self.my_nick) )
        self.tc.process_line(self.ack_host_line, True)
        self.assertEqual(target, "#sysadmins")
        self.assertEqual(message, "%s: The Host fake-host.mozilla.org has been ack'd" % (self.my_nick) )
        
    def test_ack_host_by_index_after_one_cycle(self):
        self.tc.ackable_list = [None]*self.tc.list_size
        self.assertEqual(len(self.tc.ackable_list), 100)
        for i in range(0,101):
            service_line = "[1318882274] SERVICE NOTIFICATION: sysalertslist;fake-host.mozilla.org;root partition%s;CRITICAL;notify-by-email;DISK CRITICAL - free space: / 5294 MB (5 inode=99):" % i
            self.tc.process_line(service_line, True)
        message = "ack 100 test message"
        m = re.search('^(?:\s*ack\s*)?(\d+)(?:\s*ack\s*)?[:\s]+([^:]+)\s*$', message)
        target, message = self.tc.ack(self.event, message, m)
        self.assertEqual(target, "#sysadmins")
        self.assertEqual(message, "%s: The Service fake-host.mozilla.org:root partition100 has been ack'd" % (self.my_nick) )
        self.tc.process_line(self.ack_host_line, True)

    def test_ack_host_by_index_after_one_cycle_long_service_message(self):
        self.tc.ackable_list = [None]*self.tc.list_size
        self.assertEqual(len(self.tc.ackable_list), 100)
        for i in range(0,12):
            service_line = "[1334695172] SERVICE NOTIFICATION: sysalertslist;db1.foo.bar.mozilla.com;MySQL Replication;UNKNOWN;notify-by-sms;**ePN /usr/lib64/nagios/plugins/mozilla/check_mysql_replication: DBI connect(host=10.0.0.0:database=,username,...) failed: Cant connect to MySQL server on 10.0.0.0 (111) at (eval 6) line 30."
            self.tc.process_line(service_line, True)
        message = "ack 110 test message"
        m = re.search('^(?:\s*ack\s*)?(\d+)(?:\s*ack\s*)?[:\s]+([^:]+)\s*$', message)
        target, message = self.tc.ack(self.event, message, m)
        self.assertEqual(target, "#sysadmins")
        self.assertEqual(message, "%s: The Service db1.foo.bar.mozilla.com:MySQL Replication has been ack'd" % (self.my_nick) )
        self.tc.process_line(self.ack_host_line, True)
        message = "status db1.foo.mozilla.com:MySQL replication"
        m = re.search('^status ([^:]+):(.+)$', message)
        target, message = self.tc.status_by_host_name(self.event, message, m)
        self.assertEqual(target, "#sysadmins")
        #self.assertEqual(message[0], "%s: db1.foo.mozilla.com:mysql Replication is \x033OK\x03\x03\x03 - uptime: 18346  threads: 199  questions: 12026601  slow queries: 1  opens: 496  flush tables: 1  open tables: 489  queries per second avg: 655.543" % (self.my_nick) )

    def test_disallowed_ack_list(self):
        self.assertEqual(self.tc.disallowed_ack[0], 'serverops_bugs')

    def test_ack_service_by_index_disallowed(self):
        self.tc.ackable_list = [None]*self.tc.list_size
        self.assertEqual(len(self.tc.ackable_list), 100)
        for i in range(0,12):
            service_line = "[1334695172] SERVICE NOTIFICATION: sysalertslist;db1.foo.bar.mozilla.com;serverops_bugs;CRITICAL;notify-by-sms;some critical bug that I don't want to ack"
            self.tc.process_line(service_line, True)
        message = "ack 110 test message"
        m = re.search('^(?:\s*ack\s*)?(\d+)(?:\s*ack\s*)?[:\s]+([^:]+)\s*$', message)
        target, message = self.tc.ack(self.event, message, m)
        self.assertEqual(target, "#sysadmins")
        self.assertEqual(message, "%s: I'm sorry but you're not allowed to ACK this alert here. Please visit the appropriate nagios webui to ACK it there." % (self.my_nick) )
        self.tc.process_line(self.ack_host_line, True)
        
    def test_ack_host_by_index_after_half_cycle(self):
        self.tc.ackable_list = [None]*self.tc.list_size
        self.assertEqual(len(self.tc.ackable_list), 100)
        for i in range(0,51):
            service_line = "[1318882274] SERVICE NOTIFICATION: sysalertslist;fake-host.mozilla.org;root partition%s;CRITICAL;notify-by-email;DISK CRITICAL - free space: / 5294 MB (5 inode=99):" % i
            self.tc.process_line(service_line, True)
        message = "ack 150 test message"
        m = re.search('^(?:\s*ack\s*)?(\d+)(?:\s*ack\s*)?[:\s]+([^:]+)\s*$', message)
        target, message = self.tc.ack(self.event, message, m)
        self.assertEqual(target, "#sysadmins")
        self.assertEqual(message, "%s: The Service fake-host.mozilla.org:root partition50 has been ack'd" % (self.my_nick) )
        self.assertEqual(self.tc.ackable_list[51], None)

    def test_ack_host_by_index_after_five_cycles(self):
        self.tc.ackable_list = [None]*self.tc.list_size
        self.assertEqual(len(self.tc.ackable_list), 100)
        for i in range(0,501):
            service_line = "[1318882274] SERVICE NOTIFICATION: sysalertslist;fake-host.mozilla.org;root partition%s;CRITICAL;notify-by-email;DISK CRITICAL - free space: / 5294 MB (5 inode=99):" % i
            self.tc.process_line(service_line, True)
        message = "ack 100 test message"
        m = re.search('^(?:\s*ack\s*)?(\d+)(?:\s*ack\s*)?[:\s]+([^:]+)\s*$', message)
        target, message = self.tc.ack(self.event, message, m)
        self.assertEqual(target, "#sysadmins")
        self.assertEqual(message, "%s: The Service fake-host.mozilla.org:root partition500 has been ack'd" % (self.my_nick) )
        self.tc.process_line(self.ack_host_line, True)

    def test_ack_host_by_index_after_five_cycles_with_ack(self):
        self.tc.ackable_list = [None]*self.tc.list_size
        self.assertEqual(len(self.tc.ackable_list), 100)
        for i in range(0,501):
            service_line = "[1318882274] SERVICE NOTIFICATION: sysalertslist;fake-host.mozilla.org;root partition%s;CRITICAL;notify-by-email;DISK CRITICAL - free space: / 5294 MB (5 inode=99):" % i
            self.tc.process_line(service_line, True)
            message = "ack %i test message" % (i % self.tc.list_size)
            m = re.search('^(?:\s*ack\s*)?(\d+)(?:\s*ack\s*)?[:\s]+([^:]+)\s*$', message)
            target, message = self.tc.ack(self.event, message, m)
            self.assertEqual(target, "#sysadmins")
            self.assertEqual(message, "%s: The Service fake-host.mozilla.org:root partition%i has been ack'd" % (self.my_nick, i) )
            self.tc.process_line(self.ack_host_line, True)

    def test_ack_host_by_index_after_five_cycles_with_ack_incorrect_syntax(self):
        self.tc.ackable_list = [None]*self.tc.list_size
        self.assertEqual(len(self.tc.ackable_list), 100)
        for i in range(0,501):
            service_line = "[1318882274] SERVICE NOTIFICATION: sysalertslist;fake-host.mozilla.org;root partition%s;CRITICAL;notify-by-email;DISK CRITICAL - free space: / 5294 MB (5 inode=99):" % i
            self.tc.process_line(service_line, True)
            message = "%i ack test message" % (i % self.tc.list_size)
            m = re.search('^(?:\s*ack\s*)?(\d+)(?:\s*ack\s*)?[:\s]+([^:]+)\s*$', message)
            target, message = self.tc.ack(self.event, message, m)
            self.assertEqual(target, "#sysadmins")
            self.assertEqual(message, "%s: The Service fake-host.mozilla.org:root partition%i has been ack'd" % (self.my_nick, i) )
            self.tc.process_line(self.ack_host_line, True)
    def test_ack_host_by_index_after_hundred_cycles(self):
        self.tc.ackable_list = [None]*self.tc.list_size
        self.assertEqual(len(self.tc.ackable_list), 100)
        for i in range(0,100001):
            service_line = "[1318882274] SERVICE NOTIFICATION: sysalertslist;fake-host.mozilla.org;root partition%s;CRITICAL;notify-by-email;DISK CRITICAL - free space: / 5294 MB (5 inode=99):" % i
            self.tc.process_line(service_line, True)
        message = "ack 100 test message"
        m = re.search('^(?:\s*ack\s*)?(\d+)(?:\s*ack\s*)?[:\s]+([^:]+)\s*$', message)
        target, message = self.tc.ack(self.event, message, m)
        self.assertEqual(target, "#sysadmins")
        self.assertEqual(message, "%s: The Service fake-host.mozilla.org:root partition100000 has been ack'd" % (self.my_nick) )
        self.tc.process_line(self.ack_host_line, True)

    def test_unack_by_index(self):
        cmd = "unack 100"
        m = re.search('^unack (\d+)$', cmd)
        target, message = self.tc.unack(self.event, cmd, m)
        self.assertEqual(target, "#sysadmins")
        self.assertEqual(message, "%s: Sorry, but no alert exists at this index" % (self.my_nick) )

        #Now add an alert to the list and try to unack
        tmp = self.tc.ackable('test-host.fake.mozilla.com', None, 'CRITICAL', 'Test Message')
        self.assertEqual(self.tc.get_ack_number(), 100)
        target, message = self.tc.unack(self.event, cmd, m)
        self.assertEqual(target, "#sysadmins")
        self.assertEqual(message, "%s: The Host test-host.fake.mozilla.com has been ack'd" % (self.my_nick) )
    def test_process_line(self):
        self.tc.process_line(self.service_line, True)
        self.assertEqual(self.tc.get_ack_number(), 100)
        self.tc.process_line(self.host_line, True)
        self.tc.process_line(self.service_line, True)
        self.assertEqual(self.tc.get_ack_number(), 102)

    def test_process_line_with_unknown_contacts(self):
        self.tc.process_line(self.service_line, True)
        self.assertEqual(self.tc.get_ack_number(), 100)
        self.tc.process_line(self.host_line, True)
        self.tc.process_line(self.service_line, True)
        self.assertEqual(self.tc.get_ack_number(), 102)
        service_line = "[1318882274] SERVICE NOTIFICATION: unknowncontacthere;fake-host.mozilla.org;root partition;CRITICAL;notify-by-email;DISK CRITICAL - free space: / 5294 MB (5 inode=99):"
        self.tc.process_line(service_line, True)
        self.assertEqual(self.tc.get_ack_number(), 102)
        self.tc.process_line(self.service_line, True)
        self.assertEqual(self.tc.get_ack_number(), 103)

    def test_page_by_index(self):
        self.tc.process_line(self.service_line, True)
        self.assertEqual(self.tc.get_ack_number(), 100)
        cmd = "page 100 %s" % (self.event.source)
        m = re.search('^page\s+(\d+)\s+(\w+)\s*$', cmd)
        target, message = self.tc.page_with_alert_number(self.event, cmd, m)
        self.assertEqual(target, "#sysadmins")
        self.assertEqual(message, "%s: %s has been paged" % (self.my_nick, self.event.source) )

    def test_page_by_bad_index(self):
        self.tc.process_line(self.service_line, True)
        self.assertEqual(self.tc.get_ack_number(), 100)
        cmd = "page 101 %s" % (self.event.source)
        m = re.search('^page\s+(\d+)\s+(\w+)\s*$', cmd)
        target, message = self.tc.page_with_alert_number(self.event, cmd, m)
        self.assertEqual(target, "#sysadmins")
        self.assertEqual(message, "%s: Sorry, but no alert exists at this index" % (self.my_nick) )

    def test_get_channel_group(self):
        self.assertEqual(self.tc.get_channel_group('sysalertslist'), '#sysadmins')

    """
        This test is no longer valid, we did away with a default contact channel
    """
    """def test_get_channel_group_not_found(self):
        self.assertEqual(self.tc.get_channel_group('thisshouldnevermatchblahblah'), '#default')
    """

    def test_get_page_plugin(self):
        plugins = self.tc.return_plugins()
        self.assertEqual('^(?:\s*ack\s*)?(\d+)(?:\s*ack\s*)?[:\s]+([^:]+)\s*$', plugins[0]['regex'])