# 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 ban spammer feature."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import json
import mock
import six
import unittest
from six.moves import urllib

import settings
from features import banspammer
from framework import framework_views
from framework import permissions
from framework import urls
from mrproto import tracker_pb2
from services import service_manager
from testing import fake
from testing import testing_helpers

class BanSpammerTest(unittest.TestCase):

  def setUp(self):
    self.cnxn = 'fake cnxn'
    self.mr = testing_helpers.MakeMonorailRequest()
    self.services = service_manager.Services(
        issue=fake.IssueService(),
        project=fake.ProjectService(),
        spam=fake.SpamService(),
        user=fake.UserService())
    self.servlet = banspammer.BanSpammer(services=self.services)

  @mock.patch('framework.cloud_tasks_helpers._get_client')
  def testProcessFormData_noPermission(self, get_client_mock):
    self.servlet.services.user.TestAddUser('member', 222)
    self.servlet.services.user.TestAddUser('spammer@domain.com', 111)
    mr = testing_helpers.MakeMonorailRequest(
        path='/u/spammer@domain.com/banSpammer.do',
        perms=permissions.GetPermissions(None, {}, None))
    mr.viewed_user_auth.user_view = framework_views.MakeUserView(mr.cnxn,
        self.servlet.services.user, 111)
    mr.auth.user_id = 222
    self.assertRaises(permissions.PermissionException,
        self.servlet.AssertBasePermission, mr)
    try:
      self.servlet.ProcessFormData(mr, {})
    except permissions.PermissionException:
      pass
    self.assertEqual(get_client_mock().queue_path.call_count, 0)
    self.assertEqual(get_client_mock().create_task.call_count, 0)

  @mock.patch('framework.cloud_tasks_helpers._get_client')
  def testProcessFormData_ok(self, get_client_mock):
    self.servlet.services.user.TestAddUser('owner', 222)
    self.servlet.services.user.TestAddUser('spammer@domain.com', 111)
    mr = testing_helpers.MakeMonorailRequest(
        path='/u/spammer@domain.com/banSpammer.do',
        perms=permissions.ADMIN_PERMISSIONSET)
    mr.viewed_user_auth.user_view = framework_views.MakeUserView(mr.cnxn,
        self.servlet.services.user, 111)
    mr.viewed_user_auth.user_pb.user_id = 111
    mr.auth.user_id = 222
    self.servlet.ProcessFormData(mr, {'banned': 'non-empty'})

    params = {'spammer_id': 111, 'reporter_id': 222, 'is_spammer': True}
    task = {
        'app_engine_http_request':
            {
                'relative_uri': urls.BAN_SPAMMER_TASK + '.do',
                'body': six.ensure_binary(urllib.parse.urlencode(params)),
                'headers': {
                    'Content-type': 'application/x-www-form-urlencoded'
                }
            }
    }
    get_client_mock().queue_path.assert_called_with(
        settings.app_id, settings.CLOUD_TASKS_REGION, 'default')
    get_client_mock().create_task.assert_called_once()
    _, kwargs = get_client_mock().create_task.call_args
    self.assertEqual(kwargs['task'], task)


class BanSpammerTaskTest(unittest.TestCase):
  def setUp(self):
    self.services = service_manager.Services(
        issue=fake.IssueService(),
        spam=fake.SpamService())
    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})

    res = self.servlet.HandleRequest(mr)
    self.assertEqual(res, json.dumps({'comments': 0, 'issues': 0}))

  def testProcessFormData_okSomeIssues(self):
    mr = testing_helpers.MakeMonorailRequest(
        path=urls.BAN_SPAMMER_TASK + '.do',
        method='POST',
        params={
            'spammer_id': 111,
            'reporter_id': 222
        })
    for i in range(0, 10):
      issue = fake.MakeTestIssue(
          1, i, 'issue_summary', 'New', 111, project_name='project-name')
      self.servlet.services.issue.TestAddIssue(issue)

    res = self.servlet.HandleRequest(mr)
    self.assertEqual(res, json.dumps({'comments': 0, 'issues': 10}))

  def testProcessFormData_okSomeCommentsAndIssues(self):
    mr = testing_helpers.MakeMonorailRequest(
        path=urls.BAN_SPAMMER_TASK + '.do', method='POST',
        params={'spammer_id': 111, 'reporter_id': 222})

    for i in range(0, 12):
      issue = fake.MakeTestIssue(
          1, i, 'issue_summary', 'New', 111, project_name='project-name')
      self.servlet.services.issue.TestAddIssue(issue)

    for i in range(10, 20):
      issue = fake.MakeTestIssue(
          1, i, 'issue_summary', 'New', 222, project_name='project-name')
      self.servlet.services.issue.TestAddIssue(issue)
      for _ in range(0, 5):
        comment = tracker_pb2.IssueComment()
        comment.project_id = 1
        comment.user_id = 111
        comment.issue_id = issue.issue_id
        self.servlet.services.issue.TestAddComment(comment, issue.local_id)
    res = self.servlet.HandleRequest(mr)
    self.assertEqual(res, json.dumps({'comments': 50, 'issues': 10}))
