From e0ae19c7a911d742a7b82f90bac0fa86757eaeae Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Fri, 15 Oct 2010 17:37:26 +0900 Subject: prevent leakage of FLAGS changes across tests --- nova/flags.py | 6 +++++ nova/test.py | 56 +++++++++++++++++++++----------------------- nova/tests/flags_unittest.py | 12 ++++++++++ 3 files changed, 45 insertions(+), 29 deletions(-) diff --git a/nova/flags.py b/nova/flags.py index ab80e83fb..3b473488f 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -90,6 +90,12 @@ class FlagValues(gflags.FlagValues): self.ClearDirty() return args + def Reset(self): + gflags.FlagValues.Reset(self) + self.__dict__['__dirty'] = [] + self.__dict__['__was_already_parsed'] = False + self.__dict__['__stored_argv'] = [] + def SetDirty(self, name): """Mark a flag as dirty so that accessing it will case a reparse.""" self.__dict__['__dirty'].append(name) diff --git a/nova/test.py b/nova/test.py index b9ea36e1d..dab3dcf41 100644 --- a/nova/test.py +++ b/nova/test.py @@ -22,9 +22,9 @@ Allows overriding of flags for use of fakes, and some black magic for inline callbacks. """ +import datetime import sys import time -import datetime import mox import stubout @@ -80,30 +80,33 @@ class TrialTestCase(unittest.TestCase): self.flag_overrides = {} self.injected = [] self._monkeyPatchAttach() + self._original_flags = FLAGS.FlagValuesDict() def tearDown(self): # pylint: disable-msg=C0103 """Runs after each test method to finalize/tear down test environment""" - self.reset_flags() - self.mox.UnsetStubs() - self.stubs.UnsetAll() - self.stubs.SmartUnsetAll() - self.mox.VerifyAll() - # NOTE(vish): Clean up any ips associated during the test. - ctxt = context.get_admin_context() - db.fixed_ip_disassociate_all_by_timeout(ctxt, FLAGS.host, self.start) - db.network_disassociate_all(ctxt) - rpc.Consumer.attach_to_twisted = self.originalAttach - for x in self.injected: - try: - x.stop() - except AssertionError: - pass - - if FLAGS.fake_rabbit: - fakerabbit.reset_all() - db.security_group_destroy_all(ctxt) - - super(TrialTestCase, self).tearDown() + try: + self.mox.UnsetStubs() + self.stubs.UnsetAll() + self.stubs.SmartUnsetAll() + self.mox.VerifyAll() + # NOTE(vish): Clean up any ips associated during the test. + ctxt = context.get_admin_context() + db.fixed_ip_disassociate_all_by_timeout(ctxt, FLAGS.host, self.start) + db.network_disassociate_all(ctxt) + rpc.Consumer.attach_to_twisted = self.originalAttach + for x in self.injected: + try: + x.stop() + except AssertionError: + pass + + if FLAGS.fake_rabbit: + fakerabbit.reset_all() + + db.security_group_destroy_all(ctxt) + super(TrialTestCase, self).tearDown() + finally: + self.reset_flags() def flags(self, **kw): """Override flag variables for a test""" @@ -117,7 +120,8 @@ class TrialTestCase(unittest.TestCase): def reset_flags(self): """Resets all flag variables for the test. Runs after each test""" - for k, v in self.flag_overrides.iteritems(): + FLAGS.Reset() + for k, v in self._original_flags.iteritems(): setattr(FLAGS, k, v) def run(self, result=None): @@ -171,12 +175,6 @@ class BaseTestCase(TrialTestCase): self._done_waiting = False self._timed_out = False - def tearDown(self):# pylint: disable-msg=C0103 - """Runs after each test method to finalize/tear down test environment""" - super(BaseTestCase, self).tearDown() - if FLAGS.fake_rabbit: - fakerabbit.reset_all() - def _wait_for_test(self, timeout=60): """ Push the ioloop along to wait for our test to complete. """ self._waiting = self.ioloop.add_timeout(time.time() + timeout, diff --git a/nova/tests/flags_unittest.py b/nova/tests/flags_unittest.py index d49d5dc43..714170e5e 100644 --- a/nova/tests/flags_unittest.py +++ b/nova/tests/flags_unittest.py @@ -20,6 +20,8 @@ from nova import exception from nova import flags from nova import test +FLAGS = flags.FLAGS +flags.DEFINE_string('flags_unittest', 'foo', 'for testing purposes only') class FlagsTestCase(test.TrialTestCase): def setUp(self): @@ -85,3 +87,13 @@ class FlagsTestCase(test.TrialTestCase): self.assert_('runtime_answer' in self.global_FLAGS) self.assertEqual(self.global_FLAGS.runtime_answer, 60) + + def test_flag_leak_left(self): + self.assertEqual(FLAGS.flags_unittest, 'foo') + FLAGS.flags_unittest = 'bar' + self.assertEqual(FLAGS.flags_unittest, 'bar') + + def test_flag_leak_right(self): + self.assertEqual(FLAGS.flags_unittest, 'foo') + FLAGS.flags_unittest = 'bar' + self.assertEqual(FLAGS.flags_unittest, 'bar') -- cgit From 38a4e415ef7e903e3c63bd584df8e4fee0163512 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Fri, 15 Oct 2010 17:54:38 +0900 Subject: trivial style change --- nova/test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/test.py b/nova/test.py index dab3dcf41..8e89eb43e 100644 --- a/nova/test.py +++ b/nova/test.py @@ -79,7 +79,7 @@ class TrialTestCase(unittest.TestCase): self.stubs = stubout.StubOutForTesting() self.flag_overrides = {} self.injected = [] - self._monkeyPatchAttach() + self._monkey_patch_attach() self._original_flags = FLAGS.FlagValuesDict() def tearDown(self): # pylint: disable-msg=C0103 @@ -147,7 +147,7 @@ class TrialTestCase(unittest.TestCase): _wrapped.func_name = func.func_name return _wrapped - def _monkeyPatchAttach(self): + def _monkey_patch_attach(self): self.originalAttach = rpc.Consumer.attach_to_twisted def _wrapped(innerSelf): rv = self.originalAttach(innerSelf) -- cgit From 8b2d1143f53bb029941a770e2611bb58a064c492 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Fri, 15 Oct 2010 19:27:39 +0900 Subject: make --help work for twistd-based services --- nova/tests/twistd_unittest.py | 53 +++++++++++++++++++++++++++++++++++++++++++ nova/twistd.py | 6 +++++ run_tests.py | 1 + 3 files changed, 60 insertions(+) create mode 100644 nova/tests/twistd_unittest.py diff --git a/nova/tests/twistd_unittest.py b/nova/tests/twistd_unittest.py new file mode 100644 index 000000000..75007b9c8 --- /dev/null +++ b/nova/tests/twistd_unittest.py @@ -0,0 +1,53 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import StringIO +import sys + +from nova import twistd +from nova import exception +from nova import flags +from nova import test + + +FLAGS = flags.FLAGS + + +class TwistdTestCase(test.TrialTestCase): + def setUp(self): + super(TwistdTestCase, self).setUp() + self.Options = twistd.WrapTwistedOptions(twistd.TwistdServerOptions) + sys.stdout = StringIO.StringIO() + + def tearDown(self): + super(TwistdTestCase, self).tearDown() + sys.stdout = sys.__stdout__ + + def test_basic(self): + options = self.Options() + argv = options.parseOptions() + + def test_logfile(self): + options = self.Options() + argv = options.parseOptions(['--logfile=foo']) + self.assertEqual(FLAGS.logfile, 'foo') + + def test_help(self): + options = self.Options() + self.assertRaises(SystemExit, options.parseOptions, ['--help']) + self.assert_('pidfile' in sys.stdout.getvalue()) diff --git a/nova/twistd.py b/nova/twistd.py index 9511c231c..df75b603e 100644 --- a/nova/twistd.py +++ b/nova/twistd.py @@ -51,6 +51,8 @@ class TwistdServerOptions(ServerOptions): class FlagParser(object): + # this is a required attribute for gflags + syntactic_help = '' def __init__(self, parser): self.parser = parser @@ -81,6 +83,8 @@ def WrapTwistedOptions(wrapped): reflect.accumulateClassList(self.__class__, 'optFlags', twistd_flags) for flag in twistd_flags: key = flag[0].replace('-', '_') + if hasattr(FLAGS, key): + continue flags.DEFINE_boolean(key, None, str(flag[-1])) def _absorbParameters(self): @@ -88,6 +92,8 @@ def WrapTwistedOptions(wrapped): reflect.accumulateClassList(self.__class__, 'optParameters', twistd_params) for param in twistd_params: key = param[0].replace('-', '_') + if hasattr(FLAGS, key): + continue if len(param) > 4: flags.DEFINE(FlagParser(param[4]), key, param[2], str(param[3]), diff --git a/run_tests.py b/run_tests.py index 0b27ec6cf..225dcac17 100644 --- a/run_tests.py +++ b/run_tests.py @@ -62,6 +62,7 @@ from nova.tests.quota_unittest import * from nova.tests.rpc_unittest import * from nova.tests.scheduler_unittest import * from nova.tests.service_unittest import * +from nova.tests.twistd_unittest import * from nova.tests.validator_unittest import * from nova.tests.virt_unittest import * from nova.tests.volume_unittest import * -- cgit