blob: 364566a8a847c55c944260d9158d76994a86dea7 [file] [log] [blame]
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +01001# Copyright 2020 The Chromium Authors
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
Copybara854996b2021-09-07 19:36:02 +00004"""Tests for the hotlists servicer."""
5from __future__ import print_function
6from __future__ import division
7from __future__ import absolute_import
8
9import unittest
10import mock
11import logging
12
13from google.protobuf import timestamp_pb2
14from google.protobuf import empty_pb2
15
16from api import resource_name_converters as rnc
17from api.v3 import projects_servicer
18from api.v3 import converters
19from api.v3.api_proto import projects_pb2
20from api.v3.api_proto import project_objects_pb2
21from api.v3.api_proto import issue_objects_pb2
22from framework import exceptions
23from framework import monorailcontext
24from framework import permissions
25from testing import fake
26from services import service_manager
27
28from google.appengine.ext import testbed
29
30class ProjectsServicerTest(unittest.TestCase):
31
32 def setUp(self):
33 # memcache and datastore needed for generating page tokens.
34 self.testbed = testbed.Testbed()
35 self.testbed.activate()
36 self.testbed.init_memcache_stub()
37 self.testbed.init_datastore_v3_stub()
38
39 self.cnxn = fake.MonorailConnection()
40 self.services = service_manager.Services(
41 features=fake.FeaturesService(),
42 issue=fake.IssueService(),
43 project=fake.ProjectService(),
44 config=fake.ConfigService(),
45 user=fake.UserService(),
46 template=fake.TemplateService(),
47 usergroup=fake.UserGroupService())
48 self.projects_svcr = projects_servicer.ProjectsServicer(
49 self.services, make_rate_limiter=False)
50
51 self.user_1 = self.services.user.TestAddUser('user_111@example.com', 111)
52
53 self.project_1 = self.services.project.TestAddProject(
54 'proj', project_id=789)
55 self.template_1 = self.services.template.TestAddIssueTemplateDef(
56 123, 789, 'template_1_name', content='foo bar', summary='foo')
57 self.project_1_resource_name = 'projects/proj'
58 self.converter = None
59
60 def CallWrapped(self, wrapped_handler, mc, *args, **kwargs):
61 self.converter = converters.Converter(mc, self.services)
62 self.projects_svcr.converter = self.converter
63 return wrapped_handler.wrapped(self.projects_svcr, mc, *args, **kwargs)
64
65 def testListIssueTemplates(self):
66 request = projects_pb2.ListIssueTemplatesRequest(
67 parent=self.project_1_resource_name)
68 mc = monorailcontext.MonorailContext(
69 self.services, cnxn=self.cnxn, requester=self.user_1.email)
70 response = self.CallWrapped(
71 self.projects_svcr.ListIssueTemplates, mc, request)
72
73 expected_issue = issue_objects_pb2.Issue(
74 summary=self.template_1.summary,
75 state=issue_objects_pb2.IssueContentState.Value('ACTIVE'),
76 status=issue_objects_pb2.Issue.StatusValue(
77 status=self.template_1.status,
78 derivation=issue_objects_pb2.Derivation.Value('EXPLICIT')))
79 expected_template = project_objects_pb2.IssueTemplate(
80 name='projects/{}/templates/{}'.format(
81 self.project_1.project_name, self.template_1.template_id),
82 display_name=self.template_1.name,
83 issue=expected_issue,
84 summary_must_be_edited=False,
85 template_privacy=project_objects_pb2.IssueTemplate.TemplatePrivacy
86 .Value('PUBLIC'),
87 default_owner=project_objects_pb2.IssueTemplate.DefaultOwner.Value(
88 'DEFAULT_OWNER_UNSPECIFIED'),
89 component_required=False)
90
91 self.assertEqual(
92 response,
93 projects_pb2.ListIssueTemplatesResponse(templates=[expected_template]))
94
95 @mock.patch('api.v3.api_constants.MAX_COMPONENTS_PER_PAGE', 3)
96 def testListComponentDefs(self):
97 project = self.services.project.TestAddProject(
98 'greece', project_id=987, owner_ids=[self.user_1.user_id])
99 config = fake.MakeTestConfig(project.project_id, [], [])
100 cd_1 = fake.MakeTestComponentDef(project.project_id, 1, path='Circe')
101 cd_2 = fake.MakeTestComponentDef(project.project_id, 2, path='Achilles')
102 cd_3 = fake.MakeTestComponentDef(project.project_id, 3, path='Patroclus')
103 cd_4 = fake.MakeTestComponentDef(project.project_id, 3, path='Galatea')
104 config.component_defs = [cd_1, cd_2, cd_3, cd_4]
105 self.services.config.StoreConfig(self.cnxn, config)
106
107 mc = monorailcontext.MonorailContext(
108 self.services, cnxn=self.cnxn, requester=self.user_1.email)
109
110 request = projects_pb2.ListComponentDefsRequest(parent='projects/greece')
111 response_1 = self.CallWrapped(
112 self.projects_svcr.ListComponentDefs, mc, request)
113 expected_cds_1 = self.converter.ConvertComponentDefs(
114 [cd_1, cd_2, cd_3], project.project_id)
115 self.assertEqual(list(response_1.component_defs), expected_cds_1)
116
117 request = projects_pb2.ListComponentDefsRequest(
118 parent='projects/greece', page_token=response_1.next_page_token)
119 response_2 = self.CallWrapped(
120 self.projects_svcr.ListComponentDefs, mc, request)
121 expected_cds_2 = self.converter.ConvertComponentDefs(
122 [cd_4], project.project_id)
123 self.assertEqual(list(response_2.component_defs), expected_cds_2)
124
125 @mock.patch('api.v3.api_constants.MAX_COMPONENTS_PER_PAGE', 2)
126 def testListComponentDefs_PaginateAndMaxSizeCap(self):
127 project = self.services.project.TestAddProject(
128 'greece', project_id=987, owner_ids=[self.user_1.user_id])
129 config = fake.MakeTestConfig(project.project_id, [], [])
130 cd_1 = fake.MakeTestComponentDef(project.project_id, 1, path='Circe')
131 cd_2 = fake.MakeTestComponentDef(project.project_id, 2, path='Achilles')
132 cd_3 = fake.MakeTestComponentDef(project.project_id, 3, path='Patroclus')
133 cd_4 = fake.MakeTestComponentDef(project.project_id, 4, path='Galatea')
134 cd_5 = fake.MakeTestComponentDef(project.project_id, 5, path='Briseis')
135 config.component_defs = [cd_1, cd_2, cd_3, cd_4, cd_5]
136 self.services.config.StoreConfig(self.cnxn, config)
137
138 mc = monorailcontext.MonorailContext(
139 self.services, cnxn=self.cnxn, requester=self.user_1.email)
140
141 request = projects_pb2.ListComponentDefsRequest(
142 parent='projects/greece', page_size=3)
143 response_1 = self.CallWrapped(
144 self.projects_svcr.ListComponentDefs, mc, request)
145 expected_cds_1 = self.converter.ConvertComponentDefs(
146 [cd_1, cd_2], project.project_id)
147 self.assertEqual(list(response_1.component_defs), expected_cds_1)
148
149 request = projects_pb2.ListComponentDefsRequest(
150 parent='projects/greece', page_size=3,
151 page_token=response_1.next_page_token)
152 response_2 = self.CallWrapped(
153 self.projects_svcr.ListComponentDefs, mc, request)
154 expected_cds_2 = self.converter.ConvertComponentDefs(
155 [cd_3, cd_4], project.project_id)
156 self.assertEqual(list(response_2.component_defs), expected_cds_2)
157
158 request = projects_pb2.ListComponentDefsRequest(
159 parent='projects/greece', page_size=3,
160 page_token=response_2.next_page_token)
161 response_3 = self.CallWrapped(
162 self.projects_svcr.ListComponentDefs, mc, request)
163 expected_cds_3 = self.converter.ConvertComponentDefs(
164 [cd_5], project.project_id)
165 self.assertEqual(response_3, projects_pb2.ListComponentDefsResponse(
166 component_defs=expected_cds_3))
167
168 @mock.patch('time.time')
169 def testCreateComponentDef(self, mockTime):
170 now = 123
171 mockTime.return_value = now
172
173 user_1 = self.services.user.TestAddUser('achilles@test.com', 981)
174 self.services.user.TestAddUser('patroclus@test.com', 982)
175 self.services.user.TestAddUser('circe@test.com', 983)
176
177 project = self.services.project.TestAddProject(
178 'chicken', project_id=987, owner_ids=[user_1.user_id])
179 config = fake.MakeTestConfig(project.project_id, [], [])
180 self.services.config.StoreConfig(self.cnxn, config)
181
182 expected = project_objects_pb2.ComponentDef(
183 value='circe',
184 docstring='You threw me to the crows',
185 admins=['users/983'],
186 ccs=['users/981', 'users/982'],
187 labels=['more-soup', 'beach-day'],
188 )
189 request = projects_pb2.CreateComponentDefRequest(
190 parent='projects/chicken', component_def=expected)
191 mc = monorailcontext.MonorailContext(
192 self.services, cnxn=self.cnxn, requester=user_1.email)
193 response = self.CallWrapped(
194 self.projects_svcr.CreateComponentDef, mc, request)
195
196 self.assertEqual(1, len(config.component_defs))
197 expected.name = 'projects/chicken/componentDefs/%d' % config.component_defs[
198 0].component_id
199 expected.state = project_objects_pb2.ComponentDef.ComponentDefState.Value(
200 'ACTIVE')
201 expected.creator = 'users/981'
202 expected.create_time.FromSeconds(now)
203 expected.modify_time.FromSeconds(0)
204 self.assertEqual(response, expected)
205
206 def testDeleteComponentDef(self):
207 user_1 = self.services.user.TestAddUser('achilles@test.com', 981)
208 project = self.services.project.TestAddProject(
209 'chicken', project_id=987, owner_ids=[user_1.user_id])
210 config = fake.MakeTestConfig(project.project_id, [], [])
211 component_def = fake.MakeTestComponentDef(
212 project.project_id, 1, path='Chickens>Dickens')
213 config.component_defs = [component_def]
214 self.services.config.StoreConfig(self.cnxn, config)
215
216 request = projects_pb2.DeleteComponentDefRequest(
217 name='projects/chicken/componentDefs/1')
218 mc = monorailcontext.MonorailContext(
219 self.services, cnxn=self.cnxn, requester=user_1.email)
220 actual = self.CallWrapped(
221 self.projects_svcr.DeleteComponentDef, mc, request)
222 self.assertEqual(actual, empty_pb2.Empty())
223
224 self.assertEqual(config.component_defs, [])
225
Adrià Vilanova Martínezf5e10392021-12-07 22:55:40 +0100226 def testGetComponentDef(self):
227 user_1 = self.services.user.TestAddUser('achilles@test.com', 981)
228 project = self.services.project.TestAddProject(
229 'chicken', project_id=987, owner_ids=[user_1.user_id])
230 config = fake.MakeTestConfig(project.project_id, [], [])
231 component_def = fake.MakeTestComponentDef(
232 project.project_id, 1, path='Chickens>Dickens')
233 config.component_defs = [component_def]
234 self.services.config.StoreConfig(self.cnxn, config)
235
236 request = projects_pb2.GetComponentDefRequest(
237 name='projects/chicken/componentDefs/1')
238 mc = monorailcontext.MonorailContext(
239 self.services, cnxn=self.cnxn, requester=user_1.email)
240 actual = self.CallWrapped(
241 self.projects_svcr.GetComponentDef, mc, request)
242 expected_cd = self.converter.ConvertComponentDef(component_def)
243 self.assertEqual(actual, expected_cd)
244
Copybara854996b2021-09-07 19:36:02 +0000245 @mock.patch('project.project_helpers.GetThumbnailUrl')
246 def testListProjects(self, mock_GetThumbnailUrl):
247 mock_GetThumbnailUrl.return_value = 'xyz'
248
249 request = projects_pb2.ListProjectsRequest()
250
251 mc = monorailcontext.MonorailContext(
252 self.services, cnxn=self.cnxn, requester=self.user_1.email)
253 response = self.CallWrapped(self.projects_svcr.ListProjects, mc, request)
254
255 expected_project = project_objects_pb2.Project(
256 name=self.project_1_resource_name,
257 display_name=self.project_1.project_name,
258 summary=self.project_1.summary,
259 thumbnail_url='xyz')
260
261 self.assertEqual(
262 response,
263 projects_pb2.ListProjectsResponse(projects=[expected_project]))