Merge branch 'main' into avm99963-monorail

Merged commit 3779da353b36d43cf778e7d4f468097714dd4540

GitOrigin-RevId: 6451a5c6b75afb0fd1f37b3f14521148d0722ea8
diff --git a/features/test/activities_test.py b/features/test/activities_test.py
index 4eae1ab..c17eb4b 100644
--- a/features/test/activities_test.py
+++ b/features/test/activities_test.py
@@ -10,7 +10,10 @@
 
 import unittest
 
-import mox
+try:
+  from mox3 import mox
+except ImportError:
+  import mox
 
 from features import activities
 from framework import framework_views
diff --git a/features/test/alert2issue_test.py b/features/test/alert2issue_test.py
index 3b1b6d1..2046b5b 100644
--- a/features/test/alert2issue_test.py
+++ b/features/test/alert2issue_test.py
@@ -11,7 +11,10 @@
 import email
 import unittest
 from mock import patch
-import mox
+try:
+  from mox3 import mox
+except ImportError:
+  import mox
 from parameterized import parameterized
 
 from features import alert2issue
diff --git a/features/test/banspammer_test.py b/features/test/banspammer_test.py
index edf7aba..e12c506 100644
--- a/features/test/banspammer_test.py
+++ b/features/test/banspammer_test.py
@@ -10,10 +10,8 @@
 
 import json
 import mock
-import os
 import unittest
 from six.moves import urllib
-import webapp2
 
 import settings
 from features import banspammer
@@ -35,7 +33,7 @@
         project=fake.ProjectService(),
         spam=fake.SpamService(),
         user=fake.UserService())
-    self.servlet = banspammer.BanSpammer('req', 'res', services=self.services)
+    self.servlet = banspammer.BanSpammer(services=self.services)
 
   @mock.patch('framework.cloud_tasks_helpers._get_client')
   def testProcessFormData_noPermission(self, get_client_mock):
@@ -92,17 +90,15 @@
     self.services = service_manager.Services(
         issue=fake.IssueService(),
         spam=fake.SpamService())
-    self.res = webapp2.Response()
-    self.servlet = banspammer.BanSpammerTask('req', self.res,
-        services=self.services)
+    self.servlet = banspammer.BanSpammerTask(services=self.services)
 
   def testProcessFormData_okNoIssues(self):
     mr = testing_helpers.MakeMonorailRequest(
         path=urls.BAN_SPAMMER_TASK + '.do', method='POST',
         params={'spammer_id': 111, 'reporter_id': 222})
 
-    self.servlet.HandleRequest(mr)
-    self.assertEqual(self.res.body, json.dumps({'comments': 0, 'issues': 0}))
+    res = self.servlet.HandleRequest(mr)
+    self.assertEqual(res, json.dumps({'comments': 0, 'issues': 0}))
 
   def testProcessFormData_okSomeIssues(self):
     mr = testing_helpers.MakeMonorailRequest(
@@ -114,8 +110,8 @@
           1, i, 'issue_summary', 'New', 111, project_name='project-name')
       self.servlet.services.issue.TestAddIssue(issue)
 
-    self.servlet.HandleRequest(mr)
-    self.assertEqual(self.res.body, json.dumps({'comments': 0, 'issues': 10}))
+    res = self.servlet.HandleRequest(mr)
+    self.assertEqual(res, json.dumps({'comments': 0, 'issues': 10}))
 
   def testProcessFormData_okSomeCommentsAndIssues(self):
     mr = testing_helpers.MakeMonorailRequest(
@@ -137,5 +133,5 @@
         comment.user_id = 111
         comment.issue_id = issue.issue_id
         self.servlet.services.issue.TestAddComment(comment, issue.local_id)
-    self.servlet.HandleRequest(mr)
-    self.assertEqual(self.res.body, json.dumps({'comments': 50, 'issues': 10}))
+    res = self.servlet.HandleRequest(mr)
+    self.assertEqual(res, json.dumps({'comments': 50, 'issues': 10}))
diff --git a/features/test/dateaction_test.py b/features/test/dateaction_test.py
index 09e5c5c..8ca5bc3 100644
--- a/features/test/dateaction_test.py
+++ b/features/test/dateaction_test.py
@@ -36,8 +36,7 @@
     self.services = service_manager.Services(
         user=fake.UserService(),
         issue=fake.IssueService())
-    self.servlet = dateaction.DateActionCron(
-        'req', 'res', services=self.services)
+    self.servlet = dateaction.DateActionCron(services=self.services)
     self.TIMESTAMP_MIN = (
         NOW // framework_constants.SECS_PER_DAY *
         framework_constants.SECS_PER_DAY)
@@ -128,8 +127,7 @@
         project=fake.ProjectService(),
         config=fake.ConfigService(),
         issue_star=fake.IssueStarService())
-    self.servlet = dateaction.IssueDateActionTask(
-        'req', 'res', services=self.services)
+    self.servlet = dateaction.IssueDateActionTask(services=self.services)
 
     self.config = self.services.config.GetProjectConfig('cnxn', 789)
     self.config.field_defs = [
diff --git a/features/test/hotlistcreate_test.py b/features/test/hotlistcreate_test.py
index 8cf0012..e6cda4b 100644
--- a/features/test/hotlistcreate_test.py
+++ b/features/test/hotlistcreate_test.py
@@ -8,7 +8,10 @@
 from __future__ import division
 from __future__ import absolute_import
 
-import mox
+try:
+  from mox3 import mox
+except ImportError:
+  import mox
 import unittest
 
 import settings
@@ -30,8 +33,7 @@
                                         user=fake.UserService(),
                                              issue=fake.IssueService(),
                                              features=fake.FeaturesService())
-    self.servlet = hotlistcreate.HotlistCreate('req', 'res',
-                                               services=self.services)
+    self.servlet = hotlistcreate.HotlistCreate(services=self.services)
     self.mox = mox.Mox()
 
   def tearDown(self):
diff --git a/features/test/hotlistdetails_test.py b/features/test/hotlistdetails_test.py
index 9a9e53f..561199c 100644
--- a/features/test/hotlistdetails_test.py
+++ b/features/test/hotlistdetails_test.py
@@ -9,7 +9,10 @@
 from __future__ import absolute_import
 
 import logging
-import mox
+try:
+  from mox3 import mox
+except ImportError:
+  import mox
 import unittest
 import mock
 
diff --git a/features/test/hotlistissues_test.py b/features/test/hotlistissues_test.py
index 49c3270..265c9d1 100644
--- a/features/test/hotlistissues_test.py
+++ b/features/test/hotlistissues_test.py
@@ -8,7 +8,10 @@
 from __future__ import division
 from __future__ import absolute_import
 
-import mox
+try:
+  from mox3 import mox
+except ImportError:
+  import mox
 import mock
 import unittest
 import time
diff --git a/features/test/hotlistpeople_test.py b/features/test/hotlistpeople_test.py
index 74beec3..3ee7925 100644
--- a/features/test/hotlistpeople_test.py
+++ b/features/test/hotlistpeople_test.py
@@ -8,7 +8,10 @@
 from __future__ import division
 from __future__ import absolute_import
 
-import mox
+try:
+  from mox3 import mox
+except ImportError:
+  import mox
 import unittest
 import logging
 
diff --git a/features/test/inboundemail_test.py b/features/test/inboundemail_test.py
index 0eaa281..de05749 100644
--- a/features/test/inboundemail_test.py
+++ b/features/test/inboundemail_test.py
@@ -9,14 +9,14 @@
 from __future__ import absolute_import
 
 import unittest
-import webapp2
-from mock import patch
 
-import mox
+try:
+  from mox3 import mox
+except ImportError:
+  import mox
 import time
 
 from google.appengine.api import mail
-from google.appengine.ext.webapp.mail_handlers import BounceNotificationHandler
 
 import settings
 from businesslogic import work_env
@@ -58,8 +58,7 @@
     self.msg = testing_helpers.MakeMessage(
         testing_helpers.HEADER_LINES, 'awesome!')
 
-    request, _ = testing_helpers.GetRequestObjects()
-    self.inbound = inboundemail.InboundEmail(request, None, self.services)
+    self.inbound = inboundemail.InboundEmail(self.services)
     self.mox = mox.Mox()
 
   def tearDown(self):
@@ -348,10 +347,7 @@
         user=fake.UserService())
     self.user = self.services.user.TestAddUser('user@example.com', 111)
 
-    app = webapp2.WSGIApplication(config={'services': self.services})
-    app.set_globals(app=app)
-
-    self.servlet = inboundemail.BouncedEmail()
+    self.servlet = inboundemail.BouncedEmail(self.services)
     self.mox = mox.Mox()
 
   def tearDown(self):
@@ -369,8 +365,6 @@
 
   def testReceive_NoSuchUser(self):
     """When not found, log it and ignore without creating a user record."""
-    self.servlet.request = webapp2.Request.blank(
-        '/', POST={'raw-message': 'this is an email message'})
     bounce_message = testing_helpers.Blank(
         original={'to': 'nope@example.com'},
         notification='notification')
diff --git a/features/test/notify_test.py b/features/test/notify_test.py
index 9ddcce7..e73488d 100644
--- a/features/test/notify_test.py
+++ b/features/test/notify_test.py
@@ -11,7 +11,7 @@
 import json
 import mock
 import unittest
-import webapp2
+import flask
 
 from google.appengine.ext import testbed
 
@@ -63,7 +63,13 @@
     self.orig_sign_attachment_id = attachment_helpers.SignAttachmentID
     attachment_helpers.SignAttachmentID = (
         lambda aid: 'signed_%d' % aid)
-
+    self.servlet = notify.OutboundEmailTask(services=self.services)
+    self.app = flask.Flask('test_app')
+    self.app.config['TESTING'] = True
+    self.app.add_url_rule(
+        '/_task/outboundEmail.do',
+        view_func=self.servlet.PostOutboundEmailTask,
+        methods=['POST'])
     self.testbed = testbed.Testbed()
     self.testbed.activate()
     self.testbed.init_memcache_stub()
@@ -89,8 +95,7 @@
                        result['params']['issue_ids'])
 
   def testNotifyIssueChangeTask_Normal(self):
-    task = notify.NotifyIssueChangeTask(
-        request=None, response=None, services=self.services)
+    task = notify.NotifyIssueChangeTask(services=self.services)
     params = {'send_email': 1, 'issue_id': 12345001, 'seq': 0,
               'commenter_id': 2}
     mr = testing_helpers.MakeMonorailRequest(
@@ -107,8 +112,7 @@
         project_id=12345, local_id=1, owner_id=1, reporter_id=1,
         is_spam=True)
     self.services.issue.TestAddIssue(issue)
-    task = notify.NotifyIssueChangeTask(
-        request=None, response=None, services=self.services)
+    task = notify.NotifyIssueChangeTask(services=self.services)
     params = {'send_email': 0, 'issue_id': issue.issue_id, 'seq': 0,
               'commenter_id': 2}
     mr = testing_helpers.MakeMonorailRequest(
@@ -124,8 +128,7 @@
     issue2 = MakeTestIssue(
         project_id=12345, local_id=2, owner_id=2, reporter_id=1)
     self.services.issue.TestAddIssue(issue2)
-    task = notify.NotifyBlockingChangeTask(
-        request=None, response=None, services=self.services)
+    task = notify.NotifyBlockingChangeTask(services=self.services)
     params = {
         'send_email': 1, 'issue_id': issue2.issue_id, 'seq': 0,
         'delta_blocker_iids': self.issue1.issue_id, 'commenter_id': 1,
@@ -143,8 +146,7 @@
         project_id=12345, local_id=2, owner_id=2, reporter_id=1,
         is_spam=True)
     self.services.issue.TestAddIssue(issue2)
-    task = notify.NotifyBlockingChangeTask(
-        request=None, response=None, services=self.services)
+    task = notify.NotifyBlockingChangeTask(services=self.services)
     params = {
         'send_email': 1, 'issue_id': issue2.issue_id, 'seq': 0,
         'delta_blocker_iids': self.issue1.issue_id, 'commenter_id': 1}
@@ -163,8 +165,7 @@
         project_id=12345, local_id=2, owner_id=2, reporter_id=1)
     issue2.cc_ids = [3]
     self.services.issue.TestAddIssue(issue2)
-    task = notify.NotifyBulkChangeTask(
-        request=None, response=None, services=self.services)
+    task = notify.NotifyBulkChangeTask(services=self.services)
     params = {
         'send_email': 1, 'seq': 0,
         'issue_ids': '%d,%d' % (self.issue1.issue_id, issue2.issue_id),
@@ -195,8 +196,7 @@
     """We generate email tasks for also-notify addresses."""
     self.issue1.derived_notify_addrs = [
         'mailing-list@example.com', 'member@example.com']
-    task = notify.NotifyBulkChangeTask(
-        request=None, response=None, services=self.services)
+    task = notify.NotifyBulkChangeTask(services=self.services)
     params = {
         'send_email': 1, 'seq': 0,
         'issue_ids': '%d' % (self.issue1.issue_id),
@@ -230,8 +230,7 @@
   def testNotifyBulkChangeTask_ProjectNotify(self, create_task_mock):
     """We generate email tasks for project.issue_notify_address."""
     self.project.issue_notify_address = 'mailing-list@example.com'
-    task = notify.NotifyBulkChangeTask(
-        request=None, response=None, services=self.services)
+    task = notify.NotifyBulkChangeTask(services=self.services)
     params = {
         'send_email': 1, 'seq': 0,
         'issue_ids': '%d' % (self.issue1.issue_id),
@@ -265,8 +264,7 @@
   @mock.patch('framework.cloud_tasks_helpers.create_task')
   def testNotifyBulkChangeTask_SubscriberGetsEmail(self, create_task_mock):
     """If a user subscription matches the issue, notify that user."""
-    task = notify.NotifyBulkChangeTask(
-        request=None, response=None, services=self.services)
+    task = notify.NotifyBulkChangeTask(services=self.services)
     params = {
         'send_email': 1,
         'issue_ids': '%d' % (self.issue1.issue_id),
@@ -293,8 +291,7 @@
   def testNotifyBulkChangeTask_CCAndSubscriberListsIssueOnce(
       self, create_task_mock):
     """If a user both CCs and subscribes, include issue only once."""
-    task = notify.NotifyBulkChangeTask(
-        request=None, response=None, services=self.services)
+    task = notify.NotifyBulkChangeTask(services=self.services)
     params = {
         'send_email': 1,
         'issue_ids': '%d' % (self.issue1.issue_id),
@@ -335,8 +332,7 @@
         project_id=12345, local_id=2, owner_id=2, reporter_id=1,
         is_spam=True)
     self.services.issue.TestAddIssue(issue2)
-    task = notify.NotifyBulkChangeTask(
-        request=None, response=None, services=self.services)
+    task = notify.NotifyBulkChangeTask(services=self.services)
     params = {
         'send_email': 1,
         'issue_ids': '%d,%d' % (self.issue1.issue_id, issue2.issue_id),
@@ -353,8 +349,7 @@
   def testFormatBulkIssues_Normal_Single(self):
     """A user may see full notification details for all changed issues."""
     self.issue1.summary = 'one summary'
-    task = notify.NotifyBulkChangeTask(
-        request=None, response=None, services=self.services)
+    task = notify.NotifyBulkChangeTask(services=self.services)
     users_by_id = {}
     commenter_view = None
     config = self.services.config.GetProjectConfig('cnxn', 12345)
@@ -374,8 +369,7 @@
     """A user may see full notification details for all changed issues."""
     self.issue1.summary = 'one summary'
     self.issue2.summary = 'two summary'
-    task = notify.NotifyBulkChangeTask(
-        request=None, response=None, services=self.services)
+    task = notify.NotifyBulkChangeTask(services=self.services)
     users_by_id = {}
     commenter_view = None
     config = self.services.config.GetProjectConfig('cnxn', 12345)
@@ -396,8 +390,7 @@
     """A user may not see full notification details for some changed issue."""
     self.issue1.summary = 'one summary'
     self.issue1.labels = ['Restrict-View-Google']
-    task = notify.NotifyBulkChangeTask(
-        request=None, response=None, services=self.services)
+    task = notify.NotifyBulkChangeTask(services=self.services)
     users_by_id = {}
     commenter_view = None
     config = self.services.config.GetProjectConfig('cnxn', 12345)
@@ -419,8 +412,7 @@
     self.issue1.summary = 'one summary'
     self.issue1.labels = ['Restrict-View-Google']
     self.issue2.summary = 'two summary'
-    task = notify.NotifyBulkChangeTask(
-        request=None, response=None, services=self.services)
+    task = notify.NotifyBulkChangeTask(services=self.services)
     users_by_id = {}
     commenter_view = None
     config = self.services.config.GetProjectConfig('cnxn', 12345)
@@ -522,8 +514,7 @@
     self.services.issue.TestAddAttachment(
         attach, comment.id, approval_issue.issue_id)
 
-    task = notify.NotifyApprovalChangeTask(
-        request=None, response=None, services=self.services)
+    task = notify.NotifyApprovalChangeTask(services=self.services)
     params = {
         'send_email': 1,
         'issue_id': approval_issue.issue_id,
@@ -556,8 +547,7 @@
         project_id=12345, user_id=999, issue_id=approval_issue.issue_id,
         amendments=[amend2], timestamp=1234567891, content='')
     self.services.issue.TestAddComment(comment2, approval_issue.local_id)
-    task = notify.NotifyApprovalChangeTask(
-        request=None, response=None, services=self.services)
+    task = notify.NotifyApprovalChangeTask(services=self.services)
     params = {
         'send_email': 1,
         'issue_id': approval_issue.issue_id,
@@ -579,8 +569,7 @@
         result['notified'])
 
   def testNotifyApprovalChangeTask_GetApprovalEmailRecipients(self):
-    task = notify.NotifyApprovalChangeTask(
-        request=None, response=None, services=self.services)
+    task = notify.NotifyApprovalChangeTask(services=self.services)
     issue = fake.MakeTestIssue(789, 1, 'summary', 'New', 111)
     approval_value = tracker_pb2.ApprovalValue(
         approver_ids=[222, 333],
@@ -625,8 +614,7 @@
         'proj', owner_ids=[777, 888], project_id=789)
     self.services.user.TestAddUser('owner1@test.com', 777)
     self.services.user.TestAddUser('cow@test.com', 888)
-    task = notify.NotifyRulesDeletedTask(
-        request=None, response=None, services=self.services)
+    task = notify.NotifyRulesDeletedTask(services=self.services)
     params = {'project_id': 789,
               'filter_rules': 'if green make yellow,if orange make blue'}
     mr = testing_helpers.MakeMonorailRequest(
@@ -649,18 +637,12 @@
         'reply_to': 'user@example.com',
         'to': 'user@example.com',
         'subject': 'Test subject'}
-    body = json.dumps(params)
-    request = webapp2.Request.blank('/', body=body)
-    task = notify.OutboundEmailTask(
-        request=request, response=None, services=self.services)
-    mr = testing_helpers.MakeMonorailRequest(
-        user_info={'user_id': 1},
-        payload=body,
-        method='POST',
-        services=self.services)
-    result = task.HandleRequest(mr)
-    self.assertEqual(params['from_addr'], result['sender'])
-    self.assertEqual(params['subject'], result['subject'])
+    data = json.dumps(params)
+    res = self.app.test_client().post('/_task/outboundEmail.do', data=data)
+    res_string = res.get_data()[5:]
+    res_json = json.loads(res_string)
+    self.assertEqual(params['from_addr'], res_json['sender'])
+    self.assertEqual(params['subject'], res_json['subject'])
 
   def testOutboundEmailTask_MissingTo(self):
     """We skip emails that don't specify the To-line."""
@@ -668,36 +650,26 @@
         'from_addr': 'requester@example.com',
         'reply_to': 'user@example.com',
         'subject': 'Test subject'}
-    body = json.dumps(params)
-    request = webapp2.Request.blank('/', body=body)
-    task = notify.OutboundEmailTask(
-        request=request, response=None, services=self.services)
-    mr = testing_helpers.MakeMonorailRequest(
-        user_info={'user_id': 1},
-        payload=body,
-        method='POST',
-        services=self.services)
-    result = task.HandleRequest(mr)
-    self.assertEqual('Skipping because no "to" address found.', result['note'])
-    self.assertNotIn('from_addr', result)
+    data = json.dumps(params)
+    res = self.app.test_client().post('/_task/outboundEmail.do', data=data)
+    res_string = res.get_data()[5:]
+    res_json = json.loads(res_string)
+    self.assertEqual(
+        'Skipping because no "to" address found.', res_json['note'])
+    self.assertNotIn('from_addr', res_string)
 
   def testOutboundEmailTask_BannedUser(self):
     """We don't send emails to banned users.."""
+    self.servlet.services.user.TestAddUser(
+        'banned@example.com', 404, banned=True)
     params = {
         'from_addr': 'requester@example.com',
         'reply_to': 'user@example.com',
         'to': 'banned@example.com',
         'subject': 'Test subject'}
-    body = json.dumps(params)
-    request = webapp2.Request.blank('/', body=body)
-    task = notify.OutboundEmailTask(
-        request=request, response=None, services=self.services)
-    mr = testing_helpers.MakeMonorailRequest(
-        user_info={'user_id': 1},
-        payload=body,
-        method='POST',
-        services=self.services)
-    self.services.user.TestAddUser('banned@example.com', 404, banned=True)
-    result = task.HandleRequest(mr)
-    self.assertEqual('Skipping because user is banned.', result['note'])
-    self.assertNotIn('from_addr', result)
+    data = json.dumps(params)
+    res = self.app.test_client().post('/_task/outboundEmail.do', data=data)
+    res_string = res.get_data()[5:]
+    res_json = json.loads(res_string)
+    self.assertEqual('Skipping because user is banned.', res_json['note'])
+    self.assertNotIn('from_addr', res_string)
diff --git a/features/test/pubsub_test.py b/features/test/pubsub_test.py
index 2044cf7..e86230c 100644
--- a/features/test/pubsub_test.py
+++ b/features/test/pubsub_test.py
@@ -38,8 +38,7 @@
 
   def testPublishPubsubIssueChangeTask_NoIssueIdParam(self):
     """Test case when issue_id param is not passed."""
-    task = pubsub.PublishPubsubIssueChangeTask(
-        request=None, response=None, services=self.services)
+    task = pubsub.PublishPubsubIssueChangeTask(services=self.services)
     mr = testing_helpers.MakeMonorailRequest(
         user_info={'user_id': 1},
         params={},
@@ -54,8 +53,7 @@
   def testPublishPubsubIssueChangeTask_PubSubAPIInitFailure(self):
     """Test case when pub/sub API fails to init."""
     pubsub.set_up_pubsub_api = Mock(return_value=None)
-    task = pubsub.PublishPubsubIssueChangeTask(
-        request=None, response=None, services=self.services)
+    task = pubsub.PublishPubsubIssueChangeTask(services=self.services)
     mr = testing_helpers.MakeMonorailRequest(
         user_info={'user_id': 1},
         params={},
@@ -69,8 +67,7 @@
 
   def testPublishPubsubIssueChangeTask_IssueNotFound(self):
     """Test case when issue is not found."""
-    task = pubsub.PublishPubsubIssueChangeTask(
-        request=None, response=None, services=self.services)
+    task = pubsub.PublishPubsubIssueChangeTask(services=self.services)
     mr = testing_helpers.MakeMonorailRequest(
         user_info={'user_id': 1},
         params={'issue_id': 314159},
@@ -87,8 +84,7 @@
     issue = fake.MakeTestIssue(789, 543, 'sum', 'New', 111, issue_id=78901,
         project_name='rutabaga')
     self.services.issue.TestAddIssue(issue)
-    task = pubsub.PublishPubsubIssueChangeTask(
-        request=None, response=None, services=self.services)
+    task = pubsub.PublishPubsubIssueChangeTask(services=self.services)
     mr = testing_helpers.MakeMonorailRequest(
         user_info={'user_id': 1},
         params={'issue_id': 78901},
diff --git a/features/test/savedqueries_helpers_test.py b/features/test/savedqueries_helpers_test.py
index d635fe1..7f5ad47 100644
--- a/features/test/savedqueries_helpers_test.py
+++ b/features/test/savedqueries_helpers_test.py
@@ -10,7 +10,10 @@
 
 import unittest
 
-import mox
+try:
+  from mox3 import mox
+except ImportError:
+  import mox
 
 from features import savedqueries_helpers
 from testing import fake