Merge branch 'main' into avm99963-monorail
Merged commit 34d8229ae2b51fb1a15bd208e6fe6185c94f6266
GitOrigin-RevId: 7ee0917f93a577e475f8e09526dd144d245593f4
diff --git a/services/test/api_svc_v1_test.py b/services/test/api_svc_v1_test.py
index b7cd9b1..72f7aee 100644
--- a/services/test/api_svc_v1_test.py
+++ b/services/test/api_svc_v1_test.py
@@ -1,7 +1,6 @@
-# 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
+# Copyright 2016 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
"""Tests for the API v1."""
from __future__ import print_function
@@ -9,9 +8,11 @@
from __future__ import absolute_import
import datetime
+from unittest import mock
import endpoints
import logging
from mock import Mock, patch, ANY
+import six
import time
import unittest
import webtest
@@ -27,9 +28,9 @@
from framework import permissions
from framework import profiler
from framework import template_helpers
-from proto import api_pb2_v1
-from proto import project_pb2
-from proto import tracker_pb2
+from mrproto import api_pb2_v1
+from mrproto import project_pb2
+from mrproto import tracker_pb2
from search import frontendsearchpipeline
from services import api_svc_v1
from services import service_manager
@@ -40,6 +41,7 @@
from testing_utils import testing
from tracker import tracker_bizobj
from tracker import tracker_constants
+from redirect import redirect_utils
def MakeFakeServiceManager():
@@ -163,7 +165,7 @@
oauth.get_current_user.side_effect = oauth.Error()
with self.assertRaises(webtest.AppError) as cm:
self.call_api('users_get', self.request)
- self.assertTrue(cm.exception.message.startswith('Bad response: 401'))
+ self.assertTrue(str(cm.exception).startswith('Bad response: 401'))
class MonorailApiTest(testing.EndpointsTestCase):
@@ -198,6 +200,7 @@
lambda x, y, z, u, v, w: ('id', 'email'))
self.mock(tracker_fulltext, 'IndexIssues', lambda x, y, z, u, v: None)
+ self.mock(tracker_fulltext, 'UnindexIssues', lambda _: None)
def SetUpComponents(
self, project_id, component_id, component_name, component_doc='doc',
@@ -303,6 +306,85 @@
self.assertEqual('Field1', resp['fieldValues'][0]['fieldName'])
self.assertEqual('11', resp['fieldValues'][0]['fieldValue'])
+ @mock.patch('businesslogic.work_env.WorkEnv.GetIssueMigratedID')
+ def testIssuesGet_GetIssue_MigratedId(self, mockGetIssueMigratedId):
+ """Get the requested issue."""
+ mockGetIssueMigratedId.return_value = '23456'
+
+ self.services.project.TestAddProject(
+ 'test-project', owner_ids=[222], project_id=12345)
+ self.SetUpComponents(12345, 1, 'API')
+ self.SetUpFieldDefs(1, 12345, 'Field1', tracker_pb2.FieldTypes.INT_TYPE)
+
+ fv = tracker_pb2.FieldValue(field_id=1, int_value=11)
+ issue1 = fake.MakeTestIssue(
+ project_id=12345,
+ local_id=1,
+ owner_id=222,
+ reporter_id=111,
+ status='New',
+ summary='sum',
+ component_ids=[1],
+ field_values=[fv])
+ self.services.issue.TestAddIssue(issue1)
+
+ resp = self.call_api('issues_get', self.request).json_body
+ self.assertEqual(1, resp['id'])
+ self.assertEqual('New', resp['status'])
+ self.assertEqual('open', resp['state'])
+ self.assertFalse(resp['canEdit'])
+ self.assertTrue(resp['canComment'])
+ self.assertEqual('requester@example.com', resp['author']['name'])
+ self.assertEqual('user@example.com', resp['owner']['name'])
+ self.assertEqual('API', resp['components'][0])
+ self.assertEqual('Field1', resp['fieldValues'][0]['fieldName'])
+ self.assertEqual('11', resp['fieldValues'][0]['fieldValue'])
+ self.assertEqual('23456', resp['migrated_id'])
+
+ @patch('framework.cloud_tasks_helpers.create_task')
+ def testIssuesInsert_FreezeLabels(self, _create_task_mock):
+ """Attempts to add new labels are blocked"""
+ self.services.project.TestAddProject(
+ 'test-project', owner_ids=[222], committer_ids=[111], project_id=999)
+ self.SetUpFieldDefs(1, 999, 'Field1', tracker_pb2.FieldTypes.INT_TYPE)
+
+ issue1 = fake.MakeTestIssue(
+ project_id=999,
+ local_id=1,
+ owner_id=222,
+ reporter_id=111,
+ status='New',
+ summary='Test issue')
+ self.services.issue.TestAddIssue(issue1)
+
+ issue_dict = {
+ 'blockedOn': [{
+ 'issueId': 1
+ }],
+ 'cc': [{
+ 'name': 'user@example.com'
+ }, {
+ 'name': ''
+ }, {
+ 'name': ' '
+ }],
+ 'description': 'description',
+ 'labels': ['freeze_new_label', 'label1'],
+ 'owner': {
+ 'name': 'requester@example.com'
+ },
+ 'status': 'New',
+ 'summary': 'Test issue',
+ 'fieldValues': [{
+ 'fieldName': 'Field1',
+ 'fieldValue': '11'
+ }]
+ }
+ self.request.update(issue_dict)
+
+ with self.call_should_fail(400):
+ self.call_api('issues_insert', self.request)
+
def testIssuesInsert_BadRequest(self):
"""The request does not specify summary or status."""
@@ -573,6 +655,36 @@
with self.call_should_fail(403):
self.call_api('issues_comments_insert', self.request)
+ def testIssuesCommentsInsert_ArchivedProject(self):
+ """No permission to comment in an archived project."""
+ self.services.project.TestAddProject(
+ 'test-project',
+ owner_ids=[111],
+ state=project_pb2.ProjectState.ARCHIVED,
+ project_id=12345)
+ issue1 = fake.MakeTestIssue(12345, 1, 'Issue 1', 'New', 2)
+ self.services.issue.TestAddIssue(issue1)
+
+ self.services.project.TestAddProject(
+ 'archived-project', owner_ids=[222], project_id=6789)
+ issue2 = fake.MakeTestIssue(
+ 6789, 2, 'Issue 2', 'New', 222, project_name='archived-project')
+ self.services.issue.TestAddIssue(issue2)
+
+ self.request['updates'] = {
+ 'blockedOn': ['archived-project:2'],
+ 'mergedInto': '',
+ }
+ with self.call_should_fail(403):
+ self.call_api('issues_comments_insert', self.request)
+
+ self.request['updates'] = {
+ 'blockedOn': [],
+ 'mergedInto': 'archived-project:2',
+ }
+ with self.call_should_fail(403):
+ self.call_api('issues_comments_insert', self.request)
+
def testIssuesCommentsInsert_CommentPermissionOnly(self):
"""User has permission to comment, even though they cannot edit."""
self.services.project.TestAddProject(
@@ -600,6 +712,28 @@
with self.call_should_fail(400):
self.call_api('issues_comments_insert', self.request)
+ def testIssuesCommentsInsert_FreezeLabels(self):
+ """Attempts to add new labels are blocked"""
+ self.services.project.TestAddProject(
+ 'test-project', owner_ids=[111], project_id=999)
+
+ issue1 = fake.MakeTestIssue(
+ 999, 1, 'Issue 1', 'New', 222, project_name='test-project')
+ self.services.issue.TestAddIssue(issue1)
+
+ self.request['updates'] = {
+ 'summary': 'new summary',
+ 'status': 'Started',
+ 'owner': 'requester@example.com',
+ 'cc': ['user@example.com'],
+ 'labels': ['freeze_new_label', '-remove_label'],
+ 'blockedOn': ['2'],
+ 'blocking': ['3'],
+ }
+
+ with self.call_should_fail(400):
+ self.call_api('issues_comments_insert', self.request)
+
def testIssuesCommentsInsert_Amendments_Normal(self):
"""Insert comments with amendments."""
@@ -703,10 +837,10 @@
self.assertEqual(2, len(issue2_comments)) # description and merge
source_starrers = self.services.issue_star.LookupItemStarrers(
'cnxn', issue1.issue_id)
- self.assertItemsEqual([111, 222, 333], source_starrers)
+ six.assertCountEqual(self, [111, 222, 333], source_starrers)
target_starrers = self.services.issue_star.LookupItemStarrers(
'cnxn', issue2.issue_id)
- self.assertItemsEqual([111, 222, 333, 555], target_starrers)
+ six.assertCountEqual(self, [111, 222, 333, 555], target_starrers)
def testIssuesCommentsInsert_CustomFields(self):
"""Update custom field values."""
@@ -1470,9 +1604,13 @@
with self.call_should_fail(403):
self.call_api('groups_create', self.request)
- def SetUpGroupRequest(self, group_name, who_can_view_members='MEMBERS',
- ext_group_type=None, perms=None,
- requester='requester@example.com'):
+ def SetUpGroupRequest(
+ self,
+ group_name,
+ who_can_view_members='MEMBERS',
+ ext_group_type='CHROME_INFRA_AUTH',
+ perms=None,
+ requester='requester@example.com'):
request = {
'groupName': group_name,
'requester': requester,
@@ -1648,7 +1786,8 @@
cd_dict = {
'componentPath': 'API'}
self.request.update(cd_dict)
- _ = self.call_api('components_delete', self.request).json_body
+ with self.assertWarns(webtest.lint.WSGIWarning):
+ _ = self.call_api('components_delete', self.request)
self.assertEqual(0, len(self.config.component_defs))
def testComponentsUpdate_Invalid(self):
@@ -1704,12 +1843,13 @@
'requester@example.com', 'user@example.com', '', ' ']},
{'field': 'DEPRECATED', 'deprecated': True}]}
self.request.update(cd_dict)
- _ = self.call_api('components_update', self.request).json_body
+ with self.assertWarns(webtest.lint.WSGIWarning):
+ _ = self.call_api('components_update', self.request)
component_def = tracker_bizobj.FindComponentDef(
'API', self.config)
self.assertIsNotNone(component_def)
self.assertEqual('', component_def.docstring)
- self.assertItemsEqual([111, 222], component_def.cc_ids)
+ six.assertCountEqual(self, [111, 222], component_def.cc_ids)
self.assertTrue(component_def.deprecated)
cd_dict = {
@@ -1717,7 +1857,8 @@
'updates': [
{'field': 'LEAF_NAME', 'leafName': 'NewParent'}]}
self.request.update(cd_dict)
- _ = self.call_api('components_update', self.request).json_body
+ with self.assertWarns(webtest.lint.WSGIWarning):
+ _ = self.call_api('components_update', self.request)
cd_parent = tracker_bizobj.FindComponentDef(
'NewParent', self.config)
cd_child = tracker_bizobj.FindComponentDef(
@@ -1838,6 +1979,21 @@
api_svc_v1.api_base_checks(
request, requester, self.services, None, self.auth_client_ids, [])
+ def testNonLiveMigratedProject(self):
+ archived_project = 'archived-migrated-project'
+ redirect_utils.PROJECT_REDIRECT_MAP = {
+ 'archived-migrated-project': 'https://example.dev'
+ }
+ self.services.project.TestAddProject(
+ archived_project,
+ owner_ids=[111],
+ state=project_pb2.ProjectState.ARCHIVED)
+ request = RequestMock()
+ request.projectId = archived_project
+ requester = RequesterMock(email='test@example.com')
+ api_svc_v1.api_base_checks(
+ request, requester, self.services, None, self.auth_client_ids, [])
+
def testNoViewProjectPermission(self):
nonmember_email = 'nonmember@example.com'
self.services.user.TestAddUser(nonmember_email, 222)