1 """logtest, a unittest.TestCase helper for testing log output."""
2
3 import sys
4 import time
5
6 import cherrypy
7 from cherrypy._cpcompat import basestring, ntob, unicodestr
8
9
10 try:
11
12 import msvcrt
13
16 except ImportError:
17
18 import tty
19 import termios
20
22 fd = sys.stdin.fileno()
23 old_settings = termios.tcgetattr(fd)
24 try:
25 tty.setraw(sys.stdin.fileno())
26 ch = sys.stdin.read(1)
27 finally:
28 termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
29 return ch
30
31
33
34 """unittest.TestCase mixin for testing log messages.
35
36 logfile: a filename for the desired log. Yes, I know modes are evil,
37 but it makes the test functions so much cleaner to set this once.
38
39 lastmarker: the last marker in the log. This can be used to search for
40 messages since the last marker.
41
42 markerPrefix: a string with which to prefix log markers. This should be
43 unique enough from normal log output to use for marker identification.
44 """
45
46 logfile = None
47 lastmarker = None
48 markerPrefix = ntob("test suite marker: ")
49
51 print("")
52 print(" ERROR: %s" % msg)
53
54 if not self.interactive:
55 raise self.failureException(msg)
56
57 p = (" Show: "
58 "[L]og [M]arker [P]attern; "
59 "[I]gnore, [R]aise, or sys.e[X]it >> ")
60 sys.stdout.write(p + ' ')
61
62 sys.stdout.flush()
63 while True:
64 i = getchar().upper()
65 if i not in "MPLIRX":
66 continue
67 print(i.upper())
68 if i == "L":
69 for x, line in enumerate(data):
70 if (x + 1) % self.console_height == 0:
71
72 sys.stdout.write("<-- More -->\r ")
73 m = getchar().lower()
74
75 sys.stdout.write(" \r ")
76 if m == "q":
77 break
78 print(line.rstrip())
79 elif i == "M":
80 print(repr(marker or self.lastmarker))
81 elif i == "P":
82 print(repr(pattern))
83 elif i == "I":
84
85 return
86 elif i == "R":
87 raise self.failureException(msg)
88 elif i == "X":
89 self.exit()
90 sys.stdout.write(p + ' ')
91
94
96 """Overwrite self.logfile with 0 bytes."""
97 open(self.logfile, 'wb').write("")
98
107
109 """Return lines from self.logfile in the marked region.
110
111 If marker is None, self.lastmarker is used. If the log hasn't
112 been marked (using self.markLog), the entire log will be returned.
113 """
114
115
116
117 logfile = self.logfile
118 marker = marker or self.lastmarker
119 if marker is None:
120 return open(logfile, 'rb').readlines()
121
122 if isinstance(marker, unicodestr):
123 marker = marker.encode('utf-8')
124 data = []
125 in_region = False
126 for line in open(logfile, 'rb'):
127 if in_region:
128 if (line.startswith(self.markerPrefix) and not marker in line):
129 break
130 else:
131 data.append(line)
132 elif marker in line:
133 in_region = True
134 return data
135
137 """Fail if the given (partial) line is not 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 return
147 msg = "%r not found in log" % line
148 self._handleLogError(msg, data, marker, line)
149
151 """Fail if the given (partial) line is in the log.
152
153 The log will be searched from the given marker to the next marker.
154 If marker is None, self.lastmarker is used. If the log hasn't
155 been marked (using self.markLog), the entire log will be searched.
156 """
157 data = self._read_marked_region(marker)
158 for logline in data:
159 if line in logline:
160 msg = "%r found in log" % line
161 self._handleLogError(msg, data, marker, line)
162
163 - def assertLog(self, sliceargs, lines, marker=None):
164 """Fail if log.readlines()[sliceargs] is not contained in 'lines'.
165
166 The log will be searched from the given marker to the next marker.
167 If marker is None, self.lastmarker is used. If the log hasn't
168 been marked (using self.markLog), the entire log will be searched.
169 """
170 data = self._read_marked_region(marker)
171 if isinstance(sliceargs, int):
172
173 if isinstance(lines, (tuple, list)):
174 lines = lines[0]
175 if isinstance(lines, unicodestr):
176 lines = lines.encode('utf-8')
177 if lines not in data[sliceargs]:
178 msg = "%r not found on log line %r" % (lines, sliceargs)
179 self._handleLogError(
180 msg,
181 [data[sliceargs], "--EXTRA CONTEXT--"] + data[
182 sliceargs + 1:sliceargs + 6],
183 marker,
184 lines)
185 else:
186
187 if isinstance(lines, tuple):
188 lines = list(lines)
189 elif isinstance(lines, basestring):
190 raise TypeError("The 'lines' arg must be a list when "
191 "'sliceargs' is a tuple.")
192
193 start, stop = sliceargs
194 for line, logline in zip(lines, data[start:stop]):
195 if isinstance(line, unicodestr):
196 line = line.encode('utf-8')
197 if line not in logline:
198 msg = "%r not found in log" % line
199 self._handleLogError(msg, data[start:stop], marker, line)
200