# 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

"""Tests for the reap module."""
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import

import unittest

import mock
import mox

from mock import Mock

from framework import reap
from framework import sql
from proto import project_pb2
from services import service_manager
from services import template_svc
from testing import fake
from testing import testing_helpers


class ReapTest(unittest.TestCase):

  def setUp(self):
    self.project_service = fake.ProjectService()
    self.issue_service = fake.IssueService()
    self.issue_star_service = fake.IssueStarService()
    self.config_service = fake.ConfigService()
    self.features_service = fake.FeaturesService()
    self.project_star_service = fake.ProjectStarService()
    self.services = service_manager.Services(
        project=self.project_service,
        issue=self.issue_service,
        issue_star=self.issue_star_service,
        config=self.config_service,
        features=self.features_service,
        project_star=self.project_star_service,
        template=Mock(spec=template_svc.TemplateService),
        user=fake.UserService(),
        usergroup=fake.UserGroupService())

    self.proj1_id = 1001
    self.proj1_issue_id = 111
    self.proj1 = self.project_service.TestAddProject(
        name='proj1', project_id=self.proj1_id)
    self.proj2_id = 1002
    self.proj2_issue_id = 112
    self.proj2 = self.project_service.TestAddProject(
        name='proj2', project_id=self.proj2_id)

    self.mox = mox.Mox()
    self.cnxn = self.mox.CreateMock(sql.MonorailConnection)
    self.project_service.project_tbl = self.mox.CreateMock(sql.SQLTableManager)
    self.issue_service.issue_tbl = self.mox.CreateMock(sql.SQLTableManager)

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

  def setUpMarkDoomedProjects(self):
    self.project_service.project_tbl.Select(
        self.cnxn, cols=['project_id'], limit=1000, state='archived',
        where=mox.IgnoreArg()).AndReturn([[self.proj1_id]])

  def testMarkDoomedProjects(self):
    self.setUpMarkDoomedProjects()
    reaper = reap.Reap('req', 'resp', services=self.services)

    self.mox.ReplayAll()
    doomed_project_ids = reaper._MarkDoomedProjects(self.cnxn)
    self.mox.VerifyAll()

    self.assertEqual([self.proj1_id], doomed_project_ids)
    self.assertEqual(project_pb2.ProjectState.DELETABLE, self.proj1.state)
    self.assertEqual('DELETABLE_%s' % self.proj1_id, self.proj1.project_name)

  def setUpExpungeParts(self):
    self.project_service.project_tbl.Select(
        self.cnxn, cols=['project_id'], limit=100,
        state='deletable').AndReturn([[self.proj1_id], [self.proj2_id]])
    self.issue_service.issue_tbl.Select(
        self.cnxn, cols=['id'], limit=1000,
        project_id=self.proj1_id).AndReturn([[self.proj1_issue_id]])
    self.issue_service.issue_tbl.Select(
        self.cnxn, cols=['id'], limit=1000,
        project_id=self.proj2_id).AndReturn([[self.proj2_issue_id]])

  def testExpungeDeletableProjects(self):
    self.setUpExpungeParts()
    reaper = reap.Reap('req', 'resp', services=self.services)

    self.mox.ReplayAll()
    expunged_project_ids = reaper._ExpungeDeletableProjects(self.cnxn)
    self.mox.VerifyAll()

    self.assertEqual([self.proj1_id, self.proj2_id], expunged_project_ids)
    # Verify all expected expunge methods were called.
    self.assertEqual(
        [self.proj1_issue_id, self.proj2_issue_id],
        self.services.issue_star.expunged_item_ids)
    self.assertEqual(
        [self.proj1_issue_id, self.proj2_issue_id],
        self.services.issue.expunged_issues)
    self.assertEqual(
        [self.proj1_id, self.proj2_id], self.services.config.expunged_configs)
    self.assertEqual(
        [self.proj1_id, self.proj2_id],
        self.services.features.expunged_saved_queries)
    self.assertEqual(
        [self.proj1_id, self.proj2_id],
        self.services.features.expunged_filter_rules)
    self.assertEqual(
        [self.proj1_id, self.proj2_id],
        self.services.issue.expunged_former_locations)
    self.assertEqual(
        [self.proj1_id, self.proj2_id], self.services.issue.expunged_local_ids)
    self.assertEqual(
        [self.proj1_id, self.proj2_id],
        self.services.features.expunged_quick_edit)
    self.assertEqual(
        [self.proj1_id, self.proj2_id],
        self.services.project_star.expunged_item_ids)
    self.assertEqual(0, len(self.services.project.test_projects))
    self.services.template.ExpungeProjectTemplates.assert_has_calls([
        mock.call(self.cnxn, 1001),
        mock.call(self.cnxn, 1002)])
