You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bloodhound.apache.org by rj...@apache.org on 2014/02/27 03:14:38 UTC
svn commit: r1572404 [4/8] - in
/bloodhound/branches/bep_0007_embeddable_objects: ./ bloodhound_dashboard/
bloodhound_dashboard/bhdashboard/
bloodhound_dashboard/bhdashboard/default-pages/
bloodhound_dashboard/bhdashboard/layouts/ bloodhound_dashboard/...
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/__init__.py
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/__init__.py?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/__init__.py (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/__init__.py Thu Feb 27 02:14:33 2014
@@ -1,4 +1,5 @@
-
+# -*- coding: utf-8 -*-
+#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
@@ -16,15 +17,17 @@
# specific language governing permissions and limitations
# under the License.
+import logging
+import sys
from collections import deque
from fnmatch import fnmatch
-import sys
-try:
+if sys.version_info < (2, 7):
import unittest2 as unittest
-except ImportError:
+else:
import unittest
-from pkg_resources import resource_listdir, resource_isdir, resource_exists
+from pkg_resources import resource_exists, resource_filename, \
+ resource_isdir, resource_listdir
class TestLoader(unittest.TestLoader):
@@ -33,7 +36,8 @@ class TestLoader(unittest.TestLoader):
sortTestMethodsUsing = cmp
suiteClass = unittest.TestSuite
- def discover_package(self, package_or_requirement, pattern='test*.py', ignore_subpkg_root=True):
+ def discover_package(self, package_or_requirement, pattern='*/test*.py',
+ ignore_subpkg_root=True, exclude=None):
"""Find and return all test modules from the specified package
directory, recursing into subdirectories to find them. Only test files
that match the pattern will be loaded. (Using shell style pattern
@@ -43,17 +47,23 @@ class TestLoader(unittest.TestLoader):
and registered with `pkg_resources` (e.g. via `setup.py develop`).
If a target test module contains a '__testloader__' attribute then
- related object will override current loader for every individual
+ related object will override current loader for every individual
module across the hierarchy.
"""
pending = deque([(package_or_requirement, self, True)])
tests = []
+ log = logging.getLogger('bh.tests')
+ if len(log.handlers) == 0:
+ # Configure logger instance. otherwise messages won't be displayed
+ _configure_logger(log)
while pending:
mdlnm, loader, isdir = pending.popleft()
try:
mdl = self._get_module_from_name(mdlnm)
except (ImportError, ValueError):
- # Skip packages not having __init__.py
+ # Log import error and skip packages that don't import
+ log.exception('Discovered package %s but import failed',
+ mdlnm)
continue
loader = getattr(mdl, self.testLoaderAttribute, None) or loader
if not (isdir and ignore_subpkg_root):
@@ -63,12 +73,18 @@ class TestLoader(unittest.TestLoader):
tests.append(loader.loadTestsFromModule(mdl))
if isdir and resource_exists(mdlnm, '__init__.py'):
for fnm in resource_listdir(mdlnm, ''):
- if resource_isdir(mdlnm, fnm):
- pending.append( (mdlnm + '.' + fnm, loader, True) )
+ fpath = resource_filename(mdlnm, fnm)
+ if resource_isdir(mdlnm, fnm) \
+ and (exclude is None
+ or not fnmatch(fpath + '/', exclude)):
+ pending.append((mdlnm + '.' + fnm, loader, True))
elif any(fnm.endswith(ext) for ext in ['.py', '.pyc']) \
- and fnmatch(fnm, pattern) and fnm != '__init__.py':
+ and fnmatch(fpath, pattern) \
+ and fnm != '__init__.py'\
+ and (exclude is None
+ or not fnmatch(fpath, exclude)):
submdlnm = mdlnm + '.' + fnm.rsplit('.', 1)[0]
- pending.append( (submdlnm, loader, False) )
+ pending.append((submdlnm, loader, False))
return self.suiteClass(tests)
def _get_module_from_name(self, name):
@@ -76,8 +92,17 @@ class TestLoader(unittest.TestLoader):
return sys.modules[name]
+def _configure_logger(log):
+ # See logging.basicConfig
+ handler = logging.StreamHandler()
+ formatter = logging.Formatter(logging.BASIC_FORMAT, None)
+ handler.setFormatter(formatter)
+ log.addHandler(handler)
+
+
def test_suite():
- return TestLoader().discover_package('tests', pattern='*.py')
+ return TestLoader().discover_package('tests', pattern='*.py',
+ exclude='*/functional/*')
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/admin/__init__.py
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/admin/__init__.py?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/admin/__init__.py (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/admin/__init__.py Thu Feb 27 02:14:33 2014
@@ -1,4 +1,5 @@
-
+# -*- coding: utf-8 -*-
+#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
@@ -22,4 +23,3 @@ from tests import TestLoader
def test_suite():
return TestLoader().discover_package(__name__, pattern='*.py')
-
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/admin/console-tests.txt
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/admin/console-tests.txt?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/admin/console-tests.txt (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/admin/console-tests.txt Thu Feb 27 02:14:33 2014
@@ -1022,3 +1022,115 @@ name17 0 2010-01-18 val17 val17
name18 0 2010-01-19 val18 val18
name19 0 2010-01-20 val19 val19
+===== test_product_help_ok =====
+trac-admin - The Trac Administration Console 1.0.1
+help Show documentation
+initenv Create and initialize a new environment
+attachment add Attach a file to a resource
+attachment export Export an attachment from a resource to a file or stdout
+attachment list List attachments of a resource
+attachment remove Remove an attachment from a resource
+changeset added Notify trac about changesets added to a repository
+changeset modified Notify trac about changesets modified in a repository
+component add Add a new component
+component chown Change component ownership
+component list Show available components
+component remove Remove/uninstall a component
+component rename Rename a component
+config get Get the value of the given option in "trac.ini"
+config remove Remove the specified option from "trac.ini"
+config set Set the value for the given option in "trac.ini"
+deploy Extract static resources from Trac and all plugins
+hotcopy Make a hot backup copy of an environment
+milestone add Add milestone
+milestone completed Set milestone complete date
+milestone due Set milestone due date
+milestone list Show milestones
+milestone remove Remove milestone
+milestone rename Rename milestone
+permission add Add a new permission rule
+permission export Export permission rules to a file or stdout as CSV
+permission import Import permission rules from a file or stdin as CSV
+permission list List permission rules
+permission remove Remove a permission rule
+priority add Add a priority value option
+priority change Change a priority value
+priority list Show possible ticket priorities
+priority order Move a priority value up or down in the list
+priority remove Remove a priority value
+repository add Add a source repository
+repository alias Create an alias for a repository
+repository list List source repositories
+repository remove Remove a source repository
+repository resync Re-synchronize trac with repositories
+repository set Set an attribute of a repository
+repository sync Resume synchronization of repositories
+resolution add Add a resolution value option
+resolution change Change a resolution value
+resolution list Show possible ticket resolutions
+resolution order Move a resolution value up or down in the list
+resolution remove Remove a resolution value
+session add Create a session for the given sid
+session delete Delete the session of the specified sid
+session list List the name and email for the given sids
+session purge Purge all anonymous sessions older than the given age
+session set Set the name or email attribute of the given sid
+severity add Add a severity value option
+severity change Change a severity value
+severity list Show possible ticket severities
+severity order Move a severity value up or down in the list
+severity remove Remove a severity value
+ticket remove Remove ticket
+ticket_type add Add a ticket type
+ticket_type change Change a ticket type
+ticket_type list Show possible ticket types
+ticket_type order Move a ticket type up or down in the list
+ticket_type remove Remove a ticket type
+upgrade Upgrade database to current version
+version add Add version
+version list Show versions
+version remove Remove version
+version rename Rename version
+version time Set version date
+wiki dump Export wiki pages to files named by title
+wiki export Export wiki page to file or stdout
+wiki import Import wiki page from file or stdin
+wiki list List wiki pages
+wiki load Import wiki pages from files
+wiki remove Remove wiki page
+wiki rename Rename wiki page
+wiki replace Replace the content of wiki pages from files (DANGEROUS!)
+wiki upgrade Upgrade default wiki pages to current version
+===== test_product_help_version =====
+version add <name> [time]
+
+ Add version
+
+version list
+
+ Show versions
+
+version remove <name>
+
+ Remove version
+
+version rename <name> <newname>
+
+ Rename version
+
+version time <name> <time>
+
+ Set version date
+
+===== test_product_help_version_add =====
+version add <name> [time]
+
+ Add version
+
+===== test_product_fail_version_add =====
+Error: Invalid arguments
+
+version add <name> [time]
+
+ Add version
+
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/admin/console.py
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/admin/console.py?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/admin/console.py (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/admin/console.py Thu Feb 27 02:14:33 2014
@@ -1,4 +1,5 @@
-
+# -*- coding: utf-8 -*-
+#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
@@ -20,16 +21,15 @@
import os.path
import sys
-from StringIO import StringIO
import unittest
-from trac.admin.tests.console import load_expected_results, \
- STRIP_TRAILING_SPACE, TracadminTestCase
+from trac.admin.tests.console import TracadminTestCase, load_expected_results
from multiproduct.env import ProductEnvironment
from tests.env import MultiproductTestCase
-class ProductTracadminTestCase(TracadminTestCase, MultiproductTestCase):
+
+class ProductTracAdminTestCase(TracadminTestCase, MultiproductTestCase):
expected_results = load_expected_results(
os.path.join(os.path.split(__file__)[0], 'console-tests.txt'),
@@ -40,14 +40,14 @@ class ProductTracadminTestCase(Tracadmin
env = getattr(self, '_env', None)
if env is None:
self.global_env = self._setup_test_env(
- enable=('trac.*', 'multiproduct.*'),
+ enable=('trac.*', 'multiproduct.*'),
disable=('trac.tests.*',),
- )
+ )
self._upgrade_mp(self.global_env)
self._setup_test_log(self.global_env)
self._load_product_from_data(self.global_env, self.default_product)
- self._env = env = ProductEnvironment(
- self.global_env, self.default_product)
+ self._env = env = ProductEnvironment(self.global_env,
+ self.default_product)
self._load_default_data(env)
return env
@@ -59,41 +59,41 @@ class ProductTracadminTestCase(Tracadmin
self.global_env.reset_db()
self.global_env = self._env = None
- def _execute(self, cmd, strip_trailing_space=True, input=None):
- _in = sys.stdin
- _err = sys.stderr
- _out = sys.stdout
- try:
- if input:
- sys.stdin = StringIO(input.encode('utf-8'))
- sys.stdin.encoding = 'utf-8' # fake input encoding
- sys.stderr = sys.stdout = out = StringIO()
- out.encoding = 'utf-8' # fake output encoding
- retval = None
- try:
- retval = self._admin.onecmd(cmd)
- except SystemExit:
- pass
- value = out.getvalue()
- if isinstance(value, str): # reverse what print_listing did
- value = value.decode('utf-8')
- if retval != 0:
- self.env.log.debug('trac-admin failure: %s', value)
- if strip_trailing_space:
- return retval, STRIP_TRAILING_SPACE.sub('', value)
- else:
- return retval, value
- finally:
- sys.stdin = _in
- sys.stderr = _err
- sys.stdout = _out
+ def test_product_help_ok(self):
+ self._admin.env_set('', self.global_env)
+ from trac import __version__
+ test_name = sys._getframe().f_code.co_name
+ expected_results = self.expected_results[test_name] \
+ % {'version': __version__}
+ rv, output = self._execute('product admin %s help'
+ % self.default_product)
+ self.assertEqual(0, rv)
+ self.assertEqual(expected_results, output)
+
+ def test_product_help_version(self):
+ rv, output = self._execute('help version')
+ self.assertEqual(0, rv)
+ expected = self.expected_results[self._testMethodName]
+ self.assertEqual(expected, output)
+
+ def test_product_help_version_add(self):
+ rv, output = self._execute('help version add')
+ self.assertEqual(0, rv)
+ expected = self.expected_results[self._testMethodName]
+ self.assertEqual(expected, output)
+
+ def test_product_fail_version_add(self):
+ rv, output = self._execute('version add v x y')
+ self.assertEqual(2, rv)
+ expected = self.expected_results[self._testMethodName]
+ self.assertEqual(expected, output)
def test_suite():
return unittest.TestSuite([
- unittest.makeSuite(ProductTracadminTestCase,'test'),
- ])
+ unittest.makeSuite(ProductTracAdminTestCase),
+ ])
+
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
-
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/admin/product_admin.py
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/admin/product_admin.py?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/admin/product_admin.py (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/admin/product_admin.py Thu Feb 27 02:14:33 2014
@@ -1,4 +1,5 @@
-
+# -*- coding: utf-8 -*-
+#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
@@ -54,11 +55,11 @@ class TestAdminPanel(Component):
yield 'testcat1', 'Test category 1', 'panel1', 'Test panel 1'
yield 'testcat1', 'Test category 1', 'panel2', 'Test panel 2'
yield 'testcat1', 'Test category 1', 'panel3', 'Test panel 3'
-
+
yield 'testcat2', 'Test category 2', 'panel1', 'Test panel 1'
yield 'testcat2', 'Test category 2', 'panel_2', 'Test panel 2'
yield 'testcat2', 'Test category 2', 'panel-3', 'Test panel 3'
-
+
yield 'testcat3', 'Test category 3', 'panel1', 'Test panel 1'
yield 'testcat3', 'Test category 3', 'panel2', 'Test panel 2'
@@ -106,10 +107,10 @@ class BaseProductAdminPanelTestCase(Mult
def setUp(self):
self._mp_setup(enable=[AdminModule, DefaultPermissionPolicy,
DefaultPermissionStore, PermissionSystem,
- PluginAdminPanel, RequestDispatcher,
+ PluginAdminPanel, RequestDispatcher,
api.MultiProductSystem,
product_admin.ProductAdminModule,
- PanelsWhitelist, SectionWhitelist,
+ PanelsWhitelist, SectionWhitelist,
TestAdminPanel, TestPermissionRequestor])
self.global_env = self.env
self.env = ProductEnvironment(self.global_env, self.default_product)
@@ -125,10 +126,10 @@ class BaseProductAdminPanelTestCase(Mult
class ProductAdminSetupTestCase(BaseProductAdminPanelTestCase):
- ALL_PANELS = [('testcat1', 'panel1'), ('testcat1', 'panel2'),
- ('testcat1', 'panel3'), ('testcat2', 'panel_1'),
- ('testcat2', 'panel-2'), ('testcat2', 'panel3'),
- ('testcat3', 'panel1'), ('testcat3', 'panel2'),
+ ALL_PANELS = [('testcat1', 'panel1'), ('testcat1', 'panel2'),
+ ('testcat1', 'panel3'), ('testcat2', 'panel_1'),
+ ('testcat2', 'panel-2'), ('testcat2', 'panel3'),
+ ('testcat3', 'panel1'), ('testcat3', 'panel2'),
('general', 'plugin'), ]
def test_init_whitelist(self):
@@ -137,7 +138,7 @@ class ProductAdminSetupTestCase(BaseProd
('testcat1', 'panel1') : True,
('testcat1', 'panel3'): True,
('testcat2', 'panel3'): True,
- ('general', 'plugin') : True,},
+ ('general', 'plugin') : True,},
self.product_admin.acl)
self.assertTrue(all(not self.global_product_admin._check_panel(c, p)
for c, p in self.ALL_PANELS))
@@ -153,9 +154,9 @@ class ProductAdminSetupTestCase(BaseProd
self.assertFalse(self.product_admin._check_panel('other', 'panel'))
def test_init_blacklist(self):
- self.global_env.config.set('multiproduct', 'admin_blacklist',
+ self.global_env.config.set('multiproduct', 'admin_blacklist',
'testcat1:panel1,testcat3:panel2')
- self.env.config.set('multiproduct', 'admin_blacklist',
+ self.env.config.set('multiproduct', 'admin_blacklist',
'testcat1:panel3,testcat3:panel1,testcat2:*')
self.assertEqual(['testcat1:panel1','testcat3:panel2'],
@@ -170,7 +171,7 @@ class ProductAdminSetupTestCase(BaseProd
('testcat1', 'panel3'): False,
('testcat2', 'panel3'): True,
('testcat3', 'panel1'): False,
- ('general', 'plugin'): True,},
+ ('general', 'plugin'): True,},
self.product_admin.acl)
self.assertTrue(all(not self.global_product_admin._check_panel(c, p)
@@ -192,9 +193,9 @@ class ProductAdminDispatchTestCase(BaseP
def setUp(self):
BaseProductAdminPanelTestCase.setUp(self)
- self.global_env.config.set('multiproduct', 'admin_blacklist',
+ self.global_env.config.set('multiproduct', 'admin_blacklist',
'testcat1:panel1,testcat3:panel2')
- self.env.config.set('multiproduct', 'admin_blacklist',
+ self.env.config.set('multiproduct', 'admin_blacklist',
'testcat1:panel3,testcat3:panel1,testcat2:*')
global_permsys = PermissionSystem(self.global_env)
permsys = PermissionSystem(self.env)
@@ -502,4 +503,3 @@ def test_suite():
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
-
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/attachment.py
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/attachment.py?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/attachment.py (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/attachment.py Thu Feb 27 02:14:33 2014
@@ -1,4 +1,5 @@
-
+# -*- coding: utf-8 -*-
+#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
@@ -68,4 +69,3 @@ def test_suite():
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
-
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/config.py
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/config.py?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/config.py (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/config.py Thu Feb 27 02:14:33 2014
@@ -19,12 +19,13 @@
"""Tests for Apache(TM) Bloodhound's product configuration objects"""
-from ConfigParser import ConfigParser
-from itertools import groupby
import os.path
import shutil
-from StringIO import StringIO
+import time
import unittest
+from ConfigParser import ConfigParser
+from StringIO import StringIO
+from itertools import groupby
from trac.config import Option
from trac.tests.config import ConfigurationTestCase
@@ -35,9 +36,8 @@ from multiproduct.config import Configur
from multiproduct.model import Product, ProductSetting
from tests.env import MultiproductTestCase
-class ProductConfigTestCase(ConfigurationTestCase, MultiproductTestCase):
- r"""Test cases for Trac configuration objects rewritten for product
- scope.
+class MultiproductConfigTestCase(MultiproductTestCase):
+ r"""Test setup for configuration test cases.
"""
def setUp(self):
r"""Replace Trac environment with product environment
@@ -48,7 +48,7 @@ class ProductConfigTestCase(Configuratio
tmpdir = os.path.realpath(self.env.path)
self.filename = os.path.join(tmpdir, 'conf', 'product.ini')
# Ensure conf sub-folder is created
- os.mkdir(os.path.dirname(self.filename))
+ os.path.dirname(self.filename)
self._upgrade_mp(self.env)
self._setup_test_log(self.env)
@@ -82,13 +82,13 @@ class ProductConfigTestCase(Configuratio
parser.readfp(fp, 'bh-product-test')
with self.env.db_transaction as db:
# Delete existing setting for target product , if any
- for setting in ProductSetting.select(self.env, db,
+ for setting in ProductSetting.select(self.env, db,
{'product' : product}):
setting.delete()
# Insert new options
for section in parser.sections():
option_key = dict(
- section=to_unicode(section),
+ section=to_unicode(section),
product=to_unicode(product)
)
for option, value in parser.items(section):
@@ -121,7 +121,7 @@ class ProductConfigTestCase(Configuratio
def _dump_settings(self, config):
product = config.product
fields = ('section', 'option', 'value')
- rows = [tuple(getattr(s, f, None) for f in fields) for s in
+ rows = [tuple(getattr(s, f, None) for f in fields) for s in
ProductSetting.select(config.env, where={'product' : product})]
dump = []
@@ -131,7 +131,12 @@ class ProductConfigTestCase(Configuratio
dump.append('%s = %s\n' % (row[1], row[2]))
return dump
- # Test cases rewritten to avoid reading config file.
+
+class ProductConfigTestCase(MultiproductConfigTestCase, ConfigurationTestCase):
+ r"""Test cases for Trac configuration objects rewritten for product
+ scope.
+ """
+ # Test cases rewritten to avoid reading config file.
# It does make sense for product config as it's stored in the database
def test_set_and_save(self):
@@ -150,12 +155,12 @@ class ProductConfigTestCase(Configuratio
dump = self._dump_settings(config)
self.assertEquals([
u'[aä]\n',
- u"option1 = Voilà l'été\n",
- u"option2 = Voilà l'été\n",
- u'öption0 = x\n',
- # u"option3 = Voilàl'été\n",
+ u"option1 = Voilà l'été\n",
+ u"option2 = Voilà l'été\n",
+ u'öption0 = x\n',
+ # u"option3 = Voilàl'été\n",
u'[b]\n',
- u'öption0 = y\n',
+ u'öption0 = y\n',
],
dump)
config2 = self._read()
@@ -177,10 +182,10 @@ class ProductConfigTestCase(Configuratio
dump = self._dump_settings(config)
self.assertEquals([
u'[a]\n',
- u"option1 = Voilà l'été\n",
- u"option2 = Voilà l'été\n",
+ u"option1 = Voilà l'été\n",
+ u"option2 = Voilà l'été\n",
u'[inherit]\n',
- u"file = trac-site.ini\n",
+ u"file = trac-site.ini\n",
],
dump)
config2 = self._read()
@@ -196,9 +201,62 @@ class ProductConfigTestCase(Configuratio
config.set('a', 'option', 'value2')
self.assertEquals('value2', config.get('a', 'option'))
+
+class ProductConfigSyncTestCase(MultiproductConfigTestCase):
+ """Test cases for concurrent access of product configuration objects.
+ """
+ def test_sync(self):
+ """Config cache consistency on concurrent edits
+ """
+ config1 = self._read()
+ config2 = self._read()
+
+ # Initial values will be empty
+ # This will initialize both instances' cache
+ self.assertEqual('', config1.get('s', 'o'))
+ self.assertEqual('', config2.get('s', 'o'))
+
+ # First time assignment, no actual cache
+ config1.set('s', 'o', 'value0')
+ self.assertEqual('value0', config1.get('s', 'o'))
+ self.assertEqual('value0', config2.get('s', 'o'))
+
+ # Subsequent hits retrieved from cache
+ config1.set('s', 'o', 'value1')
+ self.assertEqual('value0', config2.get('s', 'o'))
+ # ... unless cache invalidated e.g. by calling save()
+ config1.save()
+ self.assertTrue(config2.parse_if_needed())
+ self.assertEqual('value1', config1.get('s', 'o'))
+ self.assertEqual('value1', config2.get('s', 'o'))
+
+ # TODO: Replace with trac.util.compat:wait_for_file_mtime_change when
+ # changes from Trac 1.0-stable (> r12258) or Trac 1.0.2 are integrated
+ # Two edits may look simultaneous depending on FS accuracy,
+ # so wait 1 second to ensure next timestamp below will be different
+ # otherwise the test is fragile and results non-deterministic.
+ # This holds for Trac config objects too.
+ time.sleep(1)
+
+ # After update no subsequent modifications reported
+ config2.set('s', 'o', 'value2')
+ self.assertFalse(config1.parse_if_needed())
+ self.assertEqual('value1', config1.get('s', 'o'))
+ # ... unless cache invalidated e.g. by calling touch()
+ config2.touch()
+ self.assertTrue(config1.parse_if_needed())
+ self.assertEqual('value2', config1.get('s', 'o'))
+ self.assertEqual('value2', config2.get('s', 'o'))
+ self.assertTrue(config2.parse_if_needed())
+
+
def test_suite():
- return unittest.makeSuite(ProductConfigTestCase,'test')
+ suite = unittest.TestSuite()
+
+ suite.addTest(unittest.makeSuite(ProductConfigTestCase,'test'))
+ suite.addTest(unittest.makeSuite(ProductConfigSyncTestCase,'test'))
+
+ return suite
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
-
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/core.py
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/core.py?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/core.py (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/core.py Thu Feb 27 02:14:33 2014
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
@@ -15,16 +17,13 @@
# specific language governing permissions and limitations
# under the License.
-import sys
-if sys.version < (2, 7):
- import unittest2 as unittest
-else:
- import unittest
+from tests import unittest
from trac.core import Interface, implements, Component
from multiproduct.core import MultiProductExtensionPoint
+
class MultiProductExtensionPointTestCase(unittest.TestCase):
def setUp(self):
from trac.core import ComponentManager, ComponentMeta
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/__init__.py
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/__init__.py?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/__init__.py (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/__init__.py Thu Feb 27 02:14:33 2014
@@ -1,4 +1,5 @@
-
+# -*- coding: utf-8 -*-
+#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
@@ -20,4 +21,3 @@ from tests import TestLoader
def test_suite():
return TestLoader().discover_package(__name__, pattern='*.py')
-
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/api.py
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/api.py?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/api.py (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/api.py Thu Feb 27 02:14:33 2014
@@ -1,4 +1,5 @@
-
+# -*- coding: utf-8 -*-
+#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/cursor.py
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/cursor.py?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/cursor.py (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/cursor.py Thu Feb 27 02:14:33 2014
@@ -1,4 +1,5 @@
-
+# -*- coding: utf-8 -*-
+#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
@@ -1057,5 +1058,3 @@ class DbCursorTestCase(unittest.TestCase
if __name__ == '__main__':
unittest.main()
-
-
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/mysql.py
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/mysql.py?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/mysql.py (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/mysql.py Thu Feb 27 02:14:33 2014
@@ -1,4 +1,5 @@
-
+# -*- coding: utf-8 -*-
+#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/postgres.py
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/postgres.py?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/postgres.py (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/postgres.py Thu Feb 27 02:14:33 2014
@@ -1,4 +1,5 @@
-
+# -*- coding: utf-8 -*-
+#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/util.py
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/util.py?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/util.py (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/db/util.py Thu Feb 27 02:14:33 2014
@@ -1,4 +1,5 @@
-
+# -*- coding: utf-8 -*-
+#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/env.py
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/env.py?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/env.py (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/env.py Thu Feb 27 02:14:33 2014
@@ -19,23 +19,17 @@
"""Tests for Apache(TM) Bloodhound's product environments"""
-from inspect import stack
import os.path
import shutil
-from sqlite3 import OperationalError
import sys
import tempfile
+from inspect import stack
+from tests import unittest
from types import MethodType
-if sys.version_info < (2, 7):
- import unittest2 as unittest
- from unittest2.case import _AssertRaisesContext
-else:
- import unittest
- from unittest.case import _AssertRaisesContext
-
+from trac.admin.api import AdminCommandManager, IAdminCommandProvider
from trac.config import Option
-from trac.core import Component, ComponentMeta
+from trac.core import Component, ComponentMeta, implements
from trac.env import Environment
from trac.test import EnvironmentStub, MockPerm
from trac.tests.env import EnvironmentTestCase
@@ -44,10 +38,12 @@ from trac.ticket.web_ui import TicketMod
from trac.util.text import to_unicode
from trac.web.href import Href
-from multiproduct.api import MultiProductSystem
+from multiproduct.api import DB_VERSION, MultiProductSystem
from multiproduct.env import ProductEnvironment
from multiproduct.model import Product
+_AssertRaisesContext = unittest.case._AssertRaisesContext
+
class ProductEnvironmentStub(ProductEnvironment):
r"""A product environment slightly tweaked for testing purposes
@@ -93,7 +89,7 @@ class MultiproductTestCase(unittest.Test
return _AssertRaisesContext.__exit__(self, exc_type,
exc_value, tb)
except self.failureException, exc:
- msg = self.test_case.exceptFailureMessage
+ msg = self.test_case.exceptFailureMessage
if msg is not None:
standardMsg = str(exc)
msg = msg % self._tb_locals(tb)
@@ -160,7 +156,7 @@ class MultiproductTestCase(unittest.Test
# Test setup
def _setup_test_env(self, create_folder=True, path=None, **kwargs):
- r"""Prepare a new test environment .
+ r"""Prepare a new test environment .
Optionally set its path to a meaningful location (temp folder
if `path` is `None`).
@@ -170,20 +166,27 @@ class MultiproductTestCase(unittest.Test
self.env = env = EnvironmentStub(**kwargs)
if create_folder:
if path is None:
- env.path = tempfile.mkdtemp('bh-product-tempenv')
+ env.path = tempfile.mkdtemp(prefix='bh-tempenv-')
else:
env.path = path
- if not os.path.exists(path):
- os.mkdir(path)
+ if not os.path.exists(env.path):
+ os.mkdir(env.path)
+ conf_dir = os.path.join(env.path, 'conf')
+ if not os.path.exists(conf_dir):
+ os.mkdir(conf_dir)
return env
def _setup_test_log(self, env):
r"""Ensure test product with prefix is loaded
"""
- logdir = tempfile.gettempdir()
- logpath = os.path.join(logdir, 'trac-testing.log')
+ if not hasattr(env, 'path') or not env.path:
+ env.path = tempfile.mkdtemp(prefix='bh-product-tempenv-')
+ log_dir = os.path.join(env.path, 'log')
+ if not os.path.exists(log_dir):
+ os.mkdir(log_dir)
+ log_file = os.path.join(log_dir, 'trac-testing.log')
config = env.config
- config.set('logging', 'log_file', logpath)
+ config.set('logging', 'log_file', log_file)
config.set('logging', 'log_type', 'file')
config.set('logging', 'log_level', 'DEBUG')
@@ -196,7 +199,7 @@ class MultiproductTestCase(unittest.Test
# Clean-up logger instance and associated handler
# Otherwise large test suites will only result in ERROR eventually
- # (at least in Unix systems) with messages
+ # (at least in Unix systems) with messages
#
# TracError: Error reading '/path/to/file', make sure it is readable.
# error: /path/to/: Too many open files
@@ -225,16 +228,20 @@ class MultiproductTestCase(unittest.Test
r"""Apply multi product upgrades
"""
# Do not break wiki parser ( see #373 )
- env.disable_component(TicketModule)
- env.disable_component(ReportModule)
+ EnvironmentStub.disable_component_in_config(env, TicketModule)
+ EnvironmentStub.disable_component_in_config(env, ReportModule)
mpsystem = MultiProductSystem(env)
- try:
- mpsystem.upgrade_environment(env.db_transaction)
- except OperationalError:
- # Database is upgraded, but database version was deleted.
- # Complete the upgrade by inserting default product.
- mpsystem._insert_default_product(env.db_transaction)
+ with env.db_transaction as db:
+ try:
+ mpsystem.upgrade_environment(db)
+ except env.db_exc.OperationalError:
+ # Database is upgraded, but database version was deleted.
+ # Complete the upgrade by inserting default product.
+ mpsystem._insert_default_product(db)
+ finally:
+ # Ensure that multiproduct DB version is set to latest value
+ mpsystem._update_db_version(db, DB_VERSION)
# assume that the database schema has been upgraded, enable
# multi-product schema support in environment
env.enable_multiproduct_schema(True)
@@ -311,7 +318,7 @@ class ProductEnvApiTestCase(Multiproduct
if self.env is not None:
try:
self.env.reset_db()
- except OperationalError:
+ except self.env.db_exc.OperationalError:
# "Database not found ...",
# "OperationalError: no such table: system" or the like
pass
@@ -333,7 +340,7 @@ class ProductEnvApiTestCase(Multiproduct
def property_mock(attrnm, expected_self):
def assertAttrFwd(instance):
- self.assertIs(instance, expected_self,
+ self.assertIs(instance, expected_self,
"Mismatch in property '%s'" % (attrnm,))
raise AttrSuccess
return property(assertAttrFwd)
@@ -343,7 +350,7 @@ class ProductEnvApiTestCase(Multiproduct
for attrnm in 'system_info_providers secure_cookies ' \
'project_admin_trac_url get_system_info get_version ' \
'get_templates_dir get_templates_dir get_log_dir ' \
- 'backup'.split():
+ 'backup'.split():
original = getattr(Environment, attrnm)
if isinstance(original, MethodType):
translation = getattr(self.product_env, attrnm)
@@ -388,15 +395,8 @@ class ProductEnvApiTestCase(Multiproduct
def test_typecheck(self):
"""Testing env.__init__"""
self._load_product_from_data(self.env, 'tp2')
- with self.assertRaises(TypeError) as cm_test:
- new_env = ProductEnvironment(self.product_env, 'tp2')
-
- msg = str(cm_test.exception)
- expected_msg = "Initializer must be called with " \
- "trac.env.Environment instance as first argument " \
- "(got multiproduct.env.ProductEnvironment instance " \
- "instead)"
- self.assertEqual(msg, expected_msg)
+ env2 = ProductEnvironment(self.product_env, 'tp2')
+ self.assertIs(env2, ProductEnvironment(self.env, 'tp2'))
def test_component_enable(self):
"""Testing env.is_component_enabled"""
@@ -404,6 +404,7 @@ class ProductEnvApiTestCase(Multiproduct
pass
# Let's pretend this was declared elsewhere
C.__module__ = 'dummy_module'
+ sys.modules['dummy_module'] = sys.modules[__name__]
global_env = self.env
product_env = self.product_env
@@ -420,6 +421,8 @@ class ProductEnvApiTestCase(Multiproduct
expected_rules = {
'multiproduct': True,
'trac': True,
+ 'trac.ticket.report.reportmodule': False,
+ 'trac.ticket.web_ui.ticketmodule': False,
'trac.db': True,
cname: False,
}
@@ -520,24 +523,24 @@ class ProductEnvApiTestCase(Multiproduct
self.assertEquals('value2', product_config['section'].get('key'))
def test_parametric_singleton(self):
- self.assertIs(self.product_env,
+ self.assertIs(self.product_env,
ProductEnvironment(self.env, self.default_product))
for prefix in self.PRODUCT_DATA:
if prefix != self.default_product:
self._load_product_from_data(self.env, prefix)
- envgen1 = dict([prefix, ProductEnvironment(self.env, prefix)]
+ envgen1 = dict([prefix, ProductEnvironment(self.env, prefix)]
for prefix in self.PRODUCT_DATA)
- envgen2 = dict([prefix, ProductEnvironment(self.env, prefix)]
+ envgen2 = dict([prefix, ProductEnvironment(self.env, prefix)]
for prefix in self.PRODUCT_DATA)
for prefix, env1 in envgen1.iteritems():
- self.assertIs(env1, envgen2[prefix],
+ self.assertIs(env1, envgen2[prefix],
"Identity check (by prefix) '%s'" % (prefix,))
for prefix, env1 in envgen1.iteritems():
- self.assertIs(env1, envgen2[prefix],
+ self.assertIs(env1, envgen2[prefix],
"Identity check (by prefix) '%s'" % (prefix,))
def load_product(prefix):
@@ -552,12 +555,12 @@ class ProductEnvApiTestCase(Multiproduct
for prefix in self.PRODUCT_DATA)
for prefix, env1 in envgen1.iteritems():
- self.assertIs(env1, envgen3[prefix],
+ self.assertIs(env1, envgen3[prefix],
"Identity check (by product model) '%s'" % (prefix,))
class ProductEnvHrefTestCase(MultiproductTestCase):
- """Assertions for resolution of product environment's base URL
+ """Assertions for resolution of product environment's base URL
[https://issues.apache.org/bloodhound/wiki/Proposals/BEP-0003 BEP 3]
"""
@@ -570,7 +573,6 @@ class ProductEnvHrefTestCase(Multiproduc
def setUp(self):
self._mp_setup()
- self.env.path = '/path/to/env'
self.env.abs_href = Href('http://globalenv.com/trac.cgi')
url_pattern = getattr(getattr(self, self._testMethodName).im_func,
'product_base_url', '')
@@ -579,11 +581,12 @@ class ProductEnvHrefTestCase(Multiproduc
self.product_env = ProductEnvironment(self.env, self.default_product)
def tearDown(self):
+ shutil.rmtree(os.path.dirname(self.env.path), ignore_errors=True)
# Release reference to transient environment mock object
if self.env is not None:
try:
self.env.reset_db()
- except OperationalError:
+ except self.env.db_exc.OperationalError:
# "Database not found ...",
# "OperationalError: no such table: system" or the like
pass
@@ -610,8 +613,11 @@ class ProductEnvHrefTestCase(Multiproduc
def test_href_inherit_sibling_paths(self):
"""Test product base URL at sibling paths inheriting configuration.
"""
- self.assertEqual('/trac.cgi/env/tp1', self.product_env.href())
- self.assertEqual('http://globalenv.com/trac.cgi/env/tp1',
+ self.assertEqual('/trac.cgi/%s/tp1'
+ % os.path.split(self.env.path)[-1],
+ self.product_env.href())
+ self.assertEqual('http://globalenv.com/trac.cgi/%s/tp1'
+ % os.path.split(self.env.path)[-1],
self.product_env.abs_href())
@product_base_url('')
@@ -635,7 +641,9 @@ class ProductEnvHrefTestCase(Multiproduc
"""Test complex product base URL
"""
self.assertEqual('/bh/tp1', self.product_env.href())
- self.assertEqual('http://env.tld/bh/tp1', self.product_env.abs_href())
+ self.assertEqual('http://%s.tld/bh/tp1'
+ % os.path.split(self.env.path)[-1],
+ self.product_env.abs_href())
@product_base_url('http://$(prefix)s.$(envname)s.tld/')
def test_product_href_uses_multiproduct_product_base_url(self):
@@ -651,7 +659,9 @@ class ProductEnvHrefTestCase(Multiproduc
# Product URLs
self.assertEqual('', self.product_env.base_url)
self.assertEqual('/', self.product_env.href())
- self.assertEqual('http://tp1.env.tld', self.product_env.abs_href())
+ self.assertEqual('http://tp1.%s.tld'
+ % os.path.split(self.env.path)[-1],
+ self.product_env.abs_href())
@product_base_url('http://$(prefix)s.$(envname)s.tld/')
def test_product_href_uses_products_base_url(self):
@@ -679,16 +689,146 @@ class ProductEnvHrefTestCase(Multiproduc
self.assertEqual('', self.product_env.base_url)
self.assertEqual('/', self.product_env.href())
- self.assertEqual('http://tp1.env.tld', self.product_env.abs_href())
+ self.assertEqual('http://tp1.%s.tld'
+ % os.path.split(self.env.path)[-1],
+ self.product_env.abs_href())
product_base_url = staticmethod(product_base_url)
+class ProductEnvConfigTestCase(MultiproductTestCase):
+ """Test cases for product environment's configuration
+ """
+
+ class DummyAdminCommand(Component):
+ """Dummy class used for testing purposes
+ """
+ implements(IAdminCommandProvider)
+
+ class DummyException(Exception):
+ pass
+
+ def do_fail(self, *args):
+ raise DummyException(args)
+
+ def get_admin_commands(self):
+ yield "fail", "[ARG]...", "Always fail", None, self.do_fail
+
+
+ def setUp(self):
+ self._mp_setup(create_folder=True)
+ self.global_env = self.env
+ self.env = ProductEnvironment(self.global_env, self.default_product)
+
+ # Random component class
+ self.component_class = self.DummyAdminCommand
+
+ def tearDown(self):
+ if self.global_env is not None:
+ try:
+ self.global_env.reset_db()
+ except self.global_env.db_exc.OperationalError:
+ # "Database not found ...",
+ # "OperationalError: no such table: system" or the like
+ pass
+
+ shutil.rmtree(self.env.path)
+ self.env = self.global_env = None
+
+ def test_regression_bh_539(self):
+ tracadmin = AdminCommandManager(self.env)
+
+ self.assertTrue(self.env[self.component_class] is None,
+ "Expected component disabled")
+ self.assertFalse(any(isinstance(c, self.component_class)
+ for c in tracadmin.providers),
+ "Component erroneously listed in admin cmd providers")
+ self.assertEqual([], tracadmin.get_command_help(args=['fail']))
+
+ # Enable component in both global and product context
+ cmd_args = ['config', 'set', 'components', __name__ + '.*', 'enabled']
+ AdminCommandManager(self.global_env).execute_command(*cmd_args)
+ tracadmin.execute_command(*cmd_args)
+
+ self.assertTrue(self.env[self.component_class] is not None,
+ "Expected component enabled")
+ self.assertTrue(any(isinstance(c, self.component_class)
+ for c in tracadmin.providers),
+ "Component not listed in admin cmd providers")
+ self.assertEqual(1, len(tracadmin.get_command_help(args=['fail'])))
+
+ def test_regression_bh_539_concurrent(self):
+ try:
+ # It is necessary to load another environment object to work around
+ # ProductEnvironment class' parametric singleton constraint
+ old_env = self.env
+ # In-memory DB has to be shared
+ self.global_env.__class__.global_databasemanager = \
+ self.env.global_databasemanager
+ new_global_env = self._setup_test_env(create_folder=True,
+ path=self.global_env.path)
+ self.env = old_env
+ self._setup_test_log(new_global_env)
+
+ # FIXME: EnvironmentStub config is not bound to a real file
+ # ... so let's reuse one config for both envs to simulate that they
+ # are in sync, a condition verified in another test case
+ new_global_env.config = self.global_env.config
+
+ new_env = ProductEnvironment(new_global_env, self.default_product)
+
+ self.assertTrue(new_global_env is not self.global_env)
+ self.assertTrue(new_env is not self.env)
+ self.assertEqual(self.env.path, new_env.path)
+ self.assertEqual(self.env.config._lock_path,
+ new_env.config._lock_path)
+
+ tracadmin = AdminCommandManager(self.env)
+ new_tracadmin = AdminCommandManager(new_env)
+
+ # Assertions for self.env
+ self.assertTrue(self.env[self.component_class] is None,
+ "Expected component disabled")
+ self.assertFalse(any(isinstance(c, self.component_class)
+ for c in tracadmin.providers),
+ "Component erroneously listed in admin cmd "
+ "providers")
+ self.assertEqual([], tracadmin.get_command_help(args=['fail']))
+
+ # Repeat assertions for new_env
+ self.assertTrue(new_env[self.component_class] is None,
+ "Expected component disabled")
+ self.assertFalse(any(isinstance(c, self.component_class)
+ for c in new_tracadmin.providers),
+ "Component erroneously listed in admin cmd "
+ "providers")
+ self.assertEqual([], new_tracadmin.get_command_help(args=['fail']))
+
+ # Enable component in both self.global_env and self.env contexts
+ cmd_args = ['config', 'set', 'components',
+ __name__ + '.*', 'enabled']
+ AdminCommandManager(self.global_env).execute_command(*cmd_args)
+ tracadmin.execute_command(*cmd_args)
+
+ # Assert that changes are auto-magically reflected in new_env
+ self.assertTrue(new_env[self.component_class] is not None,
+ "Expected component enabled")
+ self.assertTrue(any(isinstance(c, self.component_class)
+ for c in new_tracadmin.providers),
+ "Component not listed in admin cmd providers")
+ self.assertEqual(
+ 1, len(new_tracadmin.get_command_help(args=['fail'])))
+ finally:
+ self.global_env.__class__.global_databasemanager = None
+ new_global_env = new_env = None
+
+
def test_suite():
return unittest.TestSuite([
unittest.makeSuite(ProductEnvTestCase, 'test'),
unittest.makeSuite(ProductEnvApiTestCase, 'test'),
unittest.makeSuite(ProductEnvHrefTestCase, 'test'),
+ unittest.makeSuite(ProductEnvConfigTestCase, 'test'),
])
if __name__ == '__main__':
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/hooks.py
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/hooks.py?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/hooks.py (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/hooks.py Thu Feb 27 02:14:33 2014
@@ -17,11 +17,7 @@
# specific language governing permissions and limitations
# under the License.
-
-try:
- import unittest2 as unittest
-except ImportError:
- import unittest
+from tests import unittest
from trac.web.href import Href
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/mimeview/__init__.py
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/mimeview/__init__.py?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/mimeview/__init__.py (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/mimeview/__init__.py Thu Feb 27 02:14:33 2014
@@ -1,4 +1,5 @@
-
+# -*- coding: utf-8 -*-
+#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
@@ -22,4 +23,3 @@ from tests import TestLoader
def test_suite():
return TestLoader().discover_package(__name__, pattern='*.py')
-
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/mimeview/api.py
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/mimeview/api.py?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/mimeview/api.py (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/mimeview/api.py Thu Feb 27 02:14:33 2014
@@ -1,4 +1,5 @@
-
+# -*- coding: utf-8 -*-
+#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
@@ -60,4 +61,3 @@ def test_suite():
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
-
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/mimeview/patch.py
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/mimeview/patch.py?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/mimeview/patch.py (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/mimeview/patch.py Thu Feb 27 02:14:33 2014
@@ -1,4 +1,5 @@
-
+# -*- coding: utf-8 -*-
+#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
@@ -64,4 +65,3 @@ def test_suite():
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
-
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/mimeview/pygments.py
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/mimeview/pygments.py?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/mimeview/pygments.py (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/mimeview/pygments.py Thu Feb 27 02:14:33 2014
@@ -1,4 +1,5 @@
-
+# -*- coding: utf-8 -*-
+#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
@@ -18,19 +19,15 @@
"""Tests for Apache(TM) Bloodhound's Pygments renderer in product environments"""
-import sys
-if sys.version_info < (2, 7):
- import unittest2 as unittest
-else:
- import unittest
+from tests import unittest
+from tests.env import MultiproductTestCase
from trac.mimeview.api import Mimeview
from trac.mimeview.pygments import PygmentsRenderer
-from trac.mimeview.tests import pygments as test_pygments
+from trac.mimeview.tests import pygments as test_pygments
from trac.web.chrome import Chrome
from multiproduct.env import ProductEnvironment
-from tests.env import MultiproductTestCase
have_pygments = False
@@ -42,6 +39,7 @@ else:
test_python_hello = test_python_hello_mimeview = \
lambda self : None
+
class ProductPygmentsRendererTestCase(super_class, MultiproductTestCase):
@property
@@ -71,7 +69,7 @@ class ProductPygmentsRendererTestCase(su
self.global_env = self._env = None
ProductPygmentsRendererTestCase = unittest.skipUnless(
- test_pygments.have_pygments,
+ test_pygments.have_pygments,
'mimeview/tests/pygments (no pygments installed)'
)(ProductPygmentsRendererTestCase)
@@ -82,4 +80,3 @@ def test_suite():
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
-
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/model.py
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/model.py?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/model.py (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/model.py Thu Feb 27 02:14:33 2014
@@ -1,4 +1,5 @@
-
+# -*- coding: utf-8 -*-
+#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
@@ -18,26 +19,18 @@
"""Tests for multiproduct/model.py"""
import shutil
-import sys
import tempfile
+from tests import unittest
-if sys.version_info < (2, 7):
- import unittest2 as unittest
-else:
- import unittest
-
-from sqlite3 import OperationalError
-
-from trac.test import EnvironmentStub
from trac.core import TracError
+from trac.test import EnvironmentStub
+from trac.tests.resource import TestResourceChangeListener
from trac.ticket.model import Ticket
-from multiproduct.env import ProductEnvironment
-from multiproduct.model import Product
from bhdashboard.model import ModelBase
-
from multiproduct.api import MultiProductSystem
-from trac.tests.resource import TestResourceChangeListener
+from multiproduct.env import ProductEnvironment
+from multiproduct.model import Product
class ProductTestCase(unittest.TestCase):
@@ -48,15 +41,15 @@ class ProductTestCase(unittest.TestCase)
def setUp(self):
self.env = EnvironmentStub(enable=['trac.*', 'multiproduct.*'])
- self.env.path = tempfile.mkdtemp('bh-product-tempenv')
-
+ self.env.path = tempfile.mkdtemp(prefix='bh-product-tempenv-')
+
self.mpsystem = MultiProductSystem(self.env)
try:
self.mpsystem.upgrade_environment(self.env.db_transaction)
- except OperationalError:
+ except self.env.db_exc.OperationalError:
# table remains but database version is deleted
pass
-
+
self.listener = self._enable_resource_change_listener()
self.default_data = {'prefix':self.INITIAL_PREFIX,
'name':self.INITIAL_NAME,
@@ -70,7 +63,7 @@ class ProductTestCase(unittest.TestCase)
def tearDown(self):
shutil.rmtree(self.env.path)
self.env.reset_db()
-
+
def _enable_resource_change_listener(self):
listener = TestResourceChangeListener(self.env)
listener.resource_type = Product
@@ -89,36 +82,36 @@ class ProductTestCase(unittest.TestCase)
test = {'prefix': 'td',
'name': 'test field access',
'description': 'product to test field setting'}
-
+
product = Product(self.env)
-
+
# attempt to set the fields from the data
product.prefix = test['prefix']
product.name = test['name']
product.description = test['description']
-
+
self.assertEqual(product._data['prefix'], test['prefix'])
self.assertEqual(product._data['name'], test['name'])
self.assertEqual(product._data['description'], test['description'])
-
+
def test_select(self):
"""tests that select can search Products by fields"""
-
+
p2_data = {'prefix':'tp2',
'name':'test project 2',
'description':'a different test project'}
p3_data = {'prefix':'tp3',
'name':'test project 3',
'description':'test project'}
-
+
product2 = Product(self.env)
product2._data.update(p2_data)
product3 = Product(self.env)
product3._data.update(p3_data)
-
+
product2.insert()
product3.insert()
-
+
products = list(Product.select(self.env, where={'prefix':'tp'}))
self.assertEqual(1, len(products))
products = list(Product.select(self.env,
@@ -127,43 +120,43 @@ class ProductTestCase(unittest.TestCase)
products = list(Product.select(self.env,
where={'prefix':'tp3', 'name':'test project 3'}))
self.assertEqual(1, len(products))
-
+
def test_update(self):
"""tests that we can use update to push data to the database"""
product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
self.assertEqual('test project', product._data['name'])
-
- new_data = {'prefix':'tp',
- 'name':'updated',
+
+ new_data = {'prefix':'tp',
+ 'name':'updated',
'description':'nothing'}
product._data.update(new_data)
product.update()
-
+
comp_product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
self.assertEqual('updated', comp_product._data['name'])
-
+
def test_update_key_change(self):
"""tests that we raise an error for attempting to update key fields"""
- bad_data = {'prefix':'tp0',
- 'name':'update',
+ bad_data = {'prefix':'tp0',
+ 'name':'update',
'description':'nothing'}
product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
product._data.update(bad_data)
self.assertRaises(TracError, product.update)
-
+
def test_insert(self):
"""test saving new Product"""
data = {'prefix':'new', 'name':'new', 'description':'new'}
product = Product(self.env)
product._data.update(data)
product.insert()
-
+
check_products = list(Product.select(self.env, where={'prefix':'new'}))
-
+
self.assertEqual(product._data['prefix'],
check_products[0]._data['prefix'])
self.assertEqual(1, len(check_products))
-
+
def test_insert_duplicate_key(self):
"""test attempted saving of Product with existing key fails"""
dupe_key_data = {'prefix':'tp',
@@ -172,22 +165,22 @@ class ProductTestCase(unittest.TestCase)
product2 = Product(self.env)
product2._data.update(dupe_key_data)
self.assertRaises(TracError, product2.insert)
-
+
def test_delete(self):
"""test that we are able to delete Products"""
product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
product.delete()
-
+
post = list(Product.select(self.env, where={'prefix':'tp'}))
self.assertEqual(0, len(post))
-
+
def test_delete_twice(self):
"""test that we error when deleting twice on the same key"""
product = list(Product.select(self.env, where={'prefix':'tp'}))[0]
product.delete()
-
+
self.assertRaises(TracError, product.delete)
-
+
def test_field_data_get(self):
"""tests that we can use table.field syntax to get to the field data"""
prefix = self.default_data['prefix']
@@ -197,12 +190,12 @@ class ProductTestCase(unittest.TestCase)
self.assertEqual(prefix, product.prefix)
self.assertEqual(name, product.name)
self.assertEqual(description, product.description)
-
+
def test_field_set(self):
"""tests that we can use table.field = something to set field data"""
prefix = self.default_data['prefix']
product = list(Product.select(self.env, where={'prefix':prefix}))[0]
-
+
new_description = 'test change of description'
product.description = new_description
self.assertEqual(new_description, product.description)
@@ -226,7 +219,7 @@ class ProductTestCase(unittest.TestCase)
for table in schema:
for statement in db_connector.to_sql(table):
db(statement)
-
+
structure = dict([(table.name, [col.name for col in table.columns])
for table in schema])
tm1 = TestModel(self.env)
@@ -292,4 +285,3 @@ def suite():
if __name__ == '__main__':
unittest.main()
-
Modified: bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/perm.py
URL: http://svn.apache.org/viewvc/bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/perm.py?rev=1572404&r1=1572403&r2=1572404&view=diff
==============================================================================
--- bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/perm.py (original)
+++ bloodhound/branches/bep_0007_embeddable_objects/bloodhound_multiproduct/tests/perm.py Thu Feb 27 02:14:33 2014
@@ -40,7 +40,7 @@ from tests.env import MultiproductTestCa
perm.DefaultPermissionPolicy.CACHE_EXPIRY = 0
-class ProductDefaultPermissionStoreTestCase(DefaultPermissionStoreTestCase,
+class ProductDefaultPermissionStoreTestCase(DefaultPermissionStoreTestCase,
MultiproductTestCase):
def setUp(self):
@@ -64,17 +64,17 @@ class ProductDefaultPermissionStoreTestC
store1 = perm.DefaultPermissionStore(env1)
global_env.db_transaction.executemany(
- "INSERT INTO permission VALUES (%s,%s)",
+ "INSERT INTO permission VALUES (%s,%s)",
[('dev', 'WIKI_MODIFY'),
('dev', 'REPORT_ADMIN'),
('john', 'dev')])
env.db_transaction.executemany(
- "INSERT INTO permission VALUES (%s,%s)",
+ "INSERT INTO permission VALUES (%s,%s)",
[('dev', 'WIKI_VIEW'),
('dev', 'REPORT_VIEW'),
('john', 'dev')])
env1.db_transaction.executemany(
- "INSERT INTO permission VALUES (%s,%s)",
+ "INSERT INTO permission VALUES (%s,%s)",
[('dev', 'TICKET_CREATE'),
('dev', 'MILESTONE_VIEW'),
('john', 'dev')])
@@ -185,7 +185,7 @@ class SudoTestCase(ProductPermissionCach
with self.assertRaises(RuntimeError) as test_cm:
sudoperm.has_permission('TEST_MODIFY')
- self.assertEqual('Permission check out of context',
+ self.assertEqual('Permission check out of context',
str(test_cm.exception))
with self.assertRaises(ValueError) as test_cm:
@@ -210,30 +210,30 @@ class SudoTestCase(ProductPermissionCach
sudoperm = sudo(None, 'TEST_CREATE', ['TRAC_ADMIN'])
sudoperm.perm = self.perm
-
+
self.assertTrue(sudoperm.has_permission('EMAIL_VIEW'))
def test_sudo_ambiguous(self):
with self.assertRaises(ValueError) as test_cm:
- sudo(None, 'TEST_MODIFY', ['TEST_MODIFY', 'TEST_DELETE'],
+ sudo(None, 'TEST_MODIFY', ['TEST_MODIFY', 'TEST_DELETE'],
['TEST_MODIFY', 'TEST_CREATE'])
- self.assertEquals('Impossible to grant and revoke (TEST_MODIFY)',
+ self.assertEquals('Impossible to grant and revoke (TEST_MODIFY)',
str(test_cm.exception))
with self.assertRaises(ValueError) as test_cm:
- sudoperm = sudo(None, 'TEST_MODIFY', ['TEST_ADMIN'],
+ sudoperm = sudo(None, 'TEST_MODIFY', ['TEST_ADMIN'],
['TEST_MODIFY', 'TEST_CREATE'])
sudoperm.perm = self.perm
self.assertEquals('Impossible to grant and revoke '
- '(TEST_CREATE, TEST_MODIFY)',
+ '(TEST_CREATE, TEST_MODIFY)',
str(test_cm.exception))
with self.assertRaises(ValueError) as test_cm:
req = Mock(perm=self.perm)
- sudo(req, 'TEST_MODIFY', ['TEST_ADMIN'],
+ sudo(req, 'TEST_MODIFY', ['TEST_ADMIN'],
['TEST_MODIFY', 'TEST_CREATE'])
self.assertEquals('Impossible to grant and revoke '
- '(TEST_CREATE, TEST_MODIFY)',
+ '(TEST_CREATE, TEST_MODIFY)',
str(test_cm.exception))
# Sudo permission context equivalent to permissions cache
@@ -254,9 +254,9 @@ class SudoTestCase(ProductPermissionCach
for tcnm in tcnames:
f1 = _test_with_sudo_rules(tcnm, '', [])
- f2 = _test_with_sudo_rules(tcnm, 'test_sudo_partial_',
+ f2 = _test_with_sudo_rules(tcnm, 'test_sudo_partial_',
['TEST_MODIFY'])
- f3 = _test_with_sudo_rules(tcnm, 'test_sudo_full_',
+ f3 = _test_with_sudo_rules(tcnm, 'test_sudo_full_',
['TEST_MODIFY', 'TEST_ADMIN'])
for f in (f1, f2, f3):
_gen_tests[f.func_name] = f
@@ -267,7 +267,7 @@ list(setattr(SudoTestCase, tcnm, f)
for tcnm, f in SudoTestCase._gen_tests.iteritems())
-class ProductPermissionPolicyTestCase(PermissionPolicyTestCase,
+class ProductPermissionPolicyTestCase(PermissionPolicyTestCase,
MultiproductTestCase):
@property
def env(self):
@@ -294,7 +294,7 @@ class ProductPermissionPolicyTestCase(Pe
def setUp(self):
super(ProductPermissionPolicyTestCase, self).setUp()
- self.global_env.config.set('trac', 'permission_policies',
+ self.global_env.config.set('trac', 'permission_policies',
'DefaultPermissionPolicy')
self.permsys = perm.PermissionSystem(self.env)
self.global_perm_admin = perm.PermissionAdmin(self.global_env)
@@ -309,7 +309,7 @@ class ProductPermissionPolicyTestCase(Pe
self.permsys.policies)
def test_policy_chaining(self):
- self.env.config.set('trac', 'permission_policies',
+ self.env.config.set('trac', 'permission_policies',
'TestPermissionPolicy,DefaultPermissionPolicy')
self.policy.grant('testuser', ['TEST_MODIFY'])
system = perm.PermissionSystem(self.env)
@@ -346,7 +346,7 @@ class ProductPermissionPolicyTestCase(Pe
'Check for permission action %s' % (action,))
self.assertFalse(self.perm.has_permission('UNKNOWN_PERM'))
- # Clear permissions cache and retry
+ # Clear permissions cache and retry
self.perm._cache.clear()
self.global_perm_admin._do_remove('testuser', 'TRAC_ADMIN')
@@ -371,9 +371,9 @@ class ProductPermissionPolicyTestCase(Pe
# Setting TRAC_ADMIN permission in product scope is in vain
# since it controls access to critical actions affecting the whole site
# This will protect the system against malicious actors
- # and / or failures leading to the addition of TRAC_ADMIN permission
+ # and / or failures leading to the addition of TRAC_ADMIN permission
# in product perm store in spite of obtaining unrighteous super powers.
- # On the other hand this also means that PRODUCT_ADMIN(s) are
+ # On the other hand this also means that PRODUCT_ADMIN(s) are
# able to set user permissions at will without jeopardizing system
# integrity and stability.
self.product_perm_admin._do_add('testuser', 'TRAC_ADMIN')
@@ -439,7 +439,7 @@ class ProductPermissionPolicyTestCase(Pe
def test_suite():
suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(ProductDefaultPermissionStoreTestCase,
+ suite.addTest(unittest.makeSuite(ProductDefaultPermissionStoreTestCase,
'test'))
suite.addTest(unittest.makeSuite(ProductPermissionSystemTestCase, 'test'))
suite.addTest(unittest.makeSuite(ProductPermissionCacheTestCase, 'test'))
@@ -452,4 +452,3 @@ def test_suite():
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
-