From 106eb47eff0551c73b2e90385b9c3a910fec8633 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Sun, 20 Feb 2011 23:16:10 -0800 Subject: fixes for various logging errors and issues --- run_tests.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'run_tests.py') diff --git a/run_tests.py b/run_tests.py index 24786e8ad..bf12c62c6 100644 --- a/run_tests.py +++ b/run_tests.py @@ -26,8 +26,6 @@ from nose import config from nose import result from nose import core -from nova import log as logging - class NovaTestResult(result.TextTestResult): def __init__(self, *args, **kw): @@ -60,7 +58,8 @@ class NovaTestRunner(core.TextTestRunner): if __name__ == '__main__': - logging.basicConfig() + if os.path.exists("nova.sqlite"): + os.unlink("nova.sqlite") c = config.Config(stream=sys.stdout, env=os.environ, verbosity=3, -- cgit From c7d83e26f7d6388857b4db4538602395b688aa7a Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 21 Feb 2011 11:42:46 -0800 Subject: use tests.sqlite so it doesn't conflict with running db --- run_tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'run_tests.py') diff --git a/run_tests.py b/run_tests.py index bf12c62c6..274dc4a97 100644 --- a/run_tests.py +++ b/run_tests.py @@ -58,8 +58,8 @@ class NovaTestRunner(core.TextTestRunner): if __name__ == '__main__': - if os.path.exists("nova.sqlite"): - os.unlink("nova.sqlite") + if os.path.exists("tests.sqlite"): + os.unlink("tests.sqlite") c = config.Config(stream=sys.stdout, env=os.environ, verbosity=3, -- cgit From 29644fe5a9cf47ae33af31b848c0edc4567f3c09 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 21 Feb 2011 13:46:41 -0800 Subject: switch to explicit call to logging.setup() --- run_tests.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'run_tests.py') diff --git a/run_tests.py b/run_tests.py index 274dc4a97..82345433a 100644 --- a/run_tests.py +++ b/run_tests.py @@ -26,6 +26,7 @@ from nose import config from nose import result from nose import core +from nova import log as logging class NovaTestResult(result.TextTestResult): def __init__(self, *args, **kw): @@ -60,6 +61,7 @@ class NovaTestRunner(core.TextTestRunner): if __name__ == '__main__': if os.path.exists("tests.sqlite"): os.unlink("tests.sqlite") + logging.setup() c = config.Config(stream=sys.stdout, env=os.environ, verbosity=3, -- cgit From 90007cd9085909a1e1ac59732a0b371dd79c2557 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 21 Feb 2011 15:55:50 -0800 Subject: pretty colors for logs and a few optimizations --- run_tests.py | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 200 insertions(+), 2 deletions(-) (limited to 'run_tests.py') diff --git a/run_tests.py b/run_tests.py index 82345433a..43508394f 100644 --- a/run_tests.py +++ b/run_tests.py @@ -17,6 +17,29 @@ # See the License for the specific language governing permissions and # limitations under the License. +# Colorizer Code is borrowed from Twisted: +# Copyright (c) 2001-2010 Twisted Matrix Laboratories. +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + import gettext import os import unittest @@ -28,14 +51,186 @@ from nose import core from nova import log as logging +class _AnsiColorizer(object): + """ + A colorizer is an object that loosely wraps around a stream, allowing + callers to write text to the stream in a particular color. + + Colorizer classes must implement C{supported()} and C{write(text, color)}. + """ + _colors = dict(black=30, red=31, green=32, yellow=33, + blue=34, magenta=35, cyan=36, white=37) + + def __init__(self, stream): + self.stream = stream + + def supported(cls, stream=sys.stdout): + """ + A class method that returns True if the current platform supports + coloring terminal output using this method. Returns False otherwise. + """ + if not stream.isatty(): + return False # auto color only on TTYs + try: + import curses + except ImportError: + return False + else: + try: + try: + return curses.tigetnum("colors") > 2 + except curses.error: + curses.setupterm(fd=stream.fileno()) + return curses.tigetnum("colors") > 2 + except: + raise + # guess false in case of error + return False + supported = classmethod(supported) + + def write(self, text, color): + """ + Write the given text to the stream in the given color. + + @param text: Text to be written to the stream. + + @param color: A string label for a color. e.g. 'red', 'white'. + """ + color = self._colors[color] + self.stream.write('\x1b[%s;1m%s\x1b[0m' % (color, text)) + + +class _Win32Colorizer(object): + """ + See _AnsiColorizer docstring. + """ + def __init__(self, stream): + from win32console import GetStdHandle, STD_ERROR_HANDLE, \ + FOREGROUND_RED, FOREGROUND_BLUE, FOREGROUND_GREEN, \ + FOREGROUND_INTENSITY + red, green, blue, bold = (FOREGROUND_RED, FOREGROUND_GREEN, + FOREGROUND_BLUE, FOREGROUND_INTENSITY) + self.stream = stream + self.screenBuffer = GetStdHandle(STD_ERROR_HANDLE) + self._colors = { + 'normal': red | green | blue, + 'red': red | bold, + 'green': green | bold, + 'blue': blue | bold, + 'yellow': red | green | bold, + 'magenta': red | blue | bold, + 'cyan': green | blue | bold, + 'white': red | green | blue | bold + } + + def supported(cls, stream=sys.stdout): + try: + import win32console + screenBuffer = win32console.GetStdHandle( + win32console.STD_ERROR_HANDLE) + except ImportError: + return False + import pywintypes + try: + screenBuffer.SetConsoleTextAttribute( + win32console.FOREGROUND_RED | + win32console.FOREGROUND_GREEN | + win32console.FOREGROUND_BLUE) + except pywintypes.error: + return False + else: + return True + supported = classmethod(supported) + + def write(self, text, color): + color = self._colors[color] + self.screenBuffer.SetConsoleTextAttribute(color) + self.stream.write(text) + self.screenBuffer.SetConsoleTextAttribute(self._colors['normal']) + + +class _NullColorizer(object): + """ + See _AnsiColorizer docstring. + """ + def __init__(self, stream): + self.stream = stream + + def supported(cls, stream=sys.stdout): + return True + supported = classmethod(supported) + + def write(self, text, color): + self.stream.write(text) + class NovaTestResult(result.TextTestResult): def __init__(self, *args, **kw): result.TextTestResult.__init__(self, *args, **kw) self._last_case = None + self.colorizer = None + for colorizer in [_Win32Colorizer, _AnsiColorizer, _NullColorizer]: + # NOTE(vish): nose does funky stuff with stdout, so use stderr + # to setup the colorizer + if colorizer.supported(sys.stderr): + self.colorizer = colorizer(self.stream) + break def getDescription(self, test): return str(test) + def addSuccess(self, test): + if self.showAll: + self.colorizer.write("OK", 'green') + self.stream.writeln() + elif self.dots: + self.stream.write('.') + self.stream.flush() + + def addFailure(self, test): + if self.showAll: + self.colorizer.write("FAIL", 'red') + self.stream.writeln() + elif self.dots: + self.stream.write('F') + self.stream.flush() + + def addError(self, test, err): + """Overrides normal addError to add support for + errorClasses. If the exception is a registered class, the + error will be added to the list for that class, not errors. + """ + stream = getattr(self, 'stream', None) + ec, ev, tb = err + try: + exc_info = self._exc_info_to_string(err, test) + except TypeError: + # 2.3 compat + exc_info = self._exc_info_to_string(err) + for cls, (storage, label, isfail) in self.errorClasses.items(): + if result.isclass(ec) and issubclass(ec, cls): + if isfail: + test.passed = False + storage.append((test, exc_info)) + # Might get patched into a streamless result + if stream is not None: + if self.showAll: + message = [label] + detail = result._exception_detail(err[1]) + if detail: + message.append(detail) + stream.writeln(": ".join(message)) + elif self.dots: + stream.write(label[:1]) + return + self.errors.append((test, exc_info)) + test.passed = False + if stream is not None: + if self.showAll: + self.colorizer.write("ERROR", 'red') + self.stream.writeln() + elif self.dots: + stream.write('E') + def startTest(self, test): unittest.TestResult.startTest(self, test) current_case = test.test.__class__.__name__ @@ -59,12 +254,15 @@ class NovaTestRunner(core.TextTestRunner): if __name__ == '__main__': - if os.path.exists("tests.sqlite"): - os.unlink("tests.sqlite") logging.setup() + testdir = os.path.abspath(os.path.join("nova","tests")) + testdb = os.path.join(testdir, "tests.sqlite") + if os.path.exists(testdb): + os.unlink(testdb) c = config.Config(stream=sys.stdout, env=os.environ, verbosity=3, + workingDir=testdir, plugins=core.DefaultPluginManager()) runner = NovaTestRunner(stream=c.stream, -- cgit From 71f7119910f16cb99c10f43a07ccb1e7c0ca473f Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 21 Feb 2011 16:05:28 -0800 Subject: remove changes to test db --- run_tests.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'run_tests.py') diff --git a/run_tests.py b/run_tests.py index 82345433a..cb957da42 100644 --- a/run_tests.py +++ b/run_tests.py @@ -59,8 +59,6 @@ class NovaTestRunner(core.TextTestRunner): if __name__ == '__main__': - if os.path.exists("tests.sqlite"): - os.unlink("tests.sqlite") logging.setup() c = config.Config(stream=sys.stdout, env=os.environ, -- cgit From 11c57867ec18bd61dcc6bde0dc4b459318d54e70 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 21 Feb 2011 16:19:48 -0800 Subject: fixed newline and moved import fake_flags into run_tests where it makes more sense --- run_tests.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'run_tests.py') diff --git a/run_tests.py b/run_tests.py index cb957da42..6d96454b9 100644 --- a/run_tests.py +++ b/run_tests.py @@ -27,6 +27,8 @@ from nose import result from nose import core from nova import log as logging +from nova.tests import fake_flags + class NovaTestResult(result.TextTestResult): def __init__(self, *args, **kw): -- cgit From 60ed7c9c52306d08b1ad3e759e173931b0a495a8 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 23 Feb 2011 00:59:15 -0800 Subject: fix failures --- run_tests.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'run_tests.py') diff --git a/run_tests.py b/run_tests.py index 4084d8d80..01a1cf8bc 100644 --- a/run_tests.py +++ b/run_tests.py @@ -181,6 +181,7 @@ class NovaTestResult(result.TextTestResult): return str(test) def addSuccess(self, test): + unittest.TestResult.addSuccess(self, test) if self.showAll: self.colorizer.write("OK", 'green') self.stream.writeln() @@ -188,7 +189,8 @@ class NovaTestResult(result.TextTestResult): self.stream.write('.') self.stream.flush() - def addFailure(self, test): + def addFailure(self, test, err): + unittest.TestResult.addFailure(self, test, err) if self.showAll: self.colorizer.write("FAIL", 'red') self.stream.writeln() -- cgit From d160455b77d7e180f252f4b412e3f65d7286b51f Mon Sep 17 00:00:00 2001 From: termie Date: Wed, 23 Feb 2011 08:45:27 -0800 Subject: allow users to omit 'nova.tests' with run_tests --- run_tests.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'run_tests.py') diff --git a/run_tests.py b/run_tests.py index 6d96454b9..47e3ee317 100644 --- a/run_tests.py +++ b/run_tests.py @@ -17,6 +17,23 @@ # See the License for the specific language governing permissions and # limitations under the License. +"""Unittest runner for Nova. + +To run all tests + python run_tests.py + +To run a single test: + python run_tests.py test_compute:ComputeTestCase.test_run_terminate + +To run a single test module: + python run_tests.py test_compute + + or + + python run_tests.py api.test_wsgi + +""" + import gettext import os import unittest @@ -62,6 +79,15 @@ class NovaTestRunner(core.TextTestRunner): if __name__ == '__main__': logging.setup() + # If any argument looks like a test name but doesn't have "nova.tests" in + # front of it, automatically add that so we don't have to type as much + argv = [] + for x in sys.argv: + if x.startswith('test_'): + argv.append('nova.tests.%s' % x) + else: + argv.append(x) + c = config.Config(stream=sys.stdout, env=os.environ, verbosity=3, @@ -70,4 +96,4 @@ if __name__ == '__main__': runner = NovaTestRunner(stream=c.stream, verbosity=c.verbosity, config=c) - sys.exit(not core.run(config=c, testRunner=runner)) + sys.exit(not core.run(config=c, testRunner=runner, argv=argv)) -- cgit From 3c09d486f862de7069b848e8124787cfbf4247f8 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 23 Feb 2011 11:20:52 -0800 Subject: use flags for sqlite db names and fix flags in dhcpbridge --- run_tests.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'run_tests.py') diff --git a/run_tests.py b/run_tests.py index 01a1cf8bc..88c42bd31 100644 --- a/run_tests.py +++ b/run_tests.py @@ -46,13 +46,17 @@ import unittest import sys from nose import config -from nose import result from nose import core +from nose import result +from nova import flags from nova import log as logging from nova.tests import fake_flags +FLAGS = flags.FLAGS + + class _AnsiColorizer(object): """ A colorizer is an object that loosely wraps around a stream, allowing @@ -259,10 +263,11 @@ class NovaTestRunner(core.TextTestRunner): if __name__ == '__main__': logging.setup() - testdir = os.path.abspath(os.path.join("nova","tests")) - testdb = os.path.join(testdir, "tests.sqlite") + testdb = os.path.join(FLAGS.state_path, + FLAGS.sqlite_db) if os.path.exists(testdb): os.unlink(testdb) + testdir = os.path.abspath(os.path.join("nova","tests")) c = config.Config(stream=sys.stdout, env=os.environ, verbosity=3, -- cgit From b09534dac05a3b4c127c633d8c050bb310a27166 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 23 Feb 2011 11:52:10 -0800 Subject: put the redirection back in to run_tests.sh and fix terminal colors by using original stdout --- run_tests.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'run_tests.py') diff --git a/run_tests.py b/run_tests.py index 01a1cf8bc..c78f88831 100644 --- a/run_tests.py +++ b/run_tests.py @@ -82,7 +82,7 @@ class _AnsiColorizer(object): try: return curses.tigetnum("colors") > 2 except curses.error: - curses.setupterm(fd=stream.fileno()) + curses.setupterm() return curses.tigetnum("colors") > 2 except: raise @@ -107,13 +107,13 @@ class _Win32Colorizer(object): See _AnsiColorizer docstring. """ def __init__(self, stream): - from win32console import GetStdHandle, STD_ERROR_HANDLE, \ + from win32console import GetStdHandle, STD_OUT_HANDLE, \ FOREGROUND_RED, FOREGROUND_BLUE, FOREGROUND_GREEN, \ FOREGROUND_INTENSITY red, green, blue, bold = (FOREGROUND_RED, FOREGROUND_GREEN, FOREGROUND_BLUE, FOREGROUND_INTENSITY) self.stream = stream - self.screenBuffer = GetStdHandle(STD_ERROR_HANDLE) + self.screenBuffer = GetStdHandle(STD_OUT_HANDLE) self._colors = { 'normal': red | green | blue, 'red': red | bold, @@ -129,7 +129,7 @@ class _Win32Colorizer(object): try: import win32console screenBuffer = win32console.GetStdHandle( - win32console.STD_ERROR_HANDLE) + win32console.STD_OUT_HANDLE) except ImportError: return False import pywintypes @@ -170,12 +170,14 @@ class NovaTestResult(result.TextTestResult): result.TextTestResult.__init__(self, *args, **kw) self._last_case = None self.colorizer = None + # NOTE(vish): reset stdout for the terminal check + stdout = sys.stdout + sys.stdout = sys.__stdout__ for colorizer in [_Win32Colorizer, _AnsiColorizer, _NullColorizer]: - # NOTE(vish): nose does funky stuff with stdout, so use stderr - # to setup the colorizer - if colorizer.supported(sys.stderr): + if colorizer.supported(): self.colorizer = colorizer(self.stream) break + sys.stdout = stdout def getDescription(self, test): return str(test) -- cgit From 19dc13131b7fe512cb7897a888093b5c9a62e69d Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 23 Feb 2011 12:00:02 -0800 Subject: move the deletion of the db into fixtures --- run_tests.py | 4 ---- 1 file changed, 4 deletions(-) (limited to 'run_tests.py') diff --git a/run_tests.py b/run_tests.py index bb6f0dd1e..5fb5ba32f 100644 --- a/run_tests.py +++ b/run_tests.py @@ -265,10 +265,6 @@ class NovaTestRunner(core.TextTestRunner): if __name__ == '__main__': logging.setup() - testdb = os.path.join(FLAGS.state_path, - FLAGS.sqlite_db) - if os.path.exists(testdb): - os.unlink(testdb) testdir = os.path.abspath(os.path.join("nova","tests")) c = config.Config(stream=sys.stdout, env=os.environ, -- cgit From 5e2f82b1487b8f8e43539d0c71466fbbfed23121 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 23 Feb 2011 15:29:02 -0800 Subject: revert logfile redirection and make colors work by temporarily switching stdout --- run_tests.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'run_tests.py') diff --git a/run_tests.py b/run_tests.py index 877849ab5..2c04a0641 100644 --- a/run_tests.py +++ b/run_tests.py @@ -97,7 +97,7 @@ class _AnsiColorizer(object): try: return curses.tigetnum("colors") > 2 except curses.error: - curses.setupterm(fd=stream.fileno()) + curses.setupterm() return curses.tigetnum("colors") > 2 except: raise @@ -122,13 +122,13 @@ class _Win32Colorizer(object): See _AnsiColorizer docstring. """ def __init__(self, stream): - from win32console import GetStdHandle, STD_ERROR_HANDLE, \ + from win32console import GetStdHandle, STD_OUT_HANDLE, \ FOREGROUND_RED, FOREGROUND_BLUE, FOREGROUND_GREEN, \ FOREGROUND_INTENSITY red, green, blue, bold = (FOREGROUND_RED, FOREGROUND_GREEN, FOREGROUND_BLUE, FOREGROUND_INTENSITY) self.stream = stream - self.screenBuffer = GetStdHandle(STD_ERROR_HANDLE) + self.screenBuffer = GetStdHandle(STD_OUT_HANDLE) self._colors = { 'normal': red | green | blue, 'red': red | bold, @@ -144,7 +144,7 @@ class _Win32Colorizer(object): try: import win32console screenBuffer = win32console.GetStdHandle( - win32console.STD_ERROR_HANDLE) + win32console.STD_OUT_HANDLE) except ImportError: return False import pywintypes @@ -185,12 +185,14 @@ class NovaTestResult(result.TextTestResult): result.TextTestResult.__init__(self, *args, **kw) self._last_case = None self.colorizer = None + # NOTE(vish): reset stdout for the terminal check + stdout = sys.stdout + sys.stdout = sys.__stdout__ for colorizer in [_Win32Colorizer, _AnsiColorizer, _NullColorizer]: - # NOTE(vish): nose does funky stuff with stdout, so use stderr - # to setup the colorizer - if colorizer.supported(sys.stderr): + if colorizer.supported(): self.colorizer = colorizer(self.stream) break + sys.stdout = stdout def getDescription(self, test): return str(test) -- cgit From c27c19ea316b343f1623a7c1bf21c53cd426603b Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 23 Feb 2011 15:35:30 -0800 Subject: fix pep8 --- run_tests.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'run_tests.py') diff --git a/run_tests.py b/run_tests.py index 2c04a0641..eef0120bc 100644 --- a/run_tests.py +++ b/run_tests.py @@ -87,7 +87,7 @@ class _AnsiColorizer(object): coloring terminal output using this method. Returns False otherwise. """ if not stream.isatty(): - return False # auto color only on TTYs + return False # auto color only on TTYs try: import curses except ImportError: @@ -180,6 +180,7 @@ class _NullColorizer(object): def write(self, text, color): self.stream.write(text) + class NovaTestResult(result.TextTestResult): def __init__(self, *args, **kw): result.TextTestResult.__init__(self, *args, **kw) @@ -276,7 +277,7 @@ class NovaTestRunner(core.TextTestRunner): if __name__ == '__main__': logging.setup() - testdir = os.path.abspath(os.path.join("nova","tests")) + testdir = os.path.abspath(os.path.join("nova", "tests")) testdb = os.path.join(testdir, "tests.sqlite") if os.path.exists(testdb): os.unlink(testdb) -- cgit From 78eddce564cccf0d9be19b303cbc122966f5fa71 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 23 Feb 2011 15:42:59 -0800 Subject: added comments about where code came from --- run_tests.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'run_tests.py') diff --git a/run_tests.py b/run_tests.py index eef0120bc..8025548e5 100644 --- a/run_tests.py +++ b/run_tests.py @@ -198,6 +198,7 @@ class NovaTestResult(result.TextTestResult): def getDescription(self, test): return str(test) + # NOTE(vish): copied from unittest with edit to add color def addSuccess(self, test): unittest.TestResult.addSuccess(self, test) if self.showAll: @@ -207,6 +208,7 @@ class NovaTestResult(result.TextTestResult): self.stream.write('.') self.stream.flush() + # NOTE(vish): copied from unittest with edit to add color def addFailure(self, test, err): unittest.TestResult.addFailure(self, test, err) if self.showAll: @@ -216,6 +218,7 @@ class NovaTestResult(result.TextTestResult): self.stream.write('F') self.stream.flush() + # NOTE(vish): copied from nose with edit to add color def addError(self, test, err): """Overrides normal addError to add support for errorClasses. If the exception is a registered class, the -- cgit