#!/usr/bin/env python
#
# Revelation 0.4.1 - a password manager for GNOME 2
# http://oss.codepoet.no/revelation/
# $Id$
#
# Unit tests for util module
#
#
# Copyright (c) 2003-2005 Erik Grinaker
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
import os, sys, time, unittest, xml.dom.minidom
from revelation import util
class dom_text(unittest.TestCase):
"dom_text()"
def test_children(self):
"dom_text() ignores children"
dom = xml.dom.minidom.parseString("test123test")
self.assertEquals(util.dom_text(dom.documentElement), "testtest")
def test_text(self):
"dom_text() returns text contents"
dom = xml.dom.minidom.parseString("test123")
self.assertEquals(util.dom_text(dom.documentElement), "test123")
def test_whitespace(self):
"dom_text() preserves whitespace"
dom = xml.dom.minidom.parseString("\n\ttest123 \n")
self.assertEquals(util.dom_text(dom.documentElement), "\n\ttest123 \n")
class escape_markup(unittest.TestCase):
"escape_markup()"
def test_amp(self):
"escape_markup() replaces & with &"
self.assertEqual(
util.escape_markup("test&123"),
"test&123".replace("&", "&")
)
def test_gt(self):
"escape_markup() replaces > with >"
self.assertEqual(
util.escape_markup("test>123"),
"test>123".replace(">", ">")
)
def test_lt(self):
"escape_markup() replaces < with <"
self.assertEqual(
util.escape_markup("test<123"),
"test<123".replace("<", "<")
)
class execute(unittest.TestCase):
"execute()"
def test_output(self):
"execute() returns output"
self.assertEqual(util.execute("echo -n test123")[0], "test123")
def test_run(self):
"execute() runs command"
if os.access("/tmp/exectest", os.F_OK):
os.unlink("/tmp/exectest")
util.execute("touch /tmp/exectest")
self.assertEqual(os.access("/tmp/exectest", os.F_OK), True)
def test_status(self):
"execute() returns status code"
self.assertEqual(util.execute("exit 0")[1], 0)
self.assertEqual(util.execute("exit 1")[1], 1)
self.assertEqual(util.execute("exit 52")[1], 52)
class execute_child(unittest.TestCase):
"execute_child()"
def test_nowait(self):
"execute_child() doesn't wait"
start = time.time()
util.execute_child("sleep 2")
self.assertEqual(start > time.time() - 1, True)
def test_pid(self):
"execute_child() returns process id"
pid = util.execute_child("sleep 1")
waitdata = os.waitpid(pid, 0)
self.assertEqual(pid, waitdata[0])
def test_run(self):
"execute_child() runs command"
if os.access("/tmp/exectest", os.F_OK):
os.unlink("/tmp/exectest")
util.execute_child("touch /tmp/exectest")
time.sleep(1)
self.assertEqual(os.access("/tmp/exectest", os.F_OK), True)
class generate_password(unittest.TestCase):
"generate_password()"
def test_ambiguous(self):
"generate_password() avoids ambiguous chars when told"
for i in range(100):
password = util.generate_password(256, True)
for char in "0OIl1S5qg":
self.assertEqual(
char in password,
False
)
def test_digits(self):
"generate_password() always includes a digit"
for i in range(100):
for char in util.generate_password(8):
if char.isdigit():
digit = True
break
else:
digit = False
self.assertEqual(digit, True)
def test_length(self):
"generate_password() returns string of correct length"
for length in 1, 5, 17, 54, 270:
self.assertEqual(
len(util.generate_password(length)),
length
)
def test_lowercase(self):
"generate_password() always includes a lowercase char"
for i in range(100):
for char in util.generate_password(8):
if char.islower():
lower = True
break
else:
lower = False
self.assertEqual(lower, True)
def test_random(self):
"generate_password() returns random string"
for i in range(3):
self.assertNotEqual(
util.generate_password(8),
util.generate_password(8)
)
def test_uppercase(self):
"generate_password() always includes an uppercase char"
for i in range(100):
for char in util.generate_password(8):
if char.isupper():
upper = True
break
else:
upper = False
self.assertEqual(upper, True)
class pad_right(unittest.TestCase):
"pad_right()"
def test_longstring(self):
"pad_right() returns entire string when too long"
self.assertEquals(util.pad_right("jeje123", 5), "jeje123")
def test_none(self):
"pad_right() returns None when passed None"
self.assertEquals(util.pad_right(None, 10), None)
def test_pad(self):
"pad_right() pads correctly"
self.assertEquals(util.pad_right("jeje123", 10, "a"), "jeje123aaa")
class parse_subst(unittest.TestCase):
"parse_subst()"
def test_complex(self):
"parse_subst() handles complex expressions"
map = {
"u" : "erikg",
"p" : "",
"h" : "localhost",
"d" : "test",
"D" : ""
}
s = "/usr/bin/mysql %(-u %u%) %(--password=%p%) %(-H %h%) %d %?D"
r = "/usr/bin/mysql -u erikg -H localhost test "
self.assertEquals(util.parse_subst(s, map), r)
def test_empty(self):
"parse_subst() handles empty strings"
self.assertEquals(util.parse_subst("", {}), "")
def test_inv_var(self):
"parse_subst() raises SubstFormatError on unknown variable"
self.assertRaises(util.SubstFormatError, util.parse_subst, "test %a 123", { "b": "item" })
self.assertRaises(util.SubstFormatError, util.parse_subst, "test %?a 123", { "b": "item" })
self.assertRaises(util.SubstFormatError, util.parse_subst, "test%( %a%) 123", { "b": "item" })
def test_inv_value(self):
"parse_subst() raises SubstValueError on empty variable value"
self.assertRaises(util.SubstValueError, util.parse_subst, "test %a 123", { "a": "" })
def test_inv_substring(self):
"parse_subst() raises FormatError on non-closed substring"
self.assertRaises(util.SubstFormatError, util.parse_subst, "test%( %a 123", { "b": "item" })
def test_escape(self):
"parse_subst() handles % escapes"
self.assertEquals(util.parse_subst("te%%st", {}), "te%st")
def test_normal(self):
"parse_subst() ignores normal characters"
s = "aBidU&72!78>,-4=*`-fui(Hd"
self.assertEquals(util.parse_subst(s, {}), s)
def test_optional(self):
"parse_subst() handles optional variables"
self.assertEquals(
util.parse_subst(
"test %a %?b 123",
{ "a" : "item", "b" : "" }
),
"test item 123"
)
self.assertEquals(
util.parse_subst(
"test %a %?b 123",
{ "a" : "item", "b" : "optional" }
),
"test item optional 123"
)
def test_subst(self):
"parse_subst() handles variable expansion"
self.assertEquals(
util.parse_subst(
"test %a %b 123",
{ "a" : "item", "b" : "item2" }
),
"test item item2 123"
)
def test_substring(self):
"parse_subst() handles substring expansion"
self.assertEquals(
util.parse_subst(
"test %a%( %b %%%) 123",
{ "a" : "item", "b" : "" }
),
"test item 123"
)
self.assertEquals(
util.parse_subst(
"test %a%( %b %%%) 123",
{ "a" : "item", "b" : "optional" }
),
"test item optional % 123"
)
class random_string(unittest.TestCase):
"random_string()"
def test_length(self):
"random_string() returns string of correct length"
for length in 1, 5, 17, 54, 270:
self.assertEqual(
len(util.random_string(length)),
length
)
def test_random(self):
"random_string() returns a random string"
for i in range(3):
self.assertNotEqual(
util.random_string(8),
util.random_string(8)
)
class time_period_rough(unittest.TestCase):
"time_period_rough()"
def test_endfirst(self):
"time_period_rough() returns '0 seconds' when end-time is earliest"
self.assertEqual(
util.time_period_rough(1098565803, 1098565800),
"0 seconds"
)
def test_results(self):
"time_period_rough() returns correct results"
data = (
# year intervals
( "2004-10-23 10:00:00", "2005-10-23 10:00:00", "1 year" ),
( "2004-10-23 10:00:00", "2006-10-23 09:59:59", "1 year" ),
( "2004-10-23 10:00:00", "2007-02-11 15:14:31", "2 years" ),
( "2004-10-23 10:00:00", "2015-12-11 15:14:31", "11 years" ),
# month intervals
( "2004-10-23 10:00:00", "2004-11-23 10:00:00", "1 month" ),
( "2004-10-23 10:00:00", "2004-12-23 09:59:59", "1 month" ),
( "2004-02-01 10:00:00", "2004-03-01 10:00:00", "1 month" ),
( "2004-10-23 10:00:00", "2004-12-23 10:00:00", "2 months" ),
( "2004-10-23 10:00:00", "2005-03-07 23:11:42", "4 months" ),
( "2004-10-23 10:00:00", "2005-10-23 09:59:59", "11 months" ),
# week intervals
( "2004-10-23 10:00:00", "2004-10-30 10:00:00", "1 week" ),
( "2004-10-23 10:00:00", "2004-10-31 15:41:11", "1 week" ),
( "2004-10-23 10:00:00", "2004-11-23 09:59:59", "4 weeks" ),
( "2004-10-23 10:00:00", "2004-11-06 18:11:21", "2 weeks" ),
# day intervals
( "2004-10-23 10:00:00", "2004-10-24 10:00:00", "1 day" ),
( "2004-10-23 10:00:00", "2004-10-25 09:59:59", "1 day" ),
( "2004-10-23 10:00:00", "2004-10-25 10:00:00", "2 days" ),
( "2004-10-23 10:00:00", "2004-10-29 19:21:47", "6 days" ),
( "2004-10-30 10:00:00", "2004-11-03 04:13:17", "3 days" ),
( "2004-12-29 08:11:45", "2005-01-03 10:48:53", "5 days" ),
# hour intervals
( "2004-10-23 10:00:00", "2004-10-23 11:00:00", "1 hour" ),
( "2004-10-23 10:00:00", "2004-10-23 11:53:24", "1 hour" ),
( "2004-10-23 10:00:00", "2004-10-23 12:00:00", "2 hours" ),
( "2004-10-23 10:00:00", "2004-10-23 19:59:59", "9 hours" ),
( "2004-10-23 05:32:11", "2004-10-23 14:18:32", "8 hours" ),
( "2004-10-23 10:00:00", "2004-10-24 09:59:59", "23 hours" ),
( "2004-10-31 10:00:00", "2004-11-01 04:42:11", "18 hours" ),
( "2004-12-31 17:43:11", "2005-01-01 11:18:55", "17 hours" ),
# minute intervals
( "2004-10-23 10:00:00", "2004-10-23 10:01:00", "1 minute" ),
( "2004-10-23 10:00:00", "2004-10-23 10:01:13", "1 minute" ),
( "2004-10-23 10:00:00", "2004-10-23 10:02:00", "2 minutes" ),
( "2004-10-23 10:00:00", "2004-10-23 10:24:41", "24 minutes" ),
( "2004-10-23 10:00:00", "2004-10-23 10:59:59", "59 minutes" ),
( "2004-10-23 10:42:28", "2004-10-23 11:18:04", "35 minutes" ),
( "2004-10-23 23:57:21", "2004-10-24 00:13:22", "16 minutes" ),
( "2004-10-31 23:57:21", "2004-11-01 00:13:22", "16 minutes" ),
( "2004-12-31 23:57:21", "2005-01-01 00:13:22", "16 minutes" ),
# second intervals
( "2004-10-23 10:00:00", "2004-10-23 10:00:00", "0 seconds" ),
( "2004-10-23 10:00:00", "2004-10-23 10:00:01", "1 second" ),
( "2004-10-23 10:00:00", "2004-10-23 10:00:23", "23 seconds" ),
( "2004-10-23 10:00:00", "2004-10-23 10:00:59", "59 seconds" ),
( "2004-10-23 12:59:48", "2004-10-23 13:00:12", "24 seconds" ),
( "2004-10-23 23:59:43", "2004-10-24 00:00:22", "39 seconds" ),
( "2004-10-31 23:59:43", "2004-11-01 00:00:22", "39 seconds" ),
( "2004-12-31 23:59:43", "2005-01-01 00:00:22", "39 seconds" )
)
for start, end, range in data:
start = time.mktime((int(start[0:4]), int(start[5:7]), int(start[8:10]), int(start[11:13]), int(start[14:16]), int(start[17:19]), 0, 1, 0))
end = time.mktime((int(end[0:4]), int(end[5:7]), int(end[8:10]), int(end[11:13]), int(end[14:16]), int(end[17:19]), 0, 1, 0))
self.assertEqual(
util.time_period_rough(start, end),
range
)
class trace_exception(unittest.TestCase):
"trace_exception()"
def test_exception(self):
"trace_exception() generates a traceback for an exception"
try:
raise IOError
except IOError:
type, value, tb = sys.exc_info()
self.assertEquals(util.trace_exception(type, value, tb) not in ( None, "" ), True)
if __name__ == "__main__":
unittest.main()