diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/unit/rpc/test_common.py | 76 | ||||
-rw-r--r-- | tests/unit/rpc/test_kombu.py | 14 | ||||
-rw-r--r-- | tests/unit/test_lockutils.py | 2 | ||||
-rw-r--r-- | tests/unit/test_rootwrap.py | 202 | ||||
-rw-r--r-- | tests/unit/test_timeutils.py | 55 | ||||
-rw-r--r-- | tests/unit/test_version.py | 27 |
6 files changed, 347 insertions, 29 deletions
diff --git a/tests/unit/rpc/test_common.py b/tests/unit/rpc/test_common.py index 6f8b7ff..fd59929 100644 --- a/tests/unit/rpc/test_common.py +++ b/tests/unit/rpc/test_common.py @@ -236,3 +236,79 @@ class RpcCommonTestCase(test_utils.BaseTestCase): self.assertRaises(rpc_common.ClientException, naughty) self.assertRaises(ValueError, really_naughty) + + def test_serialize_msg_v1(self): + self.stubs.Set(rpc_common, '_SEND_RPC_ENVELOPE', False) + msg = {'foo': 'bar'} + self.assertEqual(msg, rpc_common.serialize_msg(msg)) + + def test_serialize_msg_v2(self): + self.stubs.Set(rpc_common, '_SEND_RPC_ENVELOPE', True) + msg = {'foo': 'bar'} + s_msg = {'oslo.version': rpc_common._RPC_ENVELOPE_VERSION, + 'oslo.message': jsonutils.dumps(msg)} + serialized = rpc_common.serialize_msg(msg) + + self.assertEqual(s_msg, rpc_common.serialize_msg(msg)) + + self.assertEqual(msg, rpc_common.deserialize_msg(serialized)) + + def test_deserialize_msg_no_envelope(self): + self.assertEqual(1, rpc_common.deserialize_msg(1)) + self.assertEqual([], rpc_common.deserialize_msg([])) + self.assertEqual({}, rpc_common.deserialize_msg({})) + self.assertEqual('foo', rpc_common.deserialize_msg('foo')) + + def test_deserialize_msg_bad_version(self): + s_msg = {'oslo.version': '8675309.0', + 'oslo.message': 'whatever'} + + self.assertRaises(rpc_common.UnsupportedRpcEnvelopeVersion, + rpc_common.deserialize_msg, s_msg) + + def test_safe_log_sanitizes_globals(self): + def logger_method(msg, data): + self.assertEquals('<SANITIZED>', data['_context_auth_token']) + self.assertEquals('<SANITIZED>', data['auth_token']) + + data = {'_context_auth_token': 'banana', + 'auth_token': 'cheese'} + rpc_common._safe_log(logger_method, 'foo', data) + + def test_safe_log_sanitizes_set_admin_password(self): + def logger_method(msg, data): + self.assertEquals('<SANITIZED>', data['args']['new_pass']) + + data = {'_context_auth_token': 'banana', + 'auth_token': 'cheese', + 'method': 'set_admin_password', + 'args': {'new_pass': 'gerkin'}} + rpc_common._safe_log(logger_method, 'foo', data) + + def test_safe_log_sanitizes_run_instance(self): + def logger_method(msg, data): + self.assertEquals('<SANITIZED>', data['args']['admin_password']) + + data = {'_context_auth_token': 'banana', + 'auth_token': 'cheese', + 'method': 'run_instance', + 'args': {'admin_password': 'gerkin'}} + rpc_common._safe_log(logger_method, 'foo', data) + + def test_safe_log_sanitizes_cells_route_message(self): + def logger_method(msg, data): + vals = data['args']['message']['args']['method_info'] + self.assertEquals('<SANITIZED>', vals['method_kwargs']['password']) + + meth_info = {'method_args': ['aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee'], + 'method': 'set_admin_password', + 'method_kwargs': {'password': 'this_password_is_visible'}} + data = {'method': 'route_message', + 'args': {'routing_path': 'a.fake.path', + 'direction': 'down', + 'message': {'args': {'is_broadcast': False, + 'service_name': 'compute', + 'method_info': meth_info}, + 'method': 'run_service_api_method'}, + 'dest_cell_name': 'cell!0001'}} + rpc_common._safe_log(logger_method, 'foo', data) diff --git a/tests/unit/rpc/test_kombu.py b/tests/unit/rpc/test_kombu.py index 5da05de..921415d 100644 --- a/tests/unit/rpc/test_kombu.py +++ b/tests/unit/rpc/test_kombu.py @@ -118,7 +118,7 @@ class RpcKombuTestCase(common.BaseRpcAMQPTestCase): self.received_message = message conn.declare_topic_consumer('a_topic', _callback) - conn.topic_send('a_topic', message) + conn.topic_send('a_topic', rpc_common.serialize_msg(message)) conn.consume(limit=1) conn.close() @@ -138,7 +138,7 @@ class RpcKombuTestCase(common.BaseRpcAMQPTestCase): conn.declare_topic_consumer('a_topic', _callback, exchange_name="foorbar") - conn.topic_send('a_topic', message) + conn.topic_send('a_topic', rpc_common.serialize_msg(message)) conn.consume(limit=1) conn.close() @@ -162,7 +162,7 @@ class RpcKombuTestCase(common.BaseRpcAMQPTestCase): conn.declare_topic_consumer('a_topic', _callback1, queue_name='queue1') conn.declare_topic_consumer('a_topic', _callback2, queue_name='queue2') - conn.topic_send('a_topic', message) + conn.topic_send('a_topic', rpc_common.serialize_msg(message)) conn.consume(limit=2) conn.close() @@ -192,7 +192,7 @@ class RpcKombuTestCase(common.BaseRpcAMQPTestCase): exchange_name="abc") conn.declare_topic_consumer('a_topic', _callback2, queue_name='queue2', exchange_name="abc") - conn.topic_send('a_topic', message) + conn.topic_send('a_topic', rpc_common.serialize_msg(message)) conn.consume(limit=2) conn.close() @@ -222,7 +222,7 @@ class RpcKombuTestCase(common.BaseRpcAMQPTestCase): exchange_name="abc") conn.declare_topic_consumer('a_topic', _callback2, queue_name='queue2', exchange_name="def") - conn.topic_send('a_topic', message) + conn.topic_send('a_topic', rpc_common.serialize_msg(message)) conn.consume(limit=2) conn.close() @@ -241,7 +241,7 @@ class RpcKombuTestCase(common.BaseRpcAMQPTestCase): self.received_message = message conn.declare_direct_consumer('a_direct', _callback) - conn.direct_send('a_direct', message) + conn.direct_send('a_direct', rpc_common.serialize_msg(message)) conn.consume(limit=1) conn.close() @@ -438,7 +438,7 @@ class RpcKombuTestCase(common.BaseRpcAMQPTestCase): self.received_message = message conn.declare_direct_consumer('a_direct', _callback) - conn.direct_send('a_direct', message) + conn.direct_send('a_direct', rpc_common.serialize_msg(message)) info = _raise_exc_stub(self.stubs, 1, conn.connection, 'drain_events', 'foo timeout foo') diff --git a/tests/unit/test_lockutils.py b/tests/unit/test_lockutils.py index 5f50217..d6fbd8b 100644 --- a/tests/unit/test_lockutils.py +++ b/tests/unit/test_lockutils.py @@ -27,6 +27,7 @@ from eventlet import greenthread from eventlet import greenpool from openstack.common import lockutils +from openstack.common import testutils from tests import utils as test_utils @@ -128,6 +129,7 @@ class LockTestCase(test_utils.BaseTestCase): if os.path.exists(tempdir): shutil.rmtree(tempdir) + @testutils.skip_test("Regularly fails, see bug #1095957") def test_synchronized_externally(self): """We can lock across multiple processes""" tempdir = tempfile.mkdtemp() diff --git a/tests/unit/test_rootwrap.py b/tests/unit/test_rootwrap.py new file mode 100644 index 0000000..2391005 --- /dev/null +++ b/tests/unit/test_rootwrap.py @@ -0,0 +1,202 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 OpenStack LLC +# +# 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 ConfigParser +import logging +import logging.handlers +import os +import stubout +import subprocess +import unittest + +from openstack.common.rootwrap import filters +from openstack.common.rootwrap import wrapper + + +class RootwrapTestCase(unittest.TestCase): + + def setUp(self): + super(RootwrapTestCase, self).setUp() + self.stubs = stubout.StubOutForTesting() + self.filters = [ + filters.RegExpFilter("/bin/ls", "root", 'ls', '/[a-z]+'), + filters.CommandFilter("/usr/bin/foo_bar_not_exist", "root"), + filters.RegExpFilter("/bin/cat", "root", 'cat', '/[a-z]+'), + filters.CommandFilter("/nonexistent/cat", "root"), + filters.CommandFilter("/bin/cat", "root") # Keep this one last + ] + + def test_RegExpFilter_match(self): + usercmd = ["ls", "/root"] + filtermatch = wrapper.match_filter(self.filters, usercmd) + self.assertFalse(filtermatch is None) + self.assertEqual(filtermatch.get_command(usercmd), + ["/bin/ls", "/root"]) + + def test_RegExpFilter_reject(self): + usercmd = ["ls", "root"] + self.assertRaises(wrapper.NoFilterMatched, + wrapper.match_filter, self.filters, usercmd) + + def test_missing_command(self): + valid_but_missing = ["foo_bar_not_exist"] + invalid = ["foo_bar_not_exist_and_not_matched"] + self.assertRaises(wrapper.FilterMatchNotExecutable, + wrapper.match_filter, + self.filters, valid_but_missing) + self.assertRaises(wrapper.NoFilterMatched, + wrapper.match_filter, self.filters, invalid) + + def _test_DnsmasqFilter(self, filter_class, config_file_arg): + usercmd = ['env', config_file_arg + '=A', 'NETWORK_ID=foobar', + 'dnsmasq', 'foo'] + f = filter_class("/usr/bin/dnsmasq", "root") + self.assertTrue(f.match(usercmd)) + self.assertEqual(f.get_command(usercmd), ['/usr/bin/dnsmasq', 'foo']) + env = f.get_environment(usercmd) + self.assertEqual(env.get(config_file_arg), 'A') + self.assertEqual(env.get('NETWORK_ID'), 'foobar') + + def test_DnsmasqFilter(self): + self._test_DnsmasqFilter(filters.DnsmasqFilter, 'CONFIG_FILE') + + def test_DeprecatedDnsmasqFilter(self): + self._test_DnsmasqFilter(filters.DeprecatedDnsmasqFilter, 'FLAGFILE') + + def test_KillFilter(self): + if not os.path.exists("/proc/%d" % os.getpid()): + self.skipTest("Test requires /proc filesystem (procfs)") + p = subprocess.Popen(["cat"], stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + try: + f = filters.KillFilter("root", "/bin/cat", "-9", "-HUP") + f2 = filters.KillFilter("root", "/usr/bin/cat", "-9", "-HUP") + usercmd = ['kill', '-ALRM', p.pid] + # Incorrect signal should fail + self.assertFalse(f.match(usercmd) or f2.match(usercmd)) + usercmd = ['kill', p.pid] + # Providing no signal should fail + self.assertFalse(f.match(usercmd) or f2.match(usercmd)) + # Providing matching signal should be allowed + usercmd = ['kill', '-9', p.pid] + self.assertTrue(f.match(usercmd) or f2.match(usercmd)) + + f = filters.KillFilter("root", "/bin/cat") + f2 = filters.KillFilter("root", "/usr/bin/cat") + usercmd = ['kill', os.getpid()] + # Our own PID does not match /bin/sleep, so it should fail + self.assertFalse(f.match(usercmd) or f2.match(usercmd)) + usercmd = ['kill', 999999] + # Nonexistent PID should fail + self.assertFalse(f.match(usercmd) or f2.match(usercmd)) + usercmd = ['kill', p.pid] + # Providing no signal should work + self.assertTrue(f.match(usercmd) or f2.match(usercmd)) + finally: + # Terminate the "cat" process and wait for it to finish + p.terminate() + p.wait() + + def test_KillFilter_no_raise(self): + """Makes sure ValueError from bug 926412 is gone""" + f = filters.KillFilter("root", "") + # Providing anything other than kill should be False + usercmd = ['notkill', 999999] + self.assertFalse(f.match(usercmd)) + # Providing something that is not a pid should be False + usercmd = ['kill', 'notapid'] + self.assertFalse(f.match(usercmd)) + + def test_KillFilter_deleted_exe(self): + """Makes sure deleted exe's are killed correctly""" + # See bug #967931. + def fake_readlink(blah): + return '/bin/commandddddd (deleted)' + + f = filters.KillFilter("root", "/bin/commandddddd") + usercmd = ['kill', 1234] + # Providing no signal should work + self.stubs.Set(os, 'readlink', fake_readlink) + self.assertTrue(f.match(usercmd)) + + def test_ReadFileFilter(self): + goodfn = '/good/file.name' + f = filters.ReadFileFilter(goodfn) + usercmd = ['cat', '/bad/file'] + self.assertFalse(f.match(['cat', '/bad/file'])) + usercmd = ['cat', goodfn] + self.assertEqual(f.get_command(usercmd), ['/bin/cat', goodfn]) + self.assertTrue(f.match(usercmd)) + + def test_exec_dirs_search(self): + # This test supposes you have /bin/cat or /usr/bin/cat locally + f = filters.CommandFilter("cat", "root") + usercmd = ['cat', '/f'] + self.assertTrue(f.match(usercmd)) + self.assertTrue(f.get_command(usercmd, + exec_dirs=['/bin', '/usr/bin']) + in (['/bin/cat', '/f'], ['/usr/bin/cat', '/f'])) + + def test_skips(self): + # Check that all filters are skipped and that the last matches + usercmd = ["cat", "/"] + filtermatch = wrapper.match_filter(self.filters, usercmd) + self.assertTrue(filtermatch is self.filters[-1]) + + def test_RootwrapConfig(self): + raw = ConfigParser.RawConfigParser() + + # Empty config should raise ConfigParser.Error + self.assertRaises(ConfigParser.Error, wrapper.RootwrapConfig, raw) + + # Check default values + raw.set('DEFAULT', 'filters_path', '/a,/b') + config = wrapper.RootwrapConfig(raw) + self.assertEqual(config.filters_path, ['/a', '/b']) + self.assertEqual(config.exec_dirs, os.environ["PATH"].split(':')) + self.assertFalse(config.use_syslog) + self.assertEqual(config.syslog_log_facility, + logging.handlers.SysLogHandler.LOG_SYSLOG) + self.assertEqual(config.syslog_log_level, logging.ERROR) + + # Check general values + raw.set('DEFAULT', 'exec_dirs', '/a,/x') + config = wrapper.RootwrapConfig(raw) + self.assertEqual(config.exec_dirs, ['/a', '/x']) + + raw.set('DEFAULT', 'use_syslog', 'oui') + self.assertRaises(ValueError, wrapper.RootwrapConfig, raw) + raw.set('DEFAULT', 'use_syslog', 'true') + config = wrapper.RootwrapConfig(raw) + self.assertTrue(config.use_syslog) + + raw.set('DEFAULT', 'syslog_log_facility', 'moo') + self.assertRaises(ValueError, wrapper.RootwrapConfig, raw) + raw.set('DEFAULT', 'syslog_log_facility', 'local0') + config = wrapper.RootwrapConfig(raw) + self.assertEqual(config.syslog_log_facility, + logging.handlers.SysLogHandler.LOG_LOCAL0) + raw.set('DEFAULT', 'syslog_log_facility', 'LOG_AUTH') + config = wrapper.RootwrapConfig(raw) + self.assertEqual(config.syslog_log_facility, + logging.handlers.SysLogHandler.LOG_AUTH) + + raw.set('DEFAULT', 'syslog_log_level', 'bar') + self.assertRaises(ValueError, wrapper.RootwrapConfig, raw) + raw.set('DEFAULT', 'syslog_log_level', 'INFO') + config = wrapper.RootwrapConfig(raw) + self.assertEqual(config.syslog_log_level, logging.INFO) diff --git a/tests/unit/test_timeutils.py b/tests/unit/test_timeutils.py index 8236032..1407f29 100644 --- a/tests/unit/test_timeutils.py +++ b/tests/unit/test_timeutils.py @@ -27,14 +27,10 @@ from openstack.common import timeutils class TimeUtilsTest(unittest.TestCase): def setUp(self): - utc_timezone = iso8601.iso8601.UTC self.skynet_self_aware_time_str = '1997-08-29T06:14:00Z' - self.skynet_self_aware_time = datetime.datetime(1997, 8, 29, 6, 14, 0, - tzinfo=utc_timezone) - self.one_minute_before = datetime.datetime(1997, 8, 29, 6, 13, 0, - tzinfo=iso8601.iso8601.UTC) - self.one_minute_after = datetime.datetime(1997, 8, 29, 6, 15, 0, - tzinfo=iso8601.iso8601.UTC) + self.skynet_self_aware_time = datetime.datetime(1997, 8, 29, 6, 14, 0) + self.one_minute_before = datetime.datetime(1997, 8, 29, 6, 13, 0) + self.one_minute_after = datetime.datetime(1997, 8, 29, 6, 15, 0) self.skynet_self_aware_time_perfect_str = '1997-08-29T06:14:00.000000' self.skynet_self_aware_time_perfect = datetime.datetime(1997, 8, 29, 6, 14, 0) @@ -50,7 +46,9 @@ class TimeUtilsTest(unittest.TestCase): def test_parse_isotime(self): expect = timeutils.parse_isotime(self.skynet_self_aware_time_str) - self.assertEqual(self.skynet_self_aware_time, expect) + skynet_self_aware_time_utc = self.skynet_self_aware_time.replace( + tzinfo=iso8601.iso8601.UTC) + self.assertEqual(skynet_self_aware_time_utc, expect) def test_strtime(self): expect = timeutils.strtime(self.skynet_self_aware_time_perfect) @@ -67,31 +65,52 @@ class TimeUtilsTest(unittest.TestCase): t = timeutils.parse_strtime(s) self.assertEqual(orig_t, t) - def test_is_older_than(self): + def _test_is_older_than(self, fn): + strptime = datetime.datetime.strptime with mock.patch('datetime.datetime') as datetime_mock: datetime_mock.utcnow.return_value = self.skynet_self_aware_time - expect_true = timeutils.is_older_than(self.one_minute_before, 59) + datetime_mock.strptime = strptime + expect_true = timeutils.is_older_than(fn(self.one_minute_before), + 59) self.assertTrue(expect_true) - expect_false = timeutils.is_older_than(self.one_minute_before, 60) + expect_false = timeutils.is_older_than(fn(self.one_minute_before), + 60) self.assertFalse(expect_false) - expect_false = timeutils.is_older_than(self.one_minute_before, 61) + expect_false = timeutils.is_older_than(fn(self.one_minute_before), + 61) self.assertFalse(expect_false) - def test_is_newer_than(self): + def test_is_older_than_datetime(self): + self._test_is_older_than(lambda x: x) + + def test_is_older_than_str(self): + self._test_is_older_than(timeutils.strtime) + + def _test_is_newer_than(self, fn): + strptime = datetime.datetime.strptime with mock.patch('datetime.datetime') as datetime_mock: datetime_mock.utcnow.return_value = self.skynet_self_aware_time - expect_true = timeutils.is_newer_than(self.one_minute_after, 59) + datetime_mock.strptime = strptime + expect_true = timeutils.is_newer_than(fn(self.one_minute_after), + 59) self.assertTrue(expect_true) - expect_false = timeutils.is_newer_than(self.one_minute_after, 60) + expect_false = timeutils.is_newer_than(fn(self.one_minute_after), + 60) self.assertFalse(expect_false) - expect_false = timeutils.is_newer_than(self.one_minute_after, 61) + expect_false = timeutils.is_newer_than(fn(self.one_minute_after), + 61) self.assertFalse(expect_false) + def test_is_newer_than_datetime(self): + self._test_is_newer_than(lambda x: x) + + def test_is_newer_than_str(self): + self._test_is_newer_than(timeutils.strtime) + def test_utcnow_ts(self): skynet_self_aware_timestamp = 872835240 dt = datetime.datetime.utcfromtimestamp(skynet_self_aware_timestamp) - expect = dt.replace(tzinfo=iso8601.iso8601.UTC) - self.assertEqual(self.skynet_self_aware_time, expect) + self.assertEqual(self.skynet_self_aware_time, dt) with mock.patch('datetime.datetime') as datetime_mock: datetime_mock.utcnow.return_value = self.skynet_self_aware_time ts = timeutils.utcnow_ts() diff --git a/tests/unit/test_version.py b/tests/unit/test_version.py index 8e60f51..c67ccde 100644 --- a/tests/unit/test_version.py +++ b/tests/unit/test_version.py @@ -42,23 +42,23 @@ class DeferredVersionTestCase(BaseTestCase): super(DeferredVersionTestCase, self).setUp() self.conf = ConfigOpts() - def test_deferred_version(self): + def test_cached_version(self): class MyVersionInfo(version.VersionInfo): def _generate_version(self): return "5.5.5.5" deferred_string = MyVersionInfo("openstack").\ - deferred_version_string() + cached_version_string() self.conf([], project="project", prog="prog", version=deferred_string) self.assertEquals("5.5.5.5", str(self.conf.version)) - def test_print_deferred_version(self): + def test_print_cached_version(self): class MyVersionInfo(version.VersionInfo): def _generate_version(self): return "5.5.5.5" deferred_string = MyVersionInfo("openstack")\ - .deferred_version_string() + .cached_version_string() self.stubs.Set(sys, 'stderr', StringIO.StringIO()) self.assertRaises(SystemExit, self.conf, ['--version'], @@ -66,3 +66,22 @@ class DeferredVersionTestCase(BaseTestCase): prog="prog", version=deferred_string) self.assertEquals("5.5.5.5", sys.stderr.getvalue().strip()) + + def test_print_cached_version_with_long_string(self): + my_version = "11111222223333344444555556666677777888889999900000" + + class MyVersionInfo(version.VersionInfo): + def _generate_version(self): + return my_version + + deferred_string = MyVersionInfo("openstack")\ + .cached_version_string() + + for i in range(50): + self.stubs.Set(sys, 'stderr', StringIO.StringIO()) + self.assertRaises(SystemExit, + self.conf, ['--version'], + project="project", + prog="prog", + version=deferred_string) + self.assertEquals(my_version, sys.stderr.getvalue().strip()) |