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