Copybara | 854996b | 2021-09-07 19:36:02 +0000 | [diff] [blame] | 1 | # Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 | # Use of this source code is governed by a BSD-style |
| 3 | # license that can be found in the LICENSE file or at |
| 4 | # https://developers.google.com/open-source/licenses/bsd |
| 5 | |
| 6 | """Unit tests for framework_views classes.""" |
| 7 | from __future__ import print_function |
| 8 | from __future__ import division |
| 9 | from __future__ import absolute_import |
| 10 | |
| 11 | import time |
| 12 | import unittest |
| 13 | |
| 14 | from framework import framework_constants |
| 15 | from framework import framework_views |
| 16 | from framework import monorailrequest |
| 17 | from proto import project_pb2 |
| 18 | from proto import tracker_pb2 |
| 19 | from proto import user_pb2 |
| 20 | import settings |
| 21 | from services import service_manager |
| 22 | from testing import fake |
| 23 | |
| 24 | |
| 25 | LONG_STR = 'VeryLongStringThatCertainlyWillNotFit' |
| 26 | LONG_PART_STR = 'OnePartThatWillNotFit-OneShort' |
| 27 | |
| 28 | |
| 29 | class LabelViewTest(unittest.TestCase): |
| 30 | |
| 31 | def testLabelView(self): |
| 32 | view = framework_views.LabelView('', None) |
| 33 | self.assertEqual('', view.name) |
| 34 | |
| 35 | view = framework_views.LabelView('Priority-High', None) |
| 36 | self.assertEqual('Priority-High', view.name) |
| 37 | self.assertIsNone(view.is_restrict) |
| 38 | self.assertEqual('', view.docstring) |
| 39 | self.assertEqual('Priority', view.prefix) |
| 40 | self.assertEqual('High', view.value) |
| 41 | |
| 42 | view = framework_views.LabelView('%s-%s' % (LONG_STR, LONG_STR), None) |
| 43 | self.assertEqual('%s-%s' % (LONG_STR, LONG_STR), view.name) |
| 44 | self.assertEqual('', view.docstring) |
| 45 | self.assertEqual(LONG_STR, view.prefix) |
| 46 | self.assertEqual(LONG_STR, view.value) |
| 47 | |
| 48 | view = framework_views.LabelView(LONG_PART_STR, None) |
| 49 | self.assertEqual(LONG_PART_STR, view.name) |
| 50 | self.assertEqual('', view.docstring) |
| 51 | self.assertEqual('OnePartThatWillNotFit', view.prefix) |
| 52 | self.assertEqual('OneShort', view.value) |
| 53 | |
| 54 | config = tracker_pb2.ProjectIssueConfig() |
| 55 | config.well_known_labels.append(tracker_pb2.LabelDef( |
| 56 | label='Priority-High', label_docstring='Must ship in this milestone')) |
| 57 | |
| 58 | view = framework_views.LabelView('Priority-High', config) |
| 59 | self.assertEqual('Must ship in this milestone', view.docstring) |
| 60 | |
| 61 | view = framework_views.LabelView('Priority-Foo', config) |
| 62 | self.assertEqual('', view.docstring) |
| 63 | |
| 64 | view = framework_views.LabelView('Restrict-View-Commit', None) |
| 65 | self.assertTrue(view.is_restrict) |
| 66 | |
| 67 | |
| 68 | class StatusViewTest(unittest.TestCase): |
| 69 | |
| 70 | def testStatusView(self): |
| 71 | view = framework_views.StatusView('', None) |
| 72 | self.assertEqual('', view.name) |
| 73 | |
| 74 | view = framework_views.StatusView('Accepted', None) |
| 75 | self.assertEqual('Accepted', view.name) |
| 76 | self.assertEqual('', view.docstring) |
| 77 | self.assertEqual('yes', view.means_open) |
| 78 | |
| 79 | view = framework_views.StatusView(LONG_STR, None) |
| 80 | self.assertEqual(LONG_STR, view.name) |
| 81 | self.assertEqual('', view.docstring) |
| 82 | self.assertEqual('yes', view.means_open) |
| 83 | |
| 84 | config = tracker_pb2.ProjectIssueConfig() |
| 85 | config.well_known_statuses.append(tracker_pb2.StatusDef( |
| 86 | status='SlamDunk', status_docstring='Code fixed and taught a lesson', |
| 87 | means_open=False)) |
| 88 | |
| 89 | view = framework_views.StatusView('SlamDunk', config) |
| 90 | self.assertEqual('Code fixed and taught a lesson', view.docstring) |
| 91 | self.assertFalse(view.means_open) |
| 92 | |
| 93 | view = framework_views.StatusView('SlammedBack', config) |
| 94 | self.assertEqual('', view.docstring) |
| 95 | |
| 96 | |
| 97 | class UserViewTest(unittest.TestCase): |
| 98 | |
| 99 | def setUp(self): |
| 100 | self.user = user_pb2.User(user_id=111) |
| 101 | |
| 102 | def testGetAvailablity_Anon(self): |
| 103 | self.user.user_id = 0 |
| 104 | user_view = framework_views.UserView(self.user) |
| 105 | self.assertEqual(None, user_view.avail_message) |
| 106 | self.assertEqual(None, user_view.avail_state) |
| 107 | |
| 108 | def testGetAvailablity_Banned(self): |
| 109 | self.user.banned = 'spamming' |
| 110 | user_view = framework_views.UserView(self.user) |
| 111 | self.assertEqual('Banned', user_view.avail_message) |
| 112 | self.assertEqual('banned', user_view.avail_state) |
| 113 | |
| 114 | def testGetAvailablity_Vacation(self): |
| 115 | self.user.vacation_message = 'gone fishing' |
| 116 | user_view = framework_views.UserView(self.user) |
| 117 | self.assertEqual('gone fishing', user_view.avail_message) |
| 118 | self.assertEqual('none', user_view.avail_state) |
| 119 | |
| 120 | self.user.vacation_message = ( |
| 121 | 'Gone fishing as really long time with lots of friends and reading ' |
| 122 | 'a long novel by a famous author. I wont have internet access but ' |
| 123 | 'If you urgently need anything you can call Alice or Bob for most ' |
| 124 | 'things otherwise call Charlie. Wish me luck! ') |
| 125 | user_view = framework_views.UserView(self.user) |
| 126 | self.assertTrue(len(user_view.avail_message) >= 50) |
| 127 | self.assertTrue(len(user_view.avail_message_short) < 50) |
| 128 | self.assertEqual('none', user_view.avail_state) |
| 129 | |
| 130 | def testGetAvailablity_Bouncing(self): |
| 131 | self.user.email_bounce_timestamp = 1234567890 |
| 132 | user_view = framework_views.UserView(self.user) |
| 133 | self.assertEqual('Email to this user bounced', user_view.avail_message) |
| 134 | self.assertEqual(user_view.avail_message_short, user_view.avail_message) |
| 135 | self.assertEqual('none', user_view.avail_state) |
| 136 | |
| 137 | def testGetAvailablity_Groups(self): |
| 138 | user_view = framework_views.UserView(self.user, is_group=True) |
| 139 | self.assertEqual(None, user_view.avail_message) |
| 140 | self.assertEqual(None, user_view.avail_state) |
| 141 | |
| 142 | self.user.email = 'likely-user-group@example.com' |
| 143 | user_view = framework_views.UserView(self.user) |
| 144 | self.assertEqual(None, user_view.avail_message) |
| 145 | self.assertEqual(None, user_view.avail_state) |
| 146 | |
| 147 | def testGetAvailablity_NeverVisitied(self): |
| 148 | self.user.last_visit_timestamp = 0 |
| 149 | user_view = framework_views.UserView(self.user) |
| 150 | self.assertEqual('User never visited', user_view.avail_message) |
| 151 | self.assertEqual('never', user_view.avail_state) |
| 152 | |
| 153 | def testGetAvailablity_NotRecent(self): |
| 154 | now = int(time.time()) |
| 155 | self.user.last_visit_timestamp = now - 20 * framework_constants.SECS_PER_DAY |
| 156 | user_view = framework_views.UserView(self.user) |
| 157 | self.assertEqual('Last visit 20 days ago', user_view.avail_message) |
| 158 | self.assertEqual('unsure', user_view.avail_state) |
| 159 | |
| 160 | def testGetAvailablity_ReallyLongTime(self): |
| 161 | now = int(time.time()) |
| 162 | self.user.last_visit_timestamp = now - 99 * framework_constants.SECS_PER_DAY |
| 163 | user_view = framework_views.UserView(self.user) |
| 164 | self.assertEqual('Last visit > 30 days ago', user_view.avail_message) |
| 165 | self.assertEqual('none', user_view.avail_state) |
| 166 | |
| 167 | def testDeletedUser(self): |
| 168 | deleted_user = user_pb2.User(user_id=1) |
| 169 | user_view = framework_views.UserView(deleted_user) |
| 170 | self.assertEqual( |
| 171 | user_view.display_name, framework_constants.DELETED_USER_NAME) |
| 172 | self.assertEqual(user_view.email, '') |
| 173 | self.assertEqual(user_view.obscure_email, '') |
| 174 | self.assertEqual(user_view.profile_url, '') |
| 175 | |
| 176 | class RevealEmailsToMembersTest(unittest.TestCase): |
| 177 | |
| 178 | def setUp(self): |
| 179 | self.cnxn = fake.MonorailConnection() |
| 180 | self.services = service_manager.Services( |
| 181 | project=fake.ProjectService(), |
| 182 | user=fake.UserService(), |
| 183 | usergroup=fake.UserGroupService()) |
| 184 | self.mr = monorailrequest.MonorailRequest(None) |
| 185 | self.mr.project = self.services.project.TestAddProject( |
| 186 | 'proj', |
| 187 | project_id=789, |
| 188 | owner_ids=[111], |
| 189 | committer_ids=[222], |
| 190 | contrib_ids=[333, 888]) |
| 191 | user = self.services.user.TestAddUser('test@example.com', 1000) |
| 192 | self.mr.auth.user_pb = user |
| 193 | |
| 194 | def CheckRevealAllToMember( |
| 195 | self, logged_in_user_id, expected, viewed_user_id=333, group_id=None): |
| 196 | user_view = framework_views.StuffUserView( |
| 197 | viewed_user_id, 'user@example.com', True) |
| 198 | |
| 199 | if group_id: |
| 200 | pass # xxx re-implement groups |
| 201 | |
| 202 | users_by_id = {333: user_view} |
| 203 | self.mr.auth.user_id = logged_in_user_id |
| 204 | self.mr.auth.effective_ids = {logged_in_user_id} |
| 205 | # Assert display name is obscured before the reveal. |
| 206 | self.assertEqual('u...@example.com', user_view.display_name) |
| 207 | # Assert profile url contains user ID before the reveal. |
| 208 | self.assertEqual('/u/%s/' % viewed_user_id, user_view.profile_url) |
| 209 | framework_views.RevealAllEmailsToMembers( |
| 210 | self.cnxn, self.services, self.mr.auth, users_by_id) |
| 211 | self.assertEqual(expected, not user_view.obscure_email) |
| 212 | if expected: |
| 213 | # Assert display name is now revealed. |
| 214 | self.assertEqual('user@example.com', user_view.display_name) |
| 215 | # Assert profile url contains the email. |
| 216 | self.assertEqual('/u/user@example.com/', user_view.profile_url) |
| 217 | else: |
| 218 | # Assert display name is still hidden. |
| 219 | self.assertEqual('u...@example.com', user_view.display_name) |
| 220 | # Assert profile url still contains user ID. |
| 221 | self.assertEqual('/u/%s/' % viewed_user_id, user_view.profile_url) |
| 222 | |
| 223 | # TODO(https://crbug.com/monorail/8192): Remove this method and related test. |
| 224 | def DeprecatedCheckRevealAllToMember( |
| 225 | self, logged_in_user_id, expected, viewed_user_id=333, group_id=None): |
| 226 | user_view = framework_views.StuffUserView( |
| 227 | viewed_user_id, 'user@example.com', True) |
| 228 | |
| 229 | if group_id: |
| 230 | pass # xxx re-implement groups |
| 231 | |
| 232 | users_by_id = {333: user_view} |
| 233 | self.mr.auth.user_id = logged_in_user_id |
| 234 | self.mr.auth.effective_ids = {logged_in_user_id} |
| 235 | # Assert display name is obscured before the reveal. |
| 236 | self.assertEqual('u...@example.com', user_view.display_name) |
| 237 | # Assert profile url contains user ID before the reveal. |
| 238 | self.assertEqual('/u/%s/' % viewed_user_id, user_view.profile_url) |
| 239 | framework_views.RevealAllEmailsToMembers( |
| 240 | self.cnxn, self.services, self.mr.auth, users_by_id, self.mr.project) |
| 241 | self.assertEqual(expected, not user_view.obscure_email) |
| 242 | if expected: |
| 243 | # Assert display name is now revealed. |
| 244 | self.assertEqual('user@example.com', user_view.display_name) |
| 245 | # Assert profile url contains the email. |
| 246 | self.assertEqual('/u/user@example.com/', user_view.profile_url) |
| 247 | else: |
| 248 | # Assert display name is still hidden. |
| 249 | self.assertEqual('u...@example.com', user_view.display_name) |
| 250 | # Assert profile url still contains user ID. |
| 251 | self.assertEqual('/u/%s/' % viewed_user_id, user_view.profile_url) |
| 252 | |
| 253 | def testDontRevealEmailsToPriviledgedDomain(self): |
| 254 | """We no longer give this advantage based on email address domain.""" |
| 255 | for priviledged_user_domain in settings.priviledged_user_domains: |
| 256 | self.mr.auth.user_pb.email = 'test@' + priviledged_user_domain |
| 257 | self.CheckRevealAllToMember(100001, False) |
| 258 | |
| 259 | def testRevealEmailToSelf(self): |
| 260 | logged_in_user = self.services.user.TestAddUser('user@example.com', 333) |
| 261 | self.mr.auth.user_pb = logged_in_user |
| 262 | self.CheckRevealAllToMember(333, True) |
| 263 | |
| 264 | def testRevealAllEmailsToMembers_Collaborators(self): |
| 265 | self.CheckRevealAllToMember(0, False) |
| 266 | self.CheckRevealAllToMember(111, True) |
| 267 | self.CheckRevealAllToMember(222, True) |
| 268 | self.CheckRevealAllToMember(333, True) |
| 269 | self.CheckRevealAllToMember(444, False) |
| 270 | |
| 271 | # Viewed user has indirect role in the project via a group. |
| 272 | self.CheckRevealAllToMember(0, False, group_id=888) |
| 273 | self.CheckRevealAllToMember(111, True, group_id=888) |
| 274 | # xxx re-implement |
| 275 | # self.CheckRevealAllToMember( |
| 276 | # 111, True, viewed_user_id=444, group_id=888) |
| 277 | |
| 278 | # Logged in user has indirect role in the project via a group. |
| 279 | self.CheckRevealAllToMember(888, True) |
| 280 | |
| 281 | def testDeprecatedRevealAllEmailsToMembers_Collaborators(self): |
| 282 | self.DeprecatedCheckRevealAllToMember(0, False) |
| 283 | self.DeprecatedCheckRevealAllToMember(111, True) |
| 284 | self.DeprecatedCheckRevealAllToMember(222, True) |
| 285 | self.DeprecatedCheckRevealAllToMember(333, True) |
| 286 | self.DeprecatedCheckRevealAllToMember(444, False) |
| 287 | |
| 288 | # Viewed user has indirect role in the project via a group. |
| 289 | self.DeprecatedCheckRevealAllToMember(0, False, group_id=888) |
| 290 | self.DeprecatedCheckRevealAllToMember(111, True, group_id=888) |
| 291 | |
| 292 | # Logged in user has indirect role in the project via a group. |
| 293 | self.DeprecatedCheckRevealAllToMember(888, True) |
| 294 | |
| 295 | def testRevealAllEmailsToMembers_Admins(self): |
| 296 | self.CheckRevealAllToMember(555, False) |
| 297 | self.mr.auth.user_pb.is_site_admin = True |
| 298 | self.CheckRevealAllToMember(555, True) |
| 299 | |
| 300 | |
| 301 | class RevealAllEmailsTest(unittest.TestCase): |
| 302 | |
| 303 | def testRevealAllEmail(self): |
| 304 | users_by_id = { |
| 305 | 111: framework_views.StuffUserView(111, 'a@a.com', True), |
| 306 | 222: framework_views.StuffUserView(222, 'b@b.com', True), |
| 307 | 333: framework_views.StuffUserView(333, 'c@c.com', True), |
| 308 | 999: framework_views.StuffUserView(999, 'z@z.com', True), |
| 309 | } |
| 310 | # Assert display names are obscured before the reveal. |
| 311 | self.assertEqual('a...@a.com', users_by_id[111].display_name) |
| 312 | self.assertEqual('b...@b.com', users_by_id[222].display_name) |
| 313 | self.assertEqual('c...@c.com', users_by_id[333].display_name) |
| 314 | self.assertEqual('z...@z.com', users_by_id[999].display_name) |
| 315 | |
| 316 | framework_views.RevealAllEmails(users_by_id) |
| 317 | |
| 318 | self.assertFalse(users_by_id[111].obscure_email) |
| 319 | self.assertFalse(users_by_id[222].obscure_email) |
| 320 | self.assertFalse(users_by_id[333].obscure_email) |
| 321 | self.assertFalse(users_by_id[999].obscure_email) |
| 322 | # Assert display names are now revealed. |
| 323 | self.assertEqual('a@a.com', users_by_id[111].display_name) |
| 324 | self.assertEqual('b@b.com', users_by_id[222].display_name) |
| 325 | self.assertEqual('c@c.com', users_by_id[333].display_name) |
| 326 | self.assertEqual('z@z.com', users_by_id[999].display_name) |