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] [:bar] [pid 123] mod_wsgi (pid=123)") 44 self.assertEqual('bar', match.group('log_level')) 45 self.assertEqual('od_wsgi', match.group('mod_wsgi')) 46 47 def testExampleLog(self): 48 """Try on some example lines from a real apache error log.""" 49 with open(os.path.join(os.path.dirname(__file__), 50 'apache_error_log_example.txt')) as fh: 51 example_log = fh.readlines() 52 matcher_output = [apache_error_log_metrics.ERROR_LOG_MATCHER.match(line) 53 for line in example_log] 54 matched = filter(bool, matcher_output) 55 self.assertEqual(5, len(matched)) 56 57 self.assertEqual('error', matched[0].group('log_level')) 58 self.assertEqual(None, matched[0].group('mod_wsgi')) 59 60 self.assertEqual('warn', matched[1].group('log_level')) 61 self.assertEqual('od_wsgi', matched[1].group('mod_wsgi')) 62 63 self.assertEqual('error', matched[2].group('log_level')) 64 self.assertEqual(None, matched[2].group('mod_wsgi')) 65 66 self.assertEqual('error', matched[3].group('log_level')) 67 self.assertEqual(None, matched[3].group('mod_wsgi')) 68 69 self.assertEqual('error', matched[4].group('log_level')) 70 self.assertEqual(None, matched[4].group('mod_wsgi')) 71 72 def testApacheErrorLogScriptWithNonMatchingLine(self): 73 """Try shelling out the the script with --debug-file. 74 75 Sending it a non-matching line should result in no output from 76 ERROR_LOG_METRIC. 77 """ 78 with tempfile.NamedTemporaryFile() as temp_file: 79 p = subprocess.Popen([SCRIPT_PATH, 80 '--debug-metrics-file', temp_file.name], 81 stdin=subprocess.PIPE, stdout=subprocess.PIPE) 82 p.communicate('an-example-log-line') 83 84 with open(temp_file.name) as fh: 85 contents = fh.read() 86 87 # We have to use re.search here with a word border character ('\b') 88 # because the ERROR_LOG_LINE_METRIC contains ERROR_LOG_METRIC as a 89 # substring. 90 self.assertTrue(re.search( 91 apache_error_log_metrics.ERROR_LOG_LINE_METRIC[1:] + r'\b', 92 contents)) 93 self.assertFalse(re.search( 94 apache_error_log_metrics.ERROR_LOG_METRIC[1:] + r'\b', 95 contents)) 96 97 def testApachErrorLogScriptWithMatchingLine(self): 98 """Try shelling out the the script with --debug-file. 99 100 Sending it a line which matches the first-line regex should result in 101 output from ERROR_LOG_METRIC. 102 """ 103 with tempfile.NamedTemporaryFile() as temp_file: 104 p = subprocess.Popen([SCRIPT_PATH, 105 '--debug-metrics-file', temp_file.name], 106 stdin=subprocess.PIPE, stdout=subprocess.PIPE) 107 p.communicate('[foo] [:bar] [pid 123] WARNING') 108 109 with open(temp_file.name) as fh: 110 contents = fh.read() 111 112 self.assertTrue(re.search( 113 apache_error_log_metrics.ERROR_LOG_LINE_METRIC[1:] + r'\b', 114 contents)) 115 self.assertTrue(re.search( 116 apache_error_log_metrics.ERROR_LOG_METRIC[1:] + r'\b', 117 contents)) 118 119 120if __name__ == '__main__': 121 unittest.main() 122