#!/usr/bin/env python
# Copyright (c) 2012 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.

"""Unit tests for scm.py."""

import logging
import os
import sys
import unittest

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from testing_support import fake_repos
from testing_support.super_mox import SuperMoxTestBase

import scm
import subprocess2


# Access to a protected member XXX of a client class
# pylint: disable=W0212


class BaseTestCase(SuperMoxTestBase):
  # Like unittest's assertRaises, but checks for Gclient.Error.
  def assertRaisesError(self, msg, fn, *args, **kwargs):
    try:
      fn(*args, **kwargs)
    except scm.gclient_utils.Error, e:
      self.assertEquals(e.args[0], msg)
    else:
      self.fail('%s not raised' % msg)


class BaseSCMTestCase(BaseTestCase):
  def setUp(self):
    BaseTestCase.setUp(self)
    self.mox.StubOutWithMock(scm.gclient_utils, 'CheckCallAndFilter')
    self.mox.StubOutWithMock(scm.gclient_utils, 'CheckCallAndFilterAndHeader')
    self.mox.StubOutWithMock(subprocess2, 'Popen')
    self.mox.StubOutWithMock(subprocess2, 'communicate')


class RootTestCase(BaseSCMTestCase):
  def testMembersChanged(self):
    self.mox.ReplayAll()
    members = [
        'cStringIO',
        'determine_scm',
        'ElementTree',
        'gclient_utils',
        'GenFakeDiff',
        'GetCasedPath',
        'GIT',
        'glob',
        'logging',
        'only_int',
        'os',
        're',
        'subprocess2',
        'SVN',
        'sys',
        'tempfile',
        'time',
        'ValidateEmail',
    ]
    # If this test fails, you should add the relevant test.
    self.compareMembers(scm, members)


class GitWrapperTestCase(BaseSCMTestCase):
  def testMembersChanged(self):
    members = [
        'ApplyEnvVars',
        'AssertVersion',
        'Capture',
        'CaptureStatus',
        'CleanupDir',
        'current_version',
        'FetchUpstreamTuple',
        'GenerateDiff',
        'GetBlessedSha1ForSvnRev',
        'GetBranch',
        'GetBranchRef',
        'GetCheckoutRoot',
        'GetDifferentFiles',
        'GetEmail',
        'GetGitDir',
        'GetGitSvnHeadRev',
        'GetPatchName',
        'GetSha1ForSvnRev',
        'GetSVNBranch',
        'GetUpstreamBranch',
        'IsDirectoryVersioned',
        'IsGitSvn',
        'IsInsideWorkTree',
        'IsValidRevision',
        'IsWorkTreeDirty',
        'MatchSvnGlob',
        'ParseGitSvnSha1',
        'RefToRemoteRef',
        'ShortBranchName',
    ]
    # If this test fails, you should add the relevant test.
    self.compareMembers(scm.GIT, members)

  def testGetEmail(self):
    self.mox.StubOutWithMock(scm.GIT, 'Capture')
    scm.GIT.Capture(['config', 'user.email'], cwd=self.root_dir
                    ).AndReturn('mini@me.com')
    self.mox.ReplayAll()
    self.assertEqual(scm.GIT.GetEmail(self.root_dir), 'mini@me.com')

  def testMatchSvnGlob(self):
    self.assertEquals(scm.GIT.MatchSvnGlob(
        'svn://svn.chromium.org/chrome/trunk/src',
        'svn://svn.chromium.org/chrome',
        'trunk/src:refs/remotes/origin/trunk',
        False), 'refs/remotes/origin/trunk')
    self.assertEquals(scm.GIT.MatchSvnGlob(
        'https://v8.googlecode.com/svn/branches/bleeding_edge',
        'https://v8.googlecode.com/svn',
        'branches/*:refs/remotes/*',
        True), 'refs/remotes/bleeding_edge')

  def testRefToRemoteRefNoRemote(self):
    refs = {
        # local ref for upstream branch-head
        'refs/remotes/branch-heads/1234': ('refs/remotes/branch-heads/',
                                           '1234'),
        # upstream ref for branch-head
        'refs/branch-heads/1234': ('refs/remotes/branch-heads/', '1234'),
        # could be either local or upstream ref, assumed to refer to
        # upstream, but probably don't want to encourage refs like this.
        'branch-heads/1234': ('refs/remotes/branch-heads/', '1234'),
        # actively discouraging refs like this, should prepend with 'refs/'
        'remotes/branch-heads/1234': None,
        # might be non-"branch-heads" upstream branches, but can't resolve
        # without knowing the remote.
        'refs/heads/1234': None,
        'heads/1234': None,
        # underspecified, probably intended to refer to a local branch
        '1234': None,
        }
    for k, v in refs.items():
      r = scm.GIT.RefToRemoteRef(k)
      self.assertEqual(r, v, msg='%s -> %s, expected %s' % (k, r, v))

  def testRefToRemoteRefWithRemote(self):
    remote = 'origin'
    refs = {
        # This shouldn't be any different from the NoRemote() version.
        'refs/branch-heads/1234': ('refs/remotes/branch-heads/', '1234'),
        # local refs for upstream branch
        'refs/remotes/%s/foobar' % remote: ('refs/remotes/%s/' % remote,
                                            'foobar'),
        '%s/foobar' % remote: ('refs/remotes/%s/' % remote, 'foobar'),
        # upstream ref for branch
        'refs/heads/foobar': ('refs/remotes/%s/' % remote, 'foobar'),
        # could be either local or upstream ref, assumed to refer to
        # upstream, but probably don't want to encourage refs like this.
        'heads/foobar': ('refs/remotes/%s/' % remote, 'foobar'),
        # underspecified, probably intended to refer to a local branch
        'foobar': None,
        }
    for k, v in refs.items():
      r = scm.GIT.RefToRemoteRef(k, remote)
      self.assertEqual(r, v, msg='%s -> %s, expected %s' % (k, r, v))


class RealGitTest(fake_repos.FakeReposTestBase):
  def setUp(self):
    super(RealGitTest, self).setUp()
    self.enabled = self.FAKE_REPOS.set_up_git()
    if self.enabled:
      self.clone_dir = scm.os.path.join(self.FAKE_REPOS.git_root, 'repo_1')

  def testIsValidRevision(self):
    if not self.enabled:
      return
    # Sha1's are [0-9a-z]{32}, so starting with a 'z' or 'r' should always fail.
    self.assertFalse(scm.GIT.IsValidRevision(cwd=self.clone_dir, rev='zebra'))
    self.assertFalse(scm.GIT.IsValidRevision(cwd=self.clone_dir, rev='r123456'))
    # Valid cases
    first_rev = self.githash('repo_1', 1)
    self.assertTrue(scm.GIT.IsValidRevision(cwd=self.clone_dir, rev=first_rev))
    self.assertTrue(scm.GIT.IsValidRevision(cwd=self.clone_dir, rev='HEAD'))


class RealGitSvnTest(fake_repos.FakeReposTestBase):
  def setUp(self):
    super(RealGitSvnTest, self).setUp()
    self.enabled = self.FAKE_REPOS.set_up_git() and self.FAKE_REPOS.set_up_svn()
    if self.enabled:
      self.tree_name = 'git-svn'
      self.svn_url = scm.os.path.join(self.FAKE_REPOS.svn_base, 'trunk')
      self.clone_dir = scm.os.path.join(self.FAKE_REPOS.git_root,
                                        self.tree_name)
      scm.os.makedirs(self.clone_dir)
      self._capture(['svn', 'clone', '-q', '-q', self.svn_url, self.clone_dir])
      # git rev-list gives revisions in reverse chronological order.
      hashes = reversed(self._capture(['rev-list', 'HEAD']).splitlines())
      # We insert a null value at 0 to do 1-based indexing, not 0-based, as SVN
      # revisions are 1-based (i.e. they start at r1, not r0).
      self.git_hashes = ([None] + list(hashes))

  def tearDown(self):
    scm.gclient_utils.rmtree(self.clone_dir)

  def _capture(self, cmd, **kwargs):
    kwargs.setdefault('cwd', self.clone_dir)
    return scm.GIT.Capture(cmd, **kwargs)

  def testGetGitSvnHeadRev(self):
    if not self.enabled:
      return
    self.assertEquals(scm.GIT.GetGitSvnHeadRev(cwd=self.clone_dir), 2)
    self._capture(['reset', '--hard', 'HEAD^'])
    self.assertEquals(scm.GIT.GetGitSvnHeadRev(cwd=self.clone_dir), 1)

  def testIsGitSvn(self):
    if not self.enabled:
      return
    # Git-svn
    self.assertTrue(scm.GIT.IsGitSvn(self.clone_dir))
    # Pure git
    git_dir = scm.os.path.join(self.FAKE_REPOS.git_root, 'repo_1')
    self.assertFalse(scm.GIT.IsGitSvn(git_dir))
    # Pure svn
    svn_dir = scm.os.path.join(self.FAKE_REPOS.svn_checkout, 'trunk')
    self.assertFalse(scm.GIT.IsGitSvn(svn_dir))

  def testParseGitSvnSha1(self):
    test_sha1 = 'a5c63ce8671922e5c59c0dea49ef4f9d4a3020c9'
    expected_output = test_sha1 + '\n'
    # Cygwin git-svn 1.7.9 prints extra escape sequences when run under
    # TERM=xterm
    cygwin_output = test_sha1 + '\n\033[?1034h'

    self.assertEquals(scm.GIT.ParseGitSvnSha1(expected_output), test_sha1)
    self.assertEquals(scm.GIT.ParseGitSvnSha1(cygwin_output), test_sha1)

  def testGetGetSha1ForSvnRev(self):
    if not self.enabled:
      return
    self.assertEquals(scm.GIT.GetSha1ForSvnRev(cwd=self.clone_dir, rev=1),
                      self.git_hashes[1])
    self.assertEquals(scm.GIT.GetSha1ForSvnRev(cwd=self.clone_dir, rev=2),
                      self.git_hashes[2])


class SVNTestCase(BaseSCMTestCase):
  def setUp(self):
    BaseSCMTestCase.setUp(self)
    self.mox.StubOutWithMock(scm.SVN, 'Capture')
    self.url = self.SvnUrl()

  def testMembersChanged(self):
    self.mox.ReplayAll()
    members = [
        'AssertVersion',
        'Capture',
        'CaptureLocalInfo',
        'CaptureRemoteInfo',
        'CaptureRevision',
        'CaptureStatus',
        'current_version',
        'GenerateDiff',
        'GetCheckoutRoot',
        'GetEmail',
        'GetFileProperty',
        'IsMoved',
        'IsMovedInfo',
        'IsValidRevision',
        'ReadSimpleAuth',
        'Revert',
        'RunAndGetFileList',
    ]
    # If this test fails, you should add the relevant test.
    self.compareMembers(scm.SVN, members)

  def testGetCheckoutRoot(self):
    # pylint: disable=E1103
    self.mox.StubOutWithMock(scm.SVN, '_CaptureInfo')
    self.mox.StubOutWithMock(scm, 'GetCasedPath')
    scm.os.path.abspath = lambda x: x
    scm.GetCasedPath = lambda x: x
    scm.SVN._CaptureInfo([], self.root_dir + '/foo/bar').AndReturn({
        'Repository Root': 'svn://svn.chromium.org/chrome',
        'URL': 'svn://svn.chromium.org/chrome/trunk/src',
    })
    scm.SVN._CaptureInfo([], self.root_dir + '/foo').AndReturn({
        'Repository Root': 'svn://svn.chromium.org/chrome',
        'URL': 'svn://svn.chromium.org/chrome/trunk',
    })
    scm.SVN._CaptureInfo([], self.root_dir).AndReturn({
        'Repository Root': 'svn://svn.chromium.org/chrome',
        'URL': 'svn://svn.chromium.org/chrome/trunk/tools/commit-queue/workdir',
    })
    self.mox.ReplayAll()
    self.assertEquals(scm.SVN.GetCheckoutRoot(self.root_dir + '/foo/bar'),
                      self.root_dir + '/foo')

  def testGetFileInfo(self):
    xml_text = r"""<?xml version="1.0"?>
<info>
<entry kind="file" path="%s" revision="14628">
<url>http://src.chromium.org/svn/trunk/src/chrome/app/d</url>
<repository><root>http://src.chromium.org/svn</root></repository>
<wc-info>
<schedule>add</schedule>
<depth>infinity</depth>
<copy-from-url>http://src.chromium.org/svn/trunk/src/chrome/app/DEPS</copy-from-url>
<copy-from-rev>14628</copy-from-rev>
<checksum>369f59057ba0e6d9017e28f8bdfb1f43</checksum>
</wc-info>
</entry>
</info>
""" % self.url
    scm.SVN.Capture(['info', '--xml', self.url], None).AndReturn(xml_text)
    expected = {
      'URL': 'http://src.chromium.org/svn/trunk/src/chrome/app/d',
      'UUID': None,
      'Repository Root': 'http://src.chromium.org/svn',
      'Schedule': 'add',
      'Copied From URL':
        'http://src.chromium.org/svn/trunk/src/chrome/app/DEPS',
      'Copied From Rev': '14628',
      'Path': self.url,
      'Revision': 14628,
      'Node Kind': 'file',
    }
    self.mox.ReplayAll()
    file_info = scm.SVN._CaptureInfo([self.url], None)
    self.assertEquals(sorted(file_info.items()), sorted(expected.items()))

  def testCaptureInfo(self):
    xml_text = """<?xml version="1.0"?>
<info>
<entry
   kind="dir"
   path="."
   revision="35">
<url>%s</url>
<repository>
<root>%s</root>
<uuid>7b9385f5-0452-0410-af26-ad4892b7a1fb</uuid>
</repository>
<wc-info>
<schedule>normal</schedule>
<depth>infinity</depth>
</wc-info>
<commit
   revision="35">
<author>maruel</author>
<date>2008-12-04T20:12:19.685120Z</date>
</commit>
</entry>
</info>
""" % (self.url, self.root_dir)
    scm.SVN.Capture(['info', '--xml', self.url], None).AndReturn(xml_text)
    self.mox.ReplayAll()
    file_info = scm.SVN._CaptureInfo([self.url], None)
    expected = {
      'URL': self.url,
      'UUID': '7b9385f5-0452-0410-af26-ad4892b7a1fb',
      'Revision': 35,
      'Repository Root': self.root_dir,
      'Schedule': 'normal',
      'Copied From URL': None,
      'Copied From Rev': None,
      'Path': '.',
      'Node Kind': 'directory',
    }
    self.assertEqual(file_info, expected)

  def testCaptureStatus(self):
    text = r"""<?xml version="1.0"?>
<status>
<target path=".">
<entry path="unversionned_file.txt">
<wc-status props="none" item="unversioned"></wc-status>
</entry>
<entry path="build\internal\essential.vsprops">
<wc-status props="normal" item="modified" revision="14628">
<commit revision="13818">
<author>ajwong@chromium.org</author>
<date>2009-04-16T00:42:06.872358Z</date>
</commit>
</wc-status>
</entry>
<entry path="chrome\app\d">
<wc-status props="none" copied="true" tree-conflicted="true" item="added">
</wc-status>
</entry>
<entry path="chrome\app\DEPS">
<wc-status props="modified" item="modified" revision="14628">
<commit revision="1279">
<author>brettw@google.com</author>
<date>2008-08-23T17:16:42.090152Z</date>
</commit>
</wc-status>
</entry>
<entry path="scripts\master\factory\gclient_factory.py">
<wc-status props="normal" item="conflicted" revision="14725">
<commit revision="14633">
<author>nsylvain@chromium.org</author>
<date>2009-04-27T19:37:17.977400Z</date>
</commit>
</wc-status>
</entry>
</target>
</status>
"""
    scm.SVN.Capture(['status', '--xml'], '.').AndReturn(text)

    self.mox.ReplayAll()
    info = scm.SVN.CaptureStatus(None, '.')
    expected = [
      ('?      ', 'unversionned_file.txt'),
      ('M      ', 'build\\internal\\essential.vsprops'),
      ('A  +   ', 'chrome\\app\\d'),
      ('MM     ', 'chrome\\app\\DEPS'),
      ('C      ', 'scripts\\master\\factory\\gclient_factory.py'),
    ]
    self.assertEquals(sorted(info), sorted(expected))

  def testCaptureStatusEmpty(self):
    text = r"""<?xml version="1.0"?>
    <status>
    <target
       path="perf">
       </target>
       </status>"""
    scm.SVN.Capture(['status', '--xml'], None).AndReturn(text)
    self.mox.ReplayAll()
    info = scm.SVN.CaptureStatus(None, None)
    self.assertEquals(info, [])


class RealSvnTest(fake_repos.FakeReposTestBase):
  # Tests that work with a checkout.
  def setUp(self):
    super(RealSvnTest, self).setUp()
    self.enabled = self.FAKE_REPOS.set_up_svn()
    if self.enabled:
      self.svn_root = scm.os.path.join(self.root_dir, 'base')
      scm.SVN.Capture(
          ['checkout', self.svn_base + 'trunk/third_party', 'base'],
          cwd=self.root_dir)
      self.tree = self.mangle_svn_tree(('trunk/third_party@-1', ''),)

  def _capture(self, cmd, **kwargs):
    kwargs.setdefault('cwd', self.svn_root)
    return scm.SVN.Capture(cmd, **kwargs)

  def testCheckout(self):
    if not self.enabled:
      return
    # Checkout and verify the tree.
    self.assertTree(self.tree, self.svn_root)

  def testIsValidRevision(self):
    if not self.enabled:
      return
    url_at_rev = self.svn_base + 'trunk/third_party@%s'
    # Invalid or non-existent.
    self.assertFalse(scm.SVN.IsValidRevision('url://totally_invalid/trunk/foo'))
    self.assertFalse(scm.SVN.IsValidRevision(url_at_rev % 0))
    self.assertFalse(scm.SVN.IsValidRevision(url_at_rev % 123))
    # Valid.
    self.assertTrue(scm.SVN.IsValidRevision(url_at_rev % 1))
    self.assertTrue(scm.SVN.IsValidRevision(url_at_rev % 2))
    self.assertTrue(scm.SVN.IsValidRevision(url_at_rev % 'HEAD'))


if __name__ == '__main__':
  if '-v' in sys.argv:
    logging.basicConfig(level=logging.DEBUG)
  unittest.main()

# vim: ts=2:sw=2:tw=80:et:
