Modified: bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/list_of_attachments.html URL: http://svn.apache.org/viewvc/bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/list_of_attachments.html?rev=1639823&r1=1639822&r2=1639823&view=diff ============================================================================== --- bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/list_of_attachments.html (original) +++ bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/list_of_attachments.html Sat Nov 15 01:14:46 2014 @@ -1,4 +1,13 @@ -<!--! +<!--! Copyright (C) 2010-2014 Edgewall Software + + This software is licensed as described in the file COPYING, which + you should have received as part of this distribution. The terms + are also available at http://trac.edgewall.com/license.html. + + This software consists of voluntary contributions made by many + individuals. For the exact contribution history, see the revision + history and logs, available at http://trac.edgewall.org/. + Display a list of attachments. Arguments:
Modified: bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/macros.html URL: http://svn.apache.org/viewvc/bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/macros.html?rev=1639823&r1=1639822&r2=1639823&view=diff ============================================================================== --- bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/macros.html (original) +++ bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/macros.html Sat Nov 15 01:14:46 2014 @@ -1,3 +1,13 @@ +<!--! Copyright (C) 2006-2014 Edgewall Software + + This software is licensed as described in the file COPYING, which + you should have received as part of this distribution. The terms + are also available at http://trac.edgewall.com/license.html. + + This software consists of voluntary contributions made by many + individuals. For the exact contribution history, see the revision + history and logs, available at http://trac.edgewall.org/. +--> <div xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://genshi.edgewall.org/" xmlns:xi="http://www.w3.org/2001/XInclude" Modified: bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/page_index.html URL: http://svn.apache.org/viewvc/bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/page_index.html?rev=1639823&r1=1639822&r2=1639823&view=diff ============================================================================== --- bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/page_index.html (original) +++ bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/page_index.html Sat Nov 15 01:14:46 2014 @@ -1,6 +1,17 @@ -<!--! Display a page index. +<!--! Copyright (C) 2008-2014 Edgewall Software - `paginator` must be a trac.util.presentation.Paginator instance + This software is licensed as described in the file COPYING, which + you should have received as part of this distribution. The terms + are also available at http://trac.edgewall.com/license.html. + + This software consists of voluntary contributions made by many + individuals. For the exact contribution history, see the revision + history and logs, available at http://trac.edgewall.org/. + +Display a page index. + +Arguments: + - `paginator` must be a trac.util.presentation.Paginator instance --> <div xmlns="http://www.w3.org/1999/xhtml" Modified: bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/preview_file.html URL: http://svn.apache.org/viewvc/bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/preview_file.html?rev=1639823&r1=1639822&r2=1639823&view=diff ============================================================================== --- bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/preview_file.html (original) +++ bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/preview_file.html Sat Nov 15 01:14:46 2014 @@ -1,4 +1,13 @@ -<!--! +<!--! Copyright (C) 2010-2014 Edgewall Software + + This software is licensed as described in the file COPYING, which + you should have received as part of this distribution. The terms + are also available at http://trac.edgewall.com/license.html. + + This software consists of voluntary contributions made by many + individuals. For the exact contribution history, see the revision + history and logs, available at http://trac.edgewall.org/. + Display a div for visualizing a preview of a file content. Arguments: Modified: bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/progress_bar.html URL: http://svn.apache.org/viewvc/bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/progress_bar.html?rev=1639823&r1=1639822&r2=1639823&view=diff ============================================================================== --- bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/progress_bar.html (original) +++ bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/progress_bar.html Sat Nov 15 01:14:46 2014 @@ -1,4 +1,13 @@ -<!--! +<!--! Copyright (C) 2010-2014 Edgewall Software + + This software is licensed as described in the file COPYING, which + you should have received as part of this distribution. The terms + are also available at http://trac.edgewall.com/license.html. + + This software consists of voluntary contributions made by many + individuals. For the exact contribution history, see the revision + history and logs, available at http://trac.edgewall.org/. + Display groups of tickets in a progress bar. Arguments: Modified: bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/progress_bar_grouped.html URL: http://svn.apache.org/viewvc/bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/progress_bar_grouped.html?rev=1639823&r1=1639822&r2=1639823&view=diff ============================================================================== --- bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/progress_bar_grouped.html (original) +++ bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/progress_bar_grouped.html Sat Nov 15 01:14:46 2014 @@ -1,4 +1,13 @@ -<!--! +<!--! Copyright (C) 2011-2014 Edgewall Software + + This software is licensed as described in the file COPYING, which + you should have received as part of this distribution. The terms + are also available at http://trac.edgewall.com/license.html. + + This software consists of voluntary contributions made by many + individuals. For the exact contribution history, see the revision + history and logs, available at http://trac.edgewall.org/. + Display a table of progress bars for ticket groups Arguments: Modified: bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/theme.html URL: http://svn.apache.org/viewvc/bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/theme.html?rev=1639823&r1=1639822&r2=1639823&view=diff ============================================================================== --- bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/theme.html (original) +++ bloodhound/branches/trac-1.0.2-integration/trac/trac/templates/theme.html Sat Nov 15 01:14:46 2014 @@ -1,3 +1,13 @@ +<!--! Copyright (C) 2006-2014 Edgewall Software + + This software is licensed as described in the file COPYING, which + you should have received as part of this distribution. The terms + are also available at http://trac.edgewall.com/license.html. + + This software consists of voluntary contributions made by many + individuals. For the exact contribution history, see the revision + history and logs, available at http://trac.edgewall.org/. +--> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> Modified: bloodhound/branches/trac-1.0.2-integration/trac/trac/test.py URL: http://svn.apache.org/viewvc/bloodhound/branches/trac-1.0.2-integration/trac/trac/test.py?rev=1639823&r1=1639822&r2=1639823&view=diff ============================================================================== --- bloodhound/branches/trac-1.0.2-integration/trac/trac/test.py (original) +++ bloodhound/branches/trac-1.0.2-integration/trac/trac/test.py Sat Nov 15 01:14:46 2014 @@ -144,7 +144,8 @@ class TestSetup(unittest.TestSuite): return result def _wrapped_run(self, *args, **kwargs): - "Python 2.7 / unittest2 compatibility - there must be a better way..." + """Python 2.7 / unittest2 compatibility - there must be a better + way...""" self.setUp() if hasattr(self, 'fixture'): for test in self._tests: @@ -153,6 +154,7 @@ class TestSetup(unittest.TestSuite): unittest.TestSuite._wrapped_run(self, *args, **kwargs) self.tearDown() + class TestCaseSetup(unittest.TestCase): def setFixture(self, fixture): self.fixture = fixture @@ -164,7 +166,7 @@ def get_dburi(): dburi = os.environ.get('TRAC_TEST_DB_URI') if dburi: scheme, db_prop = _parse_db_str(dburi) - # Assume the schema 'tractest' for Postgres + # Assume the schema 'tractest' for PostgreSQL if scheme == 'postgres' and \ not db_prop.get('params', {}).get('schema'): if '?' in dburi: @@ -176,9 +178,8 @@ def get_dburi(): def reset_sqlite_db(env, db_prop): - dbname = os.path.basename(db_prop['path']) with env.db_transaction as db: - tables = db("SELECT name FROM sqlite_master WHERE type='table'") + tables = db.get_table_names() for table in tables: db("DELETE FROM %s" % table) return tables @@ -189,24 +190,24 @@ def reset_postgres_db(env, db_prop): dbname = db.schema if dbname: # reset sequences - # information_schema.sequences view is available in PostgreSQL 8.2+ - # however Trac supports PostgreSQL 8.0+, uses + # information_schema.sequences view is available in + # PostgreSQL 8.2+ however Trac supports PostgreSQL 8.0+, uses # pg_get_serial_sequence() - for seq in db(""" - SELECT sequence_name FROM ( - SELECT pg_get_serial_sequence(%s||table_name, - column_name) - AS sequence_name - FROM information_schema.columns - WHERE table_schema=%s) AS tab - WHERE sequence_name IS NOT NULL""", - (dbname + '.', dbname)): + seqs = [seq for seq, in db(""" + SELECT sequence_name + FROM ( + SELECT pg_get_serial_sequence( + quote_ident(table_schema) || '.' || + quote_ident(table_name), column_name) AS sequence_name + FROM information_schema.columns + WHERE table_schema=%s) AS tab + WHERE sequence_name IS NOT NULL""", (dbname,))] + for seq in seqs: db("ALTER SEQUENCE %s RESTART WITH 1" % seq) # clear tables - tables = db("""SELECT table_name FROM information_schema.tables - WHERE table_schema=%s""", (dbname,)) + tables = db.get_table_names() for table in tables: - db("DELETE FROM %s" % table) + db("DELETE FROM %s" % db.quote(table)) # PostgreSQL supports TRUNCATE TABLE as well # (see http://www.postgresql.org/docs/8.1/static/sql-truncate.html) # but on the small tables used here, DELETE is actually much faster @@ -217,12 +218,18 @@ def reset_mysql_db(env, db_prop): dbname = os.path.basename(db_prop['path']) if dbname: with env.db_transaction as db: - tables = db("""SELECT table_name FROM information_schema.tables + tables = db("""SELECT table_name, auto_increment + FROM information_schema.tables WHERE table_schema=%s""", (dbname,)) - for table in tables: - # TRUNCATE TABLE is prefered to DELETE FROM, as we need to reset - # the auto_increment in MySQL. - db("TRUNCATE TABLE %s" % table) + for table, auto_increment in tables: + if auto_increment is None or auto_increment == 1: + # DELETE FROM is preferred to TRUNCATE TABLE, as the + # auto_increment is not used or it is 1. + db("DELETE FROM %s" % table) + else: + # TRUNCATE TABLE is preferred to DELETE FROM, as we + # need to reset the auto_increment in MySQL. + db("TRUNCATE TABLE %s" % table) return tables @@ -233,6 +240,7 @@ class EnvironmentStub(Environment): href = abs_href = None global_databasemanager = None + required = False def __init__(self, default_data=False, enable=None, disable=None, path=None, destroying=False): @@ -242,7 +250,20 @@ class EnvironmentStub(Environment): defaults. :param enable: A list of component classes or name globs to activate in the stub environment. + :param disable: A list of component classes or name globs to + deactivate in the stub environment. + :param path: The location of the environment in the file system. + No files or directories are created when specifying + this parameter. + :param destroying: If True, the database will not be reset. This is + useful for cases when the object is being + constructed in order to call `destroy_db`. """ + if enable is not None and not isinstance(enable, (list, tuple)): + raise TypeError('Keyword argument "enable" must be a list') + if disable is not None and not isinstance(disable, (list, tuple)): + raise TypeError('Keyword argument "disable" must be a list') + ComponentManager.__init__(self) Component.__init__(self) @@ -266,7 +287,7 @@ class EnvironmentStub(Environment): if enable is not None: self.config.set('components', 'trac.*', 'disabled') else: - self.config.set('components', 'tracopt.versioncontrol.svn.*', + self.config.set('components', 'tracopt.versioncontrol.*', 'enabled') for name_or_class in enable or (): config_key = self._component_name(name_or_class) @@ -315,28 +336,26 @@ class EnvironmentStub(Environment): remove_sqlite_db = False try: with self.db_transaction as db: - db.rollback() # make sure there's no transaction in progress + db.rollback() # make sure there's no transaction in progress # check the database version - database_version = db( - "SELECT value FROM system WHERE name='database_version'") - if database_version: - database_version = int(database_version[0][0]) - if database_version == db_default.db_version: - # same version, simply clear the tables (faster) - m = sys.modules[__name__] - reset_fn = 'reset_%s_db' % scheme - if hasattr(m, reset_fn): - tables = getattr(m, reset_fn)(self, db_prop) - else: - # different version or version unknown, drop the tables - remove_sqlite_db = True - self.destroy_db(scheme, db_prop) - except Exception, e: + database_version = self.get_version() + except Exception: # "Database not found ...", # "OperationalError: no such table: system" or the like pass + else: + if database_version == db_default.db_version: + # same version, simply clear the tables (faster) + m = sys.modules[__name__] + reset_fn = 'reset_%s_db' % scheme + if hasattr(m, reset_fn): + tables = getattr(m, reset_fn)(self, db_prop) + else: + # different version or version unknown, drop the tables + remove_sqlite_db = True + self.destroy_db(scheme, db_prop) - db = None # as we might shutdown the pool FIXME no longer needed! + db = None # as we might shutdown the pool FIXME no longer needed! if scheme == 'sqlite' and remove_sqlite_db: path = db_prop['path'] @@ -354,12 +373,14 @@ class EnvironmentStub(Environment): self.global_databasemanager.shutdown() with self.db_transaction as db: + if scheme == 'sqlite': + # Speed-up tests with SQLite database + db("PRAGMA synchronous = OFF") if default_data: for table, cols, vals in db_default.get_data(db): db.executemany("INSERT INTO %s (%s) VALUES (%s)" % (table, ','.join(cols), - ','.join(['%s' for c in cols])), - vals) + ','.join(['%s'] * len(cols))), vals) else: db("INSERT INTO system (name, value) VALUES (%s, %s)", ('database_version', str(db_default.db_version))) @@ -370,12 +391,9 @@ class EnvironmentStub(Environment): try: with self.db_transaction as db: if scheme == 'postgres' and db.schema: - db('DROP SCHEMA "%s" CASCADE' % db.schema) + db('DROP SCHEMA %s CASCADE' % db.quote(db.schema)) elif scheme == 'mysql': - dbname = os.path.basename(db_prop['path']) - for table in db(""" - SELECT table_name FROM information_schema.tables - WHERE table_schema=%s""", (dbname,)): + for table in db.get_table_names(): db("DROP TABLE IF EXISTS `%s`" % table) except Exception: # "TracError: Database not found...", @@ -383,7 +401,7 @@ class EnvironmentStub(Environment): pass return False - # overriden + # overridden def is_component_enabled(self, cls): if self._component_name(cls).startswith('__main__.'): @@ -410,11 +428,13 @@ def locate(fn): INCLUDE_FUNCTIONAL_TESTS = True + def suite(): import trac.tests import trac.admin.tests import trac.db.tests import trac.mimeview.tests + import trac.timeline.tests import trac.ticket.tests import trac.util.tests import trac.versioncontrol.tests @@ -423,17 +443,17 @@ def suite(): import trac.wiki.tests import tracopt.mimeview.tests import tracopt.perm.tests + import tracopt.ticket.tests import tracopt.versioncontrol.git.tests import tracopt.versioncontrol.svn.tests suite = unittest.TestSuite() suite.addTest(trac.tests.basicSuite()) - if INCLUDE_FUNCTIONAL_TESTS: - suite.addTest(trac.tests.functionalSuite()) suite.addTest(trac.admin.tests.suite()) suite.addTest(trac.db.tests.suite()) suite.addTest(trac.mimeview.tests.suite()) suite.addTest(trac.ticket.tests.suite()) + suite.addTest(trac.timeline.tests.suite()) suite.addTest(trac.util.tests.suite()) suite.addTest(trac.versioncontrol.tests.suite()) suite.addTest(trac.versioncontrol.web_ui.tests.suite()) @@ -441,9 +461,12 @@ def suite(): suite.addTest(trac.wiki.tests.suite()) suite.addTest(tracopt.mimeview.tests.suite()) suite.addTest(tracopt.perm.tests.suite()) + suite.addTest(tracopt.ticket.tests.suite()) suite.addTest(tracopt.versioncontrol.git.tests.suite()) suite.addTest(tracopt.versioncontrol.svn.tests.suite()) suite.addTest(doctest.DocTestSuite(sys.modules[__name__])) + if INCLUDE_FUNCTIONAL_TESTS: + suite.addTest(trac.tests.functionalSuite()) return suite Modified: bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/__init__.py URL: http://svn.apache.org/viewvc/bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/__init__.py?rev=1639823&r1=1639822&r2=1639823&view=diff ============================================================================== --- bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/__init__.py (original) +++ bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/__init__.py Sat Nov 15 01:14:46 2014 @@ -1,7 +1,20 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2004-2013 Edgewall Software +# All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://trac.edgewall.org/wiki/TracLicense. +# +# This software consists of voluntary contributions made by many +# individuals. For the exact contribution history, see the revision +# history and logs, available at http://trac.edgewall.org/log/. + import unittest -from trac.tests import attachment, config, core, env, perm, resource, \ - wikisyntax, functional +from trac.tests import attachment, config, core, env, perm, notification, \ + resource, wikisyntax, functional def suite(): suite = unittest.TestSuite() @@ -15,6 +28,7 @@ def basicSuite(): suite.addTest(config.suite()) suite.addTest(core.suite()) suite.addTest(env.suite()) + suite.addTest(notification.suite()) suite.addTest(perm.suite()) suite.addTest(resource.suite()) suite.addTest(wikisyntax.suite()) Modified: bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/allwiki.py URL: http://svn.apache.org/viewvc/bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/allwiki.py?rev=1639823&r1=1639822&r2=1639823&view=diff ============================================================================== --- bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/allwiki.py (original) +++ bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/allwiki.py Sat Nov 15 01:14:46 2014 @@ -1,3 +1,16 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2006-2013 Edgewall Software +# All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://trac.edgewall.org/wiki/TracLicense. +# +# This software consists of voluntary contributions made by many +# individuals. For the exact contribution history, see the revision +# history and logs, available at http://trac.edgewall.org/log/. + import unittest import trac.tests.wikisyntax Modified: bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/attachment.py URL: http://svn.apache.org/viewvc/bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/attachment.py?rev=1639823&r1=1639822&r2=1639823&view=diff ============================================================================== --- bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/attachment.py (original) +++ bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/attachment.py Sat Nov 15 01:14:46 2014 @@ -1,6 +1,19 @@ # -*- coding: utf-8 -*- +# +# Copyright (C) 2005-2013 Edgewall Software +# All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://trac.edgewall.org/wiki/TracLicense. +# +# This software consists of voluntary contributions made by many +# individuals. For the exact contribution history, see the revision +# history and logs, available at http://trac.edgewall.org/log/. -import os.path +from __future__ import with_statement + +import os import shutil from StringIO import StringIO import tempfile @@ -44,8 +57,7 @@ class AttachmentTestCase(unittest.TestCa def setUp(self): self.env = EnvironmentStub() - self.env.path = os.path.join(tempfile.gettempdir(), 'trac-tempenv') - os.mkdir(self.env.path) + self.env.path = tempfile.mkdtemp(prefix='trac-tempenv-') self.attachments_dir = os.path.join(self.env.path, 'files', 'attachments') self.env.config.set('trac', 'permission_policies', @@ -53,6 +65,10 @@ class AttachmentTestCase(unittest.TestCa self.env.config.set('attachment', 'max_size', 512) self.perm = PermissionCache(self.env) + with self.env.db_transaction as db: + db("INSERT INTO wiki (name,version) VALUES ('WikiStart',1)") + db("INSERT INTO wiki (name,version) VALUES ('SomePage',1)") + db("INSERT INTO ticket (id) VALUES (42)") def tearDown(self): shutil.rmtree(self.env.path) @@ -144,7 +160,7 @@ class AttachmentTestCase(unittest.TestCa hashes['42'][0:3], hashes['42'], hashes['foo.2.txt'] + '.txt'), attachment.path) - self.assert_(os.path.exists(attachment.path)) + self.assertTrue(os.path.exists(attachment.path)) def test_insert_outside_attachments_dir(self): attachment = Attachment(self.env, '../../../../../sth/private', 42) @@ -163,8 +179,8 @@ class AttachmentTestCase(unittest.TestCa attachment1.delete() attachment2.delete() - assert not os.path.exists(attachment1.path) - assert not os.path.exists(attachment2.path) + self.assertFalse(os.path.exists(attachment1.path)) + self.assertFalse(os.path.exists(attachment2.path)) attachments = Attachment.select(self.env, 'wiki', 'SomePage') self.assertEqual(0, len(list(attachments))) @@ -191,7 +207,7 @@ class AttachmentTestCase(unittest.TestCa self.assertEqual(2, len(list(attachments))) attachments = Attachment.select(self.env, 'ticket', 123) self.assertEqual(0, len(list(attachments))) - assert os.path.exists(path1) and os.path.exists(attachment2.path) + self.assertTrue(os.path.exists(path1) and os.path.exists(attachment2.path)) attachment1.reparent('ticket', 123) self.assertEqual('ticket', attachment1.parent_realm) @@ -203,19 +219,19 @@ class AttachmentTestCase(unittest.TestCa self.assertEqual(1, len(list(attachments))) attachments = Attachment.select(self.env, 'ticket', 123) self.assertEqual(1, len(list(attachments))) - assert not os.path.exists(path1) and os.path.exists(attachment1.path) - assert os.path.exists(attachment2.path) + self.assertFalse(os.path.exists(path1) and os.path.exists(attachment1.path)) + self.assertTrue(os.path.exists(attachment2.path)) def test_legacy_permission_on_parent(self): """Ensure that legacy action tests are done on parent. As `ATTACHMENT_VIEW` maps to `TICKET_VIEW`, the `TICKET_VIEW` is tested against the ticket's resource.""" attachment = Attachment(self.env, 'ticket', 42) - self.assert_('ATTACHMENT_VIEW' in self.perm(attachment.resource)) + self.assertTrue('ATTACHMENT_VIEW' in self.perm(attachment.resource)) def test_resource_doesnt_exist(self): r = Resource('wiki', 'WikiStart').child('attachment', 'file.txt') - self.assertEqual(False, AttachmentModule(self.env).resource_exists(r)) + self.assertFalse(AttachmentModule(self.env).resource_exists(r)) def test_resource_exists(self): att = Attachment(self.env, 'wiki', 'WikiStart') @@ -232,6 +248,10 @@ class AttachmentResourceChangeListenerTe self.listener = TestResourceChangeListener(self.env) self.listener.resource_type = Attachment self.listener.callback = self.listener_callback + from trac.wiki.model import WikiPage + page = WikiPage(self.env, 'WikiStart') + page.text = "WikiStart" + page.save('user', '', '::1') def tearDown(self): self.env.reset_db() @@ -277,7 +297,7 @@ class AttachmentResourceChangeListenerTe def suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(AttachmentTestCase, 'test')) + suite.addTest(unittest.makeSuite(AttachmentTestCase)) suite.addTest(unittest.makeSuite( AttachmentResourceChangeListenerTestCase, 'test')) return suite Modified: bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/config.py URL: http://svn.apache.org/viewvc/bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/config.py?rev=1639823&r1=1639822&r2=1639823&view=diff ============================================================================== --- bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/config.py (original) +++ bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/config.py Sat Nov 15 01:14:46 2014 @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C) 2005-2009 Edgewall Software +# Copyright (C) 2005-2013 Edgewall Software # Copyright (C) 2005-2007 Christopher Lenz <cml...@gmx.de> # All rights reserved. # @@ -19,8 +19,10 @@ import tempfile import time import unittest +import trac.tests.compat from trac.config import * -from trac.test import Configuration +from trac.core import Component, Interface, implements +from trac.test import Configuration, EnvironmentStub from trac.util import create_file @@ -29,6 +31,7 @@ class ConfigurationTestCase(unittest.Tes def setUp(self): tmpdir = os.path.realpath(tempfile.gettempdir()) self.filename = os.path.join(tmpdir, 'trac-test.ini') + self.env = EnvironmentStub() self._write([]) self._orig_registry = Option.registry Option.registry = {} @@ -46,79 +49,80 @@ class ConfigurationTestCase(unittest.Tes def test_default(self): config = self._read() - self.assertEquals('', config.get('a', 'option')) - self.assertEquals('value', config.get('a', 'option', 'value')) + self.assertEqual('', config.get('a', 'option')) + self.assertEqual('value', config.get('a', 'option', 'value')) class Foo(object): option_a = Option('a', 'option', 'value') - self.assertEquals('value', config.get('a', 'option')) + self.assertEqual('value', config.get('a', 'option')) def test_default_bool(self): config = self._read() - self.assertEquals(False, config.getbool('a', 'option')) - self.assertEquals(True, config.getbool('a', 'option', 'yes')) - self.assertEquals(True, config.getbool('a', 'option', 1)) + self.assertFalse(config.getbool('a', 'option')) + self.assertTrue(config.getbool('a', 'option', 'yes')) + self.assertTrue(config.getbool('a', 'option', 1)) class Foo(object): option_a = Option('a', 'option', 'true') - self.assertEquals(True, config.getbool('a', 'option')) + self.assertTrue(config.getbool('a', 'option')) def test_default_int(self): config = self._read() self.assertRaises(ConfigurationError, config.getint, 'a', 'option', 'b') - self.assertEquals(0, config.getint('a', 'option')) - self.assertEquals(1, config.getint('a', 'option', '1')) - self.assertEquals(1, config.getint('a', 'option', 1)) + self.assertEqual(0, config.getint('a', 'option')) + self.assertEqual(1, config.getint('a', 'option', '1')) + self.assertEqual(1, config.getint('a', 'option', 1)) class Foo(object): option_a = Option('a', 'option', '2') - self.assertEquals(2, config.getint('a', 'option')) + self.assertEqual(2, config.getint('a', 'option')) def test_default_float(self): config = self._read() self.assertRaises(ConfigurationError, config.getfloat, 'a', 'option', 'b') - self.assertEquals(0.0, config.getfloat('a', 'option')) - self.assertEquals(1.2, config.getfloat('a', 'option', '1.2')) - self.assertEquals(1.2, config.getfloat('a', 'option', 1.2)) - self.assertEquals(1.0, config.getfloat('a', 'option', 1)) + self.assertEqual(0.0, config.getfloat('a', 'option')) + self.assertEqual(1.2, config.getfloat('a', 'option', '1.2')) + self.assertEqual(1.2, config.getfloat('a', 'option', 1.2)) + self.assertEqual(1.0, config.getfloat('a', 'option', 1)) class Foo(object): option_a = Option('a', 'option', '2.5') - self.assertEquals(2.5, config.getfloat('a', 'option')) + self.assertEqual(2.5, config.getfloat('a', 'option')) def test_default_path(self): config = self._read() class Foo(object): option_a = PathOption('a', 'opt1', 'file.ini') option_b = PathOption('a', 'opt2', '/somewhere/file.ini') - self.assertEquals('file.ini', config.get('a', 'opt1')) + self.assertEqual('file.ini', config.get('a', 'opt1')) self.assertNotEquals('file.ini', config.getpath('a', 'opt1')) self.assertTrue(os.path.isabs(config.getpath('a', 'opt1'))) - self.assertEquals('/somewhere/file.ini', os.path.splitdrive( - config.getpath('a', 'opt2'))[1].replace('\\', '/')) - self.assertEquals('/none.ini', os.path.splitdrive( - config.getpath('a', 'opt3', '/none.ini'))[1].replace('\\', '/')) + self.assertEqual('/somewhere/file.ini', os.path.splitdrive( + config.getpath('a', 'opt2'))[1].replace('\\', '/')) + self.assertEqual('/none.ini', os.path.splitdrive( + config.getpath('a', 'opt3', + '/none.ini'))[1].replace('\\', '/')) self.assertNotEquals('none.ini', config.getpath('a', 'opt3', 'none.ini')) def test_read_and_get(self): self._write(['[a]', 'option = x']) config = self._read() - self.assertEquals('x', config.get('a', 'option')) - self.assertEquals('x', config.get('a', 'option', 'y')) - self.assertEquals('y', config.get('b', 'option2', 'y')) + self.assertEqual('x', config.get('a', 'option')) + self.assertEqual('x', config.get('a', 'option', 'y')) + self.assertEqual('y', config.get('b', 'option2', 'y')) def test_read_and_get_unicode(self): self._write([u'[ä]', u'öption = x']) config = self._read() - self.assertEquals('x', config.get(u'ä', u'öption')) - self.assertEquals('x', config.get(u'ä', u'öption', 'y')) - self.assertEquals('y', config.get('b', u'öption2', 'y')) + self.assertEqual('x', config.get(u'ä', u'öption')) + self.assertEqual('x', config.get(u'ä', u'öption', 'y')) + self.assertEqual('y', config.get('b', u'öption2', 'y')) def test_read_and_getbool(self): self._write(['[a]', 'option = yes', 'option2 = true', @@ -126,73 +130,74 @@ class ConfigurationTestCase(unittest.Tes 'option5 = 1', 'option6 = 123', 'option7 = 123.456', 'option8 = disabled', 'option9 = 0', 'option10 = 0.0']) config = self._read() - self.assertEquals(True, config.getbool('a', 'option')) - self.assertEquals(True, config.getbool('a', 'option', False)) - self.assertEquals(True, config.getbool('a', 'option2')) - self.assertEquals(True, config.getbool('a', 'option3')) - self.assertEquals(True, config.getbool('a', 'option4')) - self.assertEquals(True, config.getbool('a', 'option5')) - self.assertEquals(True, config.getbool('a', 'option6')) - self.assertEquals(True, config.getbool('a', 'option7')) - self.assertEquals(False, config.getbool('a', 'option8')) - self.assertEquals(False, config.getbool('a', 'option9')) - self.assertEquals(False, config.getbool('a', 'option10')) - self.assertEquals(False, config.getbool('b', 'option_b')) - self.assertEquals(False, config.getbool('b', 'option_b', False)) - self.assertEquals(False, config.getbool('b', 'option_b', 'disabled')) + self.assertTrue(config.getbool('a', 'option')) + self.assertTrue(config.getbool('a', 'option', False)) + self.assertTrue(config.getbool('a', 'option2')) + self.assertTrue(config.getbool('a', 'option3')) + self.assertTrue(config.getbool('a', 'option4')) + self.assertTrue(config.getbool('a', 'option5')) + self.assertTrue(config.getbool('a', 'option6')) + self.assertTrue(config.getbool('a', 'option7')) + self.assertFalse(config.getbool('a', 'option8')) + self.assertFalse(config.getbool('a', 'option9')) + self.assertFalse(config.getbool('a', 'option10')) + self.assertFalse(config.getbool('b', 'option_b')) + self.assertFalse(config.getbool('b', 'option_b', False)) + self.assertFalse(config.getbool('b', 'option_b', 'disabled')) def test_read_and_getint(self): self._write(['[a]', 'option = 42']) config = self._read() - self.assertEquals(42, config.getint('a', 'option')) - self.assertEquals(42, config.getint('a', 'option', 25)) - self.assertEquals(0, config.getint('b', 'option2')) - self.assertEquals(25, config.getint('b', 'option2', 25)) - self.assertEquals(25, config.getint('b', 'option2', '25')) + self.assertEqual(42, config.getint('a', 'option')) + self.assertEqual(42, config.getint('a', 'option', 25)) + self.assertEqual(0, config.getint('b', 'option2')) + self.assertEqual(25, config.getint('b', 'option2', 25)) + self.assertEqual(25, config.getint('b', 'option2', '25')) def test_read_and_getfloat(self): self._write(['[a]', 'option = 42.5']) config = self._read() - self.assertEquals(42.5, config.getfloat('a', 'option')) - self.assertEquals(42.5, config.getfloat('a', 'option', 25.3)) - self.assertEquals(0, config.getfloat('b', 'option2')) - self.assertEquals(25.3, config.getfloat('b', 'option2', 25.3)) - self.assertEquals(25.0, config.getfloat('b', 'option2', 25)) - self.assertEquals(25.3, config.getfloat('b', 'option2', '25.3')) + self.assertEqual(42.5, config.getfloat('a', 'option')) + self.assertEqual(42.5, config.getfloat('a', 'option', 25.3)) + self.assertEqual(0, config.getfloat('b', 'option2')) + self.assertEqual(25.3, config.getfloat('b', 'option2', 25.3)) + self.assertEqual(25.0, config.getfloat('b', 'option2', 25)) + self.assertEqual(25.3, config.getfloat('b', 'option2', '25.3')) def test_read_and_getlist(self): self._write(['[a]', 'option = foo, bar, baz']) config = self._read() - self.assertEquals(['foo', 'bar', 'baz'], - config.getlist('a', 'option')) - self.assertEquals([], - config.getlist('b', 'option2')) - self.assertEquals(['foo', 'bar', 'baz'], - config.getlist('b', 'option2', ['foo', 'bar', 'baz'])) - self.assertEquals(['foo', 'bar', 'baz'], - config.getlist('b', 'option2', 'foo, bar, baz')) + self.assertEqual(['foo', 'bar', 'baz'], + config.getlist('a', 'option')) + self.assertEqual([], + config.getlist('b', 'option2')) + self.assertEqual(['foo', 'bar', 'baz'], + config.getlist('b', 'option2', + ['foo', 'bar', 'baz'])) + self.assertEqual(['foo', 'bar', 'baz'], + config.getlist('b', 'option2', 'foo, bar, baz')) def test_read_and_getlist_sep(self): self._write(['[a]', 'option = foo | bar | baz']) config = self._read() - self.assertEquals(['foo', 'bar', 'baz'], - config.getlist('a', 'option', sep='|')) + self.assertEqual(['foo', 'bar', 'baz'], + config.getlist('a', 'option', sep='|')) def test_read_and_getlist_keep_empty(self): self._write(['[a]', 'option = ,bar,baz']) config = self._read() - self.assertEquals(['bar', 'baz'], config.getlist('a', 'option')) - self.assertEquals(['', 'bar', 'baz'], - config.getlist('a', 'option', keep_empty=True)) + self.assertEqual(['bar', 'baz'], config.getlist('a', 'option')) + self.assertEqual(['', 'bar', 'baz'], + config.getlist('a', 'option', keep_empty=True)) def test_read_and_getlist_false_values(self): config = self._read() values = [None, False, '', 'foo', u'', u'bar', 0, 0L, 0.0, 0j, 42, 43.0] - self.assertEquals([False, 'foo', u'bar', 0, 0L, 0.0, 0j, 42, 43.0], - config.getlist('a', 'false', values)) - self.assertEquals(values, config.getlist('a', 'false', values, - keep_empty=True)) + self.assertEqual([False, 'foo', u'bar', 0, 0L, 0.0, 0j, 42, 43.0], + config.getlist('a', 'false', values)) + self.assertEqual(values, config.getlist('a', 'false', values, + keep_empty=True)) def test_read_and_choice(self): self._write(['[a]', 'option = 2', 'invalid = d']) @@ -208,8 +213,83 @@ class ConfigurationTestCase(unittest.Tes self.config = config foo = Foo() - self.assertEquals('2', foo.option) - self.assertEquals('1', foo.other) + self.assertEqual('2', foo.option) + self.assertEqual('1', foo.other) + self.assertRaises(ConfigurationError, getattr, foo, 'invalid') + + def test_read_and_getextensionoption(self): + self._write(['[a]', 'option = ImplA', 'invalid = ImplB']) + config = self._read() + + class IDummy(Interface): + pass + + class ImplA(Component): + implements(IDummy) + + class Foo(Component): + default1 = (ExtensionOption)('a', 'default1', IDummy) + default2 = (ExtensionOption)('a', 'default2', IDummy, 'ImplA') + default3 = (ExtensionOption)('a', 'default3', IDummy, 'ImplB') + option = (ExtensionOption)('a', 'option', IDummy) + option2 = (ExtensionOption)('a', 'option', IDummy, 'ImplB') + invalid = (ExtensionOption)('a', 'invalid', IDummy) + + def __init__(self): + self.config = config + + foo = Foo(self.env) + self.assertRaises(ConfigurationError, getattr, foo, 'default1') + self.assertIsInstance(foo.default2, ImplA) + self.assertRaises(ConfigurationError, getattr, foo, 'default3') + self.assertIsInstance(foo.option, ImplA) + self.assertIsInstance(foo.option2, ImplA) + self.assertRaises(ConfigurationError, getattr, foo, 'invalid') + + def test_read_and_getorderedextensionsoption(self): + self._write(['[a]', 'option = ImplA, ImplB', + 'invalid = ImplB, ImplD']) + config = self._read() + + class IDummy(Interface): + pass + + class ImplA(Component): + implements(IDummy) + + class ImplB(Component): + implements(IDummy) + + class ImplC(Component): + implements(IDummy) + + class Foo(Component): + # enclose in parentheses to avoid messages extraction + default1 = (OrderedExtensionsOption)('a', 'default1', IDummy, + include_missing=False) + default2 = (OrderedExtensionsOption)('a', 'default2', IDummy) + default3 = (OrderedExtensionsOption)('a', 'default3', IDummy, + 'ImplB, ImplC', + include_missing=False) + option = (OrderedExtensionsOption)('a', 'option', IDummy, + include_missing=False) + invalid = (OrderedExtensionsOption)('a', 'invalid', IDummy) + + def __init__(self): + self.config = config + + foo = Foo(self.env) + self.assertEqual([], foo.default1) + self.assertEqual(3, len(foo.default2)) + self.assertIsInstance(foo.default2[0], ImplA) + self.assertIsInstance(foo.default2[1], ImplB) + self.assertIsInstance(foo.default2[2], ImplC) + self.assertEqual(2, len(foo.default3)) + self.assertIsInstance(foo.default3[0], ImplB) + self.assertIsInstance(foo.default3[1], ImplC) + self.assertEqual(2, len(foo.option)) + self.assertIsInstance(foo.option[0], ImplA) + self.assertIsInstance(foo.option[1], ImplB) self.assertRaises(ConfigurationError, getattr, foo, 'invalid') def test_getpath(self): @@ -218,12 +298,20 @@ class ConfigurationTestCase(unittest.Tes config.set('a', 'path_a', os.path.join(base, 'here', 'absolute.txt')) config.set('a', 'path_b', 'thisdir.txt') config.set('a', 'path_c', os.path.join(os.pardir, 'parentdir.txt')) - self.assertEquals(os.path.join(base, 'here', 'absolute.txt'), - config.getpath('a', 'path_a')) - self.assertEquals(os.path.join(base, 'thisdir.txt'), - config.getpath('a', 'path_b')) - self.assertEquals(os.path.join(os.path.dirname(base), 'parentdir.txt'), - config.getpath('a', 'path_c')) + self.assertEqual(os.path.join(base, 'here', 'absolute.txt'), + config.getpath('a', 'path_a')) + self.assertEqual(os.path.join(base, 'thisdir.txt'), + config.getpath('a', 'path_b')) + self.assertEqual(os.path.join(os.path.dirname(base), 'parentdir.txt'), + config.getpath('a', 'path_c')) + + def test_set_raises(self): + class Foo(object): + option = Option('a', 'option', 'value') + + f = Foo() + self.assertRaises(AttributeError, setattr, f, 'option', + Option('a', 'option2', 'value2')) def test_set_and_save(self): config = self._read() @@ -233,57 +321,57 @@ class ConfigurationTestCase(unittest.Tes config.set(u'aä', 'option1', u"Voilà l'été") # unicode # Note: the following would depend on the locale.getpreferredencoding() # config.set('a', 'option3', "Voil\xe0 l'\xe9t\xe9") # latin-1 - self.assertEquals('x', config.get(u'aä', u'öption0')) - self.assertEquals(u"Voilà l'été", config.get(u'aä', 'option1')) - self.assertEquals(u"Voilà l'été", config.get(u'aä', 'option2')) + self.assertEqual('x', config.get(u'aä', u'öption0')) + self.assertEqual(u"Voilà l'été", config.get(u'aä', 'option1')) + self.assertEqual(u"Voilà l'été", config.get(u'aä', 'option2')) config.save() configfile = open(self.filename, 'r') - self.assertEquals(['# -*- coding: utf-8 -*-\n', - '\n', - '[aä]\n', - "option1 = Voilà l'été\n", - "option2 = Voilà l'été\n", - 'öption0 = x\n', - # "option3 = Voilàl'été\n", - '\n', - '[b]\n', - 'öption0 = y\n', - '\n'], - configfile.readlines()) + self.assertEqual(['# -*- coding: utf-8 -*-\n', + '\n', + '[aä]\n', + "option1 = Voilà l'été\n", + "option2 = Voilà l'été\n", + 'öption0 = x\n', + # "option3 = Voilàl'été\n", + '\n', + '[b]\n', + 'öption0 = y\n', + '\n'], + configfile.readlines()) configfile.close() config2 = Configuration(self.filename) - self.assertEquals('x', config2.get(u'aä', u'öption0')) - self.assertEquals(u"Voilà l'été", config2.get(u'aä', 'option1')) - self.assertEquals(u"Voilà l'été", config2.get(u'aä', 'option2')) - # self.assertEquals(u"Voilà l'été", config2.get('a', 'option3')) + self.assertEqual('x', config2.get(u'aä', u'öption0')) + self.assertEqual(u"Voilà l'été", config2.get(u'aä', 'option1')) + self.assertEqual(u"Voilà l'été", config2.get(u'aä', 'option2')) + # self.assertEqual(u"Voilà l'été", config2.get('a', 'option3')) def test_set_and_save_inherit(self): def testcb(): config = self._read() config.set('a', 'option2', "Voilà l'été") # UTF-8 config.set('a', 'option1', u"Voilà l'été") # unicode - self.assertEquals('x', config.get('a', 'option')) - self.assertEquals(u"Voilà l'été", config.get('a', 'option1')) - self.assertEquals(u"Voilà l'été", config.get('a', 'option2')) + self.assertEqual('x', config.get('a', 'option')) + self.assertEqual(u"Voilà l'été", config.get('a', 'option1')) + self.assertEqual(u"Voilà l'été", config.get('a', 'option2')) config.save() configfile = open(self.filename, 'r') - self.assertEquals(['# -*- coding: utf-8 -*-\n', - '\n', - '[a]\n', - "option1 = Voilà l'été\n", - "option2 = Voilà l'été\n", - '\n', - '[inherit]\n', - "file = trac-site.ini\n", - '\n'], - configfile.readlines()) + self.assertEqual(['# -*- coding: utf-8 -*-\n', + '\n', + '[a]\n', + "option1 = Voilà l'été\n", + "option2 = Voilà l'été\n", + '\n', + '[inherit]\n', + "file = trac-site.ini\n", + '\n'], + configfile.readlines()) configfile.close() config2 = Configuration(self.filename) - self.assertEquals('x', config2.get('a', 'option')) - self.assertEquals(u"Voilà l'été", config2.get('a', 'option1')) - self.assertEquals(u"Voilà l'été", config2.get('a', 'option2')) + self.assertEqual('x', config2.get('a', 'option')) + self.assertEqual(u"Voilà l'été", config2.get('a', 'option1')) + self.assertEqual(u"Voilà l'été", config2.get('a', 'option2')) self._test_with_inherit(testcb) def test_simple_remove(self): @@ -292,106 +380,106 @@ class ConfigurationTestCase(unittest.Tes config.get('a', 'option') # populates the cache config.set(u'aä', u'öption', u'öne') config.remove('a', 'option') - self.assertEquals('', config.get('a', 'option')) + self.assertEqual('', config.get('a', 'option')) config.remove(u'aä', u'öption') - self.assertEquals('', config.get('aä', 'öption')) + self.assertEqual('', config.get('aä', 'öption')) config.remove('a', 'option2') # shouldn't fail config.remove('b', 'option2') # shouldn't fail def test_sections(self): self._write(['[a]', 'option = x', '[b]', 'option = y']) config = self._read() - self.assertEquals(['a', 'b'], config.sections()) + self.assertEqual(['a', 'b'], config.sections()) class Foo(object): # enclose in parentheses to avoid messages extraction section_c = (ConfigSection)('c', 'Doc for c') option_c = Option('c', 'option', 'value') - self.assertEquals(['a', 'b', 'c'], config.sections()) + self.assertEqual(['a', 'b', 'c'], config.sections()) foo = Foo() foo.config = config - self.assert_(foo.section_c is config['c']) - self.assertEquals('value', foo.section_c.get('option')) + self.assertTrue(foo.section_c is config['c']) + self.assertEqual('value', foo.section_c.get('option')) def test_sections_unicode(self): self._write([u'[aä]', u'öption = x', '[b]', 'option = y']) config = self._read() - self.assertEquals([u'aä', 'b'], config.sections()) + self.assertEqual([u'aä', 'b'], config.sections()) class Foo(object): option_c = Option(u'cä', 'option', 'value') - self.assertEquals([u'aä', 'b', u'cä'], config.sections()) + self.assertEqual([u'aä', 'b', u'cä'], config.sections()) def test_options(self): self._write(['[a]', 'option = x', '[b]', 'option = y']) config = self._read() - self.assertEquals(('option', 'x'), iter(config.options('a')).next()) - self.assertEquals(('option', 'y'), iter(config.options('b')).next()) + self.assertEqual(('option', 'x'), iter(config.options('a')).next()) + self.assertEqual(('option', 'y'), iter(config.options('b')).next()) self.assertRaises(StopIteration, iter(config.options('c')).next) - self.assertEquals('option', iter(config['a']).next()) - self.assertEquals('option', iter(config['b']).next()) + self.assertEqual('option', iter(config['a']).next()) + self.assertEqual('option', iter(config['b']).next()) self.assertRaises(StopIteration, iter(config['c']).next) class Foo(object): option_a = Option('a', 'b', 'c') - self.assertEquals([('option', 'x'), ('b', 'c')], - list(config.options('a'))) + self.assertEqual([('option', 'x'), ('b', 'c')], + list(config.options('a'))) def test_options_unicode(self): self._write([u'[ä]', u'öption = x', '[b]', 'option = y']) config = self._read() - self.assertEquals((u'öption', 'x'), iter(config.options(u'ä')).next()) - self.assertEquals(('option', 'y'), iter(config.options('b')).next()) + self.assertEqual((u'öption', 'x'), iter(config.options(u'ä')).next()) + self.assertEqual(('option', 'y'), iter(config.options('b')).next()) self.assertRaises(StopIteration, iter(config.options('c')).next) - self.assertEquals(u'öption', iter(config['ä']).next()) + self.assertEqual(u'öption', iter(config['ä']).next()) class Foo(object): option_a = Option(u'ä', u'öption2', 'c') - self.assertEquals([(u'öption', 'x'), (u'öption2', 'c')], - list(config.options(u'ä'))) + self.assertEqual([(u'öption', 'x'), (u'öption2', 'c')], + list(config.options(u'ä'))) def test_has_option(self): config = self._read() - self.assertEquals(False, config.has_option('a', 'option')) - self.assertEquals(False, 'option' in config['a']) + self.assertFalse(config.has_option('a', 'option')) + self.assertFalse('option' in config['a']) self._write(['[a]', 'option = x']) config = self._read() - self.assertEquals(True, config.has_option('a', 'option')) - self.assertEquals(True, 'option' in config['a']) + self.assertTrue(config.has_option('a', 'option')) + self.assertTrue('option' in config['a']) class Foo(object): option_a = Option('a', 'option2', 'x2') - self.assertEquals(True, config.has_option('a', 'option2')) + self.assertTrue(config.has_option('a', 'option2')) def test_has_option_unicode(self): config = self._read() - self.assertEquals(False, config.has_option(u'ä', u'öption')) - self.assertEquals(False, u'öption' in config[u'ä']) + self.assertFalse(config.has_option(u'ä', u'öption')) + self.assertFalse(u'öption' in config[u'ä']) self._write([u'[ä]', u'öption = x']) config = self._read() - self.assertEquals(True, config.has_option(u'ä', u'öption')) - self.assertEquals(True, u'öption' in config[u'ä']) + self.assertTrue(config.has_option(u'ä', u'öption')) + self.assertTrue(u'öption' in config[u'ä']) class Foo(object): option_a = Option(u'ä', u'öption2', 'x2') - self.assertEquals(True, config.has_option(u'ä', u'öption2')) + self.assertTrue(config.has_option(u'ä', u'öption2')) def test_reparse(self): self._write(['[a]', 'option = x']) config = self._read() - self.assertEquals('x', config.get('a', 'option')) + self.assertEqual('x', config.get('a', 'option')) time.sleep(2) # needed because of low mtime granularity, # especially on fat filesystems self._write(['[a]', 'option = y']) config.parse_if_needed() - self.assertEquals('y', config.get('a', 'option')) + self.assertEqual('y', config.get('a', 'option')) def test_inherit_one_level(self): def testcb(): @@ -401,7 +489,7 @@ class ConfigurationTestCase(unittest.Tes config.remove('a', 'option') # Should *not* remove option in parent self.assertEqual('x', config.get('a', 'option')) self.assertEqual([('option', 'x')], list(config.options('a'))) - self.assertEqual(True, 'a' in config) + self.assertTrue('a' in config) self._test_with_inherit(testcb) def test_inherit_multiple(self): @@ -441,6 +529,89 @@ class ConfigurationTestCase(unittest.Tes os.remove(site1) os.rmdir(os.path.dirname(site1)) + def test_option_with_raw_default(self): + class Foo(object): + # enclose in parentheses to avoid messages extraction + option_none = (Option)('a', 'none', None) + option_blah = (Option)('a', 'blah', u'Blà h!') + option_true = (BoolOption)('a', 'true', True) + option_false = (BoolOption)('a', 'false', False) + option_list = (ListOption)('a', 'list', ['#cc0', 4.2, 42L, 0, None, + True, False, None], + sep='|') + option_choice = (ChoiceOption)('a', 'choice', [-42, 42]) + + config = self._read() + config.set_defaults() + config.save() + with open(self.filename, 'r') as f: + self.assertEqual('# -*- coding: utf-8 -*-\n', f.next()) + self.assertEqual('\n', f.next()) + self.assertEqual('[a]\n', f.next()) + self.assertEqual('blah = Blà h!\n', f.next()) + self.assertEqual('choice = -42\n', f.next()) + self.assertEqual('false = disabled\n', f.next()) + self.assertEqual('list = #cc0|4.2|42|0||enabled|disabled|\n', + f.next()) + self.assertEqual('# none = <inherited>\n', f.next()) + self.assertEqual('true = enabled\n', f.next()) + self.assertEqual('\n', f.next()) + self.assertRaises(StopIteration, f.next) + + def test_unicode_option_with_raw_default(self): + class Foo(object): + # enclose in parentheses to avoid messages extraction + option_none = (Option)(u'résumé', u'nöné', None) + option_blah = (Option)(u'résumé', u'bláh', u'Blà h!') + option_true = (BoolOption)(u'résumé', u'trüé', True) + option_false = (BoolOption)(u'résumé', u'fálsé', False) + option_list = (ListOption)(u'résumé', u'liÅt', + [u'#ccö', 4.2, 42L, 0, None, True, + False, None], + sep='|') + option_choice = (ChoiceOption)(u'résumé', u'chöicé', [-42, 42]) + + config = self._read() + config.set_defaults() + config.save() + with open(self.filename, 'r') as f: + self.assertEqual('# -*- coding: utf-8 -*-\n', f.next()) + self.assertEqual('\n', f.next()) + self.assertEqual('[résumé]\n', f.next()) + self.assertEqual('bláh = Blà h!\n', f.next()) + self.assertEqual('chöicé = -42\n', f.next()) + self.assertEqual('fálsé = disabled\n', f.next()) + self.assertEqual('liÅt = #ccö|4.2|42|0||enabled|disabled|\n', + f.next()) + self.assertEqual('# nöné = <inherited>\n', f.next()) + self.assertEqual('trüé = enabled\n', f.next()) + self.assertEqual('\n', f.next()) + self.assertRaises(StopIteration, f.next) + + def test_save_changes_mtime(self): + """Test that each save operation changes the file modification time.""" + class Foo(object): + IntOption('section', 'option', 1) + sconfig = self._read() + sconfig.set_defaults() + sconfig.save() + rconfig = self._read() + self.assertEqual(1, rconfig.getint('section', 'option')) + sconfig.set('section', 'option', 2) + time.sleep(1.0 - time.time() % 1.0) + sconfig.save() + rconfig.parse_if_needed() + self.assertEqual(2, rconfig.getint('section', 'option')) + + def test_touch_changes_mtime(self): + """Test that each touch command changes the file modification time.""" + config = self._read() + time.sleep(1.0 - time.time() % 1.0) + config.touch() + mtime = os.stat(self.filename).st_mtime + config.touch() + self.assertNotEqual(mtime, os.stat(self.filename).st_mtime) + def _test_with_inherit(self, testcb): sitename = os.path.join(tempfile.gettempdir(), 'trac-site.ini') try: @@ -454,7 +625,7 @@ class ConfigurationTestCase(unittest.Tes def suite(): - return unittest.makeSuite(ConfigurationTestCase, 'test') + return unittest.makeSuite(ConfigurationTestCase) if __name__ == '__main__': unittest.main(defaultTest='suite') Modified: bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/contentgen.py URL: http://svn.apache.org/viewvc/bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/contentgen.py?rev=1639823&r1=1639822&r2=1639823&view=diff ============================================================================== --- bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/contentgen.py (original) +++ bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/contentgen.py Sat Nov 15 01:14:46 2014 @@ -1,11 +1,23 @@ -#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Copyright (C) 2008-2013 Edgewall Software +# All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://trac.edgewall.org/wiki/TracLicense. +# +# This software consists of voluntary contributions made by many +# individuals. For the exact contribution history, see the revision +# history and logs, available at http://trac.edgewall.org/log/. import random - +import uuid try: - all_words = [x.strip() for x in open('/usr/share/dict/words').readlines() if x.strip().isalpha()] -except Exception: + all_words = [x.strip() for x in open('/usr/share/dict/words').readlines() + if x.strip().isalpha()] +except IOError: all_words = [ 'one', 'two', @@ -19,37 +31,50 @@ except Exception: 'ten', ] -def random_word(): + +def random_word(min_length=1): word = random.choice(all_words) + while len(word) < min_length: + word = random.choice(all_words) # Do not return CamelCase words if word[0].isupper(): word = word.lower().capitalize() return word + _random_unique_camels = [] def random_unique_camel(): """Returns a unique camelcase word pair""" while True: - camel = random_word().title() + random_word().title() + camel = random_word(2).title() + random_word(2).title() if not camel in _random_unique_camels: break _random_unique_camels.append(camel) return camel + def random_sentence(word_count=None): - if word_count == None: + """Generates a random sentence. The first word consists of the first 8 + characters of a uuid to ensure uniqueness. + + :param word_count: number of words in the sentence + """ + if word_count is None: word_count = random.randint(1, 20) - words = [random_word() for x in range(word_count)] + words = [random_word() for x in range(word_count - 1)] + words.insert(0, str(uuid.uuid1()).split('-')[0]) return '%s.' % ' '.join(words) + def random_paragraph(sentence_count=None): - if sentence_count == None: + if sentence_count is None: sentence_count = random.randint(1, 10) sentences = [random_sentence(random.randint(2, 15)) for x in range(sentence_count)] return ' '.join(sentences) + def random_page(paragraph_count=None): - if paragraph_count == None: + if paragraph_count is None: paragraph_count = random.randint(1, 10) paragraphs = [random_paragraph(random.randint(1, 5)) for x in range(paragraph_count)] return '\r\n\r\n'.join(paragraphs) Modified: bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/core.py URL: http://svn.apache.org/viewvc/bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/core.py?rev=1639823&r1=1639822&r2=1639823&view=diff ============================================================================== --- bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/core.py (original) +++ bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/core.py Sat Nov 15 01:14:46 2014 @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright (C)2005-2009 Edgewall Software +# Copyright (C) 2005-2009 Edgewall Software # Copyright (C) 2005 Christopher Lenz <cml...@gmx.de> # All rights reserved. # @@ -14,7 +14,9 @@ # # Author: Christopher Lenz <cml...@gmx.de> +import trac.tests.compat from trac.core import * +from trac.core import ComponentManager import unittest @@ -51,7 +53,7 @@ class ComponentTestCase(unittest.TestCas registry. """ from trac.core import ComponentMeta - assert Component not in ComponentMeta._components + self.assertNotIn(Component, ComponentMeta._components) self.assertRaises(TracError, self.compmgr.__getitem__, Component) def test_abstract_component_not_registered(self): @@ -62,7 +64,7 @@ class ComponentTestCase(unittest.TestCas from trac.core import ComponentMeta class AbstractComponent(Component): abstract = True - assert AbstractComponent not in ComponentMeta._components + self.assertNotIn(AbstractComponent, ComponentMeta._components) self.assertRaises(TracError, self.compmgr.__getitem__, AbstractComponent) @@ -82,8 +84,8 @@ class ComponentTestCase(unittest.TestCas """ class ComponentA(Component): pass - assert self.compmgr[ComponentA] - assert ComponentA(self.compmgr) + self.assertTrue(self.compmgr[ComponentA]) + self.assertTrue(ComponentA(self.compmgr)) def test_component_identity(self): """ @@ -94,9 +96,9 @@ class ComponentTestCase(unittest.TestCas pass c1 = ComponentA(self.compmgr) c2 = ComponentA(self.compmgr) - assert c1 is c2, 'Expected same component instance' + self.assertIs(c1, c2, 'Expected same component instance') c2 = self.compmgr[ComponentA] - assert c1 is c2, 'Expected same component instance' + self.assertIs(c1, c2, 'Expected same component instance') def test_component_initializer(self): """ @@ -212,7 +214,7 @@ class ComponentTestCase(unittest.TestCas def test(self): return 'x' tests = iter(ComponentA(self.compmgr).tests) - self.assertEquals('x', tests.next().test()) + self.assertEqual('x', tests.next().test()) self.assertRaises(StopIteration, tests.next) def test_extension_point_with_two_extensions(self): @@ -231,7 +233,7 @@ class ComponentTestCase(unittest.TestCas def test(self): return 'y' results = [test.test() for test in ComponentA(self.compmgr).tests] - self.assertEquals(['x', 'y'], sorted(results)) + self.assertEqual(['x', 'y'], sorted(results)) def test_inherited_extension_point(self): """ @@ -246,7 +248,7 @@ class ComponentTestCase(unittest.TestCas def test(self): return 'x' tests = iter(ConcreteComponent(self.compmgr).tests) - self.assertEquals('x', tests.next().test()) + self.assertEqual('x', tests.next().test()) self.assertRaises(StopIteration, tests.next) def test_inherited_implements(self): @@ -260,7 +262,7 @@ class ComponentTestCase(unittest.TestCas class ConcreteComponent(BaseComponent): pass from trac.core import ComponentMeta - assert ConcreteComponent in ComponentMeta._registry.get(ITest, []) + self.assertIn(ConcreteComponent, ComponentMeta._registry.get(ITest, [])) def test_inherited_implements_multilevel(self): """ @@ -276,8 +278,8 @@ class ComponentTestCase(unittest.TestCas class ConcreteComponent(ChildComponent): pass from trac.core import ComponentMeta - assert ConcreteComponent in ComponentMeta._registry.get(ITest, []) - assert ConcreteComponent in ComponentMeta._registry.get(IOtherTest, []) + self.assertIn(ConcreteComponent, ComponentMeta._registry.get(ITest, [])) + self.assertIn(ConcreteComponent, ComponentMeta._registry.get(IOtherTest, [])) def test_component_manager_component(self): """ @@ -295,9 +297,9 @@ class ComponentTestCase(unittest.TestCas def test(self): return 'x' mgr = ManagerComponent('Test', 42) - assert id(mgr) == id(mgr[ManagerComponent]) + self.assertEqual(id(mgr), id(mgr[ManagerComponent])) tests = iter(mgr.tests) - self.assertEquals('x', tests.next().test()) + self.assertEqual('x', tests.next().test()) self.assertRaises(StopIteration, tests.next) def test_component_manager_component_isolation(self): @@ -308,69 +310,28 @@ class ComponentTestCase(unittest.TestCas See bh:comment:5:ticket:438 and #11121 """ - from trac.core import ComponentManager - class ManagerComponent(ComponentManager, Component): - tests = ExtensionPoint(ITest) - def __init__(self, foo, bar): - ComponentManager.__init__(self) - self.foo, self.bar = foo, bar - - class YetAnotherManagerComponent(ComponentManager, Component): - implements(ITest) - def __init__(self, foo, bar): - ComponentManager.__init__(self) - self.foo, self.bar = foo, bar - - # ITest methods - def test(self): - return self.foo + self.bar - - class ComponentA(Component): - tests = ExtensionPoint(ITest) - - class Extender(Component): + class ManagerComponentA(ComponentManager, Component): implements(ITest) def test(self): - return 'x' - - mgr = ManagerComponent('Test', 42) - yamc = YetAnotherManagerComponent('y', 'z') + pass - assert yamc[ManagerComponent] is None - assert mgr[YetAnotherManagerComponent] is None - assert yamc[ComponentManager] is None - assert self.compmgr[YetAnotherManagerComponent] is None - assert mgr[ComponentManager] is None - assert self.compmgr[ManagerComponent] is None - - self.assertTrue(any(c.__class__ is YetAnotherManagerComponent - for c in ComponentA(yamc).tests)) - self.assertFalse(any(c.__class__ is YetAnotherManagerComponent - for c in ComponentA(self.compmgr).tests)) - self.assertFalse(any(c.__class__ is YetAnotherManagerComponent - for c in ComponentA(mgr).tests)) - self.assertFalse(any(c.__class__ is ManagerComponent - for c in ComponentA(yamc).tests)) - self.assertFalse(any(c.__class__ is YetAnotherManagerComponent - for c in mgr.tests)) + class ManagerComponentB(ManagerComponentA): + pass - results = [test.test() for test in ComponentA(yamc).tests] - self.assertEquals(['x', 'yz'], sorted(results)) + class Tester(Component): + tests = ExtensionPoint(ITest) - results = [test.test() for test in ComponentA(self.compmgr).tests] - self.assertEquals(['x'], sorted(results)) + mgrA = ManagerComponentA() + mgrB = ManagerComponentB() - results = [test.test() for test in ComponentA(mgr).tests] - self.assertEquals(['x'], sorted(results)) - results = [test.test() for test in mgr.tests] - self.assertEquals(['x'], sorted(results)) + self.assertEqual([mgrA], Tester(mgrA).tests) + self.assertEqual([mgrB], Tester(mgrB).tests) def test_instantiation_doesnt_enable(self): """ Make sure that a component disabled by the ComponentManager is not implicitly enabled by instantiating it directly. """ - from trac.core import ComponentManager class DisablingComponentManager(ComponentManager): def is_component_enabled(self, cls): return False @@ -378,10 +339,21 @@ class ComponentTestCase(unittest.TestCas pass mgr = DisablingComponentManager() instance = ComponentA(mgr) - self.assertEqual(None, mgr[ComponentA]) + self.assertIsNone(mgr[ComponentA]) + + def test_invalid_argument_raises(self): + """ + AssertionError is raised when first argument to initializer is not a + ComponentManager instance. + """ + class ComponentA(Component): + pass + self.assertRaises(AssertionError, Component) + def suite(): - return unittest.makeSuite(ComponentTestCase, 'test') + return unittest.makeSuite(ComponentTestCase) + if __name__ == '__main__': - unittest.main() + unittest.main(defaultTest='suite') Modified: bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/env.py URL: http://svn.apache.org/viewvc/bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/env.py?rev=1639823&r1=1639822&r2=1639823&view=diff ============================================================================== --- bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/env.py (original) +++ bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/env.py Sat Nov 15 01:14:46 2014 @@ -1,24 +1,72 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2003-2013 Edgewall Software +# All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://trac.edgewall.org/wiki/TracLicense. +# +# This software consists of voluntary contributions made by many +# individuals. For the exact contribution history, see the revision +# history and logs, available at http://trac.edgewall.org/log/. + from __future__ import with_statement +from ConfigParser import RawConfigParser +import os.path +import shutil +import tempfile +import unittest + +import trac.tests.compat from trac import db_default +from trac.core import ComponentManager from trac.env import Environment +from trac.test import EnvironmentStub -import os.path -import unittest -import tempfile -import shutil + +class EnvironmentCreatedWithoutData(Environment): + def __init__(self, path, create=False, options=[]): + ComponentManager.__init__(self) + + self.path = path + self.systeminfo = [] + self.href = self.abs_href = None + + if create: + self.create(options) + else: + self.verify() + self.setup_config() + + +class EmptyEnvironmentTestCase(unittest.TestCase): + + def setUp(self): + env_path = tempfile.mkdtemp(prefix='trac-tempenv-') + self.env = EnvironmentCreatedWithoutData(env_path, create=True) + + def tearDown(self): + self.env.shutdown() # really closes the db connections + shutil.rmtree(self.env.path) + + def test_get_version(self): + """Testing env.get_version""" + self.assertFalse(self.env.get_version()) class EnvironmentTestCase(unittest.TestCase): def setUp(self): - env_path = os.path.join(tempfile.gettempdir(), 'trac-tempenv') + env_path = tempfile.mkdtemp(prefix='trac-tempenv-') self.addCleanup(self.cleanupEnvPath, env_path) self.env = Environment(env_path, create=True) + self.env.config.set('trac', 'base_url', + 'http://trac.edgewall.org/some/path') + self.env.config.save() def tearDown(self): - with self.env.db_query as db: - db.close() self.env.shutdown() # really closes the db connections shutil.rmtree(self.env.path) @@ -26,33 +74,77 @@ class EnvironmentTestCase(unittest.TestC if os.path.exists(path): shutil.rmtree(path) + def test_db_exc(self): + db_exc = self.env.db_exc + self.assertTrue(hasattr(db_exc, 'IntegrityError')) + self.assertIs(db_exc, self.env.db_exc) + + def test_abs_href(self): + abs_href = self.env.abs_href + self.assertEqual('http://trac.edgewall.org/some/path', abs_href()) + self.assertIs(abs_href, self.env.abs_href) + + def test_href(self): + href = self.env.href + self.assertEqual('/some/path', href()) + self.assertIs(href, self.env.href) + def test_get_version(self): """Testing env.get_version""" - assert self.env.get_version() == db_default.db_version + self.assertEqual(db_default.db_version, self.env.get_version()) + self.assertEqual(db_default.db_version, self.env.database_version) + self.assertEqual(db_default.db_version, self.env.database_initial_version) def test_get_known_users(self): """Testing env.get_known_users""" with self.env.db_transaction as db: db.executemany("INSERT INTO session VALUES (%s,%s,0)", - [('123', 0),('tom', 1), ('joe', 1), ('jane', 1)]) + [('123', 0), ('tom', 1), ('joe', 1), ('jane', 1)]) db.executemany("INSERT INTO session_attribute VALUES (%s,%s,%s,%s)", - [('123', 0, 'email', 'a...@example.com'), - ('tom', 1, 'name', 'Tom'), - ('tom', 1, 'email', 't...@example.com'), - ('joe', 1, 'email', 'j...@example.com'), - ('jane', 1, 'name', 'Jane')]) + [('123', 0, 'email', 'a...@example.com'), + ('tom', 1, 'name', 'Tom'), + ('tom', 1, 'email', 't...@example.com'), + ('joe', 1, 'email', 'j...@example.com'), + ('jane', 1, 'name', 'Jane')]) users = {} for username, name, email in self.env.get_known_users(): users[username] = (name, email) - assert not users.has_key('anonymous') + self.assertTrue('anonymous' not in users) self.assertEqual(('Tom', 't...@example.com'), users['tom']) self.assertEqual((None, 'j...@example.com'), users['joe']) self.assertEqual(('Jane', None), users['jane']) + def test_is_component_enabled(self): + self.assertEqual(True, Environment.required) + self.assertEqual(True, self.env.is_component_enabled(Environment)) + self.assertEqual(False, EnvironmentStub.required) + self.assertEqual(None, self.env.is_component_enabled(EnvironmentStub)) + + def test_dumped_values_in_tracini(self): + parser = RawConfigParser() + filename = self.env.config.filename + self.assertEqual([filename], parser.read(filename)) + self.assertEqual('#cc0,#0c0,#0cc,#00c,#c0c,#c00', + parser.get('revisionlog', 'graph_colors')) + self.assertEqual('disabled', parser.get('trac', 'secure_cookies')) + + def test_dumped_values_in_tracini_sample(self): + parser = RawConfigParser() + filename = self.env.config.filename + '.sample' + self.assertEqual([filename], parser.read(filename)) + self.assertEqual('#cc0,#0c0,#0cc,#00c,#c0c,#c00', + parser.get('revisionlog', 'graph_colors')) + self.assertEqual('disabled', parser.get('trac', 'secure_cookies')) + self.assertTrue(parser.has_option('logging', 'log_format')) + self.assertEqual('', parser.get('logging', 'log_format')) + def suite(): - return unittest.makeSuite(EnvironmentTestCase,'test') + suite = unittest.TestSuite() + suite.addTest(unittest.makeSuite(EnvironmentTestCase)) + suite.addTest(unittest.makeSuite(EmptyEnvironmentTestCase)) + return suite if __name__ == '__main__': unittest.main(defaultTest='suite') Modified: bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/functional/__init__.py URL: http://svn.apache.org/viewvc/bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/functional/__init__.py?rev=1639823&r1=1639822&r2=1639823&view=diff ============================================================================== --- bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/functional/__init__.py (original) +++ bloodhound/branches/trac-1.0.2-integration/trac/trac/tests/functional/__init__.py Sat Nov 15 01:14:46 2014 @@ -1,4 +1,17 @@ -#!/usr/bin/python +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright (C) 2008-2013 Edgewall Software +# All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://trac.edgewall.org/wiki/TracLicense. +# +# This software consists of voluntary contributions made by many +# individuals. For the exact contribution history, see the revision +# history and logs, available at http://trac.edgewall.org/log/. + """functional_tests While unittests work well for testing facets of an implementation, they fail to @@ -42,17 +55,19 @@ Requirements: - lxml for XHTML validation (optional) """ +import exceptions import os +import shutil import signal +import stat import sys import time -import shutil -import stat import unittest -import exceptions +from datetime import datetime, timedelta import trac -from trac.tests.functional.compat import close_fds, rmtree +from trac.tests.compat import rmtree +from trac.util.compat import close_fds # Handle missing twill so we can print a useful 'SKIP' # message. We import subprocess first to allow customizing it on Windows @@ -60,7 +75,7 @@ from trac.tests.functional.compat import # is allowed to load first, its (unmodified) copy will always be loaded. import subprocess -from better_twill import twill, b, tc, ConnectError +from trac.tests.functional.better_twill import twill, b, tc, ConnectError try: # This is the first indicator of whether the subversion bindings are @@ -70,11 +85,15 @@ try: except ImportError: has_svn = False -from datetime import datetime, timedelta +try: + from configobj import ConfigObj +except ImportError: + ConfigObj = None + print "SKIP: fine-grained permission tests (ConfigObj not installed)" +from trac.test import TestSetup, TestCaseSetup from trac.tests.contentgen import random_sentence, random_page, random_word, \ random_unique_camel -from trac.test import TestSetup, TestCaseSetup internal_error = 'Trac detected an internal error:' @@ -112,14 +131,23 @@ if twill: subdirectory 'testenv<portnum>'. """ if port is None: - port = 8000 + os.getpid() % 1000 - dirname = "testenv" + try: + port = int(os.getenv('TRAC_TEST_PORT')) + except (TypeError, ValueError): + pass + + env_path = os.getenv('TRAC_TEST_ENV_PATH') + if not env_path: + env_name = 'testenv%s' % (port or '') + env_path = os.path.join(trac_source_tree, env_name) else: - dirname = "testenv%s" % port - dirname = os.path.join(trac_source_tree, dirname) + env_path += str(port or '') + + if port is None: + port = 8000 + os.getpid() % 1000 baseurl = "http://127.0.0.1:%s" % port - self._testenv = self.env_class(dirname, port, baseurl) + self._testenv = self.env_class(env_path, port, baseurl) self._testenv.start() self._tester = self.tester_class(baseurl) self.fixture = (self._testenv, self._tester) @@ -137,10 +165,16 @@ if twill: class FunctionalTwillTestCaseSetup(FunctionalTestCaseSetup): failureException = twill.errors.TwillAssertionError + else: # We're going to have to skip the functional tests + class FunctionalTestSuite(TestSetup): + def __init__(self): + raise ImportError("Twill not installed") + class FunctionalTwillTestCaseSetup: pass + class FunctionalTestCaseSetup: pass @@ -151,15 +185,33 @@ def regex_owned_by(username): return '(Owned by:(<[^>]*>|\\n| )*%s)' % username +def functionalSuite(): + suite = FunctionalTestSuite() + return suite + + def suite(): - if twill: - from trac.tests.functional.testcases import suite - suite = suite() - else: - diagnostic = "SKIP: functional tests" - if not twill: - diagnostic += " (no twill installed)" - print diagnostic + try: + suite = functionalSuite() + import trac.tests.functional.testcases + trac.tests.functional.testcases.functionalSuite(suite) + import trac.versioncontrol.tests + trac.versioncontrol.tests.functionalSuite(suite) + import trac.ticket.tests + trac.ticket.tests.functionalSuite(suite) + import trac.prefs.tests + trac.prefs.tests.functionalSuite(suite) + import trac.wiki.tests + trac.wiki.tests.functionalSuite(suite) + import trac.timeline.tests + trac.timeline.tests.functionalSuite(suite) + import trac.admin.tests + trac.admin.tests.functionalSuite(suite) + # The db tests should be last since the backup test occurs there. + import trac.db.tests + trac.db.tests.functionalSuite(suite) + except ImportError, e: + print("SKIP: functional tests (%s)" % e) # No tests to run, provide an empty suite. suite = unittest.TestSuite() return suite