# 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

"""Unit tests for savedqueries_helpers feature."""
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

from features import savedqueries_helpers
from testing import fake
from tracker import tracker_bizobj


class SavedQueriesHelperTest(unittest.TestCase):

  def setUp(self):
    self.features = fake.FeaturesService()
    self.project = fake.ProjectService()
    self.cnxn = 'fake cnxn'
    self.mox = mox.Mox()

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

  def testParseSavedQueries(self):
    post_data = {
        'xyz_savedquery_name_1': '',
        'xyz_savedquery_name_2': 'name2',
        'xyz_savedquery_name_3': 'name3',
        'xyz_savedquery_id_1': 1,
        'xyz_savedquery_id_2': 2,
        'xyz_savedquery_id_3': 3,
        'xyz_savedquery_projects_1': '123',
        'xyz_savedquery_projects_2': 'abc',
        'xyz_savedquery_projects_3': 'def',
        'xyz_savedquery_base_1': 4,
        'xyz_savedquery_base_2': 5,
        'xyz_savedquery_base_3': 6,
        'xyz_savedquery_query_1': 'query1',
        'xyz_savedquery_query_2': 'query2',
        'xyz_savedquery_query_3': 'query3',
        'xyz_savedquery_sub_mode_1': 'sub_mode1',
        'xyz_savedquery_sub_mode_2': 'sub_mode2',
        'xyz_savedquery_sub_mode_3': 'sub_mode3',
    }
    self.project.TestAddProject(name='abc', project_id=1001)
    self.project.TestAddProject(name='def', project_id=1002)

    saved_queries = savedqueries_helpers.ParseSavedQueries(
        self.cnxn, post_data, self.project, prefix='xyz_')
    self.assertEqual(2, len(saved_queries))

    # pylint: disable=unbalanced-tuple-unpacking
    saved_query1, saved_query2 = saved_queries
    # Assert contents of saved_query1.
    self.assertEqual(2, saved_query1.query_id)
    self.assertEqual('name2', saved_query1.name)
    self.assertEqual(5, saved_query1.base_query_id)
    self.assertEqual('query2', saved_query1.query)
    self.assertEqual([1001], saved_query1.executes_in_project_ids)
    self.assertEqual('sub_mode2', saved_query1.subscription_mode)
    # Assert contents of saved_query2.
    self.assertEqual(3, saved_query2.query_id)
    self.assertEqual('name3', saved_query2.name)
    self.assertEqual(6, saved_query2.base_query_id)
    self.assertEqual('query3', saved_query2.query)
    self.assertEqual([1002], saved_query2.executes_in_project_ids)
    self.assertEqual('sub_mode3', saved_query2.subscription_mode)

  def testSavedQueryToCond(self):
    class MockSavedQuery:
      def __init__(self):
        self.base_query_id = 1
        self.query = 'query'
    saved_query = MockSavedQuery()

    cond_for_missing_query = savedqueries_helpers.SavedQueryToCond(None)
    self.assertEqual('', cond_for_missing_query)

    cond_with_no_base = savedqueries_helpers.SavedQueryToCond(saved_query)
    self.assertEqual('query', cond_with_no_base)

    self.mox.StubOutWithMock(tracker_bizobj, 'GetBuiltInQuery')
    tracker_bizobj.GetBuiltInQuery(1).AndReturn('base')
    self.mox.ReplayAll()
    cond_with_base = savedqueries_helpers.SavedQueryToCond(saved_query)
    self.assertEqual('base query', cond_with_base)
    self.mox.VerifyAll()

  def testSavedQueryIDToCond(self):
    self.mox.StubOutWithMock(savedqueries_helpers, 'SavedQueryToCond')
    savedqueries_helpers.SavedQueryToCond(mox.IgnoreArg()).AndReturn('ret')
    self.mox.ReplayAll()
    query_cond = savedqueries_helpers.SavedQueryIDToCond(
        self.cnxn, self.features, 1)
    self.assertEqual('ret', query_cond)
    self.mox.VerifyAll()

    self.mox.StubOutWithMock(tracker_bizobj, 'GetBuiltInQuery')
    tracker_bizobj.GetBuiltInQuery(1).AndReturn('built_in_query')
    self.mox.ReplayAll()
    query_cond = savedqueries_helpers.SavedQueryIDToCond(
        self.cnxn, self.features, 1)
    self.assertEqual('built_in_query', query_cond)
    self.mox.VerifyAll()
