Esempio n. 1
0
 def getReport(self, req, rid):
     """
     Get report detail and matching tickets
     """
     rid = int(rid)
     rm = ReportModule(self.env)
     r = Report(self.env, rid)
     title, description, sql = r.title, r.description, r.query
     cols, rows, do_, not_, care = rm.execute_paginated_report(
         req, rid, sql, {}, 0, 0)
     tickets = []
     if 'ticket' in cols:
         for i in rows:
             tickets.append(i[cols.index('ticket')])
     return {
         "report": {
             "id": r.id,
             "title": r.title,
             "description": r.description
         },
         "tickets": tickets
     }
Esempio n. 2
0
class ReportModuleTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub(default_data=True)
        self.report_module = ReportModule(self.env)

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

    def _insert_report(self, title, query, description):
        with self.env.db_transaction as db:
            cursor = db.cursor()
            cursor.execute(
                """
                INSERT INTO report (title,query,description)
                VALUES (%s,%s,%s)
                """, (title, query, description))
            return db.get_last_id(cursor, 'report')

    def test_create_report(self):
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'new',
                              'title': "New Report",
                              'query': "SELECT 1",
                              'description': "The description"
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        self.assertTrue(Report(self.env, 9).exists)
        self.assertIn("The report has been created.", req.chrome['notices'])
        self.assertEqual('http://example.org/trac.cgi/report/9',
                         req.headers_sent['Location'])

    def test_create_report_cancel(self):
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'new',
                              'cancel': True,
                              'title': "New Report",
                              'query': "SELECT 1",
                              'description': "The description"
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        self.assertRaises(ResourceNotFound, Report, self.env, 9)
        self.assertNotIn("The report has been created.", req.chrome['notices'])
        self.assertEqual('http://example.org/trac.cgi/report',
                         req.headers_sent['Location'])

    def test_delete_report(self):
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'delete',
                              'id': '1'
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        self.assertRaises(ResourceNotFound, Report, self.env, 1)
        self.assertIn("The report {1} has been deleted.",
                      req.chrome['notices'])
        self.assertEqual('http://example.org/trac.cgi/report',
                         req.headers_sent['Location'])

    def test_delete_report_cancel(self):
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'delete',
                              'cancel': True,
                              'id': '1'
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        self.assertTrue(Report(self.env, 1).exists)
        self.assertNotIn("The report {1} has been deleted.",
                         req.chrome['notices'])
        self.assertEqual('http://example.org/trac.cgi/report/1',
                         req.headers_sent['Location'])

    def test_update_report(self):
        report = Report(self.env)
        report.query = "SELECT 1"
        report.insert()
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'edit',
                              'id': '1',
                              'title': "New Report edited",
                              'query': "SELECT 2",
                              'description': "The description edited"
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        report = Report(self.env, 1)
        self.assertEqual("New Report edited", report.title)
        self.assertEqual("SELECT 2", report.query)
        self.assertEqual("The description edited", report.description)
        self.assertIn("Your changes have been saved.", req.chrome['notices'])

    def test_update_report_cancel(self):
        report = Report(self.env)
        report.query = "SELECT 1"
        report.insert()
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'edit',
                              'cancel': True,
                              'id': '1',
                              'title': "New Report edited",
                              'query': "SELECT 2",
                              'description': "The description edited"
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        report = Report(self.env, 1)
        self.assertEqual("Active Tickets", report.title)
        self.assertEqual(
            " * List all active tickets by priority.\n"
            " * Color each row based on priority.\n", report.description)
        self.assertIn("SELECT p.value AS __color__", report.query)
        self.assertNotIn("Your changes have been saved.",
                         req.chrome['notices'])

    def test_render_confirm_delete(self):
        req = MockRequest(self.env,
                          method='GET',
                          args={
                              'action': 'delete',
                              'id': '1'
                          })

        data = self.report_module.process_request(req)[1]

        self.assertEqual("Delete Report {1} Active Tickets", data['title'])
        self.assertEqual('delete', data['action'])
        self.assertEqual(1, data['report']['id'])
        self.assertEqual('Active Tickets', data['report']['title'])

    def test_render_editor(self):
        req = MockRequest(self.env,
                          method='GET',
                          args={
                              'action': 'edit',
                              'id': '1'
                          })

        data = self.report_module.process_request(req)[1]

        self.assertEqual(1, data['report']['id'])
        self.assertEqual("Active Tickets", data['report']['title'])
        self.assertEqual(
            " * List all active tickets by priority.\n"
            " * Color each row based on priority.\n",
            data['report']['description'])
        self.assertIn("SELECT p.value AS __color__", data['report']['sql'])

    def test_render_list(self):
        req = MockRequest(self.env,
                          method='GET',
                          args={
                              'action': 'view',
                              'id': '-1'
                          })

        data = self.report_module.process_request(req)[1]

        self.assertEqual('report', data['sort'])
        self.assertEqual(1, data['asc'])
        self.assertEqual(8, len(data['reports']))
        self.assertEqual(1, data['reports'][0][0])
        self.assertEqual('Active Tickets', data['reports'][0][1])
        self.assertEqual(
            " * List all active tickets by priority.\n"
            " * Color each row based on priority.\n", data['reports'][0][2])
        self.assertTrue('Active Reports', data['reports'][0][3])
        self.assertTrue('Active Reports', data['reports'][0][4])

    def test_render_view(self):
        req = MockRequest(self.env,
                          method='GET',
                          args={
                              'action': 'view',
                              'id': '1'
                          })

        data = self.report_module.process_request(req)[1]

        self.assertEqual(1, data['report']['id'])
        self.assertEqual("{1} Active Tickets", data['title'])
        self.assertEqual(
            " * List all active tickets by priority.\n"
            " * Color each row based on priority.\n", data['description'])

    def test_render_empty_report(self):
        """Empty report raises a TracError."""
        rid = self._insert_report('Empty report', '', '')
        req = MockRequest(self.env,
                          method='GET',
                          args={
                              'action': 'view',
                              'id': rid
                          })
        data = self.report_module.process_request(req)[1]
        self.assertEqual("Report failed: Report {%d} has no SQL query." % rid,
                         data['message'])

    def test_render_view_sort_order_preserved_on_update(self):
        """Sort column and order are preserved on update."""
        req = MockRequest(self.env,
                          method='GET',
                          args={
                              'action': 'view',
                              'id': 1,
                              'sort': 'summary',
                              'asc': '1'
                          })

        data = self.report_module.process_request(req)[1]

        self.assertEqual(1, data['asc'])
        self.assertEqual('summary', data['sort'])

    def test_sub_var_no_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            u"$VAR", {'VAR': 'value'})
        self.assertEqual("%s", sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_digits_underscore(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            u"$_VAR, $VAR2, $2VAR", {
                '_VAR': 'value1',
                'VAR2': 'value2'
            })
        self.assertEqual("%s, %s, $2VAR", sql)
        self.assertEqual(['value1', 'value2'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            u"'$VAR'", {'VAR': 'value'})
        with self.env.db_query as db:
            concatenated = db.concat("''", '%s', "''")
        self.assertEqual(concatenated, sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_missing_args(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            u"$VAR, $PARAM, $MISSING", {'VAR': 'value'})
        self.assertEqual("%s, %s, %s", sql)
        self.assertEqual(['value', '', ''], values)
        self.assertEqual(['PARAM', 'MISSING'], missing_args)

    def test_csv_escape(self):
        req = MockRequest(self.env)
        cols = ['TEST_COL', 'TEST_ZERO']
        rows = [('value, needs escaped', 0)]

        self.assertRaises(RequestDone, self.report_module._send_csv, req, cols,
                          rows)
        self.assertEqual(
            '\xef\xbb\xbfTEST_COL,TEST_ZERO\r\n"'
            'value, needs escaped",0\r\n', req.response_sent.getvalue())

    def test_saved_custom_query_redirect(self):
        query = u'query:?type=résumé'
        rid = self._insert_report('redirect', query, '')
        req = MockRequest(self.env)

        self.assertRaises(RequestDone, self.report_module._render_view, req,
                          rid)
        self.assertEqual(
            'http://example.org/trac.cgi/query?' +
            'type=r%C3%A9sum%C3%A9&report=' + str(rid),
            req.headers_sent['Location'])

    def test_quoted_id_with_var(self):
        req = MockRequest(self.env)
        name = """%s"`'%%%?"""
        with self.env.db_query as db:
            sql = u'SELECT 1 AS %s, $USER AS user' % db.quote(name)
            rv = self.report_module.execute_paginated_report(
                req, 1, sql, {'USER': '******'})
        self.assertEqual(5, len(rv), repr(rv))
        cols, results, num_items, missing_args, limit_offset = rv
        self.assertEqual([name, 'user'], cols)
        self.assertEqual([(1, 'joe')], results)
        self.assertEqual([], missing_args)
        self.assertIsNone(limit_offset)

    def test_value_error_from_get_var_args(self):
        req = MockRequest(self.env, path_info='/report/1')

        def get_var_args(req):
            raise ValueError('<error>')

        self.report_module.get_var_args = get_var_args
        self.assertTrue(self.report_module.match_request(req))
        data = self.report_module.process_request(req)[1]
        self.assertEqual('Report failed: <error>', data['message'])

    def test_title_and_description_with_sub_vars(self):
        with self.env.db_transaction:
            id_ = self._insert_report(
                'Tickets on $M for $USER',
                'SELECT * FROM ticket WHERE milestone=$M AND owner=$USER',
                'Show tickets on $M for $USER')
            for milestone in ('milestone1', 'milestone2'):
                insert_ticket(self.env,
                              status='new',
                              summary='Test 1',
                              owner='joe',
                              milestone=milestone)
        req = MockRequest(self.env,
                          path_info='/report/%d' % id_,
                          authname='joe',
                          args={'M': 'milestone2'})
        self.assertTrue(self.report_module.match_request(req))
        data = self.report_module.process_request(req)[1]
        self.assertEqual('{%d} Tickets on milestone2 for joe' % id_,
                         data['title'])
        self.assertEqual('Show tickets on milestone2 for joe',
                         data['description'])
        self.assertIsNone(data['message'])
        self.assertEqual(1, data['numrows'])

    def test_title_and_description_with_sub_vars_in_sql(self):
        with self.env.db_transaction:
            id_ = self._insert_report(
                'Tickets on $M for $USER', '-- M=milestone1\r\n'
                'SELECT * FROM ticket WHERE milestone=$M AND owner=$USER\r\n',
                'Show tickets on $M for $USER')
            for milestone in ('milestone1', 'milestone2'):
                insert_ticket(self.env,
                              status='new',
                              summary='Test 1',
                              owner='joe',
                              milestone=milestone)
        req = MockRequest(self.env,
                          path_info='/report/%d' % id_,
                          authname='joe')
        self.assertTrue(self.report_module.match_request(req))
        data = self.report_module.process_request(req)[1]
        self.assertEqual('{%d} Tickets on milestone1 for joe' % id_,
                         data['title'])
        self.assertEqual('Show tickets on milestone1 for joe',
                         data['description'])
        self.assertIsNone(data['message'])
        self.assertEqual(1, data['numrows'])

    def test_clear(self):
        req = MockRequest(self.env,
                          method='GET',
                          path_info='/report',
                          args={'action': 'clear'})
        req.session['query_href'] = req.href.query()
        req.session['query_tickets'] = '42'
        self.assertTrue(self.report_module.match_request(req))
        self.assertEqual('report_list.html',
                         self.report_module.process_request(req)[0])
        self.assertIn('query_href', req.session)
        self.assertIn('query_tickets', req.session)

        req = MockRequest(self.env,
                          method='POST',
                          path_info='/report',
                          args={'action': 'clear'})
        self.assertTrue(self.report_module.match_request(req))
        self.assertRaises(RequestDone, self.report_module.process_request, req)
        self.assertNotIn('query_href', req.session)
        self.assertNotIn('query_tickets', req.session)

    def test_valid_html_for_report(self):
        req = MockRequest(
            self.env,
            method='POST',
            path_info='/report',
            args={
                'action': 'new',
                'title': '#13046',
                'query': "SELECT '#13046' AS foo_, 42 AS bar, 'blah' AS _baz_",
                'description': ''
            })
        self.assertTrue(self.report_module.match_request(req))
        self.assertRaises(RequestDone, self.report_module.process_request, req)

        req = MockRequest(self.env, method='GET', path_info='/report/9')
        self.assertTrue(self.report_module.match_request(req))
        rv = self.report_module.process_request(req)
        rendered = Chrome(self.env).render_template(req, rv[0], rv[1], {
            'fragment': False,
            'iterable': False
        })
        self.assertRegexpMatches(
            rendered, r'<tr[^>]*>\s*'
            r'<td class="fullrow foo" colspan="100">'
            r'\s*#13046\s*<hr />\s*</td>\s*</tr>')
        self.assertRegexpMatches(
            rendered, r'<tr[^>]*>\s*'
            r'<td class="fullrow bar" colspan="100">'
            r'\s*42\s*<hr />\s*</td>\s*</tr>')
        self.assertRegexpMatches(
            rendered, r'<tr[^>]*>\s*'
            r'<td class="fullrow baz" colspan="100">'
            r'\s*blah\s*<hr />\s*</td>\s*</tr>')
        if genshi:
            XML(rendered)  # validates as XML

    def test_timestamp_columns(self):
        req = MockRequest(
            self.env,
            method='POST',
            path_info='/report',
            args={
                'action':
                'new',
                'title':
                '#13134',
                'query':
                "SELECT %d AS time, %d AS created, %d AS datetime" %
                ((1 * 86400 + 42) * 1000000, (2 * 86400 + 43) * 1000000,
                 (3 * 86400 + 44) * 1000000),
                'description':
                ''
            })
        self.assertTrue(self.report_module.match_request(req))
        self.assertRaises(RequestDone, self.report_module.process_request, req)

        req = MockRequest(self.env, method='GET', path_info='/report/9')
        self.assertTrue(self.report_module.match_request(req))
        rv = self.report_module.process_request(req)
        rendered = Chrome(self.env).render_template(req, rv[0], rv[1], {
            'fragment': False,
            'iterable': False
        })
        self.assertRegexpMatches(
            rendered, r'<td class="date">\s*(12:00:42 AM|00:00:42)\s*</td>')
        self.assertRegexpMatches(
            rendered, r'<td class="date">\s*(Jan 3, 1970|01/03/70)\s*</td>')
        self.assertRegexpMatches(
            rendered, r'<td class="date">\s*(Jan 4, 1970, 12:00:44 AM|'
            r'01/04/70 00:00:44)\s*</td>')
Esempio n. 3
0
class ReportTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub()
        self.report_module = ReportModule(self.env)

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

    def _make_environ(self,
                      scheme='http',
                      server_name='example.org',
                      server_port=80,
                      method='GET',
                      script_name='/trac',
                      **kwargs):
        environ = {
            'wsgi.url_scheme': scheme,
            'wsgi.input': StringIO(''),
            'REQUEST_METHOD': method,
            'SERVER_NAME': server_name,
            'SERVER_PORT': server_port,
            'SCRIPT_NAME': script_name
        }
        environ.update(kwargs)
        return environ

    def test_sub_var_no_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "$VAR", {'VAR': 'value'})
        self.assertEqual("%s", sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_digits_underscore(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "$_VAR, $VAR2, $2VAR", {
                '_VAR': 'value1',
                'VAR2': 'value2'
            })
        self.assertEqual("%s, %s, $2VAR", sql)
        self.assertEqual(['value1', 'value2'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "'$VAR'", {'VAR': 'value'})
        with self.env.db_query as db:
            concatenated = db.concat("''", '%s', "''")
        self.assertEqual(concatenated, sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_missing_args(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "$VAR, $PARAM, $MISSING", {'VAR': 'value'})
        self.assertEqual("%s, %s, %s", sql)
        self.assertEqual(['value', '', ''], values)
        self.assertEqual(['PARAM', 'MISSING'], missing_args)

    def test_csv_escape(self):
        buf = StringIO()

        def start_response(status, headers):
            return buf.write

        environ = self._make_environ()
        req = Request(environ, start_response)
        cols = ['TEST_COL', 'TEST_ZERO']
        rows = [('value, needs escaped', 0)]
        try:
            self.report_module._send_csv(req, cols, rows)
        except RequestDone:
            pass
        self.assertEqual(
            '\xef\xbb\xbfTEST_COL,TEST_ZERO\r\n"value, needs escaped",0\r\n',
            buf.getvalue())

    def test_saved_custom_query_redirect(self):
        query = u'query:?type=résumé'
        with self.env.db_transaction as db:
            cursor = db.cursor()
            cursor.execute(
                "INSERT INTO report (title,query,description) "
                "VALUES (%s,%s,%s)", ('redirect', query, ''))
            id = db.get_last_id(cursor, 'report')

        headers_sent = {}

        def start_response(status, headers):
            headers_sent.update(dict(headers))

        environ = self._make_environ()
        req = Request(environ, start_response)
        req.authname = 'anonymous'
        req.session = Mock(save=lambda: None)
        self.assertRaises(RequestDone, self.report_module._render_view, req,
                          id)
        self.assertEqual('http://example.org/trac/query?' + \
                         'type=r%C3%A9sum%C3%A9&report=' + str(id),
                         headers_sent['Location'])

    def test_quoted_id_with_var(self):
        req = Mock(base_path='',
                   chrome={},
                   args={},
                   session={},
                   abs_href=Href('/'),
                   href=Href('/'),
                   locale='',
                   perm=MockPerm(),
                   authname=None,
                   tz=None)
        name = """%s"`'%%%?"""
        with self.env.db_query as db:
            sql = 'SELECT 1 AS %s, $USER AS user' % db.quote(name)
            rv = self.report_module.execute_paginated_report(
                req, 1, sql, {'USER': '******'})
        self.assertEqual(5, len(rv), repr(rv))
        cols, results, num_items, missing_args, limit_offset = rv
        self.assertEqual([name, 'user'], cols)
        self.assertEqual([(1, 'joe')], results)
        self.assertEqual([], missing_args)
        self.assertEqual(None, limit_offset)
Esempio n. 4
0
class ReportModuleTestCase(unittest.TestCase):
    def setUp(self):
        self.env = EnvironmentStub(default_data=True)
        self.report_module = ReportModule(self.env)

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

    def test_create_report(self):
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'new',
                              'title': "New Report",
                              'query': "SELECT 1",
                              'description': "The description"
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        self.assertTrue(Report(self.env, 9).exists)
        self.assertIn("The report has been created.", req.chrome['notices'])
        self.assertEqual('http://example.org/trac.cgi/report/9',
                         req.headers_sent['Location'])

    def test_create_report_cancel(self):
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'new',
                              'cancel': True,
                              'title': "New Report",
                              'query': "SELECT 1",
                              'description': "The description"
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        self.assertRaises(ResourceNotFound, Report, self.env, 9)
        self.assertNotIn("The report has been created.", req.chrome['notices'])
        self.assertEqual('http://example.org/trac.cgi/report',
                         req.headers_sent['Location'])

    def test_delete_report(self):
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'delete',
                              'id': '1'
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        self.assertRaises(ResourceNotFound, Report, self.env, 1)
        self.assertIn("The report {1} has been deleted.",
                      req.chrome['notices'])
        self.assertEqual('http://example.org/trac.cgi/report',
                         req.headers_sent['Location'])

    def test_delete_report_cancel(self):
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'delete',
                              'cancel': True,
                              'id': '1'
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        self.assertTrue(Report(self.env, 1).exists)
        self.assertNotIn("The report {1} has been deleted.",
                         req.chrome['notices'])
        self.assertEqual('http://example.org/trac.cgi/report/1',
                         req.headers_sent['Location'])

    def test_update_report(self):
        Report(self.env).insert()
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'edit',
                              'id': '1',
                              'title': "New Report edited",
                              'query': "SELECT 2",
                              'description': "The description edited"
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        report = Report(self.env, 1)
        self.assertEqual("New Report edited", report.title)
        self.assertEqual("SELECT 2", report.query)
        self.assertEqual("The description edited", report.description)
        self.assertIn("Your changes have been saved.", req.chrome['notices'])

    def test_update_report_cancel(self):
        Report(self.env).insert()
        req = MockRequest(self.env,
                          method='POST',
                          args={
                              'action': 'edit',
                              'cancel': True,
                              'id': '1',
                              'title': "New Report edited",
                              'query': "SELECT 2",
                              'description': "The description edited"
                          })

        self.assertRaises(RequestDone, self.report_module.process_request, req)
        report = Report(self.env, 1)
        self.assertEqual("Active Tickets", report.title)
        self.assertEqual(
            " * List all active tickets by priority.\n"
            " * Color each row based on priority.\n", report.description)
        self.assertIn("SELECT p.value AS __color__", report.query)
        self.assertNotIn("Your changes have been saved.",
                         req.chrome['notices'])

    def test_render_confirm_delete(self):
        req = MockRequest(self.env,
                          method='GET',
                          args={
                              'action': 'delete',
                              'id': '1'
                          })

        data = self.report_module.process_request(req)[1]

        self.assertEqual("Delete Report {1} Active Tickets", data['title'])
        self.assertEqual('delete', data['action'])
        self.assertEqual(1, data['report']['id'])
        self.assertEqual('Active Tickets', data['report']['title'])

    def test_render_editor(self):
        req = MockRequest(self.env,
                          method='GET',
                          args={
                              'action': 'edit',
                              'id': '1'
                          })

        data = self.report_module.process_request(req)[1]

        self.assertEqual(1, data['report']['id'])
        self.assertEqual("Active Tickets", data['report']['title'])
        self.assertEqual(
            " * List all active tickets by priority.\n"
            " * Color each row based on priority.\n",
            data['report']['description'])
        self.assertIn("SELECT p.value AS __color__", data['report']['sql'])

    def test_render_list(self):
        req = MockRequest(self.env,
                          method='GET',
                          args={
                              'action': 'view',
                              'id': '-1'
                          })

        data = self.report_module.process_request(req)[1]

        self.assertEqual('report', data['sort'])
        self.assertEqual(1, data['asc'])
        self.assertEqual(8, len(data['reports']))
        self.assertEqual(1, data['reports'][0][0])
        self.assertEqual('Active Tickets', data['reports'][0][1])
        self.assertEqual(
            " * List all active tickets by priority.\n"
            " * Color each row based on priority.\n", data['reports'][0][2])
        self.assertTrue('Active Reports', data['reports'][0][3])
        self.assertTrue('Active Reports', data['reports'][0][4])

    def test_render_view(self):
        req = MockRequest(self.env,
                          method='GET',
                          args={
                              'action': 'view',
                              'id': '1'
                          })

        data = self.report_module.process_request(req)[1]

        self.assertEqual(1, data['report']['id'])
        self.assertEqual("{1} Active Tickets", data['title'])
        self.assertEqual(
            " * List all active tickets by priority.\n"
            " * Color each row based on priority.\n", data['description'])

    def test_sub_var_no_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            u"$VAR", {'VAR': 'value'})
        self.assertEqual("%s", sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_digits_underscore(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            u"$_VAR, $VAR2, $2VAR", {
                '_VAR': 'value1',
                'VAR2': 'value2'
            })
        self.assertEqual("%s, %s, $2VAR", sql)
        self.assertEqual(['value1', 'value2'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            u"'$VAR'", {'VAR': 'value'})
        with self.env.db_query as db:
            concatenated = db.concat("''", '%s', "''")
        self.assertEqual(concatenated, sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_missing_args(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            u"$VAR, $PARAM, $MISSING", {'VAR': 'value'})
        self.assertEqual("%s, %s, %s", sql)
        self.assertEqual(['value', '', ''], values)
        self.assertEqual(['PARAM', 'MISSING'], missing_args)

    def test_csv_escape(self):
        req = MockRequest(self.env)
        cols = ['TEST_COL', 'TEST_ZERO']
        rows = [('value, needs escaped', 0)]

        self.assertRaises(RequestDone, self.report_module._send_csv, req, cols,
                          rows)
        self.assertEqual(
            '\xef\xbb\xbfTEST_COL,TEST_ZERO\r\n"'
            'value, needs escaped",0\r\n', req.response_sent.getvalue())

    def test_saved_custom_query_redirect(self):
        query = u'query:?type=résumé'
        with self.env.db_transaction as db:
            cursor = db.cursor()
            cursor.execute(
                "INSERT INTO report (title,query,description) "
                "VALUES (%s,%s,%s)", ('redirect', query, ''))
            id = db.get_last_id(cursor, 'report')
        req = MockRequest(self.env)

        self.assertRaises(RequestDone, self.report_module._render_view, req,
                          id)
        self.assertEqual(
            'http://example.org/trac.cgi/query?' +
            'type=r%C3%A9sum%C3%A9&report=' + str(id),
            req.headers_sent['Location'])

    def test_quoted_id_with_var(self):
        req = MockRequest(self.env)
        name = """%s"`'%%%?"""
        with self.env.db_query as db:
            sql = u'SELECT 1 AS %s, $USER AS user' % db.quote(name)
            rv = self.report_module.execute_paginated_report(
                req, 1, sql, {'USER': '******'})
        self.assertEqual(5, len(rv), repr(rv))
        cols, results, num_items, missing_args, limit_offset = rv
        self.assertEqual([name, 'user'], cols)
        self.assertEqual([(1, 'joe')], results)
        self.assertEqual([], missing_args)
        self.assertEqual(None, limit_offset)
Esempio n. 5
0
class ReportTestCase(unittest.TestCase):

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

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

    def _make_environ(self, scheme='http', server_name='example.org',
                      server_port=80, method='GET', script_name='/trac',
                      **kwargs):
        environ = {'wsgi.url_scheme': scheme, 'wsgi.input': StringIO(''),
                   'REQUEST_METHOD': method, 'SERVER_NAME': server_name,
                   'SERVER_PORT': server_port, 'SCRIPT_NAME': script_name}
        environ.update(kwargs)
        return environ

    def test_sub_var_no_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "$VAR", {'VAR': 'value'})
        self.assertEqual("%s", sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_digits_underscore(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "$_VAR, $VAR2, $2VAR", {'_VAR': 'value1', 'VAR2': 'value2'})
        self.assertEqual("%s, %s, $2VAR", sql)
        self.assertEqual(['value1', 'value2'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_quotes(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "'$VAR'", {'VAR': 'value'})
        with self.env.db_query as db:
            concatenated = db.concat("''", '%s', "''")
        self.assertEqual(concatenated, sql)
        self.assertEqual(['value'], values)
        self.assertEqual([], missing_args)

    def test_sub_var_missing_args(self):
        sql, values, missing_args = self.report_module.sql_sub_vars(
            "$VAR, $PARAM, $MISSING", {'VAR': 'value'})
        self.assertEqual("%s, %s, %s", sql)
        self.assertEqual(['value', '', ''], values)
        self.assertEqual(['PARAM', 'MISSING'], missing_args)

    def test_csv_escape(self):
        buf = StringIO()
        def start_response(status, headers):
            return buf.write
        environ = self._make_environ()
        req = Request(environ, start_response)
        cols = ['TEST_COL', 'TEST_ZERO']
        rows = [('value, needs escaped', 0)]
        try:
            self.report_module._send_csv(req, cols, rows)
        except RequestDone:
            pass
        self.assertEqual('\xef\xbb\xbfTEST_COL,TEST_ZERO\r\n"value, needs escaped",0\r\n',
                         buf.getvalue())

    def test_saved_custom_query_redirect(self):
        query = u'query:?type=résumé'
        with self.env.db_transaction as db:
            cursor = db.cursor()
            cursor.execute("INSERT INTO report (title,query,description) "
                           "VALUES (%s,%s,%s)", ('redirect', query, ''))
            id = db.get_last_id(cursor, 'report')

        headers_sent = {}
        def start_response(status, headers):
            headers_sent.update(dict(headers))
        environ = self._make_environ()
        req = Request(environ, start_response)
        req.authname = 'anonymous'
        req.session = Mock(save=lambda: None)
        self.assertRaises(RequestDone,
                          self.report_module._render_view, req, id)
        self.assertEqual('http://example.org/trac/query?' + \
                         'type=r%C3%A9sum%C3%A9&report=' + str(id),
                         headers_sent['Location'])

    def test_quoted_id_with_var(self):
        req = Mock(base_path='', chrome={}, args={}, session={},
                   abs_href=Href('/'), href=Href('/'), locale='',
                   perm=MockPerm(), authname=None, tz=None)
        name = """%s"`'%%%?"""
        with self.env.db_query as db:
            sql = 'SELECT 1 AS %s, $USER AS user' % db.quote(name)
            rv = self.report_module.execute_paginated_report(req, 1, sql,
                                                             {'USER': '******'})
        self.assertEqual(5, len(rv), repr(rv))
        cols, results, num_items, missing_args, limit_offset = rv
        self.assertEqual([name, 'user'], cols)
        self.assertEqual([(1, 'joe')], results)
        self.assertEqual([], missing_args)
        self.assertEqual(None, limit_offset)