diff options
Diffstat (limited to 'tests/unit')
-rw-r--r-- | tests/unit/crypto/__init__.py | 0 | ||||
-rw-r--r-- | tests/unit/crypto/test_utils.py | 186 | ||||
-rw-r--r-- | tests/unit/rpc/test_kombu.py | 36 | ||||
-rw-r--r-- | tests/unit/test_context.py | 4 | ||||
-rw-r--r-- | tests/unit/test_excutils.py | 8 | ||||
-rw-r--r-- | tests/unit/test_log.py | 16 | ||||
-rw-r--r-- | tests/unit/test_notifier.py | 8 | ||||
-rw-r--r-- | tests/unit/test_rootwrap.py | 49 | ||||
-rw-r--r-- | tests/unit/test_service.py | 27 |
9 files changed, 325 insertions, 9 deletions
diff --git a/tests/unit/crypto/__init__.py b/tests/unit/crypto/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/unit/crypto/__init__.py diff --git a/tests/unit/crypto/test_utils.py b/tests/unit/crypto/test_utils.py new file mode 100644 index 0000000..3a39100 --- /dev/null +++ b/tests/unit/crypto/test_utils.py @@ -0,0 +1,186 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 Red Hat, Inc. +# +# 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. +""" +Unit Tests for crypto utils. +""" + +from openstack.common.crypto import utils as cryptoutils +from tests import utils as test_utils + + +class CryptoUtilsTestCase(test_utils.BaseTestCase): + + # Uses Tests from RFC5869 + def _test_HKDF(self, ikm, prk, okm, length, + salt=None, info='', hashtype='SHA256'): + hkdf = cryptoutils.HKDF(hashtype=hashtype) + + tprk = hkdf.extract(ikm, salt=salt) + self.assertEqual(prk, tprk) + + tokm = hkdf.expand(prk, info, length) + self.assertEqual(okm, tokm) + + def test_HKDF_1(self): + ikm = '\x0b' * 22 + salt = ''.join(map(lambda x: chr(x), range(0x00, 0x0d))) + info = ''.join(map(lambda x: chr(x), range(0xf0, 0xfa))) + length = 42 + + prk = ('\x07\x77\x09\x36\x2c\x2e\x32\xdf\x0d\xdc\x3f\x0d\xc4\x7b' + '\xba\x63\x90\xb6\xc7\x3b\xb5\x0f\x9c\x31\x22\xec\x84\x4a' + '\xd7\xc2\xb3\xe5') + + okm = ('\x3c\xb2\x5f\x25\xfa\xac\xd5\x7a\x90\x43\x4f\x64\xd0\x36' + '\x2f\x2a\x2d\x2d\x0a\x90\xcf\x1a\x5a\x4c\x5d\xb0\x2d\x56' + '\xec\xc4\xc5\xbf\x34\x00\x72\x08\xd5\xb8\x87\x18\x58\x65') + + self._test_HKDF(ikm, prk, okm, length, salt, info) + + def test_HKDF_2(self): + ikm = ''.join(map(lambda x: chr(x), range(0x00, 0x50))) + salt = ''.join(map(lambda x: chr(x), range(0x60, 0xb0))) + info = ''.join(map(lambda x: chr(x), range(0xb0, 0x100))) + length = 82 + + prk = ('\x06\xa6\xb8\x8c\x58\x53\x36\x1a\x06\x10\x4c\x9c\xeb\x35' + '\xb4\x5c\xef\x76\x00\x14\x90\x46\x71\x01\x4a\x19\x3f\x40' + '\xc1\x5f\xc2\x44') + + okm = ('\xb1\x1e\x39\x8d\xc8\x03\x27\xa1\xc8\xe7\xf7\x8c\x59\x6a' + '\x49\x34\x4f\x01\x2e\xda\x2d\x4e\xfa\xd8\xa0\x50\xcc\x4c' + '\x19\xaf\xa9\x7c\x59\x04\x5a\x99\xca\xc7\x82\x72\x71\xcb' + '\x41\xc6\x5e\x59\x0e\x09\xda\x32\x75\x60\x0c\x2f\x09\xb8' + '\x36\x77\x93\xa9\xac\xa3\xdb\x71\xcc\x30\xc5\x81\x79\xec' + '\x3e\x87\xc1\x4c\x01\xd5\xc1\xf3\x43\x4f\x1d\x87') + + self._test_HKDF(ikm, prk, okm, length, salt, info) + + def test_HKDF_3(self): + ikm = '\x0b' * 22 + length = 42 + + prk = ('\x19\xef\x24\xa3\x2c\x71\x7b\x16\x7f\x33\xa9\x1d\x6f\x64' + '\x8b\xdf\x96\x59\x67\x76\xaf\xdb\x63\x77\xac\x43\x4c\x1c' + '\x29\x3c\xcb\x04') + + okm = ('\x8d\xa4\xe7\x75\xa5\x63\xc1\x8f\x71\x5f\x80\x2a\x06\x3c' + '\x5a\x31\xb8\xa1\x1f\x5c\x5e\xe1\x87\x9e\xc3\x45\x4e\x5f' + '\x3c\x73\x8d\x2d\x9d\x20\x13\x95\xfa\xa4\xb6\x1a\x96\xc8') + + self._test_HKDF(ikm, prk, okm, length) + + def test_HKDF_4(self): + ikm = '\x0b' * 11 + salt = ''.join(map(lambda x: chr(x), range(0x00, 0x0d))) + info = ''.join(map(lambda x: chr(x), range(0xf0, 0xfa))) + length = 42 + + prk = ('\x9b\x6c\x18\xc4\x32\xa7\xbf\x8f\x0e\x71\xc8\xeb\x88\xf4' + '\xb3\x0b\xaa\x2b\xa2\x43') + + okm = ('\x08\x5a\x01\xea\x1b\x10\xf3\x69\x33\x06\x8b\x56\xef\xa5' + '\xad\x81\xa4\xf1\x4b\x82\x2f\x5b\x09\x15\x68\xa9\xcd\xd4' + '\xf1\x55\xfd\xa2\xc2\x2e\x42\x24\x78\xd3\x05\xf3\xf8\x96') + + self._test_HKDF(ikm, prk, okm, length, salt, info, hashtype='SHA') + + def test_HKDF_5(self): + ikm = ''.join(map(lambda x: chr(x), range(0x00, 0x50))) + salt = ''.join(map(lambda x: chr(x), range(0x60, 0xb0))) + info = ''.join(map(lambda x: chr(x), range(0xb0, 0x100))) + length = 82 + + prk = ('\x8a\xda\xe0\x9a\x2a\x30\x70\x59\x47\x8d\x30\x9b\x26\xc4' + '\x11\x5a\x22\x4c\xfa\xf6') + + okm = ('\x0b\xd7\x70\xa7\x4d\x11\x60\xf7\xc9\xf1\x2c\xd5\x91\x2a' + '\x06\xeb\xff\x6a\xdc\xae\x89\x9d\x92\x19\x1f\xe4\x30\x56' + '\x73\xba\x2f\xfe\x8f\xa3\xf1\xa4\xe5\xad\x79\xf3\xf3\x34' + '\xb3\xb2\x02\xb2\x17\x3c\x48\x6e\xa3\x7c\xe3\xd3\x97\xed' + '\x03\x4c\x7f\x9d\xfe\xb1\x5c\x5e\x92\x73\x36\xd0\x44\x1f' + '\x4c\x43\x00\xe2\xcf\xf0\xd0\x90\x0b\x52\xd3\xb4') + + self._test_HKDF(ikm, prk, okm, length, salt, info, hashtype='SHA') + + def test_HKDF_6(self): + ikm = '\x0b' * 22 + length = 42 + + prk = ('\xda\x8c\x8a\x73\xc7\xfa\x77\x28\x8e\xc6\xf5\xe7\xc2\x97' + '\x78\x6a\xa0\xd3\x2d\x01') + + okm = ('\x0a\xc1\xaf\x70\x02\xb3\xd7\x61\xd1\xe5\x52\x98\xda\x9d' + '\x05\x06\xb9\xae\x52\x05\x72\x20\xa3\x06\xe0\x7b\x6b\x87' + '\xe8\xdf\x21\xd0\xea\x00\x03\x3d\xe0\x39\x84\xd3\x49\x18') + + self._test_HKDF(ikm, prk, okm, length, hashtype='SHA') + + def test_HKDF_7(self): + ikm = '\x0c' * 22 + length = 42 + + prk = ('\x2a\xdc\xca\xda\x18\x77\x9e\x7c\x20\x77\xad\x2e\xb1\x9d' + '\x3f\x3e\x73\x13\x85\xdd') + + okm = ('\x2c\x91\x11\x72\x04\xd7\x45\xf3\x50\x0d\x63\x6a\x62\xf6' + '\x4f\x0a\xb3\xba\xe5\x48\xaa\x53\xd4\x23\xb0\xd1\xf2\x7e' + '\xbb\xa6\xf5\xe5\x67\x3a\x08\x1d\x70\xcc\xe7\xac\xfc\x48') + + self._test_HKDF(ikm, prk, okm, length, hashtype='SHA') + + def test_HKDF_8(self): + ikm = '\x0b' * 22 + prk = ('\x19\xef\x24\xa3\x2c\x71\x7b\x16\x7f\x33\xa9\x1d\x6f\x64' + '\x8b\xdf\x96\x59\x67\x76\xaf\xdb\x63\x77\xac\x43\x4c\x1c' + '\x29\x3c\xcb\x04') + + # Just testing HKDFOutputLengthTooLong is returned + try: + self._test_HKDF(ikm, prk, None, 1000000) + except cryptoutils.HKDFOutputLengthTooLong: + pass + + def test_SymmetricCrypto_encrypt_string(self): + msg = 'Plain Text' + + skc = cryptoutils.SymmetricCrypto() + key = skc.new_key(16) + cipher = skc.encrypt(key, msg) + plain = skc.decrypt(key, cipher) + self.assertEqual(msg, plain) + + def test_SymmetricCrypto_encrypt_blocks(self): + cb = 16 + et = 'AES' + + skc = cryptoutils.SymmetricCrypto(enctype=et) + key = skc.new_key(16) + msg = skc.new_key(cb * 2) + + for i in range(0, cb * 2): + cipher = skc.encrypt(key, msg[0:i], b64encode=False) + plain = skc.decrypt(key, cipher, b64decode=False) + self.assertEqual(msg[0:i], plain) + + def test_SymmetricCrypto_signing(self): + msg = 'Authenticated Message' + signature = 'KWjl6i30RMjc5PjnaccRwTPKTRCWM6sPpmGS2bxm5fQ=' + skey = 'L\xdd0\xf3\xb4\xc6\xe2p\xef\xc7\xbd\xaa\xc9eNC' + + skc = cryptoutils.SymmetricCrypto() + validate = skc.sign(skey, msg) + self.assertEqual(signature, validate) diff --git a/tests/unit/rpc/test_kombu.py b/tests/unit/rpc/test_kombu.py index 470f98a..9838652 100644 --- a/tests/unit/rpc/test_kombu.py +++ b/tests/unit/rpc/test_kombu.py @@ -41,6 +41,8 @@ from tests import utils try: import kombu + import kombu.connection + import kombu.entity from openstack.common.rpc import impl_kombu except ImportError: kombu = None @@ -715,6 +717,32 @@ class RpcKombuTestCase(amqp.BaseRpcAMQPTestCase): "args": {"value": value}}) self.assertEqual(value, result) + def test_reconnect_max_retries(self): + self.config(rabbit_hosts=[ + 'host1:1234', 'host2:5678', '[::1]:2345', + '[2001:0db8:85a3:0042:0000:8a2e:0370:7334]'], + rabbit_max_retries=2, + rabbit_retry_interval=0.1, + rabbit_retry_backoff=0.1) + + info = {'attempt': 0} + + class MyConnection(kombu.connection.BrokerConnection): + def __init__(self, *args, **params): + super(MyConnection, self).__init__(*args, **params) + info['attempt'] += 1 + + def connect(self): + if info['attempt'] < 3: + # the word timeout is important (see impl_kombu.py:486) + raise Exception('connection timeout') + super(kombu.connection.BrokerConnection, self).connect() + + self.stubs.Set(kombu.connection, 'BrokerConnection', MyConnection) + + self.assertRaises(rpc_common.RPCException, self.rpc.Connection, FLAGS) + self.assertEqual(info['attempt'], 2) + class RpcKombuHATestCase(utils.BaseTestCase): def setUp(self): @@ -765,15 +793,13 @@ class RpcKombuHATestCase(utils.BaseTestCase): ] } - import kombu.connection - class MyConnection(kombu.connection.BrokerConnection): def __init__(myself, *args, **params): super(MyConnection, myself).__init__(*args, **params) self.assertEqual(params, info['params_list'][info['attempt'] % len(info['params_list'])]) - info['attempt'] = info['attempt'] + 1 + info['attempt'] += 1 def connect(myself): if info['attempt'] < 5: @@ -790,8 +816,6 @@ class RpcKombuHATestCase(utils.BaseTestCase): def test_queue_not_declared_ha_if_ha_off(self): self.config(rabbit_ha_queues=False) - import kombu.entity - def my_declare(myself): self.assertEqual(None, (myself.queue_arguments or {}).get('x-ha-policy')) @@ -804,8 +828,6 @@ class RpcKombuHATestCase(utils.BaseTestCase): def test_queue_declared_ha_if_ha_on(self): self.config(rabbit_ha_queues=True) - import kombu.entity - def my_declare(myself): self.assertEqual('all', (myself.queue_arguments or {}).get('x-ha-policy')) diff --git a/tests/unit/test_context.py b/tests/unit/test_context.py index 0db7aaa..2f9a3de 100644 --- a/tests/unit/test_context.py +++ b/tests/unit/test_context.py @@ -24,3 +24,7 @@ class ContextTest(utils.BaseTestCase): def test_context(self): ctx = context.RequestContext() self.assertTrue(ctx) + + def test_admin_context_show_deleted_flag_default(self): + ctx = context.get_admin_context() + self.assertFalse(ctx.show_deleted) diff --git a/tests/unit/test_excutils.py b/tests/unit/test_excutils.py index b8f9b96..1386eaa 100644 --- a/tests/unit/test_excutils.py +++ b/tests/unit/test_excutils.py @@ -52,6 +52,14 @@ class SaveAndReraiseTest(utils.BaseTestCase): self.assertEqual(str(e), msg) + def test_save_and_reraise_exception_no_reraise(self): + """Test that suppressing the reraise works.""" + try: + raise Exception('foo') + except Exception: + with excutils.save_and_reraise_exception() as ctxt: + ctxt.reraise = False + class ForeverRetryUncaughtExceptionsTest(utils.BaseTestCase): diff --git a/tests/unit/test_log.py b/tests/unit/test_log.py index a65801b..e58bd7d 100644 --- a/tests/unit/test_log.py +++ b/tests/unit/test_log.py @@ -1,3 +1,19 @@ +# Copyright (c) 2011 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 cStringIO import logging import os diff --git a/tests/unit/test_notifier.py b/tests/unit/test_notifier.py index 6c3b886..891b0ec 100644 --- a/tests/unit/test_notifier.py +++ b/tests/unit/test_notifier.py @@ -13,6 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. +import socket + from oslo.config import cfg from openstack.common import context @@ -308,3 +310,9 @@ class MultiNotifierTestCase(test_utils.BaseTestCase): notifier_api.WARN, dict(a=3)) self.assertEqual(self.notify_count, 1) + + def test_publisher_id(self): + self.assertEqual(notifier_api.publisher_id('foobar'), + 'foobar.' + socket.gethostname()) + self.assertEqual(notifier_api.publisher_id('foobar', 'baz'), + 'foobar.baz') diff --git a/tests/unit/test_rootwrap.py b/tests/unit/test_rootwrap.py index 02789ec..a649660 100644 --- a/tests/unit/test_rootwrap.py +++ b/tests/unit/test_rootwrap.py @@ -40,6 +40,32 @@ class RootwrapTestCase(utils.BaseTestCase): filters.CommandFilter("/bin/cat", "root") # Keep this one last ] + def test_CommandFilter(self): + f = filters.CommandFilter("sleep", 'root', '10') + self.assertFalse(f.match(["sleep2"])) + + # verify that any arguments are accepted + self.assertTrue(f.match(["sleep"])) + self.assertTrue(f.match(["sleep", "anything"])) + self.assertTrue(f.match(["sleep", "10"])) + f = filters.CommandFilter("sleep", 'root') + self.assertTrue(f.match(["sleep", "10"])) + + def test_empty_commandfilter(self): + f = filters.CommandFilter("sleep", "root") + self.assertFalse(f.match([])) + self.assertFalse(f.match(None)) + + def test_empty_regexpfilter(self): + f = filters.RegExpFilter("sleep", "root", "sleep") + self.assertFalse(f.match([])) + self.assertFalse(f.match(None)) + + def test_empty_invalid_regexpfilter(self): + f = filters.RegExpFilter("sleep", "root") + self.assertFalse(f.match(["anything"])) + self.assertFalse(f.match([])) + def test_RegExpFilter_match(self): usercmd = ["ls", "/root"] filtermatch = wrapper.match_filter(self.filters, usercmd) @@ -178,8 +204,9 @@ class RootwrapTestCase(utils.BaseTestCase): # Filter shouldn't be able to find binary in $PATH, so fail with fixtures.EnvironmentVariable("PATH", "/foo:/bar"): self.assertFalse(f.match(usercmd)) - pass - + # ensure that unset $PATH is not causing an exception + with fixtures.EnvironmentVariable("PATH"): + self.assertFalse(f.match(usercmd)) finally: # Terminate the "cat" process and wait for it to finish p.terminate() @@ -194,6 +221,9 @@ class RootwrapTestCase(utils.BaseTestCase): # Providing something that is not a pid should be False usercmd = ['kill', 'notapid'] self.assertFalse(f.match(usercmd)) + # no arguments should also be fine + self.assertFalse(f.match([])) + self.assertFalse(f.match(None)) def test_KillFilter_deleted_exe(self): """Makes sure deleted exe's are killed correctly.""" @@ -288,6 +318,12 @@ class RootwrapTestCase(utils.BaseTestCase): self.assertRaises(wrapper.NoFilterMatched, wrapper.match_filter, filter_list, args) + def test_ReadFileFilter_empty_args(self): + goodfn = '/good/file.name' + f = filters.ReadFileFilter(goodfn) + self.assertFalse(f.match([])) + self.assertFalse(f.match(None)) + def test_exec_dirs_search(self): # This test supposes you have /bin/cat or /usr/bin/cat locally f = filters.CommandFilter("cat", "root") @@ -314,6 +350,11 @@ class RootwrapTestCase(utils.BaseTestCase): config = wrapper.RootwrapConfig(raw) self.assertEqual(config.filters_path, ['/a', '/b']) self.assertEqual(config.exec_dirs, os.environ["PATH"].split(':')) + + with fixtures.EnvironmentVariable("PATH"): + c = wrapper.RootwrapConfig(raw) + self.assertEqual(c.exec_dirs, []) + self.assertFalse(config.use_syslog) self.assertEqual(config.syslog_log_facility, logging.handlers.SysLogHandler.LOG_SYSLOG) @@ -381,6 +422,10 @@ class PathFilterTestCase(utils.BaseTestCase): self.SYMLINK_OUTSIDE_DIR = os.path.join(tmpdir.path, gen_name()) os.symlink(os.path.join('/tmp', 'some_file'), self.SYMLINK_OUTSIDE_DIR) + def test_empty_args(self): + self.assertFalse(self.f.match([])) + self.assertFalse(self.f.match(None)) + def test_argument_pass_constraint(self): f = filters.PathFilter('/bin/chown', 'root', 'pass', 'pass') diff --git a/tests/unit/test_service.py b/tests/unit/test_service.py index 0f93830..20007de 100644 --- a/tests/unit/test_service.py +++ b/tests/unit/test_service.py @@ -31,6 +31,7 @@ import socket import time import traceback +from eventlet import event from oslo.config import cfg from openstack.common import eventlet_backdoor @@ -195,6 +196,20 @@ class ServiceLauncherTest(utils.BaseTestCase): self.assertEqual(os.WEXITSTATUS(status), 0) +class _Service(service.Service): + def __init__(self): + super(_Service, self).__init__() + self.init = event.Event() + self.cleaned_up = False + + def start(self): + self.init.send() + + def stop(self): + self.cleaned_up = True + super(_Service, self).stop() + + class LauncherTest(utils.BaseTestCase): def test_backdoor_port(self): @@ -252,3 +267,15 @@ class LauncherTest(utils.BaseTestCase): svc = service.Service() self.assertRaises(eventlet_backdoor.EventletBackdoorConfigValueError, service.launch, svc) + + def test_graceful_shutdown(self): + # test that services are given a chance to clean up: + svc = _Service() + + launcher = service.launch(svc) + # wait on 'init' so we know the service had time to start: + svc.init.wait() + + launcher.stop() + self.assertTrue(svc.cleaned_up) + self.assertTrue(svc._done.ready()) |