# 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.search.backendsearch."""
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 search import backendsearch
from search import backendsearchpipeline
from services import service_manager
from testing import fake
from testing import testing_helpers


class BackendSearchTest(unittest.TestCase):

  def setUp(self):
    self.services = service_manager.Services(
        issue=fake.IssueService(),
        )
    self.mr = testing_helpers.MakeMonorailRequest(
        path='/_backend/besearch?q=Priority:High&shard=2')
    self.mr.query_project_names = ['proj']
    self.mr.specified_logged_in_user_id = 111
    self.mr.specified_me_user_ids = [222]
    self.mr.shard_id = 2
    self.servlet = backendsearch.BackendSearch(services=self.services)
    self.mox = mox.Mox()

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

  def testHandleRequest_NoResults(self):
    """Handle the case where the search has no results."""
    pipeline = testing_helpers.Blank(
        SearchForIIDs=lambda: None,
        result_iids=[],
        search_limit_reached=False,
        error=None)
    self.mox.StubOutWithMock(backendsearchpipeline, 'BackendSearchPipeline')
    backendsearchpipeline.BackendSearchPipeline(
      self.mr, self.services, 100, ['proj'], 111, [222]
      ).AndReturn(pipeline)
    self.mox.ReplayAll()

    json_data = self.servlet.HandleRequest(self.mr)
    self.mox.VerifyAll()
    self.assertEqual([], json_data['unfiltered_iids'])
    self.assertFalse(json_data['search_limit_reached'])
    self.assertEqual(None, json_data['error'])

  def testHandleRequest_ResultsInOnePagainationPage(self):
    """Prefetch all result issues and return them."""
    allowed_iids = [1, 2, 3, 4, 5, 6, 7, 8]
    pipeline = testing_helpers.Blank(
        SearchForIIDs=lambda: None,
        result_iids=allowed_iids,
        search_limit_reached=False,
        error=None)
    self.mox.StubOutWithMock(backendsearchpipeline, 'BackendSearchPipeline')
    backendsearchpipeline.BackendSearchPipeline(
      self.mr, self.services, 100, ['proj'], 111, [222]
      ).AndReturn(pipeline)
    self.mox.StubOutWithMock(self.services.issue, 'GetIssues')
    # All issues are prefetched because they fit  on the first pagination page.
    self.services.issue.GetIssues(self.mr.cnxn, allowed_iids, shard_id=2)
    self.mox.ReplayAll()

    json_data = self.servlet.HandleRequest(self.mr)
    self.mox.VerifyAll()
    self.assertEqual([1, 2, 3, 4, 5, 6, 7, 8], json_data['unfiltered_iids'])
    self.assertFalse(json_data['search_limit_reached'])
    self.assertEqual(None, json_data['error'])

  def testHandleRequest_ResultsExceedPagainationPage(self):
    """Return all result issue IDs, but only prefetch the first page."""
    self.mr.num = 5
    pipeline = testing_helpers.Blank(
        SearchForIIDs=lambda: None,
        result_iids=[1, 2, 3, 4, 5, 6, 7, 8],
        search_limit_reached=False,
        error=None)
    self.mox.StubOutWithMock(backendsearchpipeline, 'BackendSearchPipeline')
    backendsearchpipeline.BackendSearchPipeline(
      self.mr, self.services, 100, ['proj'], 111, [222]
      ).AndReturn(pipeline)
    self.mox.StubOutWithMock(self.services.issue, 'GetIssues')
    # First 5 issues are prefetched because num=5
    self.services.issue.GetIssues(self.mr.cnxn, [1, 2, 3, 4, 5], shard_id=2)
    self.mox.ReplayAll()

    json_data = self.servlet.HandleRequest(self.mr)
    self.mox.VerifyAll()
    # All are IDs are returned to the frontend.
    self.assertEqual([1, 2, 3, 4, 5, 6, 7, 8], json_data['unfiltered_iids'])
    self.assertFalse(json_data['search_limit_reached'])
    self.assertEqual(None, json_data['error'])

  def testHandleRequest_QueryError(self):
    """Handle the case where the search has no results."""
    error = ValueError('Malformed query')
    pipeline = testing_helpers.Blank(
        SearchForIIDs=lambda: None,
        result_iids=[],
        search_limit_reached=False,
        error=error)
    self.mox.StubOutWithMock(backendsearchpipeline, 'BackendSearchPipeline')
    backendsearchpipeline.BackendSearchPipeline(
      self.mr, self.services, 100, ['proj'], 111, [222]
      ).AndReturn(pipeline)
    self.mox.ReplayAll()

    json_data = self.servlet.HandleRequest(self.mr)
    self.mox.VerifyAll()
    self.assertEqual([], json_data['unfiltered_iids'])
    self.assertFalse(json_data['search_limit_reached'])
    self.assertEqual(error.message, json_data['error'])
