"""Tests for apache_error_log_metrics."""

import os
import re
import subprocess
import tempfile
import unittest

import common

import apache_error_log_metrics


SCRIPT_PATH = os.path.abspath(
    os.path.join(os.path.dirname(__file__),
                 'apache_error_log_metrics.py'))


class ApacheErrorTest(unittest.TestCase):
    """Unittest for the apache error log regexp."""

    def testNonMatchingLine(self):
        """Test for log lines which don't match the expected format.."""
        lines = [
          '[] [] [] blank components',
          '[] [:error] [] no "pid" section',
          '[] [:error] [pid 1234] no timestamp',
          '[hello world] [:] [pid 1234] no log level',
          '[hello] [:error] [pid 42]     too far indented.'
        ]
        for line in lines:
          self.assertEqual(
              None, apache_error_log_metrics.ERROR_LOG_MATCHER.match(line))

    def testMatchingLines(self):
        """Test for lines that are expected to match the format."""
        match = apache_error_log_metrics.ERROR_LOG_MATCHER.match(
            "[foo] [:bar] [pid 123] WARNING")
        self.assertEqual('bar', match.group('log_level'))
        self.assertEqual(None, match.group('mod_wsgi'))

        match = apache_error_log_metrics.ERROR_LOG_MATCHER.match(
            "[foo] [:bar] [pid 123] mod_wsgi (pid=123)")
        self.assertEqual('bar', match.group('log_level'))
        self.assertEqual('od_wsgi', match.group('mod_wsgi'))

    def testExampleLog(self):
        """Try on some example lines from a real apache error log."""
        with open(os.path.join(os.path.dirname(__file__),
                               'apache_error_log_example.txt')) as fh:
          example_log = fh.readlines()
        matcher_output = [apache_error_log_metrics.ERROR_LOG_MATCHER.match(line)
                          for line in example_log]
        matched = filter(bool, matcher_output)
        self.assertEqual(5, len(matched))

        self.assertEqual('error', matched[0].group('log_level'))
        self.assertEqual(None, matched[0].group('mod_wsgi'))

        self.assertEqual('warn', matched[1].group('log_level'))
        self.assertEqual('od_wsgi', matched[1].group('mod_wsgi'))

        self.assertEqual('error', matched[2].group('log_level'))
        self.assertEqual(None, matched[2].group('mod_wsgi'))

        self.assertEqual('error', matched[3].group('log_level'))
        self.assertEqual(None, matched[3].group('mod_wsgi'))

        self.assertEqual('error', matched[4].group('log_level'))
        self.assertEqual(None, matched[4].group('mod_wsgi'))

    def testApacheErrorLogScriptWithNonMatchingLine(self):
        """Try shelling out the the script with --debug-file.

        Sending it a non-matching line should result in no output from
        ERROR_LOG_METRIC.
        """
        with tempfile.NamedTemporaryFile() as temp_file:
            p = subprocess.Popen([SCRIPT_PATH,
                                  '--debug-metrics-file', temp_file.name],
                                 stdin=subprocess.PIPE, stdout=subprocess.PIPE)
            p.communicate('an-example-log-line')

            with open(temp_file.name) as fh:
                contents = fh.read()

            # We have to use re.search here with a word border character ('\b')
            # because the ERROR_LOG_LINE_METRIC contains ERROR_LOG_METRIC as a
            # substring.
            self.assertTrue(re.search(
                apache_error_log_metrics.ERROR_LOG_LINE_METRIC[1:] + r'\b',
                contents))
            self.assertFalse(re.search(
                apache_error_log_metrics.ERROR_LOG_METRIC[1:] + r'\b',
                contents))

    def testApachErrorLogScriptWithMatchingLine(self):
        """Try shelling out the the script with --debug-file.

        Sending it a line which matches the first-line regex should result in
        output from ERROR_LOG_METRIC.
        """
        with tempfile.NamedTemporaryFile() as temp_file:
            p = subprocess.Popen([SCRIPT_PATH,
                                  '--debug-metrics-file', temp_file.name],
                                 stdin=subprocess.PIPE, stdout=subprocess.PIPE)
            p.communicate('[foo] [:bar] [pid 123] WARNING')

            with open(temp_file.name) as fh:
                contents = fh.read()

            self.assertTrue(re.search(
                apache_error_log_metrics.ERROR_LOG_LINE_METRIC[1:] + r'\b',
                contents))
            self.assertTrue(re.search(
                apache_error_log_metrics.ERROR_LOG_METRIC[1:] + r'\b',
                contents))


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