Exemplo n.º 1
0
class PlatformBuildTestCase(unittest.TestCase):
    """Tests that involve Builds, TargetPlatforms and BuildSteps"""

    def setUp(self):
        self.env = EnvironmentStub()
        self.env.path = tempfile.mkdtemp()
        logs_dir = self.env.config.get("bitten", "logs_dir")
        if os.path.isabs(logs_dir):
            raise ValueError("Should not have absolute logs directory for temporary test")
        logs_dir = os.path.join(self.env.path, logs_dir)
        os.makedirs(logs_dir)

        db = self.env.get_db_cnx()
        cursor = db.cursor()
        connector, _ = DatabaseManager(self.env)._get_connector()
        for schema in [Build._schema, TargetPlatform._schema, BuildStep._schema]: 
            for table in schema:
                for stmt in connector.to_sql(table):
                    cursor.execute(stmt)
        db.commit()

    def test_delete_platform_with_pending_builds(self):
        """Check that deleting a platform with pending builds removes those pending builds"""
        db = self.env.get_db_cnx()
        platform = TargetPlatform(self.env, config='test', name='Linux')
        platform.insert()
        build = Build(self.env, config='test', platform=platform.id, rev='42', rev_time=12039)
        build.insert()

        platform.delete()
        pending = list(build.select(self.env, config='test', status=Build.PENDING))
        self.assertEqual(0, len(pending))
Exemplo n.º 2
0
class AnnouncementSystemSendTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub(enable=['trac.*', 'announcer.*'])
        self.env.path = tempfile.mkdtemp()
        self.db_mgr = DatabaseManager(self.env)
        self.db = self.env.get_db_cnx()
        self.an_sys = AnnouncementSystem(self.env)

    def tearDown(self):
        self.db.close()
        # Really close db connections.
        self.env.shutdown()
        shutil.rmtree(self.env.path)

    # Tests

    def test_filter_added(self):
        class DummySubscriptionFilter(Component):
            """Test implementation for checking the filter ExtensionPoint."""
            implements(IAnnouncementSubscriptionFilter)

            def filter_subscriptions(self, event, subscriptions):
                """Just a pass-through."""
                return subscriptions

        dummy = DummySubscriptionFilter(self.env)
        self.assertTrue(dummy in self.an_sys.subscription_filters)
Exemplo n.º 3
0
class VersionControlAdminTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub()

    def tearDown(self):
        self.env.reset_db()

    def test_render_admin_with_alias_to_default_repos(self):
        with self.env.db_transaction as db:
            # Add aliases to non-existent default repository
            db.executemany(
                "INSERT INTO repository (id, name, value) VALUES (%s, %s, %s)",
                [(1, 'name', ''),     (1, 'dir', None), (1, 'alias', ''),
                 (2, 'name', 'blah'), (2, 'dir', None), (2, 'alias', '')])

        panel = RepositoryAdminPanel(self.env)
        req = Mock(method='GET', chrome={}, args={}, session={},
                   abs_href=Href('/'), href=Href('/'), locale=None,
                   perm=MockPerm(), authname='anonymous', tz=utc)
        template, data = panel.render_admin_panel(req, 'versioncontrol',
                                                  'repository', '')
        repositories = data['repositories']
        self.assertNotEqual({}, repositories)
        self.assertEqual('', repositories['']['name'])
        self.assertEqual('', repositories['']['alias'])
        self.assertEqual('blah', repositories['blah']['name'])
        self.assertEqual('', repositories['blah']['alias'])
Exemplo n.º 4
0
class _BaseTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub(default_data=True,
                                   enable=['trac.*', 'tractags.*'])
        self.env.path = tempfile.mkdtemp()
        self.perms = PermissionSystem(self.env)
        self.req = Mock(authname='editor')

        self.actions = ['TAGS_ADMIN', 'TAGS_MODIFY', 'TAGS_VIEW']
        self.db = self.env.get_db_cnx()
        setup = TagSetup(self.env)
        # Current tractags schema is setup with enabled component anyway.
        #   Revert these changes for getting default permissions inserted.
        self._revert_tractags_schema_init()
        setup.upgrade_environment(self.db)
        self.tag_s = tractags.api.TagSystem(self.env)

    def tearDown(self):
        self.db.close()
        # Really close db connections.
        self.env.shutdown()
        shutil.rmtree(self.env.path)

    # Helpers

    def _revert_tractags_schema_init(self):
        cursor = self.db.cursor()
        cursor.execute("DROP TABLE IF EXISTS tags")
        cursor.execute("DROP TABLE IF EXISTS tags_change")
        cursor.execute("DELETE FROM system WHERE name='tags_version'")
        cursor.execute("DELETE FROM permission WHERE action %s"
                       % self.db.like(), ('TAGS_%',))
Exemplo n.º 5
0
class TicketFieldTimelineFilterTests(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        t1 = self._insert_and_load_ticket("foo")
        self.filter = TicketFieldTimelineFilter(self.env)
        self.context = Mock(resource=t1.resource)

    def tearDown(self):
        self.env.reset_db()

    def test_returns_none_for_invalid_ticket_id(self):
        event = ['ticket', None, None, ['88']]

        result = self.filter.filter_event(self.context, None, event, None)
        self.assertIsNone(result)

    def test_long_resource_id(self):
        """Test resource with long id (#547)"""
        resource = self.context.resource
        resource.id = long(resource.id)
        event = ['ticket', None, None, [resource]]

        result = self.filter.filter_event(self.context, None, event, None)
        self.assertEqual(result, event)

    def _insert_and_load_ticket(self, summary, **kw):
        ticket = Ticket(self.env)
        ticket["summary"] = summary
        for k, v in kw.items():
            ticket[k] = v
        return Ticket(self.env, ticket.insert())
Exemplo n.º 6
0
def make_trac_environment_with_plugin():
    env = EnvironmentStub(
        enable=["ticketref.*", TicketRefsPlugin, TicketRefsTemplate])
    TicketRefsPlugin(env).upgrade_environment(env.get_db_cnx())
    tref = TicketRefsPlugin(env)
    tmpl = TicketRefsTemplate(env)
    return env, tref, tmpl
Exemplo n.º 7
0
    def create_trac_ctx(self, website_url, author_name, timezone_str, uri):
        req = Mock(href=Href(uri),
                   abs_href=Href(website_url),
                   authname=author_name,
                   perm=MockPerm(),
                   tz=timezone_str,
                   args={})
        context = Context.from_request(req, 'wiki', 'WikiStart')

        env = EnvironmentStub(enable=['trac.*']) # + additional components
        # -- macros support
        env.path = ''
        # -- intertrac support
        env.config.set('intertrac', 'trac.title', "Trac's Trac")
        env.config.set('intertrac', 'trac.url',
                       website_url)
        env.config.set('intertrac', 't', 'trac')
        env.config.set('intertrac', 'th.title', "Trac Hacks")
        env.config.set('intertrac', 'th.url',
                       "http://trac-hacks.org")
        env.config.set('intertrac', 'th.compat', 'false')
        # -- safe schemes
        env.config.set('wiki', 'safe_schemes',
                       'file,ftp,http,https,svn,svn+ssh,git,'
                       'rfc-2396.compatible,rfc-2396+under_score')

        env.href = req.href
        env.abs_href = req.abs_href
        return (env, context)
Exemplo n.º 8
0
class _BaseTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub(default_data=True,
                                   enable=['trac.*', 'tractags.*'])
        self.env.path = tempfile.mkdtemp()

        self.db = self.env.get_db_cnx()
        setup = TagSetup(self.env)
        # Current tractags schema is setup with enabled component anyway.
        #   Revert these changes for getting default permissions inserted.
        self._revert_tractags_schema_init()
        setup.upgrade_environment(self.db)

    def tearDown(self):
        self.db.close()
        # Really close db connections.
        self.env.shutdown()
        shutil.rmtree(self.env.path)

    # Helpers

    def _revert_tractags_schema_init(self):
        cursor = self.db.cursor()
        cursor.execute("DROP TABLE IF EXISTS tags")
        cursor.execute("DROP TABLE IF EXISTS tags_change")
        cursor.execute("DELETE FROM system WHERE name='tags_version'")
        cursor.execute("DELETE FROM permission WHERE action %s"
                       % self.db.like(), ('TAGS_%',))

    def _insert_tags(self, tagspace, name, tags):
        cursor = self.db.cursor()
        args = [(tagspace, name, tag) for tag in tags]
        cursor.executemany("INSERT INTO tags (tagspace,name,tag) "
                           "VALUES (%s,%s,%s)", args)
Exemplo n.º 9
0
class ComponentTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub(default_data=True)

    def tearDown(self):
        self.env.reset_db()

    def test_exists_negative(self):
        def get_fake_component():
            return Component(self.env, "Shrubbery")
        self.assertRaises(TracError, get_fake_component)

    def test_exists(self):
        """
        http://trac.edgewall.org/ticket/4247
        """
        for c in Component.select(self.env):
            self.assertEqual(c.exists, True)

    def test_create_and_update(self):
        component = Component(self.env)
        component.name = 'Test'
        component.insert()

        self.assertEqual([('Test', None, None)], self.env.db_query("""
            SELECT name, owner, description FROM component
            WHERE name='Test'"""))

        # Use the same model object to update the component
        component.owner = 'joe'
        component.update()
        self.assertEqual([('Test', 'joe', None)], self.env.db_query(
            "SELECT name, owner, description FROM component WHERE name='Test'"))
Exemplo n.º 10
0
class TargetPlatformTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub()
        self.env.path = tempfile.mkdtemp()
        logs_dir = self.env.config.get("bitten", "logs_dir")
        if os.path.isabs(logs_dir):
            raise ValueError("Should not have absolute logs directory for temporary test")
        logs_dir = os.path.join(self.env.path, logs_dir)
        os.makedirs(logs_dir)

        db = self.env.get_db_cnx()
        cursor = db.cursor()
        connector, _ = DatabaseManager(self.env)._get_connector()
        for table in TargetPlatform._schema:
            for stmt in connector.to_sql(table):
                cursor.execute(stmt)
        db.commit()

    def test_new(self):
        platform = TargetPlatform(self.env)
        self.assertEqual(False, platform.exists)
        self.assertEqual([], platform.rules)

    def test_insert(self):
        platform = TargetPlatform(self.env, config='test', name='Windows XP')
        platform.rules += [(Build.OS_NAME, 'Windows'), (Build.OS_VERSION, 'XP')]
        platform.insert()

        assert platform.exists
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        cursor.execute("SELECT config,name FROM bitten_platform "
                       "WHERE id=%s", (platform.id,))
        self.assertEqual(('test', 'Windows XP'), cursor.fetchone())

        cursor.execute("SELECT propname,pattern,orderno FROM bitten_rule "
                       "WHERE id=%s", (platform.id,))
        self.assertEqual((Build.OS_NAME, 'Windows', 0), cursor.fetchone())
        self.assertEqual((Build.OS_VERSION, 'XP', 1), cursor.fetchone())

    def test_fetch(self):
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        cursor.execute("INSERT INTO bitten_platform (config,name) "
                       "VALUES (%s,%s)", ('test', 'Windows'))
        id = db.get_last_id(cursor, 'bitten_platform')
        platform = TargetPlatform.fetch(self.env, id)
        assert platform.exists
        self.assertEqual('test', platform.config)
        self.assertEqual('Windows', platform.name)

    def test_select(self):
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        cursor.executemany("INSERT INTO bitten_platform (config,name) "
                           "VALUES (%s,%s)", [('test', 'Windows'),
                           ('test', 'Mac OS X')])
        platforms = list(TargetPlatform.select(self.env, config='test'))
        self.assertEqual(2, len(platforms))
Exemplo n.º 11
0
Arquivo: api.py Projeto: zjj/trac_hack
class ConnectionTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        self.db = self.env.get_db_cnx()

    def tearDown(self):
        self.env.reset_db()

    def test_get_last_id(self):
        c = self.db.cursor()
        q = "INSERT INTO report (author) VALUES ('anonymous')"
        c.execute(q)
        # Row ID correct before...
        id1 = self.db.get_last_id(c, 'report')
        self.assertNotEqual(0, id1)
        self.db.commit()
        c.execute(q)
        self.db.commit()
        # ... and after commit()
        id2 = self.db.get_last_id(c, 'report')
        self.assertEqual(id1 + 1, id2)

    def test_update_sequence(self):
        cursor = self.db.cursor()
        cursor.execute("""
            INSERT INTO report (id, author) VALUES (42, 'anonymous')
            """)
        self.db.commit()
        self.db.update_sequence(cursor, 'report', 'id')
        self.db.commit()
        cursor.execute("INSERT INTO report (author) VALUES ('next-id')")
        self.db.commit()
        cursor.execute("SELECT id FROM report WHERE author='next-id'")
        self.assertEqual(43, cursor.fetchall()[0][0])
Exemplo n.º 12
0
class StringsTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub()

    def test_insert_unicode(self):
        self.env.db_transaction(
                "INSERT INTO system (name,value) VALUES (%s,%s)",
                ('test-unicode', u'ünicöde'))
        self.assertEqual([(u'ünicöde',)], self.env.db_query(
            "SELECT value FROM system WHERE name='test-unicode'"))

    def test_insert_empty(self):
        from trac.util.text import empty
        self.env.db_transaction(
                "INSERT INTO system (name,value) VALUES (%s,%s)",
                ('test-empty', empty))
        self.assertEqual([(u'',)], self.env.db_query(
            "SELECT value FROM system WHERE name='test-empty'"))

    def test_insert_markup(self):
        from genshi.core import Markup
        self.env.db_transaction(
                "INSERT INTO system (name,value) VALUES (%s,%s)",
                ('test-markup', Markup(u'<em>märkup</em>')))
        self.assertEqual([(u'<em>märkup</em>',)], self.env.db_query(
            "SELECT value FROM system WHERE name='test-markup'"))

    def test_quote(self):
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        cursor.execute('SELECT 1 AS %s' % \
                       db.quote(r'alpha\`\"\'\\beta``gamma""delta'))
        self.assertEqual(r'alpha\`\"\'\\beta``gamma""delta',
                         get_column_names(cursor)[0])
Exemplo n.º 13
0
class PluginAdminPanelTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        self.req = Mock(
            args={},
            chrome={"notices": []},
            href=self.env.href,
            lc_time=locale_en,
            method=None,
            perm=MockPerm(),
            session={},
            tz=utc,
        )

    def tearDown(self):
        self.env.reset_db()

    def test_abstract_component_not_visible(self):
        class AbstractComponent(Component):
            abstract = True

        class NotAbstractComponent(Component):
            abstract = False

        panel = PluginAdminPanel(self.env)
        data = panel.render_admin_panel(self.req, "general", "plugin", None)[1]

        module = self.__class__.__module__
        components = []
        for plugin in data["plugins"]:
            if module in plugin["modules"].keys():
                components = plugin["modules"][module]["components"].keys()
        self.assertNotIn("AbstractComponent", components)
        self.assertIn("NotAbstractComponent", components)
Exemplo n.º 14
0
class TracHoursByCommentTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub(default_data=True,
                                   enable=['trac.*', 'trachours.*'])
        self.env.path = tempfile.mkdtemp()
        setup = SetupTracHours(self.env)
        setup.upgrade_environment(db=self.env.get_db_cnx())
        self.hours_thp = TracHoursPlugin(self.env)
        self.hours_thbc = TracHoursByComment(self.env)
        self.ticket_system = TicketSystem(self.env)

    def tearDown(self):
        self.env.reset_db()
        revert_trachours_schema_init(db=self.env.get_db_cnx())
        shutil.rmtree(self.env.path)

    def test_ticket_delete(self):
        ticket = Ticket(self.env)
        ticket['summary'] = 'ticket summary'
        ticket.insert()
        self.hours_thp.add_ticket_hours(ticket.id, 'user', 160)
        self.hours_thp.add_ticket_hours(ticket.id, 'user', 1200)

        ticket.delete()

        hours = self.hours_thp.get_ticket_hours(ticket.id)
        self.assertEqual([], hours)
Exemplo n.º 15
0
class GetBlogPostsTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        if hasattr(self.env, "db_transaction"):
            with self.env.db_transaction as db:
                FullBlogSetup(self.env).upgrade_environment(db)
        else:
            FullBlogSetup(self.env).upgrade_environment(self.env.get_db_cnx())

    def tearDown(self):
        self.env.destroy_db()
        del self.env

    def test_get_by_category(self):
        bp = BlogPost(self.env, "one")
        bp.update_fields({"title": "one", "body": "body", "author": "user", "categories": "about stuff"})
        self.assertEquals([], bp.save("user"))
        posts = get_blog_posts(self.env)
        self.assertEquals(1, len(posts))
        self.assertEquals("one", posts[0][0])
        posts = get_blog_posts(self.env, category="non-existing")
        self.assertEquals(0, len(posts))
        posts = get_blog_posts(self.env, category="stuff")
        self.assertEquals(1, len(posts))
        self.assertEquals("one", posts[0][0])
        self.assertEquals(get_blog_posts(self.env, category="about"), get_blog_posts(self.env, category="stuff"))
Exemplo n.º 16
0
class VersionTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub(default_data=True)
        self.db = self.env.get_db_cnx()

    def tearDown(self):
        self.env.reset_db()

    def test_exists_negative(self):
        def get_fake_version():
            return Version(self.env, "-1")

        self.assertRaises(TracError, get_fake_version)

    def test_exists(self):
        """
        http://trac.edgewall.org/ticket/4247
        """
        for v in Version.select(self.env):
            self.assertEqual(v.exists, True)

    def test_create_and_update(self):
        version = Version(self.env)
        version.name = "Test"
        version.insert()

        cursor = self.db.cursor()
        cursor.execute("SELECT name,time,description FROM version " "WHERE name='Test'")
        self.assertEqual(("Test", 0, None), cursor.fetchone())

        # Use the same model object to update the version
        version.description = "Some text"
        version.update()
        cursor.execute("SELECT name,time,description FROM version " "WHERE name='Test'")
        self.assertEqual(("Test", 0, "Some text"), cursor.fetchone())
Exemplo n.º 17
0
class _BaseTestCase(unittest.TestCase):
    def setUp(self):
        #self.basedir = os.path.realpath(tempfile.mkdtemp())
        self.env = EnvironmentStub(enable=['trac.*', 'acct_mgr.*'])
        self.env.config.set('account-manager', 'password_store',
                            'SessionStore')
        self.store = SessionStore(self.env)
        #self.env.path = os.path.join(self.basedir, 'trac-tempenv')
        #os.mkdir(self.env.path)

    def test_get_users(self):
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        cursor.executemany("INSERT INTO session_attribute "
                       "(sid,authenticated,name,value) "
                       "VALUES (%s,1,'password',%s)",
                       [('a', 'a'),
                        ('b', 'b'),
                        ('c', 'c')])
        self.assertEqual(set(['a', 'b', 'c']), set(self.store.get_users()))

    def test_has_user(self):
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        cursor.execute("INSERT INTO session_attribute "
                       "(sid,authenticated,name,value) "
                       "VALUES (%s,1,'password',%s)",
                       ('bar', 'bar'))

        self.assertFalse(self.store.has_user('foo'))
        self.assertTrue(self.store.has_user('bar'))

    def test_create_user(self):
        self.assertFalse(self.store.has_user('foo'))
        self.store.set_password('foo', 'password')
        self.assertTrue(self.store.has_user('foo'))
 
    def test_update_password(self):
        self.store.set_password('foo', 'pass1')
        self.assertFalse(self.store.check_password('foo', 'pass2'))
        self.store.set_password('foo', 'pass2')
        self.assertTrue(self.store.check_password('foo', 'pass2'))
        self.store.set_password('foo', 'pass3', 'pass2')
        self.assertTrue(self.store.check_password('foo', 'pass3'))

    def test_delete_user(self):
        self.store.set_password('foo', 'password')
        self.assertTrue(self.store.has_user('foo'))
        self.assertTrue(self.store.delete_user('foo'))
        self.assertFalse(self.store.has_user('foo'))

    def test_delete_nonexistant_user(self):
        self.assertFalse(self.store.has_user('foo'))
        self.assertFalse(self.store.delete_user('foo'))

    def test_unicode_username_and_password(self):
        username = u'\u4e60'
        password = u'\u4e61'
        self.store.set_password(username, password)
        self.assertTrue(self.store.check_password(username, password))
Exemplo n.º 18
0
class ComponentTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub(default_data=True)
        self.db = self.env.get_db_cnx()

    def tearDown(self):
        self.env.reset_db()

    def test_exists_negative(self):
        def get_fake_component():
            return Component(self.env, "Shrubbery")

        self.assertRaises(TracError, get_fake_component)

    def test_exists(self):
        """
        http://trac.edgewall.org/ticket/4247
        """
        for c in Component.select(self.env):
            self.assertEqual(c.exists, True)

    def test_create_and_update(self):
        component = Component(self.env)
        component.name = "Test"
        component.insert()

        cursor = self.db.cursor()
        cursor.execute("SELECT name,owner,description FROM component " "WHERE name='Test'")
        self.assertEqual(("Test", None, None), cursor.fetchone())

        # Use the same model object to update the component
        component.owner = "joe"
        component.update()
        cursor.execute("SELECT name,owner,description FROM component " "WHERE name='Test'")
        self.assertEqual(("Test", "joe", None), cursor.fetchone())
Exemplo n.º 19
0
class GetBlogPostsTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub()
        FullBlogSetup(self.env).upgrade_environment(self.env.get_db_cnx())

    def tearDown(self):
        self.env.destroy_db()
        del self.env

    def test_get_by_category(self):
        bp = BlogPost(self.env, 'one')
        bp.update_fields({'title': 'one', 'body': 'body', 'author': 'user',
                          'categories': 'about stuff'})
        self.assertEquals([], bp.save('user'))
        posts = get_blog_posts(self.env)
        self.assertEquals(1, len(posts))
        self.assertEquals('one', posts[0][0])
        posts = get_blog_posts(self.env, category='non-existing')
        self.assertEquals(0, len(posts))
        posts = get_blog_posts(self.env, category='stuff')
        self.assertEquals(1, len(posts))
        self.assertEquals('one', posts[0][0])
        self.assertEquals(get_blog_posts(self.env, category='about'),
                          get_blog_posts(self.env, category='stuff'))
Exemplo n.º 20
0
class GroupPostsByMonthTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub()
        FullBlogSetup(self.env).upgrade_environment(self.env.get_db_cnx())

    def tearDown(self):
        self.env.destroy_db()
        del self.env

    def test_many_posts(self):
        # 2 posts in one period
        one = BlogPost(self.env, 'one')
        one.update_fields({'title': 'one', 'body': 'body', 'author': 'user'})
        self.assertEquals([], one.save('user'))
        two = BlogPost(self.env, 'two')
        two.update_fields({'title': 'two', 'body': 'body', 'author': 'user'})
        self.assertEquals([], two.save('user'))
        grouped = group_posts_by_month(get_blog_posts(self.env))
        self.assertEquals(1, len(grouped))
        # Add 1 post in another period
        three = BlogPost(self.env, 'three')
        three.update_fields({'title': 'three', 'body': 'body', 'author': 'user',
            'publish_time': three.publish_time - datetime.timedelta(days=-100)})
        self.assertEquals([], three.save('user'))
        grouped = group_posts_by_month(get_blog_posts(self.env))
        self.assertEquals(2, len(grouped))
        self.assertEquals(1, len(grouped[0][1]))
        self.assertEquals(2, len(grouped[1][1]))
        self.assertEquals(type(grouped[0][0]), datetime.datetime)
        self.assertEquals((one.name, one.version, one.publish_time, one.author, one.title, one.body, []), grouped[1][1][0])

    def test_no_posts(self):
        grouped = group_posts_by_month(get_blog_posts(self.env))
        self.assertEquals([], grouped)
Exemplo n.º 21
0
class VersionTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub(default_data=True)

    def tearDown(self):
        self.env.reset_db()

    def test_exists_negative(self):
        def get_fake_version():
            return Version(self.env, "-1")
        self.assertRaises(TracError, get_fake_version)

    def test_exists(self):
        """
        http://trac.edgewall.org/ticket/4247
        """
        for v in Version.select(self.env):
            self.assertEqual(v.exists, True)

    def test_create_and_update(self):
        version = Version(self.env)
        version.name = 'Test'
        version.insert()

        self.assertEqual([('Test', 0, None)], self.env.db_query(
            "SELECT name, time, description FROM version WHERE name='Test'"))

        # Use the same model object to update the version
        version.description = 'Some text'
        version.update()
        self.assertEqual([('Test', 0, 'Some text')], self.env.db_query(
            "SELECT name, time, description FROM version WHERE name='Test'"))
Exemplo n.º 22
0
class CommitTicketUpdaterTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub(enable=['trac.*',
                                           'tracopt.ticket.commit_updater.*'])
        self.env.config.set('ticket', 'commit_ticket_update_check_perms', False)
        self.repos = Mock(Repository, 'repos1', {'name': 'repos1', 'id': 1},
                          self.env.log, normalize_rev=lambda rev: 1)
        self.updater = CommitTicketUpdater(self.env)

    def tearDown(self):
        self.env.reset_db()

    def _make_tickets(self, num):
        self.tickets = []
        for i in xrange(0, num):
            ticket = Ticket(self.env)
            ticket['reporter'] = 'someone'
            ticket['summary'] = random_sentence()
            ticket.insert()
            self.tickets.append(ticket)

    def test_changeset_added(self):
        self._make_tickets(1)
        message = 'This is the first comment. Refs #1.'
        chgset = Mock(repos=self.repos, rev=1, message=message, author='joe',
                      date=datetime(2001, 1, 1, 1, 1, 1, 0, utc))
        self.updater.changeset_added(self.repos, chgset)
        self.assertEqual("""\
In [changeset:"1/repos1" 1/repos1]:
{{{
#!CommitTicketReference repository="repos1" revision="1"
This is the first comment. Refs #1.
}}}""", self.tickets[0].get_change(cnum=1)['fields']['comment']['new'])

    def test_changeset_modified(self):
        self._make_tickets(2)
        message = 'This is the first comment. Refs #1.'
        old_chgset = Mock(repos=self.repos, rev=1,
                          message=message, author='joe',
                          date=datetime(2001, 1, 1, 1, 1, 1, 0, utc))
        message = 'This is the first comment after an edit. Refs #1, #2.'
        new_chgset = Mock(repos=self.repos, rev=1,
                          message=message, author='joe',
                          date=datetime(2001, 1, 2, 1, 1, 1, 0, utc))
        self.updater.changeset_added(self.repos, old_chgset)
        self.updater.changeset_modified(self.repos, new_chgset, old_chgset)
        self.assertEqual("""\
In [changeset:"1/repos1" 1/repos1]:
{{{
#!CommitTicketReference repository="repos1" revision="1"
This is the first comment. Refs #1.
}}}""", self.tickets[0].get_change(cnum=1)['fields']['comment']['new'])
        self.assertEqual("""\
In [changeset:"1/repos1" 1/repos1]:
{{{
#!CommitTicketReference repository="repos1" revision="1"
This is the first comment after an edit. Refs #1, #2.
}}}""", self.tickets[1].get_change(cnum=1)['fields']['comment']['new'])
Exemplo n.º 23
0
class CrashDumpModelTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub(enable=['trac.*', 'crashdump.*'])
        self.env.path = tempfile.mkdtemp()
        self.db_mgr = DatabaseManager(self.env)
        self.env.upgrade()
        #self.db = self.env.get_db_cnx()
        self.crashdump_module = CrashDumpModule(self.env)

    def tearDown(self):
        #self.db.close()
        self.env.shutdown()
        shutil.rmtree(self.env.path)

    def _insert_crashdump(self, **kw):
        """Helper for inserting a ticket into the database"""
        crash = CrashDump(env=self.env)
        for k, v in kw.items():
            crash[k] = v
        crash.insert()
        return crash

    def test_new_crash(self):
        crash = CrashDump(env=self.env)
        crash.insert()
        self.assertIsNotNone(crash)
        self.assertIsNone(crash.uuid)
        self.assertIsNotNone(crash.id)

    def test_existing_crash(self):

        crash = CrashDump(env=self.env, uuid='67cbc89f-1001-4691-a2c2-c1bb40aac806', must_exist=False)
        crash.insert()
        self.assertIsNotNone(crash.uuid)
        self.assertEqual(crash.uuid, '67cbc89f-1001-4691-a2c2-c1bb40aac806')

        crash2 = CrashDump(id=crash.id, env=self.env)
        self.assertIsNotNone(crash2.uuid)

        self.assertEqual(crash.id, crash2.id)
        self.assertEqual(crash.uuid, crash2.uuid)

        crash3 = CrashDump(uuid=crash.uuid, env=self.env)

        self.assertEqual(crash.uuid, crash3.uuid)
        self.assertEqual(crash.id, crash3.id)


        crash4 = CrashDump(id='      #%i           ' % crash.id, env=self.env)

        self.assertEqual(crash.uuid, crash4.uuid)
        self.assertEqual(crash.id, crash4.id)

    def test_non_existing_crash(self):
        self.assertRaises(ResourceNotFound,
                          CrashDump, id='#1742', env=self.env)

        self.assertRaises(ResourceNotFound,
                          CrashDump, id='42', env=self.env)
Exemplo n.º 24
0
    def destroy(self):
        """Remove all of the test environment data."""
        env = EnvironmentStub(path=self.tracdir, destroying=True)
        env.destroy_db()

        self.destroy_repo()
        if os.path.exists(self.dirname):
            rmtree(self.dirname)
Exemplo n.º 25
0
 def test_sub_var_mysql(self):
     env = EnvironmentStub()
     env.db = MockMySQLConnection() # ditto
     sql, values, missing_args = ReportModule(env).sql_sub_vars(
         "'$VAR'", {'VAR': 'value'})
     self.assertEqual("concat('', %s, '')", sql)
     self.assertEqual(['value'], values)
     self.assertEqual([], missing_args)
Exemplo n.º 26
0
 def test_sub_var_mysql(self):
     req = Mock(hdf=dict())
     env = EnvironmentStub()
     env.db = MockMySQLConnection()
     sql, args = ReportModule(env).sql_sub_vars(req, "'$VAR'",
                                                {'VAR': 'value'})
     self.assertEqual("concat('', %s, '')", sql)
     self.assertEqual(['value'], args)
Exemplo n.º 27
0
class DefaultPermissionStoreTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub(enable=[perm.DefaultPermissionStore,
                                           perm.DefaultPermissionGroupProvider])
        self.store = perm.DefaultPermissionStore(self.env)

    def test_simple_actions(self):
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        cursor.executemany("INSERT INTO permission VALUES (%s,%s)", [
                           ('john', 'WIKI_MODIFY'), ('john', 'REPORT_ADMIN'),
                           ('kate', 'TICKET_CREATE')])
        self.assertEquals(['WIKI_MODIFY', 'REPORT_ADMIN'],
                          self.store.get_user_permissions('john'))
        self.assertEquals(['TICKET_CREATE'], self.store.get_user_permissions('kate'))

    def test_simple_group(self):
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        cursor.executemany("INSERT INTO permission VALUES (%s,%s)", [
                           ('dev', 'WIKI_MODIFY'), ('dev', 'REPORT_ADMIN'),
                           ('john', 'dev')])
        self.assertEquals(['WIKI_MODIFY', 'REPORT_ADMIN'],
                          self.store.get_user_permissions('john'))

    def test_nested_groups(self):
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        cursor.executemany("INSERT INTO permission VALUES (%s,%s)", [
                           ('dev', 'WIKI_MODIFY'), ('dev', 'REPORT_ADMIN'),
                           ('admin', 'dev'), ('john', 'admin')])
        self.assertEquals(['WIKI_MODIFY', 'REPORT_ADMIN'],
                          self.store.get_user_permissions('john'))

    def test_builtin_groups(self):
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        cursor.executemany("INSERT INTO permission VALUES (%s,%s)", [
                           ('authenticated', 'WIKI_MODIFY'),
                           ('authenticated', 'REPORT_ADMIN'),
                           ('anonymous', 'TICKET_CREATE')])
        self.assertEquals(['WIKI_MODIFY', 'REPORT_ADMIN', 'TICKET_CREATE'],
                          self.store.get_user_permissions('john'))
        self.assertEquals(['TICKET_CREATE'],
                          self.store.get_user_permissions('anonymous'))

    def test_get_all_permissions(self):
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        cursor.executemany("INSERT INTO permission VALUES (%s,%s)", [
                           ('dev', 'WIKI_MODIFY'), ('dev', 'REPORT_ADMIN'),
                           ('john', 'dev')])
        expected = [('dev', 'WIKI_MODIFY'),
                    ('dev', 'REPORT_ADMIN'),
                    ('john', 'dev')]
        for res in self.store.get_all_permissions():
            self.failIf(res not in expected)
Exemplo n.º 28
0
    def destroy(self):
        """Remove all of the test environment data."""
        env = EnvironmentStub()
        env.destroy_db()
        env.shutdown()

        self.destroy_repo()
        if os.path.exists(self.dirname):
            rmtree(self.dirname)
Exemplo n.º 29
0
def env_stub_with_tables():
    env = EnvironmentStub()
    db = env.get_db_cnx()
    cursor = db.cursor()
    connector, _ = DatabaseManager(env)._get_connector()
    for table in schema:
        for stmt in connector.to_sql(table):
            cursor.execute(stmt)
    return env
Exemplo n.º 30
0
class PermissionCacheTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub(enable=[perm.DefaultPermissionStore,
                                           perm.DefaultPermissionPolicy,
                                           TestPermissionRequestor])
        self.env.config.set('trac', 'permission_policies',
                            'DefaultPermissionPolicy')
        self.perm_system = perm.PermissionSystem(self.env)
        # by-pass DefaultPermissionPolicy cache:
        perm.DefaultPermissionPolicy.CACHE_EXPIRY = -1
        self.perm_system.grant_permission('testuser', 'TEST_MODIFY')
        self.perm_system.grant_permission('testuser', 'TEST_ADMIN')
        self.perm = perm.PermissionCache(self.env, 'testuser')

    def tearDown(self):
        self.env.reset_db()

    def test_contains(self):
        self.assertTrue('TEST_MODIFY' in self.perm)
        self.assertTrue('TEST_ADMIN' in self.perm)
        self.assertFalse('TRAC_ADMIN' in self.perm)

    def test_has_permission(self):
        self.assertTrue(self.perm.has_permission('TEST_MODIFY'))
        self.assertTrue(self.perm.has_permission('TEST_ADMIN'))
        self.assertFalse(self.perm.has_permission('TRAC_ADMIN'))

    def test_require(self):
        self.perm.require('TEST_MODIFY')
        self.perm.require('TEST_ADMIN')
        self.assertRaises(perm.PermissionError, self.perm.require,
                          'TRAC_ADMIN')

    def test_assert_permission(self):
        self.perm.assert_permission('TEST_MODIFY')
        self.perm.assert_permission('TEST_ADMIN')
        self.assertRaises(perm.PermissionError,
                          self.perm.assert_permission, 'TRAC_ADMIN')

    def test_cache(self):
        self.perm.assert_permission('TEST_MODIFY')
        self.perm.assert_permission('TEST_ADMIN')
        self.perm_system.revoke_permission('testuser', 'TEST_ADMIN')
        # Using cached GRANT here
        self.perm.assert_permission('TEST_ADMIN')

    def test_cache_shared(self):
        # we need to start with an empty cache here (#7201)
        perm1 = perm.PermissionCache(self.env, 'testcache')
        perm1 = perm1('ticket', 1)
        perm2 = perm1('ticket', 1) # share internal cache
        self.perm_system.grant_permission('testcache', 'TEST_ADMIN')
        perm1.assert_permission('TEST_ADMIN')
        self.perm_system.revoke_permission('testcache', 'TEST_ADMIN')
        # Using cached GRANT here (from shared cache)
        perm2.assert_permission('TEST_ADMIN')
Exemplo n.º 31
0
class MySQLConnectionTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        self.schema = [
            Table('test_simple', key='id')[Column('id', auto_increment=True),
                                           Column('username'),
                                           Column('email'),
                                           Column('enabled', type='int'),
                                           Column('extra'),
                                           Index(['username'], unique=True),
                                           Index(['email'], unique=False), ],
            Table('test_composite',
                  key=['id',
                       'name'])[Column('id', type='int'),
                                Column('name'),
                                Column('value'),
                                Column('enabled', type='int'),
                                Index(['name', 'value'], unique=False),
                                Index(['name', 'enabled'], unique=True), ],
        ]
        self.dbm = DatabaseManager(self.env)
        self.dbm.drop_tables(self.schema)
        self.dbm.create_tables(self.schema)
        self.dbm.insert_into_tables([
            ('test_simple', ('username', 'email', 'enabled'),
             [('joe', '*****@*****.**', 1), (u'joé', '*****@*****.**', 0)]),
            ('test_composite', ('id', 'name', 'value', 'enabled'),
             [(1, 'foo', '42', 1), (1, 'bar', '42', 1), (2, 'foo', '43', 0),
              (2, 'bar', '43', 0)]),
        ])

    def tearDown(self):
        DatabaseManager(self.env).drop_tables(self.schema)
        self.env.reset_db()

    def _show_index(self, table):
        with self.env.db_query as db:
            cursor = db.cursor()
            cursor.execute("SHOW INDEX FROM " + db.quote(table))
            columns = get_column_names(cursor)
            rows = [dict(zip(columns, row)) for row in cursor]
            results = {}
            for index, group in itertools.groupby(rows,
                                                  lambda v: v['Key_name']):
                group = list(group)
                results[index] = {
                    'unique': not group[0]['Non_unique'],
                    'columns': [row['Column_name'] for row in group],
                }
            return results

    def _drop_column(self, table, column):
        with self.env.db_transaction as db:
            db.drop_column(table, column)

    def _query(self, stmt, *args):
        return self.env.db_query(stmt, args)

    def test_remove_simple_keys(self):
        indices_0 = self._show_index('test_simple')
        self.assertEqual(
            ['PRIMARY', 'test_simple_email_idx', 'test_simple_username_idx'],
            sorted(indices_0))
        self.assertEqual({
            'unique': True,
            'columns': ['id']
        }, indices_0['PRIMARY'])
        self.assertEqual({
            'unique': True,
            'columns': ['username']
        }, indices_0['test_simple_username_idx'])
        self.assertEqual({
            'unique': False,
            'columns': ['email']
        }, indices_0['test_simple_email_idx'])

        self._drop_column('test_simple', 'enabled')
        self.assertEqual(indices_0, self._show_index('test_simple'))

        self._drop_column('test_simple', 'username')
        indices_1 = self._show_index('test_simple')
        self.assertEqual(['PRIMARY', 'test_simple_email_idx'],
                         sorted(indices_1))

        self._drop_column('test_simple', 'email')
        indices_2 = self._show_index('test_simple')
        self.assertEqual(['PRIMARY'], sorted(indices_2))

        self._drop_column('test_simple', 'id')
        indices_3 = self._show_index('test_simple')
        self.assertEqual({}, indices_3)

    def test_remove_composite_keys(self):
        indices_0 = self._show_index('test_composite')
        self.assertEqual([
            'PRIMARY', 'test_composite_name_enabled_idx',
            'test_composite_name_value_idx'
        ], sorted(indices_0))
        self.assertEqual({
            'unique': True,
            'columns': ['id', 'name']
        }, indices_0['PRIMARY'])
        self.assertEqual({
            'unique': False,
            'columns': ['name', 'value']
        }, indices_0['test_composite_name_value_idx'])
        self.assertEqual({
            'unique': True,
            'columns': ['name', 'enabled']
        }, indices_0['test_composite_name_enabled_idx'])

        self._drop_column('test_composite', 'id')
        indices_1 = self._show_index('test_composite')
        self.assertEqual([
            'test_composite_name_enabled_idx', 'test_composite_name_value_idx'
        ], sorted(indices_1))
        self.assertEqual(indices_0['test_composite_name_value_idx'],
                         indices_1['test_composite_name_value_idx'])
        self.assertEqual(indices_0['test_composite_name_enabled_idx'],
                         indices_1['test_composite_name_enabled_idx'])
        rows = self._query("""SELECT * FROM test_composite
                              ORDER BY name, value, enabled""")
        self.assertEqual([('bar', '42', 1), ('bar', '43', 0), ('foo', '42', 1),
                          ('foo', '43', 0)], rows)

        self._drop_column('test_composite', 'name')
        self.assertEqual({}, self._show_index('test_composite'))
        rows = self._query("""SELECT * FROM test_composite
                              ORDER BY value, enabled""")
        self.assertEqual([('42', 1), ('42', 1), ('43', 0), ('43', 0)], rows)
Exemplo n.º 32
0
 def setUp(self):
     self.env = EnvironmentStub(path=mkdtemp())
     os.mkdir(self.env.templates_dir)
     filepath = os.path.join(self.env.templates_dir, self.filename)
     create_file(filepath, self.template)
     self.chrome = Chrome(self.env)
Exemplo n.º 33
0
 def setUp(self):
     self.env = EnvironmentStub(enable=self.system_info_providers)
Exemplo n.º 34
0
class UnicodeNameTestCase(unittest.TestCase, GitCommandMixin):

    def setUp(self):
        self.env = EnvironmentStub()
        self.repos_path = mkdtemp()
        # create git repository and master branch
        self._git('init')
        self._git('config', 'core.quotepath', 'true')  # ticket:11198
        self._git('config', 'user.name', "Joé")  # passing utf-8 bytes
        self._git('config', 'user.email', "*****@*****.**")
        create_file(os.path.join(self.repos_path, '.gitignore'))
        self._git('add', '.gitignore')
        self._git_commit('-a', '-m', 'test',
                         date=datetime(2013, 1, 1, 9, 4, 57))

    def tearDown(self):
        self.env.reset_db()
        if os.path.isdir(self.repos_path):
            rmtree(self.repos_path)

    def _storage(self):
        path = os.path.join(self.repos_path, '.git')
        return Storage(path, self.env.log, self.git_bin, 'utf-8')

    def test_unicode_verifyrev(self):
        storage = self._storage()
        self.assertIsNotNone(storage.verifyrev(u'master'))
        self.assertIsNone(storage.verifyrev(u'tété'))

    def test_unicode_filename(self):
        create_file(os.path.join(self.repos_path, 'tickét.txt'))
        self._git('add', 'tickét.txt')
        self._git_commit('-m', 'unicode-filename', date='1359912600 +0100')
        storage = self._storage()
        filenames = sorted(fname for mode, type, sha, size, fname
                                 in storage.ls_tree('HEAD'))
        self.assertEqual(unicode, type(filenames[0]))
        self.assertEqual(unicode, type(filenames[1]))
        self.assertEqual(u'.gitignore', filenames[0])
        self.assertEqual(u'tickét.txt', filenames[1])
        # check commit author, for good measure
        self.assertEqual(u'Joé <*****@*****.**> 1359912600 +0100',
                         storage.read_commit(storage.head())[1]['author'][0])

    def test_unicode_branches(self):
        self._git('checkout', '-b', 'tickɇt10980', 'master')
        storage = self._storage()
        branches = sorted(storage.get_branches())
        self.assertEqual(unicode, type(branches[0][0]))
        self.assertEqual(unicode, type(branches[1][0]))
        self.assertEqual(u'master', branches[0][0])
        self.assertEqual(u'tickɇt10980', branches[1][0])

        contains = sorted(storage.get_branch_contains(branches[1][1],
                                                      resolve=True))
        self.assertEqual(unicode, type(contains[0][0]))
        self.assertEqual(unicode, type(contains[1][0]))
        self.assertEqual(u'master', contains[0][0])
        self.assertEqual(u'tickɇt10980', contains[1][0])

    def test_unicode_tags(self):
        self._git('tag', 'tɐg-t10980', 'master')
        self._git_commit('-m', 'blah', '--allow-empty')
        self._git('tag', 'v0.42.1', 'master')
        storage = self._storage()

        tags = storage.get_tags()
        self.assertEqual(unicode, type(tags[0]))
        self.assertEqual([u'tɐg-t10980', 'v0.42.1'], tags)

        rev = storage.verifyrev(u'tɐg-t10980')
        self.assertIsNotNone(rev)
        self.assertEqual([u'tɐg-t10980'], storage.get_tags(rev))

        rev = storage.verifyrev('v0.42.1')
        self.assertIsNotNone(rev)
        self.assertEqual(['v0.42.1'], storage.get_tags(rev))

    def test_ls_tree(self):
        paths = [u'normal-path.txt',
                 u'tickét.tx\\t',
                 u'\a\b\t\n\v\f\r\x1b"\\.tx\\t']
        for path in paths:
            path_utf8 = path.encode('utf-8')
            create_file(os.path.join(self.repos_path, path_utf8))
            self._git('add', path_utf8)
        self._git_commit('-m', 'ticket:11180 and ticket:11198',
                         date=datetime(2013, 4, 30, 13, 48, 57))

        storage = self._storage()
        rev = storage.head()
        entries = storage.ls_tree(rev, '/')
        self.assertEqual(4, len(entries))
        self.assertEqual(u'\a\b\t\n\v\f\r\x1b"\\.tx\\t', entries[0][4])
        self.assertEqual(u'.gitignore', entries[1][4])
        self.assertEqual(u'normal-path.txt', entries[2][4])
        self.assertEqual(u'tickét.tx\\t', entries[3][4])

    def test_get_historian(self):
        paths = [u'normal-path.txt',
                 u'tickét.tx\\t',
                 u'\a\b\t\n\v\f\r\x1b"\\.tx\\t']

        for path in paths:
            path_utf8 = path.encode('utf-8')
            create_file(os.path.join(self.repos_path, path_utf8))
            self._git('add', path_utf8)
        self._git_commit('-m', 'ticket:11180 and ticket:11198',
                         date=datetime(2013, 4, 30, 17, 48, 57))

        def validate(path, quotepath):
            self._git('config', 'core.quotepath', quotepath)
            storage = self._storage()
            rev = storage.head()
            with storage.get_historian('HEAD', path) as historian:
                hrev = storage.last_change('HEAD', path, historian)
                self.assertEqual(rev, hrev)

        validate(paths[0], 'true')
        validate(paths[0], 'false')
        validate(paths[1], 'true')
        validate(paths[1], 'false')
        validate(paths[2], 'true')
        validate(paths[2], 'false')
Exemplo n.º 35
0
 def setUp(self):
     self.env = EnvironmentStub(path=mkdtemp())
     self.chrome = Chrome(self.env)
Exemplo n.º 36
0
 def _destroy_db(self):
     EnvironmentStub(path=self.path, destroying=True).destroy_db()
Exemplo n.º 37
0
class WikiPageTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        self.env.path = tempfile.mkdtemp(prefix='trac-tempenv-')

    def tearDown(self):
        self.env.reset_db_and_disk()

    def test_new_page(self):
        page = WikiPage(self.env)
        self.assertFalse(page.exists)
        self.assertIsNone(page.name)
        self.assertEqual(0, page.version)
        self.assertEqual('', page.text)
        self.assertEqual(0, page.readonly)
        self.assertEqual('', page.author)
        self.assertEqual('', page.comment)
        self.assertIsNone(page.time)
        self.assertEqual('<WikiPage None>', repr(page))

    def test_existing_page(self):
        t = datetime(2001, 1, 1, 1, 1, 1, 0, utc)
        self.env.db_transaction(
            "INSERT INTO wiki VALUES(%s,%s,%s,%s,%s,%s,%s,%s)",
            ('TestPage', 1, to_utimestamp(t), 'joe', '::1', 'Bla bla',
             'Testing', 0))

        page = WikiPage(self.env, 'TestPage')
        self.assertTrue(page.exists)
        self.assertEqual('TestPage', page.name)
        self.assertEqual(1, page.version)
        self.assertIsNone(page.resource.version)
        self.assertEqual('Bla bla', page.text)
        self.assertEqual(0, page.readonly)
        self.assertEqual('joe', page.author)
        self.assertEqual('Testing', page.comment)
        self.assertEqual(t, page.time)
        self.assertEqual("<WikiPage u'TestPage@1'>", repr(page))

        history = list(page.get_history())
        self.assertEqual(1, len(history))
        self.assertEqual((1, t, 'joe', 'Testing', '::1'), history[0])

        page = WikiPage(self.env, 'TestPage', 1)
        self.assertEqual(1, page.resource.version)
        self.assertEqual(1, page.version)

        resource = Resource('wiki', 'TestPage')
        page = WikiPage(self.env, resource, 1)
        self.assertEqual(1, page.version)

    def test_create_page(self):
        page = WikiPage(self.env)
        page.name = 'TestPage'
        page.text = 'Bla bla'
        t = datetime(2001, 1, 1, 1, 1, 1, 0, utc)
        page.save('joe', 'Testing', '::1', t)

        self.assertTrue(page.exists)
        self.assertEqual(1, page.version)
        self.assertIsNone(page.resource.version)
        self.assertEqual(0, page.readonly)
        self.assertEqual('joe', page.author)
        self.assertEqual('Testing', page.comment)
        self.assertEqual(t, page.time)

        self.assertEqual(
            [(1, to_utimestamp(t), 'joe', '::1', 'Bla bla', 'Testing', 0)],
            self.env.db_query(
                """
                SELECT version, time, author, ipnr, text, comment, readonly
                FROM wiki WHERE name=%s
                """, ('TestPage', )))

        listener = TestWikiChangeListener(self.env)
        self.assertEqual(page, listener.added[0])

    def test_update_page(self):
        t = datetime(2001, 1, 1, 1, 1, 1, 0, utc)
        t2 = datetime(2002, 1, 1, 1, 1, 1, 0, utc)
        self.env.db_transaction(
            "INSERT INTO wiki VALUES(%s,%s,%s,%s,%s,%s,%s,%s)",
            ('TestPage', 1, to_utimestamp(t), 'joe', '::1', 'Bla bla',
             'Testing', 0))

        page = WikiPage(self.env, 'TestPage')
        page.text = 'Bla'
        page.save('kate', 'Changing', '192.168.0.101', t2)

        self.assertEqual(2, page.version)
        self.assertIsNone(page.resource.version)
        self.assertEqual(0, page.readonly)
        self.assertEqual('kate', page.author)
        self.assertEqual('Changing', page.comment)
        self.assertEqual(t2, page.time)

        with self.env.db_query as db:
            rows = db(
                """
               SELECT version, time, author, ipnr, text, comment, readonly
               FROM wiki WHERE name=%s ORDER BY version
               """, ('TestPage', ))
            self.assertEqual(2, len(rows))
            self.assertEqual(
                (1, to_utimestamp(t), 'joe', '::1', 'Bla bla', 'Testing', 0),
                rows[0])
            self.assertEqual((2, to_utimestamp(t2), 'kate', '192.168.0.101',
                              'Bla', 'Changing', 0), rows[1])

        listener = TestLegacyWikiChangeListener(self.env)
        self.assertEqual((page, 2, t2, 'Changing', 'kate', '192.168.0.101'),
                         listener.changed[0])
        listener = TestWikiChangeListener(self.env)
        self.assertEqual((page, 2, t2, 'Changing', 'kate'),
                         listener.changed[0])

        page = WikiPage(self.env, 'TestPage')
        history = list(page.get_history())
        self.assertEqual(2, len(history))
        self.assertEqual((2, t2, 'kate', 'Changing', '192.168.0.101'),
                         history[0])
        self.assertEqual((1, t, 'joe', 'Testing', '::1'), history[1])

    def test_delete_page(self):
        self.env.db_transaction(
            "INSERT INTO wiki VALUES(%s,%s,%s,%s,%s,%s,%s,%s)",
            ('TestPage', 1, 42, 'joe', '::1', 'Bla bla', 'Testing', 0))

        page = WikiPage(self.env, 'TestPage')
        page.delete()

        self.assertFalse(page.exists)

        self.assertEqual([],
                         self.env.db_query(
                             """
            SELECT version, time, author, ipnr, text, comment, readonly
            FROM wiki WHERE name=%s
            """, ('TestPage', )))

        listener = TestWikiChangeListener(self.env)
        self.assertEqual(page, listener.deleted[0])

    def test_delete_page_version(self):
        self.env.db_transaction.executemany(
            "INSERT INTO wiki VALUES(%s,%s,%s,%s,%s,%s,%s,%s)",
            [('TestPage', 1, 42, 'joe', '::1', 'Bla bla', 'Testing', 0),
             ('TestPage', 2, 43, 'kate', '192.168.0.11', 'Bla', 'Changing', 0)
             ])

        page = WikiPage(self.env, 'TestPage')
        page.delete(version=2)

        self.assertTrue(page.exists)
        self.assertEqual([(1, 42, 'joe', '::1', 'Bla bla', 'Testing', 0)],
                         self.env.db_query(
                             """
                SELECT version, time, author, ipnr, text, comment, readonly
                FROM wiki WHERE name=%s
                """, ('TestPage', )))

        listener = TestWikiChangeListener(self.env)
        self.assertEqual(page, listener.deleted_version[0])

    def test_delete_page_last_version(self):
        self.env.db_transaction(
            "INSERT INTO wiki VALUES(%s,%s,%s,%s,%s,%s,%s,%s)",
            ('TestPage', 1, 42, 'joe', '::1', 'Bla bla', 'Testing', 0))

        page = WikiPage(self.env, 'TestPage')
        page.delete(version=1)

        self.assertFalse(page.exists)

        self.assertEqual([],
                         self.env.db_query(
                             """
            SELECT version, time, author, ipnr, text, comment, readonly
            FROM wiki WHERE name=%s
            """, ('TestPage', )))

        listener = TestWikiChangeListener(self.env)
        self.assertEqual(page, listener.deleted[0])

    def test_rename_page(self):
        data = (1, 42, 'joe', '::1', 'Bla bla', 'Testing', 0)
        self.env.db_transaction(
            "INSERT INTO wiki VALUES(%s,%s,%s,%s,%s,%s,%s,%s)",
            ('TestPage', ) + data)
        attachment = Attachment(self.env, 'wiki', 'TestPage')
        attachment.insert('foo.txt', StringIO(), 0, 1)

        page = WikiPage(self.env, 'TestPage')
        page.rename('PageRenamed')
        self.assertEqual('PageRenamed', page.name)
        self.assertEqual('PageRenamed', page.resource.id)

        self.assertEqual([data],
                         self.env.db_query(
                             """
            SELECT version, time, author, ipnr, text, comment, readonly
            FROM wiki WHERE name=%s
            """, ('PageRenamed', )))

        attachments = Attachment.select(self.env, 'wiki', 'PageRenamed')
        self.assertEqual('foo.txt', attachments.next().filename)
        self.assertRaises(StopIteration, attachments.next)
        Attachment.delete_all(self.env, 'wiki', 'PageRenamed')

        old_page = WikiPage(self.env, 'TestPage')
        self.assertFalse(old_page.exists)

        self.assertEqual([],
                         self.env.db_query(
                             """
            SELECT version, time, author, ipnr, text, comment, readonly
            FROM wiki WHERE name=%s
            """, ('TestPage', )))

        listener = TestWikiChangeListener(self.env)
        self.assertEqual((page, 'TestPage'), listener.renamed[0])

    def test_edit_comment_of_page_version(self):
        self.env.db_transaction.executemany(
            "INSERT INTO wiki VALUES(%s,%s,%s,%s,%s,%s,%s,%s)",
            [('TestPage', 1, 42, 'joe', '::1', 'Bla bla', 'old 1', 0),
             ('TestPage', 2, 43, 'kate', '::11', 'Bla', 'old 2', 0)])

        page = WikiPage(self.env, 'TestPage')
        page.edit_comment('edited comment two')

        old_page = WikiPage(self.env, 'TestPage', 1)
        old_page.edit_comment('new comment one')

        self.assertEqual('edited comment two', page.comment)
        self.assertEqual('new comment one', old_page.comment)
        self.assertEqual(
            [(1, 42, 'joe', '::1', 'Bla bla', 'new comment one', 0),
             (2, 43, 'kate', '::11', 'Bla', 'edited comment two', 0)],
            self.env.db_query(
                """
                SELECT version, time, author, ipnr, text, comment, readonly
                FROM wiki WHERE name=%s
                ORDER BY version
                """, ('TestPage', )))

        listener = TestWikiChangeListener(self.env)
        self.assertEqual((page, 'old 2'), listener.comment_modified[0])
        self.assertEqual((old_page, 'old 1'), listener.comment_modified[1])

    def test_invalid_page_name(self):
        invalid_names = ('../Page', 'Page/..', 'Page/////SubPage',
                         'Page/./SubPage', '/PagePrefix', 'PageSuffix/')

        for name in invalid_names:
            page = WikiPage(self.env)
            page.name = name
            page.text = 'Bla bla'
            t = datetime(2001, 1, 1, 1, 1, 1, 0, utc)
            self.assertRaises(TracError, page.save, 'joe', 'Testing', '::1', t)

        page = WikiPage(self.env)
        page.name = 'TestPage'
        page.text = 'Bla bla'
        t = datetime(2001, 1, 1, 1, 1, 1, 0, utc)
        page.save('joe', 'Testing', '::1', t)
        for name in invalid_names:
            page = WikiPage(self.env, 'TestPage')
            self.assertRaises(TracError, page.rename, name)

    def test_invalid_version(self):
        data = [(1, 42, 'joe', '::1', 'First revision', 'Rev1', 0),
                (2, 42, 'joe', '::1', 'Second revision', 'Rev2', 0)]
        with self.env.db_transaction as db:
            for d in data:
                db("INSERT INTO wiki VALUES(%s,%s,%s,%s,%s,%s,%s,%s)",
                   ('TestPage', ) + d)

        page = WikiPage(self.env, 'TestPage', '1abc')
        self.assertEqual(2, page.version)

        resource = Resource('wiki', 'TestPage')
        page = WikiPage(self.env, resource, '1abc')
        self.assertEqual(2, page.version)

        resource = Resource('wiki', 'TestPage', '1abc')
        page = WikiPage(self.env, resource)
        self.assertEqual(2, page.version)

        resource = Resource('wiki', 'TestPage', 1)
        page = WikiPage(self.env, resource)
        self.assertEqual(1, page.version)

        resource = Resource('wiki', 'TestPage', 2)
        page = WikiPage(self.env, resource, 1)
        self.assertEqual(1, page.version)
Exemplo n.º 38
0
 def _destroy_db(self):
     EnvironmentStub(path=self.path).destroy_db()
Exemplo n.º 39
0
 def setUp(self):
     self.env = EnvironmentStub(enable=('trac.web.chrome.*', ))
Exemplo n.º 40
0
class EnvironmentUpgradeTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()

    def tearDown(self):
        self.env.reset_db()

    def test_multiple_upgrade_participants(self):
        class Participant1(Component):
            implements(IEnvironmentSetupParticipant)

            def environment_created(self):
                pass

            def environment_needs_upgrade(self):
                return True

            def upgrade_environment(self):
                insert_value('value1', 1)

        class Participant2(Component):
            implements(IEnvironmentSetupParticipant)

            def environment_created(self):
                pass

            def environment_needs_upgrade(self):
                return True

            def upgrade_environment(self):
                insert_value('value2', 2)

        def insert_value(name, value):
            with self.env.db_transaction as db:
                db(
                    """
                    INSERT INTO {0} (name, value) VALUES (%s, %s)
                    """.format(db.quote('system')), (name, value))

        def select_value(name):
            with self.env.db_query as db:
                for value, in db(
                        """
                        SELECT value FROM {0} WHERE name=%s
                        """.format(db.quote('system')), (name, )):
                    return value

        self.env.enable_component(Participant1)
        self.env.enable_component(Participant2)

        self.assertTrue(self.env.needs_upgrade())
        self.assertTrue(self.env.upgrade())
        self.assertEqual('1', select_value('value1'))
        self.assertEqual('2', select_value('value2'))

    def test_upgrade_environment(self):
        """EnvironmentSetupParticipants are called only if
        environment_needs_upgrade returns True for the participant.
        """
        class SetupParticipantA(Component):
            implements(IEnvironmentSetupParticipant)

            called = False

            def environment_created(self):
                pass

            def environment_needs_upgrade(self):
                return True

            def upgrade_environment(self):
                self.called = True

        class SetupParticipantB(Component):
            implements(IEnvironmentSetupParticipant)

            called = False

            def environment_created(self):
                pass

            def environment_needs_upgrade(self):
                return False

            def upgrade_environment(self):
                self.called = True

        self.env.enable_component(SetupParticipantA)
        self.env.enable_component(SetupParticipantB)
        participant_a = SetupParticipantA(self.env)
        participant_b = SetupParticipantB(self.env)

        self.assertTrue(self.env.needs_upgrade())
        self.env.upgrade()
        self.assertTrue(participant_a.called)
        self.assertFalse(participant_b.called)
Exemplo n.º 41
0
 def setUp(self):
     self.env = EnvironmentStub()
     self.env.config.set('trac', 'base_url',
                         'https://trac.edgewall.org/some/path')
Exemplo n.º 42
0
class TagSystemTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub(default_data=True,
                                   enable=['trac.*', 'tractags.*'])
        self.env.path = tempfile.mkdtemp()
        self.perms = PermissionSystem(self.env)
        self.req = Mock()

        self.actions = ['TAGS_ADMIN', 'TAGS_MODIFY', 'TAGS_VIEW']
        self.tag_s = TagSystem(self.env)
        self.db = self.env.get_db_cnx()
        setup = TagSetup(self.env)
        # Current tractags schema is setup with enabled component anyway.
        #   Revert these changes for getting default permissions inserted.
        self._revert_tractags_schema_init()
        setup.upgrade_environment(self.db)

    def tearDown(self):
        self.db.close()
        # Really close db connections.
        self.env.shutdown()
        shutil.rmtree(self.env.path)

    # Helpers

    def _revert_tractags_schema_init(self):
        cursor = self.db.cursor()
        cursor.execute("DROP TABLE IF EXISTS tags")
        cursor.execute("DELETE FROM system WHERE name='tags_version'")
        cursor.execute(
            "DELETE FROM permission WHERE action %s" % self.db.like(),
            ('TAGS_%', ))

    # Tests

    def test_available_actions(self):
        for action in self.actions:
            self.failIf(action not in self.perms.get_actions())

    def test_available_providers(self):
        # Standard implementations of DefaultTagProvider should be registered.
        seen = []
        for provider in [
                TicketTagProvider(self.env),
                WikiTagProvider(self.env)
        ]:
            self.failIf(provider not in self.tag_s.tag_providers)
            # Ensure unique provider references, a possible bug in Trac-0.11.
            self.failIf(provider in seen)
            seen.append(provider)

    def test_set_tags_no_perms(self):
        resource = Resource('wiki', 'WikiStart')
        tags = ['tag1']
        # Mock an anonymous request.
        self.req.perm = PermissionCache(self.env)
        self.assertRaises(PermissionError, self.tag_s.set_tags, self.req,
                          resource, tags)

    def test_set_tags(self):
        resource = Resource('wiki', 'WikiStart')
        tags = ['tag1']
        self.req.perm = PermissionCache(self.env, username='******')
        # Shouldn't raise an error with appropriate permission.
        self.tag_s.set_tags(self.req, resource, tags)

    def test_query_no_args(self):
        # Regression test for query without argument,
        #   reported as th:ticket:7857.

        # Mock an anonymous request.
        self.req.perm = PermissionCache(self.env)
        self.assertEquals(
            [(res, tags)
             for res, tags in self.tag_s.query(self.req, query='')], [])
Exemplo n.º 43
0
 def setUp(self):
     self.basedir = os.path.realpath(tempfile.mkdtemp())
     self.env = EnvironmentStub()
     self.env.path = os.path.join(self.basedir, 'trac-tempenv')
     os.mkdir(self.env.path)
Exemplo n.º 44
0
 def setUp(self):
     self.env = EnvironmentStub()
Exemplo n.º 45
0
 def setUp(self):
     self.env = EnvironmentStub()
     self.env.path = tempfile.mkdtemp(prefix='trac-tempenv-')
Exemplo n.º 46
0
class KnownUsersTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub()
        users = [
            ('123', None, '*****@*****.**', 0),
            ('jane', 'Jane', None, 1),
            ('joe', None, '*****@*****.**', 1),
            ('tom', 'Tom', '*****@*****.**', 1)
        ]
        self.env.insert_users(users)
        self.expected = [user[:3] for user in users if user[3] == 1]

    def tearDown(self):
        self.env.reset_db()

    def test_get_known_users_as_list_of_tuples(self):
        users = list(self.env.get_known_users())

        i = 0
        for i, user in enumerate(users):
            self.assertEqual(self.expected[i], user)
        else:
            self.assertEqual(2, i)

    def test_get_known_users_as_dict(self):
        users = self.env.get_known_users(as_dict=True)

        self.assertEqual(3, len(users))
        for exp in self.expected:
            self.assertEqual(exp[1:], users[exp[0]])

    def test_get_known_users_is_cached(self):
        self.env.get_known_users()
        self.env.get_known_users(as_dict=True)
        self.env.insert_users([('user4', None, None)])

        users_list = list(self.env.get_known_users())
        users_dict = self.env.get_known_users(as_dict=True)

        i = 0
        for i, user in enumerate(users_list):
            self.assertEqual(self.expected[i], user)
            self.assertIn(self.expected[i][0], users_dict)
        else:
            self.assertEqual(2, i)
            self.assertEqual(3, len(users_dict))

    def test_invalidate_known_users_cache(self):
        self.env.get_known_users()
        self.env.get_known_users(as_dict=True)
        user = ('user4', 'User Four', '*****@*****.**')
        self.env.insert_users([user])
        self.expected.append(user[:3])

        self.env.invalidate_known_users_cache()
        users_list = self.env.get_known_users()
        users_dict = self.env.get_known_users(as_dict=True)

        i = 0
        for i, user in enumerate(users_list):
            self.assertEqual(self.expected[i], user)
            self.assertIn(self.expected[i][0], users_dict)
        else:
            self.assertEqual(3, i)
            self.assertEqual(4, len(users_dict))
Exemplo n.º 47
0
class CommitTicketUpdaterTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub(
            enable=['trac.*', 'tracopt.ticket.commit_updater.*'])
        self.env.config.set('ticket', 'commit_ticket_update_check_perms',
                            False)
        self.repos = Mock(Repository,
                          'repos1', {
                              'name': 'repos1',
                              'id': 1
                          },
                          self.env.log,
                          normalize_rev=lambda rev: 1)
        self.updater = CommitTicketUpdater(self.env)

    def tearDown(self):
        self.env.reset_db()

    def _make_tickets(self, num):
        self.tickets = []
        for i in xrange(num):
            ticket = insert_ticket(self.env,
                                   reporter='someone',
                                   summary=random_sentence())
            self.tickets.append(ticket)

    def test_changeset_added(self):
        self._make_tickets(1)
        message = 'This is the first comment. Refs #1.'
        chgset = Mock(repos=self.repos,
                      rev=1,
                      message=message,
                      author='joe',
                      date=datetime(2001, 1, 1, 1, 1, 1, 0, utc))
        self.updater.changeset_added(self.repos, chgset)
        changes = self.tickets[0].get_change(cnum=1)
        self.assertEqual(
            textwrap.dedent("""\
            In [changeset:"1/repos1" 1/repos1]:
            {{{
            #!CommitTicketReference repository="repos1" revision="1"
            This is the first comment. Refs #1.
            }}}"""), changes['fields']['comment']['new'])

    def test_changeset_modified(self):
        self._make_tickets(2)
        message = 'This is the first comment. Refs #1.'
        old_chgset = Mock(repos=self.repos,
                          rev=1,
                          message=message,
                          author='joe',
                          date=datetime(2001, 1, 1, 1, 1, 1, 0, utc))
        message = 'This is the first comment after an edit. Refs #1, #2.'
        new_chgset = Mock(repos=self.repos,
                          rev=1,
                          message=message,
                          author='joe',
                          date=datetime(2001, 1, 2, 1, 1, 1, 0, utc))
        self.updater.changeset_added(self.repos, old_chgset)
        self.updater.changeset_modified(self.repos, new_chgset, old_chgset)
        changes = self.tickets[0].get_change(cnum=1)
        self.assertEqual(
            textwrap.dedent("""\
            In [changeset:"1/repos1" 1/repos1]:
            {{{
            #!CommitTicketReference repository="repos1" revision="1"
            This is the first comment. Refs #1.
            }}}"""), changes['fields']['comment']['new'])
        changes = self.tickets[1].get_change(cnum=1)
        self.assertEqual(
            textwrap.dedent("""\
            In [changeset:"1/repos1" 1/repos1]:
            {{{
            #!CommitTicketReference repository="repos1" revision="1"
            This is the first comment after an edit. Refs #1, #2.
            }}}"""), changes['fields']['comment']['new'])

    def test_commands_refs(self):
        commands = {
            (1, ): 'Refs #1',
            (2, ): 'refs #2',
            (3, ): 'refs ticket:3#comment:1',
            (4, 5): 'refs ticket:4#comment:description and '
            'ticket:5#comment:1'
        }
        self._make_tickets(5)
        rev = 0

        for tkts, cmd in commands.items():
            rev += 1
            message = "This is the first comment. %s." % cmd
            chgset = Mock(repos=self.repos,
                          rev=rev,
                          message=message,
                          author='joe',
                          date=datetime(2001, 1, 1, 1, 1, 1, 0, utc))

            self.updater.changeset_added(self.repos, chgset)
            comment = self.updater.make_ticket_comment(self.repos, chgset)

            for tkt in tkts:
                change = self.tickets[tkt - 1].get_change(cnum=1)
                self.assertEqual(comment, change['fields']['comment']['new'])
Exemplo n.º 48
0
 def setUp(self):
     self.env = EnvironmentStub(enable=self.navigation_contributors)
Exemplo n.º 49
0
    def setUp(self):
        tmpdir = mkdtemp()
        self.authz_file = os.path.join(tmpdir, 'trac-authz')
        create_file(self.authz_file, textwrap.dedent("""\
            [groups]
            group1 = user
            group2 = @group1

            cycle1 = @cycle2
            cycle2 = @cycle3
            cycle3 = @cycle1, user

            alias1 = &jekyll
            alias2 = @alias1

            [aliases]
            jekyll = Mr Hyde

            # Read / write permissions
            [/readonly]
            user = r
            [/writeonly]
            user = w
            [/readwrite]
            user = rw
            [/empty]
            user =

            # Trailing slashes
            [/trailing_a]
            user = r
            [/trailing_b/]
            user = r

            # Sub-paths
            [/sub/path]
            user = r

            # Module usage
            [module:/module_a]
            user = r
            [other:/module_b]
            user = r
            [/module_c]
            user = r
            [module:/module_d]
            user =
            [/module_d]
            user = r

            # Wildcards
            [/wildcard]
            * = r

            # Special tokens
            [/special/anonymous]
            $anonymous = r
            [/special/authenticated]
            $authenticated = r

            # Groups
            [/groups_a]
            @group1 = r
            [/groups_b]
            @group2 = r
            [/cyclic]
            @cycle1 = r

            # Precedence
            [module:/precedence_a]
            user =
            [/precedence_a]
            user = r
            [/precedence_b]
            user = r
            [/precedence_b/sub]
            user =
            [/precedence_b/sub/test]
            user = r
            [/precedence_c]
            user =
            @group1 = r
            [/precedence_d]
            @group1 = r
            user =

            # Aliases
            [/aliases_a]
            &jekyll = r
            [/aliases_b]
            @alias2 = r

            # Scoped repository
            [scoped:/scope/dir1]
            joe = r
            [scoped:/scope/dir2]
            Jane = r

            # multiple entries
            [/multiple]
            $authenticated = r
            [/multiple/foo]
            joe =
            $authenticated =
            * = r
            [/multiple/bar]
            * =
            john = r
            Jane = r
            $anonymous = r
            [/multiple/baz]
            $anonymous = r
            * =
            Jane = r
            [module:/multiple/bar]
            joe = r
            john =

            # multiple entries with module and parent directory
            [/multiple/1]
            user = r
            @group1 = r
            $authenticated = r
            * = r
            [module:/multiple/1/user]
            user =
            [module:/multiple/1/group]
            @group1 =
            [module:/multiple/1/auth]
            $authenticated =
            [module:/multiple/1/star]
            * =
            [/multiple/2]
            user =
            @group1 =
            $authenticated =
            * =
            [module:/multiple/2/user]
            user = r
            [module:/multiple/2/group]
            @group1 = r
            [module:/multiple/2/auth]
            $authenticated = r
            [module:/multiple/2/star]
            * = r
            """))
        self.env = EnvironmentStub(enable=[AuthzSourcePolicy], path=tmpdir)
        self.env.config.set('trac', 'permission_policies',
                            'AuthzSourcePolicy, DefaultPermissionPolicy')
        self.env.config.set('svn', 'authz_file', self.authz_file)

        # Monkey-subclass RepositoryManager to serve mock repositories
        rm = RepositoryManager(self.env)

        class TestRepositoryManager(rm.__class__):
            def get_real_repositories(self):
                return {Mock(reponame='module'), Mock(reponame='other'),
                        Mock(reponame='scoped')}

            def get_repository(self, reponame):
                if reponame == 'scoped':
                    def get_changeset(rev):
                        if rev == 123:
                            def get_changes():
                                yield ('/dir1/file',)
                        elif rev == 456:
                            def get_changes():
                                yield ('/dir2/file',)
                        else:
                            def get_changes():
                                return iter([])
                        return Mock(get_changes=get_changes)
                    return Mock(scope='/scope',
                                get_changeset=get_changeset)
                return Mock(scope='/')

        rm.__class__ = TestRepositoryManager
Exemplo n.º 50
0
 def setUp(self):
     self.env = EnvironmentStub(default_data=True)
     self.env.config.set('ldap', 'enable', 'true')
     self.env.config.set('ldap', 'basedn', 'dc=example,dc=org')
     self.env.config.set('ldap', 'host', 'xebian')
Exemplo n.º 51
0
class AuthzSourcePolicyTestCase(unittest.TestCase):

    def setUp(self):
        tmpdir = mkdtemp()
        self.authz_file = os.path.join(tmpdir, 'trac-authz')
        create_file(self.authz_file, textwrap.dedent("""\
            [groups]
            group1 = user
            group2 = @group1

            cycle1 = @cycle2
            cycle2 = @cycle3
            cycle3 = @cycle1, user

            alias1 = &jekyll
            alias2 = @alias1

            [aliases]
            jekyll = Mr Hyde

            # Read / write permissions
            [/readonly]
            user = r
            [/writeonly]
            user = w
            [/readwrite]
            user = rw
            [/empty]
            user =

            # Trailing slashes
            [/trailing_a]
            user = r
            [/trailing_b/]
            user = r

            # Sub-paths
            [/sub/path]
            user = r

            # Module usage
            [module:/module_a]
            user = r
            [other:/module_b]
            user = r
            [/module_c]
            user = r
            [module:/module_d]
            user =
            [/module_d]
            user = r

            # Wildcards
            [/wildcard]
            * = r

            # Special tokens
            [/special/anonymous]
            $anonymous = r
            [/special/authenticated]
            $authenticated = r

            # Groups
            [/groups_a]
            @group1 = r
            [/groups_b]
            @group2 = r
            [/cyclic]
            @cycle1 = r

            # Precedence
            [module:/precedence_a]
            user =
            [/precedence_a]
            user = r
            [/precedence_b]
            user = r
            [/precedence_b/sub]
            user =
            [/precedence_b/sub/test]
            user = r
            [/precedence_c]
            user =
            @group1 = r
            [/precedence_d]
            @group1 = r
            user =

            # Aliases
            [/aliases_a]
            &jekyll = r
            [/aliases_b]
            @alias2 = r

            # Scoped repository
            [scoped:/scope/dir1]
            joe = r
            [scoped:/scope/dir2]
            Jane = r

            # multiple entries
            [/multiple]
            $authenticated = r
            [/multiple/foo]
            joe =
            $authenticated =
            * = r
            [/multiple/bar]
            * =
            john = r
            Jane = r
            $anonymous = r
            [/multiple/baz]
            $anonymous = r
            * =
            Jane = r
            [module:/multiple/bar]
            joe = r
            john =

            # multiple entries with module and parent directory
            [/multiple/1]
            user = r
            @group1 = r
            $authenticated = r
            * = r
            [module:/multiple/1/user]
            user =
            [module:/multiple/1/group]
            @group1 =
            [module:/multiple/1/auth]
            $authenticated =
            [module:/multiple/1/star]
            * =
            [/multiple/2]
            user =
            @group1 =
            $authenticated =
            * =
            [module:/multiple/2/user]
            user = r
            [module:/multiple/2/group]
            @group1 = r
            [module:/multiple/2/auth]
            $authenticated = r
            [module:/multiple/2/star]
            * = r
            """))
        self.env = EnvironmentStub(enable=[AuthzSourcePolicy], path=tmpdir)
        self.env.config.set('trac', 'permission_policies',
                            'AuthzSourcePolicy, DefaultPermissionPolicy')
        self.env.config.set('svn', 'authz_file', self.authz_file)

        # Monkey-subclass RepositoryManager to serve mock repositories
        rm = RepositoryManager(self.env)

        class TestRepositoryManager(rm.__class__):
            def get_real_repositories(self):
                return {Mock(reponame='module'), Mock(reponame='other'),
                        Mock(reponame='scoped')}

            def get_repository(self, reponame):
                if reponame == 'scoped':
                    def get_changeset(rev):
                        if rev == 123:
                            def get_changes():
                                yield ('/dir1/file',)
                        elif rev == 456:
                            def get_changes():
                                yield ('/dir2/file',)
                        else:
                            def get_changes():
                                return iter([])
                        return Mock(get_changes=get_changes)
                    return Mock(scope='/scope',
                                get_changeset=get_changeset)
                return Mock(scope='/')

        rm.__class__ = TestRepositoryManager

    def tearDown(self):
        self.env.reset_db_and_disk()

    def test_get_authz_file_notfound_raises(self):
        """ConfigurationError exception is raised if file not found."""
        authz_file = os.path.join(self.env.path, 'some-nonexistent-file')
        self.env.config.set('svn', 'authz_file', authz_file)
        policy = AuthzSourcePolicy(self.env)
        self.assertRaises(ConfigurationError, policy.check_permission,
                          'BROWSER_VIEW', 'user', None, None)

    def test_get_authz_file_notdefined_raises(self):
        """ConfigurationError exception is raised if the option
        `[svn] authz_file` is not specified in trac.ini."""
        self.env.config.remove('svn', 'authz_file')
        policy = AuthzSourcePolicy(self.env)
        self.assertRaises(ConfigurationError, policy.check_permission,
                          'BROWSER_VIEW', 'user', None, None)

    def test_get_authz_file_empty_raises(self):
        """ConfigurationError exception is raised if the option
        `[svn] authz_file` is empty."""
        self.env.config.set('svn', 'authz_file', '')
        policy = AuthzSourcePolicy(self.env)
        self.assertRaises(ConfigurationError, policy.check_permission,
                          'BROWSER_VIEW', 'user', None, None)

    def test_get_authz_file_removed_raises(self):
        """ConfigurationError exception is raised if file is removed."""
        policy = AuthzSourcePolicy(self.env)
        os.remove(self.authz_file)
        self.assertRaises(ConfigurationError, policy.check_permission,
                          'BROWSER_VIEW', 'user', None, None)

    def test_parse_error_raises(self):
        """ConfigurationError exception is raised when exception occurs
        parsing the `[svn authz_file`."""
        create_file(self.authz_file, textwrap.dedent("""\
            [/somepath
            joe = r
            """))
        policy = AuthzSourcePolicy(self.env)
        self.assertRaises(ConfigurationError, policy.check_permission,
                          'BROWSER_VIEW', 'user', None, None)

    def assertPathPerm(self, result, user, reponame=None, path=None):
        """Assert that `user` is granted access `result` to `path` within
        the repository `reponame`.
        """
        policy = AuthzSourcePolicy(self.env)
        resource = None
        if reponame is not None:
            resource = Resource('source', path,
                                parent=Resource('repository', reponame))
        for perm in ('BROWSER_VIEW', 'FILE_VIEW', 'LOG_VIEW'):
            check = policy.check_permission(perm, user, resource, None)
            self.assertEqual(result, check)

    def assertRevPerm(self, result, user, reponame=None, rev=None):
        """Assert that `user` is granted access `result` to `rev` within
        the repository `reponame`.
        """
        policy = AuthzSourcePolicy(self.env)
        resource = None
        if reponame is not None:
            resource = Resource('changeset', rev,
                                parent=Resource('repository', reponame))
        check = policy.check_permission('CHANGESET_VIEW', user, resource,
                                             None)
        self.assertEqual(result, check)

    def test_coarse_permissions(self):
        policy = AuthzSourcePolicy(self.env)
        # Granted to all due to wildcard
        self.assertPathPerm(True, 'unknown')
        self.assertPathPerm(True, 'joe')
        self.assertRevPerm(True, 'unknown')
        self.assertRevPerm(True, 'joe')
        # Granted if at least one fine permission is granted
        policy._mtime = 0
        create_file(self.authz_file, textwrap.dedent("""\
            [/somepath]
            joe = r
            denied =
            [module:/otherpath]
            Jane = r
            $anonymous = r
            [inactive:/not-in-this-instance]
            unknown = r
            """))
        self.assertPathPerm(None, 'unknown')
        self.assertRevPerm(None, 'unknown')
        self.assertPathPerm(None, 'denied')
        self.assertRevPerm(None, 'denied')
        self.assertPathPerm(True, 'joe')
        self.assertRevPerm(True, 'joe')
        self.assertPathPerm(True, 'Jane')
        self.assertRevPerm(True, 'Jane')
        self.assertPathPerm(True, 'anonymous')
        self.assertRevPerm(True, 'anonymous')

    def test_default_permission(self):
        # By default, permissions are undecided
        self.assertPathPerm(None, 'joe', '', '/not_defined')
        self.assertPathPerm(None, 'Jane', 'repo', '/not/defined/either')

    def test_read_write(self):
        # Allow 'r' and 'rw' entries, deny 'w' and empty entries
        self.assertPathPerm(True, 'user', '', '/readonly')
        self.assertPathPerm(True, 'user', '', '/readwrite')
        self.assertPathPerm(False, 'user', '', '/writeonly')
        self.assertPathPerm(False, 'user', '', '/empty')

    def test_trailing_slashes(self):
        # Combinations of trailing slashes in the file and in the path
        self.assertPathPerm(True, 'user', '', '/trailing_a')
        self.assertPathPerm(True, 'user', '', '/trailing_a/')
        self.assertPathPerm(True, 'user', '', '/trailing_b')
        self.assertPathPerm(True, 'user', '', '/trailing_b/')

    def test_sub_path(self):
        # Permissions are inherited from containing directories
        self.assertPathPerm(True, 'user', '', '/sub/path')
        self.assertPathPerm(True, 'user', '', '/sub/path/test')
        self.assertPathPerm(True, 'user', '', '/sub/path/other/sub')

    def test_module_usage(self):
        # If a module name is specified, the rules are specific to the module
        self.assertPathPerm(True, 'user', 'module', '/module_a')
        self.assertPathPerm(None, 'user', 'module', '/module_b')
        # If a module is specified, but the configuration contains a non-module
        # path, the non-module path can still apply
        self.assertPathPerm(True, 'user', 'module', '/module_c')
        # The module-specific rule takes precedence
        self.assertPathPerm(True, 'user', '', '/module_d')
        self.assertPathPerm(False, 'user', 'module', '/module_d')

    def test_wildcard(self):
        # The * wildcard matches all users, including anonymous
        self.assertPathPerm(True, 'anonymous', '', '/wildcard')
        self.assertPathPerm(True, 'joe', '', '/wildcard')
        self.assertPathPerm(True, 'Jane', '', '/wildcard')

    def test_special_tokens(self):
        # The $anonymous token matches only anonymous users
        self.assertPathPerm(True, 'anonymous', '', '/special/anonymous')
        self.assertPathPerm(None, 'user', '', '/special/anonymous')
        # The $authenticated token matches all authenticated users
        self.assertPathPerm(None, 'anonymous', '', '/special/authenticated')
        self.assertPathPerm(True, 'joe', '', '/special/authenticated')
        self.assertPathPerm(True, 'Jane', '', '/special/authenticated')

    def test_groups(self):
        # Groups are specified in a separate section and used with an @ prefix
        self.assertPathPerm(True, 'user', '', '/groups_a')
        # Groups can also be members of other groups
        self.assertPathPerm(True, 'user', '', '/groups_b')
        # Groups should not be defined cyclically, but they are still handled
        # correctly to avoid infinite loops
        self.assertPathPerm(True, 'user', '', '/cyclic')

    def test_precedence(self):
        # Module-specific sections take precedence over non-module sections
        self.assertPathPerm(False, 'user', 'module', '/precedence_a')
        # The most specific section applies
        self.assertPathPerm(True, 'user', '', '/precedence_b/sub/test')
        # ... intentional deviation from SVN's rules as we need to
        # make '/precedence_b/sub' browseable so that the user can see
        # '/precedence_b/sub/test':
        self.assertPathPerm(True, 'user', '', '/precedence_b/sub')
        self.assertPathPerm(True, 'user', '', '/precedence_b')
        # Ordering isn't significant; any entry could grant permission
        self.assertPathPerm(True, 'user', '', '/precedence_c')
        self.assertPathPerm(True, 'user', '', '/precedence_d')

    def test_aliases(self):
        # Aliases are specified in a separate section and used with an & prefix
        self.assertPathPerm(True, 'Mr Hyde', '', '/aliases_a')
        # Aliases can also be used in groups
        self.assertPathPerm(True, 'Mr Hyde', '', '/aliases_b')

    def test_scoped_repository(self):
        # Take repository scope into account
        self.assertPathPerm(True, 'joe', 'scoped', '/dir1')
        self.assertPathPerm(None, 'joe', 'scoped', '/dir2')
        self.assertPathPerm(True, 'joe', 'scoped', '/')
        self.assertPathPerm(None, 'Jane', 'scoped', '/dir1')
        self.assertPathPerm(True, 'Jane', 'scoped', '/dir2')
        self.assertPathPerm(True, 'Jane', 'scoped', '/')

    def test_multiple_entries(self):
        self.assertPathPerm(True,  'anonymous', '',       '/multiple/foo')
        self.assertPathPerm(True,  'joe',       '',       '/multiple/foo')
        self.assertPathPerm(True,  'anonymous', '',       '/multiple/bar')
        self.assertPathPerm(False, 'joe',       '',       '/multiple/bar')
        self.assertPathPerm(True,  'john',      '',       '/multiple/bar')
        self.assertPathPerm(True,  'anonymous', '',       '/multiple/baz')
        self.assertPathPerm(True,  'Jane',      '',       '/multiple/baz')
        self.assertPathPerm(False, 'joe',       '',       '/multiple/baz')
        self.assertPathPerm(True,  'anonymous', 'module', '/multiple/foo')
        self.assertPathPerm(True,  'joe',       'module', '/multiple/foo')
        self.assertPathPerm(True,  'anonymous', 'module', '/multiple/bar')
        self.assertPathPerm(True,  'joe',       'module', '/multiple/bar')
        self.assertPathPerm(False, 'john',      'module', '/multiple/bar')
        self.assertPathPerm(True,  'anonymous', 'module', '/multiple/baz')
        self.assertPathPerm(True,  'Jane',      'module', '/multiple/baz')
        self.assertPathPerm(False, 'joe',       'module', '/multiple/baz')

    def test_multiple_entries_with_module_and_parent_directory(self):
        self.assertPathPerm(True,  'anonymous', '',       '/multiple/1')
        self.assertPathPerm(True,  'user',      '',       '/multiple/1')
        self.assertPathPerm(True,  'someone',   '',       '/multiple/1')
        self.assertPathPerm(True,  'anonymous', 'module', '/multiple/1')
        self.assertPathPerm(True,  'user',      'module', '/multiple/1')
        self.assertPathPerm(True,  'someone',   'module', '/multiple/1')
        self.assertPathPerm(True,  'anonymous', 'module', '/multiple/1/user')
        self.assertPathPerm(False, 'user',      'module', '/multiple/1/user')
        self.assertPathPerm(True,  'someone',   'module', '/multiple/1/user')
        self.assertPathPerm(True,  'anonymous', 'module', '/multiple/1/group')
        self.assertPathPerm(False, 'user',      'module', '/multiple/1/group')
        self.assertPathPerm(True,  'someone',   'module', '/multiple/1/group')
        self.assertPathPerm(True,  'anonymous', 'module', '/multiple/1/auth')
        self.assertPathPerm(False, 'user',      'module', '/multiple/1/auth')
        self.assertPathPerm(False, 'someone',   'module', '/multiple/1/auth')
        self.assertPathPerm(False, 'anonymous', 'module', '/multiple/1/star')
        self.assertPathPerm(False, 'user',      'module', '/multiple/1/star')
        self.assertPathPerm(False, 'someone',   'module', '/multiple/1/star')

        self.assertPathPerm(False, 'anonymous', '',       '/multiple/2')
        self.assertPathPerm(False, 'user',      '',       '/multiple/2')
        self.assertPathPerm(False, 'someone',   '',       '/multiple/2')
        self.assertPathPerm(True,  'anonymous', 'module', '/multiple/2')
        self.assertPathPerm(True,  'user',      'module', '/multiple/2')
        self.assertPathPerm(True,  'someone',   'module', '/multiple/2')
        self.assertPathPerm(False, 'anonymous', 'module', '/multiple/2/user')
        self.assertPathPerm(True,  'user',      'module', '/multiple/2/user')
        self.assertPathPerm(False, 'someone',   'module', '/multiple/2/user')
        self.assertPathPerm(False, 'anonymous', 'module', '/multiple/2/group')
        self.assertPathPerm(True,  'user',      'module', '/multiple/2/group')
        self.assertPathPerm(False, 'someone',   'module', '/multiple/2/group')
        self.assertPathPerm(False, 'anonymous', 'module', '/multiple/2/auth')
        self.assertPathPerm(True,  'user',      'module', '/multiple/2/auth')
        self.assertPathPerm(True,  'someone',   'module', '/multiple/2/auth')
        self.assertPathPerm(True,  'anonymous', 'module', '/multiple/2/star')
        self.assertPathPerm(True,  'user',      'module', '/multiple/2/star')
        self.assertPathPerm(True,  'someone',   'module', '/multiple/2/star')

    def test_changesets(self):
        # Changesets are allowed if at least one changed path is allowed, or
        # if the changeset is empty
        self.assertRevPerm(True, 'joe', 'scoped', 123)
        self.assertRevPerm(None, 'joe', 'scoped', 456)
        self.assertRevPerm(True, 'joe', 'scoped', 789)
        self.assertRevPerm(None, 'Jane', 'scoped', 123)
        self.assertRevPerm(True, 'Jane', 'scoped', 456)
        self.assertRevPerm(True, 'Jane', 'scoped', 789)
        self.assertRevPerm(None, 'user', 'scoped', 123)
        self.assertRevPerm(None, 'user', 'scoped', 456)
        self.assertRevPerm(True, 'user', 'scoped', 789)
Exemplo n.º 52
0
 def setUp(self):
     self.env = EnvironmentStub(default_data=True)
     self.env.path = os.path.join(tempfile.gettempdir(), 'trac-tempenv')
     os.mkdir(self.env.path)
Exemplo n.º 53
0
class NormalTestCase(unittest.TestCase, GitCommandMixin):

    def setUp(self):
        self.env = EnvironmentStub()
        self.repos_path = mkdtemp()
        # create git repository and master branch
        self._git('init')
        self._git('config', 'core.quotepath', 'true')  # ticket:11198
        self._git('config', 'user.name', "Joe")
        self._git('config', 'user.email', "*****@*****.**")
        create_file(os.path.join(self.repos_path, '.gitignore'))
        self._git('add', '.gitignore')
        self._git_commit('-a', '-m', 'test',
                         date=datetime(2013, 1, 1, 9, 4, 56))

    def tearDown(self):
        RepositoryManager(self.env).reload_repositories()
        StorageFactory._clean()
        self.env.reset_db()
        if os.path.isdir(self.repos_path):
            rmtree(self.repos_path)

    def _factory(self, weak, path=None):
        if path is None:
            path = os.path.join(self.repos_path, '.git')
        return StorageFactory(path, self.env.log, weak)

    def _storage(self, path=None):
        if path is None:
            path = os.path.join(self.repos_path, '.git')
        return Storage(path, self.env.log, self.git_bin, 'utf-8')

    def test_control_files_detection(self):
        # Exception not raised when path points to ctrl file dir
        self.assertIsInstance(self._storage().repo, GitCore)
        # Exception not raised when path points to parent of ctrl files dir
        self.assertIsInstance(self._storage(self.repos_path).repo, GitCore)
        # Exception raised when path points to dir with no ctrl files
        path = tempfile.mkdtemp(dir=self.repos_path)
        self.assertRaises(GitError, self._storage, path)
        # Exception raised if a ctrl file is missing
        os.remove(os.path.join(self.repos_path, '.git', 'HEAD'))
        self.assertRaises(GitError, self._storage, self.repos_path)

    def test_get_branches_with_cr_in_commitlog(self):
        # regression test for #11598
        message = 'message with carriage return'.replace(' ', '\r')

        create_file(os.path.join(self.repos_path, 'ticket11598.txt'))
        self._git('add', 'ticket11598.txt')
        self._git_commit('-m', message,
                         date=datetime(2013, 5, 9, 11, 5, 21))

        storage = self._storage()
        branches = sorted(storage.get_branches())
        self.assertEqual('master', branches[0][0])
        self.assertEqual(1, len(branches))

    if os.name == 'nt':
        del test_get_branches_with_cr_in_commitlog

    def test_rev_is_anchestor_of(self):
        # regression test for #11215
        path = os.path.join(self.repos_path, '.git')
        DbRepositoryProvider(self.env).add_repository('gitrepos', path, 'git')
        repos = RepositoryManager(self.env).get_repository('gitrepos')
        parent_rev = repos.youngest_rev

        create_file(os.path.join(self.repos_path, 'ticket11215.txt'))
        self._git('add', 'ticket11215.txt')
        self._git_commit('-m', 'ticket11215',
                         date=datetime(2013, 6, 27, 18, 26, 2))
        repos.sync()
        rev = repos.youngest_rev

        self.assertNotEqual(rev, parent_rev)
        self.assertFalse(repos.rev_older_than(None, None))
        self.assertFalse(repos.rev_older_than(None, rev[:7]))
        self.assertFalse(repos.rev_older_than(rev[:7], None))
        self.assertTrue(repos.rev_older_than(parent_rev, rev))
        self.assertTrue(repos.rev_older_than(parent_rev[:7], rev[:7]))
        self.assertFalse(repos.rev_older_than(rev, parent_rev))
        self.assertFalse(repos.rev_older_than(rev[:7], parent_rev[:7]))

    def test_node_get_history_with_empty_commit(self):
        # regression test for #11328
        path = os.path.join(self.repos_path, '.git')
        DbRepositoryProvider(self.env).add_repository('gitrepos', path, 'git')
        repos = RepositoryManager(self.env).get_repository('gitrepos')
        parent_rev = repos.youngest_rev

        self._git_commit('-m', 'ticket:11328', '--allow-empty',
                         date=datetime(2013, 10, 15, 9, 46, 27))
        repos.sync()
        rev = repos.youngest_rev

        node = repos.get_node('', rev)
        self.assertEqual(rev, repos.git.last_change(rev, ''))
        history = list(node.get_history())
        self.assertEqual(u'', history[0][0])
        self.assertEqual(rev, history[0][1])
        self.assertEqual(Changeset.EDIT, history[0][2])
        self.assertEqual(u'', history[1][0])
        self.assertEqual(parent_rev, history[1][1])
        self.assertEqual(Changeset.ADD, history[1][2])
        self.assertEqual(2, len(history))

    def test_sync_after_removing_branch(self):
        self._git('checkout', '-b', 'b1', 'master')
        self._git('checkout', 'master')
        create_file(os.path.join(self.repos_path, 'newfile.txt'))
        self._git('add', 'newfile.txt')
        self._git_commit('-m', 'added newfile.txt to master',
                         date=datetime(2013, 12, 23, 6, 52, 23))

        storage = self._storage()
        storage.sync()
        self.assertEqual(['b1', 'master'],
                         sorted(b[0] for b in storage.get_branches()))
        self._git('branch', '-D', 'b1')
        self.assertTrue(storage.sync())
        self.assertEqual(['master'],
                         sorted(b[0] for b in storage.get_branches()))
        self.assertFalse(storage.sync())

    def test_turn_off_persistent_cache(self):
        # persistent_cache is enabled
        parent_rev = self._factory(False).getInstance().youngest_rev()

        create_file(os.path.join(self.repos_path, 'newfile.txt'))
        self._git('add', 'newfile.txt')
        self._git_commit('-m', 'test_turn_off_persistent_cache',
                         date=datetime(2014, 1, 29, 13, 13, 25))

        # persistent_cache is disabled
        rev = self._factory(True).getInstance().youngest_rev()
        self.assertNotEqual(rev, parent_rev)
Exemplo n.º 54
0
 def setUp(self):
     self.env = EnvironmentStub(enable=self.navigation_contributors +
                                ['trac.perm.*'])
     self.env.config.set('trac', 'permission_policies',
                         'DefaultPermissionPolicy')
Exemplo n.º 55
0
 def setUp(self):
     self.env = EnvironmentStub(path=mkdtemp())
     self.env.config.filename = os.path.join(self.env.path, 'trac.ini')
Exemplo n.º 56
0
 def setUp(self):
     self.env = EnvironmentStub()
     self.log = self.env.log
     self.env.db_transaction.executemany(
         "INSERT INTO repository (id, name, value) VALUES (%s, %s, %s)",
         [(1, 'name', 'test-repos'), (1, 'youngest_rev', '')])
Exemplo n.º 57
0
 def setUp(self):
     self.env = EnvironmentStub(default_data=True)
Exemplo n.º 58
0
class CacheTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        self.log = self.env.log
        self.env.db_transaction.executemany(
            "INSERT INTO repository (id, name, value) VALUES (%s, %s, %s)",
            [(1, 'name', 'test-repos'), (1, 'youngest_rev', '')])

    def tearDown(self):
        self.env.reset_db()

    # Helpers

    def get_repos(self, get_changeset=None, youngest_rev=1):
        if get_changeset is None:

            def no_changeset(rev):
                raise NoSuchChangeset(rev)

            get_changeset = no_changeset
        return Mock(
            Repository,
            'test-repos', {
                'name': 'test-repos',
                'id': 1
            },
            self.log,
            get_changeset=get_changeset,
            get_oldest_rev=lambda: 0,
            get_youngest_rev=lambda: youngest_rev,
            normalize_rev=lambda x: get_changeset(x).rev,
            next_rev=(lambda x: int(x) < youngest_rev and x + 1 or None))

    def preset_cache(self, *args):
        """Each arg is a (rev tuple, changes list of tuples) pair."""
        with self.env.db_transaction as db:
            for rev, changes in args:
                db(
                    """INSERT INTO revision (repos, rev, time, author, message)
                      VALUES (1,%s,%s,%s,%s)
                      """, rev)
                if changes:
                    db.executemany(
                        """
                          INSERT INTO node_change (repos, rev, path, node_type,
                                                   change_type, base_path,
                                                   base_rev)
                          VALUES (1, %s, %s, %s, %s, %s, %s)
                          """, [(rev[0], ) + change for change in changes])
            db(
                """UPDATE repository SET value=%s
                  WHERE id=1 AND name='youngest_rev'
                  """, (args[-1][0][0], ))

    # Tests

    def test_repr(self):
        repos = self.get_repos()
        cache = CachedRepository(self.env, repos, self.log)
        self.assertEqual("<CachedRepository 1 'test-repos' '/'>", repr(cache))

    def test_initial_sync_with_empty_repos(self):
        repos = self.get_repos()
        cache = CachedRepository(self.env, repos, self.log)
        cache.sync()

        with self.env.db_query as db:
            self.assertEqual(
                [], db("SELECT rev, time, author, message FROM revision"))
            self.assertEqual(0, db("SELECT COUNT(*) FROM node_change")[0][0])

    def test_initial_sync(self):
        t1 = datetime(2001, 1, 1, 1, 1, 1, 0, utc)
        t2 = datetime(2002, 1, 1, 1, 1, 1, 0, utc)
        repos = self.get_repos(get_changeset=lambda x: changesets[int(x)],
                               youngest_rev=1)
        changes = [('trunk', Node.DIRECTORY, Changeset.ADD, None, None),
                   ('trunk/README', Node.FILE, Changeset.ADD, None, None)]
        changesets = [
            Mock(Changeset, repos, 0, '', '', t1, get_changes=lambda: []),
            Mock(Changeset,
                 repos,
                 1,
                 'Import',
                 'joe',
                 t2,
                 get_changes=lambda: iter(changes))
        ]
        cache = CachedRepository(self.env, repos, self.log)
        cache.sync()

        with self.env.db_query as db:
            rows = db("SELECT rev, time, author, message FROM revision")
            self.assertEqual(len(rows), 2)
            self.assertEqual(('0', to_utimestamp(t1), '', ''), rows[0])
            self.assertEqual(('1', to_utimestamp(t2), 'joe', 'Import'),
                             rows[1])
            rows = db("""
                SELECT rev, path, node_type, change_type, base_path, base_rev
                FROM node_change""")
            self.assertEqual(len(rows), 2)
            self.assertEqual(('1', 'trunk', 'D', 'A', None, None), rows[0])
            self.assertEqual(('1', 'trunk/README', 'F', 'A', None, None),
                             rows[1])

    def test_update_sync(self):
        t1 = datetime(2001, 1, 1, 1, 1, 1, 0, utc)
        t2 = datetime(2002, 1, 1, 1, 1, 1, 0, utc)
        t3 = datetime(2003, 1, 1, 1, 1, 1, 0, utc)
        self.preset_cache(
            (('0', to_utimestamp(t1), '', ''), []),
            (('1', to_utimestamp(t2), 'joe', 'Import'), [
                ('trunk', 'D', 'A', None, None),
                ('trunk/README', 'F', 'A', None, None)
            ]),
        )
        repos = self.get_repos(get_changeset=lambda x: changesets[int(x)],
                               youngest_rev=2)
        changes = [('trunk/README', Node.FILE, Changeset.EDIT, 'trunk/README',
                    1)]
        changesets = [
            None,
            Mock(Changeset, repos, 1, '', '', t2, get_changes=lambda: []),
            Mock(Changeset,
                 repos,
                 2,
                 'Update',
                 'joe',
                 t3,
                 get_changes=lambda: iter(changes))
        ]
        cache = CachedRepository(self.env, repos, self.log)
        cache.sync()

        with self.env.db_query as db:
            self.assertEqual(
                [(to_utimestamp(t3), 'joe', 'Update')],
                db("SELECT time, author, message FROM revision WHERE rev='2'"))
            self.assertEqual(
                [('trunk/README', 'F', 'E', 'trunk/README', '1')],
                db("""SELECT path, node_type, change_type, base_path,
                                 base_rev
                          FROM node_change WHERE rev='2'"""))

    def test_clean_sync(self):
        t1 = datetime(2001, 1, 1, 1, 1, 1, 0, utc)
        t2 = datetime(2002, 1, 1, 1, 1, 1, 0, utc)
        t3 = datetime(2003, 1, 1, 1, 1, 1, 0, utc)
        self.preset_cache(
            (('0', to_utimestamp(t1), '', ''), []),
            (('1', to_utimestamp(t2), 'joe', 'Import'), [
                ('trunk', 'D', 'A', None, None),
                ('trunk/README', 'F', 'A', None, None)
            ]),
        )
        repos = self.get_repos(get_changeset=lambda x: changesets[int(x)],
                               youngest_rev=2)
        changes1 = [('trunk', Node.DIRECTORY, Changeset.ADD, None, None),
                    ('trunk/README', Node.FILE, Changeset.ADD, None, None)]
        changes2 = [('trunk/README', Node.FILE, Changeset.EDIT, 'trunk/README',
                     1)]
        changesets = [
            Mock(Changeset,
                 repos,
                 0,
                 '**empty**',
                 'joe',
                 t1,
                 get_changes=lambda: []),
            Mock(Changeset,
                 repos,
                 1,
                 'Initial Import',
                 'joe',
                 t2,
                 get_changes=lambda: iter(changes1)),
            Mock(Changeset,
                 repos,
                 2,
                 'Update',
                 'joe',
                 t3,
                 get_changes=lambda: iter(changes2))
        ]
        cache = CachedRepository(self.env, repos, self.log)
        cache.sync(clean=True)

        rows = self.env.db_query("""
            SELECT time, author, message FROM revision ORDER BY rev
            """)
        self.assertEqual(3, len(rows))
        self.assertEqual((to_utimestamp(t1), 'joe', '**empty**'), rows[0])
        self.assertEqual((to_utimestamp(t2), 'joe', 'Initial Import'), rows[1])
        self.assertEqual((to_utimestamp(t3), 'joe', 'Update'), rows[2])

        rows = self.env.db_query("""
            SELECT rev, path, node_type, change_type, base_path, base_rev
            FROM node_change ORDER BY rev, path""")
        self.assertEqual(3, len(rows))
        self.assertEqual(('1', 'trunk', 'D', 'A', None, None), rows[0])
        self.assertEqual(('1', 'trunk/README', 'F', 'A', None, None), rows[1])
        self.assertEqual(('2', 'trunk/README', 'F', 'E', 'trunk/README', '1'),
                         rows[2])

    def test_sync_changeset(self):
        t1 = datetime(2001, 1, 1, 1, 1, 1, 0, utc)
        t2 = datetime(2002, 1, 1, 1, 1, 1, 0, utc)
        self.preset_cache(
            (('0', to_utimestamp(t1), '', ''), []),
            (('1', to_utimestamp(t2), 'joe', 'Import'), [
                ('trunk', 'D', 'A', None, None),
                ('trunk/README', 'F', 'A', None, None)
            ]),
        )
        repos = self.get_repos(get_changeset=lambda x: changesets[int(x)],
                               youngest_rev=1)
        changes1 = [('trunk', Node.DIRECTORY, Changeset.ADD, None, None),
                    ('trunk/README', Node.FILE, Changeset.ADD, None, None)]
        changesets = [
            Mock(Changeset,
                 repos,
                 0,
                 '**empty**',
                 'joe',
                 t1,
                 get_changes=lambda: []),
            Mock(Changeset,
                 repos,
                 1,
                 'Initial Import',
                 'joe',
                 t2,
                 get_changes=lambda: iter(changes1)),
        ]
        cache = CachedRepository(self.env, repos, self.log)
        cache.sync_changeset(0)

        rows = self.env.db_query(
            "SELECT time, author, message FROM revision ORDER BY rev")
        self.assertEqual(2, len(rows))
        self.assertEqual((to_utimestamp(t1), 'joe', '**empty**'), rows[0])
        self.assertEqual((to_utimestamp(t2), 'joe', 'Import'), rows[1])

    def test_sync_changeset_if_not_exists(self):
        t = [
            datetime(2001, 1, 1, 1, 1, 1, 0, utc),  # r0
            datetime(2002, 1, 1, 1, 1, 1, 0, utc),  # r1
            datetime(2003, 1, 1, 1, 1, 1, 0, utc),  # r2
            datetime(2004, 1, 1, 1, 1, 1, 0, utc),  # r3
        ]
        self.preset_cache(
            (('0', to_utimestamp(t[0]), 'joe', '**empty**'), []),
            (('1', to_utimestamp(t[1]), 'joe', 'Import'), [
                ('trunk', 'D', 'A', None, None),
                ('trunk/README', 'F', 'A', None, None)
            ]),
            # not exists r2
            (('3', to_utimestamp(t[3]), 'joe', 'Add COPYING'), [
                ('trunk/COPYING', 'F', 'A', None, None)
            ]),
        )
        repos = self.get_repos(get_changeset=lambda x: changesets[int(x)],
                               youngest_rev=3)
        changes = [
            None,  # r0
            [
                ('trunk', Node.DIRECTORY, Changeset.ADD, None, None),  # r1
                ('trunk/README', Node.FILE, Changeset.ADD, None, None)
            ],
            [
                ('branches', Node.DIRECTORY, Changeset.ADD, None, None),  # r2
                ('tags', Node.DIRECTORY, Changeset.ADD, None, None)
            ],
            [('trunk/COPYING', Node.FILE, Changeset.ADD, None, None)],  # r3
        ]
        changesets = [
            Mock(Changeset,
                 repos,
                 0,
                 '**empty**',
                 'joe',
                 t[0],
                 get_changes=lambda: []),
            Mock(Changeset,
                 repos,
                 1,
                 'Initial Import',
                 'joe',
                 t[1],
                 get_changes=lambda: iter(changes[1])),
            Mock(Changeset,
                 repos,
                 2,
                 'Created directories',
                 'john',
                 t[2],
                 get_changes=lambda: iter(changes[2])),
            Mock(Changeset,
                 repos,
                 3,
                 'Add COPYING',
                 'joe',
                 t[3],
                 get_changes=lambda: iter(changes[3])),
        ]
        cache = CachedRepository(self.env, repos, self.log)
        self.assertRaises(NoSuchChangeset, cache.get_changeset, 2)
        cache.sync()
        self.assertRaises(NoSuchChangeset, cache.get_changeset, 2)

        self.assertIsNone(cache.sync_changeset(2))
        cset = cache.get_changeset(2)
        self.assertEqual('john', cset.author)
        self.assertEqual('Created directories', cset.message)
        self.assertEqual(t[2], cset.date)
        cset_changes = cset.get_changes()
        self.assertEqual(
            ('branches', Node.DIRECTORY, Changeset.ADD, None, None),
            next(cset_changes))
        self.assertEqual(('tags', Node.DIRECTORY, Changeset.ADD, None, None),
                         next(cset_changes))
        self.assertRaises(StopIteration, next, cset_changes)

        rows = self.env.db_query(
            "SELECT time,author,message FROM revision ORDER BY rev")
        self.assertEqual(4, len(rows))
        self.assertEqual((to_utimestamp(t[0]), 'joe', '**empty**'), rows[0])
        self.assertEqual((to_utimestamp(t[1]), 'joe', 'Import'), rows[1])
        self.assertEqual((to_utimestamp(t[2]), 'john', 'Created directories'),
                         rows[2])
        self.assertEqual((to_utimestamp(t[3]), 'joe', 'Add COPYING'), rows[3])

    def test_sync_changeset_with_string_rev(self):  # ticket:11660
        class MockCachedRepository(CachedRepository):
            def db_rev(self, rev):
                return '%010d' % rev

        t1 = datetime(2001, 1, 1, 1, 1, 1, 0, utc)
        t2 = datetime(2002, 1, 1, 1, 1, 1, 0, utc)
        repos = self.get_repos(get_changeset=lambda x: changesets[int(x)],
                               youngest_rev=1)
        changesets = [
            Mock(Changeset,
                 repos,
                 0,
                 'empty',
                 'joe',
                 t1,
                 get_changes=lambda: []),
            Mock(Changeset,
                 repos,
                 1,
                 'first',
                 'joe',
                 t2,
                 get_changes=lambda: []),
        ]
        cache = MockCachedRepository(self.env, repos, self.log)

        cache.sync_changeset('0')  # not cached yet
        cache.sync_changeset(u'1')  # not cached yet
        rows = self.env.db_query(
            "SELECT rev,author FROM revision ORDER BY rev")
        self.assertEqual(2, len(rows))
        self.assertEqual(('0000000000', 'joe'), rows[0])
        self.assertEqual(('0000000001', 'joe'), rows[1])

        cache.sync_changeset(u'0')  # cached
        cache.sync_changeset('1')  # cached
        rows = self.env.db_query(
            "SELECT rev,author FROM revision ORDER BY rev")
        self.assertEqual(2, len(rows))
        self.assertEqual(('0000000000', 'joe'), rows[0])
        self.assertEqual(('0000000001', 'joe'), rows[1])

    def test_get_changes(self):
        t1 = datetime(2001, 1, 1, 1, 1, 1, 0, utc)
        t2 = datetime(2002, 1, 1, 1, 1, 1, 0, utc)
        self.preset_cache(
            (('0', to_utimestamp(t1), '', ''), []),
            (('1', to_utimestamp(t2), 'joe', 'Import'), [
                ('trunk', 'D', 'A', None, None),
                ('trunk/RDME', 'F', 'A', None, None)
            ]),
        )
        repos = self.get_repos()
        cache = CachedRepository(self.env, repos, self.log)
        self.assertEqual('1', cache.youngest_rev)
        changeset = cache.get_changeset(1)
        self.assertEqual('joe', changeset.author)
        self.assertEqual('Import', changeset.message)
        self.assertEqual(t2, changeset.date)
        changes = changeset.get_changes()
        self.assertEqual(('trunk', Node.DIRECTORY, Changeset.ADD, None, None),
                         next(changes))
        self.assertEqual(('trunk/RDME', Node.FILE, Changeset.ADD, None, None),
                         next(changes))
        self.assertRaises(StopIteration, next, changes)
Exemplo n.º 59
0
class FormatAuthorTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub(enable=[
            'trac.web.chrome.*', 'trac.perm.*', 'tracopt.perm.authz_policy'
        ])
        self.env.config.set('trac', 'permission_policies',
                            'AuthzPolicy, DefaultPermissionPolicy')
        fd, self.authz_file = tempfile.mkstemp()
        with os.fdopen(fd, 'w') as f:
            f.write(
                textwrap.dedent("""\
                [wiki:WikiStart]
                user2 = EMAIL_VIEW
                [wiki:TracGuide]
                user2 =
                """))
        PermissionSystem(self.env).grant_permission('user1', 'EMAIL_VIEW')
        self.env.config.set('authz_policy', 'authz_file', self.authz_file)

    def tearDown(self):
        os.remove(self.authz_file)

    def test_subject_is_anonymous(self):
        format_author = Chrome(self.env).format_author
        self.assertEqual('anonymous', format_author(None, 'anonymous'))

    def test_subject_is_none(self):
        format_author = Chrome(self.env).format_author
        self.assertEqual('(none)', format_author(None, None))

    def test_actor_has_email_view(self):
        req = MockRequest(self.env, authname='user1')
        author = Chrome(self.env).format_author(req, '*****@*****.**')
        self.assertEqual('*****@*****.**', author)

    def test_actor_no_email_view(self):
        req = MockRequest(self.env, authname='user2')
        author = Chrome(self.env).format_author(req, '*****@*****.**')
        self.assertEqual(u'user@\u2026', author)

    def test_actor_no_email_view_show_email_addresses(self):
        self.env.config.set('trac', 'show_email_addresses', True)
        req = MockRequest(self.env, authname='user2')
        author = Chrome(self.env).format_author(req, '*****@*****.**')
        self.assertEqual('*****@*****.**', author)

    def test_actor_no_email_view_no_req(self):
        author = Chrome(self.env).format_author(None, '*****@*****.**')
        self.assertEqual(u'user@\u2026', author)

    def test_actor_has_email_view_for_resource(self):
        format_author = Chrome(self.env).format_author
        req = MockRequest(self.env, authname='user2')
        resource = Resource('wiki', 'WikiStart')
        author = format_author(req, '*****@*****.**', resource)
        self.assertEqual('*****@*****.**', author)

    def test_actor_has_email_view_for_resource_negative(self):
        format_author = Chrome(self.env).format_author
        req = MockRequest(self.env, authname='user2')
        resource = Resource('wiki', 'TracGuide')
        author = format_author(req, '*****@*****.**', resource)
        self.assertEqual(u'user@\u2026', author)

    def test_show_full_names_true(self):
        format_author = Chrome(self.env).format_author
        self.env.config.set('trac', 'show_full_names', True)
        self.env.insert_users([('user1', 'User One', '*****@*****.**'),
                               ('user2', None, None)])

        self.assertEqual('User One', format_author(None, 'user1'))
        self.assertEqual('user2', format_author(None, 'user2'))

    def test_show_full_names_false(self):
        format_author = Chrome(self.env).format_author
        self.env.config.set('trac', 'show_full_names', False)

        self.assertEqual('user1', format_author(None, 'user1'))
        self.assertEqual('user2', format_author(None, 'user2'))

    def test_show_email_true(self):
        format_author = Chrome(self.env).format_author
        req = MockRequest(self.env, authname='user2')

        author = format_author(None, '*****@*****.**', show_email=True)
        self.assertEqual('*****@*****.**', author)
        author = format_author(req, '*****@*****.**', show_email=True)
        self.assertEqual('*****@*****.**', author)

    def test_show_email_false(self):
        format_author = Chrome(self.env).format_author
        req = MockRequest(self.env, authname='user1')

        author = format_author(None, '*****@*****.**', show_email=False)
        self.assertEqual(u'user@\u2026', author)
        author = format_author(req, '*****@*****.**', show_email=False)
        self.assertEqual(u'user@\u2026', author)

    def test_show_full_names_true_actor_has_email_view(self):
        format_author = Chrome(self.env).format_author
        self.env.config.set('trac', 'show_full_names', True)
        self.env.insert_users([('user1', 'User One', '*****@*****.**'),
                               ('user2', None, None)])

        self.assertEqual('User One', format_author(None, 'user1'))
        self.assertEqual('user2', format_author(None, 'user2'))

    def test_show_full_names_false_actor_has_email_view(self):
        req = MockRequest(self.env, authname='user1')
        format_author = Chrome(self.env).format_author
        self.env.config.set('trac', 'show_full_names', False)

        self.assertEqual('user1', format_author(req, 'user1'))
        self.assertEqual('user2', format_author(req, 'user2'))

    def test_show_email_addresses_true(self):
        req = MockRequest(self.env)
        format_author = Chrome(self.env).format_author
        self.env.config.set('trac', 'show_email_addresses', True)

        self.assertEqual('*****@*****.**',
                         format_author(None, '*****@*****.**'))
        self.assertEqual('*****@*****.**',
                         format_author(req, '*****@*****.**'))

    def test_show_email_addresses_false(self):
        req = MockRequest(self.env)
        format_author = Chrome(self.env).format_author
        self.env.config.set('trac', 'show_email_addresses', False)

        self.assertEqual(u'user3@\u2026',
                         format_author(None, '*****@*****.**'))
        self.assertEqual('*****@*****.**',
                         format_author(req, '*****@*****.**'))

    def test_format_emails(self):
        format_emails = Chrome(self.env).format_emails
        to_format = '[email protected], user2; [email protected]'

        self.assertEqual(u'user1@\u2026, user2, user3@\u2026',
                         format_emails(None, to_format))

    def test_format_emails_actor_has_email_view(self):
        req = MockRequest(self.env, authname='user1')
        context = web_context(req)
        format_emails = Chrome(self.env).format_emails
        to_format = '[email protected], user2; [email protected]'

        self.assertEqual('[email protected], user2, [email protected]',
                         format_emails(context, to_format))

    def test_format_emails_actor_no_email_view(self):
        req = MockRequest(self.env, authname='user2')
        context = web_context(req)
        format_emails = Chrome(self.env).format_emails
        to_format = '[email protected], user2; [email protected]'

        self.assertEqual(u'user1@\u2026, user2, user3@\u2026',
                         format_emails(context, to_format))
Exemplo n.º 60
0
class ChromeTemplateRenderingTestCase(unittest.TestCase):

    filename = 'test_chrome.html'

    template = textwrap.dedent("""\
        <!DOCTYPE html>
        <html>
          <body>
            <h1>${greeting}</h1>
          </body>
        </html>
        """)

    def setUp(self):
        self.env = EnvironmentStub(path=mkdtemp())
        os.mkdir(self.env.templates_dir)
        filepath = os.path.join(self.env.templates_dir, self.filename)
        create_file(filepath, self.template)
        self.chrome = Chrome(self.env)

    def tearDown(self):
        self.env.reset_db_and_disk()

    def test_load_template(self):
        t1 = self.chrome.load_template(self.filename)
        self.assertTrue(isinstance(t1, jinja2.Template))
        t1_text = self.chrome.load_template(self.filename, text=True)
        self.assertTrue(isinstance(t1_text, jinja2.Template))
        # testing template cache
        t2 = self.chrome.load_template(self.filename)
        t2_text = self.chrome.load_template(self.filename, text=True)
        self.assertIs(t1, t2)
        self.assertIs(t1_text, t2_text)
        self.assertIsNot(t1, t1_text)

    def test_render_template_string(self):
        t = self.chrome.load_template(self.filename)
        self.assertIsNotNone(t)
        t_text = self.chrome.load_template(self.filename, text=True)
        self.assertIsNotNone(t_text)
        data = {'greeting': u"Hell&ö"}
        content = self.chrome.render_template_string(t, data)
        self.assertIsInstance(content, Markup)
        self.assertEqual(
            textwrap.dedent(u"""\
            <!DOCTYPE html>
            <html>
              <body>
                <h1>Hell&amp;ö</h1>
              </body>
            </html>"""), content)
        content_text = self.chrome.render_template_string(t_text,
                                                          data,
                                                          text=True)
        self.assertFalse(isinstance(content_text, Markup))
        self.assertIsInstance(content_text, unicode)
        self.assertEqual(
            textwrap.dedent(u"""\
            <!DOCTYPE html>
            <html>
              <body>
                <h1>Hell&ö</h1>
              </body>
            </html>"""), content_text)

    def test_render_template(self):
        data = {'greeting': u"Hell&ö"}
        content = self.chrome.render_template(MockRequest(self.env),
                                              self.filename, data,
                                              {'fragment': True})
        self.assertIsInstance(content, str)
        self.assertEqual(
            textwrap.dedent("""\
            <!DOCTYPE html>
            <html>
              <body>
                <h1>Hell&amp;ö</h1>
              </body>
            </html>"""), content)

    def test_render_template_late_data(self):
        def fn():
            add_stylesheet(req, 'common/css/blahblah.css')
            add_script(req, 'common/js/blahblah.js')
            add_script_data(req, blahblah=42)
            return 'blahblah'

        template = textwrap.dedent("""\
            # extends 'layout.html'
            <!DOCTYPE html>
            <html>
              <body>
                # block content
                <div>${fn()}</div>
                ${ super() }
                # endblock content
              </body>
            </html>
            """)
        filename = 'test_render_template_late_data.html'
        filepath = os.path.join(self.env.templates_dir, filename)
        create_file(filepath, template)
        req = MockRequest(self.env)
        data = {'fn': fn}
        content = self.chrome.render_template(req, filename, data,
                                              {'fragment': True})
        self.assertIsInstance(content, str)
        self.assertIn('<div>blahblah</div>', content)
        self.assertIn(
            ' jQuery.loadScript("/trac.cgi/chrome/'
            'common/js/blahblah.js", "");', content)
        self.assertIn(
            ' jQuery.loadStyleSheet("/trac.cgi/chrome/'
            'common/css/blahblah.css", "text/css");', content)
        self.assertIn(' var blahblah=42;', content)