# 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 the fielddetail servlet."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import mox
import unittest
import logging

import webapp2

import ezt

from framework import permissions
from proto import project_pb2
from proto import tracker_pb2
from services import service_manager
from testing import fake
from testing import testing_helpers
from tracker import fielddetail
from tracker import tracker_bizobj
from tracker import tracker_views


class FieldDetailTest(unittest.TestCase):

  def setUp(self):
    self.services = service_manager.Services(
        user=fake.UserService(),
        config=fake.ConfigService(),
        project=fake.ProjectService())
    self.servlet = fielddetail.FieldDetail(
        'req', 'res', services=self.services)
    self.project = self.services.project.TestAddProject('proj')
    self.mr = testing_helpers.MakeMonorailRequest(
        project=self.project, perms=permissions.OWNER_ACTIVE_PERMISSIONSET)
    self.config = self.services.config.GetProjectConfig(
        'fake cnxn', self.project.project_id)
    self.services.config.StoreConfig('fake cnxn', self.config)
    self.fd = tracker_bizobj.MakeFieldDef(
        123, 789, 'CPU', tracker_pb2.FieldTypes.INT_TYPE, None,
        '', False, False, False, None, None, '', False, '', '',
        tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
    self.fd.admin_ids = [111]
    self.fd.editor_ids = [222]
    self.config.field_defs.append(self.fd)
    self.services.user.TestAddUser('gatsby@example.com', 111)
    self.services.user.TestAddUser('sport@example.com', 222)
    self.mr.field_name = 'CPU'

    # Approvals
    self.approval_def = tracker_pb2.ApprovalDef(
        approval_id=234, approver_ids=[111], survey='Question 1?')
    self.sub_fd = tracker_pb2.FieldDef(
        field_name='UIMocks', approval_id=234, applicable_type='')
    self.sub_fd_deleted = tracker_pb2.FieldDef(
        field_name='UIMocksDeleted', approval_id=234, applicable_type='',
        is_deleted=True)
    self.config.field_defs.extend([self.sub_fd, self.sub_fd_deleted])
    self.config.approval_defs.append(self.approval_def)
    self.approval_fd = tracker_bizobj.MakeFieldDef(
        234, 789, 'UIReview', tracker_pb2.FieldTypes.APPROVAL_TYPE, None,
        '', False, False, False, None, None, '', False, '', '',
        tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
    self.config.field_defs.append(self.approval_fd)

    self.mox = mox.Mox()

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

  def testGetFieldDef_NotFound(self):
    self.mr.field_name = 'NeverHeardOfIt'
    self.assertRaises(
        webapp2.HTTPException,
        self.servlet._GetFieldDef, self.mr)

  def testGetFieldDef_Normal(self):
    actual_config, actual_fd = self.servlet._GetFieldDef(self.mr)
    self.assertEqual(self.config, actual_config)
    self.assertEqual(self.fd, actual_fd)

  def testAssertBasePermission_AnyoneCanView(self):
    self.servlet.AssertBasePermission(self.mr)
    self.mr.perms = permissions.COMMITTER_ACTIVE_PERMISSIONSET
    self.servlet.AssertBasePermission(self.mr)
    self.mr.perms = permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET
    self.servlet.AssertBasePermission(self.mr)
    self.mr.perms = permissions.READ_ONLY_PERMISSIONSET
    self.servlet.AssertBasePermission(self.mr)

  def testAssertBasePermission_MembersOnly(self):
    self.project.access = project_pb2.ProjectAccess.MEMBERS_ONLY
    # The project members can view the field definition.
    self.servlet.AssertBasePermission(self.mr)
    self.mr.perms = permissions.COMMITTER_ACTIVE_PERMISSIONSET
    self.servlet.AssertBasePermission(self.mr)
    self.mr.perms = permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET
    self.servlet.AssertBasePermission(self.mr)
    # Non-member is not allowed to view anything in the project.
    self.mr.perms = permissions.EMPTY_PERMISSIONSET
    self.assertRaises(
        permissions.PermissionException,
        self.servlet.AssertBasePermission, self.mr)

  def testGatherPageData_ReadWrite(self):
    page_data = self.servlet.GatherPageData(self.mr)
    self.assertEqual(self.servlet.PROCESS_TAB_LABELS,
                     page_data['admin_tab_mode'])
    self.assertTrue(page_data['allow_edit'])
    self.assertEqual('gatsby@example.com', page_data['initial_admins'])
    self.assertEqual('sport@example.com', page_data['initial_editors'])
    field_def_view = page_data['field_def']
    self.assertEqual('CPU', field_def_view.field_name)
    self.assertEqual(page_data['approval_subfields'], [])
    self.assertEqual(page_data['initial_approvers'], '')

  def testGatherPageData_ReadOnly(self):
    self.mr.perms = permissions.READ_ONLY_PERMISSIONSET
    page_data = self.servlet.GatherPageData(self.mr)
    self.assertEqual(self.servlet.PROCESS_TAB_LABELS,
                     page_data['admin_tab_mode'])
    self.assertFalse(page_data['allow_edit'])
    self.assertEqual('gatsby@example.com', page_data['initial_admins'])
    self.assertEqual('sport@example.com', page_data['initial_editors'])
    field_def_view = page_data['field_def']
    self.assertEqual('CPU', field_def_view.field_name)
    self.assertEqual(page_data['approval_subfields'], [])
    self.assertEqual(page_data['initial_approvers'], '')

  def testGatherPageData_Approval(self):
    self.mr.field_name = 'UIReview'
    page_data = self.servlet.GatherPageData(self.mr)
    self.assertEqual(page_data['approval_subfields'], [self.sub_fd])
    self.assertEqual(page_data['initial_approvers'], 'gatsby@example.com')
    field_def_view = page_data['field_def']
    self.assertEqual(field_def_view.field_name, 'UIReview')
    self.assertEqual(field_def_view.survey, 'Question 1?')

  def testProcessFormData_Permission(self):
    """Only owners can edit fields."""
    mr = testing_helpers.MakeMonorailRequest(
        project=self.project,
        perms=permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET)
    mr.field_name = 'CPU'
    post_data = fake.PostData(
        name=['CPU'],
        deletefield=['Submit'])
    self.assertRaises(permissions.PermissionException,
                      self.servlet.ProcessFormData, mr, post_data)

    self.servlet.ProcessFormData(self.mr, post_data)

  def testProcessFormData_Delete(self):
    post_data = fake.PostData(
        name=['CPU'],
        deletefield=['Submit'])
    url = self.servlet.ProcessFormData(self.mr, post_data)
    self.assertTrue('/adminLabels?deleted=1&' in url)
    fd = tracker_bizobj.FindFieldDef('CPU', self.config)
    self.assertEqual('CPU', fd.field_name)
    self.assertTrue(fd.is_deleted)

  def testProcessFormData_Cancel(self):
    post_data = fake.PostData(
        name=['CPU'],
        cancel=['Submit'],
        max_value=['200'])
    url = self.servlet.ProcessFormData(self.mr, post_data)
    logging.info(url)
    self.assertTrue('/adminLabels?ts=' in url)
    config = self.services.config.GetProjectConfig(
        self.mr.cnxn, self.mr.project_id)

    fd = tracker_bizobj.FindFieldDef('CPU', config)
    self.assertIsNone(fd.max_value)
    self.assertIsNone(fd.min_value)

  def testProcessFormData_Edit(self):
    post_data = fake.PostData(
        name=['CPU'],
        field_type=['INT_TYPE'],
        min_value=['2'],
        max_value=['98'],
        notify_on=['never'],
        is_required=[],
        is_multivalued=[],
        docstring=['It is just some field'],
        applicable_type=['Defect'],
        admin_names=['gatsby@example.com'])
    url = self.servlet.ProcessFormData(self.mr, post_data)
    self.assertTrue('/fields/detail?field=CPU&saved=1&' in url)
    config = self.services.config.GetProjectConfig(
        self.mr.cnxn, self.mr.project_id)

    fd = tracker_bizobj.FindFieldDef('CPU', config)
    self.assertEqual('CPU', fd.field_name)
    self.assertEqual(2, fd.min_value)
    self.assertEqual(98, fd.max_value)
    self.assertEqual([111], fd.admin_ids)
    self.assertEqual([], fd.editor_ids)

  def testProcessDeleteField(self):
    self.servlet._ProcessDeleteField(self.mr, self.config, self.fd)
    self.assertTrue(self.fd.is_deleted)

  def testProcessDeleteField_subfields(self):
    approval_fd = tracker_bizobj.MakeFieldDef(
        3, 789, 'Legal', tracker_pb2.FieldTypes.APPROVAL_TYPE, None,
        '', False, False, False, None, None, '', False, '', '',
        tracker_pb2.NotifyTriggers.NEVER, 'no_action', 'doc', False)
    self.fd.approval_id=3
    self.config.field_defs.append(approval_fd)
    self.servlet._ProcessDeleteField(self.mr, self.config, approval_fd)
    self.assertTrue(self.fd.is_deleted)
    self.assertTrue(approval_fd.is_deleted)

  def testProcessEditField_Normal(self):
    post_data = fake.PostData(
        name=['CPU'],
        field_type=['INT_TYPE'],
        min_value=['2'],
        admin_names=['gatsby@example.com'],
        editor_names=['sport@example.com'],
        is_restricted_field=['Yes'])
    self.servlet._ProcessEditField(
        self.mr, post_data, self.config, self.fd)
    fd = tracker_bizobj.FindFieldDef('CPU', self.config)
    self.assertEqual('CPU', fd.field_name)
    self.assertEqual(2, fd.min_value)
    self.assertEqual([111], fd.admin_ids)
    self.assertEqual([222], fd.editor_ids)

  def testProcessEditField_Reject(self):
    post_data = fake.PostData(
        name=['CPU'],
        field_type=['INT_TYPE'],
        min_value=['4'],
        max_value=['1'],
        admin_names=[''],
        editor_names=[''])

    self.mox.StubOutWithMock(self.servlet, 'PleaseCorrect')
    self.servlet.PleaseCorrect(
        self.mr,
        field_def=mox.IgnoreArg(),
        initial_applicable_type='',
        initial_choices='',
        initial_admins='',
        initial_editors='',
        initial_approvers='',
        initial_is_restricted_field=False)
    self.mox.ReplayAll()

    url = self.servlet._ProcessEditField(
        self.mr, post_data, self.config, self.fd)
    self.assertEqual('Minimum value must be less than maximum.',
                     self.mr.errors.min_value)
    self.assertIsNone(url)

    fd = tracker_bizobj.FindFieldDef('CPU', self.config)
    self.assertIsNone(fd.min_value)
    self.assertIsNone(fd.max_value)

  def testProcessEditField_Reject_EditorsForNonRestrictedField(self):
    # This method tests that an exception is raised
    # when trying to add editors to a non restricted field.
    post_data = fake.PostData(
        name=['CPU'],
        field_type=['INT_TYPE'],
        min_value=['2'],
        admin_names=[''],
        editor_names=['gatsby@example.com'])

    self.assertRaises(
        AssertionError, self.servlet._ProcessEditField, self.mr, post_data,
        self.config, self.fd)

  def testProcessEditField_RejectAssertions_1(self):
    # This method tests that an exception is raised
    # when trying to add editors to an approval field.
    post_data = fake.PostData(
        name=['CPU'],
        approver_names=['gatsby@example.com'],
        admin_names=[''],
        editor_names=['sports@example.com'])

    self.assertRaises(
        AssertionError, self.servlet._ProcessEditField, self.mr, post_data,
        self.config, self.approval_fd)

  def testProcessEditField_RejectAssertions_2(self):
    #This method tests that an exception is raised
    #when trying to restrict an approval field.
    post_data = fake.PostData(
        name=['CPU'],
        approver_names=['gatsby@example.com'],
        is_restricted_field=['Yes'],
        admin_names=[''],
        editor_names=[''])

    self.assertRaises(
        AssertionError, self.servlet._ProcessEditField, self.mr, post_data,
        self.config, self.approval_fd)

  def testProcessEditField_RejectApproval(self):
    self.mr.field_name = 'UIReview'
    post_data = fake.PostData(
        name=['UIReview'],
        admin_names=[''],
        editor_names=[''],
        survey=['WIll there be UI changes?'],
        approver_names=[''])

    self.mox.StubOutWithMock(self.servlet, 'PleaseCorrect')
    self.servlet.PleaseCorrect(
        self.mr,
        field_def=mox.IgnoreArg(),
        initial_applicable_type='',
        initial_choices='',
        initial_admins='',
        initial_editors='',
        initial_approvers='',
        initial_is_restricted_field=False)
    self.mox.ReplayAll()

    url = self.servlet._ProcessEditField(
        self.mr, post_data, self.config, self.approval_fd)
    self.assertEqual('Please provide at least one default approver.',
                     self.mr.errors.approvers)
    self.assertIsNone(url)

  def testProcessEditField_Approval(self):
    self.mr.field_name = 'UIReview'
    post_data = fake.PostData(
        name=['UIReview'],
        admin_names=[''],
        editor_names=[''],
        survey=['WIll there be UI changes?'],
        approver_names=['sport@example.com, gatsby@example.com'])


    url = self.servlet._ProcessEditField(
        self.mr, post_data, self.config, self.approval_fd)
    self.assertTrue('/fields/detail?field=UIReview&saved=1&' in url)

    approval_def = tracker_bizobj.FindApprovalDef('UIReview', self.config)
    self.assertEqual(len(approval_def.approver_ids), 2)
    self.assertEqual(sorted(approval_def.approver_ids), sorted([111, 222]))
