# 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 sitewide_helpers module."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import six
import unittest

from mrproto import project_pb2
from services import service_manager
from sitewide import sitewide_helpers
from testing import fake


REGULAR_USER_ID = 111
ADMIN_USER_ID = 222
OTHER_USER_ID = 333

# Test project IDs
REGULAR_OWNER_LIVE = 1001
REGULAR_OWNER_ARCHIVED = 1002
REGULAR_OWNER_DELETABLE = 1003
REGULAR_COMMITTER_LIVE = 2001
REGULAR_COMMITTER_ARCHIVED = 2002
REGULAR_COMMITTER_DELETABLE = 2003
OTHER_OWNER_LIVE = 3001
OTHER_OWNER_ARCHIVED = 3002
OTHER_OWNER_DELETABLE = 3003
OTHER_COMMITTER_LIVE = 4001
MEMBERS_ONLY = 5001


class HelperFunctionsTest(unittest.TestCase):

  def setUp(self):
    self.services = service_manager.Services(
        project=fake.ProjectService(),
        user=fake.UserService(),
        project_star=fake.ProjectStarService())
    self.cnxn = 'fake cnxn'

    for user_id in (ADMIN_USER_ID, REGULAR_USER_ID, OTHER_USER_ID):
      self.services.user.TestAddUser('ignored_%s@gmail.com' % user_id, user_id)

    self.regular_owner_live = self.services.project.TestAddProject(
        'regular-owner-live', state=project_pb2.ProjectState.LIVE,
        owner_ids=[REGULAR_USER_ID], project_id=REGULAR_OWNER_LIVE)
    self.regular_owner_archived = self.services.project.TestAddProject(
        'regular-owner-archived', state=project_pb2.ProjectState.ARCHIVED,
        owner_ids=[REGULAR_USER_ID], project_id=REGULAR_OWNER_ARCHIVED)
    self.regular_owner_deletable = self.services.project.TestAddProject(
        'regular-owner-deletable', state=project_pb2.ProjectState.DELETABLE,
        owner_ids=[REGULAR_USER_ID], project_id=REGULAR_OWNER_DELETABLE)
    self.regular_committer_live = self.services.project.TestAddProject(
        'regular-committer-live', state=project_pb2.ProjectState.LIVE,
        committer_ids=[REGULAR_USER_ID], project_id=REGULAR_COMMITTER_LIVE)
    self.regular_committer_archived = self.services.project.TestAddProject(
        'regular-committer-archived', state=project_pb2.ProjectState.ARCHIVED,
        committer_ids=[REGULAR_USER_ID], project_id=REGULAR_COMMITTER_ARCHIVED)
    self.regular_committer_deletable = self.services.project.TestAddProject(
        'regular-committer-deletable', state=project_pb2.ProjectState.DELETABLE,
        committer_ids=[REGULAR_USER_ID], project_id=REGULAR_COMMITTER_DELETABLE)
    self.other_owner_live = self.services.project.TestAddProject(
        'other-owner-live', state=project_pb2.ProjectState.LIVE,
        owner_ids=[OTHER_USER_ID], project_id=OTHER_OWNER_LIVE)
    self.other_owner_archived = self.services.project.TestAddProject(
        'other-owner-archived', state=project_pb2.ProjectState.ARCHIVED,
        owner_ids=[OTHER_USER_ID], project_id=OTHER_OWNER_ARCHIVED)
    self.other_owner_deletable = self.services.project.TestAddProject(
        'other-owner-deletable', state=project_pb2.ProjectState.DELETABLE,
        owner_ids=[OTHER_USER_ID], project_id=OTHER_OWNER_DELETABLE)
    self.other_committer_live = self.services.project.TestAddProject(
        'other-committer-live', state=project_pb2.ProjectState.LIVE,
        committer_ids=[OTHER_USER_ID], project_id=OTHER_COMMITTER_LIVE)

    self.regular_user = self.services.user.GetUser(self.cnxn, REGULAR_USER_ID)

    self.admin_user = self.services.user.TestAddUser(
        'administrator@chromium.org', ADMIN_USER_ID)
    self.admin_user.is_site_admin = True

    self.other_user = self.services.user.GetUser(self.cnxn, OTHER_USER_ID)

    self.members_only_project = self.services.project.TestAddProject(
        'members-only', owner_ids=[REGULAR_USER_ID], project_id=MEMBERS_ONLY)
    self.members_only_project.access = project_pb2.ProjectAccess.MEMBERS_ONLY

  def assertProjectsAnyOrder(self, actual_projects, *expected_projects):
    # Check names rather than Project objects so that output is easier to read.
    actual_names = [p.project_name for p in actual_projects]
    expected_names = [p.project_name for p in expected_projects]
    six.assertCountEqual(self, expected_names, actual_names)

  def testFilterViewableProjects_CantViewArchived(self):
    projects = list(sitewide_helpers.FilterViewableProjects(
        list(self.services.project.test_projects.values()),
        self.regular_user, {REGULAR_USER_ID}))
    self.assertProjectsAnyOrder(
        projects, self.regular_owner_live, self.regular_committer_live,
        self.other_owner_live, self.other_committer_live,
        self.members_only_project)

  def testFilterViewableProjects_NonMemberCantViewMembersOnly(self):
    projects = list(sitewide_helpers.FilterViewableProjects(
        list(self.services.project.test_projects.values()),
        self.other_user, {OTHER_USER_ID}))
    self.assertProjectsAnyOrder(
        projects, self.regular_owner_live, self.regular_committer_live,
        self.other_owner_live, self.other_committer_live)

  def testFilterViewableProjects_AdminCanViewAny(self):
    projects = list(sitewide_helpers.FilterViewableProjects(
        list(self.services.project.test_projects.values()),
        self.admin_user, {ADMIN_USER_ID}))
    self.assertProjectsAnyOrder(
        projects, self.regular_owner_live, self.regular_committer_live,
        self.other_owner_live, self.other_committer_live,
        self.members_only_project)

  def testGetStarredProjects_OnlyViewableLiveStarred(self):
    viewed_user_id = 123
    for p in self.services.project.test_projects.values():
      # We go straight to the services layer because this is a test set up
      # rather than an actual user request.
      self.services.project_star.SetStar(
          self.cnxn, p.project_id, viewed_user_id, True)

    self.assertProjectsAnyOrder(
        sitewide_helpers.GetViewableStarredProjects(
            self.cnxn, self.services, viewed_user_id,
            {REGULAR_USER_ID}, self.regular_user),
        self.regular_owner_live, self.regular_committer_live,
        self.other_owner_live, self.other_committer_live,
        self.members_only_project)

  def testGetStarredProjects_MembersOnly(self):
    # Both users were able to star the project in the past.  The stars do not
    # go away even if access to the project changes.
    self.services.project_star.SetStar(
        self.cnxn, self.members_only_project.project_id, REGULAR_USER_ID, True)
    self.services.project_star.SetStar(
        self.cnxn, self.members_only_project.project_id, OTHER_USER_ID, True)

    # But now, only one of them is currently a member, so only regular_user
    # can see the starred project in the lists.
    self.assertProjectsAnyOrder(
        sitewide_helpers.GetViewableStarredProjects(
            self.cnxn, self.services, REGULAR_USER_ID, {REGULAR_USER_ID},
            self.regular_user),
        self.members_only_project)
    self.assertProjectsAnyOrder(
        sitewide_helpers.GetViewableStarredProjects(
            self.cnxn, self.services, OTHER_USER_ID, {REGULAR_USER_ID},
            self.regular_user),
        self.members_only_project)

    # The other user cannot see the project, so they do not see it in either
    # list of starred projects.
    self.assertProjectsAnyOrder(
        sitewide_helpers.GetViewableStarredProjects(
            self.cnxn, self.services, REGULAR_USER_ID, {OTHER_USER_ID},
            self.other_user))  # No expected projects listed.
    self.assertProjectsAnyOrder(
        sitewide_helpers.GetViewableStarredProjects(
            self.cnxn, self.services, OTHER_USER_ID, {OTHER_USER_ID},
            self.other_user))  # No expected projects listed.
