1"""Tests for apache_error_log_metrics.""" 2 3import os 4import re 5import subprocess 6import tempfile 7import unittest 8 9import common 10 11import apache_error_log_metrics 12 13 14SCRIPT_PATH = os.path.abspath( 15 os.path.join(os.path.dirname(__file__), 16 'apache_error_log_metrics.py')) 17 18 19class ApacheErrorTest(unittest.TestCase): 20 """Unittest for the apache error log regexp.""" 21 22 def testNonMatchingLine(self): 23 """Test for log lines which don't match the expected format..""" 24 lines = [ 25 '[] [] [] blank components', 26 '[] [:error] [] no "pid" section', 27 '[] [:error] [pid 1234] no timestamp', 28 '[hello world] [:] [pid 1234] no log level', 29 '[hello] [:error] [pid 42] too far indented.' 30 ] 31 for line in lines: 32 self.assertEqual( 33 None, apache_error_log_metrics.ERROR_LOG_MATCHER.match(line)) 34 35 def testMatchingLines(self): 36 """Test for lines that are expected to match the format.""" 37 match = apache_error_log_metrics.ERROR_LOG_MATCHER.match( 38 "[foo] [:bar] [pid 123] WARNING") 39 self.assertEqual('bar', match.group('log_level')) 40 self.assertEqual(None, match.group('mod_wsgi')) 41 42 match = apache_error_log_metrics.ERROR_LOG_MATCHER.match( 43 "[foo] [mpm_event:bar] [pid 123] WARNING") 44 self.assertEqual('bar', match.group('log_level')) 45 self.assertEqual(None, match.group('mod_wsgi')) 46 47 match = apache_error_log_metrics.ERROR_LOG_MATCHER.match( 48 "[foo] [:bar] [pid 123] mod_wsgi (pid=123)") 49 self.assertEqual('bar', match.group('log_level')) 50 self.assertEqual('od_wsgi', match.group('mod_wsgi')) 51 52 def testExampleLog(self): 53 """Try on some example lines from a real apache error log.""" 54 with open(os.path.join(os.path.dirname(__file__), 55 'apache_error_log_example.txt')) as fh: 56 example_log = fh.readlines() 57 matcher_output = [apache_error_log_metrics.ERROR_LOG_MATCHER.match(line) 58 for line in example_log] 59 matched = filter(bool, matcher_output) 60 self.assertEqual(5, len(matched)) 61 62 self.assertEqual('error', matched[0].group('log_level')) 63 self.assertEqual(None, matched[0].group('mod_wsgi')) 64 65 self.assertEqual('warn', matched[1].group('log_level')) 66 self.assertEqual('od_wsgi', matched[1].group('mod_wsgi')) 67 68 self.assertEqual('error', matched[2].group('log_level')) 69 self.assertEqual(None, matched[2].group('mod_wsgi')) 70 71 self.assertEqual('error', matched[3].group('log_level')) 72 self.assertEqual(None, matched[3].group('mod_wsgi')) 73 74 self.assertEqual('error', matched[4].group('log_level')) 75 self.assertEqual(None, matched[4].group('mod_wsgi')) 76 77 78 def _ShellOutToScript(self, lines): 79 """Shells out to the script. 80 81 @param lines: Lines to feed to stdin.""" 82 with tempfile.NamedTemporaryFile() as temp_file: 83 p = subprocess.Popen([SCRIPT_PATH, 84 '--debug-metrics-file', temp_file.name], 85 stdin=subprocess.PIPE, stdout=subprocess.PIPE) 86 p.communicate('\n'.join(lines)) 87 88 with open(temp_file.name) as fh: 89 return fh.read() 90 91 92 def testApacheErrorLogScriptWithNonMatchingLine(self): 93 """Try shelling out the the script with --debug-file. 94 95 Sending it a non-matching line should result in no output from 96 ERROR_LOG_METRIC. 97 """ 98 contents = self._ShellOutToScript(['an example log line']) 99 100 # We have to use re.search here with a word border character ('\b') 101 # because the ERROR_LOG_LINE_METRIC contains ERROR_LOG_METRIC as a 102 # substring. 103 self.assertTrue(re.search( 104 apache_error_log_metrics.ERROR_LOG_LINE_METRIC[1:] + r'\b', 105 contents)) 106 self.assertFalse(re.search( 107 apache_error_log_metrics.ERROR_LOG_METRIC[1:] + r'\b', 108 contents)) 109 110 def testApachErrorLogScriptWithMatchingLine(self): 111 """Try shelling out the the script with a matching line. 112 113 Sending it a line which matches the first-line regex should result in 114 output from ERROR_LOG_METRIC. 115 """ 116 contents = self._ShellOutToScript(['[foo] [:bar] [pid 123] WARNING']) 117 118 self.assertTrue(re.search( 119 apache_error_log_metrics.ERROR_LOG_LINE_METRIC[1:] + r'\b', 120 contents)) 121 self.assertTrue(re.search( 122 apache_error_log_metrics.ERROR_LOG_METRIC[1:] + r'\b', 123 contents)) 124 125 def testApachErrorLogScriptWithSpecialLines(self): 126 """Sending lines with specific messages.""" 127 contents = self._ShellOutToScript(['[foo] [:bar] [pid 123] WARNING Segmentation fault']) 128 129 self.assertTrue(re.search( 130 apache_error_log_metrics.SEGFAULT_METRIC[1:] + r'\b', 131 contents)) 132 133 134if __name__ == '__main__': 135 unittest.main() 136