Project import generated by Copybara.
GitOrigin-RevId: d9e9e3fb4e31372ec1fb43b178994ca78fa8fe70
diff --git a/search/test/ast2sort_test.py b/search/test/ast2sort_test.py
new file mode 100644
index 0000000..9d365e8
--- /dev/null
+++ b/search/test/ast2sort_test.py
@@ -0,0 +1,373 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file or at
+# https://developers.google.com/open-source/licenses/bsd
+
+"""Tests for the ast2sort module."""
+from __future__ import print_function
+from __future__ import division
+from __future__ import absolute_import
+
+import unittest
+
+from proto import tracker_pb2
+from search import ast2sort
+from search import query2ast
+
+
+BUILTIN_ISSUE_FIELDS = query2ast.BUILTIN_ISSUE_FIELDS
+ANY_FIELD = query2ast.BUILTIN_ISSUE_FIELDS['any_field']
+
+
+class AST2SortTest(unittest.TestCase):
+
+ def setUp(self):
+ self.harmonized_labels = [
+ (101, 0, 'Hot'), (102, 1, 'Cold'), (103, None, 'Odd')]
+ self.harmonized_statuses = [
+ (201, 0, 'New'), (202, 1, 'Assigned'), (203, None, 'OnHold')]
+ self.harmonized_fields = []
+ self.fmt = lambda string, **kwords: string
+
+ def testBuildSortClauses_EmptySortDirectives(self):
+ left_joins, order_by = ast2sort.BuildSortClauses(
+ [], self.harmonized_labels, self.harmonized_statuses,
+ self.harmonized_fields)
+ self.assertEqual([], left_joins)
+ self.assertEqual([], order_by)
+
+ def testBuildSortClauses_Normal(self):
+ left_joins, order_by = ast2sort.BuildSortClauses(
+ ['stars', 'status', 'pri', 'reporter', 'id'], self.harmonized_labels,
+ self.harmonized_statuses, self.harmonized_fields)
+ expected_left_joins = [
+ ('User AS Sort3 ON Issue.reporter_id = Sort3.user_id', [])]
+ expected_order_by = [
+ ('Issue.star_count ASC', []),
+ ('FIELD(IF(ISNULL(Issue.status_id), Issue.derived_status_id, '
+ 'Issue.status_id), %s,%s) DESC', [201, 202]),
+ ('FIELD(IF(ISNULL(Issue.status_id), Issue.derived_status_id, '
+ 'Issue.status_id), %s) DESC', [203]),
+ ('ISNULL(Sort3.email) ASC', []),
+ ('Sort3.email ASC', []),
+ ('Issue.local_id ASC', [])]
+ self.assertEqual(expected_left_joins, left_joins)
+ self.assertEqual(expected_order_by, order_by)
+
+ def testProcessProjectSD(self):
+ left_joins, order_by = ast2sort._ProcessProjectSD(self.fmt)
+ self.assertEqual([], left_joins)
+ self.assertEqual(
+ [('Issue.project_id {sort_dir}', [])],
+ order_by)
+
+ def testProcessReporterSD(self):
+ left_joins, order_by = ast2sort._ProcessReporterSD(self.fmt)
+ self.assertEqual(
+ [('User AS {alias} ON Issue.reporter_id = {alias}.user_id', [])],
+ left_joins)
+ self.assertEqual(
+ [('ISNULL({alias}.email) {sort_dir}', []),
+ ('{alias}.email {sort_dir}', [])],
+ order_by)
+
+ def testProcessOwnerSD(self):
+ left_joins, order_by = ast2sort._ProcessOwnerSD(self.fmt)
+ self.assertEqual(
+ [('User AS {alias}_exp ON Issue.owner_id = {alias}_exp.user_id', []),
+ ('User AS {alias}_der ON '
+ 'Issue.derived_owner_id = {alias}_der.user_id', [])],
+ left_joins)
+ self.assertEqual(
+ [('(ISNULL({alias}_exp.email) AND ISNULL({alias}_der.email)) '
+ '{sort_dir}', []),
+ ('CONCAT({alias}_exp.email, {alias}_der.email) {sort_dir}', [])],
+ order_by)
+
+ def testProcessCcSD(self):
+ left_joins, order_by = ast2sort._ProcessCcSD(self.fmt)
+ self.assertEqual(
+ [('Issue2Cc AS {alias} ON Issue.id = {alias}.issue_id '
+ 'LEFT JOIN User AS {alias}_user '
+ 'ON {alias}.cc_id = {alias}_user.user_id', [])],
+ left_joins)
+ self.assertEqual(
+ [('ISNULL({alias}_user.email) {sort_dir}', []),
+ ('{alias}_user.email {sort_dir}', [])],
+ order_by)
+
+ def testProcessComponentSD(self):
+ left_joins, order_by = ast2sort._ProcessComponentSD(self.fmt)
+ self.assertEqual(
+ [('Issue2Component AS {alias} ON Issue.id = {alias}.issue_id '
+ 'LEFT JOIN ComponentDef AS {alias}_component '
+ 'ON {alias}.component_id = {alias}_component.id', [])],
+ left_joins)
+ self.assertEqual(
+ [('ISNULL({alias}_component.path) {sort_dir}', []),
+ ('{alias}_component.path {sort_dir}', [])],
+ order_by)
+
+ def testProcessSummarySD(self):
+ left_joins, order_by = ast2sort._ProcessSummarySD(self.fmt)
+ self.assertEqual(
+ [('IssueSummary AS {alias} ON Issue.id = {alias}.issue_id', [])],
+ left_joins)
+ self.assertEqual(
+ [('{alias}.summary {sort_dir}', [])],
+ order_by)
+
+ def testProcessStatusSD(self):
+ pass # TODO(jrobbins): fill in this test case
+
+ def testProcessBlockedSD(self):
+ left_joins, order_by = ast2sort._ProcessBlockedSD(self.fmt)
+ self.assertEqual(
+ [('IssueRelation AS {alias} ON Issue.id = {alias}.issue_id '
+ 'AND {alias}.kind = %s', ['blockedon'])],
+ left_joins)
+ self.assertEqual(
+ [('ISNULL({alias}.dst_issue_id) {sort_dir}', [])],
+ order_by)
+
+ def testProcessBlockedOnSD(self):
+ left_joins, order_by = ast2sort._ProcessBlockedOnSD(self.fmt)
+ self.assertEqual(
+ [('IssueRelation AS {alias} ON Issue.id = {alias}.issue_id '
+ 'AND {alias}.kind = %s', ['blockedon'])],
+ left_joins)
+ self.assertEqual(
+ [('ISNULL({alias}.dst_issue_id) {sort_dir}', []),
+ ('{alias}.dst_issue_id {sort_dir}', [])],
+ order_by)
+
+ def testProcessBlockingSD(self):
+ left_joins, order_by = ast2sort._ProcessBlockingSD(self.fmt)
+ self.assertEqual(
+ [('IssueRelation AS {alias} ON Issue.id = {alias}.dst_issue_id '
+ 'AND {alias}.kind = %s', ['blockedon'])],
+ left_joins)
+ self.assertEqual(
+ [('ISNULL({alias}.issue_id) {sort_dir}', []),
+ ('{alias}.issue_id {sort_dir}', [])],
+ order_by)
+
+ def testProcessMergedIntoSD(self):
+ left_joins, order_by = ast2sort._ProcessMergedIntoSD(self.fmt)
+ self.assertEqual(
+ [('IssueRelation AS {alias} ON Issue.id = {alias}.issue_id '
+ 'AND {alias}.kind = %s', ['mergedinto'])],
+ left_joins)
+ self.assertEqual(
+ [('ISNULL({alias}.dst_issue_id) {sort_dir}', []),
+ ('{alias}.dst_issue_id {sort_dir}', [])],
+ order_by)
+
+ def testProcessCustomAndLabelSD(self):
+ pass # TODO(jrobbins): fill in this test case
+
+ def testProcessCustomAndLabelSD_PhaseField(self):
+ harmonized_labels = []
+ bear_fd = tracker_pb2.FieldDef(
+ field_id=1, field_name='DropBear', project_id=789,
+ field_type=tracker_pb2.FieldTypes.INT_TYPE)
+ bear2_fd = tracker_pb2.FieldDef(
+ field_id=2, field_name='DropBear', project_id=788,
+ field_type=tracker_pb2.FieldTypes.STR_TYPE)
+ koala_fd = tracker_pb2.FieldDef(
+ field_id=3, field_name='koala', project_id=789,
+ field_type=tracker_pb2.FieldTypes.INT_TYPE)
+ bear_app_fd = tracker_pb2.FieldDef(
+ field_id=4, field_name='dropbear', project_id=789,
+ field_type=tracker_pb2.FieldTypes.APPROVAL_TYPE)
+ harmonized_fields = [bear_fd, bear2_fd, koala_fd, bear_app_fd]
+ phase_name = 'stable'
+ alias = 'Sort0'
+ sort_dir = 'DESC'
+ sd = 'stable.dropbear'
+ left_joins, order_by = ast2sort._ProcessCustomAndLabelSD(
+ sd, harmonized_labels, harmonized_fields, alias, sort_dir,
+ self.fmt)
+
+ expected_joins = []
+ expected_order = []
+ int_left_joins, int_order_by = ast2sort._CustomFieldSortClauses(
+ [bear_fd, bear2_fd], tracker_pb2.FieldTypes.INT_TYPE, 'int_value',
+ alias, sort_dir, phase_name=phase_name)
+ str_left_joins, str_order_by = ast2sort._CustomFieldSortClauses(
+ [bear_fd, bear2_fd], tracker_pb2.FieldTypes.STR_TYPE, 'str_value',
+ alias, sort_dir, phase_name=phase_name)
+ user_left_joins, user_order_by = ast2sort._CustomFieldSortClauses(
+ [bear_fd, bear2_fd], tracker_pb2.FieldTypes.USER_TYPE, 'user_id',
+ alias, sort_dir, phase_name=phase_name)
+ label_left_joinss, label_order_by = ast2sort._LabelSortClauses(
+ sd, harmonized_labels, self.fmt)
+ expected_joins.extend(
+ int_left_joins + str_left_joins + user_left_joins + label_left_joinss)
+ expected_order.extend(
+ int_order_by + str_order_by + user_order_by + label_order_by)
+ self.assertEqual(left_joins, expected_joins)
+ self.assertEqual(order_by, expected_order)
+
+ def testApprovalFieldSortClauses_Status(self):
+ approval_fd_list = [
+ tracker_pb2.FieldDef(field_id=2, project_id=789,
+ field_type=tracker_pb2.FieldTypes.APPROVAL_TYPE),
+ tracker_pb2.FieldDef(field_id=4, project_id=788,
+ field_type=tracker_pb2.FieldTypes.APPROVAL_TYPE)
+ ]
+ left_joins, order_by = ast2sort._ApprovalFieldSortClauses(
+ approval_fd_list, '-status', self.fmt)
+
+ self.assertEqual(
+ [('{tbl_name} AS {alias}_approval '
+ 'ON Issue.id = {alias}_approval.issue_id '
+ 'AND {alias}_approval.approval_id IN ({approval_ids_ph})', [2, 4])],
+ left_joins)
+
+ self.assertEqual(
+ [('FIELD({alias}_approval.status, {approval_status_ph}) {rev_sort_dir}',
+ ast2sort.APPROVAL_STATUS_SORT_ORDER)],
+ order_by)
+
+ def testApprovalFieldSortClauses_Approver(self):
+ approval_fd_list = [
+ tracker_pb2.FieldDef(field_id=2, project_id=789,
+ field_type=tracker_pb2.FieldTypes.APPROVAL_TYPE),
+ tracker_pb2.FieldDef(field_id=4, project_id=788,
+ field_type=tracker_pb2.FieldTypes.APPROVAL_TYPE)
+ ]
+ left_joins, order_by = ast2sort._ApprovalFieldSortClauses(
+ approval_fd_list, '-approver', self.fmt)
+
+ self.assertEqual(
+ [('{tbl_name} AS {alias}_approval '
+ 'ON Issue.id = {alias}_approval.issue_id '
+ 'AND {alias}_approval.approval_id IN ({approval_ids_ph})', [2, 4]),
+ ('User AS {alias}_approval_user '
+ 'ON {alias}_approval.approver_id = {alias}_approval_user.user_id',
+ [])],
+ left_joins)
+
+ self.assertEqual(
+ [('ISNULL({alias}_approval_user.email) {sort_dir}', []),
+ ('{alias}_approval_user.email {sort_dir}', [])],
+ order_by)
+
+ def testLabelSortClauses_NoSuchLabels(self):
+ sd = 'somethingelse'
+ harmonized_labels = [
+ (101, 0, 'Type-Defect'),
+ (102, 1, 'Type-Enhancement'),
+ (103, 2, 'Type-Task'),
+ (104, 0, 'Priority-High'),
+ (199, None, 'Type-Laundry'),
+ ]
+ left_joins, order_by = ast2sort._LabelSortClauses(
+ sd, harmonized_labels, self.fmt)
+ self.assertEqual([], left_joins)
+ self.assertEqual([], order_by)
+
+ def testLabelSortClauses_Normal(self):
+ sd = 'type'
+ harmonized_labels = [
+ (101, 0, 'Type-Defect'),
+ (102, 1, 'Type-Enhancement'),
+ (103, 2, 'Type-Task'),
+ (104, 0, 'Priority-High'),
+ (199, None, 'Type-Laundry'),
+ ]
+ left_joins, order_by = ast2sort._LabelSortClauses(
+ sd, harmonized_labels, self.fmt)
+ self.assertEqual(1, len(left_joins))
+ self.assertEqual(
+ ('Issue2Label AS {alias} ON Issue.id = {alias}.issue_id AND '
+ '{alias}.label_id IN ({all_label_ph})',
+ [101, 102, 103, 199]),
+ left_joins[0])
+ self.assertEqual(2, len(order_by))
+ self.assertEqual(
+ ('FIELD({alias}.label_id, {wk_label_ph}) {rev_sort_dir}',
+ [101, 102, 103]),
+ order_by[0])
+ self.assertEqual(
+ ('FIELD({alias}.label_id, {odd_label_ph}) {rev_sort_dir}',
+ [199]),
+ order_by[1])
+
+ def testCustomFieldSortClauses_Normal(self):
+ fd_list = [
+ tracker_pb2.FieldDef(field_id=1, project_id=789,
+ field_type=tracker_pb2.FieldTypes.INT_TYPE),
+ tracker_pb2.FieldDef(field_id=2, project_id=788,
+ field_type=tracker_pb2.FieldTypes.STR_TYPE),
+ ]
+ left_joins, order_by = ast2sort._CustomFieldSortClauses(
+ fd_list, tracker_pb2.FieldTypes.INT_TYPE, 'int_value', 'Sort0', 'DESC')
+
+ self.assertEqual(
+ left_joins, [
+ ('Issue2FieldValue AS Sort0_int_value '
+ 'ON Issue.id = Sort0_int_value.issue_id '
+ 'AND Sort0_int_value.field_id IN (%s)', [1]),
+ ])
+ self.assertEqual(
+ order_by, [
+ ('ISNULL(Sort0_int_value.int_value) DESC', []),
+ ('Sort0_int_value.int_value DESC', []),
+ ])
+
+ def testCustomFieldSortClauses_PhaseUser(self):
+ fd_list = [
+ tracker_pb2.FieldDef(field_id=1, project_id=789,
+ field_type=tracker_pb2.FieldTypes.INT_TYPE),
+ tracker_pb2.FieldDef(field_id=2, project_id=788,
+ field_type=tracker_pb2.FieldTypes.STR_TYPE),
+ tracker_pb2.FieldDef(field_id=3, project_id=788,
+ field_type=tracker_pb2.FieldTypes.USER_TYPE),
+ ]
+ left_joins, order_by = ast2sort._CustomFieldSortClauses(
+ fd_list, tracker_pb2.FieldTypes.USER_TYPE, 'user_id', 'Sort0', 'DESC',
+ phase_name='Stable')
+
+ self.assertEqual(
+ left_joins, [
+ ('Issue2FieldValue AS Sort0_user_id '
+ 'ON Issue.id = Sort0_user_id.issue_id '
+ 'AND Sort0_user_id.field_id IN (%s)', [3]),
+ ('IssuePhaseDef AS Sort0_user_id_phase '
+ 'ON Sort0_user_id.phase_id = Sort0_user_id_phase.id '
+ 'AND LOWER(Sort0_user_id_phase.name) = LOWER(%s)', ['Stable']),
+ ('User AS Sort0_user_id_user '
+ 'ON Sort0_user_id.user_id = Sort0_user_id_user.user_id', []),
+ ])
+ self.assertEqual(
+ order_by, [
+ ('ISNULL(Sort0_user_id_user.email) DESC', []),
+ ('Sort0_user_id_user.email DESC', []),
+ ])
+
+ def testOneSortDirective_NativeSortable(self):
+ left_joins, order_by = ast2sort._OneSortDirective(
+ 1, 'opened', self.harmonized_labels, self.harmonized_statuses,
+ self.harmonized_fields)
+ self.assertEqual([], left_joins)
+ self.assertEqual([('Issue.opened ASC', [])], order_by)
+
+ left_joins, order_by = ast2sort._OneSortDirective(
+ 1, 'stars', self.harmonized_labels, self.harmonized_statuses,
+ self.harmonized_fields)
+ self.assertEqual([], left_joins)
+ self.assertEqual([('Issue.star_count ASC', [])], order_by)
+
+ left_joins, order_by = ast2sort._OneSortDirective(
+ 1, '-stars', self.harmonized_labels, self.harmonized_statuses,
+ self.harmonized_fields)
+ self.assertEqual([], left_joins)
+ self.assertEqual([('Issue.star_count DESC', [])], order_by)
+
+ left_joins, order_by = ast2sort._OneSortDirective(
+ 1, 'componentmodified', self.harmonized_labels,
+ self.harmonized_statuses, self.harmonized_fields)
+ self.assertEqual([], left_joins)
+ self.assertEqual([('Issue.component_modified ASC', [])], order_by)