# 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

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

import logging
import mock
import mox
import time
import unittest

import settings
from businesslogic import work_env
from proto import features_pb2
from features import hotlist_views
from features import send_notifications
from framework import authdata
from framework import exceptions
from framework import framework_views
from framework import framework_helpers
from framework import urls
from framework import permissions
from framework import profiler
from framework import sorting
from framework import template_helpers
from proto import project_pb2
from proto import tracker_pb2
from proto import user_pb2
from services import service_manager
from services import issue_svc
from services import tracker_fulltext
from testing import fake
from testing import testing_helpers
from tracker import issuedetailezt
from tracker import tracker_constants
from tracker import tracker_helpers


class GetAdjacentIssueTest(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(),
        issue_star=fake.IssueStarService(),
        spam=fake.SpamService())
    self.services.project.TestAddProject('proj', project_id=789)
    self.mr = testing_helpers.MakeMonorailRequest()
    self.mr.auth.user_id = 111
    self.mr.auth.effective_ids = {111}
    self.mr.me_user_id = 111
    self.work_env = work_env.WorkEnv(
      self.mr, self.services, 'Testing phase')

  def testGetAdjacentIssue_PrevIssue(self):
    cur_issue = fake.MakeTestIssue(789, 2, 'sum', 'New', 111, issue_id=78902)
    next_issue = fake.MakeTestIssue(789, 3, 'sum', 'New', 111, issue_id=78903)
    prev_issue = fake.MakeTestIssue(789, 1, 'sum', 'New', 111, issue_id=78901)
    self.services.issue.TestAddIssue(cur_issue)
    self.services.issue.TestAddIssue(next_issue)
    self.services.issue.TestAddIssue(prev_issue)

    with self.work_env as we:
      we.FindIssuePositionInSearch = mock.Mock(
          return_value=[78901, 1, 78903, 3])

      actual_issue = issuedetailezt.GetAdjacentIssue(
         self.mr, we, cur_issue)
      self.assertEqual(prev_issue, actual_issue)
      we.FindIssuePositionInSearch.assert_called_once_with(cur_issue)

  def testGetAdjacentIssue_NextIssue(self):
    cur_issue = fake.MakeTestIssue(789, 2, 'sum', 'New', 111, issue_id=78902)
    next_issue = fake.MakeTestIssue(789, 3, 'sum', 'New', 111, issue_id=78903)
    prev_issue = fake.MakeTestIssue(789, 1, 'sum', 'New', 111, issue_id=78901)
    self.services.issue.TestAddIssue(cur_issue)
    self.services.issue.TestAddIssue(next_issue)
    self.services.issue.TestAddIssue(prev_issue)

    with self.work_env as we:
      we.FindIssuePositionInSearch = mock.Mock(
          return_value=[78901, 1, 78903, 3])

      actual_issue = issuedetailezt.GetAdjacentIssue(
          self.mr, we, cur_issue, next_issue=True)
      self.assertEqual(next_issue, actual_issue)
      we.FindIssuePositionInSearch.assert_called_once_with(cur_issue)

  def testGetAdjacentIssue_NotFound(self):
    cur_issue = fake.MakeTestIssue(789, 2, 'sum', 'New', 111, issue_id=78902)
    prev_issue = fake.MakeTestIssue(789, 1, 'sum', 'New', 111, issue_id=78901)
    self.services.issue.TestAddIssue(cur_issue)
    self.services.issue.TestAddIssue(prev_issue)

    with self.work_env as we:
      we.FindIssuePositionInSearch = mock.Mock(
          return_value=[78901, 1, 78903, 3])

      with self.assertRaises(exceptions.NoSuchIssueException):
        issuedetailezt.GetAdjacentIssue(
            self.mr, we, cur_issue, next_issue=True)
      we.FindIssuePositionInSearch.assert_called_once_with(cur_issue)

  def testGetAdjacentIssue_Hotlist(self):
    cur_issue = fake.MakeTestIssue(789, 2, 'sum', 'New', 111, issue_id=78902)
    next_issue = fake.MakeTestIssue(789, 3, 'sum', 'New', 111, issue_id=78903)
    prev_issue = fake.MakeTestIssue(789, 1, 'sum', 'New', 111, issue_id=78901)
    self.services.issue.TestAddIssue(cur_issue)
    self.services.issue.TestAddIssue(next_issue)
    self.services.issue.TestAddIssue(prev_issue)
    hotlist = fake.Hotlist('name', 678, owner_ids=[111])

    with self.work_env as we:
      we.GetIssuePositionInHotlist = mock.Mock(
          return_value=[78901, 1, 78903, 3])

      actual_issue = issuedetailezt.GetAdjacentIssue(
          self.mr, we, cur_issue, hotlist=hotlist, next_issue=True)
      self.assertEqual(next_issue, actual_issue)
      we.GetIssuePositionInHotlist.assert_called_once_with(
          cur_issue, hotlist, self.mr.can, self.mr.sort_spec,
          self.mr.group_by_spec)


class FlipperRedirectTest(unittest.TestCase):

  def setUp(self):
    self.services = service_manager.Services(
        config=fake.ConfigService(),
        features=fake.FeaturesService(),
        issue=fake.IssueService(),
        user=fake.UserService(),
        project=fake.ProjectService())
    self.project = self.services.project.TestAddProject(
      'proj', project_id=987, committer_ids=[111])
    self.next_servlet = issuedetailezt.FlipperNext(
        'req', 'res', services=self.services)
    self.prev_servlet = issuedetailezt.FlipperPrev(
        'req', 'res', services=self.services)
    self.list_servlet = issuedetailezt.FlipperList(
        'req', 'res', services=self.services)
    mr = testing_helpers.MakeMonorailRequest(project=self.project)
    mr.local_id = 123
    mr.me_user_id = 111

    self.next_servlet.mr = mr
    self.prev_servlet.mr = mr
    self.list_servlet.mr = mr

    self.fake_issue_1 = fake.MakeTestIssue(987, 123, 'summary', 'New', 111,
        project_name='rutabaga')
    self.services.issue.TestAddIssue(self.fake_issue_1)
    self.fake_issue_2 = fake.MakeTestIssue(987, 456, 'summary', 'New', 111,
        project_name='rutabaga')
    self.services.issue.TestAddIssue(self.fake_issue_2)
    self.fake_issue_3 = fake.MakeTestIssue(987, 789, 'summary', 'New', 111,
        project_name='potato')
    self.services.issue.TestAddIssue(self.fake_issue_3)

    self.next_servlet.redirect = mock.Mock()
    self.prev_servlet.redirect = mock.Mock()
    self.list_servlet.redirect = mock.Mock()

  @mock.patch('tracker.issuedetailezt.GetAdjacentIssue')
  def testFlipperNext(self, patchGetAdjacentIssue):
    patchGetAdjacentIssue.return_value = self.fake_issue_2
    self.next_servlet.mr.GetIntParam = mock.Mock(return_value=None)

    self.next_servlet.get(project_name='proj', viewed_username=None)
    self.next_servlet.mr.GetIntParam.assert_called_once_with('hotlist_id')
    patchGetAdjacentIssue.assert_called_once()
    self.next_servlet.redirect.assert_called_once_with(
      '/p/rutabaga/issues/detail?id=456')

  @mock.patch('tracker.issuedetailezt.GetAdjacentIssue')
  def testFlipperNext_Hotlist(self, patchGetAdjacentIssue):
    patchGetAdjacentIssue.return_value = self.fake_issue_3
    self.next_servlet.mr.GetIntParam = mock.Mock(return_value=123)
    # TODO(jeffcarp): Mock hotlist_id param on path here.

    self.next_servlet.get(project_name='proj', viewed_username=None)
    self.next_servlet.mr.GetIntParam.assert_called_with('hotlist_id')
    self.next_servlet.redirect.assert_called_once_with(
      '/p/potato/issues/detail?id=789')

  @mock.patch('tracker.issuedetailezt.GetAdjacentIssue')
  def testFlipperPrev(self, patchGetAdjacentIssue):
    patchGetAdjacentIssue.return_value = self.fake_issue_2
    self.next_servlet.mr.GetIntParam = mock.Mock(return_value=None)

    self.prev_servlet.get(project_name='proj', viewed_username=None)
    self.prev_servlet.mr.GetIntParam.assert_called_with('hotlist_id')
    patchGetAdjacentIssue.assert_called_once()
    self.prev_servlet.redirect.assert_called_once_with(
      '/p/rutabaga/issues/detail?id=456')

  @mock.patch('tracker.issuedetailezt.GetAdjacentIssue')
  def testFlipperPrev_Hotlist(self, patchGetAdjacentIssue):
    patchGetAdjacentIssue.return_value = self.fake_issue_3
    self.prev_servlet.mr.GetIntParam = mock.Mock(return_value=123)
    # TODO(jeffcarp): Mock hotlist_id param on path here.

    self.prev_servlet.get(project_name='proj', viewed_username=None)
    self.prev_servlet.mr.GetIntParam.assert_called_with('hotlist_id')
    self.prev_servlet.redirect.assert_called_once_with(
      '/p/potato/issues/detail?id=789')

  @mock.patch('tracker.issuedetailezt._ComputeBackToListURL')
  def testFlipperList(self, patch_ComputeBackToListURL):
    patch_ComputeBackToListURL.return_value = '/p/test/issues/list'
    self.list_servlet.mr.GetIntParam = mock.Mock(return_value=None)

    self.list_servlet.get()

    self.list_servlet.mr.GetIntParam.assert_called_with('hotlist_id')
    patch_ComputeBackToListURL.assert_called_once()
    self.list_servlet.redirect.assert_called_once_with(
      '/p/test/issues/list')

  @mock.patch('tracker.issuedetailezt._ComputeBackToListURL')
  def testFlipperList_Hotlist(self, patch_ComputeBackToListURL):
    patch_ComputeBackToListURL.return_value = '/p/test/issues/list'
    self.list_servlet.mr.GetIntParam = mock.Mock(return_value=123)

    self.list_servlet.get()

    self.list_servlet.mr.GetIntParam.assert_called_with('hotlist_id')
    self.list_servlet.redirect.assert_called_once_with(
      '/p/test/issues/list')


class ShouldShowFlipperTest(unittest.TestCase):

  def setUp(self):
    self.cnxn = 'fake cnxn'

  def VerifyShouldShowFlipper(
      self, expected, query, sort_spec, can, create_issues=0):
    """Instantiate a _Flipper and check if makes a pipeline or not."""
    services = service_manager.Services(
        config=fake.ConfigService(),
        issue=fake.IssueService(),
        project=fake.ProjectService(),
        user=fake.UserService())
    project = services.project.TestAddProject(
      'proj', project_id=987, committer_ids=[111])
    mr = testing_helpers.MakeMonorailRequest(project=project)
    mr.query = query
    mr.sort_spec = sort_spec
    mr.can = can
    mr.project_name = project.project_name
    mr.project = project

    for idx in range(create_issues):
      _created_issue = fake.MakeTestIssue(
          project.project_id,
          idx,
          'summary_%d' % idx,
          'status',
          111,
          reporter_id=111)
      services.issue.TestAddIssue(_created_issue)

    self.assertEqual(expected, issuedetailezt._ShouldShowFlipper(mr, services))

  def testShouldShowFlipper_RegularSizedProject(self):
    # If the user is looking for a specific issue, no flipper.
    self.VerifyShouldShowFlipper(
        False, '123', '', tracker_constants.OPEN_ISSUES_CAN)
    self.VerifyShouldShowFlipper(False, '123', '', 5)
    self.VerifyShouldShowFlipper(
        False, '123', 'priority', tracker_constants.OPEN_ISSUES_CAN)

    # If the user did a search or sort or all in a small can, show flipper.
    self.VerifyShouldShowFlipper(
        True, 'memory leak', '', tracker_constants.OPEN_ISSUES_CAN)
    self.VerifyShouldShowFlipper(
        True, 'id=1,2,3', '', tracker_constants.OPEN_ISSUES_CAN)
    # Any can other than 1 or 2 is doing a query and so it should have a
    # failry narrow result set size.  5 is issues starred by me.
    self.VerifyShouldShowFlipper(True, '', '', 5)
    self.VerifyShouldShowFlipper(
        True, '', 'status', tracker_constants.OPEN_ISSUES_CAN)

    # In a project without a huge number of issues, still show the flipper even
    # if there was no specific query.
    self.VerifyShouldShowFlipper(
        True, '', '', tracker_constants.OPEN_ISSUES_CAN)

  def testShouldShowFlipper_LargeSizedProject(self):
    settings.threshold_to_suppress_prev_next = 1

    # In a project that has tons of issues, save time by not showing the
    # flipper unless there was a specific query, sort, or can.
    self.VerifyShouldShowFlipper(
        False, '', '', tracker_constants.ALL_ISSUES_CAN, create_issues=3)
    self.VerifyShouldShowFlipper(
        False, '', '', tracker_constants.OPEN_ISSUES_CAN, create_issues=3)
