Example #1
0
    def _upgrade_mp(cls, env):
        r"""Apply multi product upgrades
        """
        # Do not break wiki parser ( see #373 )
        env.disable_component(TicketModule)
        env.disable_component(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)
        # assume that the database schema has been upgraded, enable
        # multi-product schema support in environment
        env.enable_multiproduct_schema(True)
Example #2
0
    def _upgrade_mp(cls, env):
        r"""Apply multi product upgrades
        """
        # Do not break wiki parser ( see #373 )
        env.disable_component(TicketModule)
        env.disable_component(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)
        # assume that the database schema has been upgraded, enable
        # multi-product schema support in environment
        env.enable_multiproduct_schema(True)
Example #3
0
    def _upgrade_mp(cls, env):
        r"""Apply multi product upgrades
        """
        # Do not break wiki parser ( see #373 )
        EnvironmentStub.disable_component_in_config(env, TicketModule)
        EnvironmentStub.disable_component_in_config(env, ReportModule)

        mpsystem = MultiProductSystem(env)
        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)
Example #4
0
class ProductTestCase(unittest.TestCase):
    """Unit tests covering the Product model"""
    INITIAL_PREFIX = 'tp'
    INITIAL_NAME = 'test project'
    INITIAL_DESCRIPTION = 'a test project'

    def setUp(self):
        self.env = EnvironmentStub(enable=['trac.*', 'multiproduct.*'])
        self.env.path = tempfile.mkdtemp(prefix='bh-product-tempenv-')

        self.mpsystem = MultiProductSystem(self.env)
        try:
            self.mpsystem.upgrade_environment(self.env.db_transaction)
        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,
                             'description':self.INITIAL_DESCRIPTION}

        self.global_env = self.env
        self.product = Product(self.env)
        self.product._data.update(self.default_data)
        self.product.insert()

    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
        listener.callback = self.listener_callback
        return listener

    def listener_callback(self, action, resource, context, old_values = None):
        # pylint: disable=unused-argument
        # pylint: disable=attribute-defined-outside-init
        self.prefix = resource.prefix
        self.name = resource.name
        self.description = resource.description

    def test_set_table_field(self):
        """tests that table.field style update works"""
        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,
            where={'name':'test project'}))
        self.assertEqual(1, len(products))
        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',
                    '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',
                    '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',
                         'name':'dupe',
                         'description':'dupe primary key'}
        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']
        name = self.default_data['name']
        description = self.default_data['description']
        product = list(Product.select(self.env, where={'prefix':prefix}))[0]
        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)

    def test_missing_unique_fields(self):
        """ensure that that insert method works when _meta does not specify
        unique fields when inserting more than one ProductResourceMap instances
        """
        class TestModel(ModelBase):
            """A test model with no unique_fields"""
            _meta = {'table_name': 'bloodhound_testmodel',
                     'object_name': 'TestModelObject',
                     'key_fields': ['id',],
                     'non_key_fields': ['value'],
                     'unique_fields': [],}

        from trac.db import DatabaseManager
        schema = [TestModel._get_schema(), ]
        with self.env.db_transaction as db:
            db_connector, dummy = DatabaseManager(self.env)._get_connector()
            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)
        tm1._data.update({'id':1, 'value':'value1'})
        tm1.insert()
        tm2 = TestModel(self.env)
        tm2._data.update({'id':2, 'value':'value2'})
        tm2.insert()

    def test_change_listener_created(self):
        self.assertEqual('created', self.listener.action)
        self.assertIsInstance(self.listener.resource, Product)
        self.assertEqual(self.INITIAL_PREFIX, self.prefix)
        self.assertEqual(self.INITIAL_NAME, self.name)
        self.assertEqual(self.INITIAL_DESCRIPTION, self.description)

    def test_change_listener_changed(self):
        CHANGED_NAME = "changed name"
        self.product.name = CHANGED_NAME
        self.product.update()
        self.assertEqual('changed', self.listener.action)
        self.assertIsInstance(self.listener.resource, Product)
        self.assertEqual(CHANGED_NAME, self.name)
        self.assertEqual({"name":self.INITIAL_NAME}, self.listener.old_values)

    def test_change_listener_deleted(self):
        self.product.delete()
        self.assertEqual('deleted', self.listener.action)
        self.assertIsInstance(self.listener.resource, Product)
        self.assertEqual(self.INITIAL_PREFIX, self.prefix)

    def test_get_tickets(self):
        for pdata in (
            {'prefix': 'p2', 'name':'product, too', 'description': ''},
            {'prefix': 'p3', 'name':'strike three', 'description': ''},
        ):
            num_tickets = 5
            product = Product(self.global_env)
            product._data.update(pdata)
            product.insert()
            self.env = ProductEnvironment(self.global_env, product)
            for i in range(num_tickets):
                ticket = Ticket(self.env)
                ticket['summary'] = 'hello ticket #%s-%d' % (product.prefix, i)
                ticket['reporter'] = 'admin'
                tid = ticket.insert()

            # retrieve tickets using both global and product scope
            tickets_from_global = [(t['product'], t['id']) for t in
                Product.get_tickets(self.global_env, product.prefix)]
            self.assertEqual(len(tickets_from_global), num_tickets)
            tickets_from_product = [(t['product'], t['id']) for t in
                Product.get_tickets(self.env)]
            self.assertEqual(len(tickets_from_product), num_tickets)
            # both lists should contain same elements
            intersection = set(tickets_from_global) & set(tickets_from_product)
            self.assertEqual(len(intersection), num_tickets)
Example #5
0
class ProductTestCase(unittest.TestCase):
    """Unit tests covering the Product model"""
    INITIAL_PREFIX = 'tp'
    INITIAL_NAME = 'test project'
    INITIAL_DESCRIPTION = 'a test project'

    def setUp(self):
        self.env = EnvironmentStub(enable=['trac.*', 'multiproduct.*'])
        self.env.path = tempfile.mkdtemp(prefix='bh-product-tempenv-')

        self.mpsystem = MultiProductSystem(self.env)
        try:
            self.mpsystem.upgrade_environment(self.env.db_transaction)
        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,
            'description': self.INITIAL_DESCRIPTION
        }

        self.global_env = self.env
        self.product = Product(self.env)
        self.product._data.update(self.default_data)
        self.product.insert()

    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
        listener.callback = self.listener_callback
        return listener

    def listener_callback(self, action, resource, context, old_values=None):
        # pylint: disable=unused-argument
        # pylint: disable=attribute-defined-outside-init
        self.prefix = resource.prefix
        self.name = resource.name
        self.description = resource.description

    def test_set_table_field(self):
        """tests that table.field style update works"""
        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, where={'name': 'test project'}))
        self.assertEqual(1, len(products))
        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',
            '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',
            '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',
            'name': 'dupe',
            'description': 'dupe primary key'
        }
        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']
        name = self.default_data['name']
        description = self.default_data['description']
        product = list(Product.select(self.env, where={'prefix': prefix}))[0]
        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)

    def test_missing_unique_fields(self):
        """ensure that that insert method works when _meta does not specify
        unique fields when inserting more than one ProductResourceMap instances
        """
        class TestModel(ModelBase):
            """A test model with no unique_fields"""
            _meta = {
                'table_name': 'bloodhound_testmodel',
                'object_name': 'TestModelObject',
                'key_fields': [
                    'id',
                ],
                'non_key_fields': ['value'],
                'unique_fields': [],
            }

        from trac.db import DatabaseManager
        schema = [
            TestModel._get_schema(),
        ]
        with self.env.db_transaction as db:
            db_connector, dummy = DatabaseManager(self.env)._get_connector()
            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)
        tm1._data.update({'id': 1, 'value': 'value1'})
        tm1.insert()
        tm2 = TestModel(self.env)
        tm2._data.update({'id': 2, 'value': 'value2'})
        tm2.insert()

    def test_change_listener_created(self):
        self.assertEqual('created', self.listener.action)
        self.assertIsInstance(self.listener.resource, Product)
        self.assertEqual(self.INITIAL_PREFIX, self.prefix)
        self.assertEqual(self.INITIAL_NAME, self.name)
        self.assertEqual(self.INITIAL_DESCRIPTION, self.description)

    def test_change_listener_changed(self):
        CHANGED_NAME = "changed name"
        self.product.name = CHANGED_NAME
        self.product.update()
        self.assertEqual('changed', self.listener.action)
        self.assertIsInstance(self.listener.resource, Product)
        self.assertEqual(CHANGED_NAME, self.name)
        self.assertEqual({"name": self.INITIAL_NAME}, self.listener.old_values)

    def test_change_listener_deleted(self):
        self.product.delete()
        self.assertEqual('deleted', self.listener.action)
        self.assertIsInstance(self.listener.resource, Product)
        self.assertEqual(self.INITIAL_PREFIX, self.prefix)

    def test_get_tickets(self):
        for pdata in (
            {
                'prefix': 'p2',
                'name': 'product, too',
                'description': ''
            },
            {
                'prefix': 'p3',
                'name': 'strike three',
                'description': ''
            },
        ):
            num_tickets = 5
            product = Product(self.global_env)
            product._data.update(pdata)
            product.insert()
            self.env = ProductEnvironment(self.global_env, product)
            for i in range(num_tickets):
                ticket = Ticket(self.env)
                ticket['summary'] = 'hello ticket #%s-%d' % (product.prefix, i)
                ticket['reporter'] = 'admin'
                tid = ticket.insert()

            # retrieve tickets using both global and product scope
            tickets_from_global = [
                (t['product'], t['id'])
                for t in Product.get_tickets(self.global_env, product.prefix)
            ]
            self.assertEqual(len(tickets_from_global), num_tickets)
            tickets_from_product = [(t['product'], t['id'])
                                    for t in Product.get_tickets(self.env)]
            self.assertEqual(len(tickets_from_product), num_tickets)
            # both lists should contain same elements
            intersection = set(tickets_from_global) & set(tickets_from_product)
            self.assertEqual(len(intersection), num_tickets)