# Copyright 2018 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Tests for scripts/repo_sync_manifest."""

import os
from unittest import mock

from chromite.cbuildbot import manifest_version
from chromite.cbuildbot import repository
from chromite.lib import cros_test_lib
from chromite.scripts import repo_sync_manifest


class RepoSyncManifestTest(cros_test_lib.RunCommandTempDirTestCase):
  """Unit tests for repo_sync_manifest."""

  INT_MANIFEST_URL = ('https://chrome-internal-review.googlesource.com/'
                      'chromeos/manifest-internal')
  EXT_MANIFEST_URL = ('https://chromium.googlesource.com/chromiumos/manifest')

  MV_INT_URL = ('https://chrome-internal.googlesource.com/chromeos/'
                'manifest-versions')
  MV_EXT_URL = ('https://chromium.googlesource.com/chromiumos/'
                'manifest-versions')

  def setUp(self):
    self.repo_dir = os.path.join(self.tempdir, 'repo')
    self.repo_url = os.path.join(self.tempdir, '.repo/repo')
    self.preload_src = os.path.join(self.tempdir, 'source')
    self.git_cache = os.path.join(self.tempdir, 'git_cache')
    self.manifest = os.path.join(self.tempdir, 'manifest.xml')
    self.mv_ext = os.path.join(self.tempdir, 'mv_ext')
    self.mv_int = os.path.join(self.tempdir, 'mv_int')
    self.manifest_url = 'manifest.com'

    self.repo_mock = self.PatchObject(
        repository, 'RepoRepository', autospec=True)

    self.refresh_manifest_mock = self.PatchObject(
        manifest_version, 'RefreshManifestCheckout', autospec=True)

    self.resolve_buildspec_mock = self.PatchObject(
        manifest_version, 'ResolveBuildspec', autospec=True)

    self.resolve_version_mock = self.PatchObject(
        manifest_version, 'ResolveBuildspecVersion', autospec=True)


  def notestHelp(self):
    with self.assertRaises(SystemExit):
      repo_sync_manifest.main([
          '--help',
      ])

  def testMinimal(self):
    repo_sync_manifest.main([
        '--repo-root', self.repo_dir,
    ])

    # Ensure manifest_versions is not updated.
    self.assertEqual(self.refresh_manifest_mock.mock_calls, [])

    # Ensure RepoRepository created and Sync'd as expected.
    self.assertEqual(self.repo_mock.mock_calls, [
        mock.call(
            directory=self.repo_dir,
            manifest_repo_url=self.INT_MANIFEST_URL,
            branch='master',
            git_cache_dir=None,
            repo_url=None,
            groups=None,
        ),
        mock.call().Sync(detach=True, local_manifest=None)
    ])

  def testMinimalExternal(self):
    repo_sync_manifest.main([
        '--repo-root', self.repo_dir,
        '--external',
    ])

    # Ensure manifest_versions is not updated.
    self.assertEqual(self.refresh_manifest_mock.mock_calls, [])

    # Ensure RepoRepository created and Sync'd as expected.
    self.assertEqual(self.repo_mock.mock_calls, [
        mock.call(
            directory=self.repo_dir,
            manifest_repo_url=self.EXT_MANIFEST_URL,
            branch='master',
            git_cache_dir=None,
            repo_url=None,
            groups=None,
        ),
        mock.call().Sync(detach=True, local_manifest=None)
    ])

  def testMinimalManifestUrl(self):
    repo_sync_manifest.main([
        '--repo-root', self.repo_dir,
        '--manifest-url', self.manifest_url,
    ])

    # Ensure manifest_versions is not updated.
    self.assertEqual(self.refresh_manifest_mock.mock_calls, [])

    # Ensure RepoRepository created and Sync'd as expected.
    self.assertEqual(self.repo_mock.mock_calls, [
        mock.call(
            directory=self.repo_dir,
            manifest_repo_url=self.manifest_url,
            branch='master',
            git_cache_dir=None,
            repo_url=None,
            groups=None,
        ),
        mock.call().Sync(detach=True, local_manifest=None)
    ])

  def testBranch(self):
    repo_sync_manifest.main([
        '--repo-root', self.repo_dir,
        '--branch', 'branch'
    ])

    # Ensure RepoRepository created and Sync'd as expected.
    self.assertEqual(self.repo_mock.mock_calls, [
        mock.call(
            directory=self.repo_dir,
            manifest_repo_url=self.INT_MANIFEST_URL,
            branch='branch',
            git_cache_dir=None,
            repo_url=None,
            groups=None,
        ),
        mock.call().Sync(detach=True, local_manifest=None)
    ])

    # Ensure manifest_versions is not updated.
    self.assertEqual(self.refresh_manifest_mock.mock_calls, [])

  def testBuildSpec(self):
    self.resolve_buildspec_mock.return_value = 'resolved_buildspec'

    repo_sync_manifest.main([
        '--repo-root', self.repo_dir,
        '--buildspec', 'test/spec',
        '--manifest-versions-int', self.mv_int,
    ])

    # Ensure manifest-versions interactions are correct.
    self.assertEqual(self.refresh_manifest_mock.mock_calls, [
        mock.call(self.mv_int, self.MV_INT_URL)])
    self.assertEqual(self.resolve_buildspec_mock.mock_calls, [
        mock.call(self.mv_int, 'test/spec')])
    self.assertEqual(self.resolve_version_mock.mock_calls, [])

    # Ensure RepoRepository created and Sync'd as expected.
    self.assertEqual(self.repo_mock.mock_calls, [
        mock.call(
            directory=self.repo_dir,
            manifest_repo_url=self.INT_MANIFEST_URL,
            branch='master',
            git_cache_dir=None,
            repo_url=None,
            groups=None,
        ),
        mock.call().Sync(detach=True, local_manifest='resolved_buildspec')
    ])

  def testBuildSpecExternal(self):
    self.resolve_buildspec_mock.return_value = 'resolved_buildspec'

    repo_sync_manifest.main([
        '--repo-root', self.repo_dir,
        '--buildspec', 'test/spec',
        '--manifest-versions-ext', self.mv_ext,
        '--external',
    ])

    # Ensure manifest-versions interactions are correct.
    self.assertEqual(self.refresh_manifest_mock.mock_calls, [
        mock.call(self.mv_ext, self.MV_EXT_URL)])
    self.assertEqual(self.resolve_buildspec_mock.mock_calls, [
        mock.call(self.mv_ext, 'test/spec')])
    self.assertEqual(self.resolve_version_mock.mock_calls, [])

    # Ensure RepoRepository created and Sync'd as expected.
    self.assertEqual(self.repo_mock.mock_calls, [
        mock.call(
            directory=self.repo_dir,
            manifest_repo_url=self.EXT_MANIFEST_URL,
            branch='master',
            git_cache_dir=None,
            repo_url=None,
            groups=None,
        ),
        mock.call().Sync(detach=True, local_manifest='resolved_buildspec')
    ])

  def testVersion(self):
    self.resolve_version_mock.return_value = 'resolved_buildspec'

    repo_sync_manifest.main([
        '--repo-root', self.repo_dir,
        '--version', '1.2.3',
        '--manifest-versions-int', self.mv_int,
    ])

    # Ensure manifest-versions interactions are correct.
    self.assertEqual(self.refresh_manifest_mock.mock_calls, [
        mock.call(self.mv_int, self.MV_INT_URL)])
    self.assertEqual(self.resolve_buildspec_mock.mock_calls, [])
    self.assertEqual(self.resolve_version_mock.mock_calls, [
        mock.call(self.mv_int, '1.2.3')])

    # Ensure RepoRepository created and Sync'd as expected.
    self.assertEqual(self.repo_mock.mock_calls, [
        mock.call(
            directory=self.repo_dir,
            manifest_repo_url=self.INT_MANIFEST_URL,
            branch='master',
            git_cache_dir=None,
            repo_url=None,
            groups=None,
        ),
        mock.call().Sync(detach=True, local_manifest='resolved_buildspec')
    ])

  def testVersionExternal(self):
    self.resolve_version_mock.return_value = 'resolved_buildspec'

    repo_sync_manifest.main([
        '--repo-root', self.repo_dir,
        '--version', '1.2.3',
        '--manifest-versions-ext', self.mv_ext,
        '--external',
    ])

    # Ensure manifest-versions interactions are correct.
    self.assertEqual(self.refresh_manifest_mock.mock_calls, [
        mock.call(self.mv_ext, self.MV_EXT_URL)])
    self.assertEqual(self.resolve_buildspec_mock.mock_calls, [])
    self.assertEqual(self.resolve_version_mock.mock_calls, [
        mock.call(self.mv_ext, '1.2.3')])

    # Ensure RepoRepository created and Sync'd as expected.
    self.assertEqual(self.repo_mock.mock_calls, [
        mock.call(
            directory=self.repo_dir,
            manifest_repo_url=self.EXT_MANIFEST_URL,
            branch='master',
            git_cache_dir=None,
            repo_url=None,
            groups=None,
        ),
        mock.call().Sync(detach=True, local_manifest='resolved_buildspec')
    ])

  def testBuildSpecNoManifestVersions(self):
    with self.assertRaises(AssertionError):
      repo_sync_manifest.main([
          '--repo-root', self.repo_dir,
          '--buildspec', 'test/spec',
      ])

    with self.assertRaises(AssertionError):
      repo_sync_manifest.main([
          '--repo-root', self.repo_dir,
          '--buildspec', 'test/spec',
          '--external',
      ])

  def testLocalManifest(self):
    repo_sync_manifest.main([
        '--repo-root', self.repo_dir,
        '--manifest-file', self.manifest,
    ])

    # Ensure manifest_versions is not updated.
    self.assertEqual(self.refresh_manifest_mock.mock_calls, [])

    # Ensure RepoRepository created and Sync'd as expected.
    self.assertEqual(self.repo_mock.mock_calls, [
        mock.call(
            directory=self.repo_dir,
            manifest_repo_url=self.INT_MANIFEST_URL,
            branch='master',
            git_cache_dir=None,
            repo_url=None,
            groups=None,
        ),
        mock.call().Sync(detach=True, local_manifest=self.manifest)
    ])

  def testGroups(self):
    repo_sync_manifest.main([
        '--repo-root', self.repo_dir,
        '--manifest-file', self.manifest,
        '--groups', 'all'
    ])

    # Ensure manifest_versions is not updated.
    self.assertEqual(self.refresh_manifest_mock.mock_calls, [])

    # Ensure RepoRepository created and Sync'd as expected.
    self.assertEqual(self.repo_mock.mock_calls, [
        mock.call(
            directory=self.repo_dir,
            manifest_repo_url=self.INT_MANIFEST_URL,
            branch='master',
            git_cache_dir=None,
            repo_url=None,
            groups='all',
        ),
        mock.call().Sync(detach=True, local_manifest=self.manifest)
    ])

  def testOptimizations(self):
    repo_sync_manifest.main([
        '--repo-root', self.repo_dir,
        '--copy-repo', self.preload_src,
        '--git-cache', self.git_cache,
        '--repo-url', self.repo_url,
    ])

    # Ensure manifest_versions is not updated.
    self.assertEqual(self.refresh_manifest_mock.mock_calls, [])

    # Ensure RepoRepository created and Sync'd as expected.
    self.assertEqual(self.repo_mock.mock_calls, [
        mock.call(
            directory=self.repo_dir,
            manifest_repo_url=self.INT_MANIFEST_URL,
            branch='master',
            git_cache_dir=self.git_cache,
            repo_url=self.repo_url,
            groups=None,
        ),
        mock.call().PreLoad(self.preload_src),
        mock.call().Sync(detach=True, local_manifest=None)
    ])
