Skip to content

Commit d728121

Browse files
committed
Adding some tests for admin.py. Specifically for issue2550572: setting
nosy=+foo on multiple issues gives them all the same exact nosy list. To make this work had to change the admin.py code to use "sys.stdout.write" in place of "print". In the test I now hijack stdout.write following an existing example of this for admin's import/export command that hijacks sys.stderr.write. Also I corrected a misspelling in security.py. The word "everything" was misspelled. It is not inside _() markers so I don't think it's going to affect translation and grepping the locale subdir doesn't show the original string.
1 parent afa5748 commit d728121

File tree

3 files changed

+134
-21
lines changed

3 files changed

+134
-21
lines changed

roundup/admin.py

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ def usage(self, message=''):
107107
"""
108108
if message:
109109
message = _('Problem: %(message)s\n\n')%locals()
110-
print _("""%(message)sUsage: roundup-admin [options] [<command> <arguments>]
110+
sys.stdout.write( _("""%(message)sUsage: roundup-admin [options] [<command> <arguments>]
111111
112112
Options:
113113
-i instance home -- specify the issue tracker "home directory" to administer
@@ -128,13 +128,13 @@ def usage(self, message=''):
128128
roundup-admin help -- this help
129129
roundup-admin help <command> -- command-specific help
130130
roundup-admin help all -- all available help
131-
""")%locals()
131+
""")%locals())
132132
self.help_commands()
133133

134134
def help_commands(self):
135135
"""List the commands available with their help summary.
136136
"""
137-
print _('Commands:'),
137+
sys.stdout.write( _('Commands: '))
138138
commands = ['']
139139
for command in self.commands.itervalues():
140140
h = _(command.__doc__).split('\n')[0]
@@ -143,8 +143,7 @@ def help_commands(self):
143143
commands.append(_(
144144
"""Commands may be abbreviated as long as the abbreviation
145145
matches only one command, e.g. l == li == lis == list."""))
146-
print '\n'.join(commands)
147-
print
146+
sys.stdout.write('\n'.join(commands) + '\n\n')
148147

149148
def help_commands_html(self, indent_re=re.compile(r'^(\s+)\S+')):
150149
""" Produce an HTML command list.
@@ -736,9 +735,9 @@ def do_specification(self, args):
736735
for key in cl.properties:
737736
value = cl.properties[key]
738737
if keyprop == key:
739-
print _('%(key)s: %(value)s (key property)')%locals()
738+
sys.stdout.write( _('%(key)s: %(value)s (key property)\n')%locals() )
740739
else:
741-
print _('%(key)s: %(value)s')%locals()
740+
sys.stdout.write( _('%(key)s: %(value)s\n')%locals() )
742741

743742
def do_display(self, args):
744743
''"""Usage: display designator[,designator]*
@@ -829,7 +828,7 @@ def do_create(self, args):
829828

830829
# do the actual create
831830
try:
832-
print cl.create(**props)
831+
sys.stdout.write(cl.create(**props) + '\n')
833832
except (TypeError, IndexError, ValueError), message:
834833
raise UsageError(message)
835834
self.db_uncommitted = True
@@ -1354,34 +1353,34 @@ def do_security(self, args):
13541353
try:
13551354
roles = [(args[0], self.db.security.role[args[0]])]
13561355
except KeyError:
1357-
print _('No such Role "%(role)s"')%locals()
1356+
sys.stdout.write( _('No such Role "%(role)s"\n')%locals() )
13581357
return 1
13591358
else:
13601359
roles = list(self.db.security.role.items())
13611360
role = self.db.config.NEW_WEB_USER_ROLES
13621361
if ',' in role:
1363-
print _('New Web users get the Roles "%(role)s"')%locals()
1362+
sys.stdout.write( _('New Web users get the Roles "%(role)s"\n')%locals() )
13641363
else:
1365-
print _('New Web users get the Role "%(role)s"')%locals()
1364+
sys.stdout.write( _('New Web users get the Role "%(role)s"\n')%locals() )
13661365
role = self.db.config.NEW_EMAIL_USER_ROLES
13671366
if ',' in role:
1368-
print _('New Email users get the Roles "%(role)s"')%locals()
1367+
sys.stdout.write( _('New Email users get the Roles "%(role)s"\n')%locals() )
13691368
else:
1370-
print _('New Email users get the Role "%(role)s"')%locals()
1369+
sys.stdout.write( _('New Email users get the Role "%(role)s"\n')%locals() )
13711370
roles.sort()
13721371
for rolename, role in roles:
1373-
print _('Role "%(name)s":')%role.__dict__
1372+
sys.stdout.write( _('Role "%(name)s":\n')%role.__dict__ )
13741373
for permission in role.permissions:
13751374
d = permission.__dict__
13761375
if permission.klass:
13771376
if permission.properties:
1378-
print _(' %(description)s (%(name)s for "%(klass)s"'
1379-
': %(properties)s only)')%d
1377+
sys.stdout.write( _(' %(description)s (%(name)s for "%(klass)s"' +
1378+
': %(properties)s only)\n')%d )
13801379
else:
1381-
print _(' %(description)s (%(name)s for "%(klass)s" '
1382-
'only)')%d
1380+
sys.stdout.write( _(' %(description)s (%(name)s for "%(klass)s" ' +
1381+
'only)\n')%d )
13831382
else:
1384-
print _(' %(description)s (%(name)s)')%d
1383+
sys.stdout.write( _(' %(description)s (%(name)s)\n')%d )
13851384
return 0
13861385

13871386

roundup/security.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ def __init__(self, db):
128128
# default permissions - Admin may do anything
129129
for p in 'create edit retire view'.split():
130130
p = self.addPermission(name=p.title(),
131-
description="User may %s everthing"%p)
131+
description="User may %s everything"%p)
132132
self.addPermissionToRole('Admin', p)
133133

134134
# initialise the permissions and roles needed for the UIs

test/db_test_base.py

Lines changed: 115 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
Interval, DatabaseError, Boolean, Number, Node, Integer
2626
from roundup.mailer import Mailer
2727
from roundup import date, password, init, instance, configuration, \
28-
roundupdb, i18n
28+
roundupdb, i18n, hyperdb
2929
from roundup.cgi.templating import HTMLItem
3030

3131
from mocknull import MockNull
@@ -1959,6 +1959,120 @@ def stderrwrite(s):
19591959
roundup.admin.sys = sys
19601960
shutil.rmtree('_test_export')
19611961

1962+
# test props from args parsing
1963+
def testAdminOtherCommands(self):
1964+
import roundup.admin
1965+
from roundup.exceptions import UsageError
1966+
1967+
# use the filtering setup to create a bunch of items
1968+
ae, dummy1, dummy2 = self.filteringSetup()
1969+
# create large field
1970+
self.db.priority.create(name = 'X' * 500)
1971+
self.db.config.CSV_FIELD_SIZE = 400
1972+
self.db.commit()
1973+
1974+
eoutput = [] # stderr output
1975+
soutput = [] # stdout output
1976+
1977+
def stderrwrite(s):
1978+
eoutput.append(s)
1979+
def stdoutwrite(s):
1980+
soutput.append(s)
1981+
roundup.admin.sys = MockNull ()
1982+
try:
1983+
roundup.admin.sys.stderr.write = stderrwrite
1984+
roundup.admin.sys.stdout.write = stdoutwrite
1985+
1986+
tool = roundup.admin.AdminTool()
1987+
home = '.'
1988+
tool.tracker_home = home
1989+
tool.db = self.db
1990+
tool.verbose = False
1991+
tool.separator = "\n"
1992+
tool.print_designator = True
1993+
1994+
# test props_from_args
1995+
self.assertRaises(UsageError, tool.props_from_args, "fullname") # invalid propname
1996+
1997+
self.assertEqual(tool.props_from_args("="), {'': None}) # not sure this desired, I'd expect UsageError
1998+
1999+
props = tool.props_from_args(["fullname=robert", "friends=+rouilj,+other", "key="])
2000+
self.assertEqual(props, {'fullname': 'robert', 'friends': '+rouilj,+other', 'key': None})
2001+
2002+
# test get_class()
2003+
self.assertRaises(UsageError, tool.get_class, "bar") # invalid class
2004+
2005+
# This writes to stdout, need to figure out how to redirect to a variable.
2006+
# classhandle = tool.get_class("user") # valid class
2007+
# FIXME there should be some test here
2008+
2009+
issue_class_spec = tool.do_specification(["issue"])
2010+
self.assertEqual(soutput, ['files: <roundup.hyperdb.Multilink to "file">\n',
2011+
'status: <roundup.hyperdb.Link to "status">\n',
2012+
'feedback: <roundup.hyperdb.Link to "msg">\n',
2013+
'spam: <roundup.hyperdb.Multilink to "msg">\n',
2014+
'nosy: <roundup.hyperdb.Multilink to "user">\n',
2015+
'title: <roundup.hyperdb.String>\n',
2016+
'messages: <roundup.hyperdb.Multilink to "msg">\n',
2017+
'priority: <roundup.hyperdb.Link to "priority">\n',
2018+
'assignedto: <roundup.hyperdb.Link to "user">\n',
2019+
'deadline: <roundup.hyperdb.Date>\n',
2020+
'foo: <roundup.hyperdb.Interval>\n',
2021+
'superseder: <roundup.hyperdb.Multilink to "issue">\n'])
2022+
2023+
#userclassprop=tool.do_list(["mls"])
2024+
#tool.print_designator = False
2025+
#userclassprop=tool.do_get(["realname","user1"])
2026+
2027+
# test do_create
2028+
soutput[:] = [] # empty for next round of output
2029+
userclass=tool.do_create(["issue", "title='title1 title'", "nosy=1,3"]) # should be issue 5
2030+
userclass=tool.do_create(["issue", "title='title2 title'", "nosy=2,3"]) # should be issue 6
2031+
self.assertEqual(soutput, ['5\n', '6\n'])
2032+
# verify nosy setting
2033+
props=self.db.issue.get('5', "nosy")
2034+
self.assertEqual(props, ['1','3'])
2035+
2036+
# test do_set using newly created issues
2037+
# remove user 3 from issues
2038+
# verifies issue2550572
2039+
userclass=tool.do_set(["issue5,issue6", "nosy=-3"])
2040+
# verify proper result
2041+
props=self.db.issue.get('5', "nosy")
2042+
self.assertEqual(props, ['1'])
2043+
props=self.db.issue.get('6', "nosy")
2044+
self.assertEqual(props, ['2'])
2045+
2046+
# basic usage test. TODO add full output verification
2047+
soutput[:] = [] # empty for next round of output
2048+
tool.usage(message="Hello World")
2049+
self.failUnless(soutput[0].startswith('Problem: Hello World'), None)
2050+
2051+
# check security output
2052+
soutput[:] = [] # empty for next round of output
2053+
tool.do_security("Admin")
2054+
self.assertEqual(soutput, [ 'New Web users get the Role "User"\n',
2055+
'New Email users get the Role "User"\n',
2056+
'Role "admin":\n',
2057+
' User may create everything (Create)\n',
2058+
' User may edit everything (Edit)\n',
2059+
' User may retire everything (Retire)\n',
2060+
' User may view everything (View)\n',
2061+
' User may access the web interface (Web Access)\n',
2062+
' User may manipulate user Roles through the web (Web Roles)\n',
2063+
' User may use the email interface (Email Access)\n',
2064+
'Role "anonymous":\n', 'Role "user":\n',
2065+
' User is allowed to access msg (View for "msg" only)\n'])
2066+
2067+
2068+
self.nukeAndCreate()
2069+
tool = roundup.admin.AdminTool()
2070+
tool.tracker_home = home
2071+
tool.db = self.db
2072+
tool.verbose = False
2073+
finally:
2074+
roundup.admin.sys = sys
2075+
19622076
def testAddProperty(self):
19632077
self.db.issue.create(title="spam", status='1')
19642078
self.db.commit()

0 commit comments

Comments
 (0)