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

"""Unit tests for the componentdetail servlet."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import unittest

from mock import Mock

try:
  from mox3 import mox
except ImportError:
  import mox

from features import filterrules_helpers
from framework import permissions
from mrproto import project_pb2
from services import service_manager
from services import template_svc
from testing import fake
from testing import testing_helpers
from tracker import componentdetail
from tracker import tracker_bizobj


class ComponentDetailTest(unittest.TestCase):

  def setUp(self):
    self.services = service_manager.Services(
        user=fake.UserService(),
        issue=fake.IssueService(),
        config=fake.ConfigService(),
        template=Mock(spec=template_svc.TemplateService),
        project=fake.ProjectService())
    self.servlet = componentdetail.ComponentDetail(services=self.services)
    self.project = self.services.project.TestAddProject('proj')
    self.mr = testing_helpers.MakeMonorailRequest(
        project=self.project, perms=permissions.OWNER_ACTIVE_PERMISSIONSET)
    self.mr.auth.email = 'b@example.com'
    self.config = self.services.config.GetProjectConfig(
        'fake cnxn', self.project.project_id)
    self.services.config.StoreConfig('fake cnxn', self.config)
    self.cd = tracker_bizobj.MakeComponentDef(
        1, self.project.project_id, 'BackEnd', 'doc', False, [], [111], 100000,
        122, 10000000, 133)
    self.config.component_defs = [self.cd]
    self.services.user.TestAddUser('a@example.com', 111)
    self.services.user.TestAddUser('b@example.com', 122)
    self.services.user.TestAddUser('c@example.com', 133)
    self.mr.component_path = 'BackEnd'

    self.mox = mox.Mox()

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

  def testGetComponentDef_NotFound(self):
    self.mr.component_path = 'NeverHeardOfIt'
    self.assertRaises(Exception, self.servlet._GetComponentDef, self.mr)

  def testGetComponentDef_Normal(self):
    actual_config, actual_cd = self.servlet._GetComponentDef(self.mr)
    self.assertEqual(self.config, actual_config)
    self.assertEqual(self.cd, actual_cd)

  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 component 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_COMPONENTS,
                     page_data['admin_tab_mode'])
    self.assertTrue(page_data['allow_edit'])
    self.assertEqual([], page_data['initial_admins'])
    component_def_view = page_data['component_def']
    self.assertEqual('BackEnd', component_def_view.path)

  def testGatherPageData_ReadOnly(self):
    self.mr.perms = permissions.READ_ONLY_PERMISSIONSET
    page_data = self.servlet.GatherPageData(self.mr)
    self.assertEqual(self.servlet.PROCESS_TAB_COMPONENTS,
                     page_data['admin_tab_mode'])
    self.assertFalse(page_data['allow_edit'])
    self.assertFalse(page_data['allow_delete'])
    self.assertEqual([], page_data['initial_admins'])
    component_def_view = page_data['component_def']
    self.assertEqual('BackEnd', component_def_view.path)

  def testGatherPageData_ObscuredCreatorModifier(self):
    page_data = self.servlet.GatherPageData(self.mr)

    self.assertEqual('b...@example.com', page_data['creator'].display_name)
    self.assertEqual('/u/122/', page_data['creator'].profile_url)
    self.assertEqual('Jan 1970', page_data['created'])
    self.assertEqual('c...@example.com', page_data['modifier'].display_name)
    self.assertEqual('/u/133/', page_data['modifier'].profile_url)
    self.assertEqual('Apr 1970', page_data['modified'])

  def testGatherPageData_VisibleCreatorModifierForAdmin(self):
    self.mr.auth.user_pb.is_site_admin = True
    page_data = self.servlet.GatherPageData(self.mr)

    self.assertEqual('b@example.com', page_data['creator'].display_name)
    self.assertEqual('/u/b@example.com/', page_data['creator'].profile_url)
    self.assertEqual('Jan 1970', page_data['created'])
    self.assertEqual('c@example.com', page_data['modifier'].display_name)
    self.assertEqual('/u/c@example.com/', page_data['modifier'].profile_url)
    self.assertEqual('Apr 1970', page_data['modified'])

  def testGatherPageData_VisibleCreatorForSelf(self):
    self.mr.auth.user_id = 122
    page_data = self.servlet.GatherPageData(self.mr)

    self.assertEqual('b@example.com', page_data['creator'].display_name)
    self.assertEqual('/u/b@example.com/', page_data['creator'].profile_url)
    self.assertEqual('Jan 1970', page_data['created'])
    # Modifier should still be obscured.
    self.assertEqual('c...@example.com', page_data['modifier'].display_name)
    self.assertEqual('/u/133/', page_data['modifier'].profile_url)
    self.assertEqual('Apr 1970', page_data['modified'])

  def testGatherPageData_VisibleCreatorModifierForUnobscuredEmail(self):
    creator = self.services.user.GetUser(self.mr.cnxn, 122)
    creator.obscure_email = False
    modifier = self.services.user.GetUser(self.mr.cnxn, 133)
    modifier.obscure_email = False
    page_data = self.servlet.GatherPageData(self.mr)

    self.assertEqual('b@example.com', page_data['creator'].display_name)
    self.assertEqual('/u/b@example.com/', page_data['creator'].profile_url)
    self.assertEqual('Jan 1970', page_data['created'])
    self.assertEqual('c@example.com', page_data['modifier'].display_name)
    self.assertEqual('/u/c@example.com/', page_data['modifier'].profile_url)
    self.assertEqual('Apr 1970', page_data['modified'])

  def testGatherPageData_WithSubComponents(self):
    subcd = tracker_bizobj.MakeComponentDef(
        2, self.project.project_id, 'BackEnd>Worker', 'doc', False, [], [111],
        0, 122)
    self.config.component_defs.append(subcd)
    page_data = self.servlet.GatherPageData(self.mr)
    self.assertFalse(page_data['allow_delete'])
    self.assertEqual([subcd], page_data['subcomponents'])

  def testGatherPageData_WithTemplates(self):
    self.services.template.TemplatesWithComponent.return_value = ['template']
    page_data = self.servlet.GatherPageData(self.mr)
    self.assertFalse(page_data['allow_delete'])
    self.assertEqual(['template'], page_data['templates'])

  def testProcessFormData_Permission(self):
    """Only owners can edit components."""
    mr = testing_helpers.MakeMonorailRequest(
        project=self.project,
        perms=permissions.CONTRIBUTOR_ACTIVE_PERMISSIONSET)
    mr.component_path = 'BackEnd'
    post_data = fake.PostData(
        name=['BackEnd'],
        deletecomponent=['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=['BackEnd'],
        deletecomponent=['Submit'])
    url = self.servlet.ProcessFormData(self.mr, post_data)
    self.assertTrue('/adminComponents?deleted=1&' in url)
    self.assertIsNone(
        tracker_bizobj.FindComponentDef('BackEnd', self.config))

  def testProcessFormData_Delete_WithSubComponent(self):
    subcd = tracker_bizobj.MakeComponentDef(
        2, self.project.project_id, 'BackEnd>Worker', 'doc', False, [], [111],
        0, 122)
    self.config.component_defs.append(subcd)

    post_data = fake.PostData(
        name=['BackEnd'],
        deletecomponent=['Submit'])
    with self.assertRaises(permissions.PermissionException) as cm:
      self.servlet.ProcessFormData(self.mr, post_data)
    self.assertEqual(
        'User tried to delete component that had subcomponents',
        str(cm.exception))

  def testProcessFormData_Edit(self):
    post_data = fake.PostData(
        leaf_name=['BackEnd'],
        docstring=['This is where the magic happens'],
        deprecated=[True],
        admins=['a@example.com'],
        cc=['a@example.com'],
        labels=['Hot, Cold'])

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

    self.mox.VerifyAll()
    self.assertTrue('/components/detail?component=BackEnd&saved=1&' in url)
    config = self.services.config.GetProjectConfig(
        self.mr.cnxn, self.mr.project_id)

    cd = tracker_bizobj.FindComponentDef('BackEnd', config)
    self.assertEqual('BackEnd', cd.path)
    self.assertEqual(
        'This is where the magic happens',
        cd.docstring)
    self.assertEqual(True, cd.deprecated)
    self.assertEqual([111], cd.admin_ids)
    self.assertEqual([111], cd.cc_ids)

  def testProcessDeleteComponent(self):
    self.servlet._ProcessDeleteComponent(self.mr, self.cd)
    self.assertIsNone(
        tracker_bizobj.FindComponentDef('BackEnd', self.config))

  def testProcessEditComponent(self):
    post_data = fake.PostData(
        leaf_name=['BackEnd'],
        docstring=['This is where the magic happens'],
        deprecated=[True],
        admins=['a@example.com'],
        cc=['a@example.com'],
        labels=['Hot, Cold'])

    self.servlet._ProcessEditComponent(
        self.mr, post_data, self.config, self.cd)

    self.mox.VerifyAll()
    config = self.services.config.GetProjectConfig(
        self.mr.cnxn, self.mr.project_id)
    cd = tracker_bizobj.FindComponentDef('BackEnd', config)
    self.assertEqual('BackEnd', cd.path)
    self.assertEqual(
        'This is where the magic happens',
        cd.docstring)
    self.assertEqual(True, cd.deprecated)
    self.assertEqual([111], cd.admin_ids)
    self.assertEqual([111], cd.cc_ids)
    # Assert that creator and created were not updated.
    self.assertEqual(122, cd.creator_id)
    self.assertEqual(100000, cd.created)
    # Assert that modifier and modified were updated.
    self.assertEqual(122, cd.modifier_id)
    self.assertTrue(cd.modified > 10000000)

  def testProcessEditComponent_RenameWithSubComponents(self):
    subcd_1 = tracker_bizobj.MakeComponentDef(
        2, self.project.project_id, 'BackEnd>Worker1', 'doc', False, [], [111],
        0, 125, 3, 126)
    subcd_2 = tracker_bizobj.MakeComponentDef(
        3, self.project.project_id, 'BackEnd>Worker2', 'doc', False, [], [111],
        0, 125, 4, 127)
    self.config.component_defs.extend([subcd_1, subcd_2])

    self.mox.StubOutWithMock(filterrules_helpers, 'RecomputeAllDerivedFields')
    filterrules_helpers.RecomputeAllDerivedFields(
        self.mr.cnxn, self.services, self.mr.project, self.config)
    self.mox.ReplayAll()
    post_data = fake.PostData(
        leaf_name=['BackEnds'],
        docstring=['This is where the magic happens'],
        deprecated=[True],
        admins=['a@example.com'],
        cc=['a@example.com'],
        labels=[''])

    self.servlet._ProcessEditComponent(
        self.mr, post_data, self.config, self.cd)

    self.mox.VerifyAll()
    config = self.services.config.GetProjectConfig(
        self.mr.cnxn, self.mr.project_id)
    cd = tracker_bizobj.FindComponentDef('BackEnds', config)
    self.assertEqual('BackEnds', cd.path)
    subcd_1 = tracker_bizobj.FindComponentDef('BackEnds>Worker1', config)
    self.assertEqual('BackEnds>Worker1', subcd_1.path)
    # Assert that creator and modifier have not changed for subcd_1.
    self.assertEqual(125, subcd_1.creator_id)
    self.assertEqual(0, subcd_1.created)
    self.assertEqual(126, subcd_1.modifier_id)
    self.assertEqual(3, subcd_1.modified)

    subcd_2 = tracker_bizobj.FindComponentDef('BackEnds>Worker2', config)
    self.assertEqual('BackEnds>Worker2', subcd_2.path)
    # Assert that creator and modifier have not changed for subcd_2.
    self.assertEqual(125, subcd_2.creator_id)
    self.assertEqual(0, subcd_2.created)
    self.assertEqual(127, subcd_2.modifier_id)
    self.assertEqual(4, subcd_2.modified)
