Merge branch 'main' into avm99963-monorail

Merged commit 34d8229ae2b51fb1a15bd208e6fe6185c94f6266

GitOrigin-RevId: 7ee0917f93a577e475f8e09526dd144d245593f4
diff --git a/services/test/star_svc_test.py b/services/test/star_svc_test.py
index 3a5ce74..d3b4cea 100644
--- a/services/test/star_svc_test.py
+++ b/services/test/star_svc_test.py
@@ -1,13 +1,13 @@
-# 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 star service."""
 from __future__ import print_function
 from __future__ import division
 from __future__ import absolute_import
 
+import six
 import unittest
 
 try:
@@ -15,13 +15,13 @@
 except ImportError:
   import mox
 import mock
+import time
 
 from google.appengine.ext import testbed
 
-import settings
 from mock import Mock
 from framework import sql
-from proto import user_pb2
+from services import service_manager
 from services import star_svc
 from testing import fake
 
@@ -78,13 +78,13 @@
     starrer_list_dict = self.star_service.LookupItemsStarrers(
         self.cnxn, [123, 234])
     self.mox.VerifyAll()
-    self.assertItemsEqual([123, 234], list(starrer_list_dict.keys()))
-    self.assertItemsEqual([111, 333], starrer_list_dict[123])
-    self.assertItemsEqual([111, 222], starrer_list_dict[234])
-    self.assertItemsEqual([111, 333],
-                          self.star_service.starrer_cache.GetItem(123))
-    self.assertItemsEqual([111, 222],
-                          self.star_service.starrer_cache.GetItem(234))
+    six.assertCountEqual(self, [123, 234], list(starrer_list_dict.keys()))
+    six.assertCountEqual(self, [111, 333], starrer_list_dict[123])
+    six.assertCountEqual(self, [111, 222], starrer_list_dict[234])
+    six.assertCountEqual(
+        self, [111, 333], self.star_service.starrer_cache.GetItem(123))
+    six.assertCountEqual(
+        self, [111, 222], self.star_service.starrer_cache.GetItem(234))
 
   def SetUpLookupStarredItemIDs(self):
     self.mock_tbl.Select(
@@ -96,9 +96,9 @@
     self.mox.ReplayAll()
     item_ids = self.star_service.LookupStarredItemIDs(self.cnxn, 111)
     self.mox.VerifyAll()
-    self.assertItemsEqual([123, 234], item_ids)
-    self.assertItemsEqual([123, 234],
-                          self.star_service.star_cache.GetItem(111))
+    six.assertCountEqual(self, [123, 234], item_ids)
+    six.assertCountEqual(
+        self, [123, 234], self.star_service.star_cache.GetItem(111))
 
   def testIsItemStarredBy(self):
     self.SetUpLookupStarredItemIDs()
@@ -129,7 +129,7 @@
     count_dict = self.star_service.CountItemsStars(
         self.cnxn, [123, 234])
     self.mox.VerifyAll()
-    self.assertItemsEqual([123, 234], list(count_dict.keys()))
+    six.assertCountEqual(self, [123, 234], list(count_dict.keys()))
     self.assertEqual(3, count_dict[123])
     self.assertEqual(2, count_dict[234])
 
@@ -189,17 +189,86 @@
 class IssueStarServiceTest(unittest.TestCase):
 
   def setUp(self):
-    self.mock_tbl = mock.Mock()
+    self.mox = mox.Mox()
+    self.mock_tbl = self.mox.CreateMock(sql.SQLTableManager)
     self.mock_tbl.Delete = mock.Mock()
     self.mock_tbl.InsertRows = mock.Mock()
 
+    self.mock_issue_tbl = self.mox.CreateMock(sql.SQLTableManager)
+
+    self.services = service_manager.Services()
+    self.services.issue = fake.IssueService()
+    self.services.config = fake.ConfigService()
+    self.services.features = fake.FeaturesService()
+
     self.cache_manager = fake.CacheManager()
     with mock.patch(
         'framework.sql.SQLTableManager', return_value=self.mock_tbl):
       self.issue_star = star_svc.IssueStarService(
           self.cache_manager)
+      self.issue_star.issue_tbl = self.mock_issue_tbl
 
     self.cnxn = 'fake connection'
+    self.now = int(time.time())
+
+  def testExpungeStarsByUsers(self):
+    self.mock_tbl.Select = mock.Mock(return_value=[(78901,), (78902,)])
+    self.mock_issue_tbl.Update = mock.Mock()
+
+    user_ids = [2, 3, 4]
+
+    self.mox.ReplayAll()
+    self.issue_star.ExpungeStarsByUsers(self.cnxn, user_ids, limit=40)
+    self.mox.VerifyAll()
+
+    self.mock_tbl.Select.assert_called_once_with(
+        self.cnxn,
+        cols=['IssueStar.issue_id'],
+        user_id=user_ids,
+        shard_id=mox.IgnoreArg(),
+        limit=40)
+    self.mock_tbl.Delete.assert_called_once_with(
+        self.cnxn, user_id=user_ids, commit=False, limit=40)
+    self.mock_issue_tbl.Update.assert_called_once_with(
+        self.cnxn, {'migration_modified': self.now},
+        id=[78901, 78902],
+        commit=False,
+        limit=40)
+
+  def testSetStarsBatch_Add(self):
+    issue = fake.MakeTestIssue(
+        project_id=789,
+        local_id=1,
+        reporter_id=111,
+        owner_id=456,
+        summary='sum',
+        status='Live',
+        issue_id=78901,
+        project_name='proj',
+        migration_modified_timestamp=1234567)
+    self.services.issue.TestAddIssue(issue)
+    config = self.services.config.GetProjectConfig(self.cnxn, 789)
+
+    # Set up mock for getting counts.
+    self.mock_tbl.Select(
+        self.cnxn,
+        cols=['issue_id', 'COUNT(user_id)'],
+        group_by=['issue_id'],
+        issue_id=[78901]).AndReturn([(78901, 2)])
+    self.mox.ReplayAll()
+
+    self.issue_star.SetStarsBatch(
+        self.cnxn, self.services, config, 78901, [111, 222], True)
+
+    self.mox.VerifyAll()
+    self.mock_tbl.InsertRows.assert_called_once_with(
+        self.cnxn, ['issue_id', 'user_id'], [(78901, 111), (78901, 222)],
+        ignore=True,
+        commit=True)
+
+    self.assertIn(issue, self.services.issue.updated_issues)
+    self.assertEqual(issue.migration_modified_timestamp, self.now)
+    self.assertEqual(issue.star_count, 2)
 
   def testSetStarsBatch_SkipIssueUpdate_Remove(self):
     self.issue_star.SetStarsBatch_SkipIssueUpdate(