Imported Upstream version 4.8.10
This commit is contained in:
286
ipatests/test_ipapython/test_certdb.py
Normal file
286
ipatests/test_ipapython/test_certdb.py
Normal file
@@ -0,0 +1,286 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
||||
from ipapython.certdb import (
|
||||
NSSDatabase,
|
||||
TRUSTED_PEER_TRUST_FLAGS,
|
||||
nss_supports_dbm,
|
||||
)
|
||||
from ipapython import ipautil
|
||||
from ipaplatform.osinfo import osinfo
|
||||
|
||||
CERTNICK = 'testcert'
|
||||
CERTSAN = 'testcert.certdb.test'
|
||||
|
||||
if osinfo.id == 'fedora':
|
||||
if osinfo.version_number >= (28,):
|
||||
NSS_DEFAULT = 'sql'
|
||||
else:
|
||||
NSS_DEFAULT = 'dbm'
|
||||
else:
|
||||
NSS_DEFAULT = None
|
||||
|
||||
|
||||
def create_selfsigned(nssdb):
|
||||
# create self-signed cert + key
|
||||
noisefile = os.path.join(nssdb.secdir, 'noise')
|
||||
with open(noisefile, 'wb') as f:
|
||||
f.write(os.urandom(64))
|
||||
try:
|
||||
nssdb.run_certutil([
|
||||
'-S', '-x',
|
||||
'-z', noisefile,
|
||||
'-k', 'rsa', '-g', '2048', '-Z', 'SHA256',
|
||||
'-t', 'CTu,Cu,Cu',
|
||||
'-s', 'CN=testcert',
|
||||
'-n', CERTNICK,
|
||||
'-m', '365',
|
||||
'--extSAN', f'dns:{CERTSAN}'
|
||||
])
|
||||
finally:
|
||||
os.unlink(noisefile)
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not nss_supports_dbm(),
|
||||
reason="NSS is built without support of the legacy database(DBM)",
|
||||
)
|
||||
def test_dbm_tmp():
|
||||
with NSSDatabase(dbtype='dbm') as nssdb:
|
||||
assert nssdb.dbtype == 'dbm'
|
||||
|
||||
for filename in nssdb.filenames:
|
||||
assert not os.path.isfile(filename)
|
||||
assert not nssdb.exists()
|
||||
|
||||
nssdb.create_db()
|
||||
for filename in nssdb.filenames:
|
||||
assert os.path.isfile(filename)
|
||||
assert os.path.dirname(filename) == nssdb.secdir
|
||||
assert nssdb.exists()
|
||||
|
||||
assert os.path.basename(nssdb.certdb) == 'cert8.db'
|
||||
assert nssdb.certdb in nssdb.filenames
|
||||
assert os.path.basename(nssdb.keydb) == 'key3.db'
|
||||
assert os.path.basename(nssdb.secmod) == 'secmod.db'
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
nss_supports_dbm(),
|
||||
reason="NSS is built with support of the legacy database(DBM)",
|
||||
)
|
||||
def test_dbm_raise():
|
||||
with pytest.raises(ValueError) as e:
|
||||
NSSDatabase(dbtype="dbm")
|
||||
assert (
|
||||
str(e.value) == "NSS is built without support of the legacy "
|
||||
"database(DBM)"
|
||||
)
|
||||
|
||||
|
||||
def test_sql_tmp():
|
||||
with NSSDatabase(dbtype='sql') as nssdb:
|
||||
assert nssdb.dbtype == 'sql'
|
||||
|
||||
for filename in nssdb.filenames:
|
||||
assert not os.path.isfile(filename)
|
||||
assert not nssdb.exists()
|
||||
|
||||
nssdb.create_db()
|
||||
for filename in nssdb.filenames:
|
||||
assert os.path.isfile(filename)
|
||||
assert os.path.dirname(filename) == nssdb.secdir
|
||||
assert nssdb.exists()
|
||||
|
||||
assert os.path.basename(nssdb.certdb) == 'cert9.db'
|
||||
assert nssdb.certdb in nssdb.filenames
|
||||
assert os.path.basename(nssdb.keydb) == 'key4.db'
|
||||
assert os.path.basename(nssdb.secmod) == 'pkcs11.txt'
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not nss_supports_dbm(),
|
||||
reason="NSS is built without support of the legacy database(DBM)",
|
||||
)
|
||||
def test_convert_db():
|
||||
with NSSDatabase(dbtype='dbm') as nssdb:
|
||||
assert nssdb.dbtype == 'dbm'
|
||||
|
||||
nssdb.create_db()
|
||||
assert nssdb.exists()
|
||||
|
||||
create_selfsigned(nssdb)
|
||||
|
||||
oldcerts = nssdb.list_certs()
|
||||
assert len(oldcerts) == 1
|
||||
oldkeys = nssdb.list_keys()
|
||||
assert len(oldkeys) == 1
|
||||
|
||||
nssdb.convert_db()
|
||||
assert nssdb.exists()
|
||||
|
||||
assert nssdb.dbtype == 'sql'
|
||||
newcerts = nssdb.list_certs()
|
||||
assert len(newcerts) == 1
|
||||
assert newcerts == oldcerts
|
||||
newkeys = nssdb.list_keys()
|
||||
assert len(newkeys) == 1
|
||||
assert newkeys == oldkeys
|
||||
|
||||
for filename in nssdb.filenames:
|
||||
assert os.path.isfile(filename)
|
||||
assert os.path.dirname(filename) == nssdb.secdir
|
||||
|
||||
assert os.path.basename(nssdb.certdb) == 'cert9.db'
|
||||
assert nssdb.certdb in nssdb.filenames
|
||||
assert os.path.basename(nssdb.keydb) == 'key4.db'
|
||||
assert os.path.basename(nssdb.secmod) == 'pkcs11.txt'
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not nss_supports_dbm(),
|
||||
reason="NSS is built without support of the legacy database(DBM)",
|
||||
)
|
||||
def test_convert_db_nokey():
|
||||
with NSSDatabase(dbtype='dbm') as nssdb:
|
||||
assert nssdb.dbtype == 'dbm'
|
||||
nssdb.create_db()
|
||||
|
||||
create_selfsigned(nssdb)
|
||||
|
||||
assert len(nssdb.list_certs()) == 1
|
||||
assert len(nssdb.list_keys()) == 1
|
||||
# remove key, readd cert
|
||||
cert = nssdb.get_cert(CERTNICK)
|
||||
nssdb.run_certutil(['-F', '-n', CERTNICK])
|
||||
nssdb.add_cert(cert, CERTNICK, TRUSTED_PEER_TRUST_FLAGS)
|
||||
assert len(nssdb.list_keys()) == 0
|
||||
oldcerts = nssdb.list_certs()
|
||||
assert len(oldcerts) == 1
|
||||
|
||||
nssdb.convert_db()
|
||||
assert nssdb.dbtype == 'sql'
|
||||
newcerts = nssdb.list_certs()
|
||||
assert len(newcerts) == 1
|
||||
assert newcerts == oldcerts
|
||||
assert nssdb.get_cert(CERTNICK) == cert
|
||||
newkeys = nssdb.list_keys()
|
||||
assert newkeys == ()
|
||||
|
||||
for filename in nssdb.filenames:
|
||||
assert os.path.isfile(filename)
|
||||
assert os.path.dirname(filename) == nssdb.secdir
|
||||
|
||||
old = os.path.join(nssdb.secdir, 'cert8.db')
|
||||
assert not os.path.isfile(old)
|
||||
assert os.path.isfile(old + '.migrated')
|
||||
|
||||
assert os.path.basename(nssdb.certdb) == 'cert9.db'
|
||||
assert nssdb.certdb in nssdb.filenames
|
||||
assert os.path.basename(nssdb.keydb) == 'key4.db'
|
||||
assert os.path.basename(nssdb.secmod) == 'pkcs11.txt'
|
||||
|
||||
|
||||
def test_auto_db():
|
||||
with NSSDatabase() as nssdb:
|
||||
assert nssdb.dbtype == 'auto'
|
||||
assert nssdb.filenames is None
|
||||
assert not nssdb.exists()
|
||||
with pytest.raises(RuntimeError):
|
||||
nssdb.list_certs()
|
||||
|
||||
nssdb.create_db()
|
||||
assert nssdb.dbtype in ('dbm', 'sql')
|
||||
if NSS_DEFAULT is not None:
|
||||
assert nssdb.dbtype == NSS_DEFAULT
|
||||
assert nssdb.filenames is not None
|
||||
assert nssdb.exists()
|
||||
nssdb.list_certs()
|
||||
|
||||
|
||||
def test_delete_cert_and_key():
|
||||
"""Test that delete_cert + delete_key always deletes everything
|
||||
|
||||
Test with a NSSDB that contains:
|
||||
- cert + key
|
||||
- key only
|
||||
- cert only
|
||||
- none of them
|
||||
"""
|
||||
cmd = ipautil.run(['mktemp'], capture_output=True)
|
||||
p12file = cmd.output.strip()
|
||||
|
||||
try:
|
||||
with NSSDatabase() as nssdb:
|
||||
nssdb.create_db()
|
||||
|
||||
# 1. Test delete_key_and_cert when cert + key are present
|
||||
# Create a NSS DB with cert + key
|
||||
create_selfsigned(nssdb)
|
||||
# Save both in a p12 file for latter use
|
||||
ipautil.run(
|
||||
[
|
||||
'pk12util',
|
||||
'-o', p12file, '-n', CERTNICK, '-d', nssdb.secdir,
|
||||
'-k', nssdb.pwd_file,
|
||||
'-w', nssdb.pwd_file
|
||||
])
|
||||
# Delete cert and key
|
||||
nssdb.delete_key_and_cert(CERTNICK)
|
||||
# make sure that everything was deleted
|
||||
assert len(nssdb.list_keys()) == 0
|
||||
assert len(nssdb.list_certs()) == 0
|
||||
|
||||
# 2. Test delete_key_and_cert when only key is present
|
||||
# Import cert and key then remove cert
|
||||
import_args = [
|
||||
'pk12util',
|
||||
'-i', p12file, '-d', nssdb.secdir,
|
||||
'-k', nssdb.pwd_file,
|
||||
'-w', nssdb.pwd_file]
|
||||
ipautil.run(import_args)
|
||||
nssdb.delete_cert(CERTNICK)
|
||||
# Delete cert and key
|
||||
nssdb.delete_key_and_cert(CERTNICK)
|
||||
# make sure that everything was deleted
|
||||
assert len(nssdb.list_keys()) == 0
|
||||
assert len(nssdb.list_certs()) == 0
|
||||
|
||||
# 3. Test delete_key_and_cert when only cert is present
|
||||
# Import cert and key then remove key
|
||||
ipautil.run(import_args)
|
||||
nssdb.delete_key_only(CERTNICK)
|
||||
# make sure the db contains only the cert
|
||||
assert len(nssdb.list_keys()) == 0
|
||||
assert len(nssdb.list_certs()) == 1
|
||||
|
||||
# Delete cert and key when key is not present
|
||||
nssdb.delete_key_and_cert(CERTNICK)
|
||||
# make sure that everything was deleted
|
||||
assert len(nssdb.list_keys()) == 0
|
||||
assert len(nssdb.list_certs()) == 0
|
||||
|
||||
# 4. Test delete_key_and_cert with a wrong nickname
|
||||
# Import cert and key
|
||||
ipautil.run(import_args)
|
||||
# Delete cert and key
|
||||
nssdb.delete_key_and_cert('wrongnick')
|
||||
# make sure that nothing was deleted
|
||||
assert len(nssdb.list_keys()) == 1
|
||||
assert len(nssdb.list_certs()) == 1
|
||||
finally:
|
||||
os.unlink(p12file)
|
||||
|
||||
|
||||
def test_check_validity():
|
||||
with NSSDatabase() as nssdb:
|
||||
nssdb.create_db()
|
||||
create_selfsigned(nssdb)
|
||||
with pytest.raises(ValueError):
|
||||
nssdb.verify_ca_cert_validity(CERTNICK)
|
||||
nssdb.verify_server_cert_validity(CERTNICK, CERTSAN)
|
||||
with pytest.raises(ValueError):
|
||||
nssdb.verify_server_cert_validity(CERTNICK, 'invalid.example')
|
||||
@@ -17,116 +17,136 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import unittest
|
||||
import time
|
||||
import datetime
|
||||
import email.utils
|
||||
import calendar
|
||||
from ipapython.cookie import Cookie
|
||||
|
||||
class TestParse(unittest.TestCase):
|
||||
import pytest
|
||||
|
||||
pytestmark = pytest.mark.tier0
|
||||
|
||||
|
||||
class TestParse:
|
||||
|
||||
def test_parse(self):
|
||||
# Empty string
|
||||
s = ''
|
||||
cookies = Cookie.parse(s)
|
||||
self.assertEqual(len(cookies), 0)
|
||||
assert len(cookies) == 0
|
||||
|
||||
# Invalid single token
|
||||
s = 'color'
|
||||
with self.assertRaises(ValueError):
|
||||
with pytest.raises(ValueError):
|
||||
cookies = Cookie.parse(s)
|
||||
|
||||
# Invalid single token that's keyword
|
||||
s = 'HttpOnly'
|
||||
with self.assertRaises(ValueError):
|
||||
with pytest.raises(ValueError):
|
||||
cookies = Cookie.parse(s)
|
||||
|
||||
# Invalid key/value pair whose key is a keyword
|
||||
s = 'domain=example.com'
|
||||
with self.assertRaises(ValueError):
|
||||
with pytest.raises(ValueError):
|
||||
cookies = Cookie.parse(s)
|
||||
|
||||
# 1 cookie with empty value
|
||||
s = 'color='
|
||||
cookies = Cookie.parse(s)
|
||||
assert len(cookies) == 1
|
||||
cookie = cookies[0]
|
||||
assert cookie.key == 'color'
|
||||
assert cookie.value == ''
|
||||
assert cookie.domain is None
|
||||
assert cookie.path is None
|
||||
assert cookie.max_age is None
|
||||
assert cookie.expires is None
|
||||
assert cookie.secure is None
|
||||
assert cookie.httponly is None
|
||||
assert str(cookie) == "color="
|
||||
assert cookie.http_cookie() == "color=;"
|
||||
|
||||
# 1 cookie with name/value
|
||||
s = 'color=blue'
|
||||
cookies = Cookie.parse(s)
|
||||
self.assertEqual(len(cookies), 1)
|
||||
assert len(cookies) == 1
|
||||
cookie = cookies[0]
|
||||
self.assertEqual(cookie.key, 'color')
|
||||
self.assertEqual(cookie.value, 'blue')
|
||||
self.assertEqual(cookie.domain, None)
|
||||
self.assertEqual(cookie.path, None)
|
||||
self.assertEqual(cookie.max_age, None)
|
||||
self.assertEqual(cookie.expires, None)
|
||||
self.assertEqual(cookie.secure, None)
|
||||
self.assertEqual(cookie.httponly, None)
|
||||
self.assertEqual(str(cookie), "color=blue")
|
||||
self.assertEqual(cookie.http_cookie(), "color=blue;")
|
||||
assert cookie.key == 'color'
|
||||
assert cookie.value == 'blue'
|
||||
assert cookie.domain is None
|
||||
assert cookie.path is None
|
||||
assert cookie.max_age is None
|
||||
assert cookie.expires is None
|
||||
assert cookie.secure is None
|
||||
assert cookie.httponly is None
|
||||
assert str(cookie) == "color=blue"
|
||||
assert cookie.http_cookie() == "color=blue;"
|
||||
|
||||
# 1 cookie with whose value is quoted
|
||||
# Use "get by name" utility to extract specific cookie
|
||||
s = 'color="blue"'
|
||||
cookie = Cookie.get_named_cookie_from_string(s, 'color')
|
||||
self.assertIsNotNone(cookie)
|
||||
self.assertIsNotNone(cookie, Cookie)
|
||||
self.assertEqual(cookie.key, 'color')
|
||||
self.assertEqual(cookie.value, 'blue')
|
||||
self.assertEqual(cookie.domain, None)
|
||||
self.assertEqual(cookie.path, None)
|
||||
self.assertEqual(cookie.max_age, None)
|
||||
self.assertEqual(cookie.expires, None)
|
||||
self.assertEqual(cookie.secure, None)
|
||||
self.assertEqual(cookie.httponly, None)
|
||||
self.assertEqual(str(cookie), "color=blue")
|
||||
self.assertEqual(cookie.http_cookie(), "color=blue;")
|
||||
assert cookie is not None, Cookie
|
||||
assert cookie.key == 'color'
|
||||
assert cookie.value == 'blue'
|
||||
assert cookie.domain is None
|
||||
assert cookie.path is None
|
||||
assert cookie.max_age is None
|
||||
assert cookie.expires is None
|
||||
assert cookie.secure is None
|
||||
assert cookie.httponly is None
|
||||
assert str(cookie) == "color=blue"
|
||||
assert cookie.http_cookie() == "color=blue;"
|
||||
|
||||
# 1 cookie with name/value and domain, path attributes.
|
||||
# Change up the whitespace a bit.
|
||||
s = 'color =blue; domain= example.com ; path = /toplevel '
|
||||
cookies = Cookie.parse(s)
|
||||
self.assertEqual(len(cookies), 1)
|
||||
assert len(cookies) == 1
|
||||
cookie = cookies[0]
|
||||
self.assertEqual(cookie.key, 'color')
|
||||
self.assertEqual(cookie.value, 'blue')
|
||||
self.assertEqual(cookie.domain, 'example.com')
|
||||
self.assertEqual(cookie.path, '/toplevel')
|
||||
self.assertEqual(cookie.max_age, None)
|
||||
self.assertEqual(cookie.expires, None)
|
||||
self.assertEqual(cookie.secure, None)
|
||||
self.assertEqual(cookie.httponly, None)
|
||||
self.assertEqual(str(cookie), "color=blue; Domain=example.com; Path=/toplevel")
|
||||
self.assertEqual(cookie.http_cookie(), "color=blue;")
|
||||
assert cookie.key == 'color'
|
||||
assert cookie.value == 'blue'
|
||||
assert cookie.domain == 'example.com'
|
||||
assert cookie.path == '/toplevel'
|
||||
assert cookie.max_age is None
|
||||
assert cookie.expires is None
|
||||
assert cookie.secure is None
|
||||
assert cookie.httponly is None
|
||||
assert str(cookie) == "color=blue; Domain=example.com; Path=/toplevel"
|
||||
assert cookie.http_cookie() == "color=blue;"
|
||||
|
||||
# 2 cookies, various attributes
|
||||
s = 'color=blue; Max-Age=3600; temperature=hot; HttpOnly'
|
||||
cookies = Cookie.parse(s)
|
||||
self.assertEqual(len(cookies), 2)
|
||||
assert len(cookies) == 2
|
||||
cookie = cookies[0]
|
||||
self.assertEqual(cookie.key, 'color')
|
||||
self.assertEqual(cookie.value, 'blue')
|
||||
self.assertEqual(cookie.domain, None)
|
||||
self.assertEqual(cookie.path, None)
|
||||
self.assertEqual(cookie.max_age, 3600)
|
||||
self.assertEqual(cookie.expires, None)
|
||||
self.assertEqual(cookie.secure, None)
|
||||
self.assertEqual(cookie.httponly, None)
|
||||
self.assertEqual(str(cookie), "color=blue; Max-Age=3600")
|
||||
self.assertEqual(cookie.http_cookie(), "color=blue;")
|
||||
assert cookie.key == 'color'
|
||||
assert cookie.value == 'blue'
|
||||
assert cookie.domain is None
|
||||
assert cookie.path is None
|
||||
assert cookie.max_age == 3600
|
||||
assert cookie.expires is None
|
||||
assert cookie.secure is None
|
||||
assert cookie.httponly is None
|
||||
assert str(cookie) == "color=blue; Max-Age=3600"
|
||||
assert cookie.http_cookie() == "color=blue;"
|
||||
cookie = cookies[1]
|
||||
self.assertEqual(cookie.key, 'temperature')
|
||||
self.assertEqual(cookie.value, 'hot')
|
||||
self.assertEqual(cookie.domain, None)
|
||||
self.assertEqual(cookie.path, None)
|
||||
self.assertEqual(cookie.max_age, None)
|
||||
self.assertEqual(cookie.expires, None)
|
||||
self.assertEqual(cookie.secure, None)
|
||||
self.assertEqual(cookie.httponly, True)
|
||||
self.assertEqual(str(cookie), "temperature=hot; HttpOnly")
|
||||
self.assertEqual(cookie.http_cookie(), "temperature=hot;")
|
||||
assert cookie.key == 'temperature'
|
||||
assert cookie.value == 'hot'
|
||||
assert cookie.domain is None
|
||||
assert cookie.path is None
|
||||
assert cookie.max_age is None
|
||||
assert cookie.expires is None
|
||||
assert cookie.secure is None
|
||||
assert cookie.httponly is True
|
||||
assert str(cookie) == "temperature=hot; HttpOnly"
|
||||
assert cookie.http_cookie() == "temperature=hot;"
|
||||
|
||||
class TestExpires(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
class TestExpires:
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def expires_setup(self):
|
||||
# Force microseconds to zero because cookie timestamps only have second resolution
|
||||
self.now = datetime.datetime.utcnow().replace(microsecond=0)
|
||||
self.now_timestamp = calendar.timegm(self.now.utctimetuple())
|
||||
@@ -145,233 +165,237 @@ class TestExpires(unittest.TestCase):
|
||||
# 1 cookie with name/value and no Max-Age and no Expires
|
||||
s = 'color=blue;'
|
||||
cookies = Cookie.parse(s)
|
||||
self.assertEqual(len(cookies), 1)
|
||||
assert len(cookies) == 1
|
||||
cookie = cookies[0]
|
||||
# Force timestamp to known value
|
||||
cookie.timestamp = self.now
|
||||
self.assertEqual(cookie.key, 'color')
|
||||
self.assertEqual(cookie.value, 'blue')
|
||||
self.assertEqual(cookie.domain, None)
|
||||
self.assertEqual(cookie.path, None)
|
||||
self.assertEqual(cookie.max_age, None)
|
||||
self.assertEqual(cookie.expires, None)
|
||||
self.assertEqual(cookie.secure, None)
|
||||
self.assertEqual(cookie.httponly, None)
|
||||
self.assertEqual(str(cookie), "color=blue")
|
||||
self.assertEqual(cookie.get_expiration(), None)
|
||||
assert cookie.key == 'color'
|
||||
assert cookie.value == 'blue'
|
||||
assert cookie.domain is None
|
||||
assert cookie.path is None
|
||||
assert cookie.max_age is None
|
||||
assert cookie.expires is None
|
||||
assert cookie.secure is None
|
||||
assert cookie.httponly is None
|
||||
assert str(cookie) == "color=blue"
|
||||
assert cookie.get_expiration() is None
|
||||
# Normalize
|
||||
self.assertEqual(cookie.normalize_expiration(), None)
|
||||
self.assertEqual(cookie.max_age, None)
|
||||
self.assertEqual(cookie.expires, None)
|
||||
self.assertEqual(str(cookie), "color=blue")
|
||||
assert cookie.normalize_expiration() is None
|
||||
assert cookie.max_age is None
|
||||
assert cookie.expires is None
|
||||
assert str(cookie) == "color=blue"
|
||||
|
||||
# 1 cookie with name/value and Max-Age
|
||||
s = 'color=blue; max-age=%d' % (self.max_age)
|
||||
cookies = Cookie.parse(s)
|
||||
self.assertEqual(len(cookies), 1)
|
||||
assert len(cookies) == 1
|
||||
cookie = cookies[0]
|
||||
# Force timestamp to known value
|
||||
cookie.timestamp = self.now
|
||||
self.assertEqual(cookie.key, 'color')
|
||||
self.assertEqual(cookie.value, 'blue')
|
||||
self.assertEqual(cookie.domain, None)
|
||||
self.assertEqual(cookie.path, None)
|
||||
self.assertEqual(cookie.max_age, self.max_age)
|
||||
self.assertEqual(cookie.expires, None)
|
||||
self.assertEqual(cookie.secure, None)
|
||||
self.assertEqual(cookie.httponly, None)
|
||||
self.assertEqual(str(cookie), "color=blue; Max-Age=%d" % (self.max_age))
|
||||
self.assertEqual(cookie.get_expiration(), self.age_expiration)
|
||||
assert cookie.key == 'color'
|
||||
assert cookie.value == 'blue'
|
||||
assert cookie.domain is None
|
||||
assert cookie.path is None
|
||||
assert cookie.max_age == self.max_age
|
||||
assert cookie.expires is None
|
||||
assert cookie.secure is None
|
||||
assert cookie.httponly is None
|
||||
assert str(cookie) == "color=blue; Max-Age=%d" % (self.max_age)
|
||||
assert cookie.get_expiration() == self.age_expiration
|
||||
# Normalize
|
||||
self.assertEqual(cookie.normalize_expiration(), self.age_expiration)
|
||||
self.assertEqual(cookie.max_age, None)
|
||||
self.assertEqual(cookie.expires, self.age_expiration)
|
||||
self.assertEqual(str(cookie), "color=blue; Expires=%s" % (self.age_string))
|
||||
assert cookie.normalize_expiration() == self.age_expiration
|
||||
assert cookie.max_age is None
|
||||
assert cookie.expires == self.age_expiration
|
||||
assert str(cookie) == "color=blue; Expires=%s" % (self.age_string)
|
||||
|
||||
|
||||
# 1 cookie with name/value and Expires
|
||||
s = 'color=blue; Expires=%s' % (self.expires_string)
|
||||
cookies = Cookie.parse(s)
|
||||
self.assertEqual(len(cookies), 1)
|
||||
assert len(cookies) == 1
|
||||
cookie = cookies[0]
|
||||
# Force timestamp to known value
|
||||
cookie.timestamp = self.now
|
||||
self.assertEqual(cookie.key, 'color')
|
||||
self.assertEqual(cookie.value, 'blue')
|
||||
self.assertEqual(cookie.domain, None)
|
||||
self.assertEqual(cookie.path, None)
|
||||
self.assertEqual(cookie.max_age, None)
|
||||
self.assertEqual(cookie.expires, self.expires)
|
||||
self.assertEqual(cookie.secure, None)
|
||||
self.assertEqual(cookie.httponly, None)
|
||||
self.assertEqual(str(cookie), "color=blue; Expires=%s" % (self.expires_string))
|
||||
self.assertEqual(cookie.get_expiration(), self.expires)
|
||||
assert cookie.key == 'color'
|
||||
assert cookie.value == 'blue'
|
||||
assert cookie.domain is None
|
||||
assert cookie.path is None
|
||||
assert cookie.max_age is None
|
||||
assert cookie.expires == self.expires
|
||||
assert cookie.secure is None
|
||||
assert cookie.httponly is None
|
||||
assert str(cookie) == "color=blue; Expires=%s" % (self.expires_string)
|
||||
assert cookie.get_expiration() == self.expires
|
||||
# Normalize
|
||||
self.assertEqual(cookie.normalize_expiration(), self.expires)
|
||||
self.assertEqual(cookie.max_age, None)
|
||||
self.assertEqual(cookie.expires, self.expires)
|
||||
self.assertEqual(str(cookie), "color=blue; Expires=%s" % (self.expires_string))
|
||||
assert cookie.normalize_expiration() == self.expires
|
||||
assert cookie.max_age is None
|
||||
assert cookie.expires == self.expires
|
||||
assert str(cookie) == "color=blue; Expires=%s" % (self.expires_string)
|
||||
|
||||
# 1 cookie with name/value witht both Max-Age and Expires, Max-Age takes precedence
|
||||
s = 'color=blue; Expires=%s; max-age=%d' % (self.expires_string, self.max_age)
|
||||
cookies = Cookie.parse(s)
|
||||
self.assertEqual(len(cookies), 1)
|
||||
assert len(cookies) == 1
|
||||
cookie = cookies[0]
|
||||
# Force timestamp to known value
|
||||
cookie.timestamp = self.now
|
||||
self.assertEqual(cookie.key, 'color')
|
||||
self.assertEqual(cookie.value, 'blue')
|
||||
self.assertEqual(cookie.domain, None)
|
||||
self.assertEqual(cookie.path, None)
|
||||
self.assertEqual(cookie.max_age, self.max_age)
|
||||
self.assertEqual(cookie.expires, self.expires)
|
||||
self.assertEqual(cookie.secure, None)
|
||||
self.assertEqual(cookie.httponly, None)
|
||||
self.assertEqual(str(cookie), "color=blue; Max-Age=%d; Expires=%s" % (self.max_age, self.expires_string))
|
||||
self.assertEqual(cookie.get_expiration(), self.age_expiration)
|
||||
assert cookie.key == 'color'
|
||||
assert cookie.value == 'blue'
|
||||
assert cookie.domain is None
|
||||
assert cookie.path is None
|
||||
assert cookie.max_age == self.max_age
|
||||
assert cookie.expires == self.expires
|
||||
assert cookie.secure is None
|
||||
assert cookie.httponly is None
|
||||
expected = "color=blue; Max-Age={}; Expires={}".format(
|
||||
self.max_age, self.expires_string)
|
||||
assert str(cookie) == expected
|
||||
assert cookie.get_expiration() == self.age_expiration
|
||||
# Normalize
|
||||
self.assertEqual(cookie.normalize_expiration(), self.age_expiration)
|
||||
self.assertEqual(cookie.max_age, None)
|
||||
self.assertEqual(cookie.expires, self.age_expiration)
|
||||
self.assertEqual(str(cookie), "color=blue; Expires=%s" % (self.age_string))
|
||||
assert cookie.normalize_expiration() == self.age_expiration
|
||||
assert cookie.max_age is None
|
||||
assert cookie.expires == self.age_expiration
|
||||
assert str(cookie) == "color=blue; Expires=%s" % (self.age_string)
|
||||
|
||||
# Verify different types can be assigned to the timestamp and
|
||||
# expires attribute.
|
||||
|
||||
cookie = Cookie('color', 'blue')
|
||||
cookie.timestamp = self.now
|
||||
self.assertEqual(cookie.timestamp, self.now)
|
||||
assert cookie.timestamp == self.now
|
||||
cookie.timestamp = self.now_timestamp
|
||||
self.assertEqual(cookie.timestamp, self.now)
|
||||
assert cookie.timestamp == self.now
|
||||
cookie.timestamp = self.now_string
|
||||
self.assertEqual(cookie.timestamp, self.now)
|
||||
assert cookie.timestamp == self.now
|
||||
|
||||
self.assertEqual(cookie.expires, None)
|
||||
assert cookie.expires is None
|
||||
|
||||
cookie.expires = self.expires
|
||||
self.assertEqual(cookie.expires, self.expires)
|
||||
assert cookie.expires == self.expires
|
||||
cookie.expires = self.expires_timestamp
|
||||
self.assertEqual(cookie.expires, self.expires)
|
||||
assert cookie.expires == self.expires
|
||||
cookie.expires = self.expires_string
|
||||
self.assertEqual(cookie.expires, self.expires)
|
||||
assert cookie.expires == self.expires
|
||||
|
||||
class TestInvalidAttributes(unittest.TestCase):
|
||||
|
||||
class TestInvalidAttributes:
|
||||
def test_invalid(self):
|
||||
# Invalid Max-Age
|
||||
s = 'color=blue; Max-Age=over-the-hill'
|
||||
with self.assertRaises(ValueError):
|
||||
cookies = Cookie.parse(s)
|
||||
with pytest.raises(ValueError):
|
||||
Cookie.parse(s)
|
||||
|
||||
cookie = Cookie('color', 'blue')
|
||||
with self.assertRaises(ValueError):
|
||||
with pytest.raises(ValueError):
|
||||
cookie.max_age = 'over-the-hill'
|
||||
|
||||
# Invalid Expires
|
||||
s = 'color=blue; Expires=Sun, 06 Xxx 1994 08:49:37 GMT'
|
||||
with self.assertRaises(ValueError):
|
||||
cookies = Cookie.parse(s)
|
||||
with pytest.raises(ValueError):
|
||||
Cookie.parse(s)
|
||||
|
||||
cookie = Cookie('color', 'blue')
|
||||
with self.assertRaises(ValueError):
|
||||
with pytest.raises(ValueError):
|
||||
cookie.expires = 'Sun, 06 Xxx 1994 08:49:37 GMT'
|
||||
|
||||
|
||||
class TestAttributes(unittest.TestCase):
|
||||
class TestAttributes:
|
||||
def test_attributes(self):
|
||||
cookie = Cookie('color', 'blue')
|
||||
self.assertEqual(cookie.key, 'color')
|
||||
self.assertEqual(cookie.value, 'blue')
|
||||
self.assertEqual(cookie.domain, None)
|
||||
self.assertEqual(cookie.path, None)
|
||||
self.assertEqual(cookie.max_age, None)
|
||||
self.assertEqual(cookie.expires, None)
|
||||
self.assertEqual(cookie.secure, None)
|
||||
self.assertEqual(cookie.httponly, None)
|
||||
assert cookie.key == 'color'
|
||||
assert cookie.value == 'blue'
|
||||
assert cookie.domain is None
|
||||
assert cookie.path is None
|
||||
assert cookie.max_age is None
|
||||
assert cookie.expires is None
|
||||
assert cookie.secure is None
|
||||
assert cookie.httponly is None
|
||||
|
||||
cookie.domain = 'example.com'
|
||||
self.assertEqual(cookie.domain, 'example.com')
|
||||
assert cookie.domain == 'example.com'
|
||||
cookie.domain = None
|
||||
self.assertEqual(cookie.domain, None)
|
||||
assert cookie.domain is None
|
||||
|
||||
cookie.path = '/toplevel'
|
||||
self.assertEqual(cookie.path, '/toplevel')
|
||||
assert cookie.path == '/toplevel'
|
||||
cookie.path = None
|
||||
self.assertEqual(cookie.path, None)
|
||||
assert cookie.path is None
|
||||
|
||||
cookie.max_age = 400
|
||||
self.assertEqual(cookie.max_age, 400)
|
||||
assert cookie.max_age == 400
|
||||
cookie.max_age = None
|
||||
self.assertEqual(cookie.max_age, None)
|
||||
assert cookie.max_age is None
|
||||
|
||||
cookie.expires = 'Sun, 06 Nov 1994 08:49:37 GMT'
|
||||
self.assertEqual(cookie.expires, datetime.datetime(1994, 11, 6, 8, 49, 37))
|
||||
assert cookie.expires == datetime.datetime(1994, 11, 6, 8, 49, 37)
|
||||
cookie.expires = None
|
||||
self.assertEqual(cookie.expires, None)
|
||||
assert cookie.expires is None
|
||||
|
||||
cookie.secure = True
|
||||
self.assertEqual(cookie.secure, True)
|
||||
self.assertEqual(str(cookie), "color=blue; Secure")
|
||||
assert cookie.secure is True
|
||||
assert str(cookie) == "color=blue; Secure"
|
||||
cookie.secure = False
|
||||
self.assertEqual(cookie.secure, False)
|
||||
self.assertEqual(str(cookie), "color=blue")
|
||||
assert cookie.secure is False
|
||||
assert str(cookie) == "color=blue"
|
||||
cookie.secure = None
|
||||
self.assertEqual(cookie.secure, None)
|
||||
self.assertEqual(str(cookie), "color=blue")
|
||||
assert cookie.secure is None
|
||||
assert str(cookie) == "color=blue"
|
||||
|
||||
cookie.httponly = True
|
||||
self.assertEqual(cookie.httponly, True)
|
||||
self.assertEqual(str(cookie), "color=blue; HttpOnly")
|
||||
assert cookie.httponly is True
|
||||
assert str(cookie) == "color=blue; HttpOnly"
|
||||
cookie.httponly = False
|
||||
self.assertEqual(cookie.httponly, False)
|
||||
self.assertEqual(str(cookie), "color=blue")
|
||||
assert cookie.httponly is False
|
||||
assert str(cookie) == "color=blue"
|
||||
cookie.httponly = None
|
||||
self.assertEqual(cookie.httponly, None)
|
||||
self.assertEqual(str(cookie), "color=blue")
|
||||
assert cookie.httponly is None
|
||||
assert str(cookie) == "color=blue"
|
||||
|
||||
|
||||
class TestHTTPReturn(unittest.TestCase):
|
||||
def setUp(self):
|
||||
class TestHTTPReturn:
|
||||
@pytest.fixture(autouse=True)
|
||||
def http_return_setup(self):
|
||||
self.url = 'http://www.foo.bar.com/one/two'
|
||||
|
||||
def test_no_attributes(self):
|
||||
cookie = Cookie('color', 'blue')
|
||||
self.assertTrue(cookie.http_return_ok(self.url))
|
||||
assert cookie.http_return_ok(self.url)
|
||||
|
||||
def test_domain(self):
|
||||
cookie = Cookie('color', 'blue', domain='www.foo.bar.com')
|
||||
self.assertTrue(cookie.http_return_ok(self.url))
|
||||
assert cookie.http_return_ok(self.url)
|
||||
|
||||
cookie = Cookie('color', 'blue', domain='.foo.bar.com')
|
||||
self.assertTrue(cookie.http_return_ok(self.url))
|
||||
assert cookie.http_return_ok(self.url)
|
||||
|
||||
cookie = Cookie('color', 'blue', domain='.bar.com')
|
||||
self.assertTrue(cookie.http_return_ok(self.url))
|
||||
assert cookie.http_return_ok(self.url)
|
||||
|
||||
cookie = Cookie('color', 'blue', domain='bar.com')
|
||||
with self.assertRaises(Cookie.URLMismatch):
|
||||
self.assertTrue(cookie.http_return_ok(self.url))
|
||||
with pytest.raises(Cookie.URLMismatch):
|
||||
assert cookie.http_return_ok(self.url)
|
||||
|
||||
cookie = Cookie('color', 'blue', domain='bogus.com')
|
||||
with self.assertRaises(Cookie.URLMismatch):
|
||||
self.assertTrue(cookie.http_return_ok(self.url))
|
||||
with pytest.raises(Cookie.URLMismatch):
|
||||
assert cookie.http_return_ok(self.url)
|
||||
|
||||
cookie = Cookie('color', 'blue', domain='www.foo.bar.com')
|
||||
with self.assertRaises(Cookie.URLMismatch):
|
||||
self.assertTrue(cookie.http_return_ok('http://192.168.1.1/one/two'))
|
||||
with pytest.raises(Cookie.URLMismatch):
|
||||
assert cookie.http_return_ok('http://192.168.1.1/one/two')
|
||||
|
||||
def test_path(self):
|
||||
cookie = Cookie('color', 'blue')
|
||||
self.assertTrue(cookie.http_return_ok(self.url))
|
||||
assert cookie.http_return_ok(self.url)
|
||||
|
||||
cookie = Cookie('color', 'blue', path='/')
|
||||
self.assertTrue(cookie.http_return_ok(self.url))
|
||||
assert cookie.http_return_ok(self.url)
|
||||
|
||||
cookie = Cookie('color', 'blue', path='/one')
|
||||
self.assertTrue(cookie.http_return_ok(self.url))
|
||||
assert cookie.http_return_ok(self.url)
|
||||
|
||||
cookie = Cookie('color', 'blue', path='/oneX')
|
||||
with self.assertRaises(Cookie.URLMismatch):
|
||||
self.assertTrue(cookie.http_return_ok(self.url))
|
||||
with pytest.raises(Cookie.URLMismatch):
|
||||
assert cookie.http_return_ok(self.url)
|
||||
|
||||
def test_expires(self):
|
||||
now = datetime.datetime.utcnow().replace(microsecond=0)
|
||||
@@ -380,32 +404,34 @@ class TestHTTPReturn(unittest.TestCase):
|
||||
expires = now + datetime.timedelta(days=1)
|
||||
|
||||
cookie = Cookie('color', 'blue', expires=expires)
|
||||
self.assertTrue(cookie.http_return_ok(self.url))
|
||||
assert cookie.http_return_ok(self.url)
|
||||
|
||||
# expired 1 day ago
|
||||
expires = now + datetime.timedelta(days=-1)
|
||||
cookie = Cookie('color', 'blue', expires=expires)
|
||||
with self.assertRaises(Cookie.Expired):
|
||||
self.assertTrue(cookie.http_return_ok(self.url))
|
||||
with pytest.raises(Cookie.Expired):
|
||||
assert cookie.http_return_ok(self.url)
|
||||
|
||||
|
||||
def test_httponly(self):
|
||||
cookie = Cookie('color', 'blue', httponly=True)
|
||||
self.assertTrue(cookie.http_return_ok('http://example.com'))
|
||||
self.assertTrue(cookie.http_return_ok('https://example.com'))
|
||||
assert cookie.http_return_ok('http://example.com')
|
||||
assert cookie.http_return_ok('https://example.com')
|
||||
|
||||
with self.assertRaises(Cookie.URLMismatch):
|
||||
self.assertTrue(cookie.http_return_ok('ftp://example.com'))
|
||||
with pytest.raises(Cookie.URLMismatch):
|
||||
assert cookie.http_return_ok('ftp://example.com')
|
||||
|
||||
def test_secure(self):
|
||||
cookie = Cookie('color', 'blue', secure=True)
|
||||
self.assertTrue(cookie.http_return_ok('https://Xexample.com'))
|
||||
assert cookie.http_return_ok('https://Xexample.com')
|
||||
|
||||
with self.assertRaises(Cookie.URLMismatch):
|
||||
self.assertTrue(cookie.http_return_ok('http://Xexample.com'))
|
||||
with pytest.raises(Cookie.URLMismatch):
|
||||
assert cookie.http_return_ok('http://Xexample.com')
|
||||
|
||||
class TestNormalization(unittest.TestCase):
|
||||
def setUp(self):
|
||||
|
||||
class TestNormalization:
|
||||
@pytest.fixture(autouse=True)
|
||||
def normalization_setup(self):
|
||||
# Force microseconds to zero because cookie timestamps only have second resolution
|
||||
self.now = datetime.datetime.utcnow().replace(microsecond=0)
|
||||
self.now_timestamp = calendar.timegm(self.now.utctimetuple())
|
||||
@@ -421,58 +447,53 @@ class TestNormalization(unittest.TestCase):
|
||||
self.expires_string = email.utils.formatdate(self.expires_timestamp, usegmt=True)
|
||||
|
||||
def test_path_normalization(self):
|
||||
self.assertEqual(Cookie.normalize_url_path(''), '/')
|
||||
self.assertEqual(Cookie.normalize_url_path('foo'), '/')
|
||||
self.assertEqual(Cookie.normalize_url_path('foo/'), '/')
|
||||
self.assertEqual(Cookie.normalize_url_path('/foo'), '/')
|
||||
self.assertEqual(Cookie.normalize_url_path('/foo/'), '/foo')
|
||||
self.assertEqual(Cookie.normalize_url_path('/Foo/bar'), '/foo')
|
||||
self.assertEqual(Cookie.normalize_url_path('/foo/baR/'), '/foo/bar')
|
||||
assert Cookie.normalize_url_path('') == '/'
|
||||
assert Cookie.normalize_url_path('foo') == '/'
|
||||
assert Cookie.normalize_url_path('foo/') == '/'
|
||||
assert Cookie.normalize_url_path('/foo') == '/'
|
||||
assert Cookie.normalize_url_path('/foo/') == '/foo'
|
||||
assert Cookie.normalize_url_path('/Foo/bar') == '/foo'
|
||||
assert Cookie.normalize_url_path('/foo/baR/') == '/foo/bar'
|
||||
|
||||
def test_normalization(self):
|
||||
cookie = Cookie('color', 'blue', expires=self.expires)
|
||||
cookie.timestamp = self.now_timestamp
|
||||
|
||||
self.assertEqual(cookie.domain, None)
|
||||
self.assertEqual(cookie.path, None)
|
||||
assert cookie.domain is None
|
||||
assert cookie.path is None
|
||||
|
||||
url = 'http://example.COM/foo'
|
||||
cookie.normalize(url)
|
||||
self.assertEqual(cookie.domain, 'example.com')
|
||||
self.assertEqual(cookie.path, '/')
|
||||
self.assertEqual(cookie.expires, self.expires)
|
||||
assert cookie.domain == 'example.com'
|
||||
assert cookie.path == '/'
|
||||
assert cookie.expires == self.expires
|
||||
|
||||
cookie = Cookie('color', 'blue', max_age=self.max_age)
|
||||
cookie.timestamp = self.now_timestamp
|
||||
|
||||
self.assertEqual(cookie.domain, None)
|
||||
self.assertEqual(cookie.path, None)
|
||||
assert cookie.domain is None
|
||||
assert cookie.path is None
|
||||
|
||||
url = 'http://example.com/foo/'
|
||||
cookie.normalize(url)
|
||||
self.assertEqual(cookie.domain, 'example.com')
|
||||
self.assertEqual(cookie.path, '/foo')
|
||||
self.assertEqual(cookie.expires, self.age_expiration)
|
||||
assert cookie.domain == 'example.com'
|
||||
assert cookie.path == '/foo'
|
||||
assert cookie.expires == self.age_expiration
|
||||
|
||||
cookie = Cookie('color', 'blue')
|
||||
url = 'http://example.com/foo'
|
||||
cookie.normalize(url)
|
||||
self.assertEqual(cookie.domain, 'example.com')
|
||||
self.assertEqual(cookie.path, '/')
|
||||
assert cookie.domain == 'example.com'
|
||||
assert cookie.path == '/'
|
||||
|
||||
cookie = Cookie('color', 'blue')
|
||||
url = 'http://example.com/foo/bar'
|
||||
cookie.normalize(url)
|
||||
self.assertEqual(cookie.domain, 'example.com')
|
||||
self.assertEqual(cookie.path, '/foo')
|
||||
assert cookie.domain == 'example.com'
|
||||
assert cookie.path == '/foo'
|
||||
|
||||
cookie = Cookie('color', 'blue')
|
||||
url = 'http://example.com/foo/bar/'
|
||||
cookie.normalize(url)
|
||||
self.assertEqual(cookie.domain, 'example.com')
|
||||
self.assertEqual(cookie.path, '/foo/bar')
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
assert cookie.domain == 'example.com'
|
||||
assert cookie.path == '/foo/bar'
|
||||
|
||||
163
ipatests/test_ipapython/test_directivesetter.py
Normal file
163
ipatests/test_ipapython/test_directivesetter.py
Normal file
@@ -0,0 +1,163 @@
|
||||
#
|
||||
# Copyright (C) 2017 FreeIPA Contributors. See COPYING for license
|
||||
#
|
||||
from __future__ import absolute_import
|
||||
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
from ipapython import directivesetter
|
||||
|
||||
EXAMPLE_CONFIG = [
|
||||
'foo=1\n',
|
||||
'foobar=2\n',
|
||||
]
|
||||
|
||||
WHITESPACE_CONFIG = [
|
||||
'foo 1\n',
|
||||
'foobar\t2\n',
|
||||
]
|
||||
|
||||
|
||||
class test_set_directive_lines:
|
||||
def test_remove_directive(self):
|
||||
lines = directivesetter.set_directive_lines(
|
||||
False, '=', 'foo', None, EXAMPLE_CONFIG, comment="#")
|
||||
assert list(lines) == ['foobar=2\n']
|
||||
|
||||
def test_add_directive(self):
|
||||
lines = directivesetter.set_directive_lines(
|
||||
False, '=', 'baz', '4', EXAMPLE_CONFIG, comment="#")
|
||||
assert list(lines) == ['foo=1\n', 'foobar=2\n', 'baz=4\n']
|
||||
|
||||
def test_set_directive_does_not_clobber_suffix_key(self):
|
||||
lines = directivesetter.set_directive_lines(
|
||||
False, '=', 'foo', '3', EXAMPLE_CONFIG, comment="#")
|
||||
assert list(lines) == ['foo=3\n', 'foobar=2\n']
|
||||
|
||||
|
||||
class test_set_directive_lines_whitespace:
|
||||
def test_remove_directive(self):
|
||||
lines = directivesetter.set_directive_lines(
|
||||
False, ' ', 'foo', None, WHITESPACE_CONFIG, comment="#")
|
||||
assert list(lines) == ['foobar\t2\n']
|
||||
|
||||
def test_add_directive(self):
|
||||
lines = directivesetter.set_directive_lines(
|
||||
False, ' ', 'baz', '4', WHITESPACE_CONFIG, comment="#")
|
||||
assert list(lines) == ['foo 1\n', 'foobar\t2\n', 'baz 4\n']
|
||||
|
||||
def test_set_directive_does_not_clobber_suffix_key(self):
|
||||
lines = directivesetter.set_directive_lines(
|
||||
False, ' ', 'foo', '3', WHITESPACE_CONFIG, comment="#")
|
||||
assert list(lines) == ['foo 3\n', 'foobar\t2\n']
|
||||
|
||||
def test_set_directive_with_tab(self):
|
||||
lines = directivesetter.set_directive_lines(
|
||||
False, ' ', 'foobar', '6', WHITESPACE_CONFIG, comment="#")
|
||||
assert list(lines) == ['foo 1\n', 'foobar 6\n']
|
||||
|
||||
|
||||
class test_set_directive:
|
||||
def test_set_directive(self):
|
||||
"""Check that set_directive writes the new data and preserves mode."""
|
||||
fd, filename = tempfile.mkstemp()
|
||||
try:
|
||||
os.close(fd)
|
||||
stat_pre = os.stat(filename)
|
||||
|
||||
with open(filename, 'w') as f:
|
||||
for line in EXAMPLE_CONFIG:
|
||||
f.write(line)
|
||||
|
||||
directivesetter.set_directive(
|
||||
filename, 'foo', '3', False, '=', "#")
|
||||
|
||||
stat_post = os.stat(filename)
|
||||
with open(filename, 'r') as f:
|
||||
lines = list(f)
|
||||
|
||||
assert lines == ['foo=3\n', 'foobar=2\n']
|
||||
assert stat_pre.st_mode == stat_post.st_mode
|
||||
assert stat_pre.st_uid == stat_post.st_uid
|
||||
assert stat_pre.st_gid == stat_post.st_gid
|
||||
|
||||
finally:
|
||||
os.remove(filename)
|
||||
|
||||
|
||||
class test_get_directive:
|
||||
def test_get_directive(self, tmpdir):
|
||||
configfile = tmpdir.join('config')
|
||||
configfile.write(''.join(EXAMPLE_CONFIG))
|
||||
|
||||
assert '1' == directivesetter.get_directive(str(configfile),
|
||||
'foo',
|
||||
separator='=')
|
||||
assert '2' == directivesetter.get_directive(str(configfile),
|
||||
'foobar',
|
||||
separator='=')
|
||||
|
||||
|
||||
class test_get_directive_whitespace:
|
||||
def test_get_directive(self, tmpdir):
|
||||
configfile = tmpdir.join('config')
|
||||
configfile.write(''.join(WHITESPACE_CONFIG))
|
||||
|
||||
assert '1' == directivesetter.get_directive(str(configfile),
|
||||
'foo')
|
||||
assert '2' == directivesetter.get_directive(str(configfile),
|
||||
'foobar')
|
||||
|
||||
|
||||
def test_directivesetter(tempdir):
|
||||
filename = os.path.join(tempdir, 'example.conf')
|
||||
with open(filename, 'w') as f:
|
||||
for line in EXAMPLE_CONFIG:
|
||||
f.write(line)
|
||||
|
||||
ds = directivesetter.DirectiveSetter(filename)
|
||||
assert ds.lines is None
|
||||
with ds:
|
||||
assert ds.lines == EXAMPLE_CONFIG
|
||||
ds.set('foo', '3') # quoted, space separated, doesn't change 'foo='
|
||||
ds.set('foobar', None, separator='=') # remove
|
||||
ds.set('baz', '4', False, '=') # add
|
||||
ds.setitems([
|
||||
('list1', 'value1'),
|
||||
('list2', 'value2'),
|
||||
])
|
||||
ds.setitems({
|
||||
'dict1': 'value1',
|
||||
'dict2': 'value2',
|
||||
})
|
||||
|
||||
with open(filename, 'r') as f:
|
||||
lines = list(f)
|
||||
|
||||
assert lines == [
|
||||
'foo=1\n',
|
||||
'foo "3"\n',
|
||||
'baz=4\n',
|
||||
'list1 "value1"\n',
|
||||
'list2 "value2"\n',
|
||||
'dict1 "value1"\n',
|
||||
'dict2 "value2"\n',
|
||||
]
|
||||
|
||||
with directivesetter.DirectiveSetter(filename, True, '=') as ds:
|
||||
ds.set('foo', '4') # doesn't change 'foo '
|
||||
|
||||
with open(filename, 'r') as f:
|
||||
lines = list(f)
|
||||
|
||||
assert lines == [
|
||||
'foo="4"\n',
|
||||
'foo "3"\n',
|
||||
'baz=4\n',
|
||||
'list1 "value1"\n',
|
||||
'list2 "value2"\n',
|
||||
'dict1 "value1"\n',
|
||||
'dict2 "value2"\n',
|
||||
|
||||
]
|
||||
File diff suppressed because it is too large
Load Diff
106
ipatests/test_ipapython/test_dnsutil.py
Normal file
106
ipatests/test_ipapython/test_dnsutil.py
Normal file
@@ -0,0 +1,106 @@
|
||||
#
|
||||
# Copyright (C) 2018 FreeIPA Contributors. See COPYING for license
|
||||
#
|
||||
import dns.name
|
||||
import dns.rdataclass
|
||||
import dns.rdatatype
|
||||
from dns.rdtypes.IN.SRV import SRV
|
||||
from dns.rdtypes.ANY.URI import URI
|
||||
|
||||
from ipapython import dnsutil
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def mksrv(priority, weight, port, target):
|
||||
return SRV(
|
||||
rdclass=dns.rdataclass.IN,
|
||||
rdtype=dns.rdatatype.SRV,
|
||||
priority=priority,
|
||||
weight=weight,
|
||||
port=port,
|
||||
target=dns.name.from_text(target)
|
||||
)
|
||||
|
||||
|
||||
def mkuri(priority, weight, target):
|
||||
return URI(
|
||||
rdclass=dns.rdataclass.IN,
|
||||
rdtype=dns.rdatatype.URI,
|
||||
priority=priority,
|
||||
weight=weight,
|
||||
target=target
|
||||
)
|
||||
|
||||
|
||||
class TestSortSRV:
|
||||
def test_empty(self):
|
||||
assert dnsutil.sort_prio_weight([]) == []
|
||||
|
||||
def test_one(self):
|
||||
h1 = mksrv(1, 0, 443, u"host1")
|
||||
assert dnsutil.sort_prio_weight([h1]) == [h1]
|
||||
|
||||
h2 = mksrv(10, 5, 443, u"host2")
|
||||
assert dnsutil.sort_prio_weight([h2]) == [h2]
|
||||
|
||||
def test_prio(self):
|
||||
h1 = mksrv(1, 0, 443, u"host1")
|
||||
h2 = mksrv(2, 0, 443, u"host2")
|
||||
h3 = mksrv(3, 0, 443, u"host3")
|
||||
assert dnsutil.sort_prio_weight([h3, h2, h1]) == [h1, h2, h3]
|
||||
assert dnsutil.sort_prio_weight([h3, h3, h3]) == [h3]
|
||||
assert dnsutil.sort_prio_weight([h2, h2, h1, h1]) == [h1, h2]
|
||||
|
||||
h380 = mksrv(4, 0, 80, u"host3")
|
||||
assert dnsutil.sort_prio_weight([h1, h3, h380]) == [h1, h3, h380]
|
||||
|
||||
hs = mksrv(-1, 0, 443, u"special")
|
||||
assert dnsutil.sort_prio_weight([h1, h2, hs]) == [hs, h1, h2]
|
||||
|
||||
def assert_permutations(self, answers, permutations):
|
||||
seen = set()
|
||||
for _unused in range(1000):
|
||||
result = tuple(dnsutil.sort_prio_weight(answers))
|
||||
assert result in permutations
|
||||
seen.add(result)
|
||||
if seen == permutations:
|
||||
break
|
||||
else:
|
||||
pytest.fail("sorting didn't exhaust all permutations.")
|
||||
|
||||
def test_sameprio(self):
|
||||
h1 = mksrv(1, 0, 443, u"host1")
|
||||
h2 = mksrv(1, 0, 443, u"host2")
|
||||
permutations = {
|
||||
(h1, h2),
|
||||
(h2, h1),
|
||||
}
|
||||
self.assert_permutations([h1, h2], permutations)
|
||||
|
||||
def test_weight(self):
|
||||
h1 = mksrv(1, 0, 443, u"host1")
|
||||
h2_w15 = mksrv(2, 15, 443, u"host2")
|
||||
h3_w10 = mksrv(2, 10, 443, u"host3")
|
||||
|
||||
permutations = {
|
||||
(h1, h2_w15, h3_w10),
|
||||
(h1, h3_w10, h2_w15),
|
||||
}
|
||||
self.assert_permutations([h1, h2_w15, h3_w10], permutations)
|
||||
|
||||
def test_large(self):
|
||||
records = tuple(
|
||||
mksrv(1, i, 443, "host{}".format(i)) for i in range(1000)
|
||||
)
|
||||
assert len(dnsutil.sort_prio_weight(records)) == len(records)
|
||||
|
||||
|
||||
class TestSortURI:
|
||||
def test_prio(self):
|
||||
h1 = mkuri(1, 0, u"https://host1/api")
|
||||
h2 = mkuri(2, 0, u"https://host2/api")
|
||||
h3 = mkuri(3, 0, u"https://host3/api")
|
||||
assert dnsutil.sort_prio_weight([h3, h2, h1]) == [h1, h2, h3]
|
||||
assert dnsutil.sort_prio_weight([h3, h3, h3]) == [h3]
|
||||
assert dnsutil.sort_prio_weight([h2, h2, h1, h1]) == [h1, h2]
|
||||
@@ -1,3 +1,5 @@
|
||||
# encoding: utf-8
|
||||
|
||||
# Authors:
|
||||
# Jan Cholasta <jcholast@redhat.com>
|
||||
#
|
||||
@@ -19,58 +21,73 @@
|
||||
"""
|
||||
Test the `ipapython/ipautil.py` module.
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import nose
|
||||
import os
|
||||
import pwd
|
||||
import socket
|
||||
import sys
|
||||
import tempfile
|
||||
import textwrap
|
||||
|
||||
import pytest
|
||||
import six
|
||||
|
||||
from ipalib.constants import IPAAPI_USER
|
||||
from ipaplatform.paths import paths
|
||||
from ipapython import ipautil
|
||||
|
||||
class CheckIPAddress:
|
||||
def __init__(self, addr):
|
||||
self.description = "Test IP address parsing and verification (%s)" % addr
|
||||
|
||||
def __call__(self, addr, words=None, prefixlen=None):
|
||||
try:
|
||||
ip = ipautil.CheckedIPAddress(addr, match_local=False)
|
||||
assert ip.words == words and ip.prefixlen == prefixlen
|
||||
except:
|
||||
assert words is None and prefixlen is None
|
||||
|
||||
def test_ip_address():
|
||||
addrs = [
|
||||
('10.11.12.13', (10, 11, 12, 13), 8),
|
||||
('10.11.12.13/14', (10, 11, 12, 13), 14),
|
||||
('10.11.12.13%zoneid',),
|
||||
('10.11.12.13%zoneid/14',),
|
||||
('10.11.12.1337',),
|
||||
('10.11.12.13/33',),
|
||||
('127.0.0.1',),
|
||||
('241.1.2.3',),
|
||||
('169.254.1.2',),
|
||||
('10.11.12.0/24',),
|
||||
('224.5.6.7',),
|
||||
('10.11.12.255/24',),
|
||||
|
||||
('2001::1', (0x2001, 0, 0, 0, 0, 0, 0, 1), 64),
|
||||
('2001::1/72', (0x2001, 0, 0, 0, 0, 0, 0, 1), 72),
|
||||
('2001::1%zoneid', (0x2001, 0, 0, 0, 0, 0, 0, 1), 64),
|
||||
('2001::1%zoneid/72',),
|
||||
('2001::1beef',),
|
||||
('2001::1/129',),
|
||||
('::1',),
|
||||
('6789::1',),
|
||||
('fe89::1',),
|
||||
('2001::/64',),
|
||||
('ff01::1',),
|
||||
|
||||
('junk',)
|
||||
]
|
||||
|
||||
for addr in addrs:
|
||||
yield (CheckIPAddress(addr[0]),) + addr
|
||||
pytestmark = pytest.mark.tier0
|
||||
|
||||
|
||||
class TestCIDict(object):
|
||||
def setup(self):
|
||||
def assert_equal(a, b):
|
||||
__tracebackhide__ = True
|
||||
assert a == b
|
||||
|
||||
|
||||
@pytest.mark.parametrize("addr,words,prefixlen", [
|
||||
('0.0.0.0/0', None, None),
|
||||
('10.11.12.13', (10, 11, 12, 13), 8),
|
||||
('10.11.12.13/14', (10, 11, 12, 13), 14),
|
||||
('10.11.12.13%zoneid', None, None),
|
||||
('10.11.12.13%zoneid/14', None, None),
|
||||
('10.11.12.1337', None, None),
|
||||
('10.11.12.13/33', None, None),
|
||||
('127.0.0.1', None, None),
|
||||
('241.1.2.3', None, None),
|
||||
('169.254.1.2', None, None),
|
||||
('10.11.12.0/24', (10, 11, 12, 0), 24),
|
||||
('10.0.0.255', (10, 0, 0, 255), 8),
|
||||
('224.5.6.7', None, None),
|
||||
('10.11.12.255/24', (10, 11, 12, 255), 24),
|
||||
('255.255.255.255', None, None),
|
||||
('::/0', None, None),
|
||||
('2001::1', (0x2001, 0, 0, 0, 0, 0, 0, 1), 64),
|
||||
('2001::1/72', (0x2001, 0, 0, 0, 0, 0, 0, 1), 72),
|
||||
('2001::1%zoneid', (0x2001, 0, 0, 0, 0, 0, 0, 1), 64),
|
||||
('2001::1%zoneid/72', None, None),
|
||||
('2001::1beef', None, None),
|
||||
('2001::1/129', None, None),
|
||||
('::1', None, None),
|
||||
('6789::1', None, None),
|
||||
('fe89::1', None, None),
|
||||
('2001::/64', (0x2001, 0, 0, 0, 0, 0, 0, 0), 64),
|
||||
('ff01::1', None, None),
|
||||
('junk', None, None)
|
||||
])
|
||||
def test_ip_address(addr, words, prefixlen):
|
||||
if words is None:
|
||||
pytest.raises(
|
||||
ValueError, ipautil.CheckedIPAddress, addr)
|
||||
else:
|
||||
ip = ipautil.CheckedIPAddress(addr)
|
||||
assert ip.words == words
|
||||
assert ip.prefixlen == prefixlen
|
||||
|
||||
|
||||
class TestCIDict:
|
||||
@pytest.fixture(autouse=True)
|
||||
def cidict_setup(self):
|
||||
self.cidict = ipautil.CIDict()
|
||||
self.cidict["Key1"] = "val1"
|
||||
self.cidict["key2"] = "val2"
|
||||
@@ -89,59 +106,69 @@ class TestCIDict(object):
|
||||
assert dict(cidict.items()) == {'a': 2, 'b': 3, 'C': 4}
|
||||
|
||||
def test_len(self):
|
||||
nose.tools.assert_equal(3, len(self.cidict))
|
||||
assert_equal(3, len(self.cidict))
|
||||
|
||||
def test_getitem(self):
|
||||
nose.tools.assert_equal("val1", self.cidict["Key1"])
|
||||
nose.tools.assert_equal("val1", self.cidict["key1"])
|
||||
nose.tools.assert_equal("val2", self.cidict["KEY2"])
|
||||
nose.tools.assert_equal("VAL3", self.cidict["key3"])
|
||||
nose.tools.assert_equal("VAL3", self.cidict["KEY3"])
|
||||
with nose.tools.assert_raises(KeyError):
|
||||
self.cidict["key4"]
|
||||
assert_equal("val1", self.cidict["Key1"])
|
||||
assert_equal("val1", self.cidict["key1"])
|
||||
assert_equal("val2", self.cidict["KEY2"])
|
||||
assert_equal("VAL3", self.cidict["key3"])
|
||||
assert_equal("VAL3", self.cidict["KEY3"])
|
||||
with pytest.raises(KeyError):
|
||||
self.cidict["key4"] # pylint: disable=pointless-statement
|
||||
|
||||
def test_get(self):
|
||||
nose.tools.assert_equal("val1", self.cidict.get("Key1"))
|
||||
nose.tools.assert_equal("val1", self.cidict.get("key1"))
|
||||
nose.tools.assert_equal("val2", self.cidict.get("KEY2"))
|
||||
nose.tools.assert_equal("VAL3", self.cidict.get("key3"))
|
||||
nose.tools.assert_equal("VAL3", self.cidict.get("KEY3"))
|
||||
nose.tools.assert_equal("default", self.cidict.get("key4", "default"))
|
||||
assert_equal("val1", self.cidict.get("Key1"))
|
||||
assert_equal("val1", self.cidict.get("key1"))
|
||||
assert_equal("val2", self.cidict.get("KEY2"))
|
||||
assert_equal("VAL3", self.cidict.get("key3"))
|
||||
assert_equal("VAL3", self.cidict.get("KEY3"))
|
||||
assert_equal("default", self.cidict.get("key4", "default"))
|
||||
|
||||
def test_setitem(self):
|
||||
self.cidict["key4"] = "val4"
|
||||
nose.tools.assert_equal("val4", self.cidict["key4"])
|
||||
assert_equal("val4", self.cidict["key4"])
|
||||
self.cidict["KEY4"] = "newval4"
|
||||
nose.tools.assert_equal("newval4", self.cidict["key4"])
|
||||
assert_equal("newval4", self.cidict["key4"])
|
||||
|
||||
def test_del(self):
|
||||
assert self.cidict.has_key("Key1")
|
||||
assert "Key1" in self.cidict
|
||||
del(self.cidict["Key1"])
|
||||
assert not self.cidict.has_key("Key1")
|
||||
assert "Key1" not in self.cidict
|
||||
|
||||
assert self.cidict.has_key("key2")
|
||||
assert "key2" in self.cidict
|
||||
del(self.cidict["KEY2"])
|
||||
assert not self.cidict.has_key("key2")
|
||||
assert "key2" not in self.cidict
|
||||
|
||||
def test_clear(self):
|
||||
nose.tools.assert_equal(3, len(self.cidict))
|
||||
assert_equal(3, len(self.cidict))
|
||||
self.cidict.clear()
|
||||
nose.tools.assert_equal(0, len(self.cidict))
|
||||
assert_equal(0, len(self.cidict))
|
||||
assert self.cidict == {}
|
||||
assert list(self.cidict) == []
|
||||
assert list(self.cidict.values()) == []
|
||||
assert list(self.cidict.items()) == []
|
||||
if six.PY2:
|
||||
assert self.cidict.keys() == []
|
||||
assert self.cidict.values() == []
|
||||
assert self.cidict.items() == []
|
||||
assert self.cidict._keys == {}
|
||||
|
||||
def test_copy(self):
|
||||
copy = self.cidict.copy()
|
||||
assert copy == self.cidict
|
||||
nose.tools.assert_equal(3, len(copy))
|
||||
assert copy.has_key("Key1")
|
||||
assert copy.has_key("key1")
|
||||
nose.tools.assert_equal("val1", copy["Key1"])
|
||||
assert_equal(3, len(copy))
|
||||
assert "Key1" in copy
|
||||
assert "key1" in copy
|
||||
assert_equal("val1", copy["Key1"])
|
||||
|
||||
@pytest.mark.skipif(not six.PY2, reason="Python 2 only")
|
||||
def test_haskey(self):
|
||||
assert self.cidict.has_key("KEY1")
|
||||
assert self.cidict.has_key("key2")
|
||||
assert self.cidict.has_key("key3")
|
||||
assert self.cidict.has_key("KEY1") # noqa
|
||||
assert self.cidict.has_key("key2") # noqa
|
||||
assert self.cidict.has_key("key3") # noqa
|
||||
|
||||
assert not self.cidict.has_key("Key4")
|
||||
assert not self.cidict.has_key("Key4") # noqa
|
||||
|
||||
def test_contains(self):
|
||||
assert "KEY1" in self.cidict
|
||||
@@ -151,26 +178,27 @@ class TestCIDict(object):
|
||||
assert "Key4" not in self.cidict
|
||||
|
||||
def test_items(self):
|
||||
items = self.cidict.items()
|
||||
nose.tools.assert_equal(3, len(items))
|
||||
items = list(self.cidict.items())
|
||||
assert_equal(3, len(items))
|
||||
items_set = set(items)
|
||||
assert ("Key1", "val1") in items_set
|
||||
assert ("key2", "val2") in items_set
|
||||
assert ("KEY3", "VAL3") in items_set
|
||||
|
||||
assert self.cidict.items() == list(self.cidict.iteritems()) == zip(
|
||||
self.cidict.iterkeys(), self.cidict.itervalues())
|
||||
# pylint: disable=dict-iter-method
|
||||
# pylint: disable=dict-keys-not-iterating, dict-values-not-iterating
|
||||
assert list(self.cidict.items()) == list(self.cidict.iteritems()) == list(zip(
|
||||
self.cidict.keys(), self.cidict.values()))
|
||||
|
||||
def test_iter(self):
|
||||
items = []
|
||||
assert list(self.cidict) == list(self.cidict.keys())
|
||||
assert sorted(self.cidict) == sorted(['Key1', 'key2', 'KEY3'])
|
||||
|
||||
def test_iteritems(self):
|
||||
items = []
|
||||
for (k,v) in self.cidict.iteritems():
|
||||
items.append((k,v))
|
||||
nose.tools.assert_equal(3, len(items))
|
||||
# pylint: disable=dict-iter-method
|
||||
for k, v in self.cidict.iteritems():
|
||||
items.append((k, v))
|
||||
assert_equal(3, len(items))
|
||||
items_set = set(items)
|
||||
assert ("Key1", "val1") in items_set
|
||||
assert ("key2", "val2") in items_set
|
||||
@@ -178,9 +206,10 @@ class TestCIDict(object):
|
||||
|
||||
def test_iterkeys(self):
|
||||
keys = []
|
||||
# pylint: disable=dict-iter-method
|
||||
for k in self.cidict.iterkeys():
|
||||
keys.append(k)
|
||||
nose.tools.assert_equal(3, len(keys))
|
||||
assert_equal(3, len(keys))
|
||||
keys_set = set(keys)
|
||||
assert "Key1" in keys_set
|
||||
assert "key2" in keys_set
|
||||
@@ -188,42 +217,43 @@ class TestCIDict(object):
|
||||
|
||||
def test_itervalues(self):
|
||||
values = []
|
||||
# pylint: disable=dict-iter-method
|
||||
for k in self.cidict.itervalues():
|
||||
values.append(k)
|
||||
nose.tools.assert_equal(3, len(values))
|
||||
assert_equal(3, len(values))
|
||||
values_set = set(values)
|
||||
assert "val1" in values_set
|
||||
assert "val2" in values_set
|
||||
assert "VAL3" in values_set
|
||||
|
||||
def test_keys(self):
|
||||
keys = self.cidict.keys()
|
||||
nose.tools.assert_equal(3, len(keys))
|
||||
keys = list(self.cidict.keys())
|
||||
assert_equal(3, len(keys))
|
||||
keys_set = set(keys)
|
||||
assert "Key1" in keys_set
|
||||
assert "key2" in keys_set
|
||||
assert "KEY3" in keys_set
|
||||
|
||||
assert self.cidict.keys() == list(self.cidict.iterkeys())
|
||||
# pylint: disable=dict-iter-method
|
||||
assert list(self.cidict.keys()) == list(self.cidict.iterkeys())
|
||||
|
||||
def test_values(self):
|
||||
values = self.cidict.values()
|
||||
nose.tools.assert_equal(3, len(values))
|
||||
values = list(self.cidict.values())
|
||||
assert_equal(3, len(values))
|
||||
values_set = set(values)
|
||||
assert "val1" in values_set
|
||||
assert "val2" in values_set
|
||||
assert "VAL3" in values_set
|
||||
|
||||
assert self.cidict.values() == list(self.cidict.itervalues())
|
||||
# pylint: disable=dict-iter-method
|
||||
assert list(self.cidict.values()) == list(self.cidict.itervalues())
|
||||
|
||||
def test_update(self):
|
||||
newdict = { "KEY2": "newval2",
|
||||
"key4": "val4" }
|
||||
self.cidict.update(newdict)
|
||||
nose.tools.assert_equal(4, len(self.cidict))
|
||||
assert_equal(4, len(self.cidict))
|
||||
|
||||
items = self.cidict.items()
|
||||
nose.tools.assert_equal(4, len(items))
|
||||
items = list(self.cidict.items())
|
||||
assert_equal(4, len(items))
|
||||
items_set = set(items)
|
||||
assert ("Key1", "val1") in items_set
|
||||
# note the update "overwrites" the case of the key2
|
||||
@@ -244,15 +274,15 @@ class TestCIDict(object):
|
||||
'Key1': 'val1', 'key2': 'val2', 'KEY3': 'VAL3'}
|
||||
|
||||
def test_update_duplicate_values_dict(self):
|
||||
with nose.tools.assert_raises(ValueError):
|
||||
with pytest.raises(ValueError):
|
||||
self.cidict.update({'a': 'va', 'A': None, 'b': 3})
|
||||
|
||||
def test_update_duplicate_values_list(self):
|
||||
with nose.tools.assert_raises(ValueError):
|
||||
with pytest.raises(ValueError):
|
||||
self.cidict.update([('a', 'va'), ('A', None), ('b', 3)])
|
||||
|
||||
def test_update_duplicate_values_kwargs(self):
|
||||
with nose.tools.assert_raises(ValueError):
|
||||
with pytest.raises(ValueError):
|
||||
self.cidict.update(a='va', A=None, b=3)
|
||||
|
||||
def test_update_kwargs(self):
|
||||
@@ -261,148 +291,318 @@ class TestCIDict(object):
|
||||
'b': 'vb', 'Key1': 'val1', 'key2': 'val2', 'KEY3': 'VAL3'}
|
||||
|
||||
def test_setdefault(self):
|
||||
nose.tools.assert_equal("val1", self.cidict.setdefault("KEY1", "default"))
|
||||
assert_equal("val1", self.cidict.setdefault("KEY1", "default"))
|
||||
|
||||
assert not self.cidict.has_key("KEY4")
|
||||
nose.tools.assert_equal("default", self.cidict.setdefault("KEY4", "default"))
|
||||
assert self.cidict.has_key("KEY4")
|
||||
nose.tools.assert_equal("default", self.cidict["key4"])
|
||||
assert "KEY4" not in self.cidict
|
||||
assert_equal("default", self.cidict.setdefault("KEY4", "default"))
|
||||
assert "KEY4" in self.cidict
|
||||
assert_equal("default", self.cidict["key4"])
|
||||
|
||||
assert not self.cidict.has_key("KEY5")
|
||||
nose.tools.assert_equal(None, self.cidict.setdefault("KEY5"))
|
||||
assert self.cidict.has_key("KEY5")
|
||||
nose.tools.assert_equal(None, self.cidict["key5"])
|
||||
assert "KEY5" not in self.cidict
|
||||
assert_equal(None, self.cidict.setdefault("KEY5"))
|
||||
assert "KEY5" in self.cidict
|
||||
assert_equal(None, self.cidict["key5"])
|
||||
|
||||
def test_pop(self):
|
||||
nose.tools.assert_equal("val1", self.cidict.pop("KEY1", "default"))
|
||||
assert not self.cidict.has_key("key1")
|
||||
assert_equal("val1", self.cidict.pop("KEY1", "default"))
|
||||
assert "key1" not in self.cidict
|
||||
|
||||
nose.tools.assert_equal("val2", self.cidict.pop("KEY2"))
|
||||
assert not self.cidict.has_key("key2")
|
||||
assert_equal("val2", self.cidict.pop("KEY2"))
|
||||
assert "key2" not in self.cidict
|
||||
|
||||
nose.tools.assert_equal("default", self.cidict.pop("key4", "default"))
|
||||
with nose.tools.assert_raises(KeyError):
|
||||
assert_equal("default", self.cidict.pop("key4", "default"))
|
||||
with pytest.raises(KeyError):
|
||||
self.cidict.pop("key4")
|
||||
|
||||
def test_popitem(self):
|
||||
items = set(self.cidict.items())
|
||||
nose.tools.assert_equal(3, len(self.cidict))
|
||||
assert_equal(3, len(self.cidict))
|
||||
|
||||
item = self.cidict.popitem()
|
||||
nose.tools.assert_equal(2, len(self.cidict))
|
||||
assert_equal(2, len(self.cidict))
|
||||
assert item in items
|
||||
items.discard(item)
|
||||
|
||||
item = self.cidict.popitem()
|
||||
nose.tools.assert_equal(1, len(self.cidict))
|
||||
assert_equal(1, len(self.cidict))
|
||||
assert item in items
|
||||
items.discard(item)
|
||||
|
||||
item = self.cidict.popitem()
|
||||
nose.tools.assert_equal(0, len(self.cidict))
|
||||
assert_equal(0, len(self.cidict))
|
||||
assert item in items
|
||||
items.discard(item)
|
||||
|
||||
def test_fromkeys(self):
|
||||
dct = ipautil.CIDict.fromkeys(('A', 'b', 'C'))
|
||||
assert sorted(dct.keys()) == sorted(['A', 'b', 'C'])
|
||||
assert sorted(dct.values()) == [None] * 3
|
||||
|
||||
def test_clear(self):
|
||||
self.cidict.clear()
|
||||
assert self.cidict == {}
|
||||
assert self.cidict.keys() == []
|
||||
assert self.cidict.values() == []
|
||||
assert self.cidict.items() == []
|
||||
assert self.cidict._keys == {}
|
||||
assert list(dct.values()) == [None] * 3
|
||||
|
||||
|
||||
class TestTimeParser(object):
|
||||
class TestTimeParser:
|
||||
def test_simple(self):
|
||||
timestr = "20070803"
|
||||
|
||||
time = ipautil.parse_generalized_time(timestr)
|
||||
nose.tools.assert_equal(2007, time.year)
|
||||
nose.tools.assert_equal(8, time.month)
|
||||
nose.tools.assert_equal(3, time.day)
|
||||
nose.tools.assert_equal(0, time.hour)
|
||||
nose.tools.assert_equal(0, time.minute)
|
||||
nose.tools.assert_equal(0, time.second)
|
||||
assert_equal(2007, time.year)
|
||||
assert_equal(8, time.month)
|
||||
assert_equal(3, time.day)
|
||||
assert_equal(0, time.hour)
|
||||
assert_equal(0, time.minute)
|
||||
assert_equal(0, time.second)
|
||||
|
||||
def test_hour_min_sec(self):
|
||||
timestr = "20051213141205"
|
||||
|
||||
time = ipautil.parse_generalized_time(timestr)
|
||||
nose.tools.assert_equal(2005, time.year)
|
||||
nose.tools.assert_equal(12, time.month)
|
||||
nose.tools.assert_equal(13, time.day)
|
||||
nose.tools.assert_equal(14, time.hour)
|
||||
nose.tools.assert_equal(12, time.minute)
|
||||
nose.tools.assert_equal(5, time.second)
|
||||
assert_equal(2005, time.year)
|
||||
assert_equal(12, time.month)
|
||||
assert_equal(13, time.day)
|
||||
assert_equal(14, time.hour)
|
||||
assert_equal(12, time.minute)
|
||||
assert_equal(5, time.second)
|
||||
|
||||
def test_fractions(self):
|
||||
timestr = "2003092208.5"
|
||||
|
||||
time = ipautil.parse_generalized_time(timestr)
|
||||
nose.tools.assert_equal(2003, time.year)
|
||||
nose.tools.assert_equal(9, time.month)
|
||||
nose.tools.assert_equal(22, time.day)
|
||||
nose.tools.assert_equal(8, time.hour)
|
||||
nose.tools.assert_equal(30, time.minute)
|
||||
nose.tools.assert_equal(0, time.second)
|
||||
assert_equal(2003, time.year)
|
||||
assert_equal(9, time.month)
|
||||
assert_equal(22, time.day)
|
||||
assert_equal(8, time.hour)
|
||||
assert_equal(30, time.minute)
|
||||
assert_equal(0, time.second)
|
||||
|
||||
timestr = "199203301544,25"
|
||||
|
||||
time = ipautil.parse_generalized_time(timestr)
|
||||
nose.tools.assert_equal(1992, time.year)
|
||||
nose.tools.assert_equal(3, time.month)
|
||||
nose.tools.assert_equal(30, time.day)
|
||||
nose.tools.assert_equal(15, time.hour)
|
||||
nose.tools.assert_equal(44, time.minute)
|
||||
nose.tools.assert_equal(15, time.second)
|
||||
assert_equal(1992, time.year)
|
||||
assert_equal(3, time.month)
|
||||
assert_equal(30, time.day)
|
||||
assert_equal(15, time.hour)
|
||||
assert_equal(44, time.minute)
|
||||
assert_equal(15, time.second)
|
||||
|
||||
timestr = "20060401185912,8"
|
||||
|
||||
time = ipautil.parse_generalized_time(timestr)
|
||||
nose.tools.assert_equal(2006, time.year)
|
||||
nose.tools.assert_equal(4, time.month)
|
||||
nose.tools.assert_equal(1, time.day)
|
||||
nose.tools.assert_equal(18, time.hour)
|
||||
nose.tools.assert_equal(59, time.minute)
|
||||
nose.tools.assert_equal(12, time.second)
|
||||
nose.tools.assert_equal(800000, time.microsecond)
|
||||
assert_equal(2006, time.year)
|
||||
assert_equal(4, time.month)
|
||||
assert_equal(1, time.day)
|
||||
assert_equal(18, time.hour)
|
||||
assert_equal(59, time.minute)
|
||||
assert_equal(12, time.second)
|
||||
assert_equal(800000, time.microsecond)
|
||||
|
||||
def test_time_zones(self):
|
||||
timestr = "20051213141205Z"
|
||||
|
||||
time = ipautil.parse_generalized_time(timestr)
|
||||
nose.tools.assert_equal(0, time.tzinfo.houroffset)
|
||||
nose.tools.assert_equal(0, time.tzinfo.minoffset)
|
||||
assert_equal(0, time.tzinfo.houroffset)
|
||||
assert_equal(0, time.tzinfo.minoffset)
|
||||
offset = time.tzinfo.utcoffset(time.tzinfo.dst())
|
||||
nose.tools.assert_equal(0, offset.seconds)
|
||||
assert_equal(0, offset.seconds)
|
||||
|
||||
timestr = "20051213141205+0500"
|
||||
|
||||
time = ipautil.parse_generalized_time(timestr)
|
||||
nose.tools.assert_equal(5, time.tzinfo.houroffset)
|
||||
nose.tools.assert_equal(0, time.tzinfo.minoffset)
|
||||
assert_equal(5, time.tzinfo.houroffset)
|
||||
assert_equal(0, time.tzinfo.minoffset)
|
||||
offset = time.tzinfo.utcoffset(time.tzinfo.dst())
|
||||
nose.tools.assert_equal(5 * 60 * 60, offset.seconds)
|
||||
assert_equal(5 * 60 * 60, offset.seconds)
|
||||
|
||||
timestr = "20051213141205-0500"
|
||||
|
||||
time = ipautil.parse_generalized_time(timestr)
|
||||
nose.tools.assert_equal(-5, time.tzinfo.houroffset)
|
||||
nose.tools.assert_equal(0, time.tzinfo.minoffset)
|
||||
assert_equal(-5, time.tzinfo.houroffset)
|
||||
assert_equal(0, time.tzinfo.minoffset)
|
||||
# NOTE - the offset is always positive - it's minutes
|
||||
# _east_ of UTC
|
||||
offset = time.tzinfo.utcoffset(time.tzinfo.dst())
|
||||
nose.tools.assert_equal((24 - 5) * 60 * 60, offset.seconds)
|
||||
assert_equal((24 - 5) * 60 * 60, offset.seconds)
|
||||
|
||||
timestr = "20051213141205-0930"
|
||||
|
||||
time = ipautil.parse_generalized_time(timestr)
|
||||
nose.tools.assert_equal(-9, time.tzinfo.houroffset)
|
||||
nose.tools.assert_equal(-30, time.tzinfo.minoffset)
|
||||
assert_equal(-9, time.tzinfo.houroffset)
|
||||
assert_equal(-30, time.tzinfo.minoffset)
|
||||
offset = time.tzinfo.utcoffset(time.tzinfo.dst())
|
||||
nose.tools.assert_equal(((24 - 9) * 60 * 60) - (30 * 60), offset.seconds)
|
||||
assert_equal(((24 - 9) * 60 * 60) - (30 * 60), offset.seconds)
|
||||
|
||||
|
||||
def test_run():
|
||||
result = ipautil.run([paths.ECHO, 'foo\x02bar'],
|
||||
capture_output=True,
|
||||
capture_error=True)
|
||||
assert result.returncode == 0
|
||||
assert result.output == 'foo\x02bar\n'
|
||||
assert result.raw_output == b'foo\x02bar\n'
|
||||
assert result.error_output == ''
|
||||
assert result.raw_error_output == b''
|
||||
|
||||
|
||||
def test_run_no_capture_output():
|
||||
result = ipautil.run([paths.ECHO, 'foo\x02bar'])
|
||||
assert result.returncode == 0
|
||||
assert result.output is None
|
||||
assert result.raw_output == b'foo\x02bar\n'
|
||||
assert result.error_output is None
|
||||
assert result.raw_error_output == b''
|
||||
|
||||
|
||||
def test_run_bytes():
|
||||
result = ipautil.run([paths.ECHO, b'\x01\x02'], capture_output=True)
|
||||
assert result.returncode == 0
|
||||
assert result.raw_output == b'\x01\x02\n'
|
||||
|
||||
|
||||
def test_run_decode():
|
||||
result = ipautil.run([paths.ECHO, u'á'.encode('utf-8')],
|
||||
encoding='utf-8', capture_output=True)
|
||||
assert result.returncode == 0
|
||||
if six.PY3:
|
||||
assert result.output == 'á\n'
|
||||
else:
|
||||
assert result.output == 'á\n'.encode('utf-8')
|
||||
|
||||
|
||||
def test_run_decode_bad():
|
||||
if six.PY3:
|
||||
with pytest.raises(UnicodeDecodeError):
|
||||
ipautil.run([paths.ECHO, b'\xa0\xa1'],
|
||||
capture_output=True,
|
||||
encoding='utf-8')
|
||||
else:
|
||||
result = ipautil.run([paths.ECHO, '\xa0\xa1'],
|
||||
capture_output=True,
|
||||
encoding='utf-8')
|
||||
assert result.returncode == 0
|
||||
assert result.output == '\xa0\xa1\n'
|
||||
|
||||
|
||||
def test_backcompat():
|
||||
result = out, err, rc = ipautil.run([paths.ECHO, 'foo\x02bar'],
|
||||
capture_output=True,
|
||||
capture_error=True)
|
||||
assert rc is result.returncode
|
||||
assert out is result.output
|
||||
assert err is result.error_output
|
||||
|
||||
|
||||
def test_flush_sync():
|
||||
with tempfile.NamedTemporaryFile('wb+') as f:
|
||||
f.write(b'data')
|
||||
ipautil.flush_sync(f)
|
||||
|
||||
|
||||
def test_run_stderr():
|
||||
args = [
|
||||
sys.executable, '-c',
|
||||
'import sys; sys.exit(" ".join(("error", "message")))'
|
||||
]
|
||||
|
||||
with pytest.raises(ipautil.CalledProcessError) as cm:
|
||||
ipautil.run(args)
|
||||
|
||||
assert cm.value.cmd == repr(args)
|
||||
assert cm.value.stderr == "error message\n"
|
||||
assert "CalledProcessError(" in str(cm.value)
|
||||
assert repr(args) in str(cm.value)
|
||||
assert str(cm.value).endswith("'error message\\n')")
|
||||
|
||||
with pytest.raises(ipautil.CalledProcessError) as cm:
|
||||
ipautil.run(args, nolog=["message"])
|
||||
|
||||
assert cm.value.cmd == repr(args).replace("message", "XXXXXXXX")
|
||||
assert str(cm.value).endswith("'error XXXXXXXX\\n')")
|
||||
assert "message" not in str(cm.value)
|
||||
assert "message" not in str(cm.value.output)
|
||||
assert "message" not in str(cm.value.stderr)
|
||||
|
||||
|
||||
@pytest.mark.skipif(os.geteuid() != 0,
|
||||
reason="Must have root privileges to run this test")
|
||||
def test_run_runas():
|
||||
"""
|
||||
Test run method with the runas parameter.
|
||||
The test executes 'id' to make sure that the process is
|
||||
executed with the user identity specified in runas parameter.
|
||||
The test is using 'ipaapi' user as it is configured when
|
||||
ipa-server-common package is installed.
|
||||
"""
|
||||
user = pwd.getpwnam(IPAAPI_USER)
|
||||
res = ipautil.run(['/usr/bin/id', '-u'], runas=IPAAPI_USER)
|
||||
assert res.returncode == 0
|
||||
assert res.raw_output == b'%d\n' % user.pw_uid
|
||||
|
||||
res = ipautil.run(['/usr/bin/id', '-g'], runas=IPAAPI_USER)
|
||||
assert res.returncode == 0
|
||||
assert res.raw_output == b'%d\n' % user.pw_gid
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def tcp_listen():
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
try:
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
|
||||
# port 0 means the OS selects a random, unused port for the test.
|
||||
s.bind(('', 0))
|
||||
s.listen(1)
|
||||
yield s.getsockname()[-1], s
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def udp_listen():
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
try:
|
||||
# port 0 means the OS selects a random, unused port for the test.
|
||||
s.bind(('', 0))
|
||||
yield s.getsockname()[-1], s
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
|
||||
def test_check_port_bindable_tcp(tcp_listen):
|
||||
port, sock = tcp_listen
|
||||
assert not ipautil.check_port_bindable(port)
|
||||
assert not ipautil.check_port_bindable(port, socket.SOCK_STREAM)
|
||||
sock.close()
|
||||
assert ipautil.check_port_bindable(port)
|
||||
|
||||
|
||||
def test_check_port_bindable_udp(udp_listen):
|
||||
port, sock = udp_listen
|
||||
assert not ipautil.check_port_bindable(port, socket.SOCK_DGRAM)
|
||||
sock.close()
|
||||
assert ipautil.check_port_bindable(port, socket.SOCK_DGRAM)
|
||||
|
||||
|
||||
def test_config_replace_variables(tempdir):
|
||||
conffile = os.path.join(tempdir, 'test.conf')
|
||||
|
||||
conf = textwrap.dedent("""
|
||||
replaced=foo
|
||||
removed=gone
|
||||
""")
|
||||
expected = textwrap.dedent("""
|
||||
replaced=bar
|
||||
addreplaced=baz
|
||||
""")
|
||||
|
||||
with open(conffile, 'w') as f:
|
||||
f.write(conf)
|
||||
|
||||
result = ipautil.config_replace_variables(
|
||||
conffile,
|
||||
replacevars=dict(replaced="bar", addreplaced="baz"),
|
||||
removevars={'removed'}
|
||||
)
|
||||
assert result == {
|
||||
'removed': 'gone', 'replaced': 'foo'
|
||||
}
|
||||
|
||||
with open(conffile, 'r') as f:
|
||||
newconf = f.read()
|
||||
assert newconf == expected
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#! /usr/bin/python2 -E
|
||||
#
|
||||
# Copyright (C) 2007 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
@@ -20,78 +19,72 @@
|
||||
import sys
|
||||
sys.path.insert(0, ".")
|
||||
|
||||
import unittest
|
||||
import pytest
|
||||
|
||||
from ipapython import ipavalidate
|
||||
|
||||
class TestValidate(unittest.TestCase):
|
||||
def setUp(self):
|
||||
pass
|
||||
pytestmark = pytest.mark.tier0
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
class TestValidate:
|
||||
def test_validEmail(self):
|
||||
self.assertEqual(True, ipavalidate.Email("test@freeipa.org"))
|
||||
self.assertEqual(True, ipavalidate.Email("", notEmpty=False))
|
||||
assert ipavalidate.Email("test@freeipa.org") is True
|
||||
assert ipavalidate.Email("", notEmpty=False) is True
|
||||
|
||||
def test_invalidEmail(self):
|
||||
self.assertEqual(False, ipavalidate.Email("test"))
|
||||
self.assertEqual(False, ipavalidate.Email("test@freeipa"))
|
||||
self.assertEqual(False, ipavalidate.Email("test@.com"))
|
||||
self.assertEqual(False, ipavalidate.Email(""))
|
||||
self.assertEqual(False, ipavalidate.Email(None))
|
||||
assert ipavalidate.Email("test") is False
|
||||
assert ipavalidate.Email("test@freeipa") is False
|
||||
assert ipavalidate.Email("test@.com") is False
|
||||
assert ipavalidate.Email("") is False
|
||||
assert ipavalidate.Email(None) is False
|
||||
|
||||
def test_validPlain(self):
|
||||
self.assertEqual(True, ipavalidate.Plain("Joe User"))
|
||||
self.assertEqual(True, ipavalidate.Plain("Joe O'Malley"))
|
||||
self.assertEqual(True, ipavalidate.Plain("", notEmpty=False))
|
||||
self.assertEqual(True, ipavalidate.Plain(None, notEmpty=False))
|
||||
self.assertEqual(True, ipavalidate.Plain("JoeUser", allowSpaces=False))
|
||||
self.assertEqual(True, ipavalidate.Plain("JoeUser", allowSpaces=True))
|
||||
assert ipavalidate.Plain("Joe User") is True
|
||||
assert ipavalidate.Plain("Joe O'Malley") is True
|
||||
assert ipavalidate.Plain("", notEmpty=False) is True
|
||||
assert ipavalidate.Plain(None, notEmpty=False) is True
|
||||
assert ipavalidate.Plain("JoeUser", allowSpaces=False) is True
|
||||
assert ipavalidate.Plain("JoeUser", allowSpaces=True) is True
|
||||
|
||||
def test_invalidPlain(self):
|
||||
self.assertEqual(False, ipavalidate.Plain("Joe (User)"))
|
||||
self.assertEqual(False, ipavalidate.Plain("Joe C. User"))
|
||||
self.assertEqual(False, ipavalidate.Plain("", notEmpty=True))
|
||||
self.assertEqual(False, ipavalidate.Plain(None, notEmpty=True))
|
||||
self.assertEqual(False, ipavalidate.Plain("Joe User", allowSpaces=False))
|
||||
self.assertEqual(False, ipavalidate.Plain("Joe C. User"))
|
||||
assert ipavalidate.Plain("Joe (User)") is False
|
||||
assert ipavalidate.Plain("Joe C. User") is False
|
||||
assert ipavalidate.Plain("", notEmpty=True) is False
|
||||
assert ipavalidate.Plain(None, notEmpty=True) is False
|
||||
assert ipavalidate.Plain("Joe User", allowSpaces=False) is False
|
||||
assert ipavalidate.Plain("Joe C. User") is False
|
||||
|
||||
def test_validString(self):
|
||||
self.assertEqual(True, ipavalidate.String("Joe User"))
|
||||
self.assertEqual(True, ipavalidate.String("Joe O'Malley"))
|
||||
self.assertEqual(True, ipavalidate.String("", notEmpty=False))
|
||||
self.assertEqual(True, ipavalidate.String(None, notEmpty=False))
|
||||
self.assertEqual(True, ipavalidate.String("Joe C. User"))
|
||||
assert ipavalidate.String("Joe User") is True
|
||||
assert ipavalidate.String("Joe O'Malley") is True
|
||||
assert ipavalidate.String("", notEmpty=False) is True
|
||||
assert ipavalidate.String(None, notEmpty=False) is True
|
||||
assert ipavalidate.String("Joe C. User") is True
|
||||
|
||||
def test_invalidString(self):
|
||||
self.assertEqual(False, ipavalidate.String("", notEmpty=True))
|
||||
self.assertEqual(False, ipavalidate.String(None, notEmpty=True))
|
||||
assert ipavalidate.String("", notEmpty=True) is False
|
||||
assert ipavalidate.String(None, notEmpty=True) is False
|
||||
|
||||
def test_validPath(self):
|
||||
self.assertEqual(True, ipavalidate.Path("/"))
|
||||
self.assertEqual(True, ipavalidate.Path("/home/user"))
|
||||
self.assertEqual(True, ipavalidate.Path("../home/user"))
|
||||
self.assertEqual(True, ipavalidate.Path("", notEmpty=False))
|
||||
self.assertEqual(True, ipavalidate.Path(None, notEmpty=False))
|
||||
assert ipavalidate.Path("/") is True
|
||||
assert ipavalidate.Path("/home/user") is True
|
||||
assert ipavalidate.Path("../home/user") is True
|
||||
assert ipavalidate.Path("", notEmpty=False) is True
|
||||
assert ipavalidate.Path(None, notEmpty=False) is True
|
||||
|
||||
def test_invalidPath(self):
|
||||
self.assertEqual(False, ipavalidate.Path("(foo)"))
|
||||
self.assertEqual(False, ipavalidate.Path("", notEmpty=True))
|
||||
self.assertEqual(False, ipavalidate.Path(None, notEmpty=True))
|
||||
assert ipavalidate.Path("(foo)") is False
|
||||
assert ipavalidate.Path("", notEmpty=True) is False
|
||||
assert ipavalidate.Path(None, notEmpty=True) is False
|
||||
|
||||
def test_validName(self):
|
||||
self.assertEqual(True, ipavalidate.GoodName("foo"))
|
||||
self.assertEqual(True, ipavalidate.GoodName("1foo"))
|
||||
self.assertEqual(True, ipavalidate.GoodName("foo.bar"))
|
||||
self.assertEqual(True, ipavalidate.GoodName("foo.bar$"))
|
||||
assert ipavalidate.GoodName("foo") is True
|
||||
assert ipavalidate.GoodName("1foo") is True
|
||||
assert ipavalidate.GoodName("foo.bar") is True
|
||||
assert ipavalidate.GoodName("foo.bar$") is True
|
||||
|
||||
def test_invalidName(self):
|
||||
self.assertEqual(False, ipavalidate.GoodName("foo bar"))
|
||||
self.assertEqual(False, ipavalidate.GoodName("foo%bar"))
|
||||
self.assertEqual(False, ipavalidate.GoodName("*foo"))
|
||||
self.assertEqual(False, ipavalidate.GoodName("$foo.bar$"))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
assert ipavalidate.GoodName("foo bar") is False
|
||||
assert ipavalidate.GoodName("foo%bar") is False
|
||||
assert ipavalidate.GoodName("*foo") is False
|
||||
assert ipavalidate.GoodName("$foo.bar$") is False
|
||||
|
||||
139
ipatests/test_ipapython/test_kerberos.py
Normal file
139
ipatests/test_ipapython/test_kerberos.py
Normal file
@@ -0,0 +1,139 @@
|
||||
#
|
||||
# Copyright (C) 2016 FreeIPA Project Contributors - see LICENSE file
|
||||
#
|
||||
|
||||
import pytest
|
||||
import six
|
||||
|
||||
from ipapython.kerberos import Principal
|
||||
|
||||
if six.PY3:
|
||||
unicode = str
|
||||
|
||||
valid_principals = {
|
||||
u'tuser@REALM.TEST': {
|
||||
'components': (u'tuser',),
|
||||
'realm': u'REALM.TEST',
|
||||
'username': u'tuser'
|
||||
},
|
||||
u'tuser\\@tupn.test@REALM.TEST': {
|
||||
'components': (u'tuser@tupn.test',),
|
||||
'realm': u'REALM.TEST',
|
||||
'username': u'tuser@tupn.test',
|
||||
'upn_suffix': u'tupn.test'
|
||||
},
|
||||
u'test/host.ipa.test@REALM.TEST': {
|
||||
'components': (u'test', u'host.ipa.test'),
|
||||
'realm': u'REALM.TEST',
|
||||
'hostname': u'host.ipa.test'
|
||||
},
|
||||
u'test/service/host.ipa.test@REALM.TEST': {
|
||||
'components': (u'test', u'service', u'host.ipa.test'),
|
||||
'realm': u'REALM.TEST',
|
||||
'service_name': u'test/service'
|
||||
|
||||
},
|
||||
u'tuser': {
|
||||
'components': (u'tuser',),
|
||||
'realm': None,
|
||||
'username': u'tuser'
|
||||
},
|
||||
u'$%user@REALM.TEST': {
|
||||
'components': (u'$%user',),
|
||||
'realm': u'REALM.TEST',
|
||||
'username': u'$%user'
|
||||
},
|
||||
u'host/host.ipa.test': {
|
||||
'components': (u'host', u'host.ipa.test'),
|
||||
'realm': None,
|
||||
'hostname': u'host.ipa.test'
|
||||
},
|
||||
u's$c/$%^.ipa.t%$t': {
|
||||
'components': (u's$c', u'$%^.ipa.t%$t'),
|
||||
'realm': None,
|
||||
'hostname': u'$%^.ipa.t%$t',
|
||||
'service_name': u's$c'
|
||||
},
|
||||
u'test\\/service/test\\/host@REALM\\@TEST': {
|
||||
'components': (u'test/service', u'test/host'),
|
||||
'realm': u'REALM@TEST',
|
||||
'hostname': u'test/host',
|
||||
'service_name': r'test\/service'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def valid_principal_iter(principals):
|
||||
for princ, data in principals.items():
|
||||
yield princ, data
|
||||
|
||||
|
||||
@pytest.fixture(params=list(valid_principal_iter(valid_principals)))
|
||||
def valid_principal(request):
|
||||
return request.param
|
||||
|
||||
|
||||
def test_principals(valid_principal):
|
||||
principal_name, data = valid_principal
|
||||
|
||||
princ = Principal(principal_name)
|
||||
|
||||
for name, value in data.items():
|
||||
assert getattr(princ, name) == value
|
||||
|
||||
assert unicode(princ) == principal_name
|
||||
assert repr(princ) == "ipapython.kerberos.Principal('{}')".format(
|
||||
principal_name)
|
||||
|
||||
|
||||
def test_multiple_unescaped_ats_raise_error():
|
||||
pytest.raises(ValueError, Principal, u'too@many@realms')
|
||||
|
||||
|
||||
principals_properties = {
|
||||
u'user@REALM': {
|
||||
'property_true': ('is_user',),
|
||||
'property_raises': ('upn_suffix', 'hostname', 'service_name')
|
||||
},
|
||||
u'host/m1.ipa.test@REALM': {
|
||||
'property_true': ('is_host', 'is_service'),
|
||||
'property_raises': ('username', 'upn_suffix')
|
||||
},
|
||||
u'service/m1.ipa.test@REALM': {
|
||||
'property_true': ('is_service'),
|
||||
'property_raises': ('username', 'upn_suffix')
|
||||
},
|
||||
u'user\\@domain@REALM': {
|
||||
'property_true': ('is_user', 'is_enterprise'),
|
||||
'property_raises': ('hostname', 'service_name')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def principal_properties_iter(principals_properties):
|
||||
for p, data in principals_properties.items():
|
||||
yield p, data
|
||||
|
||||
|
||||
@pytest.fixture(params=list(principal_properties_iter(principals_properties)))
|
||||
def principal_properties(request):
|
||||
return request.param
|
||||
|
||||
|
||||
def test_principal_properties(principal_properties):
|
||||
principal, data = principal_properties
|
||||
|
||||
princ = Principal(principal)
|
||||
|
||||
boolean_propertes = [prop for prop in dir(princ) if
|
||||
prop.startswith('is_')]
|
||||
|
||||
for b in boolean_propertes:
|
||||
if b in data['property_true']:
|
||||
assert getattr(princ, b)
|
||||
else:
|
||||
assert not getattr(princ, b)
|
||||
|
||||
for property_raises in data['property_raises']:
|
||||
with pytest.raises(ValueError):
|
||||
getattr(princ, property_raises)
|
||||
@@ -20,23 +20,32 @@
|
||||
Test the `kernel_keyring.py` module.
|
||||
"""
|
||||
|
||||
from nose.tools import raises, assert_raises # pylint: disable=E0611
|
||||
from ipapython import kernel_keyring
|
||||
|
||||
import pytest
|
||||
|
||||
pytestmark = pytest.mark.tier0
|
||||
|
||||
TEST_KEY = 'ipa_test'
|
||||
TEST_VALUE = 'abc123'
|
||||
UPDATE_VALUE = '123abc'
|
||||
TEST_UNICODEKEY = u'ipa_unicode'
|
||||
TEST_VALUE = b'abc123'
|
||||
UPDATE_VALUE = b'123abc'
|
||||
|
||||
SIZE_256 = 'abcdefgh' * 32
|
||||
SIZE_512 = 'abcdefgh' * 64
|
||||
SIZE_1024 = 'abcdefgh' * 128
|
||||
|
||||
class test_keyring(object):
|
||||
|
||||
@pytest.mark.skip_if_container(
|
||||
"any", reason="kernel keyrings are not namespaced yet"
|
||||
)
|
||||
class test_keyring:
|
||||
"""
|
||||
Test the kernel keyring interface
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
@pytest.fixture(autouse=True)
|
||||
def keyring_setup(self):
|
||||
try:
|
||||
kernel_keyring.del_key(TEST_KEY)
|
||||
except ValueError:
|
||||
@@ -45,6 +54,10 @@ class test_keyring(object):
|
||||
kernel_keyring.del_key(SIZE_256)
|
||||
except ValueError:
|
||||
pass
|
||||
try:
|
||||
kernel_keyring.del_key(TEST_UNICODEKEY)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
def test_01(self):
|
||||
"""
|
||||
@@ -59,8 +72,8 @@ class test_keyring(object):
|
||||
# Make sure it is gone
|
||||
try:
|
||||
result = kernel_keyring.read_key(TEST_KEY)
|
||||
except ValueError, e:
|
||||
assert e.message == 'key %s not found' % TEST_KEY
|
||||
except ValueError as e:
|
||||
assert str(e) == 'key %s not found' % TEST_KEY
|
||||
|
||||
def test_02(self):
|
||||
"""
|
||||
@@ -72,13 +85,13 @@ class test_keyring(object):
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
@raises(ValueError)
|
||||
def test_03(self):
|
||||
"""
|
||||
Add a duplicate key
|
||||
"""
|
||||
kernel_keyring.add_key(TEST_KEY, TEST_VALUE)
|
||||
kernel_keyring.add_key(TEST_KEY, TEST_VALUE)
|
||||
with pytest.raises(ValueError):
|
||||
kernel_keyring.add_key(TEST_KEY, TEST_VALUE)
|
||||
|
||||
def test_04(self):
|
||||
"""
|
||||
@@ -89,32 +102,30 @@ class test_keyring(object):
|
||||
assert(result == UPDATE_VALUE)
|
||||
|
||||
# Now update it 10 times
|
||||
for i in xrange(10):
|
||||
kernel_keyring.update_key(TEST_KEY, 'test %d' % i)
|
||||
for i in range(10):
|
||||
value = ('test %d' % i).encode('ascii')
|
||||
kernel_keyring.update_key(TEST_KEY, value)
|
||||
result = kernel_keyring.read_key(TEST_KEY)
|
||||
assert(result == 'test %d' % i)
|
||||
assert(result == value)
|
||||
|
||||
kernel_keyring.del_key(TEST_KEY)
|
||||
|
||||
@raises(ValueError)
|
||||
def test_05(self):
|
||||
"""
|
||||
Read a non-existent key
|
||||
"""
|
||||
result = kernel_keyring.read_key(TEST_KEY)
|
||||
with pytest.raises(ValueError):
|
||||
kernel_keyring.read_key(TEST_KEY)
|
||||
|
||||
def test_06(self):
|
||||
"""
|
||||
See if a key is available
|
||||
"""
|
||||
kernel_keyring.add_key(TEST_KEY, TEST_VALUE)
|
||||
assert kernel_keyring.has_key(TEST_KEY) # noqa
|
||||
|
||||
result = kernel_keyring.has_key(TEST_KEY)
|
||||
assert(result == True)
|
||||
kernel_keyring.del_key(TEST_KEY)
|
||||
|
||||
result = kernel_keyring.has_key(TEST_KEY)
|
||||
assert(result == False)
|
||||
assert not kernel_keyring.has_key(TEST_KEY) # noqa
|
||||
|
||||
def test_07(self):
|
||||
"""
|
||||
@@ -130,9 +141,9 @@ class test_keyring(object):
|
||||
"""
|
||||
Test 512-bytes of data
|
||||
"""
|
||||
kernel_keyring.add_key(TEST_KEY, SIZE_512)
|
||||
kernel_keyring.add_key(TEST_KEY, SIZE_512.encode('ascii'))
|
||||
result = kernel_keyring.read_key(TEST_KEY)
|
||||
assert(result == SIZE_512)
|
||||
assert(result == SIZE_512.encode('ascii'))
|
||||
|
||||
kernel_keyring.del_key(TEST_KEY)
|
||||
|
||||
@@ -140,8 +151,18 @@ class test_keyring(object):
|
||||
"""
|
||||
Test 1k bytes of data
|
||||
"""
|
||||
kernel_keyring.add_key(TEST_KEY, SIZE_1024)
|
||||
kernel_keyring.add_key(TEST_KEY, SIZE_1024.encode('ascii'))
|
||||
result = kernel_keyring.read_key(TEST_KEY)
|
||||
assert(result == SIZE_1024)
|
||||
assert(result == SIZE_1024.encode('ascii'))
|
||||
|
||||
kernel_keyring.del_key(TEST_KEY)
|
||||
|
||||
def test_10(self):
|
||||
"""
|
||||
Test a unicode key
|
||||
"""
|
||||
kernel_keyring.add_key(TEST_UNICODEKEY, TEST_VALUE)
|
||||
result = kernel_keyring.read_key(TEST_UNICODEKEY)
|
||||
assert(result == TEST_VALUE)
|
||||
|
||||
kernel_keyring.del_key(TEST_UNICODEKEY)
|
||||
|
||||
41
ipatests/test_ipapython/test_session_storage.py
Normal file
41
ipatests/test_ipapython/test_session_storage.py
Normal file
@@ -0,0 +1,41 @@
|
||||
#
|
||||
# Copyright (C) 2017 FreeIPA Contributors see COPYING for license
|
||||
#
|
||||
|
||||
"""
|
||||
Test the `session_storage.py` module.
|
||||
"""
|
||||
import pytest
|
||||
|
||||
from ipapython import session_storage
|
||||
|
||||
|
||||
@pytest.mark.skip_ipaclient_unittest
|
||||
@pytest.mark.needs_ipaapi
|
||||
class test_session_storage:
|
||||
"""
|
||||
Test the session storage interface
|
||||
"""
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def session_storage_setup(self):
|
||||
# TODO: set up test user and kinit to it
|
||||
# tmpdir = tempfile.mkdtemp(prefix = "tmp-")
|
||||
# os.environ['KRB5CCNAME'] = 'FILE:%s/ccache' % tmpdir
|
||||
self.principal = 'admin'
|
||||
self.key = 'X-IPA-test-session-storage'
|
||||
self.data = b'Test Data'
|
||||
|
||||
def test_01(self):
|
||||
session_storage.store_data(self.principal, self.key, self.data)
|
||||
|
||||
def test_02(self):
|
||||
data = session_storage.get_data(self.principal, self.key)
|
||||
assert(data == self.data)
|
||||
|
||||
def test_03(self):
|
||||
session_storage.remove_data(self.principal, self.key)
|
||||
try:
|
||||
session_storage.get_data(self.principal, self.key)
|
||||
except session_storage.KRB5Error:
|
||||
pass
|
||||
@@ -21,56 +21,67 @@ Test the `ipapython/ssh.py` module.
|
||||
"""
|
||||
|
||||
import base64
|
||||
import nose
|
||||
|
||||
import six
|
||||
import pytest
|
||||
|
||||
from ipapython import ssh
|
||||
|
||||
class CheckPublicKey:
|
||||
def __init__(self, pk):
|
||||
self.description = "Test SSH public key parsing (%s)" % repr(pk)
|
||||
if six.PY3:
|
||||
unicode = str
|
||||
|
||||
def __call__(self, pk, out):
|
||||
try:
|
||||
parsed = ssh.SSHPublicKey(pk)
|
||||
assert parsed.openssh() == out
|
||||
except Exception, e:
|
||||
assert type(e) is out
|
||||
pytestmark = pytest.mark.tier0
|
||||
|
||||
def test_public_key_parsing():
|
||||
b64 = 'AAAAB3NzaC1yc2EAAAADAQABAAABAQDGAX3xAeLeaJggwTqMjxNwa6XHBUAikXPGMzEpVrlLDCZtv00djsFTBi38PkgxBJVkgRWMrcBsr/35lq7P6w8KGIwA8GI48Z0qBS2NBMJ2u9WQ2hjLN6GdMlo77O0uJY3251p12pCVIS/bHRSq8kHO2No8g7KA9fGGcagPfQH+ee3t7HUkpbQkFTmbPPN++r3V8oVUk5LxbryB3UIIVzNmcSIn3JrXynlvui4MixvrtX6zx+O/bBo68o8/eZD26QrahVbA09fivrn/4h3TM019Eu/c2jOdckfU3cHUV/3Tno5d6JicibyaoDDK7S/yjdn5jhaz8MSEayQvFkZkiF0L'
|
||||
raw = base64.b64decode(b64)
|
||||
openssh = 'ssh-rsa %s' % b64
|
||||
b64 = 'AAAAB3NzaC1yc2EAAAADAQABAAABAQDGAX3xAeLeaJggwTqMjxNwa6XHBUAikXPGMzEpVrlLDCZtv00djsFTBi38PkgxBJVkgRWMrcBsr/35lq7P6w8KGIwA8GI48Z0qBS2NBMJ2u9WQ2hjLN6GdMlo77O0uJY3251p12pCVIS/bHRSq8kHO2No8g7KA9fGGcagPfQH+ee3t7HUkpbQkFTmbPPN++r3V8oVUk5LxbryB3UIIVzNmcSIn3JrXynlvui4MixvrtX6zx+O/bBo68o8/eZD26QrahVbA09fivrn/4h3TM019Eu/c2jOdckfU3cHUV/3Tno5d6JicibyaoDDK7S/yjdn5jhaz8MSEayQvFkZkiF0L'
|
||||
raw = base64.b64decode(b64)
|
||||
openssh = 'ssh-rsa %s' % b64
|
||||
|
||||
pks = [
|
||||
('\xff', UnicodeDecodeError),
|
||||
|
||||
(raw, openssh),
|
||||
('\0\0\0\x04none', u'none AAAABG5vbmU='),
|
||||
('\0\0\0', ValueError),
|
||||
('\0\0\0\0', ValueError),
|
||||
('\0\0\0\x01', ValueError),
|
||||
('\0\0\0\x01\xff', ValueError),
|
||||
@pytest.mark.parametrize("pk,out", [
|
||||
(b'\xff', UnicodeDecodeError),
|
||||
(u'\xff', ValueError),
|
||||
|
||||
(b64, openssh),
|
||||
(unicode(b64), openssh),
|
||||
(u'\n%s\n\n' % b64, openssh),
|
||||
(u'AAAABG5vbmU=', u'none AAAABG5vbmU='),
|
||||
(u'AAAAB', ValueError),
|
||||
(raw, openssh),
|
||||
(b'\0\0\0\x04none', u'none AAAABG5vbmU='),
|
||||
(b'\0\0\0', ValueError),
|
||||
(b'\0\0\0\0', ValueError),
|
||||
(b'\0\0\0\x01', ValueError),
|
||||
(b'\0\0\0\x01\xff', ValueError),
|
||||
|
||||
(openssh, openssh),
|
||||
(unicode(openssh), openssh),
|
||||
(u'none AAAABG5vbmU=', u'none AAAABG5vbmU='),
|
||||
(u'\t \t ssh-rsa \t \t%s\t \tthis is a comment\t \t ' % b64,
|
||||
u'%s this is a comment' % openssh),
|
||||
(u'opt3,opt2="\tx ",opt1,opt2="\\"x " %s comment ' % openssh,
|
||||
u'opt1,opt2="\\"x ",opt3 %s comment' % openssh),
|
||||
(u'ssh-rsa\n%s' % b64, ValueError),
|
||||
(u'ssh-rsa\t%s' % b64, ValueError),
|
||||
(u'vanitas %s' % b64, ValueError),
|
||||
(u'@opt %s' % openssh, ValueError),
|
||||
(u'opt=val %s' % openssh, ValueError),
|
||||
(u'opt, %s' % openssh, ValueError),
|
||||
]
|
||||
(u'\0\0\0\x04none', ValueError),
|
||||
(u'\0\0\0', ValueError),
|
||||
(u'\0\0\0\0', ValueError),
|
||||
(u'\0\0\0\x01', ValueError),
|
||||
(u'\0\0\0\x01\xff', ValueError),
|
||||
|
||||
for pk in pks:
|
||||
yield (CheckPublicKey(pk[0]),) + pk
|
||||
(b64, openssh),
|
||||
(unicode(b64), openssh),
|
||||
(b64.encode('ascii'), openssh),
|
||||
(u'\n%s\n\n' % b64, openssh),
|
||||
(u'AAAABG5vbmU=', u'none AAAABG5vbmU='),
|
||||
(u'AAAAB', ValueError),
|
||||
|
||||
(openssh, openssh),
|
||||
(unicode(openssh), openssh),
|
||||
(openssh.encode('ascii'), openssh),
|
||||
(u'none AAAABG5vbmU=', u'none AAAABG5vbmU='),
|
||||
(u'\t \t ssh-rsa \t \t%s\t \tthis is a comment\t \t ' % b64,
|
||||
u'%s this is a comment' % openssh),
|
||||
(u'opt3,opt2="\tx ",opt1,opt2="\\"x " %s comment ' % openssh,
|
||||
u'opt1,opt2="\\"x ",opt3 %s comment' % openssh),
|
||||
(u'ssh-rsa\n%s' % b64, ValueError),
|
||||
(u'ssh-rsa\t%s' % b64, ValueError),
|
||||
(u'vanitas %s' % b64, ValueError),
|
||||
(u'@opt %s' % openssh, ValueError),
|
||||
(u'opt=val %s' % openssh, ValueError),
|
||||
(u'opt, %s' % openssh, ValueError)],
|
||||
# ids=repr is workaround for pytest issue with NULL bytes,
|
||||
# see https://github.com/pytest-dev/pytest/issues/2644
|
||||
ids=repr
|
||||
)
|
||||
def test_public_key_parsing(pk, out):
|
||||
if isinstance(out, type) and issubclass(out, Exception):
|
||||
pytest.raises(out, ssh.SSHPublicKey, pk)
|
||||
else:
|
||||
parsed = ssh.SSHPublicKey(pk)
|
||||
assert parsed.openssh() == out
|
||||
|
||||
Reference in New Issue
Block a user