# 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.

"""Unittests for monorail.tracker.issuereindex."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import unittest

try:
  from mox3 import mox
except ImportError:
  import mox

import settings
from framework import permissions
from services import service_manager
from services import tracker_fulltext
from testing import fake
from testing import testing_helpers
from tracker import issuereindex


class IssueReindexTest(unittest.TestCase):

  def setUp(self):
    self.cnxn = 'fake cnxn'
    self.services = service_manager.Services(
        config=fake.ConfigService(),
        issue=fake.IssueService(),
        user=fake.UserService(),
        project=fake.ProjectService())
    self.project = self.services.project.TestAddProject('proj', project_id=987)
    self.mox = mox.Mox()

  def tearDown(self):
    self.mox.UnsetStubs()
    self.mox.ResetAll()

  def testAssertBasePermission_NoAccess(self):
    # Non-members and contributors do not have permission to view this page.
    for permission in (permissions.USER_PERMISSIONSET,
                       permissions.COMMITTER_ACTIVE_PERMISSIONSET):
      _, mr = testing_helpers.GetRequestObjects(
          project=self.project, perms=permission)
      servlet = issuereindex.IssueReindex(services=self.services)
    with self.assertRaises(permissions.PermissionException) as cm:
      servlet.AssertBasePermission(mr)
    self.assertEqual(
        'You are not allowed to administer this project', str(cm.exception))

  def testAssertBasePermission_WithAccess(self):
    # Owners and admins have permission to view this page.
    for permission in (permissions.OWNER_ACTIVE_PERMISSIONSET,
                       permissions.ADMIN_PERMISSIONSET):
      _, mr = testing_helpers.GetRequestObjects(
          project=self.project, perms=permission)
      servlet = issuereindex.IssueReindex(services=self.services)
      servlet.AssertBasePermission(mr)

  def testGatherPageData(self):
    servlet = issuereindex.IssueReindex(services=self.services)

    mr = testing_helpers.MakeMonorailRequest()
    mr.auto_submit = True
    ret = servlet.GatherPageData(mr)

    self.assertTrue(ret['auto_submit'])
    self.assertIsNone(ret['issue_tab_mode'])
    self.assertTrue(ret['page_perms'].CreateIssue)

  def _callProcessFormData(self, post_data, index_issue_1=True):
    servlet = issuereindex.IssueReindex(services=self.services)

    mr = testing_helpers.MakeMonorailRequest(project=self.project)
    mr.cnxn = self.cnxn

    issue1 = fake.MakeTestIssue(
        project_id=self.project.project_id, local_id=1, summary='sum',
        status='New', owner_id=111)
    issue1.project_name = self.project.project_name
    self.services.issue.TestAddIssue(issue1)

    self.mox.StubOutWithMock(tracker_fulltext, 'IndexIssues')
    if index_issue_1:
      tracker_fulltext.IndexIssues(
          self.cnxn, [issue1], self.services.user, self.services.issue,
          self.services.config)

    self.mox.ReplayAll()

    ret = servlet.ProcessFormData(mr, post_data)
    self.mox.VerifyAll()
    return ret

  def testProcessFormData_NormalInputs(self):
    post_data = {'start': 1, 'num': 5}
    ret = self._callProcessFormData(post_data)
    self.assertEqual(
        '/p/None/issues/reindex?start=6&num=5&auto_submit=False', ret)

  def testProcessFormData_LargeInputs(self):
    post_data = {'start': 0, 'num': 10000000}
    ret = self._callProcessFormData(post_data)
    self.assertEqual(
        '/p/None/issues/reindex?start=%s&num=%s&auto_submit=False' % (
            settings.max_artifact_search_results_per_page,
            settings.max_artifact_search_results_per_page), ret)

  def testProcessFormData_WithAutoSubmit(self):
    post_data = {'start': 1, 'num': 5, 'auto_submit': 1}
    ret = self._callProcessFormData(post_data)
    self.assertEqual(
        '/p/None/issues/reindex?start=6&num=5&auto_submit=True', ret)

  def testProcessFormData_WithAutoSubmitButNoMoreIssues(self):
    """This project has no issues 6-10, so stop autosubmitting."""
    post_data = {'start': 6, 'num': 5, 'auto_submit': 1}
    ret = self._callProcessFormData(post_data, index_issue_1=False)
    self.assertEqual(
        '/p/None/issues/reindex?start=11&num=5&auto_submit=False', ret)
