Package cherrypy :: Package test :: Module logtest
[hide private]
[frames] | no frames]

Source Code for Module cherrypy.test.logtest

  1  """logtest, a unittest.TestCase helper for testing log output.""" 
  2   
  3  import sys 
  4  import time 
  5   
  6   
  7  try: 
  8      # On Windows, msvcrt.getch reads a single char without output. 
  9      import msvcrt 
10 - def getchar():
11 return msvcrt.getch()
12 except ImportError: 13 # Unix getchr 14 import tty, termios
15 - def getchar():
16 fd = sys.stdin.fileno() 17 old_settings = termios.tcgetattr(fd) 18 try: 19 tty.setraw(sys.stdin.fileno()) 20 ch = sys.stdin.read(1) 21 finally: 22 termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) 23 return ch
24 25
26 -class LogCase(object):
27 """unittest.TestCase mixin for testing log messages. 28 29 logfile: a filename for the desired log. Yes, I know modes are evil, 30 but it makes the test functions so much cleaner to set this once. 31 32 lastmarker: the last marker in the log. This can be used to search for 33 messages since the last marker. 34 35 markerPrefix: a string with which to prefix log markers. This should be 36 unique enough from normal log output to use for marker identification. 37 """ 38 39 logfile = None 40 lastmarker = None 41 markerPrefix = "test suite marker: " 42
43 - def _handleLogError(self, msg, data, marker, pattern):
44 print 45 print " ERROR:", msg 46 47 if not self.interactive: 48 raise self.failureException(msg) 49 50 p = " Show: [L]og [M]arker [P]attern; [I]gnore, [R]aise, or sys.e[X]it >> " 51 print p, 52 while True: 53 i = getchar().upper() 54 if i not in "MPLIRX": 55 continue 56 print i.upper() # Also prints new line 57 if i == "L": 58 for x, line in enumerate(data): 59 if (x + 1) % self.console_height == 0: 60 # The \r and comma should make the next line overwrite 61 print "<-- More -->\r", 62 m = getchar().lower() 63 # Erase our "More" prompt 64 print " \r", 65 if m == "q": 66 break 67 print line.rstrip() 68 elif i == "M": 69 print repr(marker or self.lastmarker) 70 elif i == "P": 71 print repr(pattern) 72 elif i == "I": 73 # return without raising the normal exception 74 return 75 elif i == "R": 76 raise self.failureException(msg) 77 elif i == "X": 78 self.exit() 79 print p,
80
81 - def exit(self):
82 sys.exit()
83
84 - def emptyLog(self):
85 """Overwrite self.logfile with 0 bytes.""" 86 open(self.logfile, 'wb').write("")
87
88 - def markLog(self, key=None):
89 """Insert a marker line into the log and set self.lastmarker.""" 90 if key is None: 91 key = str(time.time()) 92 self.lastmarker = key 93 94 open(self.logfile, 'ab+').write("%s%s\n" % (self.markerPrefix, key))
95
96 - def _read_marked_region(self, marker=None):
97 """Return lines from self.logfile in the marked region. 98 99 If marker is None, self.lastmarker is used. If the log hasn't 100 been marked (using self.markLog), the entire log will be returned. 101 """ 102 ## # Give the logger time to finish writing? 103 ## time.sleep(0.5) 104 105 logfile = self.logfile 106 marker = marker or self.lastmarker 107 if marker is None: 108 return open(logfile, 'rb').readlines() 109 110 data = [] 111 in_region = False 112 for line in open(logfile, 'rb'): 113 if in_region: 114 if (line.startswith(self.markerPrefix) and not marker in line): 115 break 116 else: 117 data.append(line) 118 elif marker in line: 119 in_region = True 120 return data
121
122 - def assertInLog(self, line, marker=None):
123 """Fail if the given (partial) line is not in the log. 124 125 The log will be searched from the given marker to the next marker. 126 If marker is None, self.lastmarker is used. If the log hasn't 127 been marked (using self.markLog), the entire log will be searched. 128 """ 129 data = self._read_marked_region(marker) 130 for logline in data: 131 if line in logline: 132 return 133 msg = "%r not found in log" % line 134 self._handleLogError(msg, data, marker, line)
135
136 - def assertNotInLog(self, line, marker=None):
137 """Fail if the given (partial) line is in the log. 138 139 The log will be searched from the given marker to the next marker. 140 If marker is None, self.lastmarker is used. If the log hasn't 141 been marked (using self.markLog), the entire log will be searched. 142 """ 143 data = self._read_marked_region(marker) 144 for logline in data: 145 if line in logline: 146 msg = "%r found in log" % line 147 self._handleLogError(msg, data, marker, line)
148
149 - def assertLog(self, sliceargs, lines, marker=None):
150 """Fail if log.readlines()[sliceargs] is not contained in 'lines'. 151 152 The log will be searched from the given marker to the next marker. 153 If marker is None, self.lastmarker is used. If the log hasn't 154 been marked (using self.markLog), the entire log will be searched. 155 """ 156 data = self._read_marked_region(marker) 157 if isinstance(sliceargs, int): 158 # Single arg. Use __getitem__ and allow lines to be str or list. 159 if isinstance(lines, (tuple, list)): 160 lines = lines[0] 161 if lines not in data[sliceargs]: 162 msg = "%r not found on log line %r" % (lines, sliceargs) 163 self._handleLogError(msg, [data[sliceargs]], marker, lines) 164 else: 165 # Multiple args. Use __getslice__ and require lines to be list. 166 if isinstance(lines, tuple): 167 lines = list(lines) 168 elif isinstance(lines, basestring): 169 raise TypeError("The 'lines' arg must be a list when " 170 "'sliceargs' is a tuple.") 171 172 start, stop = sliceargs 173 for line, logline in zip(lines, data[start:stop]): 174 if line not in logline: 175 msg = "%r not found in log" % line 176 self._handleLogError(msg, data[start:stop], marker, line)
177