backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / tests / test_lib.py
1 # Copyright (C) 2013,2014,2015 Nippon Telegraph and Telephone Corporation.
2 # Copyright (C) 2013,2014,2015 YAMAMOTO Takashi <yamamoto at valinux co jp>
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #    http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13 # implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 import gettext
18 import os
19 import unittest
20 import six
21 import sys
22 import types
23 import logging
24
25 from nose import result
26 from nose import core
27 from nose import config
28
29
30 class _AnsiColorizer(object):
31     """
32     A colorizer is an object that loosely wraps around a stream, allowing
33     callers to write text to the stream in a particular color.
34
35     Colorizer classes must implement C{supported()} and C{write(text, color)}.
36     """
37     _colors = dict(black=30, red=31, green=32, yellow=33,
38                    blue=34, magenta=35, cyan=36, white=37)
39
40     def __init__(self, stream):
41         self.stream = stream
42
43     def supported(cls, stream=sys.stdout):
44         """
45         A class method that returns True if the current platform supports
46         coloring terminal output using this method. Returns False otherwise.
47         """
48         if not stream.isatty():
49             return False  # auto color only on TTYs
50         try:
51             import curses
52         except ImportError:
53             return False
54         else:
55             try:
56                 try:
57                     return curses.tigetnum("colors") > 2
58                 except curses.error:
59                     curses.setupterm()
60                     return curses.tigetnum("colors") > 2
61             except:
62                 # guess false in case of error
63                 return False
64     supported = classmethod(supported)
65
66     def write(self, text, color):
67         """
68         Write the given text to the stream in the given color.
69
70         @param text: Text to be written to the stream.
71
72         @param color: A string label for a color. e.g. 'red', 'white'.
73         """
74         color = self._colors[color]
75         self.stream.write('\x1b[%s;1m%s\x1b[0m' % (color, text))
76
77
78 class _Win32Colorizer(object):
79     """
80     See _AnsiColorizer docstring.
81     """
82
83     def __init__(self, stream):
84         from win32console import GetStdHandle, STD_OUT_HANDLE
85         from win32console import FOREGROUND_RED, FOREGROUND_BLUE
86         from win32console import FOREGROUND_GREEN, FOREGROUND_INTENSITY
87         red, green, blue, bold = (FOREGROUND_RED, FOREGROUND_GREEN,
88                                   FOREGROUND_BLUE, FOREGROUND_INTENSITY)
89         self.stream = stream
90         self.screenBuffer = GetStdHandle(STD_OUT_HANDLE)
91         self._colors = {
92             'normal': red | green | blue,
93             'red': red | bold,
94             'green': green | bold,
95             'blue': blue | bold,
96             'yellow': red | green | bold,
97             'magenta': red | blue | bold,
98             'cyan': green | blue | bold,
99             'white': red | green | blue | bold}
100
101     def supported(cls, stream=sys.stdout):
102         try:
103             import win32console
104             screenBuffer = win32console.GetStdHandle(
105                 win32console.STD_OUT_HANDLE)
106         except ImportError:
107             return False
108         import pywintypes
109         try:
110             screenBuffer.SetConsoleTextAttribute(
111                 win32console.FOREGROUND_RED |
112                 win32console.FOREGROUND_GREEN |
113                 win32console.FOREGROUND_BLUE)
114         except pywintypes.error:
115             return False
116         else:
117             return True
118     supported = classmethod(supported)
119
120     def write(self, text, color):
121         color = self._colors[color]
122         self.screenBuffer.SetConsoleTextAttribute(color)
123         self.stream.write(text)
124         self.screenBuffer.SetConsoleTextAttribute(self._colors['normal'])
125
126
127 class _NullColorizer(object):
128     """
129     See _AnsiColorizer docstring.
130     """
131
132     def __init__(self, stream):
133         self.stream = stream
134
135     def supported(cls, stream=sys.stdout):
136         return True
137     supported = classmethod(supported)
138
139     def write(self, text, color):
140         self.stream.write(text)
141
142
143 class RyuTestResult(result.TextTestResult):
144     def __init__(self, *args, **kw):
145         result.TextTestResult.__init__(self, *args, **kw)
146         self._last_case = None
147         self.colorizer = None
148         # NOTE(vish, tfukushima): reset stdout for the terminal check
149         stdout = sys.__stdout__
150         sys.stdout = sys.__stdout__
151         for colorizer in [_Win32Colorizer, _AnsiColorizer, _NullColorizer]:
152             if colorizer.supported():
153                 self.colorizer = colorizer(self.stream)
154                 break
155         sys.stdout = stdout
156
157     def getDescription(self, test):
158         return str(test)
159
160     # NOTE(vish, tfukushima): copied from unittest with edit to add color
161     def addSuccess(self, test):
162         unittest.TestResult.addSuccess(self, test)
163         if self.showAll:
164             self.colorizer.write("OK", 'green')
165             self.stream.writeln()
166         elif self.dots:
167             self.stream.write('.')
168             self.stream.flush()
169
170     # NOTE(vish, tfukushima): copied from unittest with edit to add color
171     def addFailure(self, test, err):
172         unittest.TestResult.addFailure(self, test, err)
173         if self.showAll:
174             self.colorizer.write("FAIL", 'red')
175             self.stream.writeln()
176         elif self.dots:
177             self.stream.write('F')
178             self.stream.flush()
179
180     # NOTE(vish, tfukushima): copied from unittest with edit to add color
181     def addError(self, test, err):
182         """Overrides normal addError to add support for errorClasses.
183         If the exception is a registered class, the error will be added
184         to the list for that class, not errors.
185         """
186         stream = getattr(self, 'stream', None)
187         ec, ev, tb = err
188         try:
189             exc_info = self._exc_info_to_string(err, test)
190         except TypeError:
191             # This is for compatibility with Python 2.3.
192             exc_info = self._exc_info_to_string(err)
193         for cls, (storage, label, isfail) in self.errorClasses.items():
194             if result.isclass(ec) and issubclass(ec, cls):
195                 if isfail:
196                     test.passwd = False
197                 storage.append((test, exc_info))
198                 # Might get patched into a streamless result
199                 if stream is not None:
200                     if self.showAll:
201                         message = [label]
202                         detail = result._exception_detail(err[1])
203                         if detail:
204                             message.append(detail)
205                         stream.writeln(": ".join(message))
206                     elif self.dots:
207                         stream.write(label[:1])
208                 return
209         self.errors.append((test, exc_info))
210         test.passed = False
211         if stream is not None:
212             if self.showAll:
213                 self.colorizer.write("ERROR", 'red')
214                 self.stream.writeln()
215             elif self.dots:
216                 stream.write('E')
217
218     def startTest(self, test):
219         unittest.TestResult.startTest(self, test)
220         current_case = test.test.__class__.__name__
221
222         if self.showAll:
223             if current_case != self._last_case:
224                 self.stream.writeln(current_case)
225                 self._last_case = current_case
226             # NOTE(salvatore-orlando):
227             # slightly changed in order to print test case class
228             # together with unit test name
229             self.stream.write(
230                 '    %s' % str(test.test).ljust(60))
231             self.stream.flush()
232
233
234 class RyuTestRunner(core.TextTestRunner):
235     def _makeResult(self):
236         return RyuTestResult(self.stream,
237                              self.descriptions,
238                              self.verbosity,
239                              self.config)
240
241
242 def run_tests(c=None):
243     logger = logging.getLogger()
244     hdlr = logging.StreamHandler()
245     formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
246     hdlr.setFormatter(formatter)
247     logger.addHandler(hdlr)
248     logger.setLevel(logging.DEBUG)
249
250     # NOTE(bgh): I'm not entirely sure why but nose gets confused here when
251     # calling run_tests from a plugin directory run_tests.py (instead of the
252     # main run_tests.py).  It will call run_tests with no arguments and the
253     # testing of run_tests will fail (though the plugin tests will pass).  For
254     # now we just return True to let the run_tests test pass.
255     if not c:
256         return True
257
258     runner = RyuTestRunner(stream=c.stream,
259                            verbosity=c.verbosity,
260                            config=c)
261     return not core.run(config=c, testRunner=runner)
262
263
264 def add_method(cls, method_name, method):
265     """Add the method to the class dynamically, keeping unittest/nose happy."""
266     method.func_name = method_name
267     method.__name__ = method_name
268     if six.PY3:
269         methodtype = types.MethodType(method, cls)
270         if not hasattr(method, "__qualname__"):
271             method.__qualname__ = "%s.%s" % (cls.__qualname__, method_name)
272     else:
273         methodtype = types.MethodType(method, None, cls)
274     setattr(cls, method_name, methodtype)