Ejemplo n.º 1
0
    def test_check_repository_subversion(self):
        """Testing Assembla.check_repository with Subversion"""
        try:
            account = self.create_hosting_account()
            service = account.service

            service.authorize('myuser', 'abc123', None)

            repository = Repository(path='https://svn.example.com/',
                                    hosting_account=account,
                                    tool=Tool.objects.get(name='Subversion'))
            scmtool = repository.get_scmtool()
            self.spy_on(scmtool.check_repository, call_original=False)

            service.check_repository(path='https://svn.example.com/',
                                     username='******',
                                     password='******',
                                     scmtool_class=scmtool.__class__,
                                     local_site_name=None)

            self.assertTrue(scmtool.check_repository.called)
            self.assertNotIn('p4_host',
                             scmtool.check_repository.last_call.kwargs)
        except ImportError:
            raise nose.SkipTest
Ejemplo n.º 2
0
    def test_ticket_login_with_local_site(self):
        """Testing Perforce with ticket-based logins with Local Sites"""
        repo = Repository(
            name='Perforce.com',
            path='public.perforce.com:1666',
            tool=Tool.objects.get(name='Perforce'),
            username='******',
            password='******',
            local_site=LocalSite.objects.get(name='local-site-1'))
        repo.extra_data = {
            'use_ticket_auth': True,
        }

        client = repo.get_scmtool().client
        self.assertTrue(client.use_ticket_auth)

        self.spy_on(client.get_ticket_status, call_fake=lambda *args: {
            'user': '******',
            'expiration_secs': 100000,
        })

        self.spy_on(client.login, call_original=False)

        with client.connect():
            self.assertFalse(client.login.called)
            self.assertEqual(client.p4.ticket_file,
                             os.path.join(settings.SITE_DATA_DIR, 'p4',
                                          'local-site-1', 'p4tickets'))
Ejemplo n.º 3
0
    def test_check_repository_perforce(self):
        """Testing Assembla.check_repository with Perforce"""
        try:
            account = self.create_hosting_account()
            service = account.service

            service.authorize('myuser', 'abc123', None)

            repository = Repository(hosting_account=account,
                                    tool=Tool.objects.get(name='Perforce'))
            scmtool = repository.get_scmtool()
            self.spy_on(scmtool.check_repository, call_original=False)

            service.check_repository(path='mypath',
                                     username='******',
                                     password='******',
                                     scmtool_class=scmtool.__class__,
                                     local_site_name=None,
                                     assembla_project_id='myproject')

            self.assertTrue(scmtool.check_repository.called)
            self.assertIn('p4_host', scmtool.check_repository.last_call.kwargs)
            self.assertEqual(
                scmtool.check_repository.last_call.kwargs['p4_host'],
                'myproject')
        except ImportError:
            raise nose.SkipTest
Ejemplo n.º 4
0
    def test_check_repository_perforce(self):
        """Testing Assembla.check_repository with Perforce"""
        try:
            account = self.create_hosting_account()
            service = account.service

            service.authorize('myuser', 'abc123', None)

            repository = Repository(hosting_account=account,
                                    tool=Tool.objects.get(name='Perforce'))
            scmtool = repository.get_scmtool()
            self.spy_on(scmtool.check_repository, call_original=False)

            service.check_repository(path='mypath',
                                     username='******',
                                     password='******',
                                     scmtool_class=scmtool.__class__,
                                     local_site_name=None,
                                     assembla_project_id='myproject')

            self.assertTrue(scmtool.check_repository.called)
            self.assertIn('p4_host', scmtool.check_repository.last_call.kwargs)
            self.assertEqual(
                scmtool.check_repository.last_call.kwargs['p4_host'],
                'myproject')
        except ImportError:
            self.skipTest('Perforce support is not installed')
Ejemplo n.º 5
0
    def test_check_repository_subversion(self):
        """Testing Assembla.check_repository with Subversion"""
        try:
            account = self.create_hosting_account()
            service = account.service

            service.authorize('myuser', 'abc123', None)

            repository = Repository(path='https://svn.example.com/',
                                    hosting_account=account,
                                    tool=Tool.objects.get(name='Subversion'))
            scmtool = repository.get_scmtool()
            self.spy_on(scmtool.check_repository, call_original=False)

            service.check_repository(path='https://svn.example.com/',
                                     username='******',
                                     password='******',
                                     scmtool_class=scmtool.__class__,
                                     local_site_name=None)

            self.assertTrue(scmtool.check_repository.called)
            self.assertNotIn('p4_host',
                             scmtool.check_repository.last_call.kwargs)
        except ImportError:
            self.skipTest('Perforce support is not installed')
Ejemplo n.º 6
0
    def testBadRoot(self):
        """Testing a bad CVSROOT"""
        file = "test/testfile"
        rev = Revision("1.1")
        badrepo = Repository(name="CVS", path=self.cvs_repo_path + "2", tool=Tool.objects.get(name="CVS"))
        badtool = badrepo.get_scmtool()

        self.assertRaises(SCMError, lambda: badtool.get_file(file, rev))
Ejemplo n.º 7
0
    def testPathWithoutPort(self):
        """Testing parsing a CVSROOT without a port"""
        repo = Repository(
            name="CVS", path="example.com:/cvsroot/test", username="******", tool=Tool.objects.get(name="CVS")
        )
        tool = repo.get_scmtool()

        self.assertEqual(tool.repopath, "/cvsroot/test")
        self.assertEqual(tool.client.repository, ":pserver:[email protected]:/cvsroot/test")
Ejemplo n.º 8
0
    def test_changeset_broken(self):
        """Testing PerforceTool.get_changeset error conditions"""
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          username='******',
                          password='******',
                          encoding='none')
        tool = repo.get_scmtool()

        self.assertRaises(AuthenticationError, lambda: tool.get_changeset(157))

        repo = Repository(name='localhost:1',
                          path='localhost:1',
                          tool=Tool.objects.get(name='Perforce'))

        tool = repo.get_scmtool()
        self.assertRaises(RepositoryNotFoundError,
                          lambda: tool.get_changeset(1))
Ejemplo n.º 9
0
    def testBadRoot(self):
        """Testing a bad CVSROOT"""
        file = 'test/testfile'
        rev = Revision('1.1')
        badrepo = Repository(name='CVS',
                             path=self.cvs_repo_path + '2',
                             tool=Tool.objects.get(name='CVS'))
        badtool = badrepo.get_scmtool()

        self.assertRaises(SCMError, lambda: badtool.get_file(file, rev))
Ejemplo n.º 10
0
    def test_bad_root(self):
        """Testing CVSTool with a bad CVSROOT"""
        file = 'test/testfile'
        rev = Revision('1.1')
        badrepo = Repository(name='CVS',
                             path=self.cvs_repo_path + '2',
                             tool=Tool.objects.get(name='CVS'))
        badtool = badrepo.get_scmtool()

        self.assertRaises(SCMError, lambda: badtool.get_file(file, rev))
Ejemplo n.º 11
0
    def testPathWithoutPort(self):
        """Testing parsing a CVSROOT without a port"""
        repo = Repository(name="CVS",
                          path="example.com:/cvsroot/test",
                          username="******",
                          tool=Tool.objects.get(name="CVS"))
        tool = repo.get_scmtool()

        self.assertEqual(tool.repopath, "/cvsroot/test")
        self.assertEqual(tool.client.repository,
                         ":pserver:[email protected]:/cvsroot/test")
Ejemplo n.º 12
0
    def test_https_repo(self):
        """Testing HgTool.file_exists with an HTTPS-based repository"""
        repo = Repository(name='Test HG2',
                          path='https://bitbucket.org/pypy/pypy',
                          tool=Tool.objects.get(name='Mercurial'))
        tool = repo.get_scmtool()

        rev = Revision('877cf1960916')

        self.assertTrue(tool.file_exists('TODO.rst', rev))
        self.assertTrue(not tool.file_exists('TODO.rstNotFound', rev))
Ejemplo n.º 13
0
    def test_https_repo(self):
        """Testing HgTool.file_exists with an HTTPS-based repository"""
        repo = Repository(name='Test HG2',
                          path='https://bitbucket.org/pypy/pypy',
                          tool=Tool.objects.get(name='Mercurial'))
        tool = repo.get_scmtool()

        rev = Revision('877cf1960916')

        self.assertTrue(tool.file_exists('TODO.rst', rev))
        self.assertTrue(not tool.file_exists('TODO.rstNotFound', rev))
Ejemplo n.º 14
0
    def test_custom_host(self):
        """Testing Perforce client initialization with a custom P4HOST"""
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          encoding='utf8')
        repo.extra_data['p4_host'] = 'my-custom-host'

        tool = repo.get_scmtool()

        with tool.client._connect():
            self.assertEqual(tool.client.p4.host, 'my-custom-host')
Ejemplo n.º 15
0
    def test_custom_host(self):
        """Testing Perforce client initialization with a custom P4HOST"""
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          encoding='utf8')
        repo.extra_data['p4_host'] = 'my-custom-host'

        tool = repo.get_scmtool()

        with tool.client._connect():
            self.assertEqual(tool.client.p4.host, 'my-custom-host')
Ejemplo n.º 16
0
class VMWareTests(DjangoTestCase):
    """Tests for VMware specific code"""
    fixtures = ['vmware.json', 'test_scmtools.json']

    def setUp(self):
        self.repository = Repository(name='VMware Test',
                                     path='perforce.eng.vmware.com:1666',
                                     tool=Tool.objects.get(name='VMware Perforce'))

        try:
            self.tool = self.repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest('perforce/p4python is not installed')
Ejemplo n.º 17
0
    def test_https_repo(self):
        """Testing HgTool.file_exists with an HTTPS-based repository"""
        repo = Repository(name='Test HG2',
                          path='https://www.mercurial-scm.org/repo/hg',
                          tool=Tool.objects.get(name='Mercurial'))
        tool = repo.get_scmtool()

        self.assertTrue(
            tool.file_exists('mercurial/hgweb/common.py',
                             Revision('f0735f2ce542')))
        self.assertFalse(
            tool.file_exists('mercurial/hgweb/common.py',
                             Revision('abcdef123456')))
Ejemplo n.º 18
0
    def test_changeset_broken(self):
        """Testing PerforceTool.get_changeset error conditions"""
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          username='******',
                          password='******')

        try:
            tool = repo.get_scmtool()
        except ImportError:
            raise nose.SkipTest('perforce/p4python is not installed')

        self.assertRaises(AuthenticationError, lambda: tool.get_changeset(157))

        repo = Repository(name='localhost:1',
                          path='localhost:1',
                          tool=Tool.objects.get(name='Perforce'))

        tool = repo.get_scmtool()
        self.assertRaises(RepositoryNotFoundError,
                          lambda: tool.get_changeset(1))
Ejemplo n.º 19
0
    def test_changeset_broken(self):
        """Testing PerforceTool.get_changeset error conditions"""
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          username='******',
                          password='******')

        try:
            tool = repo.get_scmtool()
        except ImportError:
            raise nose.SkipTest('perforce/p4python is not installed')

        self.assertRaises(AuthenticationError,
                          lambda: tool.get_changeset(157))

        repo = Repository(name='localhost:1',
                          path='localhost:1',
                          tool=Tool.objects.get(name='Perforce'))

        tool = repo.get_scmtool()
        self.assertRaises(RepositoryNotFoundError,
                          lambda: tool.get_changeset(1))
Ejemplo n.º 20
0
class VMWareTests(DjangoTestCase):
    """Tests for VMware specific code"""
    fixtures = ['vmware.json', 'test_scmtools.json']

    def setUp(self):
        self.repository = Repository(
            name='VMware Test',
            path='perforce.eng.vmware.com:1666',
            tool=Tool.objects.get(name='VMware Perforce'))

        try:
            self.tool = self.repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest('perforce/p4python is not installed')
Ejemplo n.º 21
0
class PerforceTests(DjangoTestCase):
    """Unit tests for perforce.

       This uses the open server at public.perforce.com to test various
       pieces.  Because we have no control over things like pending
       changesets, not everything can be tested.
       """

    fixtures = ["test_scmtools.json"]

    def setUp(self):
        self.repository = Repository(
            name="Perforce.com", path="public.perforce.com:1666", tool=Tool.objects.get(name="Perforce")
        )

        try:
            self.tool = self.repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest("perforce/p4python is not installed")

    def testChangeset(self):
        """Testing PerforceTool.get_changeset"""

        try:
            desc = self.tool.get_changeset(157)
        except P4Error, e:
            if str(e).startswith("Connect to server failed"):
                raise nose.SkipTest("Connection to public.perforce.com failed.  No internet?")
            else:
                raise
        self.assertEqual(desc.changenum, 157)
        self.assertEqual(hash(desc.description), -7425743081915501647)

        expected_files = [
            "//public/perforce/api/python/P4Client/P4Clientmodule.cc",
            "//public/perforce/api/python/P4Client/p4.py",
            "//public/perforce/api/python/P4Client/review.py",
            "//public/perforce/python/P4Client/P4Clientmodule.cc",
            "//public/perforce/python/P4Client/p4.py",
            "//public/perforce/python/P4Client/review.py",
        ]
        for file, expected in map(None, desc.files, expected_files):
            self.assertEqual(file, expected)

        self.assertEqual(hash(desc.summary), 4980424973015496725)
Ejemplo n.º 22
0
class PerforceTests(DjangoTestCase):
    """Unit tests for perforce.

       This uses the open server at public.perforce.com to test various
       pieces.  Because we have no control over things like pending
       changesets, not everything can be tested.
       """
    fixtures = ['test_scmtools.json']

    def setUp(self):
        self.repository = Repository(name='Perforce.com',
                                     path='public.perforce.com:1666',
                                     tool=Tool.objects.get(name='Perforce'))

        try:
            self.tool = self.repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest('perforce/p4python is not installed')

    def testChangeset(self):
        """Testing PerforceTool.get_changeset"""

        try:
            desc = self.tool.get_changeset(157)
        except P4Error, e:
            if str(e).startswith('Connect to server failed'):
                raise nose.SkipTest(
                    'Connection to public.perforce.com failed.  No internet?')
            else:
                raise
        self.assertEqual(desc.changenum, 157)
        self.assertEqual(hash(desc.description), -7425743081915501647)

        expected_files = [
            '//public/perforce/api/python/P4Client/P4Clientmodule.cc',
            '//public/perforce/api/python/P4Client/p4.py',
            '//public/perforce/api/python/P4Client/review.py',
            '//public/perforce/python/P4Client/P4Clientmodule.cc',
            '//public/perforce/python/P4Client/p4.py',
            '//public/perforce/python/P4Client/review.py',
        ]
        for file, expected in map(None, desc.files, expected_files):
            self.assertEqual(file, expected)

        self.assertEqual(hash(desc.summary), 4980424973015496725)
Ejemplo n.º 23
0
    def test_encoding(self):
        """Testing PerforceTool.get_changeset with a specified encoding"""
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          encoding='utf8')
        tool = repo.get_scmtool()

        try:
            tool.get_changeset(157)
            self.fail('Expected an error about unicode-enabled servers. Did '
                      'perforce.com turn on unicode for public.perforce.com?')
        except SCMError as e:
            # public.perforce.com doesn't have unicode enabled. Getting this
            # error means we at least passed the charset through correctly
            # to the p4 client.
            self.assertTrue(
                'clients require a unicode enabled server' in six.text_type(e))
Ejemplo n.º 24
0
    def test_encoding(self):
        """Testing PerforceTool.get_changeset with a specified encoding"""
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          encoding='utf8')
        tool = repo.get_scmtool()

        try:
            tool.get_changeset(157)
            self.fail('Expected an error about unicode-enabled servers. Did '
                      'perforce.com turn on unicode for public.perforce.com?')
        except SCMError as e:
            # public.perforce.com doesn't have unicode enabled. Getting this
            # error means we at least passed the charset through correctly
            # to the p4 client.
            self.assertTrue('clients require a unicode enabled server' in
                            six.text_type(e))
Ejemplo n.º 25
0
class BZRTests(SCMTestCase):
    """Unit tests for bzr."""

    fixtures = ['test_scmtools']

    def setUp(self):
        super(BZRTests, self).setUp()

        self.bzr_repo_path = os.path.join(os.path.dirname(__file__),
                                          '..', 'testdata', 'bzr_repo')
        self.bzr_ssh_path = ('bzr+ssh://localhost/%s'
                             % self.bzr_repo_path.replace('\\', '/'))
        self.bzr_sftp_path = ('sftp://localhost/%s'
                              % self.bzr_repo_path.replace('\\', '/'))
        self.repository = Repository(name='Bazaar',
                                     path='file://' + self.bzr_repo_path,
                                     tool=Tool.objects.get(name='Bazaar'))

        from reviewboard.scmtools.bzr import has_bzrlib

        if not has_bzrlib:
            self.tool = self.repository.get_scmtool()
            raise nose.SkipTest('bzrlib is not installed')

    def test_ssh(self):
        """Testing a SSH-backed bzr repository"""
        self._test_ssh(self.bzr_ssh_path, 'README')

    def test_ssh_with_site(self):
        """Testing a SSH-backed bzr repository with a LocalSite"""
        self._test_ssh_with_site(self.bzr_ssh_path, 'README')

    def test_sftp(self):
        """Testing a SFTP-backed bzr repository"""
        try:
            self._test_ssh(self.bzr_sftp_path, 'README')
        except SCMError as e:
            if six.text_type(e) == ('prefetch() takes exactly 2 arguments '
                                    '(1 given)'):
                raise nose.SkipTest(
                    'Installed bazaar and paramiko are incompatible. See '
                    'https://bugs.launchpad.net/bzr/+bug/1524066')
            else:
                raise e
Ejemplo n.º 26
0
    def _test_ssh(self, repo_path, filename=None):
        """Helper for testing an SSH connection to a local repository.

        This will attempt to SSH into the local machine and connect to the
        given repository, checking it for validity and optionally fetching
        a file.

        If this is unable to connect to the local machine, the test will be
        flagged as skipped.

        Args:
            repo_path (unicode):
                The repository path to check.

            filename (unicode, optional):
                The optional file in the repository to fetch.
        """
        self._check_can_test_ssh()

        repo = Repository(name='SSH Test', path=repo_path,
                          tool=self.repository.tool)
        tool = repo.get_scmtool()

        try:
            tool.check_repository(repo_path)
        except SocketError as e:
            if e.errno == ECONNREFUSED:
                # This box likely isn't set up for this test.
                SCMTestCase._can_test_ssh = False

                raise nose.SkipTest(
                    'Cannot perform SSH access tests. No local SSH service is '
                    'running.')
            else:
                raise

        if filename:
            self.assertNotEqual(tool.get_file(filename, HEAD), None)
Ejemplo n.º 27
0
    def test_ticket_login_with_no_valid_ticket(self):
        """Testing Perforce with ticket-based logins without a valid ticket
        """
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          username='******',
                          password='******')
        repo.extra_data = {
            'use_ticket_auth': True,
        }

        client = repo.get_scmtool().client
        self.assertTrue(client.use_ticket_auth)

        self.spy_on(client.get_ticket_status, call_fake=lambda *args: None)
        self.spy_on(client.login, call_original=False)

        with client.connect():
            self.assertTrue(client.login.called)
            self.assertEqual(client.p4.ticket_file,
                             os.path.join(settings.SITE_DATA_DIR, 'p4',
                                          'p4tickets'))
Ejemplo n.º 28
0
class CVSTests(DjangoTestCase):
    """Unit tests for CVS."""

    fixtures = ["test_scmtools.json"]

    def setUp(self):
        self.cvs_repo_path = os.path.join(os.path.dirname(__file__), "testdata/cvs_repo")
        self.repository = Repository(name="CVS", path=self.cvs_repo_path, tool=Tool.objects.get(name="CVS"))

        try:
            self.tool = self.repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest("cvs binary not found")

    def testPathWithPort(self):
        """Testing parsing a CVSROOT with a port"""
        repo = Repository(
            name="CVS", path="example.com:123/cvsroot/test", username="******", tool=Tool.objects.get(name="CVS")
        )
        tool = repo.get_scmtool()

        self.assertEqual(tool.repopath, "/cvsroot/test")
        self.assertEqual(tool.client.repository, ":pserver:[email protected]:123/cvsroot/test")

    def testPathWithoutPort(self):
        """Testing parsing a CVSROOT without a port"""
        repo = Repository(
            name="CVS", path="example.com:/cvsroot/test", username="******", tool=Tool.objects.get(name="CVS")
        )
        tool = repo.get_scmtool()

        self.assertEqual(tool.repopath, "/cvsroot/test")
        self.assertEqual(tool.client.repository, ":pserver:[email protected]:/cvsroot/test")

    def testGetFile(self):
        """Testing CVSTool.get_file"""
        expected = "test content\n"
        file = "test/testfile"
        rev = Revision("1.1")
        badrev = Revision("2.1")

        self.assertEqual(self.tool.get_file(file, rev), expected)
        self.assertEqual(self.tool.get_file(file + ",v", rev), expected)
        self.assertEqual(self.tool.get_file(self.tool.repopath + "/" + file + ",v", rev), expected)

        self.assert_(self.tool.file_exists("test/testfile"))
        self.assert_(self.tool.file_exists(self.tool.repopath + "/test/testfile"))
        self.assert_(self.tool.file_exists("test/testfile,v"))
        self.assert_(not self.tool.file_exists("test/testfile2"))
        self.assert_(not self.tool.file_exists(self.tool.repopath + "/test/testfile2"))
        self.assert_(not self.tool.file_exists("test/testfile2,v"))
        self.assert_(not self.tool.file_exists("test/testfile", badrev))

        self.assertRaises(FileNotFoundError, lambda: self.tool.get_file(""))
        self.assertRaises(FileNotFoundError, lambda: self.tool.get_file("hello", PRE_CREATION))

    def testRevisionParsing(self):
        """Testing revision number parsing"""
        self.assertEqual(self.tool.parse_diff_revision("", "PRE-CREATION")[1], PRE_CREATION)
        self.assertEqual(self.tool.parse_diff_revision("", "7 Nov 2005 13:17:07 -0000	1.2")[1], "1.2")
        self.assertEqual(self.tool.parse_diff_revision("", "7 Nov 2005 13:17:07 -0000	1.2.3.4")[1], "1.2.3.4")
        self.assertRaises(SCMError, lambda: self.tool.parse_diff_revision("", "hello"))

    def testInterface(self):
        """Testing basic CVSTool API"""
        self.assertEqual(self.tool.get_diffs_use_absolute_paths(), True)
        self.assertEqual(self.tool.get_fields(), ["diff_path"])

    def testSimpleDiff(self):
        """Testing parsing CVS simple diff"""
        diff = (
            "Index: testfile\n=========================================="
            + "=========================\nRCS file: %s/test/testfile,v\nre"
            + "trieving revision 1.1.1.1\ndiff -u -r1.1.1.1 testfile\n--- "
            + "testfile    26 Jul 2007 08:50:30 -0000      1.1.1.1\n+++ te"
            + "stfile    26 Jul 2007 10:20:20 -0000\n@@ -1 +1,2 @@\n-test "
            + "content\n+updated test content\n+added info\n"
        )
        diff = diff % self.cvs_repo_path

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, "test/testfile")
        self.assertEqual(file.origInfo, "26 Jul 2007 08:50:30 -0000      1.1.1.1")
        self.assertEqual(file.newFile, "testfile")
        self.assertEqual(file.newInfo, "26 Jul 2007 10:20:20 -0000")
        self.assertEqual(file.data, diff)

    def testBadDiff(self):
        """Testing parsing CVS diff with bad info"""
        diff = (
            "Index: newfile\n==========================================="
            + "========================\ndiff -N newfile\n--- /dev/null	1"
            + "Jan 1970 00:00:00 -0000\n+++ newfile	26 Jul 2007 10:11:45 "
            + "-0000\n@@ -0,0 +1 @@\n+new file content"
        )

        self.assertRaises(DiffParserError, lambda: self.tool.get_parser(diff).parse())

    def testBadDiff2(self):
        """Testing parsing CVS bad diff with new file"""
        diff = (
            "Index: newfile\n==========================================="
            + "========================\nRCS file: newfile\ndiff -N newfil"
            + "e\n--- /dev/null\n+++ newfile	2"
            + "6 Jul 2007 10:11:45 -0000\n@@ -0,0 +1 @@\n+new file content"
        )

        self.assertRaises(DiffParserError, lambda: self.tool.get_parser(diff).parse())

    def testNewfileDiff(self):
        """Testing parsing CVS diff with new file"""
        diff = (
            "Index: newfile\n==========================================="
            + "========================\nRCS file: newfile\ndiff -N newfil"
            + "e\n--- /dev/null	1 Jan 1970 00:00:00 -0000\n+++ newfile	2"
            + "6 Jul 2007 10:11:45 -0000\n@@ -0,0 +1 @@\n+new file content\n"
        )

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, "newfile")
        self.assertEqual(file.origInfo, "PRE-CREATION")
        self.assertEqual(file.newFile, "newfile")
        self.assertEqual(file.newInfo, "26 Jul 2007 10:11:45 -0000")
        self.assertEqual(file.data, diff)

    def testInterRevisionDiff(self):
        """Testing parsing CVS inter-revision diff"""
        diff = (
            "Index: testfile\n=========================================="
            + "=========================\nRCS file: %s/test/testfile,v\nre"
            + "trieving revision 1.1\nretrieving revision 1.2\ndiff -u -p "
            + "-r1.1 -r1.2\n--- testfile    26 Jul 2007 08:50:30 -0000    "
            + "  1.1\n+++ testfile    27 Sep 2007 22:57:16 -0000      1.2"
            + "\n@@ -1 +1,2 @@\n-test content\n+updated test content\n+add"
            + "ed info\n"
        )
        diff = diff % self.cvs_repo_path

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, "test/testfile")
        self.assertEqual(file.origInfo, "26 Jul 2007 08:50:30 -0000      1.1")
        self.assertEqual(file.newFile, "testfile")
        self.assertEqual(file.newInfo, "27 Sep 2007 22:57:16 -0000      1.2")
        self.assertEqual(file.data, diff)

    def testBadRoot(self):
        """Testing a bad CVSROOT"""
        file = "test/testfile"
        rev = Revision("1.1")
        badrepo = Repository(name="CVS", path=self.cvs_repo_path + "2", tool=Tool.objects.get(name="CVS"))
        badtool = badrepo.get_scmtool()

        self.assertRaises(SCMError, lambda: badtool.get_file(file, rev))
Ejemplo n.º 29
0
class CVSTests(DjangoTestCase):
    """Unit tests for CVS."""
    fixtures = ['test_scmtools.json']

    def setUp(self):
        self.cvs_repo_path = os.path.join(os.path.dirname(__file__),
                                          'testdata/cvs_repo')
        self.repository = Repository(name='CVS',
                                     path=self.cvs_repo_path,
                                     tool=Tool.objects.get(name='CVS'))

        try:
            self.tool = self.repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest('cvs binary not found')

    def testPathWithPort(self):
        """Testing parsing a CVSROOT with a port"""
        repo = Repository(name="CVS",
                          path="example.com:123/cvsroot/test",
                          username="******",
                          tool=Tool.objects.get(name="CVS"))
        tool = repo.get_scmtool()

        self.assertEqual(tool.repopath, "/cvsroot/test")
        self.assertEqual(tool.client.repository,
                         ":pserver:[email protected]:123/cvsroot/test")

    def testPathWithoutPort(self):
        """Testing parsing a CVSROOT without a port"""
        repo = Repository(name="CVS",
                          path="example.com:/cvsroot/test",
                          username="******",
                          tool=Tool.objects.get(name="CVS"))
        tool = repo.get_scmtool()

        self.assertEqual(tool.repopath, "/cvsroot/test")
        self.assertEqual(tool.client.repository,
                         ":pserver:[email protected]:/cvsroot/test")

    def testGetFile(self):
        """Testing CVSTool.get_file"""
        expected = "test content\n"
        file = 'test/testfile'
        rev = Revision('1.1')
        badrev = Revision('2.1')

        self.assertEqual(self.tool.get_file(file, rev), expected)
        self.assertEqual(self.tool.get_file(file + ",v", rev), expected)
        self.assertEqual(
            self.tool.get_file(self.tool.repopath + '/' + file + ",v", rev),
            expected)

        self.assert_(self.tool.file_exists('test/testfile'))
        self.assert_(
            self.tool.file_exists(self.tool.repopath + '/test/testfile'))
        self.assert_(self.tool.file_exists('test/testfile,v'))
        self.assert_(not self.tool.file_exists('test/testfile2'))
        self.assert_(not self.tool.file_exists(self.tool.repopath +
                                               '/test/testfile2'))
        self.assert_(not self.tool.file_exists('test/testfile2,v'))
        self.assert_(not self.tool.file_exists('test/testfile', badrev))

        self.assertRaises(FileNotFoundError, lambda: self.tool.get_file(''))
        self.assertRaises(FileNotFoundError,
                          lambda: self.tool.get_file('hello', PRE_CREATION))

    def testRevisionParsing(self):
        """Testing revision number parsing"""
        self.assertEqual(
            self.tool.parse_diff_revision('', 'PRE-CREATION')[1], PRE_CREATION)
        self.assertEqual(
            self.tool.parse_diff_revision('',
                                          '7 Nov 2005 13:17:07 -0000	1.2')[1],
            '1.2')
        self.assertEqual(
            self.tool.parse_diff_revision(
                '', '7 Nov 2005 13:17:07 -0000	1.2.3.4')[1], '1.2.3.4')
        self.assertRaises(SCMError,
                          lambda: self.tool.parse_diff_revision('', 'hello'))

    def testInterface(self):
        """Testing basic CVSTool API"""
        self.assertEqual(self.tool.get_diffs_use_absolute_paths(), True)
        self.assertEqual(self.tool.get_fields(), ['diff_path'])

    def testSimpleDiff(self):
        """Testing parsing CVS simple diff"""
        diff = "Index: testfile\n==========================================" + \
               "=========================\nRCS file: %s/test/testfile,v\nre" + \
               "trieving revision 1.1.1.1\ndiff -u -r1.1.1.1 testfile\n--- " + \
               "testfile    26 Jul 2007 08:50:30 -0000      1.1.1.1\n+++ te" + \
               "stfile    26 Jul 2007 10:20:20 -0000\n@@ -1 +1,2 @@\n-test " + \
               "content\n+updated test content\n+added info\n"
        diff = diff % self.cvs_repo_path

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, 'test/testfile')
        self.assertEqual(file.origInfo,
                         '26 Jul 2007 08:50:30 -0000      1.1.1.1')
        self.assertEqual(file.newFile, 'testfile')
        self.assertEqual(file.newInfo, '26 Jul 2007 10:20:20 -0000')
        self.assertEqual(file.data, diff)

    def testBadDiff(self):
        """Testing parsing CVS diff with bad info"""
        diff = "Index: newfile\n===========================================" + \
               "========================\ndiff -N newfile\n--- /dev/null	1" + \
               "Jan 1970 00:00:00 -0000\n+++ newfile	26 Jul 2007 10:11:45 " + \
               "-0000\n@@ -0,0 +1 @@\n+new file content"

        self.assertRaises(DiffParserError,
                          lambda: self.tool.get_parser(diff).parse())

    def testBadDiff2(self):
        """Testing parsing CVS bad diff with new file"""
        diff = "Index: newfile\n===========================================" + \
               "========================\nRCS file: newfile\ndiff -N newfil" + \
               "e\n--- /dev/null\n+++ newfile	2" + \
               "6 Jul 2007 10:11:45 -0000\n@@ -0,0 +1 @@\n+new file content"

        self.assertRaises(DiffParserError,
                          lambda: self.tool.get_parser(diff).parse())

    def testNewfileDiff(self):
        """Testing parsing CVS diff with new file"""
        diff = "Index: newfile\n===========================================" + \
               "========================\nRCS file: newfile\ndiff -N newfil" + \
               "e\n--- /dev/null	1 Jan 1970 00:00:00 -0000\n+++ newfile	2" + \
               "6 Jul 2007 10:11:45 -0000\n@@ -0,0 +1 @@\n+new file content\n"

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, 'newfile')
        self.assertEqual(file.origInfo, 'PRE-CREATION')
        self.assertEqual(file.newFile, 'newfile')
        self.assertEqual(file.newInfo, '26 Jul 2007 10:11:45 -0000')
        self.assertEqual(file.data, diff)

    def testInterRevisionDiff(self):
        """Testing parsing CVS inter-revision diff"""
        diff = "Index: testfile\n==========================================" + \
               "=========================\nRCS file: %s/test/testfile,v\nre" + \
               "trieving revision 1.1\nretrieving revision 1.2\ndiff -u -p " + \
               "-r1.1 -r1.2\n--- testfile    26 Jul 2007 08:50:30 -0000    " + \
               "  1.1\n+++ testfile    27 Sep 2007 22:57:16 -0000      1.2"  + \
               "\n@@ -1 +1,2 @@\n-test content\n+updated test content\n+add" + \
               "ed info\n"
        diff = diff % self.cvs_repo_path

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, 'test/testfile')
        self.assertEqual(file.origInfo, '26 Jul 2007 08:50:30 -0000      1.1')
        self.assertEqual(file.newFile, 'testfile')
        self.assertEqual(file.newInfo, '27 Sep 2007 22:57:16 -0000      1.2')
        self.assertEqual(file.data, diff)

    def testBadRoot(self):
        """Testing a bad CVSROOT"""
        file = 'test/testfile'
        rev = Revision('1.1')
        badrepo = Repository(name='CVS',
                             path=self.cvs_repo_path + '2',
                             tool=Tool.objects.get(name='CVS'))
        badtool = badrepo.get_scmtool()

        self.assertRaises(SCMError, lambda: badtool.get_file(file, rev))

    def test_ssh(self):
        """Testing a SSH-backed CVS repository"""
        repo_path, username, password = _get_repo_test_info('CVS_SSH')
        self.tool.check_repository(repo_path, username, password)
Ejemplo n.º 30
0
class CVSTests(SCMTestCase):
    """Unit tests for CVS."""

    fixtures = ['test_scmtools']

    def setUp(self):
        super(CVSTests, self).setUp()

        self.cvs_repo_path = os.path.join(os.path.dirname(__file__), '..',
                                          'testdata', 'cvs_repo')
        self.cvs_ssh_path = (':ext:localhost:%s' %
                             self.cvs_repo_path.replace('\\', '/'))
        self.repository = Repository(name='CVS',
                                     path=self.cvs_repo_path,
                                     tool=Tool.objects.get(name='CVS'))

        try:
            self.tool = self.repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest('cvs binary not found')

    def test_build_cvsroot_with_port(self):
        """Testing CVSTool.build_cvsroot with a port"""
        self._test_build_cvsroot(
            repo_path='example.com:123/cvsroot/test',
            username='******',
            expected_cvsroot=':pserver:[email protected]:123/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_without_port(self):
        """Testing CVSTool.build_cvsroot without a port"""
        self._test_build_cvsroot(
            repo_path='example.com:/cvsroot/test',
            username='******',
            expected_cvsroot=':pserver:[email protected]:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_pserver_and_no_user_or_password(self):
        """Testing CVSTool.build_cvsroot with :pserver: and no user or
        password
        """
        self._test_build_cvsroot(
            repo_path=':pserver:example.com:/cvsroot/test',
            expected_cvsroot=':pserver:example.com:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_pserver_and_inline_user(self):
        """Testing CVSTool.build_cvsroot with :pserver: and inline user"""
        self._test_build_cvsroot(
            repo_path=':pserver:[email protected]:/cvsroot/test',
            expected_cvsroot=':pserver:[email protected]:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_pserver_and_inline_user_and_password(self):
        """Testing CVSTool.build_cvsroot with :pserver: and inline user and
        password
        """
        self._test_build_cvsroot(
            repo_path=':pserver:anonymous:[email protected]:/cvsroot/test',
            expected_cvsroot=':pserver:anonymous:[email protected]:'
            '/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_pserver_and_form_user(self):
        """Testing CVSTool.build_cvsroot with :pserver: and form-provided
        user
        """
        self._test_build_cvsroot(
            repo_path=':pserver:example.com:/cvsroot/test',
            username='******',
            expected_cvsroot=':pserver:[email protected]:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_pserver_and_form_user_and_password(self):
        """Testing CVSTool.build_cvsroot with :pserver: and form-provided
        user and password
        """
        self._test_build_cvsroot(
            repo_path=':pserver:example.com:/cvsroot/test',
            username='******',
            password='******',
            expected_cvsroot=':pserver:anonymous:[email protected]:'
            '/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_pserver_and_inline_takes_precedence(self):
        """Testing CVSTool.build_cvsroot with :pserver: and inline user/password
        taking precedence
        """
        self._test_build_cvsroot(
            repo_path=':pserver:anonymous:[email protected]:/cvsroot/test',
            username='******',
            password='******',
            expected_cvsroot=':pserver:anonymous:[email protected]:'
            '/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_gserver(self):
        """Testing CVSTool.build_cvsroot with :gserver:"""
        self._test_build_cvsroot(
            repo_path=':gserver:localhost:/cvsroot/test',
            expected_cvsroot=':gserver:localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_gserver_with_username(self):
        """Testing CVSTool.build_cvsroot with :gserver: with username"""
        self._test_build_cvsroot(
            repo_path=':gserver:user@localhost:/cvsroot/test',
            expected_cvsroot=':gserver:user@localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

        self._test_build_cvsroot(
            repo_path=':gserver:localhost:/cvsroot/test',
            username='******',
            expected_cvsroot=':gserver:user@localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_gserver_with_port(self):
        """Testing CVSTool.build_cvsroot with :gserver: with port"""
        self._test_build_cvsroot(
            repo_path=':gserver:localhost:123/cvsroot/test',
            expected_cvsroot=':gserver:localhost:123/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_gserver_validates_password(self):
        """Testing CVSTool.build_cvsroot with :gserver: validates password"""
        self._test_build_cvsroot(
            repo_path=':gserver:user:pass@localhost:/cvsroot/test',
            expected_error='"gserver" CVSROOTs do not support passwords.',
            expected_cvsroot=':gserver:user@localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_kserver(self):
        """Testing CVSTool.build_cvsroot with :kserver:"""
        self._test_build_cvsroot(
            repo_path=':kserver:localhost:/cvsroot/test',
            expected_cvsroot=':kserver:localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_kserver_with_username(self):
        """Testing CVSTool.build_cvsroot with :kserver: with username"""
        self._test_build_cvsroot(
            repo_path=':kserver:user@localhost:/cvsroot/test',
            expected_cvsroot=':kserver:user@localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

        self._test_build_cvsroot(
            repo_path=':kserver:localhost:/cvsroot/test',
            username='******',
            expected_cvsroot=':kserver:user@localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_kserver_with_port(self):
        """Testing CVSTool.build_cvsroot with :kserver: with port"""
        self._test_build_cvsroot(
            repo_path=':kserver:localhost:123/cvsroot/test',
            expected_cvsroot=':kserver:localhost:123/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_kserver_validates_password(self):
        """Testing CVSTool.build_cvsroot with :kserver: validates password"""
        self._test_build_cvsroot(
            repo_path=':kserver:user:pass@localhost:/cvsroot/test',
            expected_error='"kserver" CVSROOTs do not support passwords.',
            expected_cvsroot=':kserver:user@localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_ext(self):
        """Testing CVSTool.build_cvsroot with :ext:"""
        self._test_build_cvsroot(
            repo_path=':ext:localhost:/cvsroot/test',
            expected_cvsroot=':ext:localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_ext_validates_password(self):
        """Testing CVSTool.build_cvsroot with :ext: validates password"""
        self._test_build_cvsroot(
            repo_path=':ext:user:pass@localhost:/cvsroot/test',
            expected_error='"ext" CVSROOTs do not support passwords.',
            expected_cvsroot=':ext:user@localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_ext_validates_port(self):
        """Testing CVSTool.build_cvsroot with :ext: validates port"""
        self._test_build_cvsroot(
            repo_path=':ext:localhost:123/cvsroot/test',
            expected_error='"ext" CVSROOTs do not support specifying ports.',
            expected_cvsroot=':ext:localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_server(self):
        """Testing CVSTool.build_cvsroot with :server:"""
        self._test_build_cvsroot(
            repo_path=':server:localhost:/cvsroot/test',
            expected_cvsroot=':server:localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_server_validates_password(self):
        """Testing CVSTool.build_cvsroot with :server: validates password"""
        self._test_build_cvsroot(
            repo_path=':server:user:pass@localhost:/cvsroot/test',
            expected_error='"server" CVSROOTs do not support passwords.',
            expected_cvsroot=':server:user@localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_server_validates_port(self):
        """Testing CVSTool.build_cvsroot with :server: validates port"""
        self._test_build_cvsroot(
            repo_path=':server:localhost:123/cvsroot/test',
            expected_error='"server" CVSROOTs do not support specifying '
            'ports.',
            expected_cvsroot=':server:localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_ssh(self):
        """Testing CVSTool.build_cvsroot with :ssh:"""
        self._test_build_cvsroot(
            repo_path=':ssh:localhost:/cvsroot/test',
            expected_cvsroot=':ssh:localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_ssh_validates_password(self):
        """Testing CVSTool.build_cvsroot with :ssh: validates password"""
        self._test_build_cvsroot(
            repo_path=':ssh:user:pass@localhost:/cvsroot/test',
            expected_error='"ssh" CVSROOTs do not support passwords.',
            expected_cvsroot=':ssh:user@localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_ssh_validates_port(self):
        """Testing CVSTool.build_cvsroot with :ssh: validates port"""
        self._test_build_cvsroot(
            repo_path=':ssh:localhost:123/cvsroot/test',
            expected_error='"ssh" CVSROOTs do not support specifying '
            'ports.',
            expected_cvsroot=':ssh:localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_extssh(self):
        """Testing CVSTool.build_cvsroot with :extssh:"""
        self._test_build_cvsroot(
            repo_path=':extssh:localhost:/cvsroot/test',
            expected_cvsroot=':extssh:localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_extssh_validates_password(self):
        """Testing CVSTool.build_cvsroot with :extssh: validates password"""
        self._test_build_cvsroot(
            repo_path=':extssh:user:pass@localhost:/cvsroot/test',
            expected_error='"extssh" CVSROOTs do not support passwords.',
            expected_cvsroot=':extssh:user@localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_extssh_validates_port(self):
        """Testing CVSTool.build_cvsroot with :extssh: validates port"""
        self._test_build_cvsroot(
            repo_path=':extssh:localhost:123/cvsroot/test',
            expected_error='"extssh" CVSROOTs do not support specifying '
            'ports.',
            expected_cvsroot=':extssh:localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_fork(self):
        """Testing CVSTool.build_cvsroot with :fork:"""
        self._test_build_cvsroot(repo_path=':fork:/home/myuser/cvsroot',
                                 expected_cvsroot=':fork:/home/myuser/cvsroot',
                                 expected_path='/home/myuser/cvsroot')

    def test_path_with_fork_validates_username(self):
        """Testing CVSTool.build_cvsroot with :fork: validates usernames"""
        self._test_build_cvsroot(
            repo_path=':fork:/home/myuser/cvsroot',
            username='******',
            expected_error='"fork" CVSROOTs do not support usernames.',
            expected_cvsroot=':fork:/home/myuser/cvsroot',
            expected_path='/home/myuser/cvsroot')

    def test_path_with_fork_validates_password(self):
        """Testing CVSTool.build_cvsroot with :fork: validates passwords"""
        self._test_build_cvsroot(
            repo_path=':fork:/home/myuser/cvsroot',
            password='******',
            expected_error='"fork" CVSROOTs do not support passwords.',
            expected_cvsroot=':fork:/home/myuser/cvsroot',
            expected_path='/home/myuser/cvsroot')

    def test_path_with_local(self):
        """Testing CVSTool.build_cvsroot with :local:"""
        self._test_build_cvsroot(
            repo_path=':local:/home/myuser/cvsroot',
            expected_cvsroot=':local:/home/myuser/cvsroot',
            expected_path='/home/myuser/cvsroot')

    def test_path_with_local_validates_username(self):
        """Testing CVSTool.build_cvsroot with :local: validates usernames"""
        self._test_build_cvsroot(
            repo_path=':local:/home/myuser/cvsroot',
            username='******',
            expected_error='"local" CVSROOTs do not support usernames.',
            expected_cvsroot=':local:/home/myuser/cvsroot',
            expected_path='/home/myuser/cvsroot')

    def test_path_with_local_validates_password(self):
        """Testing CVSTool.build_cvsroot with :local: validates passwords"""
        self._test_build_cvsroot(
            repo_path=':local:/home/myuser/cvsroot',
            password='******',
            expected_error='"local" CVSROOTs do not support passwords.',
            expected_cvsroot=':local:/home/myuser/cvsroot',
            expected_path='/home/myuser/cvsroot')

    def test_get_file(self):
        """Testing CVSTool.get_file"""
        expected = b'test content\n'
        file = 'test/testfile'
        rev = Revision('1.1')
        badrev = Revision('2.1')

        value = self.tool.get_file(file, rev)
        self.assertTrue(isinstance(value, bytes))
        self.assertEqual(value, expected)
        self.assertEqual(self.tool.get_file(file + ',v', rev), expected)
        self.assertEqual(
            self.tool.get_file(self.tool.repopath + '/' + file + ',v', rev),
            expected)

        self.assertTrue(self.tool.file_exists('test/testfile'))
        self.assertTrue(
            self.tool.file_exists(self.tool.repopath + '/test/testfile'))
        self.assertTrue(self.tool.file_exists('test/testfile,v'))
        self.assertTrue(not self.tool.file_exists('test/testfile2'))
        self.assertTrue(not self.tool.file_exists(self.tool.repopath +
                                                  '/test/testfile2'))
        self.assertTrue(not self.tool.file_exists('test/testfile2,v'))
        self.assertTrue(not self.tool.file_exists('test/testfile', badrev))

        self.assertRaises(FileNotFoundError, lambda: self.tool.get_file(''))
        self.assertRaises(FileNotFoundError,
                          lambda: self.tool.get_file('hello', PRE_CREATION))

    def test_get_file_with_keywords(self):
        """Testing CVSTool.get_file with file containing keywords"""
        value = self.tool.get_file('test/testfile', Revision('1.2'))

        self.assertEqual(value, '$Id$\n' '$Author$\n' '\n' 'test content\n')

    def test_revision_parsing(self):
        """Testing CVSTool revision number parsing"""
        self.assertEqual(
            self.tool.parse_diff_revision('', 'PRE-CREATION')[1], PRE_CREATION)
        self.assertEqual(
            self.tool.parse_diff_revision('',
                                          '7 Nov 2005 13:17:07 -0000\t1.2')[1],
            '1.2')
        self.assertEqual(
            self.tool.parse_diff_revision(
                '', '7 Nov 2005 13:17:07 -0000\t1.2.3.4')[1], '1.2.3.4')
        self.assertRaises(SCMError,
                          lambda: self.tool.parse_diff_revision('', 'hello'))

    def test_interface(self):
        """Testing basic CVSTool API"""
        self.assertTrue(self.tool.diffs_use_absolute_paths)

    def test_simple_diff(self):
        """Testing parsing CVS simple diff"""
        diff = (b'Index: testfile\n'
                b'==========================================================='
                b'========\n'
                b'RCS file: %s/test/testfile,v\n'
                b'retrieving revision 1.1.1.1\n'
                b'diff -u -r1.1.1.1 testfile\n'
                b'--- testfile    26 Jul 2007 08:50:30 -0000      1.1.1.1\n'
                b'+++ testfile    26 Jul 2007 10:20:20 -0000\n'
                b'@@ -1 +1,2 @@\n'
                b'-test content\n'
                b'+updated test content\n'
                b'+added info\n')
        diff = diff % self.cvs_repo_path

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, 'test/testfile')
        self.assertEqual(file.origInfo,
                         '26 Jul 2007 08:50:30 -0000      1.1.1.1')
        self.assertEqual(file.newFile, 'test/testfile')
        self.assertEqual(file.newInfo, '26 Jul 2007 10:20:20 -0000')
        self.assertEqual(file.data, diff)
        self.assertEqual(file.insert_count, 2)
        self.assertEqual(file.delete_count, 1)

    def test_new_diff_revision_format(self):
        """Testing parsing CVS diff with new revision format"""
        diff = (b'Index: %s/test/testfile\n'
                b'diff -u %s/test/testfile:1.5.2.1 %s/test/testfile:1.5.2.2\n'
                b'--- test/testfile:1.5.2.1\tThu Dec 15 16:27:47 2011\n'
                b'+++ test/testfile\tTue Jan 10 10:36:26 2012\n'
                b'@@ -1 +1,2 @@\n'
                b'-test content\n'
                b'+updated test content\n'
                b'+added info\n')
        diff = diff % (self.cvs_repo_path, self.cvs_repo_path,
                       self.cvs_repo_path)

        file = self.tool.get_parser(diff).parse()[0]
        f2, revision = self.tool.parse_diff_revision(file.origFile,
                                                     file.origInfo, file.moved)
        self.assertEqual(f2, 'test/testfile')
        self.assertEqual(revision, '1.5.2.1')
        self.assertEqual(file.newFile, 'test/testfile')
        self.assertEqual(file.newInfo, 'Tue Jan 10 10:36:26 2012')
        self.assertEqual(file.insert_count, 2)
        self.assertEqual(file.delete_count, 1)

    def test_bad_diff(self):
        """Testing parsing CVS diff with bad info"""
        diff = (b'Index: newfile\n'
                b'==========================================================='
                b'========\n'
                b'diff -N newfile\n'
                b'--- /dev/null\t1 Jan 1970 00:00:00 -0000\n'
                b'+++ newfile\t26 Jul 2007 10:11:45 -0000\n'
                b'@@ -0,0 +1 @@\n'
                b'+new file content')

        self.assertRaises(DiffParserError,
                          lambda: self.tool.get_parser(diff).parse())

    def test_bad_diff2(self):
        """Testing parsing CVS bad diff with new file"""
        diff = (b'Index: newfile\n'
                b'==========================================================='
                b'========\n'
                b'RCS file: newfile\n'
                b'diff -N newfile\n'
                b'--- /dev/null\n'
                b'+++ newfile\t26 Jul 2007 10:11:45 -0000\n'
                b'@@ -0,0 +1 @@\n'
                b'+new file content')

        self.assertRaises(DiffParserError,
                          lambda: self.tool.get_parser(diff).parse())

    def test_newfile_diff(self):
        """Testing parsing CVS diff with new file"""
        diff = (b'Index: newfile\n'
                b'==========================================================='
                b'========\n'
                b'RCS file: newfile\n'
                b'diff -N newfile\n'
                b'--- /dev/null\t1 Jan 1970 00:00:00 -0000\n'
                b'+++ newfile\t26 Jul 2007 10:11:45 -0000\n'
                b'@@ -0,0 +1 @@\n'
                b'+new file content\n')

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, 'newfile')
        self.assertEqual(file.origInfo, 'PRE-CREATION')
        self.assertEqual(file.newFile, 'newfile')
        self.assertEqual(file.newInfo, '26 Jul 2007 10:11:45 -0000')
        self.assertEqual(file.data, diff)
        self.assertEqual(file.insert_count, 1)
        self.assertEqual(file.delete_count, 0)

    def test_inter_revision_diff(self):
        """Testing parsing CVS inter-revision diff"""
        diff = (b'Index: testfile\n'
                b'==========================================================='
                b'========\n'
                b'RCS file: %s/test/testfile,v\n'
                b'retrieving revision 1.1\n'
                b'retrieving revision 1.2\n'
                b'diff -u -p -r1.1 -r1.2\n'
                b'--- testfile    26 Jul 2007 08:50:30 -0000      1.1\n'
                b'+++ testfile    27 Sep 2007 22:57:16 -0000      1.2\n'
                b'@@ -1 +1,2 @@\n'
                b'-test content\n'
                b'+updated test content\n'
                b'+added info\n')
        diff = diff % self.cvs_repo_path

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, 'test/testfile')
        self.assertEqual(file.origInfo, '26 Jul 2007 08:50:30 -0000      1.1')
        self.assertEqual(file.newFile, 'test/testfile')
        self.assertEqual(file.newInfo, '27 Sep 2007 22:57:16 -0000      1.2')
        self.assertEqual(file.data, diff)
        self.assertEqual(file.insert_count, 2)
        self.assertEqual(file.delete_count, 1)

    def test_unicode_diff(self):
        """Testing parsing CVS diff with unicode filenames"""
        diff = ('Index: téstfile\n'
                '==========================================================='
                '========\n'
                'RCS file: %s/test/téstfile,v\n'
                'retrieving revision 1.1.1.1\n'
                'diff -u -r1.1.1.1 téstfile\n'
                '--- téstfile    26 Jul 2007 08:50:30 -0000      1.1.1.1\n'
                '+++ téstfile    26 Jul 2007 10:20:20 -0000\n'
                '@@ -1 +1,2 @@\n'
                '-tést content\n'
                '+updated test content\n'
                '+added info\n')
        diff = diff % self.cvs_repo_path
        diff = diff.encode('utf-8')

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, 'test/téstfile')
        self.assertEqual(file.origInfo,
                         '26 Jul 2007 08:50:30 -0000      1.1.1.1')
        self.assertEqual(file.newFile, 'test/téstfile')
        self.assertEqual(file.newInfo, '26 Jul 2007 10:20:20 -0000')
        self.assertEqual(file.data, diff)
        self.assertEqual(file.insert_count, 2)
        self.assertEqual(file.delete_count, 1)

    def test_keyword_diff(self):
        """Testing parsing CVS diff with keywords"""
        diff = self.tool.normalize_patch(
            b'Index: Makefile\n'
            b'==========================================================='
            b'========\n'
            b'RCS file: /cvsroot/src/Makefile,v\n'
            b'retrieving revision 1.1\n'
            b'retrieving revision 1.2\n'
            b'diff -u -r1.1.1.1 Makefile\n'
            b'--- Makefile    26 Jul 2007 08:50:30 -0000      1.1\n'
            b'+++ Makefile    26 Jul 2007 10:20:20 -0000      1.2\n'
            b'@@ -1,6 +1,7 @@\n'
            b' # $Author: bob $\n'
            b' # $Date: 2014/12/18 13:09:42 $\n'
            b' # $Header: /src/Makefile,v 1.2 2014/12/18 '
            b'13:09:42 bob Exp $\n'
            b' # $Id: Makefile,v 1.2 2014/12/18 13:09:42 bob Exp $\n'
            b' # $Locker: bob $\n'
            b' # $Name: some_name $\n'
            b' # $RCSfile: Makefile,v $\n'
            b' # $Revision: 1.2 $\n'
            b' # $Source: /src/Makefile,v $\n'
            b' # $State: Exp $\n'
            b'+# foo\n'
            b' include ../tools/Makefile.base-vars\n'
            b' NAME = misc-docs\n'
            b' OUTNAME = cvs-misc-docs\n', 'Makefile')

        self.assertEqual(
            diff, b'Index: Makefile\n'
            b'==========================================================='
            b'========\n'
            b'RCS file: /cvsroot/src/Makefile,v\n'
            b'retrieving revision 1.1\n'
            b'retrieving revision 1.2\n'
            b'diff -u -r1.1.1.1 Makefile\n'
            b'--- Makefile    26 Jul 2007 08:50:30 -0000      1.1\n'
            b'+++ Makefile    26 Jul 2007 10:20:20 -0000      1.2\n'
            b'@@ -1,6 +1,7 @@\n'
            b' # $Author$\n'
            b' # $Date$\n'
            b' # $Header$\n'
            b' # $Id$\n'
            b' # $Locker$\n'
            b' # $Name$\n'
            b' # $RCSfile$\n'
            b' # $Revision$\n'
            b' # $Source$\n'
            b' # $State$\n'
            b'+# foo\n'
            b' include ../tools/Makefile.base-vars\n'
            b' NAME = misc-docs\n'
            b' OUTNAME = cvs-misc-docs\n')

    def test_keyword_diff_unicode(self):
        """Testing parsing CVS diff with keywords and unicode characters"""
        # Test bug 3931: this should succeed without a UnicodeDecodeError
        self.tool.normalize_patch(
            b'Index: Makefile\n'
            b'==========================================================='
            b'========\n'
            b'RCS file: /cvsroot/src/Makefile,v\n'
            b'retrieving revision 1.1\n'
            b'retrieving revision 1.2\n'
            b'diff -u -r1.1.1.1 Makefile\n'
            b'--- Makefile    26 Jul 2007 08:50:30 -0000      1.1\n'
            b'+++ Makefile    26 Jul 2007 10:20:20 -0000      1.2\n'
            b'@@ -1,6 +1,7 @@\n'
            b' # $Author: bob $\n'
            b' # $Date: 2014/12/18 13:09:42 $\n'
            b' # $Header: /src/Makefile,v 1.2 2014/12/18 '
            b'13:09:42 bob Exp $\n'
            b' # $Id: Makefile,v 1.2 2014/12/18 13:09:42 bob Exp $\n'
            b' # $Locker: bob $\n'
            b' # $Name: some_name $\n'
            b' # $RCSfile: Makefile,v $\n'
            b' # $Revision: 1.2 $\n'
            b' # $Source: /src/Makefile,v $\n'
            b' # $State: Exp $\n'
            b'+# foo \xf0\x9f\x92\xa9\n'
            b' include ../tools/Makefile.base-vars\n'
            b' NAME = misc-docs\n'
            b' OUTNAME = cvs-misc-docs\n', 'Makefile')

    def test_bad_root(self):
        """Testing CVSTool with a bad CVSROOT"""
        file = 'test/testfile'
        rev = Revision('1.1')
        badrepo = Repository(name='CVS',
                             path=self.cvs_repo_path + '2',
                             tool=Tool.objects.get(name='CVS'))
        badtool = badrepo.get_scmtool()

        self.assertRaises(SCMError, lambda: badtool.get_file(file, rev))

    def test_ssh(self):
        """Testing a SSH-backed CVS repository"""
        self._test_ssh(self.cvs_ssh_path, 'CVSROOT/modules')

    def test_ssh_with_site(self):
        """Testing a SSH-backed CVS repository with a LocalSite"""
        self._test_ssh_with_site(self.cvs_ssh_path, 'CVSROOT/modules')

    def _test_build_cvsroot(self,
                            repo_path,
                            expected_cvsroot,
                            expected_path,
                            expected_error=None,
                            username=None,
                            password=None):
        if expected_error:
            with self.assertRaisesMessage(ValidationError, expected_error):
                self.tool.build_cvsroot(repo_path,
                                        username,
                                        password,
                                        validate=True)

        cvsroot, norm_path = self.tool.build_cvsroot(repo_path,
                                                     username,
                                                     password,
                                                     validate=False)

        self.assertEqual(cvsroot, expected_cvsroot)
        self.assertEqual(norm_path, expected_path)
Ejemplo n.º 31
0
class MercurialTests(SCMTestCase):
    """Unit tests for mercurial."""

    fixtures = ['test_scmtools']

    def setUp(self):
        super(MercurialTests, self).setUp()

        hg_repo_path = os.path.join(os.path.dirname(__file__), '..',
                                    'testdata', 'hg_repo')
        self.repository = Repository(name='Test HG',
                                     path=hg_repo_path,
                                     tool=Tool.objects.get(name='Mercurial'))

        try:
            self.tool = self.repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest('Hg is not installed')

    def _first_file_in_diff(self, diff):
        return self.tool.get_parser(diff).parse()[0]

    def test_ssh_disallowed(self):
        """Testing HgTool does not allow SSH URLs"""
        with self.assertRaises(SCMError):
            self.tool.check_repository('ssh://foo')

    def test_git_parser_selection_with_header(self):
        """Testing HgTool returns the git parser when a header is present"""
        diffContents = (b'# HG changeset patch\n'
                        b'# Node ID 6187592a72d7\n'
                        b'# Parent  9d3f4147f294\n'
                        b'diff --git a/emptyfile b/emptyfile\n'
                        b'new file mode 100644\n')

        parser = self.tool.get_parser(diffContents)
        self.assertEqual(type(parser), HgGitDiffParser)

    def test_hg_parser_selection_with_header(self):
        """Testing HgTool returns the hg parser when a header is present"""
        diffContents = (b'# HG changeset patch'
                        b'# Node ID 6187592a72d7\n'
                        b'# Parent  9d3f4147f294\n'
                        b'diff -r 9d3f4147f294 -r 6187592a72d7 new.py\n'
                        b'--- /dev/null   Thu Jan 01 00:00:00 1970 +0000\n'
                        b'+++ b/new.py  Tue Apr 21 12:20:05 2015 -0400\n')

        parser = self.tool.get_parser(diffContents)
        self.assertEqual(type(parser), HgDiffParser)

    def test_git_parser_sets_commit_ids(self):
        """Testing HgGitDiffParser sets the parser commit ids"""
        diffContents = (b'# HG changeset patch\n'
                        b'# Node ID 6187592a72d7\n'
                        b'# Parent  9d3f4147f294\n'
                        b'diff --git a/emptyfile b/emptyfile\n'
                        b'new file mode 100644\n')

        parser = self.tool.get_parser(diffContents)
        parser.parse()
        self.assertEqual(parser.new_commit_id, b'6187592a72d7')
        self.assertEqual(parser.base_commit_id, b'9d3f4147f294')

    def test_patch_creates_new_file(self):
        """Testing HgTool with a patch that creates a new file"""
        self.assertEqual(
            PRE_CREATION,
            self.tool.parse_diff_revision('/dev/null', 'bf544ea505f8')[1])

    def test_diff_parser_new_file(self):
        """Testing HgDiffParser with a diff that creates a new file"""
        diffContents = (b'diff -r bf544ea505f8 readme\n'
                        b'--- /dev/null\n'
                        b'+++ b/readme\n')

        file = self._first_file_in_diff(diffContents)
        self.assertEqual(file.origFile, 'readme')

    def test_diff_parser_with_added_empty_file(self):
        """Testing HgDiffParser with a diff with an added empty file"""
        diff = (b'diff -r 356a6127ef19 -r 4960455a8e88 empty\n'
                b'--- /dev/null\n'
                b'+++ b/empty\n')

        file = self._first_file_in_diff(diff)
        self.assertEqual(file.origInfo, PRE_CREATION)
        self.assertEqual(file.origFile, 'empty')
        self.assertEqual(file.newInfo, '4960455a8e88')
        self.assertEqual(file.newFile, 'empty')
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_diff_parser_with_deleted_empty_file(self):
        """Testing HgDiffParser with a diff with a deleted empty file"""
        diff = (b'diff -r 356a6127ef19 -r 4960455a8e88 empty\n'
                b'--- a/empty\n'
                b'+++ /dev/null\n')

        file = self._first_file_in_diff(diff)
        self.assertEqual(file.origInfo, '356a6127ef19')
        self.assertEqual(file.origFile, 'empty')
        self.assertEqual(file.newInfo, '4960455a8e88')
        self.assertEqual(file.newFile, 'empty')
        self.assertFalse(file.binary)
        self.assertTrue(file.deleted)
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_diff_parser_uncommitted(self):
        """Testing HgDiffParser with a diff with an uncommitted change"""
        diffContents = (b'diff -r bf544ea505f8 readme\n'
                        b'--- a/readme\n'
                        b'+++ b/readme\n')

        file = self._first_file_in_diff(diffContents)
        self.assertEqual(file.origInfo, 'bf544ea505f8')
        self.assertEqual(file.origFile, 'readme')
        self.assertEqual(file.newInfo, 'Uncommitted')
        self.assertEqual(file.newFile, 'readme')

    def test_diff_parser_committed(self):
        """Testing HgDiffParser with a diff between committed revisions"""
        diffContents = (b'diff -r 356a6127ef19 -r 4960455a8e88 readme\n'
                        b'--- a/readme\n'
                        b'+++ b/readme\n')

        file = self._first_file_in_diff(diffContents)
        self.assertEqual(file.origInfo, '356a6127ef19')
        self.assertEqual(file.origFile, 'readme')
        self.assertEqual(file.newInfo, '4960455a8e88')
        self.assertEqual(file.newFile, 'readme')

    def test_diff_parser_with_preamble_junk(self):
        """Testing HgDiffParser with a diff that contains non-diff junk test
        as a preamble
        """
        diffContents = (b'changeset:   60:3613c58ad1d5\n'
                        b'user:        Michael Rowe <*****@*****.**>\n'
                        b'date:        Fri Jul 27 11:44:37 2007 +1000\n'
                        b'files:       readme\n'
                        b'description:\n'
                        b'Update the readme file\n'
                        b'\n'
                        b'\n'
                        b'diff -r 356a6127ef19 -r 4960455a8e88 readme\n'
                        b'--- a/readme\n'
                        b'+++ b/readme\n')

        file = self._first_file_in_diff(diffContents)
        self.assertEqual(file.origInfo, '356a6127ef19')
        self.assertEqual(file.origFile, 'readme')
        self.assertEqual(file.newInfo, '4960455a8e88')
        self.assertEqual(file.newFile, 'readme')

    def test_git_diff_parsing(self):
        """Testing HgDiffParser git diff support"""
        diffContents = (b'# Node ID 4960455a8e88\n'
                        b'# Parent bf544ea505f8\n'
                        b'diff --git a/path/to file/readme.txt '
                        b'b/new/path to/readme.txt\n'
                        b'rename from path/to file/readme.txt\n'
                        b'rename to new/path to/readme.txt\n'
                        b'--- a/path/to file/readme.txt\n'
                        b'+++ b/new/path to/readme.txt\n')

        file = self._first_file_in_diff(diffContents)
        self.assertEqual(file.origInfo, 'bf544ea505f8')
        self.assertEqual(file.origFile, 'path/to file/readme.txt')
        self.assertEqual(file.newInfo, '4960455a8e88')
        self.assertEqual(file.newFile, 'new/path to/readme.txt')

    def test_diff_parser_unicode(self):
        """Testing HgDiffParser with unicode characters"""

        diffContents = ('diff -r bf544ea505f8 réadme\n'
                        '--- a/réadme\n'
                        '+++ b/réadme\n').encode('utf-8')

        file = self._first_file_in_diff(diffContents)
        self.assertEqual(file.origInfo, 'bf544ea505f8')
        self.assertEqual(file.origFile, 'réadme')
        self.assertEqual(file.newInfo, 'Uncommitted')
        self.assertEqual(file.newFile, 'réadme')

    def test_git_diff_parsing_unicode(self):
        """Testing HgDiffParser git diff with unicode characters"""
        diffContents = ('# Node ID 4960455a8e88\n'
                        '# Parent bf544ea505f8\n'
                        'diff --git a/path/to file/réadme.txt '
                        'b/new/path to/réadme.txt\n'
                        'rename from path/to file/réadme.txt\n'
                        'rename to new/path to/réadme.txt\n'
                        '--- a/path/to file/réadme.txt\n'
                        '+++ b/new/path to/réadme.txt\n').encode('utf-8')

        file = self._first_file_in_diff(diffContents)
        self.assertEqual(file.origInfo, 'bf544ea505f8')
        self.assertEqual(file.origFile, 'path/to file/réadme.txt')
        self.assertEqual(file.newInfo, '4960455a8e88')
        self.assertEqual(file.newFile, 'new/path to/réadme.txt')

    def test_revision_parsing(self):
        """Testing HgDiffParser revision number parsing"""
        self.assertEqual(
            self.tool.parse_diff_revision('doc/readme', 'bf544ea505f8'),
            ('doc/readme', 'bf544ea505f8'))

        self.assertEqual(
            self.tool.parse_diff_revision('/dev/null', 'bf544ea505f8'),
            ('/dev/null', PRE_CREATION))

        # TODO think of a meaningful thing to test here...
        # self.assertRaises(SCMException,
        #                  lambda: self.tool.parse_diff_revision('', 'hello'))

    def test_get_branches(self):
        """Testing list of branches in HgClient.get_change"""
        value = self.tool.get_branches()
        self.assertTrue(isinstance(value, list))
        self.assertEqual(len(value), 1)

        self.assertEqual(value[0].id, 'default')
        self.assertEqual(value[0].commit,
                         '661e5dd3c4938ecbe8f77e2fdfa905d70485f94c')
        self.assertEqual(value[0].default, True)

    def test_get_change(self):
        """Testing raw diff of HgClient.get_change"""
        self.assertRaises(SCMError, lambda: self.tool.get_change('dummy'))

        value = self.tool.get_change('0')
        self.assertNotIn('goodbye', value.diff)
        self.assertEqual(value.id, 'f814b6e226d2ba6d26d02ca8edbff91f57ab2786')
        value = self.tool.get_change('1')
        self.assertIn('goodbye', value.diff)
        self.assertEqual(value.id, '661e5dd3c4938ecbe8f77e2fdfa905d70485f94c')

    def test_get_commits(self):
        """Testing commit objects in HgClient.get_commits"""
        value = self.tool.get_commits()
        self.assertTrue(isinstance(value, list))
        self.assertEqual(len(value), 2)

        self.assertEqual(value[0].id,
                         '661e5dd3c4938ecbe8f77e2fdfa905d70485f94c')
        self.assertEqual(value[0].message, 'second')
        self.assertEqual(value[0].author_name,
                         'Michael Rowe <*****@*****.**>')
        self.assertEqual(value[0].date, '2007-08-07T17:12:23')
        self.assertEqual(value[0].parent,
                         'f814b6e226d2ba6d26d02ca8edbff91f57ab2786')
        self.assertEqual(value[0].base_commit_id,
                         'f814b6e226d2ba6d26d02ca8edbff91f57ab2786')

        self.assertEqual(value[1].id,
                         'f814b6e226d2ba6d26d02ca8edbff91f57ab2786')
        self.assertEqual(value[1].message, 'first')
        self.assertEqual(value[1].author_name,
                         'Michael Rowe <*****@*****.**>')
        self.assertEqual(value[1].date, '2007-08-07T17:11:57')
        self.assertEqual(value[1].parent,
                         '0000000000000000000000000000000000000000')
        self.assertEqual(value[1].base_commit_id,
                         '0000000000000000000000000000000000000000')

        self.assertRaisesRegexp(SCMError, 'Cannot load commits: ',
                                lambda: self.tool.get_commits(branch='x'))

        rev = 'f814b6e226d2ba6d26d02ca8edbff91f57ab2786'
        value = self.tool.get_commits(start=rev)
        self.assertTrue(isinstance(value, list))
        self.assertEqual(len(value), 1)

    def test_get_commits_with_non_utc_server_timezone(self):
        """Testing commit objects in HgClient.get_commits with
        settings.TIME_ZONE != UTC
        """
        old_tz = os.environ[str('TZ')]
        os.environ[str('TZ')] = str('US/Pacific')

        try:
            value = self.tool.get_commits()
        finally:
            os.environ[str('TZ')] = old_tz

        self.assertTrue(isinstance(value, list))
        self.assertEqual(len(value), 2)

        self.assertEqual(value[0].id,
                         '661e5dd3c4938ecbe8f77e2fdfa905d70485f94c')
        self.assertEqual(value[0].message, 'second')
        self.assertEqual(value[0].author_name,
                         'Michael Rowe <*****@*****.**>')
        self.assertEqual(value[0].date, '2007-08-07T17:12:23')
        self.assertEqual(value[0].parent,
                         'f814b6e226d2ba6d26d02ca8edbff91f57ab2786')
        self.assertEqual(value[0].base_commit_id,
                         'f814b6e226d2ba6d26d02ca8edbff91f57ab2786')

        self.assertEqual(value[1].id,
                         'f814b6e226d2ba6d26d02ca8edbff91f57ab2786')
        self.assertEqual(value[1].message, 'first')
        self.assertEqual(value[1].author_name,
                         'Michael Rowe <*****@*****.**>')
        self.assertEqual(value[1].date, '2007-08-07T17:11:57')
        self.assertEqual(value[1].parent,
                         '0000000000000000000000000000000000000000')
        self.assertEqual(value[1].base_commit_id,
                         '0000000000000000000000000000000000000000')

        self.assertRaisesRegexp(SCMError, 'Cannot load commits: ',
                                lambda: self.tool.get_commits(branch='x'))

        rev = 'f814b6e226d2ba6d26d02ca8edbff91f57ab2786'
        value = self.tool.get_commits(start=rev)
        self.assertTrue(isinstance(value, list))
        self.assertEqual(len(value), 1)

    def test_get_file(self):
        """Testing HgTool.get_file"""
        rev = Revision('661e5dd3c493')
        file = 'doc/readme'

        value = self.tool.get_file(file, rev)
        self.assertTrue(isinstance(value, bytes))
        self.assertEqual(value, b'Hello\n\ngoodbye\n')

        self.assertTrue(self.tool.file_exists('doc/readme', rev))
        self.assertTrue(not self.tool.file_exists('doc/readme2', rev))

        self.assertRaises(FileNotFoundError, lambda: self.tool.get_file(''))

        self.assertRaises(FileNotFoundError,
                          lambda: self.tool.get_file('hello', PRE_CREATION))

    def test_get_file_base_commit_id_override(self):
        """Testing base_commit_id overrides revision in HgTool.get_file"""
        base_commit_id = Revision('661e5dd3c493')
        bogus_rev = Revision('bogusrevision')
        file = 'doc/readme'

        value = self.tool.get_file(file,
                                   bogus_rev,
                                   base_commit_id=base_commit_id)
        self.assertTrue(isinstance(value, bytes))
        self.assertEqual(value, b'Hello\n\ngoodbye\n')

        self.assertTrue(
            self.tool.file_exists('doc/readme',
                                  bogus_rev,
                                  base_commit_id=base_commit_id))
        self.assertTrue(not self.tool.file_exists(
            'doc/readme2', bogus_rev, base_commit_id=base_commit_id))

    def test_interface(self):
        """Testing basic HgTool API"""
        self.assertTrue(self.tool.diffs_use_absolute_paths)

        self.assertRaises(NotImplementedError,
                          lambda: self.tool.get_changeset(1))

    @online_only
    def test_https_repo(self):
        """Testing HgTool.file_exists with an HTTPS-based repository"""
        repo = Repository(name='Test HG2',
                          path='https://bitbucket.org/pypy/pypy',
                          tool=Tool.objects.get(name='Mercurial'))
        tool = repo.get_scmtool()

        rev = Revision('877cf1960916')

        self.assertTrue(tool.file_exists('TODO.rst', rev))
        self.assertTrue(not tool.file_exists('TODO.rstNotFound', rev))
Ejemplo n.º 32
0
class SubversionTests(DjangoTestCase):
    """Unit tests for subversion."""
    fixtures = ['test_scmtools.json']

    def setUp(self):
        svn_repo_path = os.path.join(os.path.dirname(__file__),
                                     'testdata/svn_repo')
        self.repository = Repository(name='Subversion SVN',
                                     path='file://' + svn_repo_path,
                                     tool=Tool.objects.get(name='Subversion'))

        try:
            self.tool = self.repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest('pysvn is not installed')

    def test_ssh(self):
        """Testing a SSH-backed Subversion repository"""
        repo_path, username, password = _get_repo_test_info('SVN_SSH')
        self.tool.check_repository(repo_path, username, password)

    def testGetFile(self):
        """Testing SVNTool.get_file"""
        expected = 'include ../tools/Makefile.base-vars\nNAME = misc-docs\n' + \
                   'OUTNAME = svn-misc-docs\nINSTALL_DIR = $(DESTDIR)/usr/s' + \
                   'hare/doc/subversion\ninclude ../tools/Makefile.base-rul' + \
                   'es\n'

        # There are 3 versions of this test in order to get 100% coverage of
        # the svn module.
        rev = Revision('2')
        file = 'trunk/doc/misc-docs/Makefile'

        self.assertEqual(self.tool.get_file(file, rev), expected)

        self.assertEqual(self.tool.get_file('/' + file, rev), expected)

        self.assertEqual(
            self.tool.get_file(self.repository.path + '/' + file, rev),
            expected)

        self.assert_(self.tool.file_exists('trunk/doc/misc-docs/Makefile'))
        self.assert_(
            not self.tool.file_exists('trunk/doc/misc-docs/Makefile2'))

        self.assertRaises(FileNotFoundError, lambda: self.tool.get_file(''))

        self.assertRaises(FileNotFoundError,
                          lambda: self.tool.get_file('hello', PRE_CREATION))

    def testRevisionParsing(self):
        """Testing revision number parsing"""
        self.assertEqual(
            self.tool.parse_diff_revision('', '(working copy)')[1], HEAD)
        self.assertEqual(
            self.tool.parse_diff_revision('', '   (revision 0)')[1],
            PRE_CREATION)

        self.assertEqual(
            self.tool.parse_diff_revision('', '(revision 1)')[1], '1')
        self.assertEqual(
            self.tool.parse_diff_revision('', '(revision 23)')[1], '23')

        self.assertEqual(
            self.tool.parse_diff_revision(
                '', '2007-06-06 15:32:23 UTC (rev 10958)')[1], '10958')

        self.assertRaises(SCMError,
                          lambda: self.tool.parse_diff_revision('', 'hello'))

    def testInterface(self):
        """Testing basic SVNTool API"""
        self.assertEqual(self.tool.get_diffs_use_absolute_paths(), False)

        self.assertRaises(NotImplementedError,
                          lambda: self.tool.get_changeset(1))

        self.assertRaises(NotImplementedError,
                          lambda: self.tool.get_pending_changesets(1))

    def testBinaryDiff(self):
        """Testing parsing SVN diff with binary file"""
        diff = "Index: binfile\n===========================================" + \
               "========================\nCannot display: file marked as a " + \
               "binary type.\nsvn:mime-type = application/octet-stream\n"

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, 'binfile')
        self.assertEqual(file.binary, True)

    def testKeywordDiff(self):
        """Testing parsing SVN diff with keywords"""
        # 'svn cat' will expand special variables in svn:keywords,
        # but 'svn diff' doesn't expand anything.  This causes the
        # patch to fail if those variables appear in the patch context.
        diff = "Index: Makefile\n" \
               "===========================================================" \
               "========\n" \
               "--- Makefile    (revision 4)\n" \
               "+++ Makefile    (working copy)\n" \
               "@@ -1,6 +1,7 @@\n" \
               " # $Id$\n" \
               " # $Rev$\n" \
               " # $Revision::     $\n" \
               "+# foo\n" \
               " include ../tools/Makefile.base-vars\n" \
               " NAME = misc-docs\n" \
               " OUTNAME = svn-misc-docs\n"

        filename = 'trunk/doc/misc-docs/Makefile'
        rev = Revision('4')
        file = self.tool.get_file(filename, rev)
        patch(diff, file, filename)

    def testUnterminatedKeywordDiff(self):
        """Testing parsing SVN diff with unterminated keywords"""
        diff = "Index: Makefile\n" \
               "===========================================================" \
               "========\n" \
               "--- Makefile    (revision 4)\n" \
               "+++ Makefile    (working copy)\n" \
               "@@ -1,6 +1,7 @@\n" \
               " # $Id$\n" \
               " # $Id:\n" \
               " # $Rev$\n" \
               " # $Revision::     $\n" \
               "+# foo\n" \
               " include ../tools/Makefile.base-vars\n" \
               " NAME = misc-docs\n" \
               " OUTNAME = svn-misc-docs\n"

        filename = 'trunk/doc/misc-docs/Makefile'
        rev = Revision('5')
        file = self.tool.get_file(filename, rev)
        patch(diff, file, filename)
Ejemplo n.º 33
0
class GitTests(DjangoTestCase):
    """Unit tests for Git."""

    fixtures = ["test_scmtools.json"]

    def setUp(self):
        tool = Tool.objects.get(name="Git")

        local_repo_path = os.path.join(os.path.dirname(__file__), "testdata", "git_repo")
        remote_repo_path = "[email protected]:reviewboard/reviewboard.git"
        remote_repo_raw_url = "http://github.com/api/v2/yaml/blob/show/" "reviewboard/reviewboard/<revision>"

        self.repository = Repository(name="Git test repo", path=local_repo_path, tool=tool)
        self.remote_repository = Repository(
            name="Remote Git test repo", path=remote_repo_path, raw_file_url=remote_repo_raw_url, tool=tool
        )

        try:
            self.tool = self.repository.get_scmtool()
            self.remote_tool = self.remote_repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest("git binary not found")

    def _readFixture(self, filename):
        return open(os.path.join(os.path.dirname(__file__), "testdata/%s" % filename), "r").read()

    def _getFileInDiff(self, diff, filenum=0):
        return self.tool.get_parser(diff).parse()[filenum]

    def testFilemodeDiff(self):
        """Testing parsing filemode changes Git diff"""
        diff = self._readFixture("git_filemode.diff")
        file = self._getFileInDiff(diff)
        self.assertEqual(file.origFile, "testing")
        self.assertEqual(file.newFile, "testing")
        self.assertEqual(file.origInfo, "e69de29")
        self.assertEqual(file.newInfo, "bcae657")
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertEqual(file.data.splitlines()[0], "diff --git a/testing b/testing")
        self.assertEqual(file.data.splitlines()[-1], "+ADD")

    def testFilemodeWithFollowingDiff(self):
        """Testing parsing filemode changes with following Git diff"""
        diff = self._readFixture("git_filemode2.diff")
        file = self._getFileInDiff(diff)
        self.assertEqual(file.origFile, "testing")
        self.assertEqual(file.newFile, "testing")
        self.assertEqual(file.origInfo, "e69de29")
        self.assertEqual(file.newInfo, "bcae657")
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertEqual(file.data.splitlines()[0], "diff --git a/testing b/testing")
        self.assertEqual(file.data.splitlines()[-1], "+ADD")
        file = self._getFileInDiff(diff, 1)
        self.assertEqual(file.origFile, "cfg/testcase.ini")
        self.assertEqual(file.newFile, "cfg/testcase.ini")
        self.assertEqual(file.origInfo, "cc18ec8")
        self.assertEqual(file.newInfo, "5e70b73")
        self.assertEqual(file.data.splitlines()[0], "diff --git a/cfg/testcase.ini b/cfg/testcase.ini")
        self.assertEqual(file.data.splitlines()[-1], "+db = pyunit")

    def testSimpleDiff(self):
        """Testing parsing simple Git diff"""
        diff = self._readFixture("git_simple.diff")
        file = self._getFileInDiff(diff)
        self.assertEqual(file.origFile, "cfg/testcase.ini")
        self.assertEqual(file.newFile, "cfg/testcase.ini")
        self.assertEqual(file.origInfo, "cc18ec8")
        self.assertEqual(file.newInfo, "5e70b73")
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertEqual(len(file.data), 219)
        self.assertEqual(file.data.splitlines()[0], "diff --git a/cfg/testcase.ini b/cfg/testcase.ini")
        self.assertEqual(file.data.splitlines()[-1], "+db = pyunit")

    def testNewfileDiff(self):
        """Testing parsing Git diff with new file"""
        diff = self._readFixture("git_newfile.diff")
        file = self._getFileInDiff(diff)
        self.assertEqual(file.origFile, "IAMNEW")
        self.assertEqual(file.newFile, "IAMNEW")
        self.assertEqual(file.origInfo, PRE_CREATION)
        self.assertEqual(file.newInfo, "e69de29")
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertEqual(len(file.data), 80)
        self.assertEqual(file.data.splitlines()[0], "diff --git a/IAMNEW b/IAMNEW")
        self.assertEqual(file.data.splitlines()[-1], "+Hello")

    def testNewfileNoContentDiff(self):
        """Testing parsing Git diff new file, no content"""
        diff = self._readFixture("git_newfile_nocontent.diff")
        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 0)

    def testNewfileNoContentWithFollowingDiff(self):
        """Testing parsing Git diff new file, no content, with following"""
        diff = self._readFixture("git_newfile_nocontent2.diff")
        self.assertEqual(len(self.tool.get_parser(diff).parse()), 1)
        file = self._getFileInDiff(diff)
        self.assertEqual(file.origFile, "cfg/testcase.ini")
        self.assertEqual(file.newFile, "cfg/testcase.ini")
        self.assertEqual(file.origInfo, "cc18ec8")
        self.assertEqual(file.newInfo, "5e70b73")
        self.assertEqual(file.data.splitlines()[0], "diff --git a/cfg/testcase.ini b/cfg/testcase.ini")
        self.assertEqual(file.data.splitlines()[-1], "+db = pyunit")

    def testDelFileDiff(self):
        """Testing parsing Git diff with deleted file"""
        diff = self._readFixture("git_delfile.diff")
        file = self._getFileInDiff(diff)
        self.assertEqual(file.origFile, "OLDFILE")
        self.assertEqual(file.newFile, "OLDFILE")
        self.assertEqual(file.origInfo, "8ebcb01")
        self.assertEqual(file.newInfo, "0000000")
        self.assertFalse(file.binary)
        self.assertTrue(file.deleted)
        self.assertEqual(len(file.data), 84)
        self.assertEqual(file.data.splitlines()[0], "diff --git a/OLDFILE b/OLDFILE")
        self.assertEqual(file.data.splitlines()[-1], "-Goodbye")

    def testBinaryDiff(self):
        """Testing parsing Git diff with binary"""
        diff = self._readFixture("git_binary.diff")
        file = self._getFileInDiff(diff)
        self.assertEqual(file.origFile, "pysvn-1.5.1.tar.gz")
        self.assertEqual(file.newFile, "pysvn-1.5.1.tar.gz")
        self.assertEqual(file.origInfo, PRE_CREATION)
        self.assertEqual(file.newInfo, "86b520c")
        self.assertTrue(file.binary)
        self.assertFalse(file.deleted)
        self.assertEqual(len(file.data), 53)
        self.assertEqual(file.data.splitlines()[0], "diff --git a/pysvn-1.5.1.tar.gz b/pysvn-1.5.1.tar.gz")

    def testComplexDiff(self):
        """Testing parsing Git diff with existing and new files"""
        diff = self._readFixture("git_complex.diff")
        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 6)
        self.assertEqual(files[0].origFile, "cfg/testcase.ini")
        self.assertEqual(files[0].newFile, "cfg/testcase.ini")
        self.assertEqual(files[0].origInfo, "5e35098")
        self.assertEqual(files[0].newInfo, "e254ef4")
        self.assertFalse(files[0].binary)
        self.assertFalse(files[0].deleted)
        self.assertEqual(len(files[0].data), 519)
        self.assertEqual(files[0].data.splitlines()[0], "diff --git a/cfg/testcase.ini b/cfg/testcase.ini")
        self.assertEqual(files[0].data.splitlines()[12], "         if isinstance(value, basestring):")

        self.assertEqual(files[1].origFile, "tests/tests.py")
        self.assertEqual(files[1].newFile, "tests/tests.py")
        self.assertEqual(files[1].origInfo, PRE_CREATION)
        self.assertEqual(files[1].newInfo, "e279a06")
        self.assertFalse(files[1].binary)
        self.assertFalse(files[1].deleted)
        self.assertEqual(len(files[1].data), 138)
        self.assertEqual(files[1].data.splitlines()[0], "diff --git a/tests/tests.py b/tests/tests.py")
        self.assertEqual(files[1].data.splitlines()[-1], "+This is some new content")

        self.assertEqual(files[2].origFile, "pysvn-1.5.1.tar.gz")
        self.assertEqual(files[2].newFile, "pysvn-1.5.1.tar.gz")
        self.assertEqual(files[2].origInfo, PRE_CREATION)
        self.assertEqual(files[2].newInfo, "86b520c")
        self.assertTrue(files[2].binary)
        self.assertFalse(files[2].deleted)
        self.assertEqual(len(files[2].data), 53)
        self.assertEqual(files[2].data.splitlines()[0], "diff --git a/pysvn-1.5.1.tar.gz b/pysvn-1.5.1.tar.gz")

        self.assertEqual(files[3].origFile, "readme")
        self.assertEqual(files[3].newFile, "readme")
        self.assertEqual(files[3].origInfo, "5e35098")
        self.assertEqual(files[3].newInfo, "e254ef4")
        self.assertFalse(files[3].binary)
        self.assertFalse(files[3].deleted)
        self.assertEqual(len(files[3].data), 97)
        self.assertEqual(files[3].data.splitlines()[0], "diff --git a/readme b/readme")
        self.assertEqual(files[3].data.splitlines()[-1], "+Hello there")

        self.assertEqual(files[4].origFile, "OLDFILE")
        self.assertEqual(files[4].newFile, "OLDFILE")
        self.assertEqual(files[4].origInfo, "8ebcb01")
        self.assertEqual(files[4].newInfo, "0000000")
        self.assertFalse(files[4].binary)
        self.assertTrue(files[4].deleted)
        self.assertEqual(len(files[4].data), 84)
        self.assertEqual(files[4].data.splitlines()[0], "diff --git a/OLDFILE b/OLDFILE")
        self.assertEqual(files[4].data.splitlines()[-1], "-Goodbye")

        self.assertEqual(files[5].origFile, "readme2")
        self.assertEqual(files[5].newFile, "readme2")
        self.assertEqual(files[5].origInfo, "5e43098")
        self.assertEqual(files[5].newInfo, "e248ef4")
        self.assertFalse(files[5].binary)
        self.assertFalse(files[5].deleted)
        self.assertEqual(len(files[5].data), 101)
        self.assertEqual(files[5].data.splitlines()[0], "diff --git a/readme2 b/readme2")
        self.assertEqual(files[5].data.splitlines()[-1], "+Hello there")

    def testParseDiffRevision(self):
        """Testing Git revision number parsing"""

        self.assertEqual(self.tool.parse_diff_revision("doc/readme", "bf544ea"), ("doc/readme", "bf544ea"))
        self.assertEqual(self.tool.parse_diff_revision("/dev/null", "bf544ea"), ("/dev/null", PRE_CREATION))
        self.assertEqual(self.tool.parse_diff_revision("/dev/null", "0000000"), ("/dev/null", PRE_CREATION))

    def testFileExists(self):
        """Testing GitTool.file_exists"""

        self.assert_(self.tool.file_exists("readme", "e965047"))
        self.assert_(self.tool.file_exists("readme", "d6613f5"))

        self.assert_(not self.tool.file_exists("readme", PRE_CREATION))
        self.assert_(not self.tool.file_exists("readme", "fffffff"))
        self.assert_(not self.tool.file_exists("readme2", "fffffff"))

        # these sha's are valid, but commit and tree objects, not blobs
        self.assert_(not self.tool.file_exists("readme", "a62df6c"))
        self.assert_(not self.tool.file_exists("readme2", "ccffbb4"))

    def testGetFile(self):
        """Testing GitTool.get_file"""

        self.assertEqual(self.tool.get_file("readme", PRE_CREATION), "")
        self.assertEqual(self.tool.get_file("readme", "e965047"), "Hello\n")
        self.assertEqual(self.tool.get_file("readme", "d6613f5"), "Hello there\n")

        self.assertEqual(self.tool.get_file("readme"), "Hello there\n")

        self.assertRaises(SCMError, lambda: self.tool.get_file(""))

        self.assertRaises(FileNotFoundError, lambda: self.tool.get_file("", "0000000"))
        self.assertRaises(FileNotFoundError, lambda: self.tool.get_file("hello", "0000000"))
        self.assertRaises(FileNotFoundError, lambda: self.tool.get_file("readme", "0000000"))

    def testParseDiffRevisionWithRemoteAndShortSHA1Error(self):
        """Testing GitTool.parse_diff_revision with remote files and short SHA1 error"""
        self.assertRaises(ShortSHA1Error, lambda: self.remote_tool.parse_diff_revision("README", "d7e96b3"))

    def testGetFileWithRemoteAndShortSHA1Error(self):
        """Testing GitTool.get_file with remote files and short SHA1 error"""
        self.assertRaises(ShortSHA1Error, lambda: self.remote_tool.get_file("README", "d7e96b3"))
Ejemplo n.º 34
0
class SubversionTests(DjangoTestCase):
    """Unit tests for subversion."""
    fixtures = ['test_scmtools.json']

    def setUp(self):
        svn_repo_path = os.path.join(os.path.dirname(__file__),
                                     'testdata/svn_repo')
        self.repository = Repository(name='Subversion SVN',
                                     path='file://' + svn_repo_path,
                                     tool=Tool.objects.get(name='Subversion'))

        try:
            self.tool = self.repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest('pysvn is not installed')

    def testGetFile(self):
        """Testing SVNTool.get_file"""
        expected = 'include ../tools/Makefile.base-vars\nNAME = misc-docs\n' + \
                   'OUTNAME = svn-misc-docs\nINSTALL_DIR = $(DESTDIR)/usr/s' + \
                   'hare/doc/subversion\ninclude ../tools/Makefile.base-rul' + \
                   'es\n'

        # There are 3 versions of this test in order to get 100% coverage of
        # the svn module.
        rev = Revision('2')
        file = 'trunk/doc/misc-docs/Makefile'

        self.assertEqual(self.tool.get_file(file, rev), expected)

        self.assertEqual(self.tool.get_file('/' + file, rev), expected)

        self.assertEqual(self.tool.get_file(self.repository.path + '/' + file, rev),
                         expected)


        self.assert_(self.tool.file_exists('trunk/doc/misc-docs/Makefile'))
        self.assert_(not self.tool.file_exists('trunk/doc/misc-docs/Makefile2'))

        self.assertRaises(FileNotFoundError,
                          lambda: self.tool.get_file(''))

        self.assertRaises(FileNotFoundError,
                          lambda: self.tool.get_file('hello',
                                                     PRE_CREATION))

    def testRevisionParsing(self):
        """Testing revision number parsing"""
        self.assertEqual(self.tool.parse_diff_revision('', '(working copy)')[1],
                         HEAD)
        self.assertEqual(self.tool.parse_diff_revision('', '   (revision 0)')[1],
                         PRE_CREATION)

        self.assertEqual(self.tool.parse_diff_revision('', '(revision 1)')[1],
                         '1')
        self.assertEqual(self.tool.parse_diff_revision('', '(revision 23)')[1],
                         '23')

        self.assertEqual(self.tool.parse_diff_revision('',
            '2007-06-06 15:32:23 UTC (rev 10958)')[1], '10958')

        self.assertRaises(SCMError,
                          lambda: self.tool.parse_diff_revision('', 'hello'))

    def testInterface(self):
        """Testing basic SVNTool API"""
        self.assertEqual(self.tool.get_diffs_use_absolute_paths(), False)

        self.assertRaises(NotImplementedError,
                          lambda: self.tool.get_changeset(1))

        self.assertRaises(NotImplementedError,
                          lambda: self.tool.get_pending_changesets(1))

    def testBinaryDiff(self):
        """Testing parsing SVN diff with binary file"""
        diff = "Index: binfile\n===========================================" + \
               "========================\nCannot display: file marked as a " + \
               "binary type.\nsvn:mime-type = application/octet-stream\n"

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, 'binfile')
        self.assertEqual(file.binary, True)

    def testKeywordDiff(self):
        """Testing parsing SVN diff with keywords"""
        # 'svn cat' will expand special variables in svn:keywords,
        # but 'svn diff' doesn't expand anything.  This causes the
        # patch to fail if those variables appear in the patch context.
        diff = "Index: Makefile\n" \
               "===========================================================" \
               "========\n" \
               "--- Makefile    (revision 4)\n" \
               "+++ Makefile    (working copy)\n" \
               "@@ -1,6 +1,7 @@\n" \
               " # $Id$\n" \
               " # $Rev$\n" \
               " # $Revision::     $\n" \
               "+# foo\n" \
               " include ../tools/Makefile.base-vars\n" \
               " NAME = misc-docs\n" \
               " OUTNAME = svn-misc-docs\n"

        filename = 'trunk/doc/misc-docs/Makefile'
        rev = Revision('4')
        file = self.tool.get_file(filename, rev)
        patch(diff, file, filename)
Ejemplo n.º 35
0
class CVSTests(SCMTestCase):
    """Unit tests for CVS."""

    fixtures = ['test_scmtools']

    def setUp(self):
        super(CVSTests, self).setUp()

        self.cvs_repo_path = os.path.join(os.path.dirname(__file__),
                                          '..', 'testdata', 'cvs_repo')
        self.cvs_ssh_path = (':ext:localhost:%s'
                             % self.cvs_repo_path.replace('\\', '/'))
        self.repository = Repository(name='CVS',
                                     path=self.cvs_repo_path,
                                     tool=Tool.objects.get(name='CVS'))

        try:
            self.tool = self.repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest('cvs binary not found')

    def test_build_cvsroot_with_port(self):
        """Testing CVSTool.build_cvsroot with a port"""
        self._test_build_cvsroot(
            repo_path='example.com:123/cvsroot/test',
            username='******',
            expected_cvsroot=':pserver:[email protected]:123/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_without_port(self):
        """Testing CVSTool.build_cvsroot without a port"""
        self._test_build_cvsroot(
            repo_path='example.com:/cvsroot/test',
            username='******',
            expected_cvsroot=':pserver:[email protected]:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_pserver_and_no_user_or_password(self):
        """Testing CVSTool.build_cvsroot with :pserver: and no user or
        password
        """
        self._test_build_cvsroot(
            repo_path=':pserver:example.com:/cvsroot/test',
            expected_cvsroot=':pserver:example.com:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_pserver_and_inline_user(self):
        """Testing CVSTool.build_cvsroot with :pserver: and inline user"""
        self._test_build_cvsroot(
            repo_path=':pserver:[email protected]:/cvsroot/test',
            expected_cvsroot=':pserver:[email protected]:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_pserver_and_inline_user_and_password(self):
        """Testing CVSTool.build_cvsroot with :pserver: and inline user and
        password
        """
        self._test_build_cvsroot(
            repo_path=':pserver:anonymous:[email protected]:/cvsroot/test',
            expected_cvsroot=':pserver:anonymous:[email protected]:'
                             '/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_pserver_and_form_user(self):
        """Testing CVSTool.build_cvsroot with :pserver: and form-provided
        user
        """
        self._test_build_cvsroot(
            repo_path=':pserver:example.com:/cvsroot/test',
            username='******',
            expected_cvsroot=':pserver:[email protected]:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_pserver_and_form_user_and_password(self):
        """Testing CVSTool.build_cvsroot with :pserver: and form-provided
        user and password
        """
        self._test_build_cvsroot(
            repo_path=':pserver:example.com:/cvsroot/test',
            username='******',
            password='******',
            expected_cvsroot=':pserver:anonymous:[email protected]:'
                             '/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_pserver_and_inline_takes_precedence(self):
        """Testing CVSTool.build_cvsroot with :pserver: and inline user/password
        taking precedence
        """
        self._test_build_cvsroot(
            repo_path=':pserver:anonymous:[email protected]:/cvsroot/test',
            username='******',
            password='******',
            expected_cvsroot=':pserver:anonymous:[email protected]:'
                             '/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_gserver(self):
        """Testing CVSTool.build_cvsroot with :gserver:"""
        self._test_build_cvsroot(
            repo_path=':gserver:localhost:/cvsroot/test',
            expected_cvsroot=':gserver:localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_gserver_with_username(self):
        """Testing CVSTool.build_cvsroot with :gserver: with username"""
        self._test_build_cvsroot(
            repo_path=':gserver:user@localhost:/cvsroot/test',
            expected_cvsroot=':gserver:user@localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

        self._test_build_cvsroot(
            repo_path=':gserver:localhost:/cvsroot/test',
            username='******',
            expected_cvsroot=':gserver:user@localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_gserver_with_port(self):
        """Testing CVSTool.build_cvsroot with :gserver: with port"""
        self._test_build_cvsroot(
            repo_path=':gserver:localhost:123/cvsroot/test',
            expected_cvsroot=':gserver:localhost:123/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_gserver_validates_password(self):
        """Testing CVSTool.build_cvsroot with :gserver: validates password"""
        self._test_build_cvsroot(
            repo_path=':gserver:user:pass@localhost:/cvsroot/test',
            expected_error='"gserver" CVSROOTs do not support passwords.',
            expected_cvsroot=':gserver:user@localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_kserver(self):
        """Testing CVSTool.build_cvsroot with :kserver:"""
        self._test_build_cvsroot(
            repo_path=':kserver:localhost:/cvsroot/test',
            expected_cvsroot=':kserver:localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_kserver_with_username(self):
        """Testing CVSTool.build_cvsroot with :kserver: with username"""
        self._test_build_cvsroot(
            repo_path=':kserver:user@localhost:/cvsroot/test',
            expected_cvsroot=':kserver:user@localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

        self._test_build_cvsroot(
            repo_path=':kserver:localhost:/cvsroot/test',
            username='******',
            expected_cvsroot=':kserver:user@localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_kserver_with_port(self):
        """Testing CVSTool.build_cvsroot with :kserver: with port"""
        self._test_build_cvsroot(
            repo_path=':kserver:localhost:123/cvsroot/test',
            expected_cvsroot=':kserver:localhost:123/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_kserver_validates_password(self):
        """Testing CVSTool.build_cvsroot with :kserver: validates password"""
        self._test_build_cvsroot(
            repo_path=':kserver:user:pass@localhost:/cvsroot/test',
            expected_error='"kserver" CVSROOTs do not support passwords.',
            expected_cvsroot=':kserver:user@localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_ext(self):
        """Testing CVSTool.build_cvsroot with :ext:"""
        self._test_build_cvsroot(
            repo_path=':ext:localhost:/cvsroot/test',
            expected_cvsroot=':ext:localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_ext_validates_password(self):
        """Testing CVSTool.build_cvsroot with :ext: validates password"""
        self._test_build_cvsroot(
            repo_path=':ext:user:pass@localhost:/cvsroot/test',
            expected_error='"ext" CVSROOTs do not support passwords.',
            expected_cvsroot=':ext:user@localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_ext_validates_port(self):
        """Testing CVSTool.build_cvsroot with :ext: validates port"""
        self._test_build_cvsroot(
            repo_path=':ext:localhost:123/cvsroot/test',
            expected_error='"ext" CVSROOTs do not support specifying ports.',
            expected_cvsroot=':ext:localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_server(self):
        """Testing CVSTool.build_cvsroot with :server:"""
        self._test_build_cvsroot(
            repo_path=':server:localhost:/cvsroot/test',
            expected_cvsroot=':server:localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_server_validates_password(self):
        """Testing CVSTool.build_cvsroot with :server: validates password"""
        self._test_build_cvsroot(
            repo_path=':server:user:pass@localhost:/cvsroot/test',
            expected_error='"server" CVSROOTs do not support passwords.',
            expected_cvsroot=':server:user@localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_server_validates_port(self):
        """Testing CVSTool.build_cvsroot with :server: validates port"""
        self._test_build_cvsroot(
            repo_path=':server:localhost:123/cvsroot/test',
            expected_error='"server" CVSROOTs do not support specifying '
                           'ports.',
            expected_cvsroot=':server:localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_ssh(self):
        """Testing CVSTool.build_cvsroot with :ssh:"""
        self._test_build_cvsroot(
            repo_path=':ssh:localhost:/cvsroot/test',
            expected_cvsroot=':ssh:localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_ssh_validates_password(self):
        """Testing CVSTool.build_cvsroot with :ssh: validates password"""
        self._test_build_cvsroot(
            repo_path=':ssh:user:pass@localhost:/cvsroot/test',
            expected_error='"ssh" CVSROOTs do not support passwords.',
            expected_cvsroot=':ssh:user@localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_ssh_validates_port(self):
        """Testing CVSTool.build_cvsroot with :ssh: validates port"""
        self._test_build_cvsroot(
            repo_path=':ssh:localhost:123/cvsroot/test',
            expected_error='"ssh" CVSROOTs do not support specifying '
                           'ports.',
            expected_cvsroot=':ssh:localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_extssh(self):
        """Testing CVSTool.build_cvsroot with :extssh:"""
        self._test_build_cvsroot(
            repo_path=':extssh:localhost:/cvsroot/test',
            expected_cvsroot=':extssh:localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_extssh_validates_password(self):
        """Testing CVSTool.build_cvsroot with :extssh: validates password"""
        self._test_build_cvsroot(
            repo_path=':extssh:user:pass@localhost:/cvsroot/test',
            expected_error='"extssh" CVSROOTs do not support passwords.',
            expected_cvsroot=':extssh:user@localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_extssh_validates_port(self):
        """Testing CVSTool.build_cvsroot with :extssh: validates port"""
        self._test_build_cvsroot(
            repo_path=':extssh:localhost:123/cvsroot/test',
            expected_error='"extssh" CVSROOTs do not support specifying '
                           'ports.',
            expected_cvsroot=':extssh:localhost:/cvsroot/test',
            expected_path='/cvsroot/test')

    def test_path_with_fork(self):
        """Testing CVSTool.build_cvsroot with :fork:"""
        self._test_build_cvsroot(
            repo_path=':fork:/home/myuser/cvsroot',
            expected_cvsroot=':fork:/home/myuser/cvsroot',
            expected_path='/home/myuser/cvsroot')

    def test_path_with_fork_validates_username(self):
        """Testing CVSTool.build_cvsroot with :fork: validates usernames"""
        self._test_build_cvsroot(
            repo_path=':fork:/home/myuser/cvsroot',
            username='******',
            expected_error='"fork" CVSROOTs do not support usernames.',
            expected_cvsroot=':fork:/home/myuser/cvsroot',
            expected_path='/home/myuser/cvsroot')

    def test_path_with_fork_validates_password(self):
        """Testing CVSTool.build_cvsroot with :fork: validates passwords"""
        self._test_build_cvsroot(
            repo_path=':fork:/home/myuser/cvsroot',
            password='******',
            expected_error='"fork" CVSROOTs do not support passwords.',
            expected_cvsroot=':fork:/home/myuser/cvsroot',
            expected_path='/home/myuser/cvsroot')

    def test_path_with_local(self):
        """Testing CVSTool.build_cvsroot with :local:"""
        self._test_build_cvsroot(
            repo_path=':local:/home/myuser/cvsroot',
            expected_cvsroot=':local:/home/myuser/cvsroot',
            expected_path='/home/myuser/cvsroot')

    def test_path_with_local_validates_username(self):
        """Testing CVSTool.build_cvsroot with :local: validates usernames"""
        self._test_build_cvsroot(
            repo_path=':local:/home/myuser/cvsroot',
            username='******',
            expected_error='"local" CVSROOTs do not support usernames.',
            expected_cvsroot=':local:/home/myuser/cvsroot',
            expected_path='/home/myuser/cvsroot')

    def test_path_with_local_validates_password(self):
        """Testing CVSTool.build_cvsroot with :local: validates passwords"""
        self._test_build_cvsroot(
            repo_path=':local:/home/myuser/cvsroot',
            password='******',
            expected_error='"local" CVSROOTs do not support passwords.',
            expected_cvsroot=':local:/home/myuser/cvsroot',
            expected_path='/home/myuser/cvsroot')

    def test_get_file(self):
        """Testing CVSTool.get_file"""
        expected = b'test content\n'
        file = 'test/testfile'
        rev = Revision('1.1')
        badrev = Revision('2.1')

        value = self.tool.get_file(file, rev)
        self.assertTrue(isinstance(value, bytes))
        self.assertEqual(value, expected)
        self.assertEqual(self.tool.get_file(file + ',v', rev), expected)
        self.assertEqual(self.tool.get_file(self.tool.repopath + '/' +
                                            file + ',v', rev), expected)

        self.assertTrue(self.tool.file_exists('test/testfile'))
        self.assertTrue(self.tool.file_exists(
            self.tool.repopath + '/test/testfile'))
        self.assertTrue(self.tool.file_exists('test/testfile,v'))
        self.assertTrue(not self.tool.file_exists('test/testfile2'))
        self.assertTrue(not self.tool.file_exists(
            self.tool.repopath + '/test/testfile2'))
        self.assertTrue(not self.tool.file_exists('test/testfile2,v'))
        self.assertTrue(not self.tool.file_exists('test/testfile', badrev))

        self.assertRaises(FileNotFoundError,
                          lambda: self.tool.get_file(''))
        self.assertRaises(FileNotFoundError,
                          lambda: self.tool.get_file('hello', PRE_CREATION))

    def test_get_file_with_keywords(self):
        """Testing CVSTool.get_file with file containing keywords"""
        value = self.tool.get_file('test/testfile', Revision('1.2'))

        self.assertEqual(
            value,
            '$Id$\n'
            '$Author$\n'
            '\n'
            'test content\n')

    def test_revision_parsing(self):
        """Testing CVSTool revision number parsing"""
        self.assertEqual(self.tool.parse_diff_revision('', 'PRE-CREATION')[1],
                         PRE_CREATION)
        self.assertEqual(
            self.tool.parse_diff_revision(
                '', '7 Nov 2005 13:17:07 -0000\t1.2')[1],
            '1.2')
        self.assertEqual(
            self.tool.parse_diff_revision(
                '', '7 Nov 2005 13:17:07 -0000\t1.2.3.4')[1],
            '1.2.3.4')
        self.assertRaises(SCMError,
                          lambda: self.tool.parse_diff_revision('', 'hello'))

    def test_interface(self):
        """Testing basic CVSTool API"""
        self.assertTrue(self.tool.diffs_use_absolute_paths)

    def test_simple_diff(self):
        """Testing parsing CVS simple diff"""
        diff = (b'Index: testfile\n'
                b'==========================================================='
                b'========\n'
                b'RCS file: %s/test/testfile,v\n'
                b'retrieving revision 1.1.1.1\n'
                b'diff -u -r1.1.1.1 testfile\n'
                b'--- testfile    26 Jul 2007 08:50:30 -0000      1.1.1.1\n'
                b'+++ testfile    26 Jul 2007 10:20:20 -0000\n'
                b'@@ -1 +1,2 @@\n'
                b'-test content\n'
                b'+updated test content\n'
                b'+added info\n')
        diff = diff % self.cvs_repo_path

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, 'test/testfile')
        self.assertEqual(file.origInfo,
                         '26 Jul 2007 08:50:30 -0000      1.1.1.1')
        self.assertEqual(file.newFile, 'test/testfile')
        self.assertEqual(file.newInfo, '26 Jul 2007 10:20:20 -0000')
        self.assertEqual(file.data, diff)
        self.assertEqual(file.insert_count, 2)
        self.assertEqual(file.delete_count, 1)

    def test_new_diff_revision_format(self):
        """Testing parsing CVS diff with new revision format"""
        diff = (b'Index: %s/test/testfile\n'
                b'diff -u %s/test/testfile:1.5.2.1 %s/test/testfile:1.5.2.2\n'
                b'--- test/testfile:1.5.2.1\tThu Dec 15 16:27:47 2011\n'
                b'+++ test/testfile\tTue Jan 10 10:36:26 2012\n'
                b'@@ -1 +1,2 @@\n'
                b'-test content\n'
                b'+updated test content\n'
                b'+added info\n')
        diff = diff % (self.cvs_repo_path, self.cvs_repo_path,
                       self.cvs_repo_path)

        file = self.tool.get_parser(diff).parse()[0]
        f2, revision = self.tool.parse_diff_revision(file.origFile,
                                                     file.origInfo,
                                                     file.moved)
        self.assertEqual(f2, 'test/testfile')
        self.assertEqual(revision, '1.5.2.1')
        self.assertEqual(file.newFile, 'test/testfile')
        self.assertEqual(file.newInfo, 'Tue Jan 10 10:36:26 2012')
        self.assertEqual(file.insert_count, 2)
        self.assertEqual(file.delete_count, 1)

    def test_bad_diff(self):
        """Testing parsing CVS diff with bad info"""
        diff = (b'Index: newfile\n'
                b'==========================================================='
                b'========\n'
                b'diff -N newfile\n'
                b'--- /dev/null\t1 Jan 1970 00:00:00 -0000\n'
                b'+++ newfile\t26 Jul 2007 10:11:45 -0000\n'
                b'@@ -0,0 +1 @@\n'
                b'+new file content')

        self.assertRaises(DiffParserError,
                          lambda: self.tool.get_parser(diff).parse())

    def test_bad_diff2(self):
        """Testing parsing CVS bad diff with new file"""
        diff = (b'Index: newfile\n'
                b'==========================================================='
                b'========\n'
                b'RCS file: newfile\n'
                b'diff -N newfile\n'
                b'--- /dev/null\n'
                b'+++ newfile\t26 Jul 2007 10:11:45 -0000\n'
                b'@@ -0,0 +1 @@\n'
                b'+new file content')

        self.assertRaises(DiffParserError,
                          lambda: self.tool.get_parser(diff).parse())

    def test_newfile_diff(self):
        """Testing parsing CVS diff with new file"""
        diff = (b'Index: newfile\n'
                b'==========================================================='
                b'========\n'
                b'RCS file: newfile\n'
                b'diff -N newfile\n'
                b'--- /dev/null\t1 Jan 1970 00:00:00 -0000\n'
                b'+++ newfile\t26 Jul 2007 10:11:45 -0000\n'
                b'@@ -0,0 +1 @@\n'
                b'+new file content\n')

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, 'newfile')
        self.assertEqual(file.origInfo, 'PRE-CREATION')
        self.assertEqual(file.newFile, 'newfile')
        self.assertEqual(file.newInfo, '26 Jul 2007 10:11:45 -0000')
        self.assertEqual(file.data, diff)
        self.assertEqual(file.insert_count, 1)
        self.assertEqual(file.delete_count, 0)

    def test_inter_revision_diff(self):
        """Testing parsing CVS inter-revision diff"""
        diff = (b'Index: testfile\n'
                b'==========================================================='
                b'========\n'
                b'RCS file: %s/test/testfile,v\n'
                b'retrieving revision 1.1\n'
                b'retrieving revision 1.2\n'
                b'diff -u -p -r1.1 -r1.2\n'
                b'--- testfile    26 Jul 2007 08:50:30 -0000      1.1\n'
                b'+++ testfile    27 Sep 2007 22:57:16 -0000      1.2\n'
                b'@@ -1 +1,2 @@\n'
                b'-test content\n'
                b'+updated test content\n'
                b'+added info\n')
        diff = diff % self.cvs_repo_path

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, 'test/testfile')
        self.assertEqual(file.origInfo, '26 Jul 2007 08:50:30 -0000      1.1')
        self.assertEqual(file.newFile, 'test/testfile')
        self.assertEqual(file.newInfo, '27 Sep 2007 22:57:16 -0000      1.2')
        self.assertEqual(file.data, diff)
        self.assertEqual(file.insert_count, 2)
        self.assertEqual(file.delete_count, 1)

    def test_unicode_diff(self):
        """Testing parsing CVS diff with unicode filenames"""
        diff = ('Index: téstfile\n'
                '==========================================================='
                '========\n'
                'RCS file: %s/test/téstfile,v\n'
                'retrieving revision 1.1.1.1\n'
                'diff -u -r1.1.1.1 téstfile\n'
                '--- téstfile    26 Jul 2007 08:50:30 -0000      1.1.1.1\n'
                '+++ téstfile    26 Jul 2007 10:20:20 -0000\n'
                '@@ -1 +1,2 @@\n'
                '-tést content\n'
                '+updated test content\n'
                '+added info\n')
        diff = diff % self.cvs_repo_path
        diff = diff.encode('utf-8')

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, 'test/téstfile')
        self.assertEqual(file.origInfo,
                         '26 Jul 2007 08:50:30 -0000      1.1.1.1')
        self.assertEqual(file.newFile, 'test/téstfile')
        self.assertEqual(file.newInfo, '26 Jul 2007 10:20:20 -0000')
        self.assertEqual(file.data, diff)
        self.assertEqual(file.insert_count, 2)
        self.assertEqual(file.delete_count, 1)

    def test_keyword_diff(self):
        """Testing parsing CVS diff with keywords"""
        diff = self.tool.normalize_patch(
            b'Index: Makefile\n'
            b'==========================================================='
            b'========\n'
            b'RCS file: /cvsroot/src/Makefile,v\n'
            b'retrieving revision 1.1\n'
            b'retrieving revision 1.2\n'
            b'diff -u -r1.1.1.1 Makefile\n'
            b'--- Makefile    26 Jul 2007 08:50:30 -0000      1.1\n'
            b'+++ Makefile    26 Jul 2007 10:20:20 -0000      1.2\n'
            b'@@ -1,6 +1,7 @@\n'
            b' # $Author: bob $\n'
            b' # $Date: 2014/12/18 13:09:42 $\n'
            b' # $Header: /src/Makefile,v 1.2 2014/12/18 '
            b'13:09:42 bob Exp $\n'
            b' # $Id: Makefile,v 1.2 2014/12/18 13:09:42 bob Exp $\n'
            b' # $Locker: bob $\n'
            b' # $Name: some_name $\n'
            b' # $RCSfile: Makefile,v $\n'
            b' # $Revision: 1.2 $\n'
            b' # $Source: /src/Makefile,v $\n'
            b' # $State: Exp $\n'
            b'+# foo\n'
            b' include ../tools/Makefile.base-vars\n'
            b' NAME = misc-docs\n'
            b' OUTNAME = cvs-misc-docs\n',
            'Makefile')

        self.assertEqual(
            diff,
            b'Index: Makefile\n'
            b'==========================================================='
            b'========\n'
            b'RCS file: /cvsroot/src/Makefile,v\n'
            b'retrieving revision 1.1\n'
            b'retrieving revision 1.2\n'
            b'diff -u -r1.1.1.1 Makefile\n'
            b'--- Makefile    26 Jul 2007 08:50:30 -0000      1.1\n'
            b'+++ Makefile    26 Jul 2007 10:20:20 -0000      1.2\n'
            b'@@ -1,6 +1,7 @@\n'
            b' # $Author$\n'
            b' # $Date$\n'
            b' # $Header$\n'
            b' # $Id$\n'
            b' # $Locker$\n'
            b' # $Name$\n'
            b' # $RCSfile$\n'
            b' # $Revision$\n'
            b' # $Source$\n'
            b' # $State$\n'
            b'+# foo\n'
            b' include ../tools/Makefile.base-vars\n'
            b' NAME = misc-docs\n'
            b' OUTNAME = cvs-misc-docs\n')

    def test_keyword_diff_unicode(self):
        """Testing parsing CVS diff with keywords and unicode characters"""
        # Test bug 3931: this should succeed without a UnicodeDecodeError
        self.tool.normalize_patch(
            b'Index: Makefile\n'
            b'==========================================================='
            b'========\n'
            b'RCS file: /cvsroot/src/Makefile,v\n'
            b'retrieving revision 1.1\n'
            b'retrieving revision 1.2\n'
            b'diff -u -r1.1.1.1 Makefile\n'
            b'--- Makefile    26 Jul 2007 08:50:30 -0000      1.1\n'
            b'+++ Makefile    26 Jul 2007 10:20:20 -0000      1.2\n'
            b'@@ -1,6 +1,7 @@\n'
            b' # $Author: bob $\n'
            b' # $Date: 2014/12/18 13:09:42 $\n'
            b' # $Header: /src/Makefile,v 1.2 2014/12/18 '
            b'13:09:42 bob Exp $\n'
            b' # $Id: Makefile,v 1.2 2014/12/18 13:09:42 bob Exp $\n'
            b' # $Locker: bob $\n'
            b' # $Name: some_name $\n'
            b' # $RCSfile: Makefile,v $\n'
            b' # $Revision: 1.2 $\n'
            b' # $Source: /src/Makefile,v $\n'
            b' # $State: Exp $\n'
            b'+# foo \xf0\x9f\x92\xa9\n'
            b' include ../tools/Makefile.base-vars\n'
            b' NAME = misc-docs\n'
            b' OUTNAME = cvs-misc-docs\n',
            'Makefile')

    def test_binary_diff(self):
        """Testing parsing CVS binary diff"""
        diff = (
            b'Index: testfile\n'
            b'==============================================================='
            b'====\n'
            b'RCS file: %s/test/testfile,v\n'
            b'retrieving revision 1.1.1.1\n'
            b'diff -u -r1.1.1.1 testfile\n'
            b'Binary files testfile and testfile differ\n'
            % self.cvs_repo_path)

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, 'test/testfile')
        self.assertEqual(file.origInfo, '')
        self.assertEqual(file.newFile, 'test/testfile')
        self.assertEqual(file.newInfo, '')
        self.assertTrue(file.binary)
        self.assertEqual(file.data, diff)

    def test_binary_diff_new_file(self):
        """Testing parsing CVS binary diff with new file"""
        diff = (
            b'Index: test/testfile\n'
            b'==============================================================='
            b'====\n'
            b'RCS file: test/testfile,v\n'
            b'diff -N test/testfile\n'
            b'Binary files /dev/null and testfile differ\n')

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, 'test/testfile')
        self.assertEqual(file.origInfo, 'PRE-CREATION')
        self.assertEqual(file.newFile, 'test/testfile')
        self.assertEqual(file.newInfo, '')
        self.assertTrue(file.binary)
        self.assertEqual(file.data, diff)

    def test_bad_root(self):
        """Testing CVSTool with a bad CVSROOT"""
        file = 'test/testfile'
        rev = Revision('1.1')
        badrepo = Repository(name='CVS',
                             path=self.cvs_repo_path + '2',
                             tool=Tool.objects.get(name='CVS'))
        badtool = badrepo.get_scmtool()

        self.assertRaises(SCMError, lambda: badtool.get_file(file, rev))

    def test_ssh(self):
        """Testing a SSH-backed CVS repository"""
        self._test_ssh(self.cvs_ssh_path, 'CVSROOT/modules')

    def test_ssh_with_site(self):
        """Testing a SSH-backed CVS repository with a LocalSite"""
        self._test_ssh_with_site(self.cvs_ssh_path, 'CVSROOT/modules')

    def _test_build_cvsroot(self, repo_path, expected_cvsroot, expected_path,
                            expected_error=None, username=None, password=None):
        if expected_error:
            with self.assertRaisesMessage(ValidationError, expected_error):
                self.tool.build_cvsroot(repo_path, username, password,
                                        validate=True)

        cvsroot, norm_path = self.tool.build_cvsroot(repo_path, username,
                                                     password, validate=False)

        self.assertEqual(cvsroot, expected_cvsroot)
        self.assertEqual(norm_path, expected_path)
Ejemplo n.º 36
0
class PerforceTests(BasePerforceTestCase):
    """Unit tests for Perforce.

    This uses the open server at public.perforce.com to test various
    pieces. Because we have no control over things like pending
    changesets, not everything can be tested.
    """

    fixtures = ['test_scmtools']

    def setUp(self):
        super(PerforceTests, self).setUp()

        self.repository = Repository(name='Perforce.com',
                                     path='public.perforce.com:1666',
                                     username='******',
                                     encoding='none',
                                     tool=Tool.objects.get(name='Perforce'))
        self.tool = self.repository.get_scmtool()

    def tearDown(self):
        super(PerforceTests, self).tearDown()

        shutil.rmtree(os.path.join(settings.SITE_DATA_DIR, 'p4'),
                      ignore_errors=True)

    def test_init_with_p4_client(self):
        """Testing PerforceTool.__init__ with p4_client"""
        self.repository.extra_data['p4_client'] = 'test-client'

        tool = PerforceTool(self.repository)
        self.assertIsInstance(tool.client.client_name, six.text_type)
        self.assertEqual(tool.client.client_name, 'test-client')

    def test_init_with_p4_client_none(self):
        """Testing PerforceTool.__init__ with p4_client=None"""
        self.repository.extra_data['p4_client'] = None

        tool = PerforceTool(self.repository)
        self.assertIsNone(tool.client.client_name)

    def test_init_without_p4_client(self):
        """Testing PerforceTool.__init__ without p4_client"""
        self.assertIsNone(self.tool.client.client_name)

    def test_init_with_p4_host(self):
        """Testing PerforceTool.__init__ with p4_host"""
        self.repository.extra_data['p4_host'] = 'test-host'

        tool = PerforceTool(self.repository)
        self.assertIsInstance(tool.client.p4host, six.text_type)
        self.assertEqual(tool.client.p4host, 'test-host')

    def test_init_with_p4_host_none(self):
        """Testing PerforceTool.__init__ with p4_host=None"""
        self.repository.extra_data['p4_host'] = None

        tool = PerforceTool(self.repository)
        self.assertIsNone(tool.client.p4host)

    def test_init_without_p4_host(self):
        """Testing PerforceTool.__init__ without p4_host"""
        self.assertIsNone(self.tool.client.p4host)

    def test_connect_sets_required_client_args(self):
        """Testing PerforceTool.connect sets required client args"""
        self.repository.username = '******'
        self.repository.password = '******'
        self.repository.encoding = 'utf8'
        self.repository.extra_data['use_ticket_auth'] = False

        tool = PerforceTool(self.repository)
        p4 = DummyP4()
        client = tool.client
        client.p4 = p4

        # Note that P4 will use the native string type on each major version
        # of Python. We want to sanity-check that here.
        with client.connect():
            self.assertEqual(p4.exception_level, 1)

            self.assertIsInstance(p4.user, str)
            self.assertEqual(p4.user, 'test-user')

            self.assertIsInstance(p4.password, str)
            self.assertEqual(p4.password, 'test-pass')

            self.assertIsInstance(p4.charset, str)
            self.assertEqual(p4.charset, 'utf8')

            self.assertIsInstance(p4.port, str)
            self.assertEqual(p4.port, 'public.perforce.com:1666')

            # Perforce will set a default for the host and client. They'll
            # be the same. We don't care what they are, just that they're
            # equal and of the right string type, and not "none".
            self.assertIsInstance(p4.host, str)
            self.assertIsInstance(p4.client, str)
            self.assertEqual(p4.host.split('.')[0], p4.client)
            self.assertNotEqual(p4.client.lower(), 'none')

            # Perforce will set the ticket file to be in the user's home
            # directory. We don't care about the exact contents, and will
            # just look at the filename.
            self.assertIsInstance(p4.ticket_file, str)
            self.assertTrue(p4.ticket_file.endswith('.p4tickets'))

    def test_connect_sets_optional_client_args(self):
        """Testing PerforceTool.connect sets optional client args"""
        self.repository.extra_data.update({
            'use_ticket_auth': True,
            'p4_client': 'test-client',
            'p4_host': 'test-host',
        })

        tool = PerforceTool(self.repository)
        p4 = DummyP4()
        client = tool.client
        client.p4 = p4

        self.spy_on(client.check_refresh_ticket, call_original=False)

        # Note that P4 will use the native string type on each major version
        # of Python. We want to sanity-check that here.
        with client.connect():
            self.assertIsInstance(p4.client, str)
            self.assertEqual(p4.client, 'test-client')

            self.assertIsInstance(p4.host, str)
            self.assertEqual(p4.host, 'test-host')

            self.assertIsInstance(p4.ticket_file, str)
            self.assertTrue(p4.ticket_file.endswith(
                os.path.join('data', 'p4', 'p4tickets')))

    @online_only
    def test_changeset(self):
        """Testing PerforceTool.get_changeset"""
        desc = self.tool.get_changeset(157)
        self.assertEqual(desc.changenum, 157)
        self.assertEqual(type(desc.description), six.text_type)
        self.assertEqual(md5(desc.description.encode('utf-8')).hexdigest(),
                         'b7eff0ca252347cc9b09714d07397e64')

        expected_files = [
            '//public/perforce/api/python/P4Client/P4Clientmodule.cc',
            '//public/perforce/api/python/P4Client/p4.py',
            '//public/perforce/api/python/P4Client/review.py',
            '//public/perforce/python/P4Client/P4Clientmodule.cc',
            '//public/perforce/python/P4Client/p4.py',
            '//public/perforce/python/P4Client/review.py',
        ]

        for file, expected in zip_longest(desc.files, expected_files):
            self.assertEqual(file, expected)

        self.assertEqual(md5(desc.summary.encode('utf-8')).hexdigest(),
                         '99a335676b0e5821ffb2f7469d4d7019')

    @online_only
    def test_encoding(self):
        """Testing PerforceTool.get_changeset with a specified encoding"""
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          username='******',
                          tool=Tool.objects.get(name='Perforce'),
                          encoding='utf8')
        tool = repo.get_scmtool()

        try:
            tool.get_changeset(157)
            self.fail('Expected an error about unicode-enabled servers. Did '
                      'perforce.com turn on unicode for public.perforce.com?')
        except SCMError as e:
            # public.perforce.com doesn't have unicode enabled. Getting this
            # error means we at least passed the charset through correctly
            # to the p4 client.
            self.assertTrue('clients require a unicode enabled server' in
                            six.text_type(e))

    @online_only
    def test_changeset_broken(self):
        """Testing PerforceTool.get_changeset error conditions"""
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          username='******',
                          password='******',
                          encoding='none')
        tool = repo.get_scmtool()

        self.assertRaises(AuthenticationError,
                          lambda: tool.get_changeset(157))

        repo = Repository(name='localhost:1',
                          path='localhost:1',
                          tool=Tool.objects.get(name='Perforce'))

        tool = repo.get_scmtool()
        self.assertRaises(RepositoryNotFoundError,
                          lambda: tool.get_changeset(1))

    @online_only
    def test_get_file(self):
        """Testing PerforceTool.get_file"""
        tool = self.tool

        content = tool.get_file('//depot/foo', PRE_CREATION)
        self.assertIsInstance(content, bytes)
        self.assertEqual(content, b'')

        content = tool.get_file('//public/perforce/api/python/P4Client/p4.py',
                                1)
        self.assertIsInstance(content, bytes)
        self.assertEqual(md5(content).hexdigest(),
                         '227bdd87b052fcad9369e65c7bf23fd0')

    @online_only
    def test_file_exists(self):
        """Testing PerforceTool.file_exists"""
        self.assertTrue(self.tool.file_exists(
            '//public/perforce/api/python/P4Client/p4.py', '1'))

        self.assertFalse(self.tool.file_exists(
            '//public/perforce/xxx-non-existent', '1'))

    @online_only
    def test_file_exists_with_pre_creation(self):
        """Testing PerforceTool.file_exists"""
        self.assertFalse(self.tool.file_exists('//depot/xxx-new-file',
                                               PRE_CREATION))

    @online_only
    def test_custom_host(self):
        """Testing Perforce client initialization with a custom P4HOST"""
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          username='******',
                          tool=Tool.objects.get(name='Perforce'),
                          encoding='utf8')
        repo.extra_data['p4_host'] = 'my-custom-host'

        tool = repo.get_scmtool()

        with tool.client.connect():
            self.assertEqual(tool.client.p4.host, 'my-custom-host')

    def test_ticket_login(self):
        """Testing Perforce with ticket-based logins"""
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          username='******',
                          password='******')
        repo.extra_data = {
            'use_ticket_auth': True,
        }

        client = repo.get_scmtool().client
        self.assertTrue(client.use_ticket_auth)

        self.spy_on(client.get_ticket_status, call_fake=lambda *args: {
            'user': '******',
            'expiration_secs': 100000,
        })

        self.spy_on(client.login, call_original=False)

        self.assertFalse(os.path.exists(os.path.join(
            settings.SITE_DATA_DIR, 'p4', 'p4tickets')))

        with client.connect():
            self.assertFalse(client.login.called)
            self.assertEqual(client.p4.ticket_file,
                             os.path.join(settings.SITE_DATA_DIR, 'p4',
                                          'p4tickets'))

    def test_ticket_login_with_expiring_ticket(self):
        """Testing Perforce with ticket-based logins with ticket close to
        expiring
        """
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          username='******',
                          password='******')
        repo.extra_data = {
            'use_ticket_auth': True,
        }

        client = repo.get_scmtool().client
        self.assertTrue(client.use_ticket_auth)

        self.spy_on(client.get_ticket_status, call_fake=lambda *args: {
            'user': '******',
            'expiration_secs': 99,
        })

        self.spy_on(client.login, call_original=False)

        with client.connect():
            self.assertIsNotNone(client.p4.ticket_file)
            self.assertTrue(client.login.called)
            self.assertEqual(client.p4.ticket_file,
                             os.path.join(settings.SITE_DATA_DIR, 'p4',
                                          'p4tickets'))

    def test_ticket_login_with_no_valid_ticket(self):
        """Testing Perforce with ticket-based logins without a valid ticket
        """
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          username='******',
                          password='******')
        repo.extra_data = {
            'use_ticket_auth': True,
        }

        client = repo.get_scmtool().client
        self.assertTrue(client.use_ticket_auth)

        self.spy_on(client.get_ticket_status, call_fake=lambda *args: None)
        self.spy_on(client.login, call_original=False)

        with client.connect():
            self.assertTrue(client.login.called)
            self.assertEqual(client.p4.ticket_file,
                             os.path.join(settings.SITE_DATA_DIR, 'p4',
                                          'p4tickets'))

    def test_ticket_login_with_different_user(self):
        """Testing Perforce with ticket-based logins with ticket for a
        different user
        """
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          username='******',
                          password='******')
        repo.extra_data = {
            'use_ticket_auth': True,
        }

        client = repo.get_scmtool().client
        self.assertTrue(client.use_ticket_auth)

        self.spy_on(client.get_ticket_status, call_fake=lambda *args: {
            'user': '******',
            'expiration_secs': 100000,
        })

        self.spy_on(client.login, call_original=False)

        with client.connect():
            self.assertTrue(client.login.called)
            self.assertEqual(client.p4.ticket_file,
                             os.path.join(settings.SITE_DATA_DIR, 'p4',
                                          'p4tickets'))

    @add_fixtures(['test_site'])
    def test_ticket_login_with_local_site(self):
        """Testing Perforce with ticket-based logins with Local Sites"""
        repo = Repository(
            name='Perforce.com',
            path='public.perforce.com:1666',
            tool=Tool.objects.get(name='Perforce'),
            username='******',
            password='******',
            local_site=LocalSite.objects.get(name='local-site-1'))
        repo.extra_data = {
            'use_ticket_auth': True,
        }

        client = repo.get_scmtool().client
        self.assertTrue(client.use_ticket_auth)

        self.spy_on(client.get_ticket_status, call_fake=lambda *args: {
            'user': '******',
            'expiration_secs': 100000,
        })

        self.spy_on(client.login, call_original=False)

        with client.connect():
            self.assertFalse(client.login.called)
            self.assertEqual(client.p4.ticket_file,
                             os.path.join(settings.SITE_DATA_DIR, 'p4',
                                          'local-site-1', 'p4tickets'))

    @online_only
    def test_parse_diff_revision_with_revision_eq_0(self):
        """Testing Perforce.parse_diff_revision with revision == 0"""
        self.assertEqual(
            self.tool.parse_diff_revision(
                filename=b'xxx-foo.py',
                revision=b'//public/perforce/xxx-foo.py#0'),
            (b'//public/perforce/xxx-foo.py', PRE_CREATION))

    @online_only
    def test_parse_diff_revision_with_revision_eq_1_and_existing(self):
        """Testing Perforce.parse_diff_revision with revision == 1 and existing
        file
        """
        self.assertEqual(
            self.tool.parse_diff_revision(
                filename=b'p4.p',
                revision=b'//public/perforce/api/python/P4Client/p4.py#1'),
            (b'//public/perforce/api/python/P4Client/p4.py', b'1'))

    @online_only
    def test_parse_diff_revision_with_revision_eq_1_and_new(self):
        """Testing Perforce.parse_diff_revision with revision == 1 and new file
        """
        self.assertEqual(
            self.tool.parse_diff_revision(
                filename=b'xxx-newfile',
                revision=b'//public/perforce/xxx-newfile#1'),
            (b'//public/perforce/xxx-newfile', PRE_CREATION))

    @online_only
    def test_parse_diff_revision_with_revision_gt_1(self):
        """Testing Perforce.parse_diff_revision with revision > 1"""
        self.assertEqual(
            self.tool.parse_diff_revision(
                filename=b'xxx-foo.py',
                revision=b'//public/perforce/xxx-foo.py#2'),
            (b'//public/perforce/xxx-foo.py', b'2'))

    def test_empty_diff(self):
        """Testing Perforce empty diff parsing"""
        diff = b'==== //depot/foo/proj/README#2 ==M== /src/proj/README ====\n'

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.orig_filename, b'//depot/foo/proj/README')
        self.assertEqual(file.orig_file_details, b'//depot/foo/proj/README#2')
        self.assertEqual(file.modified_filename, b'/src/proj/README')
        self.assertEqual(file.modified_file_details, b'')
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertFalse(file.moved)
        self.assertEqual(file.data, diff)
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_binary_diff(self):
        """Testing Perforce binary diff parsing"""
        diff = (b'==== //depot/foo/proj/test.png#1 ==A== /src/proj/test.png '
                b'====\nBinary files /tmp/foo and /src/proj/test.png differ\n')

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.orig_filename, b'//depot/foo/proj/test.png')
        self.assertEqual(file.orig_file_details,
                         b'//depot/foo/proj/test.png#1')
        self.assertEqual(file.modified_filename, b'/src/proj/test.png')
        self.assertEqual(file.modified_file_details, b'')
        self.assertEqual(file.data, diff)
        self.assertTrue(file.binary)
        self.assertFalse(file.deleted)
        self.assertFalse(file.moved)
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_deleted_diff(self):
        """Testing Perforce deleted diff parsing"""
        diff = (b'==== //depot/foo/proj/test.png#1 ==D== /src/proj/test.png '
                b'====\n')

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.orig_filename, b'//depot/foo/proj/test.png')
        self.assertEqual(file.orig_file_details,
                         b'//depot/foo/proj/test.png#1')
        self.assertEqual(file.modified_filename, b'/src/proj/test.png')
        self.assertEqual(file.modified_file_details, b'')
        self.assertEqual(file.data, diff)
        self.assertFalse(file.binary)
        self.assertTrue(file.deleted)
        self.assertFalse(file.moved)
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_moved_file_diff(self):
        """Testing Perforce moved file diff parsing"""
        diff = (
            b'Moved from: //depot/foo/proj/test.txt\n'
            b'Moved to: //depot/foo/proj/test2.txt\n'
            b'--- //depot/foo/proj/test.txt  //depot/foo/proj/test.txt#2\n'
            b'+++ //depot/foo/proj/test2.txt  01-02-03 04:05:06\n'
            b'@@ -1 +1,2 @@\n'
            b'-test content\n'
            b'+updated test content\n'
            b'+added info\n'
        )

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.orig_filename, b'//depot/foo/proj/test.txt')
        self.assertEqual(file.orig_file_details,
                         b'//depot/foo/proj/test.txt#2')
        self.assertEqual(file.modified_filename, b'//depot/foo/proj/test2.txt')
        self.assertEqual(file.modified_file_details, b'01-02-03 04:05:06')
        self.assertEqual(file.data, diff)
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertTrue(file.moved)
        self.assertEqual(file.data, diff)
        self.assertEqual(file.insert_count, 2)
        self.assertEqual(file.delete_count, 1)

    def test_moved_file_diff_no_changes(self):
        """Testing Perforce moved file diff parsing without changes"""
        diff = (b'==== //depot/foo/proj/test.png#5 ==MV== '
                b'//depot/foo/proj/test2.png ====\n')

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.orig_filename, b'//depot/foo/proj/test.png')
        self.assertEqual(file.orig_file_details,
                         b'//depot/foo/proj/test.png#5')
        self.assertEqual(file.modified_filename, b'//depot/foo/proj/test2.png')
        self.assertEqual(file.modified_file_details, b'')
        self.assertEqual(file.data, diff)
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertTrue(file.moved)
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_empty_and_normal_diffs(self):
        """Testing Perforce empty and normal diff parsing"""
        diff1_text = (b'==== //depot/foo/proj/test.png#1 ==A== '
                      b'/src/proj/test.png ====\n')
        diff2_text = (b'--- test.c  //depot/foo/proj/test.c#2\n'
                      b'+++ test.c  01-02-03 04:05:06\n'
                      b'@@ -1 +1,2 @@\n'
                      b'-test content\n'
                      b'+updated test content\n'
                      b'+added info\n')
        diff = diff1_text + diff2_text

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 2)
        self.assertEqual(files[0].orig_filename, b'//depot/foo/proj/test.png')
        self.assertEqual(files[0].orig_file_details,
                         b'//depot/foo/proj/test.png#1')
        self.assertEqual(files[0].modified_filename, b'/src/proj/test.png')
        self.assertEqual(files[0].modified_file_details, b'')
        self.assertFalse(files[0].binary)
        self.assertFalse(files[0].deleted)
        self.assertFalse(files[0].moved)
        self.assertEqual(files[0].data, diff1_text)
        self.assertEqual(files[0].insert_count, 0)
        self.assertEqual(files[0].delete_count, 0)

        self.assertEqual(files[1].orig_filename, b'test.c')
        self.assertEqual(files[1].orig_file_details,
                         b'//depot/foo/proj/test.c#2')
        self.assertEqual(files[1].modified_filename, b'test.c')
        self.assertEqual(files[1].modified_file_details, b'01-02-03 04:05:06')
        self.assertFalse(files[1].binary)
        self.assertFalse(files[1].deleted)
        self.assertFalse(files[1].moved)
        self.assertEqual(files[1].data, diff2_text)
        self.assertEqual(files[1].insert_count, 2)
        self.assertEqual(files[1].delete_count, 1)

    def test_diff_file_normalization(self):
        """Testing perforce diff filename normalization"""
        parser = self.tool.get_parser(b'')
        self.assertEqual(parser.normalize_diff_filename('//depot/test'),
                         '//depot/test')

    def test_unicode_diff(self):
        """Testing Perforce diff parsing with unicode characters"""
        diff = ('--- tést.c  //depot/foo/proj/tést.c#2\n'
                '+++ tést.c  01-02-03 04:05:06\n'
                '@@ -1 +1,2 @@\n'
                '-tést content\n'
                '+updated test content\n'
                '+added info\n').encode('utf-8')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)
        self.assertEqual(files[0].orig_filename, 'tést.c'.encode('utf-8'))
        self.assertEqual(files[0].orig_file_details,
                         '//depot/foo/proj/tést.c#2'.encode('utf-8'))
        self.assertEqual(files[0].modified_filename, 'tést.c'.encode('utf-8'))
        self.assertEqual(files[0].modified_file_details, b'01-02-03 04:05:06')
        self.assertFalse(files[0].binary)
        self.assertFalse(files[0].deleted)
        self.assertFalse(files[0].moved)
        self.assertEqual(files[0].insert_count, 2)
        self.assertEqual(files[0].delete_count, 1)
Ejemplo n.º 37
0
class MercurialTests(SCMTestCase):
    """Unit tests for mercurial."""

    fixtures = ['test_scmtools']

    def setUp(self):
        super(MercurialTests, self).setUp()

        hg_repo_path = os.path.join(os.path.dirname(__file__),
                                    '..', 'testdata', 'hg_repo')
        self.repository = Repository(name='Test HG',
                                     path=hg_repo_path,
                                     tool=Tool.objects.get(name='Mercurial'))

        try:
            self.tool = self.repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest('Hg is not installed')

    def _first_file_in_diff(self, diff):
        return self.tool.get_parser(diff).parse()[0]

    def test_ssh_disallowed(self):
        """Testing HgTool does not allow SSH URLs"""
        with self.assertRaises(SCMError):
            self.tool.check_repository('ssh://foo')

    def test_git_parser_selection_with_header(self):
        """Testing HgTool returns the git parser when a header is present"""
        diffContents = (b'# HG changeset patch\n'
                        b'# Node ID 6187592a72d7\n'
                        b'# Parent  9d3f4147f294\n'
                        b'diff --git a/emptyfile b/emptyfile\n'
                        b'new file mode 100644\n')

        parser = self.tool.get_parser(diffContents)
        self.assertEqual(type(parser), HgGitDiffParser)

    def test_hg_parser_selection_with_header(self):
        """Testing HgTool returns the hg parser when a header is present"""
        diffContents = (b'# HG changeset patch'
                        b'# Node ID 6187592a72d7\n'
                        b'# Parent  9d3f4147f294\n'
                        b'diff -r 9d3f4147f294 -r 6187592a72d7 new.py\n'
                        b'--- /dev/null   Thu Jan 01 00:00:00 1970 +0000\n'
                        b'+++ b/new.py  Tue Apr 21 12:20:05 2015 -0400\n')

        parser = self.tool.get_parser(diffContents)
        self.assertEqual(type(parser), HgDiffParser)

    def test_git_parser_sets_commit_ids(self):
        """Testing HgGitDiffParser sets the parser commit ids"""
        diffContents = (b'# HG changeset patch\n'
                        b'# Node ID 6187592a72d7\n'
                        b'# Parent  9d3f4147f294\n'
                        b'diff --git a/emptyfile b/emptyfile\n'
                        b'new file mode 100644\n')

        parser = self.tool.get_parser(diffContents)
        parser.parse()
        self.assertEqual(parser.new_commit_id, b'6187592a72d7')
        self.assertEqual(parser.base_commit_id, b'9d3f4147f294')

    def test_patch_creates_new_file(self):
        """Testing HgTool with a patch that creates a new file"""
        self.assertEqual(
            PRE_CREATION,
            self.tool.parse_diff_revision('/dev/null', 'bf544ea505f8')[1])

    def test_diff_parser_new_file(self):
        """Testing HgDiffParser with a diff that creates a new file"""
        diffContents = (b'diff -r bf544ea505f8 readme\n'
                        b'--- /dev/null\n'
                        b'+++ b/readme\n')

        file = self._first_file_in_diff(diffContents)
        self.assertEqual(file.origFile, 'readme')

    def test_diff_parser_with_added_empty_file(self):
        """Testing HgDiffParser with a diff with an added empty file"""
        diff = (b'diff -r 356a6127ef19 -r 4960455a8e88 empty\n'
                b'--- /dev/null\n'
                b'+++ b/empty\n')

        file = self._first_file_in_diff(diff)
        self.assertEqual(file.origInfo, PRE_CREATION)
        self.assertEqual(file.origFile, 'empty')
        self.assertEqual(file.newInfo, '4960455a8e88')
        self.assertEqual(file.newFile, 'empty')
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_diff_parser_with_deleted_empty_file(self):
        """Testing HgDiffParser with a diff with a deleted empty file"""
        diff = (b'diff -r 356a6127ef19 -r 4960455a8e88 empty\n'
                b'--- a/empty\n'
                b'+++ /dev/null\n')

        file = self._first_file_in_diff(diff)
        self.assertEqual(file.origInfo, '356a6127ef19')
        self.assertEqual(file.origFile, 'empty')
        self.assertEqual(file.newInfo, '4960455a8e88')
        self.assertEqual(file.newFile, 'empty')
        self.assertFalse(file.binary)
        self.assertTrue(file.deleted)
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_diff_parser_uncommitted(self):
        """Testing HgDiffParser with a diff with an uncommitted change"""
        diffContents = (b'diff -r bf544ea505f8 readme\n'
                        b'--- a/readme\n'
                        b'+++ b/readme\n')

        file = self._first_file_in_diff(diffContents)
        self.assertEqual(file.origInfo, 'bf544ea505f8')
        self.assertEqual(file.origFile, 'readme')
        self.assertEqual(file.newInfo, 'Uncommitted')
        self.assertEqual(file.newFile, 'readme')

    def test_diff_parser_committed(self):
        """Testing HgDiffParser with a diff between committed revisions"""
        diffContents = (b'diff -r 356a6127ef19 -r 4960455a8e88 readme\n'
                        b'--- a/readme\n'
                        b'+++ b/readme\n')

        file = self._first_file_in_diff(diffContents)
        self.assertEqual(file.origInfo, '356a6127ef19')
        self.assertEqual(file.origFile, 'readme')
        self.assertEqual(file.newInfo, '4960455a8e88')
        self.assertEqual(file.newFile, 'readme')

    def test_diff_parser_with_preamble_junk(self):
        """Testing HgDiffParser with a diff that contains non-diff junk test
        as a preamble
        """
        diffContents = (b'changeset:   60:3613c58ad1d5\n'
                        b'user:        Michael Rowe <*****@*****.**>\n'
                        b'date:        Fri Jul 27 11:44:37 2007 +1000\n'
                        b'files:       readme\n'
                        b'description:\n'
                        b'Update the readme file\n'
                        b'\n'
                        b'\n'
                        b'diff -r 356a6127ef19 -r 4960455a8e88 readme\n'
                        b'--- a/readme\n'
                        b'+++ b/readme\n')

        file = self._first_file_in_diff(diffContents)
        self.assertEqual(file.origInfo, '356a6127ef19')
        self.assertEqual(file.origFile, 'readme')
        self.assertEqual(file.newInfo, '4960455a8e88')
        self.assertEqual(file.newFile, 'readme')

    def test_git_diff_parsing(self):
        """Testing HgDiffParser git diff support"""
        diffContents = (b'# Node ID 4960455a8e88\n'
                        b'# Parent bf544ea505f8\n'
                        b'diff --git a/path/to file/readme.txt '
                        b'b/new/path to/readme.txt\n'
                        b'rename from path/to file/readme.txt\n'
                        b'rename to new/path to/readme.txt\n'
                        b'--- a/path/to file/readme.txt\n'
                        b'+++ b/new/path to/readme.txt\n')

        file = self._first_file_in_diff(diffContents)
        self.assertEqual(file.origInfo, 'bf544ea505f8')
        self.assertEqual(file.origFile, 'path/to file/readme.txt')
        self.assertEqual(file.newInfo, '4960455a8e88')
        self.assertEqual(file.newFile, 'new/path to/readme.txt')

    def test_diff_parser_unicode(self):
        """Testing HgDiffParser with unicode characters"""

        diffContents = ('diff -r bf544ea505f8 réadme\n'
                        '--- a/réadme\n'
                        '+++ b/réadme\n').encode('utf-8')

        file = self._first_file_in_diff(diffContents)
        self.assertEqual(file.origInfo, 'bf544ea505f8')
        self.assertEqual(file.origFile, 'réadme')
        self.assertEqual(file.newInfo, 'Uncommitted')
        self.assertEqual(file.newFile, 'réadme')

    def test_git_diff_parsing_unicode(self):
        """Testing HgDiffParser git diff with unicode characters"""
        diffContents = ('# Node ID 4960455a8e88\n'
                        '# Parent bf544ea505f8\n'
                        'diff --git a/path/to file/réadme.txt '
                        'b/new/path to/réadme.txt\n'
                        'rename from path/to file/réadme.txt\n'
                        'rename to new/path to/réadme.txt\n'
                        '--- a/path/to file/réadme.txt\n'
                        '+++ b/new/path to/réadme.txt\n').encode('utf-8')

        file = self._first_file_in_diff(diffContents)
        self.assertEqual(file.origInfo, 'bf544ea505f8')
        self.assertEqual(file.origFile, 'path/to file/réadme.txt')
        self.assertEqual(file.newInfo, '4960455a8e88')
        self.assertEqual(file.newFile, 'new/path to/réadme.txt')

    def test_revision_parsing(self):
        """Testing HgDiffParser revision number parsing"""
        self.assertEqual(
            self.tool.parse_diff_revision('doc/readme', 'bf544ea505f8'),
            ('doc/readme', 'bf544ea505f8'))

        self.assertEqual(
            self.tool.parse_diff_revision('/dev/null', 'bf544ea505f8'),
            ('/dev/null', PRE_CREATION))

        # TODO think of a meaningful thing to test here...
        # self.assertRaises(SCMException,
        #                  lambda: self.tool.parse_diff_revision('', 'hello'))

    def test_get_branches(self):
        """Testing list of branches in HgClient.get_change"""
        value = self.tool.get_branches()
        self.assertTrue(isinstance(value, list))
        self.assertEqual(len(value), 1)

        self.assertEqual(value[0].id, 'default')
        self.assertEqual(value[0].commit,
                         '661e5dd3c4938ecbe8f77e2fdfa905d70485f94c')
        self.assertEqual(value[0].default, True)

    def test_get_change(self):
        """Testing raw diff of HgClient.get_change"""
        self.assertRaises(SCMError, lambda: self.tool.get_change('dummy'))

        value = self.tool.get_change('0')
        self.assertNotIn('goodbye', value.diff)
        self.assertEqual(value.id, 'f814b6e226d2ba6d26d02ca8edbff91f57ab2786')
        value = self.tool.get_change('1')
        self.assertIn('goodbye', value.diff)
        self.assertEqual(value.id, '661e5dd3c4938ecbe8f77e2fdfa905d70485f94c')

    def test_get_commits(self):
        """Testing commit objects in HgClient.get_commits"""
        value = self.tool.get_commits()
        self.assertTrue(isinstance(value, list))
        self.assertEqual(len(value), 2)

        self.assertEqual(value[0].id,
                         '661e5dd3c4938ecbe8f77e2fdfa905d70485f94c')
        self.assertEqual(value[0].message, 'second')
        self.assertEqual(value[0].author_name,
                         'Michael Rowe <*****@*****.**>')
        self.assertEqual(value[0].date, '2007-08-07T17:12:23')
        self.assertEqual(value[0].parent,
                         'f814b6e226d2ba6d26d02ca8edbff91f57ab2786')
        self.assertEqual(value[0].base_commit_id,
                         'f814b6e226d2ba6d26d02ca8edbff91f57ab2786')

        self.assertEqual(value[1].id,
                         'f814b6e226d2ba6d26d02ca8edbff91f57ab2786')
        self.assertEqual(value[1].message, 'first')
        self.assertEqual(value[1].author_name,
                         'Michael Rowe <*****@*****.**>')
        self.assertEqual(value[1].date, '2007-08-07T17:11:57')
        self.assertEqual(value[1].parent,
                         '0000000000000000000000000000000000000000')
        self.assertEqual(value[1].base_commit_id,
                         '0000000000000000000000000000000000000000')

        self.assertRaisesRegexp(SCMError, 'Cannot load commits: ',
                                lambda: self.tool.get_commits(branch='x'))

        rev = 'f814b6e226d2ba6d26d02ca8edbff91f57ab2786'
        value = self.tool.get_commits(start=rev)
        self.assertTrue(isinstance(value, list))
        self.assertEqual(len(value), 1)

    def test_get_file(self):
        """Testing HgTool.get_file"""
        rev = Revision('661e5dd3c493')
        file = 'doc/readme'

        value = self.tool.get_file(file, rev)
        self.assertTrue(isinstance(value, bytes))
        self.assertEqual(value, b'Hello\n\ngoodbye\n')

        self.assertTrue(self.tool.file_exists('doc/readme', rev))
        self.assertTrue(not self.tool.file_exists('doc/readme2', rev))

        self.assertRaises(FileNotFoundError, lambda: self.tool.get_file(''))

        self.assertRaises(FileNotFoundError,
                          lambda: self.tool.get_file('hello', PRE_CREATION))

    def test_get_file_base_commit_id_override(self):
        """Testing base_commit_id overrides revision in HgTool.get_file"""
        base_commit_id = Revision('661e5dd3c493')
        bogus_rev = Revision('bogusrevision')
        file = 'doc/readme'

        value = self.tool.get_file(file, bogus_rev,
                                   base_commit_id=base_commit_id)
        self.assertTrue(isinstance(value, bytes))
        self.assertEqual(value, b'Hello\n\ngoodbye\n')

        self.assertTrue(self.tool.file_exists(
            'doc/readme',
            bogus_rev,
            base_commit_id=base_commit_id))
        self.assertTrue(not self.tool.file_exists(
            'doc/readme2',
            bogus_rev,
            base_commit_id=base_commit_id))

    def test_interface(self):
        """Testing basic HgTool API"""
        self.assertTrue(self.tool.diffs_use_absolute_paths)

        self.assertRaises(NotImplementedError,
                          lambda: self.tool.get_changeset(1))

    @online_only
    def test_https_repo(self):
        """Testing HgTool.file_exists with an HTTPS-based repository"""
        repo = Repository(name='Test HG2',
                          path='https://bitbucket.org/pypy/pypy',
                          tool=Tool.objects.get(name='Mercurial'))
        tool = repo.get_scmtool()

        rev = Revision('877cf1960916')

        self.assertTrue(tool.file_exists('TODO.rst', rev))
        self.assertTrue(not tool.file_exists('TODO.rstNotFound', rev))
Ejemplo n.º 38
0
class BZRTests(SCMTestCase):
    """Unit tests for bzr."""

    fixtures = ['test_scmtools']

    def setUp(self):
        super(BZRTests, self).setUp()

        if not is_exe_in_path('bzr'):
            raise nose.SkipTest()

        self.bzr_repo_path = os.path.join(os.path.dirname(__file__),
                                          '..', 'testdata', 'bzr_repo')
        self.bzr_ssh_path = ('bzr+ssh://localhost/%s'
                             % self.bzr_repo_path.replace('\\', '/'))
        self.bzr_sftp_path = ('sftp://localhost/%s'
                              % self.bzr_repo_path.replace('\\', '/'))
        self.repository = Repository(name='Bazaar',
                                     path='file://' + self.bzr_repo_path,
                                     tool=Tool.objects.get(name='Bazaar'))

        self.tool = self.repository.get_scmtool()

    def test_check_repository(self):
        """Testing BZRTool.check_repository"""
        self.tool.check_repository(self.repository.path)

    def test_check_repository_with_not_found(self):
        """Testing BZRTool.check_repository with repository not found"""
        with self.assertRaises(RepositoryNotFoundError):
            self.tool.check_repository('file:///dummy')

    def test_ssh(self):
        """Testing BZRTool with a SSH-backed repository"""
        self._test_ssh(self.bzr_ssh_path, 'README')

    def test_ssh_with_site(self):
        """Testing BZRTool with a SSH-backed repository with a LocalSite"""
        self._test_ssh_with_site(self.bzr_ssh_path, 'README')

    def test_sftp(self):
        """Testing BZRTool with a SFTP-backed repository"""
        try:
            self._test_ssh(self.bzr_sftp_path, 'README')
        except SCMError as e:
            err = six.text_type(e)

            if 'Installed bzr and paramiko modules are incompatible' in err:
                raise nose.SkipTest(err)

            raise

    def test_get_file(self):
        """Testing BZRTool.get_file"""
        content = self.tool.get_file('README', '2011-02-02 10:53:04 +0000')
        self.assertEqual(content, b'This is a test.\n')
        self.assertIsInstance(content, bytes)

    def test_get_file_with_timezone_offset(self):
        """Testing BZRTool.get_file with timezone offset"""
        content = self.tool.get_file('README', '2011-02-02 02:53:04 -0800')
        self.assertEqual(content, b'This is a test.\n')
        self.assertIsInstance(content, bytes)

    def test_get_file_with_revision_id(self):
        """Testing BZRTool.get_file with revision ID"""
        content = self.tool.get_file(
            'README',
            'revid:[email protected]')
        self.assertEqual(content, b'This is a test.\n')
        self.assertIsInstance(content, bytes)

    def test_get_file_with_unknown_file(self):
        """Testing BZRTool.get_file with unknown file"""
        with self.assertRaises(FileNotFoundError):
            self.tool.get_file('NOT_REAL', '2011-02-02 02:53:04 -0800')

    def test_get_file_with_unknown_revision(self):
        """Testing BZRTool.get_file with unknown revision"""
        with self.assertRaises(FileNotFoundError):
            self.tool.get_file('README', '9999-02-02 02:53:04 -0800')

    def test_get_file_with_invalid_revision(self):
        """Testing BZRTool.get_file with invalid revision"""
        with self.assertRaises(InvalidRevisionFormatError):
            self.tool.get_file('README', '\o/')

    def test_file_exists(self):
        """Testing BZRTool.get_files_exists"""
        self.assertTrue(self.tool.file_exists(
            'README',
            '2011-02-02 10:53:04 +0000'))

        self.assertFalse(self.tool.file_exists(
            'NOT_REAL',
            '2011-02-02 10:53:04 +0000'))
        self.assertFalse(self.tool.file_exists(
            'README',
            '9999-02-02 10:53:04 +0000'))

    def test_file_exists_with_timezone_offset(self):
        """Testing BZRTool.get_files_exists with timezone offset"""
        self.assertTrue(self.tool.file_exists(
            'README',
            '2011-02-02 02:53:04 -0800'))

    def test_file_exists_with_revision_id(self):
        """Testing BZRTool.files_exists with revision ID"""
        self.assertTrue(self.tool.file_exists(
            'README',
            'revid:[email protected]'))

    def test_file_exists_with_invalid_revision(self):
        """Testing BZRTool.files_exists with invalid revision"""
        with self.assertRaises(InvalidRevisionFormatError):
            self.tool.file_exists('README', '\o/')
Ejemplo n.º 39
0
class MercurialTests(DjangoTestCase):
    """Unit tests for mercurial."""

    fixtures = ["hg.json", "test_scmtools.json"]

    def setUp(self):
        hg_repo_path = os.path.join(os.path.dirname(__file__), "testdata/hg_repo.bundle")
        self.repository = Repository(name="Test HG", path=hg_repo_path, tool=Tool.objects.get(name="Mercurial"))

        try:
            self.tool = self.repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest("Hg is not installed")

    def _firstFileInDiff(self, diff):
        return self.tool.get_parser(diff).parse()[0]

    def testPatchCreatesNewFile(self):
        """Testing HgTool with a patch that creates a new file"""

        self.assertEqual(PRE_CREATION, self.tool.parse_diff_revision("/dev/null", "bf544ea505f8")[1])

    def testDiffParserNewFile(self):
        """Testing HgDiffParser with a diff that creates a new file"""

        diffContents = "diff -r bf544ea505f8 readme\n" + "--- /dev/null\n" + "+++ b/readme\n"

        file = self._firstFileInDiff(diffContents)
        self.assertEqual(file.origFile, "readme")

    def testDiffParserUncommitted(self):
        """Testing HgDiffParser with a diff with an uncommitted change"""

        diffContents = "diff -r bf544ea505f8 readme\n" + "--- a/readme\n" + "+++ b/readme\n"

        file = self._firstFileInDiff(diffContents)
        self.assertEqual(file.origInfo, "bf544ea505f8")
        self.assertEqual(file.origFile, "readme")
        self.assertEqual(file.newInfo, "Uncommitted")
        self.assertEqual(file.newFile, "readme")

    def testDiffParserCommitted(self):
        """Testing HgDiffParser with a diff between committed revisions"""

        diffContents = "diff -r 356a6127ef19 -r 4960455a8e88 readme\n" + "--- a/readme\n" + "+++ b/readme\n"

        file = self._firstFileInDiff(diffContents)
        self.assertEqual(file.origInfo, "356a6127ef19")
        self.assertEqual(file.origFile, "readme")
        self.assertEqual(file.newInfo, "4960455a8e88")
        self.assertEqual(file.newFile, "readme")

    def testDiffParserWithPreambleJunk(self):
        """Testing HgDiffParser with a diff that contains non-diff junk test as a preamble"""

        diffContents = (
            "changeset:   60:3613c58ad1d5\n"
            + "user:        Michael Rowe <*****@*****.**>\n"
            + "date:        Fri Jul 27 11:44:37 2007 +1000\n"
            + "files:       readme\n"
            + "description:\n"
            + "Update the readme file\n"
            + "\n"
            + "\n"
            + "diff -r 356a6127ef19 -r 4960455a8e88 readme\n"
            + "--- a/readme\n"
            + "+++ b/readme\n"
        )

        file = self._firstFileInDiff(diffContents)
        self.assertEqual(file.origInfo, "356a6127ef19")
        self.assertEqual(file.origFile, "readme")
        self.assertEqual(file.newInfo, "4960455a8e88")
        self.assertEqual(file.newFile, "readme")

    def testRevisionParsing(self):
        """Testing HgDiffParser revision number parsing"""

        self.assertEqual(self.tool.parse_diff_revision("doc/readme", "bf544ea505f8"), ("doc/readme", "bf544ea505f8"))

        self.assertEqual(self.tool.parse_diff_revision("/dev/null", "bf544ea505f8"), ("/dev/null", PRE_CREATION))

        # TODO think of a meaningful thing to test here...
        # self.assertRaises(SCMException,
        #                  lambda: self.tool.parse_diff_revision('', 'hello'))

    def testGetFile(self):
        """Testing HgTool.get_file"""

        rev = Revision("661e5dd3c493")
        file = "doc/readme"

        self.assertEqual(self.tool.get_file(file, rev), "Hello\n\ngoodbye\n")

        self.assert_(self.tool.file_exists("doc/readme"))
        self.assert_(not self.tool.file_exists("doc/readme2"))

        self.assertRaises(FileNotFoundError, lambda: self.tool.get_file(""))

        self.assertRaises(FileNotFoundError, lambda: self.tool.get_file("hello", PRE_CREATION))

    def testInterface(self):
        """Testing basic HgTool API"""
        self.assert_(self.tool.get_diffs_use_absolute_paths())

        self.assertRaises(NotImplementedError, lambda: self.tool.get_changeset(1))

        self.assertRaises(NotImplementedError, lambda: self.tool.get_pending_changesets(1))

        self.assertEqual(self.tool.get_fields(), ["diff_path", "parent_diff_path"])
Ejemplo n.º 40
0
class MercurialTests(DjangoTestCase):
    """Unit tests for mercurial."""
    fixtures = ['hg.json', 'test_scmtools.json']

    def setUp(self):
        hg_repo_path = os.path.join(os.path.dirname(__file__),
                                    'testdata/hg_repo.bundle')
        self.repository = Repository(name='Test HG',
                                     path=hg_repo_path,
                                     tool=Tool.objects.get(name='Mercurial'))

        try:
            self.tool = self.repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest('Hg is not installed')

    def _firstFileInDiff(self, diff):
        return self.tool.get_parser(diff).parse()[0]

    def testPatchCreatesNewFile(self):
        """Testing HgTool with a patch that creates a new file"""

        self.assertEqual(
            PRE_CREATION,
            self.tool.parse_diff_revision("/dev/null", "bf544ea505f8")[1])

    def testDiffParserNewFile(self):
        """Testing HgDiffParser with a diff that creates a new file"""

        diffContents = 'diff -r bf544ea505f8 readme\n' + \
                       '--- /dev/null\n' + \
                       '+++ b/readme\n'

        file = self._firstFileInDiff(diffContents)
        self.assertEqual(file.origFile, "readme")

    def testDiffParserUncommitted(self):
        """Testing HgDiffParser with a diff with an uncommitted change"""

        diffContents = 'diff -r bf544ea505f8 readme\n' + \
                       '--- a/readme\n' + \
                       '+++ b/readme\n'

        file = self._firstFileInDiff(diffContents)
        self.assertEqual(file.origInfo, "bf544ea505f8")
        self.assertEqual(file.origFile, "readme")
        self.assertEqual(file.newInfo, "Uncommitted")
        self.assertEqual(file.newFile, "readme")

    def testDiffParserCommitted(self):
        """Testing HgDiffParser with a diff between committed revisions"""

        diffContents = 'diff -r 356a6127ef19 -r 4960455a8e88 readme\n' + \
                       '--- a/readme\n' + \
                       '+++ b/readme\n'

        file = self._firstFileInDiff(diffContents)
        self.assertEqual(file.origInfo, "356a6127ef19")
        self.assertEqual(file.origFile, "readme")
        self.assertEqual(file.newInfo, "4960455a8e88")
        self.assertEqual(file.newFile, "readme")

    def testDiffParserWithPreambleJunk(self):
        """Testing HgDiffParser with a diff that contains non-diff junk test as a preamble"""

        diffContents = 'changeset:   60:3613c58ad1d5\n' + \
                       'user:        Michael Rowe <*****@*****.**>\n' + \
                       'date:        Fri Jul 27 11:44:37 2007 +1000\n' + \
                       'files:       readme\n' + \
                       'description:\n' + \
                       'Update the readme file\n' + \
                       '\n' + \
                       '\n' + \
                       'diff -r 356a6127ef19 -r 4960455a8e88 readme\n' + \
                       '--- a/readme\n' + \
                       '+++ b/readme\n'

        file = self._firstFileInDiff(diffContents)
        self.assertEqual(file.origInfo, "356a6127ef19")
        self.assertEqual(file.origFile, "readme")
        self.assertEqual(file.newInfo, "4960455a8e88")
        self.assertEqual(file.newFile, "readme")

    def testRevisionParsing(self):
        """Testing HgDiffParser revision number parsing"""

        self.assertEqual(
            self.tool.parse_diff_revision('doc/readme', 'bf544ea505f8'),
            ('doc/readme', 'bf544ea505f8'))

        self.assertEqual(
            self.tool.parse_diff_revision('/dev/null', 'bf544ea505f8'),
            ('/dev/null', PRE_CREATION))

        # TODO think of a meaningful thing to test here...
        # self.assertRaises(SCMException,
        #                  lambda: self.tool.parse_diff_revision('', 'hello'))

    def testGetFile(self):
        """Testing HgTool.get_file"""

        rev = Revision('661e5dd3c493')
        file = 'doc/readme'

        self.assertEqual(self.tool.get_file(file, rev), 'Hello\n\ngoodbye\n')

        self.assert_(self.tool.file_exists('doc/readme'))
        self.assert_(not self.tool.file_exists('doc/readme2'))

        self.assertRaises(FileNotFoundError, lambda: self.tool.get_file(''))

        self.assertRaises(FileNotFoundError,
                          lambda: self.tool.get_file('hello', PRE_CREATION))

    def testInterface(self):
        """Testing basic HgTool API"""
        self.assert_(self.tool.get_diffs_use_absolute_paths())

        self.assertRaises(NotImplementedError,
                          lambda: self.tool.get_changeset(1))

        self.assertRaises(NotImplementedError,
                          lambda: self.tool.get_pending_changesets(1))

        self.assertEqual(self.tool.get_fields(),
                         ['diff_path', 'parent_diff_path'])
Ejemplo n.º 41
0
class GitTests(DjangoTestCase):
    """Unit tests for Git."""
    fixtures = ['test_scmtools.json']

    def setUp(self):
        tool = Tool.objects.get(name='Git')

        local_repo_path = os.path.join(os.path.dirname(__file__), 'testdata',
                                       'git_repo')
        remote_repo_path = '[email protected]:reviewboard/reviewboard.git'
        remote_repo_raw_url = 'http://github.com/api/v2/yaml/blob/show/' \
                              'reviewboard/reviewboard/<revision>'

        self.repository = Repository(name='Git test repo',
                                     path=local_repo_path,
                                     tool=tool)
        self.remote_repository = Repository(name='Remote Git test repo',
                                            path=remote_repo_path,
                                            raw_file_url=remote_repo_raw_url,
                                            tool=tool)

        try:
            self.tool = self.repository.get_scmtool()
            self.remote_tool = self.remote_repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest('git binary not found')

    def _readFixture(self, filename):
        return open( \
            os.path.join(os.path.dirname(__file__), 'testdata/%s' % filename), \
            'r').read()

    def _getFileInDiff(self, diff, filenum=0):
        return self.tool.get_parser(diff).parse()[filenum]

    def test_ssh(self):
        """Testing a SSH-backed git repository"""
        repo_path, username, password = _get_repo_test_info('GIT_SSH')
        self.tool.check_repository(repo_path, username, password)

    def testFilemodeDiff(self):
        """Testing parsing filemode changes Git diff"""
        diff = self._readFixture('git_filemode.diff')
        file = self._getFileInDiff(diff)
        self.assertEqual(file.origFile, 'testing')
        self.assertEqual(file.newFile, 'testing')
        self.assertEqual(file.origInfo, 'e69de29')
        self.assertEqual(file.newInfo, 'bcae657')
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertEqual(file.data.splitlines()[0],
                         "diff --git a/testing b/testing")
        self.assertEqual(file.data.splitlines()[-1], "+ADD")

    def testFilemodeWithFollowingDiff(self):
        """Testing parsing filemode changes with following Git diff"""
        diff = self._readFixture('git_filemode2.diff')
        file = self._getFileInDiff(diff)
        self.assertEqual(file.origFile, 'testing')
        self.assertEqual(file.newFile, 'testing')
        self.assertEqual(file.origInfo, 'e69de29')
        self.assertEqual(file.newInfo, 'bcae657')
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertEqual(file.data.splitlines()[0],
                         "diff --git a/testing b/testing")
        self.assertEqual(file.data.splitlines()[-1], "+ADD")
        file = self._getFileInDiff(diff, 1)
        self.assertEqual(file.origFile, 'cfg/testcase.ini')
        self.assertEqual(file.newFile, 'cfg/testcase.ini')
        self.assertEqual(file.origInfo, 'cc18ec8')
        self.assertEqual(file.newInfo, '5e70b73')
        self.assertEqual(file.data.splitlines()[0],
                         "diff --git a/cfg/testcase.ini b/cfg/testcase.ini")
        self.assertEqual(file.data.splitlines()[-1], '+db = pyunit')

    def testSimpleDiff(self):
        """Testing parsing simple Git diff"""
        diff = self._readFixture('git_simple.diff')
        file = self._getFileInDiff(diff)
        self.assertEqual(file.origFile, 'cfg/testcase.ini')
        self.assertEqual(file.newFile, 'cfg/testcase.ini')
        self.assertEqual(file.origInfo, 'cc18ec8')
        self.assertEqual(file.newInfo, '5e70b73')
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertEqual(len(file.data), 249)
        self.assertEqual(file.data.splitlines()[0],
                         "diff --git a/cfg/testcase.ini b/cfg/testcase.ini")
        self.assertEqual(file.data.splitlines()[-1], "+db = pyunit")

    def testNewfileDiff(self):
        """Testing parsing Git diff with new file"""
        diff = self._readFixture('git_newfile.diff')
        file = self._getFileInDiff(diff)
        self.assertEqual(file.origFile, 'IAMNEW')
        self.assertEqual(file.newFile, 'IAMNEW')
        self.assertEqual(file.origInfo, PRE_CREATION)
        self.assertEqual(file.newInfo, 'e69de29')
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertEqual(len(file.data), 124)
        self.assertEqual(file.data.splitlines()[0],
                         "diff --git a/IAMNEW b/IAMNEW")
        self.assertEqual(file.data.splitlines()[-1], "+Hello")

    def testNewfileNoContentDiff(self):
        """Testing parsing Git diff new file, no content"""
        diff = self._readFixture('git_newfile_nocontent.diff')
        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 0)

    def testNewfileNoContentWithFollowingDiff(self):
        """Testing parsing Git diff new file, no content, with following"""
        diff = self._readFixture('git_newfile_nocontent2.diff')
        self.assertEqual(len(self.tool.get_parser(diff).parse()), 1)
        file = self._getFileInDiff(diff)
        self.assertEqual(file.origFile, 'cfg/testcase.ini')
        self.assertEqual(file.newFile, 'cfg/testcase.ini')
        self.assertEqual(file.origInfo, 'cc18ec8')
        self.assertEqual(file.newInfo, '5e70b73')
        self.assertEqual(file.data.splitlines()[0],
                         "diff --git a/cfg/testcase.ini b/cfg/testcase.ini")
        self.assertEqual(file.data.splitlines()[-1], '+db = pyunit')

    def testDelFileDiff(self):
        """Testing parsing Git diff with deleted file"""
        diff = self._readFixture('git_delfile.diff')
        file = self._getFileInDiff(diff)
        self.assertEqual(file.origFile, 'OLDFILE')
        self.assertEqual(file.newFile, 'OLDFILE')
        self.assertEqual(file.origInfo, '8ebcb01')
        self.assertEqual(file.newInfo, '0000000')
        self.assertFalse(file.binary)
        self.assertTrue(file.deleted)
        self.assertEqual(len(file.data), 132)
        self.assertEqual(file.data.splitlines()[0],
                         "diff --git a/OLDFILE b/OLDFILE")
        self.assertEqual(file.data.splitlines()[-1], "-Goodbye")

    def testBinaryDiff(self):
        """Testing parsing Git diff with binary"""
        diff = self._readFixture('git_binary.diff')
        file = self._getFileInDiff(diff)
        self.assertEqual(file.origFile, 'pysvn-1.5.1.tar.gz')
        self.assertEqual(file.newFile, 'pysvn-1.5.1.tar.gz')
        self.assertEqual(file.origInfo, PRE_CREATION)
        self.assertEqual(file.newInfo, '86b520c')
        self.assertTrue(file.binary)
        self.assertFalse(file.deleted)
        self.assertEqual(len(file.data), 97)
        self.assertEqual(
            file.data.splitlines()[0],
            "diff --git a/pysvn-1.5.1.tar.gz b/pysvn-1.5.1.tar.gz")

    def testComplexDiff(self):
        """Testing parsing Git diff with existing and new files"""
        diff = self._readFixture('git_complex.diff')
        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 6)
        self.assertEqual(files[0].origFile, 'cfg/testcase.ini')
        self.assertEqual(files[0].newFile, 'cfg/testcase.ini')
        self.assertEqual(files[0].origInfo, '5e35098')
        self.assertEqual(files[0].newInfo, 'e254ef4')
        self.assertFalse(files[0].binary)
        self.assertFalse(files[0].deleted)
        self.assertEqual(len(files[0].data), 549)
        self.assertEqual(files[0].data.splitlines()[0],
                         "diff --git a/cfg/testcase.ini b/cfg/testcase.ini")
        self.assertEqual(files[0].data.splitlines()[13],
                         "         if isinstance(value, basestring):")

        self.assertEqual(files[1].origFile, 'tests/tests.py')
        self.assertEqual(files[1].newFile, 'tests/tests.py')
        self.assertEqual(files[1].origInfo, PRE_CREATION)
        self.assertEqual(files[1].newInfo, 'e279a06')
        self.assertFalse(files[1].binary)
        self.assertFalse(files[1].deleted)
        self.assertEqual(len(files[1].data), 182)
        self.assertEqual(files[1].data.splitlines()[0],
                         "diff --git a/tests/tests.py b/tests/tests.py")
        self.assertEqual(files[1].data.splitlines()[-1],
                         "+This is some new content")

        self.assertEqual(files[2].origFile, 'pysvn-1.5.1.tar.gz')
        self.assertEqual(files[2].newFile, 'pysvn-1.5.1.tar.gz')
        self.assertEqual(files[2].origInfo, PRE_CREATION)
        self.assertEqual(files[2].newInfo, '86b520c')
        self.assertTrue(files[2].binary)
        self.assertFalse(files[2].deleted)
        self.assertEqual(len(files[2].data), 97)
        self.assertEqual(
            files[2].data.splitlines()[0],
            "diff --git a/pysvn-1.5.1.tar.gz b/pysvn-1.5.1.tar.gz")

        self.assertEqual(files[3].origFile, 'readme')
        self.assertEqual(files[3].newFile, 'readme')
        self.assertEqual(files[3].origInfo, '5e35098')
        self.assertEqual(files[3].newInfo, 'e254ef4')
        self.assertFalse(files[3].binary)
        self.assertFalse(files[3].deleted)
        self.assertEqual(len(files[3].data), 127)
        self.assertEqual(files[3].data.splitlines()[0],
                         "diff --git a/readme b/readme")
        self.assertEqual(files[3].data.splitlines()[-1], "+Hello there")

        self.assertEqual(files[4].origFile, 'OLDFILE')
        self.assertEqual(files[4].newFile, 'OLDFILE')
        self.assertEqual(files[4].origInfo, '8ebcb01')
        self.assertEqual(files[4].newInfo, '0000000')
        self.assertFalse(files[4].binary)
        self.assertTrue(files[4].deleted)
        self.assertEqual(len(files[4].data), 132)
        self.assertEqual(files[4].data.splitlines()[0],
                         "diff --git a/OLDFILE b/OLDFILE")
        self.assertEqual(files[4].data.splitlines()[-1], "-Goodbye")

        self.assertEqual(files[5].origFile, 'readme2')
        self.assertEqual(files[5].newFile, 'readme2')
        self.assertEqual(files[5].origInfo, '5e43098')
        self.assertEqual(files[5].newInfo, 'e248ef4')
        self.assertFalse(files[5].binary)
        self.assertFalse(files[5].deleted)
        self.assertEqual(len(files[5].data), 131)
        self.assertEqual(files[5].data.splitlines()[0],
                         "diff --git a/readme2 b/readme2")
        self.assertEqual(files[5].data.splitlines()[-1], "+Hello there")

    def testParseDiffRevision(self):
        """Testing Git revision number parsing"""

        self.assertEqual(
            self.tool.parse_diff_revision('doc/readme', 'bf544ea'),
            ('doc/readme', 'bf544ea'))
        self.assertEqual(self.tool.parse_diff_revision('/dev/null', 'bf544ea'),
                         ('/dev/null', PRE_CREATION))
        self.assertEqual(self.tool.parse_diff_revision('/dev/null', '0000000'),
                         ('/dev/null', PRE_CREATION))

    def testFileExists(self):
        """Testing GitTool.file_exists"""

        self.assert_(self.tool.file_exists("readme", "e965047"))
        self.assert_(self.tool.file_exists("readme", "d6613f5"))

        self.assert_(not self.tool.file_exists("readme", PRE_CREATION))
        self.assert_(not self.tool.file_exists("readme", "fffffff"))
        self.assert_(not self.tool.file_exists("readme2", "fffffff"))

        # these sha's are valid, but commit and tree objects, not blobs
        self.assert_(not self.tool.file_exists("readme", "a62df6c"))
        self.assert_(not self.tool.file_exists("readme2", "ccffbb4"))

    def testGetFile(self):
        """Testing GitTool.get_file"""

        self.assertEqual(self.tool.get_file("readme", PRE_CREATION), '')
        self.assertEqual(self.tool.get_file("readme", "e965047"), 'Hello\n')
        self.assertEqual(self.tool.get_file("readme", "d6613f5"),
                         'Hello there\n')

        self.assertEqual(self.tool.get_file("readme"), 'Hello there\n')

        self.assertRaises(SCMError, lambda: self.tool.get_file(""))

        self.assertRaises(FileNotFoundError,
                          lambda: self.tool.get_file("", "0000000"))
        self.assertRaises(FileNotFoundError,
                          lambda: self.tool.get_file("hello", "0000000"))
        self.assertRaises(FileNotFoundError,
                          lambda: self.tool.get_file("readme", "0000000"))

    def testParseDiffRevisionWithRemoteAndShortSHA1Error(self):
        """Testing GitTool.parse_diff_revision with remote files and short SHA1 error"""
        self.assertRaises(
            ShortSHA1Error,
            lambda: self.remote_tool.parse_diff_revision('README', 'd7e96b3'))

    def testGetFileWithRemoteAndShortSHA1Error(self):
        """Testing GitTool.get_file with remote files and short SHA1 error"""
        self.assertRaises(
            ShortSHA1Error,
            lambda: self.remote_tool.get_file('README', 'd7e96b3'))
Ejemplo n.º 42
0
class MercurialTests(DiffParserTestingMixin, SCMTestCase):
    """Unit tests for mercurial."""

    fixtures = ['test_scmtools']

    def setUp(self):
        super(MercurialTests, self).setUp()

        hg_repo_path = os.path.join(os.path.dirname(__file__), '..',
                                    'testdata', 'hg_repo')
        self.repository = Repository(name='Test HG',
                                     path=hg_repo_path,
                                     tool=Tool.objects.get(name='Mercurial'))

        try:
            self.tool = self.repository.get_scmtool()
        except ImportError:
            raise unittest.SkipTest('Hg is not installed')

    def test_ssh_disallowed(self):
        """Testing HgTool does not allow SSH URLs"""
        with self.assertRaises(SCMError):
            self.tool.check_repository('ssh://foo')

    def test_git_parser_selection_with_header(self):
        """Testing HgTool returns the git parser when a header is present"""
        diffContents = (b'# HG changeset patch\n'
                        b'# Node ID 6187592a72d7\n'
                        b'# Parent  9d3f4147f294\n'
                        b'diff --git a/emptyfile b/emptyfile\n'
                        b'new file mode 100644\n')

        parser = self.tool.get_parser(diffContents)
        self.assertEqual(type(parser), HgGitDiffParser)

    def test_hg_parser_selection_with_header(self):
        """Testing HgTool returns the hg parser when a header is present"""
        diffContents = (b'# HG changeset patch'
                        b'# Node ID 6187592a72d7\n'
                        b'# Parent  9d3f4147f294\n'
                        b'diff -r 9d3f4147f294 -r 6187592a72d7 new.py\n'
                        b'--- /dev/null   Thu Jan 01 00:00:00 1970 +0000\n'
                        b'+++ b/new.py  Tue Apr 21 12:20:05 2015 -0400\n')

        parser = self.tool.get_parser(diffContents)
        self.assertEqual(type(parser), HgDiffParser)

    def test_git_parser_sets_commit_ids(self):
        """Testing HgGitDiffParser sets the parser commit ids"""
        diffContents = (b'# HG changeset patch\n'
                        b'# Node ID 6187592a72d7\n'
                        b'# Parent  9d3f4147f294\n'
                        b'diff --git a/emptyfile b/emptyfile\n'
                        b'new file mode 100644\n')

        parser = self.tool.get_parser(diffContents)
        parser.parse()
        self.assertEqual(parser.new_commit_id, b'6187592a72d7')
        self.assertEqual(parser.base_commit_id, b'9d3f4147f294')

    def test_patch_creates_new_file(self):
        """Testing HgTool with a patch that creates a new file"""
        self.assertEqual(
            self.tool.parse_diff_revision(filename=b'/dev/null',
                                          revision=b'bf544ea505f8')[1],
            PRE_CREATION)

    def test_diff_parser_new_file(self):
        """Testing HgDiffParser with a diff that creates a new file"""
        diff = (b'diff -r bf544ea505f8 readme\n'
                b'--- /dev/null\n'
                b'+++ b/readme\n')

        parsed_files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(parsed_files), 1)

        self.assert_parsed_diff_file(parsed_files[0],
                                     orig_filename=b'readme',
                                     orig_file_details=PRE_CREATION,
                                     modified_filename=b'readme',
                                     modified_file_details=b'Uncommitted',
                                     data=diff)

    def test_diff_parser_with_added_empty_file(self):
        """Testing HgDiffParser with a diff with an added empty file"""
        diff = (b'diff -r 356a6127ef19 -r 4960455a8e88 empty\n'
                b'--- /dev/null\n'
                b'+++ b/empty\n')

        parsed_files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(parsed_files), 1)

        self.assert_parsed_diff_file(parsed_files[0],
                                     orig_filename=b'empty',
                                     orig_file_details=PRE_CREATION,
                                     modified_filename=b'empty',
                                     modified_file_details=b'4960455a8e88',
                                     data=diff)

    def test_diff_parser_with_deleted_empty_file(self):
        """Testing HgDiffParser with a diff with a deleted empty file"""
        diff = (b'diff -r 356a6127ef19 -r 4960455a8e88 empty\n'
                b'--- a/empty\n'
                b'+++ /dev/null\n')

        parsed_files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(parsed_files), 1)

        self.assert_parsed_diff_file(parsed_files[0],
                                     orig_filename=b'empty',
                                     orig_file_details=b'356a6127ef19',
                                     modified_filename=b'empty',
                                     modified_file_details=b'4960455a8e88',
                                     deleted=True,
                                     data=diff)

    def test_diff_parser_uncommitted(self):
        """Testing HgDiffParser with a diff with an uncommitted change"""
        diff = (b'diff -r bf544ea505f8 readme\n'
                b'--- a/readme\n'
                b'+++ b/readme\n')

        parsed_files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(parsed_files), 1)

        self.assert_parsed_diff_file(parsed_files[0],
                                     orig_filename=b'readme',
                                     orig_file_details=b'bf544ea505f8',
                                     modified_filename=b'readme',
                                     modified_file_details=b'Uncommitted',
                                     data=diff)

    def test_diff_parser_committed(self):
        """Testing HgDiffParser with a diff between committed revisions"""
        diff = (b'diff -r 356a6127ef19 -r 4960455a8e88 readme\n'
                b'--- a/readme\n'
                b'+++ b/readme\n')

        parsed_files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(parsed_files), 1)

        self.assert_parsed_diff_file(parsed_files[0],
                                     orig_filename=b'readme',
                                     orig_file_details=b'356a6127ef19',
                                     modified_filename=b'readme',
                                     modified_file_details=b'4960455a8e88',
                                     data=diff)

    def test_diff_parser_with_preamble_junk(self):
        """Testing HgDiffParser with a diff that contains non-diff junk text
        as a preamble
        """
        diff = (b'changeset:   60:3613c58ad1d5\n'
                b'user:        Michael Rowe <*****@*****.**>\n'
                b'date:        Fri Jul 27 11:44:37 2007 +1000\n'
                b'files:       readme\n'
                b'description:\n'
                b'Update the readme file\n'
                b'\n'
                b'\n'
                b'diff -r 356a6127ef19 -r 4960455a8e88 readme\n'
                b'--- a/readme\n'
                b'+++ b/readme\n')

        parsed_files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(parsed_files), 1)

        self.assert_parsed_diff_file(parsed_files[0],
                                     orig_filename=b'readme',
                                     orig_file_details=b'356a6127ef19',
                                     modified_filename=b'readme',
                                     modified_file_details=b'4960455a8e88',
                                     data=diff)

    def test_git_diff_parsing(self):
        """Testing HgDiffParser git diff support"""
        diff = (b'# Node ID 4960455a8e88\n'
                b'# Parent bf544ea505f8\n'
                b'diff --git a/path/to file/readme.txt '
                b'b/new/path to/readme.txt\n'
                b'rename from path/to file/readme.txt\n'
                b'rename to new/path to/readme.txt\n'
                b'--- a/path/to file/readme.txt\n'
                b'+++ b/new/path to/readme.txt\n')

        parsed_files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(parsed_files), 1)

        self.assert_parsed_diff_file(
            parsed_files[0],
            orig_filename=b'path/to file/readme.txt',
            orig_file_details=b'bf544ea505f8',
            modified_filename=b'new/path to/readme.txt',
            modified_file_details=b'4960455a8e88',
            moved=True,
            data=diff)

    def test_diff_parser_unicode(self):
        """Testing HgDiffParser with unicode characters"""
        diff = ('diff -r bf544ea505f8 réadme\n'
                '--- a/réadme\n'
                '+++ b/réadme\n').encode('utf-8')

        parsed_files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(parsed_files), 1)

        self.assert_parsed_diff_file(
            parsed_files[0],
            orig_filename='réadme'.encode('utf-8'),
            orig_file_details=b'bf544ea505f8',
            modified_filename='réadme'.encode('utf-8'),
            modified_file_details=b'Uncommitted',
            data=diff)

    def test_git_diff_parsing_unicode(self):
        """Testing HgDiffParser git diff with unicode characters"""
        diff = ('# Node ID 4960455a8e88\n'
                '# Parent bf544ea505f8\n'
                'diff --git a/path/to file/réadme.txt '
                'b/new/path to/réadme.txt\n'
                'rename from path/to file/réadme.txt\n'
                'rename to new/path to/réadme.txt\n'
                '--- a/path/to file/réadme.txt\n'
                '+++ b/new/path to/réadme.txt\n').encode('utf-8')

        parsed_files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(parsed_files), 1)

        self.assert_parsed_diff_file(
            parsed_files[0],
            orig_filename='path/to file/réadme.txt'.encode('utf-8'),
            orig_file_details=b'bf544ea505f8',
            modified_filename='new/path to/réadme.txt'.encode('utf-8'),
            modified_file_details=b'4960455a8e88',
            moved=True,
            data=diff)

    def test_revision_parsing(self):
        """Testing HgDiffParser revision number parsing"""
        self.assertEqual(
            self.tool.parse_diff_revision(filename=b'doc/readme',
                                          revision=b'bf544ea505f8'),
            (b'doc/readme', b'bf544ea505f8'))

        self.assertEqual(
            self.tool.parse_diff_revision(filename=b'/dev/null',
                                          revision=b'bf544ea505f8'),
            (b'/dev/null', PRE_CREATION))

    def test_get_branches(self):
        """Testing list of branches in HgClient.get_change"""
        value = self.tool.get_branches()
        self.assertTrue(isinstance(value, list))
        self.assertEqual(len(value), 1)

        self.assertEqual(value[0].id, 'default')
        self.assertEqual(value[0].commit,
                         '661e5dd3c4938ecbe8f77e2fdfa905d70485f94c')
        self.assertEqual(value[0].default, True)

    def test_get_change(self):
        """Testing raw diff of HgClient.get_change"""
        self.assertRaises(SCMError, lambda: self.tool.get_change('dummy'))

        value = self.tool.get_change('0')
        self.assertNotIn(b'goodbye', value.diff)
        self.assertEqual(value.id, 'f814b6e226d2ba6d26d02ca8edbff91f57ab2786')
        value = self.tool.get_change('1')
        self.assertIn(b'goodbye', value.diff)
        self.assertEqual(value.id, '661e5dd3c4938ecbe8f77e2fdfa905d70485f94c')

    def test_get_commits(self):
        """Testing commit objects in HgClient.get_commits"""
        value = self.tool.get_commits()
        self.assertTrue(isinstance(value, list))
        self.assertEqual(len(value), 2)

        self.assertEqual(value[0].id,
                         '661e5dd3c4938ecbe8f77e2fdfa905d70485f94c')
        self.assertEqual(value[0].message, 'second')
        self.assertEqual(value[0].author_name,
                         'Michael Rowe <*****@*****.**>')
        self.assertEqual(value[0].date, '2007-08-07T17:12:23')
        self.assertEqual(value[0].parent,
                         'f814b6e226d2ba6d26d02ca8edbff91f57ab2786')

        self.assertEqual(value[1].id,
                         'f814b6e226d2ba6d26d02ca8edbff91f57ab2786')
        self.assertEqual(value[1].message, 'first')
        self.assertEqual(value[1].author_name,
                         'Michael Rowe <*****@*****.**>')
        self.assertEqual(value[1].date, '2007-08-07T17:11:57')
        self.assertEqual(value[1].parent,
                         '0000000000000000000000000000000000000000')

        self.assertRaisesRegexp(SCMError, 'Cannot load commits: ',
                                lambda: self.tool.get_commits(branch='x'))

        rev = 'f814b6e226d2ba6d26d02ca8edbff91f57ab2786'
        value = self.tool.get_commits(start=rev)
        self.assertTrue(isinstance(value, list))
        self.assertEqual(len(value), 1)

    def test_get_commits_with_non_utc_server_timezone(self):
        """Testing commit objects in HgClient.get_commits with
        settings.TIME_ZONE != UTC
        """
        old_tz = os.environ[str('TZ')]
        os.environ[str('TZ')] = str('US/Pacific')

        try:
            value = self.tool.get_commits()
        finally:
            os.environ[str('TZ')] = old_tz

        self.assertTrue(isinstance(value, list))
        self.assertEqual(len(value), 2)

        self.assertEqual(value[0].id,
                         '661e5dd3c4938ecbe8f77e2fdfa905d70485f94c')
        self.assertEqual(value[0].message, 'second')
        self.assertEqual(value[0].author_name,
                         'Michael Rowe <*****@*****.**>')
        self.assertEqual(value[0].date, '2007-08-07T17:12:23')
        self.assertEqual(value[0].parent,
                         'f814b6e226d2ba6d26d02ca8edbff91f57ab2786')

        self.assertEqual(value[1].id,
                         'f814b6e226d2ba6d26d02ca8edbff91f57ab2786')
        self.assertEqual(value[1].message, 'first')
        self.assertEqual(value[1].author_name,
                         'Michael Rowe <*****@*****.**>')
        self.assertEqual(value[1].date, '2007-08-07T17:11:57')
        self.assertEqual(value[1].parent,
                         '0000000000000000000000000000000000000000')

        self.assertRaisesRegexp(SCMError, 'Cannot load commits: ',
                                lambda: self.tool.get_commits(branch='x'))

        rev = 'f814b6e226d2ba6d26d02ca8edbff91f57ab2786'
        value = self.tool.get_commits(start=rev)
        self.assertTrue(isinstance(value, list))
        self.assertEqual(len(value), 1)

    def test_get_file(self):
        """Testing HgTool.get_file"""
        tool = self.tool

        value = tool.get_file('doc/readme', Revision('661e5dd3c493'))
        self.assertIsInstance(value, bytes)
        self.assertEqual(value, b'Hello\n\ngoodbye\n')

        with self.assertRaises(FileNotFoundError):
            tool.get_file('')

        with self.assertRaises(FileNotFoundError):
            tool.get_file('hello', PRE_CREATION)

    def test_file_exists(self):
        """Testing HgTool.file_exists"""
        rev = Revision('661e5dd3c493')

        self.assertTrue(self.tool.file_exists('doc/readme', rev))
        self.assertFalse(self.tool.file_exists('doc/readme2', rev))

    def test_get_file_base_commit_id_override(self):
        """Testing base_commit_id overrides revision in HgTool.get_file"""
        base_commit_id = Revision('661e5dd3c493')
        bogus_rev = Revision('bogusrevision')
        file = 'doc/readme'

        value = self.tool.get_file(file,
                                   bogus_rev,
                                   base_commit_id=base_commit_id)
        self.assertTrue(isinstance(value, bytes))
        self.assertEqual(value, b'Hello\n\ngoodbye\n')

        self.assertTrue(
            self.tool.file_exists('doc/readme',
                                  bogus_rev,
                                  base_commit_id=base_commit_id))
        self.assertTrue(not self.tool.file_exists(
            'doc/readme2', bogus_rev, base_commit_id=base_commit_id))

    def test_interface(self):
        """Testing basic HgTool API"""
        self.assertTrue(self.tool.diffs_use_absolute_paths)

        self.assertRaises(NotImplementedError,
                          lambda: self.tool.get_changeset(1))

    @online_only
    def test_https_repo(self):
        """Testing HgTool.file_exists with an HTTPS-based repository"""
        repo = Repository(name='Test HG2',
                          path='https://www.mercurial-scm.org/repo/hg',
                          tool=Tool.objects.get(name='Mercurial'))
        tool = repo.get_scmtool()

        self.assertTrue(
            tool.file_exists('mercurial/hgweb/common.py',
                             Revision('f0735f2ce542')))
        self.assertFalse(
            tool.file_exists('mercurial/hgweb/common.py',
                             Revision('abcdef123456')))

    def test_normalize_patch_with_git_diff_new_symlink(self):
        """Testing HgTool.normalize_patch with Git-style diff and new symlink
        """
        self.assertEqual(
            self.tool.normalize_patch(patch=(b'diff --git /dev/null b/test\n'
                                             b'new file mode 120000\n'
                                             b'--- /dev/null\n'
                                             b'+++ b/test\n'
                                             b'@@ -0,0 +1,1 @@\n'
                                             b'+target_file\n'
                                             b'\\ No newline at end of file'),
                                      filename='test',
                                      revision=PRE_CREATION),
            (b'diff --git /dev/null b/test\n'
             b'new file mode 100000\n'
             b'--- /dev/null\n'
             b'+++ b/test\n'
             b'@@ -0,0 +1,1 @@\n'
             b'+target_file\n'
             b'\\ No newline at end of file'))

    def test_normalize_patch_with_git_diff_modified_symlink(self):
        """Testing HgTool.normalize_patch with Git-style diff and modified
        symlink
        """
        self.assertEqual(
            self.tool.normalize_patch(patch=(b'diff --git a/test b/test\n'
                                             b'index abc1234..def4567 120000\n'
                                             b'--- a/test\n'
                                             b'+++ b/test\n'
                                             b'@@ -1,1 +1,1 @@\n'
                                             b'-old_target\n'
                                             b'\\ No newline at end of file'
                                             b'+new_target\n'
                                             b'\\ No newline at end of file'),
                                      filename='test',
                                      revision='abc1234'),
            (b'diff --git a/test b/test\n'
             b'index abc1234..def4567 100000\n'
             b'--- a/test\n'
             b'+++ b/test\n'
             b'@@ -1,1 +1,1 @@\n'
             b'-old_target\n'
             b'\\ No newline at end of file'
             b'+new_target\n'
             b'\\ No newline at end of file'))

    def test_normalize_patch_with_git_diff_deleted_symlink(self):
        """Testing HgTool.normalize_patch with Git-style diff and deleted
        symlink
        """
        self.assertEqual(
            self.tool.normalize_patch(patch=(b'diff --git a/test b/test\n'
                                             b'deleted file mode 120000\n'
                                             b'index abc1234..0000000\n'
                                             b'--- a/test\n'
                                             b'+++ /dev/null\n'
                                             b'@@ -1,1 +0,0 @@\n'
                                             b'-old_target\n'
                                             b'\\ No newline at end of file'),
                                      filename='test',
                                      revision='abc1234'),
            (b'diff --git a/test b/test\n'
             b'deleted file mode 100000\n'
             b'index abc1234..0000000\n'
             b'--- a/test\n'
             b'+++ /dev/null\n'
             b'@@ -1,1 +0,0 @@\n'
             b'-old_target\n'
             b'\\ No newline at end of file'))

    def test_normalize_patch_with_hg_diff(self):
        """Testing HgTool.normalize_patch with Git-style diff and deleted
        symlink
        """
        self.assertEqual(
            self.tool.normalize_patch(
                patch=(b'diff -r 123456789abc -r 123456789def test\n'
                       b'--- a/test\n'
                       b'+++ b/test\n'
                       b'@@ -1,1 +1,1 @@\n'
                       b'-a\n'
                       b'-b\n'),
                filename='test',
                revision='123456789abc'),
            (b'diff -r 123456789abc -r 123456789def test\n'
             b'--- a/test\n'
             b'+++ b/test\n'
             b'@@ -1,1 +1,1 @@\n'
             b'-a\n'
             b'-b\n'))

    def test_get_diff_parser_cls_with_git_diff(self):
        """Testing HgTool._get_diff_parser_cls with Git diff"""
        self.assertIs(
            self.tool._get_diff_parser_cls(b'diff --git a/test b/test\n'
                                           b'--- a/test\n'
                                           b'+++ b/test\n'
                                           b'@@ -1,1 +1,1 @@\n'
                                           b'-a\n'
                                           b'-b\n'), HgGitDiffParser)

    def test_get_diff_parser_cls_with_git_diff_and_header(self):
        """Testing HgTool._get_diff_parser_cls with Git diff and header"""
        self.assertIs(
            self.tool._get_diff_parser_cls(b'# HG changeset patch\n'
                                           b'# Node ID 123456789abc\n'
                                           b'# Parent cba987654321\n'
                                           b'diff --git a/test b/test\n'
                                           b'--- a/test\n'
                                           b'+++ b/test\n'
                                           b'@@ -1,1 +1,1 @@\n'
                                           b'-a\n'
                                           b'-b\n'), HgGitDiffParser)

    def test_get_diff_parser_cls_with_hg_diff(self):
        """Testing HgTool._get_diff_parser_cls with Mercurial diff"""
        self.assertIs(
            self.tool._get_diff_parser_cls(
                b'diff -r 123456789abc -r 123456789def test\n'
                b'--- a/test   Thu Feb 17 12:36:00 2022 -0700\n'
                b'+++ b/test   Thu Feb 17 12:36:15 2022 -0700\n'
                b'@@ -1,1 +1,1 @@\n'
                b'-a\n'
                b'-b\n'), HgDiffParser)

    def test_get_diff_parser_cls_with_hg_diff_and_header(self):
        """Testing HgTool._get_diff_parser_cls with Mercurial diff and header
        """
        self.assertIs(
            self.tool._get_diff_parser_cls(
                b'# HG changeset patch\n'
                b'# Node ID 123456789abc\n'
                b'# Parent cba987654321\n'
                b'diff -r 123456789abc -r 123456789def test\n'
                b'--- a/test   Thu Feb 17 12:36:00 2022 -0700\n'
                b'+++ b/test   Thu Feb 17 12:36:15 2022 -0700\n'
                b'@@ -1,1 +1,1 @@\n'
                b'-a\n'
                b'-b\n'), HgDiffParser)

    def test_get_diff_parser_cls_with_git_before_hg(self):
        """Testing HgTool._get_diff_parser_cls with diff --git before diff -r
        """
        self.assertIs(
            self.tool._get_diff_parser_cls(
                b'diff --git a/test b/test\n'
                b'diff -r 123456789abc -r 123456789def test\n'),
            HgGitDiffParser)

    def test_get_diff_parser_cls_with_hg_before_git(self):
        """Testing HgTool._get_diff_parser_cls with diff -r before diff --git
        """
        self.assertIs(
            self.tool._get_diff_parser_cls(
                b'diff -r 123456789abc -r 123456789def test\n'
                b'diff --git a/test b/test\n'), HgDiffParser)
Ejemplo n.º 43
0
class GitTests(DjangoTestCase):
    """
    Unit tests for Git
    """
    fixtures = ['test_scmtools.json']

    def setUp(self):
        repo_path = os.path.join(os.path.dirname(__file__),
                                 'testdata', 'git_repo')
        self.repository = Repository(name='Git test repo',
                                     path=repo_path,
                                     tool=Tool.objects.get(name='Git'))
        try:
            self.tool = self.repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest('git binary not found')

    def _readFixture(self, filename):
        return open( \
            os.path.join(os.path.dirname(__file__), 'testdata/%s' % filename), \
            'r').read()

    def _getFileInDiff(self, diff, filenum=0):
        return self.tool.get_parser(diff).parse()[filenum]

    def testFilemodeDiff(self):
        """Testing parsing filemode changes Git diff"""
        diff = self._readFixture('git_filemode.diff')
        file = self._getFileInDiff(diff)
        self.assertEqual(file.origFile, 'testing')
        self.assertEqual(file.newFile, 'testing')
        self.assertEqual(file.origInfo, 'e69de29')
        self.assertEqual(file.newInfo, 'bcae657')
        self.assertFalse(file.binary)
        self.assertEqual(file.data.splitlines()[0],
                         "diff --git a/testing b/testing")
        self.assertEqual(file.data.splitlines()[-1], "+ADD")

    def testFilemodeWithFollowingDiff(self):
        """Testing parsing filemode changes with following Git diff"""
        diff = self._readFixture('git_filemode2.diff')
        file = self._getFileInDiff(diff)
        self.assertEqual(file.origFile, 'testing')
        self.assertEqual(file.newFile, 'testing')
        self.assertEqual(file.origInfo, 'e69de29')
        self.assertEqual(file.newInfo, 'bcae657')
        self.assertFalse(file.binary)
        self.assertEqual(file.data.splitlines()[0],
                         "diff --git a/testing b/testing")
        self.assertEqual(file.data.splitlines()[-1], "+ADD")
        file = self._getFileInDiff(diff, 1)
        self.assertEqual(file.origFile, 'cfg/testcase.ini')
        self.assertEqual(file.newFile, 'cfg/testcase.ini')
        self.assertEqual(file.origInfo, 'cc18ec8')
        self.assertEqual(file.newInfo, '5e70b73')
        self.assertEqual(file.data.splitlines()[0],
                        "diff --git a/cfg/testcase.ini b/cfg/testcase.ini")
        self.assertEqual(file.data.splitlines()[-1], '+db = pyunit')

    def testSimpleDiff(self):
        """Testing parsing simple Git diff"""
        diff = self._readFixture('git_simple.diff')
        file = self._getFileInDiff(diff)
        self.assertEqual(file.origFile, 'cfg/testcase.ini')
        self.assertEqual(file.newFile, 'cfg/testcase.ini')
        self.assertEqual(file.origInfo, 'cc18ec8')
        self.assertEqual(file.newInfo, '5e70b73')
        self.assertFalse(file.binary)
        self.assertEqual(len(file.data), 219)
        self.assertEqual(file.data.splitlines()[0],
                         "diff --git a/cfg/testcase.ini b/cfg/testcase.ini")
        self.assertEqual(file.data.splitlines()[-1], "+db = pyunit")

    def testNewfileDiff(self):
        """Testing parsing Git diff with new file"""
        diff = self._readFixture('git_newfile.diff')
        file = self._getFileInDiff(diff)
        self.assertEqual(file.origFile, 'IAMNEW')
        self.assertEqual(file.newFile, 'IAMNEW')
        self.assertEqual(file.origInfo, PRE_CREATION)
        self.assertEqual(file.newInfo, 'e69de29')
        self.assertFalse(file.binary)
        self.assertEqual(len(file.data), 80)
        self.assertEqual(file.data.splitlines()[0],
                         "diff --git a/IAMNEW b/IAMNEW")
        self.assertEqual(file.data.splitlines()[-1], "+Hello")

    def testNewfileNoContentDiff(self):
        """Testing parsing Git diff new file, no content"""
        diff = self._readFixture('git_newfile_nocontent.diff')
        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(self.tool.get_parser(diff).parse()), 0)

    def testNewfileNoContentWithFollowingDiff(self):
        """Testing parsing Git diff new file, no content, with following"""
        diff = self._readFixture('git_newfile_nocontent2.diff')
        self.assertEqual(len(self.tool.get_parser(diff).parse()), 1)
        file = self._getFileInDiff(diff)
        self.assertEqual(file.origFile, 'cfg/testcase.ini')
        self.assertEqual(file.newFile, 'cfg/testcase.ini')
        self.assertEqual(file.origInfo, 'cc18ec8')
        self.assertEqual(file.newInfo, '5e70b73')
        self.assertEqual(file.data.splitlines()[0],
                        "diff --git a/cfg/testcase.ini b/cfg/testcase.ini")
        self.assertEqual(file.data.splitlines()[-1], '+db = pyunit')

    def testDelFileDiff(self):
        """Testing parsing Git diff with deleted file"""
        diff = self._readFixture('git_delfile.diff')
        file = self._getFileInDiff(diff)
        self.assertEqual(file.origFile, 'OLDFILE')
        self.assertEqual(file.newFile, 'OLDFILE')
        self.assertEqual(file.origInfo, '8ebcb01')
        self.assertEqual(file.newInfo, '0000000')
        self.assertFalse(file.binary)
        self.assertEqual(len(file.data), 84)
        self.assertEqual(file.data.splitlines()[0],
                         "diff --git a/OLDFILE b/OLDFILE")
        self.assertEqual(file.data.splitlines()[-1], "-Goodbye")

    def testBinaryDiff(self):
        """Testing parsing Git diff with binary"""
        diff = self._readFixture('git_binary.diff')
        file = self._getFileInDiff(diff)
        self.assertEqual(file.origFile, 'pysvn-1.5.1.tar.gz')
        self.assertEqual(file.newFile, 'pysvn-1.5.1.tar.gz')
        self.assertEqual(file.origInfo, PRE_CREATION)
        self.assertEqual(file.newInfo, '86b520c')
        self.assertTrue(file.binary)
        self.assertEqual(len(file.data), 53)
        self.assertEqual(file.data.splitlines()[0],
                         "diff --git a/pysvn-1.5.1.tar.gz b/pysvn-1.5.1.tar.gz")

    def testComplexDiff(self):
        """Testing parsing Git diff with existing and new files"""
        diff = self._readFixture('git_complex.diff')
        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 6)
        self.assertEqual(files[0].origFile, 'cfg/testcase.ini')
        self.assertEqual(files[0].newFile, 'cfg/testcase.ini')
        self.assertEqual(files[0].origInfo, '5e35098')
        self.assertEqual(files[0].newInfo, 'e254ef4')
        self.assertFalse(files[0].binary)
        self.assertEqual(len(files[0].data), 519)
        self.assertEqual(files[0].data.splitlines()[0],
                         "diff --git a/cfg/testcase.ini b/cfg/testcase.ini")
        self.assertEqual(files[0].data.splitlines()[12],
                         "         if isinstance(value, basestring):")

        self.assertEqual(files[1].origFile, 'tests/tests.py')
        self.assertEqual(files[1].newFile, 'tests/tests.py')
        self.assertEqual(files[1].origInfo, PRE_CREATION)
        self.assertEqual(files[1].newInfo, 'e279a06')
        self.assertFalse(files[1].binary)
        self.assertEqual(len(files[1].data), 138)
        self.assertEqual(files[1].data.splitlines()[0],
                         "diff --git a/tests/tests.py b/tests/tests.py")
        self.assertEqual(files[1].data.splitlines()[-1],
                         "+This is some new content")

        self.assertEqual(files[2].origFile, 'pysvn-1.5.1.tar.gz')
        self.assertEqual(files[2].newFile, 'pysvn-1.5.1.tar.gz')
        self.assertEqual(files[2].origInfo, PRE_CREATION)
        self.assertEqual(files[2].newInfo, '86b520c')
        self.assertTrue(files[2].binary)
        self.assertEqual(len(files[2].data), 53)
        self.assertEqual(files[2].data.splitlines()[0],
                         "diff --git a/pysvn-1.5.1.tar.gz b/pysvn-1.5.1.tar.gz")

        self.assertEqual(files[3].origFile, 'readme')
        self.assertEqual(files[3].newFile, 'readme')
        self.assertEqual(files[3].origInfo, '5e35098')
        self.assertEqual(files[3].newInfo, 'e254ef4')
        self.assertFalse(files[3].binary)
        self.assertEqual(len(files[3].data), 97)
        self.assertEqual(files[3].data.splitlines()[0],
                         "diff --git a/readme b/readme")
        self.assertEqual(files[3].data.splitlines()[-1],
                         "+Hello there")

        self.assertEqual(files[4].origFile, 'OLDFILE')
        self.assertEqual(files[4].newFile, 'OLDFILE')
        self.assertEqual(files[4].origInfo, '8ebcb01')
        self.assertEqual(files[4].newInfo, '0000000')
        self.assertFalse(files[4].binary)
        self.assertEqual(len(files[4].data), 84)
        self.assertEqual(files[4].data.splitlines()[0],
                         "diff --git a/OLDFILE b/OLDFILE")
        self.assertEqual(files[4].data.splitlines()[-1],
                         "-Goodbye")

        self.assertEqual(files[5].origFile, 'readme2')
        self.assertEqual(files[5].newFile, 'readme2')
        self.assertEqual(files[5].origInfo, '5e43098')
        self.assertEqual(files[5].newInfo, 'e248ef4')
        self.assertFalse(files[5].binary)
        self.assertEqual(len(files[5].data), 101)
        self.assertEqual(files[5].data.splitlines()[0],
                         "diff --git a/readme2 b/readme2")
        self.assertEqual(files[5].data.splitlines()[-1],
                         "+Hello there")

    def testParseDiffRevision(self):
        """Testing Git revision number parsing"""

        self.assertEqual(self.tool.parse_diff_revision('doc/readme', 'bf544ea'),
                         ('doc/readme', 'bf544ea'))
        self.assertEqual(self.tool.parse_diff_revision('/dev/null', 'bf544ea'),
                         ('/dev/null', PRE_CREATION))
        self.assertEqual(self.tool.parse_diff_revision('/dev/null', '0000000'),
                         ('/dev/null', PRE_CREATION))

    def testFileExists(self):
        """Testing GitTool.file_exists"""

        self.assert_(self.tool.file_exists("readme", "e965047"))
        self.assert_(self.tool.file_exists("readme", "d6613f5"))

        self.assert_(not self.tool.file_exists("readme", PRE_CREATION))
        self.assert_(not self.tool.file_exists("readme", "fffffff"))
        self.assert_(not self.tool.file_exists("readme2", "fffffff"))

        # these sha's are valid, but commit and tree objects, not blobs
        self.assert_(not self.tool.file_exists("readme", "a62df6c"))
        self.assert_(not self.tool.file_exists("readme2", "ccffbb4"))

    def testGetFile(self):
        """Testing GitTool.get_file"""

        self.assertEqual(self.tool.get_file("readme", PRE_CREATION), '')
        self.assertEqual(self.tool.get_file("readme", "e965047"), 'Hello\n')
        self.assertEqual(self.tool.get_file("readme", "d6613f5"), 'Hello there\n')

        self.assertEqual(self.tool.get_file("readme"), 'Hello there\n')

        self.assertRaises(SCMError, lambda: self.tool.get_file(""))

        self.assertRaises(FileNotFoundError,
                          lambda: self.tool.get_file("", "0000000"))
        self.assertRaises(FileNotFoundError,
                          lambda: self.tool.get_file("hello", "0000000"))
        self.assertRaises(FileNotFoundError,
                          lambda: self.tool.get_file("readme", "0000000"))
Ejemplo n.º 44
0
class GitTests(SpyAgency, SCMTestCase):
    """Unit tests for Git."""

    fixtures = ["test_scmtools"]

    def setUp(self):
        super(GitTests, self).setUp()

        tool = Tool.objects.get(name="Git")

        self.local_repo_path = os.path.join(os.path.dirname(__file__), "..", "testdata", "git_repo")
        self.git_ssh_path = "localhost:%s" % self.local_repo_path.replace("\\", "/")
        remote_repo_path = "[email protected]:reviewboard/reviewboard.git"
        remote_repo_raw_url = "http://github.com/api/v2/yaml/blob/show/" "reviewboard/reviewboard/<revision>"

        self.repository = Repository(name="Git test repo", path=self.local_repo_path, tool=tool)
        self.remote_repository = Repository(
            name="Remote Git test repo", path=remote_repo_path, raw_file_url=remote_repo_raw_url, tool=tool
        )

        try:
            self.tool = self.repository.get_scmtool()
            self.remote_tool = self.remote_repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest("git binary not found")

    def _read_fixture(self, filename):
        filename = os.path.join(os.path.dirname(__file__), "..", "testdata", filename)
        with open(filename, "r") as f:
            return f.read()

    def _get_file_in_diff(self, diff, filenum=0):
        files = self.tool.get_parser(diff).parse()
        self.assertTrue(filenum < len(files))
        return files[filenum]

    def test_ssh(self):
        """Testing a SSH-backed git repository"""
        self._test_ssh(self.git_ssh_path)

    def test_ssh_with_site(self):
        """Testing a SSH-backed git repository with a LocalSite"""
        self._test_ssh_with_site(self.git_ssh_path)

    def test_filemode_diff(self):
        """Testing parsing filemode changes Git diff"""
        diff = self._read_fixture("git_filemode.diff")

        file = self._get_file_in_diff(diff)
        self.assertEqual(file.origFile, "testing")
        self.assertEqual(file.newFile, "testing")
        self.assertEqual(file.origInfo, "e69de29")
        self.assertEqual(file.newInfo, "bcae657")
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertEqual(file.data.splitlines()[0], "diff --git a/testing b/testing")
        self.assertEqual(file.data.splitlines()[-1], "+ADD")
        self.assertEqual(file.insert_count, 1)
        self.assertEqual(file.delete_count, 0)

    def test_filemode_with_following_diff(self):
        """Testing parsing filemode changes with following Git diff"""
        diff = self._read_fixture("git_filemode2.diff")

        file = self._get_file_in_diff(diff)
        self.assertEqual(file.origFile, "testing")
        self.assertEqual(file.newFile, "testing")
        self.assertEqual(file.origInfo, "e69de29")
        self.assertEqual(file.newInfo, "bcae657")
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertEqual(file.data.splitlines()[0], "diff --git a/testing b/testing")
        self.assertEqual(file.data.splitlines()[-1], "+ADD")
        self.assertEqual(file.insert_count, 1)
        self.assertEqual(file.delete_count, 0)

        file = self._get_file_in_diff(diff, 1)
        self.assertEqual(file.origFile, "cfg/testcase.ini")
        self.assertEqual(file.newFile, "cfg/testcase.ini")
        self.assertEqual(file.origInfo, "cc18ec8")
        self.assertEqual(file.newInfo, "5e70b73")
        self.assertEqual(file.data.splitlines()[0], "diff --git a/cfg/testcase.ini b/cfg/testcase.ini")
        self.assertEqual(file.data.splitlines()[-1], "+db = pyunit")
        self.assertEqual(file.insert_count, 2)
        self.assertEqual(file.delete_count, 1)

    def test_simple_diff(self):
        """Testing parsing simple Git diff"""
        diff = self._read_fixture("git_simple.diff")

        file = self._get_file_in_diff(diff)
        self.assertEqual(file.origFile, "cfg/testcase.ini")
        self.assertEqual(file.newFile, "cfg/testcase.ini")
        self.assertEqual(file.origInfo, "cc18ec8")
        self.assertEqual(file.newInfo, "5e70b73")
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertEqual(len(file.data), 249)
        self.assertEqual(file.data.splitlines()[0], "diff --git a/cfg/testcase.ini b/cfg/testcase.ini")
        self.assertEqual(file.data.splitlines()[-1], "+db = pyunit")
        self.assertEqual(file.insert_count, 2)
        self.assertEqual(file.delete_count, 1)

    def test_diff_with_unicode(self):
        """Testing parsing Git diff with unicode characters"""
        diff = (
            "diff --git a/cfg/téstcase.ini b/cfg/téstcase.ini\n"
            "index cc18ec8..5e70b73 100644\n"
            "--- a/cfg/téstcase.ini\n"
            "+++ b/cfg/téstcase.ini\n"
            "@@ -1,6 +1,7 @@\n"
            "+blah blah blah\n"
            " [mysql]\n"
            " hóst = localhost\n"
            " pórt = 3306\n"
            " user = user\n"
            " pass = pass\n"
            "-db = pyunít\n"
            "+db = pyunít\n"
        ).encode("utf-8")

        file = self._get_file_in_diff(diff)
        self.assertEqual(file.origFile, "cfg/téstcase.ini")
        self.assertEqual(file.newFile, "cfg/téstcase.ini")
        self.assertEqual(file.origInfo, "cc18ec8")
        self.assertEqual(file.newInfo, "5e70b73")
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertEqual(file.data.splitlines()[0].decode("utf-8"), "diff --git a/cfg/téstcase.ini b/cfg/téstcase.ini")
        self.assertEqual(file.data.splitlines()[-1].decode("utf-8"), "+db = pyunít")
        self.assertEqual(file.insert_count, 2)
        self.assertEqual(file.delete_count, 1)

    def test_diff_with_tabs_after_filename(self):
        """Testing parsing Git diffs with tabs after the filename"""
        diff = (
            b"diff --git a/README b/README\n"
            b"index 712544e4343bf04967eb5ea80257f6c64d6f42c7.."
            b"f88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1 100644\n"
            b"--- a/README\t\n"
            b"+++ b/README\t\n"
            b"@ -1,1 +1,1 @@\n"
            b"-blah blah\n"
            b"+blah\n"
            b"-\n"
            b"1.7.1\n"
        )

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(files[0].origFile, "README")
        self.assertEqual(files[0].newFile, "README")
        self.assertEqual(files[0].origInfo, "712544e4343bf04967eb5ea80257f6c64d6f42c7")
        self.assertEqual(files[0].newInfo, "f88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1")
        self.assertEqual(files[0].data, diff)
        self.assertEqual(files[0].insert_count, 1)
        self.assertEqual(files[0].delete_count, 2)

    def test_new_file_diff(self):
        """Testing parsing Git diff with new file"""
        diff = self._read_fixture("git_newfile.diff")

        file = self._get_file_in_diff(diff)
        self.assertEqual(file.origFile, "IAMNEW")
        self.assertEqual(file.newFile, "IAMNEW")
        self.assertEqual(file.origInfo, PRE_CREATION)
        self.assertEqual(file.newInfo, "e69de29")
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertEqual(len(file.data), 123)
        self.assertEqual(file.data.splitlines()[0], "diff --git a/IAMNEW b/IAMNEW")
        self.assertEqual(file.data.splitlines()[-1], "+Hello")
        self.assertEqual(file.insert_count, 1)
        self.assertEqual(file.delete_count, 0)

    def test_new_file_no_content_diff(self):
        """Testing parsing Git diff new file, no content"""
        diff = self._read_fixture("git_newfile_nocontent.diff")
        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)

        file = self._get_file_in_diff(diff)
        self.assertEqual(file.origFile, "newfile")
        self.assertEqual(file.newFile, "newfile")
        self.assertEqual(file.origInfo, PRE_CREATION)
        self.assertEqual(file.newInfo, "e69de29")
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        lines = file.data.splitlines()
        self.assertEqual(len(lines), 3)
        self.assertEqual(lines[0], "diff --git a/newfile b/newfile")
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_new_file_no_content_with_following_diff(self):
        """Testing parsing Git diff new file, no content, with following"""
        diff = self._read_fixture("git_newfile_nocontent2.diff")
        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 2)

        self.assertEqual(files[0].origFile, "newfile")
        self.assertEqual(files[0].newFile, "newfile")
        self.assertEqual(files[0].origInfo, PRE_CREATION)
        self.assertEqual(files[0].newInfo, "e69de29")
        self.assertFalse(files[0].binary)
        self.assertFalse(files[0].deleted)
        lines = files[0].data.splitlines()
        self.assertEqual(len(lines), 3)
        self.assertEqual(lines[0], "diff --git a/newfile b/newfile")
        self.assertEqual(files[0].insert_count, 0)
        self.assertEqual(files[0].delete_count, 0)

        self.assertEqual(files[1].origFile, "cfg/testcase.ini")
        self.assertEqual(files[1].newFile, "cfg/testcase.ini")
        self.assertEqual(files[1].origInfo, "cc18ec8")
        self.assertEqual(files[1].newInfo, "5e70b73")
        lines = files[1].data.splitlines()
        self.assertEqual(len(lines), 13)
        self.assertEqual(lines[0], "diff --git a/cfg/testcase.ini b/cfg/testcase.ini")
        self.assertEqual(lines[-1], "+db = pyunit")
        self.assertEqual(files[1].insert_count, 2)
        self.assertEqual(files[1].delete_count, 1)

    def test_del_file_diff(self):
        """Testing parsing Git diff with deleted file"""
        diff = self._read_fixture("git_delfile.diff")

        file = self._get_file_in_diff(diff)
        self.assertEqual(file.origFile, "OLDFILE")
        self.assertEqual(file.newFile, "OLDFILE")
        self.assertEqual(file.origInfo, "8ebcb01")
        self.assertEqual(file.newInfo, "0000000")
        self.assertFalse(file.binary)
        self.assertTrue(file.deleted)
        self.assertEqual(len(file.data), 132)
        self.assertEqual(file.data.splitlines()[0], "diff --git a/OLDFILE b/OLDFILE")
        self.assertEqual(file.data.splitlines()[-1], "-Goodbye")
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 1)

    def test_del_file_no_content_diff(self):
        """Testing parsing Git diff with deleted file, no content"""
        diff = (
            b"diff --git a/empty b/empty\n"
            b"deleted file mode 100644\n"
            b"index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391.."
            b"0000000000000000000000000000000000000000\n"
        )
        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)

        self.assertEqual(files[0].origFile, "empty")
        self.assertEqual(files[0].newFile, "empty")
        self.assertEqual(files[0].origInfo, "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391")
        self.assertEqual(files[0].newInfo, "0000000000000000000000000000000000000000")
        self.assertFalse(files[0].binary)
        self.assertTrue(files[0].deleted)
        self.assertEqual(len(files[0].data), 141)
        self.assertEqual(files[0].data.splitlines()[0], "diff --git a/empty b/empty")
        self.assertEqual(files[0].insert_count, 0)
        self.assertEqual(files[0].delete_count, 0)

    def test_del_file_no_content_with_following_diff(self):
        """Testing parsing Git diff with deleted file, no content, with
        following
        """
        diff = (
            b"diff --git a/empty b/empty\n"
            b"deleted file mode 100644\n"
            b"index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391.."
            b"0000000000000000000000000000000000000000\n"
            b"diff --git a/foo/bar b/foo/bar\n"
            b"index 484ba93ef5b0aed5b72af8f4e9dc4cfd10ef1a81.."
            b"0ae4095ddfe7387d405bd53bd59bbb5d861114c5 100644\n"
            b"--- a/foo/bar\n"
            b"+++ b/foo/bar\n"
            b"@@ -1 +1,2 @@\n"
            b"+Hello!\n"
            b"blah\n"
        )
        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 2)

        self.assertEqual(files[0].origFile, "empty")
        self.assertEqual(files[0].newFile, "empty")
        self.assertEqual(files[0].origInfo, "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391")
        self.assertEqual(files[0].newInfo, "0000000000000000000000000000000000000000")
        self.assertFalse(files[0].binary)
        self.assertTrue(files[0].deleted)
        self.assertEqual(len(files[0].data), 141)
        self.assertEqual(files[0].data.splitlines()[0], "diff --git a/empty b/empty")
        self.assertEqual(files[0].insert_count, 0)
        self.assertEqual(files[0].delete_count, 0)

        self.assertEqual(files[1].origFile, "foo/bar")
        self.assertEqual(files[1].newFile, "foo/bar")
        self.assertEqual(files[1].origInfo, "484ba93ef5b0aed5b72af8f4e9dc4cfd10ef1a81")
        self.assertEqual(files[1].newInfo, "0ae4095ddfe7387d405bd53bd59bbb5d861114c5")
        self.assertFalse(files[1].binary)
        self.assertFalse(files[1].deleted)
        lines = files[1].data.splitlines()
        self.assertEqual(len(lines), 7)
        self.assertEqual(lines[0], "diff --git a/foo/bar b/foo/bar")
        self.assertEqual(lines[5], "+Hello!")
        self.assertEqual(files[1].insert_count, 1)
        self.assertEqual(files[1].delete_count, 0)

    def test_binary_diff(self):
        """Testing parsing Git diff with binary"""
        diff = self._read_fixture("git_binary.diff")

        file = self._get_file_in_diff(diff)
        self.assertEqual(file.origFile, "pysvn-1.5.1.tar.gz")
        self.assertEqual(file.newFile, "pysvn-1.5.1.tar.gz")
        self.assertEqual(file.origInfo, PRE_CREATION)
        self.assertEqual(file.newInfo, "86b520c")
        self.assertTrue(file.binary)
        self.assertFalse(file.deleted)
        lines = file.data.splitlines()
        self.assertEqual(len(lines), 4)
        self.assertEqual(lines[0], "diff --git a/pysvn-1.5.1.tar.gz b/pysvn-1.5.1.tar.gz")
        self.assertEqual(lines[3], "Binary files /dev/null and b/pysvn-1.5.1.tar.gz differ")
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_complex_diff(self):
        """Testing parsing Git diff with existing and new files"""
        diff = self._read_fixture("git_complex.diff")
        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 7)
        self.assertEqual(files[0].origFile, "cfg/testcase.ini")
        self.assertEqual(files[0].newFile, "cfg/testcase.ini")
        self.assertEqual(files[0].origInfo, "5e35098")
        self.assertEqual(files[0].newInfo, "e254ef4")
        self.assertFalse(files[0].binary)
        self.assertFalse(files[0].deleted)
        self.assertEqual(files[0].insert_count, 2)
        self.assertEqual(files[0].delete_count, 1)
        self.assertEqual(len(files[0].data), 549)
        self.assertEqual(files[0].data.splitlines()[0], "diff --git a/cfg/testcase.ini b/cfg/testcase.ini")
        self.assertEqual(files[0].data.splitlines()[13], "         if isinstance(value, basestring):")

        self.assertEqual(files[1].origFile, "tests/models.py")
        self.assertEqual(files[1].newFile, "tests/models.py")
        self.assertEqual(files[1].origInfo, PRE_CREATION)
        self.assertEqual(files[1].newInfo, "e69de29")
        self.assertFalse(files[1].binary)
        self.assertFalse(files[1].deleted)
        self.assertEqual(files[1].insert_count, 0)
        self.assertEqual(files[1].delete_count, 0)
        lines = files[1].data.splitlines()
        self.assertEqual(len(lines), 3)
        self.assertEqual(lines[0], "diff --git a/tests/models.py b/tests/models.py")

        self.assertEqual(files[2].origFile, "tests/tests.py")
        self.assertEqual(files[2].newFile, "tests/tests.py")
        self.assertEqual(files[2].origInfo, PRE_CREATION)
        self.assertEqual(files[2].newInfo, "e279a06")
        self.assertFalse(files[2].binary)
        self.assertFalse(files[2].deleted)
        self.assertEqual(files[2].insert_count, 2)
        self.assertEqual(files[2].delete_count, 0)
        lines = files[2].data.splitlines()
        self.assertEqual(len(lines), 8)
        self.assertEqual(lines[0], "diff --git a/tests/tests.py b/tests/tests.py")
        self.assertEqual(lines[7], "+This is some new content")

        self.assertEqual(files[3].origFile, "pysvn-1.5.1.tar.gz")
        self.assertEqual(files[3].newFile, "pysvn-1.5.1.tar.gz")
        self.assertEqual(files[3].origInfo, PRE_CREATION)
        self.assertEqual(files[3].newInfo, "86b520c")
        self.assertTrue(files[3].binary)
        self.assertFalse(files[3].deleted)
        self.assertEqual(files[3].insert_count, 0)
        self.assertEqual(files[3].delete_count, 0)
        lines = files[3].data.splitlines()
        self.assertEqual(len(lines), 4)
        self.assertEqual(lines[0], "diff --git a/pysvn-1.5.1.tar.gz b/pysvn-1.5.1.tar.gz")
        self.assertEqual(lines[3], "Binary files /dev/null and b/pysvn-1.5.1.tar.gz " "differ")

        self.assertEqual(files[4].origFile, "readme")
        self.assertEqual(files[4].newFile, "readme")
        self.assertEqual(files[4].origInfo, "5e35098")
        self.assertEqual(files[4].newInfo, "e254ef4")
        self.assertFalse(files[4].binary)
        self.assertFalse(files[4].deleted)
        self.assertEqual(files[4].insert_count, 1)
        self.assertEqual(files[4].delete_count, 1)
        lines = files[4].data.splitlines()
        self.assertEqual(len(lines), 7)
        self.assertEqual(lines[0], "diff --git a/readme b/readme")
        self.assertEqual(lines[6], "+Hello there")

        self.assertEqual(files[5].origFile, "OLDFILE")
        self.assertEqual(files[5].newFile, "OLDFILE")
        self.assertEqual(files[5].origInfo, "8ebcb01")
        self.assertEqual(files[5].newInfo, "0000000")
        self.assertFalse(files[5].binary)
        self.assertTrue(files[5].deleted)
        self.assertEqual(files[5].insert_count, 0)
        self.assertEqual(files[5].delete_count, 1)
        lines = files[5].data.splitlines()
        self.assertEqual(len(lines), 7)
        self.assertEqual(lines[0], "diff --git a/OLDFILE b/OLDFILE")
        self.assertEqual(lines[6], "-Goodbye")

        self.assertEqual(files[6].origFile, "readme2")
        self.assertEqual(files[6].newFile, "readme2")
        self.assertEqual(files[6].origInfo, "5e43098")
        self.assertEqual(files[6].newInfo, "e248ef4")
        self.assertFalse(files[6].binary)
        self.assertFalse(files[6].deleted)
        self.assertEqual(files[6].insert_count, 1)
        self.assertEqual(files[6].delete_count, 1)
        lines = files[6].data.splitlines()
        self.assertEqual(len(lines), 7)
        self.assertEqual(lines[0], "diff --git a/readme2 b/readme2")
        self.assertEqual(lines[6], "+Hello there")

    def test_parse_diff_with_index_range(self):
        """Testing Git diff parsing with an index range"""
        diff = (
            b"diff --git a/foo/bar b/foo/bar2\n"
            b"similarity index 88%\n"
            b"rename from foo/bar\n"
            b"rename to foo/bar2\n"
            b"index 612544e4343bf04967eb5ea80257f6c64d6f42c7.."
            b"e88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1 100644\n"
            b"--- a/foo/bar\n"
            b"+++ b/foo/bar2\n"
            b"@ -1,1 +1,1 @@\n"
            b"-blah blah\n"
            b"+blah\n"
        )
        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)
        self.assertEqual(files[0].origFile, "foo/bar")
        self.assertEqual(files[0].newFile, "foo/bar2")
        self.assertEqual(files[0].origInfo, "612544e4343bf04967eb5ea80257f6c64d6f42c7")
        self.assertEqual(files[0].newInfo, "e88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1")
        self.assertEqual(files[0].insert_count, 1)
        self.assertEqual(files[0].delete_count, 1)

    def test_parse_diff_with_deleted_binary_files(self):
        """Testing Git diff parsing with deleted binary files"""
        diff = (
            b"diff --git a/foo.bin b/foo.bin\n"
            b"deleted file mode 100644\n"
            b"Binary file foo.bin has changed\n"
            b"diff --git a/bar.bin b/bar.bin\n"
            b"deleted file mode 100644\n"
            b"Binary file bar.bin has changed\n"
        )
        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 2)
        self.assertEqual(files[0].origFile, "foo.bin")
        self.assertEqual(files[0].newFile, "foo.bin")
        self.assertEqual(files[0].binary, True)
        self.assertEqual(files[0].deleted, True)
        self.assertEqual(files[0].insert_count, 0)
        self.assertEqual(files[0].delete_count, 0)
        self.assertEqual(files[1].origFile, "bar.bin")
        self.assertEqual(files[1].newFile, "bar.bin")
        self.assertEqual(files[1].binary, True)
        self.assertEqual(files[1].deleted, True)
        self.assertEqual(files[1].insert_count, 0)
        self.assertEqual(files[1].delete_count, 0)

    def test_parse_diff_with_all_headers(self):
        """Testing Git diff parsing and preserving all headers"""
        preamble = (
            b"From 38d8fa94a9aa0c5b27943bec31d94e880165f1e0 Mon Sep "
            b"17 00:00:00 2001\n"
            b"From: Example Joe <*****@*****.**>\n"
            b"Date: Thu, 5 Apr 2012 00:41:12 -0700\n"
            b"Subject: [PATCH 1/1] Sample patch.\n"
            b"\n"
            b"This is a test summary.\n"
            b"\n"
            b"With a description.\n"
            b"---\n"
            b" foo/bar |   2 -+n"
            b" README  |   2 -+n"
            b" 2 files changed, 2 insertions(+), 2 deletions(-)\n"
            b"\n"
        )
        diff1 = (
            b"diff --git a/foo/bar b/foo/bar2\n"
            b"index 612544e4343bf04967eb5ea80257f6c64d6f42c7.."
            b"e88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1 100644\n"
            b"--- a/foo/bar\n"
            b"+++ b/foo/bar2\n"
            b"@ -1,1 +1,1 @@\n"
            b"-blah blah\n"
            b"+blah\n"
        )
        diff2 = (
            b"diff --git a/README b/README\n"
            b"index 712544e4343bf04967eb5ea80257f6c64d6f42c7.."
            b"f88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1 100644\n"
            b"--- a/README\n"
            b"+++ b/README\n"
            b"@ -1,1 +1,1 @@\n"
            b"-blah blah\n"
            b"+blah\n"
            b"-\n"
            b"1.7.1\n"
        )
        diff = preamble + diff1 + diff2

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 2)
        self.assertEqual(files[0].origFile, "foo/bar")
        self.assertEqual(files[0].newFile, "foo/bar2")
        self.assertEqual(files[0].origInfo, "612544e4343bf04967eb5ea80257f6c64d6f42c7")
        self.assertEqual(files[0].newInfo, "e88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1")
        self.assertEqual(files[0].data, preamble + diff1)
        self.assertEqual(files[0].insert_count, 1)
        self.assertEqual(files[0].delete_count, 1)

        self.assertEqual(files[1].origFile, "README")
        self.assertEqual(files[1].newFile, "README")
        self.assertEqual(files[1].origInfo, "712544e4343bf04967eb5ea80257f6c64d6f42c7")
        self.assertEqual(files[1].newInfo, "f88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1")
        self.assertEqual(files[1].data, diff2)
        self.assertEqual(files[1].insert_count, 1)
        self.assertEqual(files[1].delete_count, 2)

    def test_parse_diff_revision(self):
        """Testing Git revision number parsing"""
        self.assertEqual(self.tool.parse_diff_revision("doc/readme", "bf544ea"), ("doc/readme", "bf544ea"))
        self.assertEqual(self.tool.parse_diff_revision("/dev/null", "bf544ea"), ("/dev/null", PRE_CREATION))
        self.assertEqual(self.tool.parse_diff_revision("/dev/null", "0000000"), ("/dev/null", PRE_CREATION))

    def test_parse_diff_with_copy_and_rename_same_file(self):
        """Testing Git diff parsing with copy and rename of same file"""
        diff = (
            b"diff --git a/foo/bar b/foo/bar2\n"
            b"similarity index 100%\n"
            b"copy from foo/bar\n"
            b"copy to foo/bar2\n"
            b"diff --git a/foo/bar b/foo/bar3\n"
            b"similarity index 92%\n"
            b"rename from foo/bar\n"
            b"rename to foo/bar3\n"
            b"index 612544e4343bf04967eb5ea80257f6c64d6f42c7.."
            b"e88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1 100644\n"
            b"--- a/foo/bar\n"
            b"+++ b/foo/bar3\n"
            b"@@ -1,1 +1,1 @@\n"
            b"-blah blah\n"
            b"+blah\n"
        )
        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 2)

        f = files[0]
        self.assertEqual(f.origFile, "foo/bar")
        self.assertEqual(f.newFile, "foo/bar2")
        self.assertEqual(f.origInfo, "")
        self.assertEqual(f.newInfo, "")
        self.assertEqual(f.insert_count, 0)
        self.assertEqual(f.delete_count, 0)
        self.assertFalse(f.moved)
        self.assertTrue(f.copied)

        f = files[1]
        self.assertEqual(f.origFile, "foo/bar")
        self.assertEqual(f.newFile, "foo/bar3")
        self.assertEqual(f.origInfo, "612544e4343bf04967eb5ea80257f6c64d6f42c7")
        self.assertEqual(f.newInfo, "e88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1")
        self.assertEqual(f.insert_count, 1)
        self.assertEqual(f.delete_count, 1)
        self.assertTrue(f.moved)
        self.assertFalse(f.copied)

    def test_parse_diff_with_mode_change_and_rename(self):
        """Testing Git diff parsing with mode change and rename"""
        diff = (
            b"diff --git a/foo/bar b/foo/bar2\n"
            b"old mode 100755\n"
            b"new mode 100644\n"
            b"similarity index 99%\n"
            b"rename from foo/bar\n"
            b"rename to foo/bar2\n"
            b"index 612544e4343bf04967eb5ea80257f6c64d6f42c7.."
            b"e88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1\n"
            b"--- a/foo/bar\n"
            b"+++ b/foo/bar2\n"
            b"@@ -1,1 +1,1 @@\n"
            b"-blah blah\n"
            b"+blah\n"
        )
        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)

        f = files[0]
        self.assertEqual(f.origFile, "foo/bar")
        self.assertEqual(f.newFile, "foo/bar2")
        self.assertEqual(f.origInfo, "612544e4343bf04967eb5ea80257f6c64d6f42c7")
        self.assertEqual(f.newInfo, "e88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1")
        self.assertEqual(f.insert_count, 1)
        self.assertEqual(f.delete_count, 1)
        self.assertTrue(f.moved)
        self.assertFalse(f.copied)

    def test_diff_git_line_without_a_b(self):
        """Testing parsing Git diff with deleted file without a/ and
        b/ filename prefixes
        """
        diff = (
            b"diff --git foo foo\n"
            b"deleted file mode 100644\n"
            b"index 612544e4343bf04967eb5ea80257f6c64d6f42c7.."
            b"0000000000000000000000000000000000000000\n"
        )

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)

        f = files[0]
        self.assertEqual(f.origFile, "foo")
        self.assertEqual(f.newFile, "foo")
        self.assertTrue(f.deleted)

    def test_diff_git_line_without_a_b_quotes(self):
        """Testing parsing Git diff with deleted file without a/ and
        b/ filename prefixes and with quotes
        """
        diff = (
            b'diff --git "foo" "foo"\n'
            b"deleted file mode 100644\n"
            b"index 612544e4343bf04967eb5ea80257f6c64d6f42c7.."
            b"0000000000000000000000000000000000000000\n"
        )

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)

        f = files[0]
        self.assertEqual(f.origFile, "foo")
        self.assertEqual(f.newFile, "foo")
        self.assertTrue(f.deleted)

    def test_diff_git_line_without_a_b_and_spaces(self):
        """Testing parsing Git diff with deleted file without a/ and
        b/ filename prefixes and with spaces
        """
        diff = (
            b"diff --git foo bar1 foo bar1\n"
            b"deleted file mode 100644\n"
            b"index 612544e4343bf04967eb5ea80257f6c64d6f42c7.."
            b"0000000000000000000000000000000000000000\n"
        )

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)

        f = files[0]
        self.assertEqual(f.origFile, "foo bar1")
        self.assertEqual(f.newFile, "foo bar1")
        self.assertTrue(f.deleted)

    def test_diff_git_line_without_a_b_and_spaces_quotes(self):
        """Testing parsing Git diff with deleted file without a/ and
        b/ filename prefixes and with space and quotes
        """
        diff = (
            b'diff --git "foo bar1" "foo bar1"\n'
            b"deleted file mode 100644\n"
            b"index 612544e4343bf04967eb5ea80257f6c64d6f42c7.."
            b"0000000000000000000000000000000000000000\n"
        )

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)

        f = files[0]
        self.assertEqual(f.origFile, "foo bar1")
        self.assertEqual(f.newFile, "foo bar1")

    def test_diff_git_line_without_a_b_and_spaces_changed(self):
        """Testing parsing Git diff with deleted file without a/ and
        b/ filename prefixes and with spaces, with filename changes
        """
        diff = (
            b"diff --git foo bar1 foo bar2\n"
            b"deleted file mode 100644\n"
            b"index 612544e4343bf04967eb5ea80257f6c64d6f42c7.."
            b"0000000000000000000000000000000000000000\n"
        )

        with self.assertRaises(DiffParserError) as cm:
            self.tool.get_parser(diff).parse()

        self.assertTrue(six.text_type(cm.exception).startswith('Unable to parse the "diff --git" line'))

    def test_diff_git_line_without_a_b_and_spaces_quotes_changed(self):
        """Testing parsing Git diff with deleted file without a/ and
        b/ filename prefixes and with spaces and quotes, with filename
        changes
        """
        diff = (
            b'diff --git "foo bar1" "foo bar2"\n'
            b"deleted file mode 100644\n"
            b"index 612544e4343bf04967eb5ea80257f6c64d6f42c7.."
            b"0000000000000000000000000000000000000000\n"
            b'diff --git "foo bar1" foo\n'
            b"deleted file mode 100644\n"
            b"index 612544e4343bf04967eb5ea80257f6c64d6f42c7.."
            b"0000000000000000000000000000000000000000\n"
            b'diff --git foo "foo bar1"\n'
            b"deleted file mode 100644\n"
            b"index 612544e4343bf04967eb5ea80257f6c64d6f42c7.."
            b"0000000000000000000000000000000000000000\n"
        )

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 3)

        f = files[0]
        self.assertEqual(f.origFile, "foo bar1")
        self.assertEqual(f.newFile, "foo bar2")
        self.assertTrue(f.deleted)

        f = files[1]
        self.assertEqual(f.origFile, "foo bar1")
        self.assertEqual(f.newFile, "foo")

        f = files[2]
        self.assertEqual(f.origFile, "foo")
        self.assertEqual(f.newFile, "foo bar1")

    def test_file_exists(self):
        """Testing GitTool.file_exists"""
        self.assertTrue(self.tool.file_exists("readme", "e965047"))
        self.assertTrue(self.tool.file_exists("readme", "d6613f5"))

        self.assertTrue(not self.tool.file_exists("readme", PRE_CREATION))
        self.assertTrue(not self.tool.file_exists("readme", "fffffff"))
        self.assertTrue(not self.tool.file_exists("readme2", "fffffff"))

        # these sha's are valid, but commit and tree objects, not blobs
        self.assertTrue(not self.tool.file_exists("readme", "a62df6c"))
        self.assertTrue(not self.tool.file_exists("readme2", "ccffbb4"))

    def test_get_file(self):
        """Testing GitTool.get_file"""
        self.assertEqual(self.tool.get_file("readme", PRE_CREATION), b"")
        self.assertTrue(isinstance(self.tool.get_file("readme", "e965047"), bytes))
        self.assertEqual(self.tool.get_file("readme", "e965047"), b"Hello\n")
        self.assertEqual(self.tool.get_file("readme", "d6613f5"), b"Hello there\n")

        self.assertEqual(self.tool.get_file("readme"), b"Hello there\n")

        self.assertRaises(SCMError, lambda: self.tool.get_file(""))

        self.assertRaises(FileNotFoundError, lambda: self.tool.get_file("", "0000000"))
        self.assertRaises(FileNotFoundError, lambda: self.tool.get_file("hello", "0000000"))
        self.assertRaises(FileNotFoundError, lambda: self.tool.get_file("readme", "0000000"))

    def test_parse_diff_revision_with_remote_and_short_SHA1_error(self):
        """Testing GitTool.parse_diff_revision with remote files and short
        SHA1 error
        """
        self.assertRaises(ShortSHA1Error, lambda: self.remote_tool.parse_diff_revision("README", "d7e96b3"))

    def test_get_file_with_remote_and_short_SHA1_error(self):
        """Testing GitTool.get_file with remote files and short SHA1 error"""
        self.assertRaises(ShortSHA1Error, lambda: self.remote_tool.get_file("README", "d7e96b3"))

    def test_valid_repository_https_username(self):
        """Testing GitClient.is_valid_repository with an HTTPS URL and external
        credentials
        """
        client = GitClient("https://example.com/test.git", username="******", password="******")

        self.spy_on(client._run_git)
        client.is_valid_repository()

        self.assertEqual(
            client._run_git.calls[0].args[0], ["ls-remote", "https://*****:*****@example.com/test.git", "HEAD"]
        )

    def test_raw_file_url_error(self):
        """Testing Repository.get_file re-fetches when raw file URL changes"""
        self.spy_on(self.remote_repository._get_file_uncached, call_fake=lambda a, b, x, y, z: "first")
        self.assertEqual(self.remote_repository.get_file("PATH", "d7e96b3"), "first")
        # Ensure output of fake result matches.
        self.remote_repository._get_file_uncached.unspy()
        self.spy_on(self.remote_repository._get_file_uncached, call_fake=lambda a, b, x, y, z: "second")
        # Grab from cache when no changes and change fake result to confirm
        # it is not called.
        self.assertEqual(self.remote_repository.get_file("PATH", "d7e96b3"), "first")
        self.remote_repository.raw_file_url = "http://github.com/api/v2/yaml/blob/show/reviewboard/<revision>"
        # When raw_file_url changed, do not grab from cache and ensure output
        # equals second fake value.
        self.assertEqual(self.remote_repository.get_file("PATH", "d7e96b3"), "second")

    def test_get_file_exists_caching_with_raw_url(self):
        """Testing Repository.get_file_exists properly checks file existence in
        repository or cache when raw file URL changes
        """
        self.spy_on(self.remote_repository._get_file_exists_uncached, call_fake=lambda a, b, x, y, z: True)
        # Use spy to put key into cache
        self.assertTrue(self.remote_repository.get_file_exists("PATH", "d7e96b3"))
        # Remove spy to ensure key is still in cache without needing spy
        self.remote_repository._get_file_exists_uncached.unspy()
        self.assertTrue(self.remote_repository.get_file_exists("PATH", "d7e96b3"))
        self.remote_repository.raw_file_url = "http://github.com/api/v2/yaml/blob/show/reviewboard/<revision>"
        # Does not exist when raw_file_url changed because it is not cached.
        self.assertFalse(self.remote_repository.get_file_exists("PATH", "d7e96b3"))
Ejemplo n.º 45
0
class PerforceTests(SCMTestCase):
    """Unit tests for perforce.

    This uses the open server at public.perforce.com to test various
    pieces.  Because we have no control over things like pending
    changesets, not everything can be tested.
    """

    fixtures = ['test_scmtools']

    def setUp(self):
        super(PerforceTests, self).setUp()

        self.repository = Repository(name='Perforce.com',
                                     path='public.perforce.com:1666',
                                     tool=Tool.objects.get(name='Perforce'))

        try:
            self.tool = self.repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest('perforce/p4python is not installed')

    @online_only
    def test_changeset(self):
        """Testing PerforceTool.get_changeset"""
        desc = self.tool.get_changeset(157)
        self.assertEqual(desc.changenum, 157)
        self.assertEqual(type(desc.description), six.text_type)
        self.assertEqual(md5(desc.description.encode('utf-8')).hexdigest(),
                         'b7eff0ca252347cc9b09714d07397e64')

        expected_files = [
            '//public/perforce/api/python/P4Client/P4Clientmodule.cc',
            '//public/perforce/api/python/P4Client/p4.py',
            '//public/perforce/api/python/P4Client/review.py',
            '//public/perforce/python/P4Client/P4Clientmodule.cc',
            '//public/perforce/python/P4Client/p4.py',
            '//public/perforce/python/P4Client/review.py',
        ]

        for file, expected in zip_longest(desc.files, expected_files):
            self.assertEqual(file, expected)

        self.assertEqual(md5(desc.summary.encode('utf-8')).hexdigest(),
                         '99a335676b0e5821ffb2f7469d4d7019')

    @online_only
    def test_encoding(self):
        """Testing PerforceTool.get_changeset with a specified encoding"""
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          encoding='utf8')
        tool = repo.get_scmtool()

        try:
            tool.get_changeset(157)
            self.fail('Expected an error about unicode-enabled servers. Did '
                      'perforce.com turn on unicode for public.perforce.com?')
        except SCMError as e:
            # public.perforce.com doesn't have unicode enabled. Getting this
            # error means we at least passed the charset through correctly
            # to the p4 client.
            self.assertTrue('clients require a unicode enabled server' in
                            six.text_type(e))

    @online_only
    def test_changeset_broken(self):
        """Testing PerforceTool.get_changeset error conditions"""
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          username='******',
                          password='******')

        try:
            tool = repo.get_scmtool()
        except ImportError:
            raise nose.SkipTest('perforce/p4python is not installed')

        self.assertRaises(AuthenticationError,
                          lambda: tool.get_changeset(157))

        repo = Repository(name='localhost:1',
                          path='localhost:1',
                          tool=Tool.objects.get(name='Perforce'))

        tool = repo.get_scmtool()
        self.assertRaises(RepositoryNotFoundError,
                          lambda: tool.get_changeset(1))

    @online_only
    def test_get_file(self):
        """Testing PerforceTool.get_file"""
        file = self.tool.get_file('//depot/foo', PRE_CREATION)
        self.assertEqual(file, b'')

        file = self.tool.get_file(
            '//public/perforce/api/python/P4Client/p4.py', 1)
        self.assertEqual(md5(file).hexdigest(),
                         '227bdd87b052fcad9369e65c7bf23fd0')

    @online_only
    def test_custom_host(self):
        """Testing Perforce client initialization with a custom P4HOST"""
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          encoding='utf8')
        repo.extra_data['p4_host'] = 'my-custom-host'

        tool = repo.get_scmtool()

        with tool.client._connect():
            self.assertEqual(tool.client.p4.host, 'my-custom-host')

    def test_empty_diff(self):
        """Testing Perforce empty diff parsing"""
        diff = b'==== //depot/foo/proj/README#2 ==M== /src/proj/README ====\n'

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, '//depot/foo/proj/README')
        self.assertEqual(file.origInfo, '//depot/foo/proj/README#2')
        self.assertEqual(file.newFile, '/src/proj/README')
        self.assertEqual(file.newInfo, '')
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertFalse(file.moved)
        self.assertEqual(file.data, diff)
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_binary_diff(self):
        """Testing Perforce binary diff parsing"""
        diff = (b'==== //depot/foo/proj/test.png#1 ==A== /src/proj/test.png '
                b'====\nBinary files /tmp/foo and /src/proj/test.png differ\n')

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, '//depot/foo/proj/test.png')
        self.assertEqual(file.origInfo, '//depot/foo/proj/test.png#1')
        self.assertEqual(file.newFile, '/src/proj/test.png')
        self.assertEqual(file.newInfo, '')
        self.assertEqual(file.data, diff)
        self.assertTrue(file.binary)
        self.assertFalse(file.deleted)
        self.assertFalse(file.moved)
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_deleted_diff(self):
        """Testing Perforce deleted diff parsing"""
        diff = (b'==== //depot/foo/proj/test.png#1 ==D== /src/proj/test.png '
                b'====\n')

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, '//depot/foo/proj/test.png')
        self.assertEqual(file.origInfo, '//depot/foo/proj/test.png#1')
        self.assertEqual(file.newFile, '/src/proj/test.png')
        self.assertEqual(file.newInfo, '')
        self.assertEqual(file.data, diff)
        self.assertFalse(file.binary)
        self.assertTrue(file.deleted)
        self.assertFalse(file.moved)
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_moved_file_diff(self):
        """Testing Perforce moved file diff parsing"""
        diff = (
            b'Moved from: //depot/foo/proj/test.txt\n'
            b'Moved to: //depot/foo/proj/test2.txt\n'
            b'--- //depot/foo/proj/test.txt  //depot/foo/proj/test.txt#2\n'
            b'+++ //depot/foo/proj/test2.txt  01-02-03 04:05:06\n'
            b'@@ -1 +1,2 @@\n'
            b'-test content\n'
            b'+updated test content\n'
            b'+added info\n'
        )

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, '//depot/foo/proj/test.txt')
        self.assertEqual(file.origInfo, '//depot/foo/proj/test.txt#2')
        self.assertEqual(file.newFile, '//depot/foo/proj/test2.txt')
        self.assertEqual(file.newInfo, '01-02-03 04:05:06')
        self.assertEqual(file.data, diff)
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertTrue(file.moved)
        self.assertEqual(file.data, diff)
        self.assertEqual(file.insert_count, 2)
        self.assertEqual(file.delete_count, 1)

    def test_moved_file_diff_no_changes(self):
        """Testing Perforce moved file diff parsing without changes"""
        diff = (b'==== //depot/foo/proj/test.png#5 ==MV== '
                b'//depot/foo/proj/test2.png ====\n')

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, '//depot/foo/proj/test.png')
        self.assertEqual(file.origInfo, '//depot/foo/proj/test.png#5')
        self.assertEqual(file.newFile, '//depot/foo/proj/test2.png')
        self.assertEqual(file.newInfo, '')
        self.assertEqual(file.data, diff)
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertTrue(file.moved)
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_empty_and_normal_diffs(self):
        """Testing Perforce empty and normal diff parsing"""
        diff1_text = (b'==== //depot/foo/proj/test.png#1 ==A== '
                      b'/src/proj/test.png ====\n')
        diff2_text = (b'--- test.c  //depot/foo/proj/test.c#2\n'
                      b'+++ test.c  01-02-03 04:05:06\n'
                      b'@@ -1 +1,2 @@\n'
                      b'-test content\n'
                      b'+updated test content\n'
                      b'+added info\n')
        diff = diff1_text + diff2_text

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 2)
        self.assertEqual(files[0].origFile, '//depot/foo/proj/test.png')
        self.assertEqual(files[0].origInfo, '//depot/foo/proj/test.png#1')
        self.assertEqual(files[0].newFile, '/src/proj/test.png')
        self.assertEqual(files[0].newInfo, '')
        self.assertFalse(files[0].binary)
        self.assertFalse(files[0].deleted)
        self.assertFalse(files[0].moved)
        self.assertEqual(files[0].data, diff1_text)
        self.assertEqual(files[0].insert_count, 0)
        self.assertEqual(files[0].delete_count, 0)

        self.assertEqual(files[1].origFile, 'test.c')
        self.assertEqual(files[1].origInfo, '//depot/foo/proj/test.c#2')
        self.assertEqual(files[1].newFile, 'test.c')
        self.assertEqual(files[1].newInfo, '01-02-03 04:05:06')
        self.assertFalse(files[1].binary)
        self.assertFalse(files[1].deleted)
        self.assertFalse(files[1].moved)
        self.assertEqual(files[1].data, diff2_text)
        self.assertEqual(files[1].insert_count, 2)
        self.assertEqual(files[1].delete_count, 1)

    def test_diff_file_normalization(self):
        """Testing perforce diff filename normalization"""
        parser = self.tool.get_parser('')
        self.assertEqual(parser.normalize_diff_filename('//depot/test'),
                         '//depot/test')

    def test_unicode_diff(self):
        """Testing Perforce diff parsing with unicode characters"""
        diff = ('--- tést.c  //depot/foo/proj/tést.c#2\n'
                '+++ tést.c  01-02-03 04:05:06\n'
                '@@ -1 +1,2 @@\n'
                '-tést content\n'
                '+updated test content\n'
                '+added info\n').encode('utf-8')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)
        self.assertEqual(files[0].origFile, 'tést.c')
        self.assertEqual(files[0].origInfo, '//depot/foo/proj/tést.c#2')
        self.assertEqual(files[0].newFile, 'tést.c')
        self.assertEqual(files[0].newInfo, '01-02-03 04:05:06')
        self.assertFalse(files[0].binary)
        self.assertFalse(files[0].deleted)
        self.assertFalse(files[0].moved)
        self.assertEqual(files[0].insert_count, 2)
        self.assertEqual(files[0].delete_count, 1)
Ejemplo n.º 46
0
class PerforceTests(SCMTestCase):
    """Unit tests for perforce.

    This uses the open server at public.perforce.com to test various
    pieces.  Because we have no control over things like pending
    changesets, not everything can be tested.
    """

    fixtures = ['test_scmtools']

    def setUp(self):
        super(PerforceTests, self).setUp()

        self.repository = Repository(name='Perforce.com',
                                     path='public.perforce.com:1666',
                                     tool=Tool.objects.get(name='Perforce'))

        try:
            self.tool = self.repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest('perforce/p4python is not installed')

    @online_only
    def test_changeset(self):
        """Testing PerforceTool.get_changeset"""
        desc = self.tool.get_changeset(157)
        self.assertEqual(desc.changenum, 157)
        self.assertEqual(type(desc.description), six.text_type)
        self.assertEqual(
            md5(desc.description.encode('utf-8')).hexdigest(),
            'b7eff0ca252347cc9b09714d07397e64')

        expected_files = [
            '//public/perforce/api/python/P4Client/P4Clientmodule.cc',
            '//public/perforce/api/python/P4Client/p4.py',
            '//public/perforce/api/python/P4Client/review.py',
            '//public/perforce/python/P4Client/P4Clientmodule.cc',
            '//public/perforce/python/P4Client/p4.py',
            '//public/perforce/python/P4Client/review.py',
        ]

        for file, expected in zip_longest(desc.files, expected_files):
            self.assertEqual(file, expected)

        self.assertEqual(
            md5(desc.summary.encode('utf-8')).hexdigest(),
            '99a335676b0e5821ffb2f7469d4d7019')

    @online_only
    def test_encoding(self):
        """Testing PerforceTool.get_changeset with a specified encoding"""
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          encoding='utf8')
        tool = repo.get_scmtool()

        try:
            tool.get_changeset(157)
            self.fail('Expected an error about unicode-enabled servers. Did '
                      'perforce.com turn on unicode for public.perforce.com?')
        except SCMError as e:
            # public.perforce.com doesn't have unicode enabled. Getting this
            # error means we at least passed the charset through correctly
            # to the p4 client.
            self.assertTrue(
                'clients require a unicode enabled server' in six.text_type(e))

    @online_only
    def test_changeset_broken(self):
        """Testing PerforceTool.get_changeset error conditions"""
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          username='******',
                          password='******')

        try:
            tool = repo.get_scmtool()
        except ImportError:
            raise nose.SkipTest('perforce/p4python is not installed')

        self.assertRaises(AuthenticationError, lambda: tool.get_changeset(157))

        repo = Repository(name='localhost:1',
                          path='localhost:1',
                          tool=Tool.objects.get(name='Perforce'))

        tool = repo.get_scmtool()
        self.assertRaises(RepositoryNotFoundError,
                          lambda: tool.get_changeset(1))

    @online_only
    def test_get_file(self):
        """Testing PerforceTool.get_file"""
        file = self.tool.get_file('//depot/foo', PRE_CREATION)
        self.assertEqual(file, b'')

        file = self.tool.get_file(
            '//public/perforce/api/python/P4Client/p4.py', 1)
        self.assertEqual(
            md5(file).hexdigest(), '227bdd87b052fcad9369e65c7bf23fd0')

    @online_only
    def test_custom_host(self):
        """Testing Perforce client initialization with a custom P4HOST"""
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          encoding='utf8')
        repo.extra_data['p4_host'] = 'my-custom-host'

        tool = repo.get_scmtool()

        with tool.client._connect():
            self.assertEqual(tool.client.p4.host, 'my-custom-host')

    def test_empty_diff(self):
        """Testing Perforce empty diff parsing"""
        diff = b'==== //depot/foo/proj/README#2 ==M== /src/proj/README ====\n'

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, '//depot/foo/proj/README')
        self.assertEqual(file.origInfo, '//depot/foo/proj/README#2')
        self.assertEqual(file.newFile, '/src/proj/README')
        self.assertEqual(file.newInfo, '')
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertFalse(file.moved)
        self.assertEqual(file.data, diff)
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_binary_diff(self):
        """Testing Perforce binary diff parsing"""
        diff = (b'==== //depot/foo/proj/test.png#1 ==A== /src/proj/test.png '
                b'====\nBinary files /tmp/foo and /src/proj/test.png differ\n')

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, '//depot/foo/proj/test.png')
        self.assertEqual(file.origInfo, '//depot/foo/proj/test.png#1')
        self.assertEqual(file.newFile, '/src/proj/test.png')
        self.assertEqual(file.newInfo, '')
        self.assertEqual(file.data, diff)
        self.assertTrue(file.binary)
        self.assertFalse(file.deleted)
        self.assertFalse(file.moved)
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_deleted_diff(self):
        """Testing Perforce deleted diff parsing"""
        diff = (b'==== //depot/foo/proj/test.png#1 ==D== /src/proj/test.png '
                b'====\n')

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, '//depot/foo/proj/test.png')
        self.assertEqual(file.origInfo, '//depot/foo/proj/test.png#1')
        self.assertEqual(file.newFile, '/src/proj/test.png')
        self.assertEqual(file.newInfo, '')
        self.assertEqual(file.data, diff)
        self.assertFalse(file.binary)
        self.assertTrue(file.deleted)
        self.assertFalse(file.moved)
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_moved_file_diff(self):
        """Testing Perforce moved file diff parsing"""
        diff = (b'Moved from: //depot/foo/proj/test.txt\n'
                b'Moved to: //depot/foo/proj/test2.txt\n'
                b'--- //depot/foo/proj/test.txt  //depot/foo/proj/test.txt#2\n'
                b'+++ //depot/foo/proj/test2.txt  01-02-03 04:05:06\n'
                b'@@ -1 +1,2 @@\n'
                b'-test content\n'
                b'+updated test content\n'
                b'+added info\n')

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, '//depot/foo/proj/test.txt')
        self.assertEqual(file.origInfo, '//depot/foo/proj/test.txt#2')
        self.assertEqual(file.newFile, '//depot/foo/proj/test2.txt')
        self.assertEqual(file.newInfo, '01-02-03 04:05:06')
        self.assertEqual(file.data, diff)
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertTrue(file.moved)
        self.assertEqual(file.data, diff)
        self.assertEqual(file.insert_count, 2)
        self.assertEqual(file.delete_count, 1)

    def test_moved_file_diff_no_changes(self):
        """Testing Perforce moved file diff parsing without changes"""
        diff = (b'==== //depot/foo/proj/test.png#5 ==MV== '
                b'//depot/foo/proj/test2.png ====\n')

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, '//depot/foo/proj/test.png')
        self.assertEqual(file.origInfo, '//depot/foo/proj/test.png#5')
        self.assertEqual(file.newFile, '//depot/foo/proj/test2.png')
        self.assertEqual(file.newInfo, '')
        self.assertEqual(file.data, diff)
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertTrue(file.moved)
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_empty_and_normal_diffs(self):
        """Testing Perforce empty and normal diff parsing"""
        diff1_text = (b'==== //depot/foo/proj/test.png#1 ==A== '
                      b'/src/proj/test.png ====\n')
        diff2_text = (b'--- test.c  //depot/foo/proj/test.c#2\n'
                      b'+++ test.c  01-02-03 04:05:06\n'
                      b'@@ -1 +1,2 @@\n'
                      b'-test content\n'
                      b'+updated test content\n'
                      b'+added info\n')
        diff = diff1_text + diff2_text

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 2)
        self.assertEqual(files[0].origFile, '//depot/foo/proj/test.png')
        self.assertEqual(files[0].origInfo, '//depot/foo/proj/test.png#1')
        self.assertEqual(files[0].newFile, '/src/proj/test.png')
        self.assertEqual(files[0].newInfo, '')
        self.assertFalse(files[0].binary)
        self.assertFalse(files[0].deleted)
        self.assertFalse(files[0].moved)
        self.assertEqual(files[0].data, diff1_text)
        self.assertEqual(files[0].insert_count, 0)
        self.assertEqual(files[0].delete_count, 0)

        self.assertEqual(files[1].origFile, 'test.c')
        self.assertEqual(files[1].origInfo, '//depot/foo/proj/test.c#2')
        self.assertEqual(files[1].newFile, 'test.c')
        self.assertEqual(files[1].newInfo, '01-02-03 04:05:06')
        self.assertFalse(files[1].binary)
        self.assertFalse(files[1].deleted)
        self.assertFalse(files[1].moved)
        self.assertEqual(files[1].data, diff2_text)
        self.assertEqual(files[1].insert_count, 2)
        self.assertEqual(files[1].delete_count, 1)

    def test_diff_file_normalization(self):
        """Testing perforce diff filename normalization"""
        parser = self.tool.get_parser('')
        self.assertEqual(parser.normalize_diff_filename('//depot/test'),
                         '//depot/test')

    def test_unicode_diff(self):
        """Testing Perforce diff parsing with unicode characters"""
        diff = ('--- tést.c  //depot/foo/proj/tést.c#2\n'
                '+++ tést.c  01-02-03 04:05:06\n'
                '@@ -1 +1,2 @@\n'
                '-tést content\n'
                '+updated test content\n'
                '+added info\n').encode('utf-8')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)
        self.assertEqual(files[0].origFile, 'tést.c')
        self.assertEqual(files[0].origInfo, '//depot/foo/proj/tést.c#2')
        self.assertEqual(files[0].newFile, 'tést.c')
        self.assertEqual(files[0].newInfo, '01-02-03 04:05:06')
        self.assertFalse(files[0].binary)
        self.assertFalse(files[0].deleted)
        self.assertFalse(files[0].moved)
        self.assertEqual(files[0].insert_count, 2)
        self.assertEqual(files[0].delete_count, 1)
Ejemplo n.º 47
0
class SubversionTests(DjangoTestCase):
    """Unit tests for subversion."""

    fixtures = ["test_scmtools.json"]

    def setUp(self):
        svn_repo_path = os.path.join(os.path.dirname(__file__), "testdata/svn_repo")
        self.repository = Repository(
            name="Subversion SVN", path="file://" + svn_repo_path, tool=Tool.objects.get(name="Subversion")
        )

        try:
            self.tool = self.repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest("pysvn is not installed")

    def testGetFile(self):
        """Testing SVNTool.get_file"""
        expected = (
            "include ../tools/Makefile.base-vars\nNAME = misc-docs\n"
            + "OUTNAME = svn-misc-docs\nINSTALL_DIR = $(DESTDIR)/usr/s"
            + "hare/doc/subversion\ninclude ../tools/Makefile.base-rul"
            + "es\n"
        )

        # There are 3 versions of this test in order to get 100% coverage of
        # the svn module.
        rev = Revision("2")
        file = "trunk/doc/misc-docs/Makefile"

        self.assertEqual(self.tool.get_file(file, rev), expected)

        self.assertEqual(self.tool.get_file("/" + file, rev), expected)

        self.assertEqual(self.tool.get_file(self.repository.path + "/" + file, rev), expected)

        self.assert_(self.tool.file_exists("trunk/doc/misc-docs/Makefile"))
        self.assert_(not self.tool.file_exists("trunk/doc/misc-docs/Makefile2"))

        self.assertRaises(FileNotFoundError, lambda: self.tool.get_file(""))

        self.assertRaises(FileNotFoundError, lambda: self.tool.get_file("hello", PRE_CREATION))

    def testRevisionParsing(self):
        """Testing revision number parsing"""
        self.assertEqual(self.tool.parse_diff_revision("", "(working copy)")[1], HEAD)
        self.assertEqual(self.tool.parse_diff_revision("", "   (revision 0)")[1], PRE_CREATION)

        self.assertEqual(self.tool.parse_diff_revision("", "(revision 1)")[1], "1")
        self.assertEqual(self.tool.parse_diff_revision("", "(revision 23)")[1], "23")

        self.assertEqual(self.tool.parse_diff_revision("", "2007-06-06 15:32:23 UTC (rev 10958)")[1], "10958")

        self.assertRaises(SCMError, lambda: self.tool.parse_diff_revision("", "hello"))

    def testInterface(self):
        """Testing basic SVNTool API"""
        self.assertEqual(self.tool.get_diffs_use_absolute_paths(), False)

        self.assertRaises(NotImplementedError, lambda: self.tool.get_changeset(1))

        self.assertRaises(NotImplementedError, lambda: self.tool.get_pending_changesets(1))

    def testBinaryDiff(self):
        """Testing parsing SVN diff with binary file"""
        diff = (
            "Index: binfile\n==========================================="
            + "========================\nCannot display: file marked as a "
            + "binary type.\nsvn:mime-type = application/octet-stream\n"
        )

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, "binfile")
        self.assertEqual(file.binary, True)

    def testKeywordDiff(self):
        """Testing parsing SVN diff with keywords"""
        # 'svn cat' will expand special variables in svn:keywords,
        # but 'svn diff' doesn't expand anything.  This causes the
        # patch to fail if those variables appear in the patch context.
        diff = (
            "Index: Makefile\n"
            "==========================================================="
            "========\n"
            "--- Makefile    (revision 4)\n"
            "+++ Makefile    (working copy)\n"
            "@@ -1,6 +1,7 @@\n"
            " # $Id$\n"
            " # $Rev$\n"
            " # $Revision::     $\n"
            "+# foo\n"
            " include ../tools/Makefile.base-vars\n"
            " NAME = misc-docs\n"
            " OUTNAME = svn-misc-docs\n"
        )

        filename = "trunk/doc/misc-docs/Makefile"
        rev = Revision("4")
        file = self.tool.get_file(filename, rev)
        patch(diff, file, filename)

    def testUnterminatedKeywordDiff(self):
        """Testing parsing SVN diff with unterminated keywords"""
        diff = (
            "Index: Makefile\n"
            "==========================================================="
            "========\n"
            "--- Makefile    (revision 4)\n"
            "+++ Makefile    (working copy)\n"
            "@@ -1,6 +1,7 @@\n"
            " # $Id$\n"
            " # $Id:\n"
            " # $Rev$\n"
            " # $Revision::     $\n"
            "+# foo\n"
            " include ../tools/Makefile.base-vars\n"
            " NAME = misc-docs\n"
            " OUTNAME = svn-misc-docs\n"
        )

        filename = "trunk/doc/misc-docs/Makefile"
        rev = Revision("5")
        file = self.tool.get_file(filename, rev)
        patch(diff, file, filename)
Ejemplo n.º 48
0
class GitTests(SpyAgency, SCMTestCase):
    """Unit tests for Git."""

    fixtures = ['test_scmtools']

    def setUp(self):
        super(GitTests, self).setUp()

        tool = Tool.objects.get(name='Git')

        self.local_repo_path = os.path.join(os.path.dirname(__file__), '..',
                                            'testdata', 'git_repo')
        self.git_ssh_path = ('localhost:%s' %
                             self.local_repo_path.replace('\\', '/'))
        remote_repo_path = '[email protected]:reviewboard/reviewboard.git'
        remote_repo_raw_url = ('http://github.com/api/v2/yaml/blob/show/'
                               'reviewboard/reviewboard/<revision>')

        self.repository = Repository(name='Git test repo',
                                     path=self.local_repo_path,
                                     tool=tool)
        self.remote_repository = Repository(name='Remote Git test repo',
                                            path=remote_repo_path,
                                            raw_file_url=remote_repo_raw_url,
                                            tool=tool)

        try:
            self.tool = self.repository.get_scmtool()
            self.remote_tool = self.remote_repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest('git binary not found')

    def _read_fixture(self, filename):
        filename = os.path.join(os.path.dirname(__file__), '..', 'testdata',
                                filename)

        with open(filename, 'rb') as f:
            return f.read()

    def _get_file_in_diff(self, diff, filenum=0):
        files = self.tool.get_parser(diff).parse()
        self.assertTrue(filenum < len(files))
        return files[filenum]

    def test_ssh(self):
        """Testing a SSH-backed git repository"""
        self._test_ssh(self.git_ssh_path)

    def test_ssh_with_site(self):
        """Testing a SSH-backed git repository with a LocalSite"""
        self._test_ssh_with_site(self.git_ssh_path)

    def test_filemode_diff(self):
        """Testing parsing filemode changes Git diff"""
        diff = (b'diff --git a/testing b/testing\n'
                b'old mode 100755\n'
                b'new mode 100644\n'
                b'index e69de29..bcae657\n'
                b'--- a/testing\n'
                b'+++ b/testing\n'
                b'@@ -0,0 +1 @@\n'
                b'+ADD\n'
                b'diff --git a/testing2 b/testing2\n'
                b'old mode 100644\n'
                b'new mode 100755\n')

        file = self._get_file_in_diff(diff)
        self.assertEqual(file.orig_filename, b'testing')
        self.assertEqual(file.modified_filename, b'testing')
        self.assertEqual(file.orig_file_details, b'e69de29')
        self.assertEqual(file.modified_file_details, b'bcae657')
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertFalse(file.is_symlink)
        self.assertEqual(file.data.splitlines()[0],
                         b'diff --git a/testing b/testing')
        self.assertEqual(file.data.splitlines()[-1], b'+ADD')
        self.assertEqual(file.insert_count, 1)
        self.assertEqual(file.delete_count, 0)

    def test_filemode_with_following_diff(self):
        """Testing parsing filemode changes with following Git diff"""
        diff = (b'diff --git a/testing b/testing\n'
                b'old mode 100755\n'
                b'new mode 100644\n'
                b'index e69de29..bcae657\n'
                b'--- a/testing\n'
                b'+++ b/testing\n'
                b'@@ -0,0 +1 @@\n'
                b'+ADD\n'
                b'diff --git a/testing2 b/testing2\n'
                b'old mode 100644\n'
                b'new mode 100755\n'
                b'diff --git a/cfg/testcase.ini b/cfg/testcase.ini\n'
                b'index cc18ec8..5e70b73 100644\n'
                b'--- a/cfg/testcase.ini\n'
                b'+++ b/cfg/testcase.ini\n'
                b'@@ -1,6 +1,7 @@\n'
                b'+blah blah blah\n'
                b' [mysql]\n'
                b' host = localhost\n'
                b' port = 3306\n'
                b' user = user\n'
                b' pass = pass\n'
                b'-db = pyunit\n'
                b'+db = pyunit\n')

        file = self._get_file_in_diff(diff)
        self.assertEqual(file.orig_filename, b'testing')
        self.assertEqual(file.modified_filename, b'testing')
        self.assertEqual(file.orig_file_details, b'e69de29')
        self.assertEqual(file.modified_file_details, b'bcae657')
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertFalse(file.is_symlink)
        self.assertEqual(file.data.splitlines()[0],
                         b'diff --git a/testing b/testing')
        self.assertEqual(file.data.splitlines()[-1], b'+ADD')
        self.assertEqual(file.insert_count, 1)
        self.assertEqual(file.delete_count, 0)

        file = self._get_file_in_diff(diff, 1)
        self.assertEqual(file.orig_filename, b'cfg/testcase.ini')
        self.assertEqual(file.modified_filename, b'cfg/testcase.ini')
        self.assertEqual(file.orig_file_details, b'cc18ec8')
        self.assertEqual(file.modified_file_details, b'5e70b73')
        self.assertEqual(file.data.splitlines()[0],
                         b'diff --git a/cfg/testcase.ini b/cfg/testcase.ini')
        self.assertEqual(file.data.splitlines()[-1], b'+db = pyunit')
        self.assertEqual(file.insert_count, 2)
        self.assertEqual(file.delete_count, 1)

    def test_simple_diff(self):
        """Testing parsing simple Git diff"""
        diff = (b'diff --git a/cfg/testcase.ini b/cfg/testcase.ini\n'
                b'index cc18ec8..5e70b73 100644\n'
                b'--- a/cfg/testcase.ini\n'
                b'+++ b/cfg/testcase.ini\n'
                b'@@ -1,6 +1,7 @@\n'
                b'+blah blah blah\n'
                b' [mysql]\n'
                b' host = localhost\n'
                b' port = 3306\n'
                b' user = user\n'
                b' pass = pass\n'
                b'-db = pyunit\n'
                b'+db = pyunit\n')

        file = self._get_file_in_diff(diff)
        self.assertEqual(file.orig_filename, b'cfg/testcase.ini')
        self.assertEqual(file.modified_filename, b'cfg/testcase.ini')
        self.assertEqual(file.orig_file_details, b'cc18ec8')
        self.assertEqual(file.modified_file_details, b'5e70b73')
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertFalse(file.is_symlink)
        self.assertEqual(len(file.data), 249)
        self.assertEqual(file.data.splitlines()[0],
                         b'diff --git a/cfg/testcase.ini b/cfg/testcase.ini')
        self.assertEqual(file.data.splitlines()[-1], b'+db = pyunit')
        self.assertEqual(file.insert_count, 2)
        self.assertEqual(file.delete_count, 1)

    def test_diff_with_unicode(self):
        """Testing parsing Git diff with unicode characters"""
        diff = ('diff --git a/cfg/téstcase.ini b/cfg/téstcase.ini\n'
                'index cc18ec8..5e70b73 100644\n'
                '--- a/cfg/téstcase.ini\n'
                '+++ b/cfg/téstcase.ini\n'
                '@@ -1,6 +1,7 @@\n'
                '+blah blah blah\n'
                ' [mysql]\n'
                ' hóst = localhost\n'
                ' pórt = 3306\n'
                ' user = user\n'
                ' pass = pass\n'
                '-db = pyunít\n'
                '+db = pyunít\n').encode('utf-8')

        file = self._get_file_in_diff(diff)
        self.assertEqual(file.orig_filename,
                         'cfg/téstcase.ini'.encode('utf-8'))
        self.assertEqual(file.modified_filename,
                         'cfg/téstcase.ini'.encode('utf-8'))
        self.assertEqual(file.orig_file_details, b'cc18ec8')
        self.assertEqual(file.modified_file_details, b'5e70b73')
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertFalse(file.is_symlink)
        self.assertEqual(file.data.splitlines()[0].decode('utf-8'),
                         'diff --git a/cfg/téstcase.ini b/cfg/téstcase.ini')
        self.assertEqual(file.data.splitlines()[-1],
                         '+db = pyunít'.encode('utf-8'))
        self.assertEqual(file.insert_count, 2)
        self.assertEqual(file.delete_count, 1)

    def test_diff_with_tabs_after_filename(self):
        """Testing parsing Git diffs with tabs after the filename"""
        diff = (b'diff --git a/README b/README\n'
                b'index 712544e4343bf04967eb5ea80257f6c64d6f42c7..'
                b'f88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1 100644\n'
                b'--- a/README\t\n'
                b'+++ b/README\t\n'
                b'@ -1,1 +1,1 @@\n'
                b'-blah blah\n'
                b'+blah\n'
                b'-\n'
                b'1.7.1\n')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(files[0].orig_filename, b'README')
        self.assertEqual(files[0].modified_filename, b'README')
        self.assertEqual(files[0].orig_file_details,
                         b'712544e4343bf04967eb5ea80257f6c64d6f42c7')
        self.assertEqual(files[0].modified_file_details,
                         b'f88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1')
        self.assertEqual(files[0].data, diff)
        self.assertEqual(files[0].insert_count, 1)
        self.assertEqual(files[0].delete_count, 2)

    def test_new_file_diff(self):
        """Testing parsing Git diff with new file"""
        diff = (b'diff --git a/IAMNEW b/IAMNEW\n'
                b'new file mode 100644\n'
                b'index 0000000..e69de29\n'
                b'--- /dev/null\n'
                b'+++ b/IAMNEW\n'
                b'@@ -0,0 +1,1 @@\n'
                b'+Hello\n')

        file = self._get_file_in_diff(diff)
        self.assertEqual(file.orig_filename, b'IAMNEW')
        self.assertEqual(file.modified_filename, b'IAMNEW')
        self.assertEqual(file.orig_file_details, PRE_CREATION)
        self.assertEqual(file.modified_file_details, b'e69de29')
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertFalse(file.is_symlink)
        self.assertEqual(len(file.data), 123)
        self.assertEqual(file.data.splitlines()[0],
                         b'diff --git a/IAMNEW b/IAMNEW')
        self.assertEqual(file.data.splitlines()[-1], b'+Hello')
        self.assertEqual(file.insert_count, 1)
        self.assertEqual(file.delete_count, 0)

    def test_new_file_no_content_diff(self):
        """Testing parsing Git diff new file, no content"""
        diff = (b'diff --git a/newfile b/newfile\n'
                b'new file mode 100644\n'
                b'index 0000000..e69de29\n')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)

        file = self._get_file_in_diff(diff)
        self.assertEqual(file.orig_filename, b'newfile')
        self.assertEqual(file.modified_filename, b'newfile')
        self.assertEqual(file.orig_file_details, PRE_CREATION)
        self.assertEqual(file.modified_file_details, b'e69de29')
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertFalse(file.is_symlink)
        lines = file.data.splitlines()
        self.assertEqual(len(lines), 3)
        self.assertEqual(lines[0], b'diff --git a/newfile b/newfile')
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_new_file_no_content_with_following_diff(self):
        """Testing parsing Git diff new file, no content, with following"""
        diff = (b'diff --git a/newfile b/newfile\n'
                b'new file mode 100644\n'
                b'index 0000000..e69de29\n'
                b'diff --git a/cfg/testcase.ini b/cfg/testcase.ini\n'
                b'index cc18ec8..5e70b73 100644\n'
                b'--- a/cfg/testcase.ini\n'
                b'+++ b/cfg/testcase.ini\n'
                b'@@ -1,6 +1,7 @@\n'
                b'+blah blah blah\n'
                b' [mysql]\n'
                b' host = localhost\n'
                b' port = 3306\n'
                b' user = user\n'
                b' pass = pass\n'
                b'-db = pyunit\n'
                b'+db = pyunit\n')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 2)

        self.assertEqual(files[0].orig_filename, b'newfile')
        self.assertEqual(files[0].modified_filename, b'newfile')
        self.assertEqual(files[0].orig_file_details, PRE_CREATION)
        self.assertEqual(files[0].modified_file_details, b'e69de29')
        self.assertFalse(files[0].binary)
        self.assertFalse(files[0].deleted)
        self.assertFalse(files[0].is_symlink)
        lines = files[0].data.splitlines()
        self.assertEqual(len(lines), 3)
        self.assertEqual(lines[0], b'diff --git a/newfile b/newfile')
        self.assertEqual(files[0].insert_count, 0)
        self.assertEqual(files[0].delete_count, 0)

        self.assertEqual(files[1].orig_filename, b'cfg/testcase.ini')
        self.assertEqual(files[1].modified_filename, b'cfg/testcase.ini')
        self.assertEqual(files[1].orig_file_details, b'cc18ec8')
        self.assertEqual(files[1].modified_file_details, b'5e70b73')
        lines = files[1].data.splitlines()
        self.assertEqual(len(lines), 13)
        self.assertEqual(lines[0],
                         b'diff --git a/cfg/testcase.ini b/cfg/testcase.ini')
        self.assertEqual(lines[-1], b'+db = pyunit')
        self.assertEqual(files[1].insert_count, 2)
        self.assertEqual(files[1].delete_count, 1)

    def test_del_file_diff(self):
        """Testing parsing Git diff with deleted file"""
        diff = (b'diff --git a/OLDFILE b/OLDFILE\n'
                b'deleted file mode 100644\n'
                b'index 8ebcb01..0000000\n'
                b'--- a/OLDFILE\n'
                b'+++ /dev/null\n'
                b'@@ -1,1 +0,0 @@\n'
                b'-Goodbye\n')

        file = self._get_file_in_diff(diff)
        self.assertEqual(file.orig_filename, b'OLDFILE')
        self.assertEqual(file.modified_filename, b'OLDFILE')
        self.assertEqual(file.orig_file_details, b'8ebcb01')
        self.assertEqual(file.modified_file_details, b'0000000')
        self.assertFalse(file.binary)
        self.assertTrue(file.deleted)
        self.assertFalse(file.is_symlink)
        self.assertEqual(len(file.data), 132)
        self.assertEqual(file.data.splitlines()[0],
                         b'diff --git a/OLDFILE b/OLDFILE')
        self.assertEqual(file.data.splitlines()[-1], b'-Goodbye')
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 1)

    def test_del_file_no_content_diff(self):
        """Testing parsing Git diff with deleted file, no content"""
        diff = (b'diff --git a/empty b/empty\n'
                b'deleted file mode 100644\n'
                b'index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..'
                b'0000000000000000000000000000000000000000\n')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)

        self.assertEqual(files[0].orig_filename, b'empty')
        self.assertEqual(files[0].modified_filename, b'empty')
        self.assertEqual(files[0].orig_file_details,
                         b'e69de29bb2d1d6434b8b29ae775ad8c2e48c5391')
        self.assertEqual(files[0].modified_file_details,
                         b'0000000000000000000000000000000000000000')
        self.assertFalse(files[0].binary)
        self.assertTrue(files[0].deleted)
        self.assertFalse(files[0].is_symlink)
        self.assertEqual(len(files[0].data), 141)
        self.assertEqual(files[0].data.splitlines()[0],
                         b'diff --git a/empty b/empty')
        self.assertEqual(files[0].insert_count, 0)
        self.assertEqual(files[0].delete_count, 0)

    def test_del_file_no_content_with_following_diff(self):
        """Testing parsing Git diff with deleted file, no content, with
        following
        """
        diff = (b'diff --git a/empty b/empty\n'
                b'deleted file mode 100644\n'
                b'index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..'
                b'0000000000000000000000000000000000000000\n'
                b'diff --git a/foo/bar b/foo/bar\n'
                b'index 484ba93ef5b0aed5b72af8f4e9dc4cfd10ef1a81..'
                b'0ae4095ddfe7387d405bd53bd59bbb5d861114c5 100644\n'
                b'--- a/foo/bar\n'
                b'+++ b/foo/bar\n'
                b'@@ -1 +1,2 @@\n'
                b'+Hello!\n'
                b'blah\n')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 2)

        self.assertEqual(files[0].orig_filename, b'empty')
        self.assertEqual(files[0].modified_filename, b'empty')
        self.assertEqual(files[0].orig_file_details,
                         b'e69de29bb2d1d6434b8b29ae775ad8c2e48c5391')
        self.assertEqual(files[0].modified_file_details,
                         b'0000000000000000000000000000000000000000')
        self.assertFalse(files[0].binary)
        self.assertTrue(files[0].deleted)
        self.assertFalse(files[0].is_symlink)
        self.assertEqual(len(files[0].data), 141)
        self.assertEqual(files[0].data.splitlines()[0],
                         b'diff --git a/empty b/empty')
        self.assertEqual(files[0].insert_count, 0)
        self.assertEqual(files[0].delete_count, 0)

        self.assertEqual(files[1].orig_filename, b'foo/bar')
        self.assertEqual(files[1].modified_filename, b'foo/bar')
        self.assertEqual(files[1].orig_file_details,
                         b'484ba93ef5b0aed5b72af8f4e9dc4cfd10ef1a81')
        self.assertEqual(files[1].modified_file_details,
                         b'0ae4095ddfe7387d405bd53bd59bbb5d861114c5')
        self.assertFalse(files[1].binary)
        self.assertFalse(files[1].deleted)
        self.assertFalse(files[1].is_symlink)
        lines = files[1].data.splitlines()
        self.assertEqual(len(lines), 7)
        self.assertEqual(lines[0], b'diff --git a/foo/bar b/foo/bar')
        self.assertEqual(lines[5], b'+Hello!')
        self.assertEqual(files[1].insert_count, 1)
        self.assertEqual(files[1].delete_count, 0)

    def test_binary_diff(self):
        """Testing parsing Git diff with binary"""
        diff = (b'diff --git a/pysvn-1.5.1.tar.gz b/pysvn-1.5.1.tar.gz\n'
                b'new file mode 100644\n'
                b'index 0000000..86b520c\n'
                b'Binary files /dev/null and b/pysvn-1.5.1.tar.gz differ\n')

        file = self._get_file_in_diff(diff)
        self.assertEqual(file.orig_filename, b'pysvn-1.5.1.tar.gz')
        self.assertEqual(file.modified_filename, b'pysvn-1.5.1.tar.gz')
        self.assertEqual(file.orig_file_details, PRE_CREATION)
        self.assertEqual(file.modified_file_details, b'86b520c')
        self.assertTrue(file.binary)
        self.assertFalse(file.deleted)
        self.assertFalse(file.is_symlink)
        lines = file.data.splitlines()
        self.assertEqual(len(lines), 4)
        self.assertEqual(
            lines[0], b'diff --git a/pysvn-1.5.1.tar.gz b/pysvn-1.5.1.tar.gz')
        self.assertEqual(
            lines[3],
            b'Binary files /dev/null and b/pysvn-1.5.1.tar.gz differ')
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_complex_diff(self):
        """Testing parsing Git diff with existing and new files"""
        diff = self._read_fixture('git_complex.diff')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 7)
        self.assertEqual(files[0].orig_filename, b'cfg/testcase.ini')
        self.assertEqual(files[0].modified_filename, b'cfg/testcase.ini')
        self.assertEqual(files[0].orig_file_details, b'5e35098')
        self.assertEqual(files[0].modified_file_details, b'e254ef4')
        self.assertFalse(files[0].binary)
        self.assertFalse(files[0].deleted)
        self.assertFalse(files[0].is_symlink)
        self.assertEqual(files[0].insert_count, 2)
        self.assertEqual(files[0].delete_count, 1)
        self.assertEqual(len(files[0].data), 549)
        self.assertEqual(files[0].data.splitlines()[0],
                         b'diff --git a/cfg/testcase.ini b/cfg/testcase.ini')
        self.assertEqual(files[0].data.splitlines()[13],
                         b'         if isinstance(value, basestring):')

        self.assertEqual(files[1].orig_filename, b'tests/models.py')
        self.assertEqual(files[1].modified_filename, b'tests/models.py')
        self.assertEqual(files[1].orig_file_details, PRE_CREATION)
        self.assertEqual(files[1].modified_file_details, b'e69de29')
        self.assertFalse(files[1].binary)
        self.assertFalse(files[1].deleted)
        self.assertFalse(files[1].is_symlink)
        self.assertEqual(files[1].insert_count, 0)
        self.assertEqual(files[1].delete_count, 0)
        lines = files[1].data.splitlines()
        self.assertEqual(len(lines), 3)
        self.assertEqual(lines[0],
                         b'diff --git a/tests/models.py b/tests/models.py')

        self.assertEqual(files[2].orig_filename, b'tests/tests.py')
        self.assertEqual(files[2].modified_filename, b'tests/tests.py')
        self.assertEqual(files[2].orig_file_details, PRE_CREATION)
        self.assertEqual(files[2].modified_file_details, b'e279a06')
        self.assertFalse(files[2].binary)
        self.assertFalse(files[2].deleted)
        self.assertFalse(files[2].is_symlink)
        self.assertEqual(files[2].insert_count, 2)
        self.assertEqual(files[2].delete_count, 0)
        lines = files[2].data.splitlines()
        self.assertEqual(len(lines), 8)
        self.assertEqual(lines[0],
                         b'diff --git a/tests/tests.py b/tests/tests.py')
        self.assertEqual(lines[7], b'+This is some new content')

        self.assertEqual(files[3].orig_filename, b'pysvn-1.5.1.tar.gz')
        self.assertEqual(files[3].modified_filename, b'pysvn-1.5.1.tar.gz')
        self.assertEqual(files[3].orig_file_details, PRE_CREATION)
        self.assertEqual(files[3].modified_file_details, b'86b520c')
        self.assertTrue(files[3].binary)
        self.assertFalse(files[3].deleted)
        self.assertFalse(files[3].is_symlink)
        self.assertEqual(files[3].insert_count, 0)
        self.assertEqual(files[3].delete_count, 0)
        lines = files[3].data.splitlines()
        self.assertEqual(len(lines), 4)
        self.assertEqual(
            lines[0], b'diff --git a/pysvn-1.5.1.tar.gz b/pysvn-1.5.1.tar.gz')
        self.assertEqual(
            lines[3], b'Binary files /dev/null and b/pysvn-1.5.1.tar.gz '
            b'differ')

        self.assertEqual(files[4].orig_filename, b'readme')
        self.assertEqual(files[4].modified_filename, b'readme')
        self.assertEqual(files[4].orig_file_details, b'5e35098')
        self.assertEqual(files[4].modified_file_details, b'e254ef4')
        self.assertFalse(files[4].binary)
        self.assertFalse(files[4].deleted)
        self.assertFalse(files[4].is_symlink)
        self.assertEqual(files[4].insert_count, 1)
        self.assertEqual(files[4].delete_count, 1)
        lines = files[4].data.splitlines()
        self.assertEqual(len(lines), 7)
        self.assertEqual(lines[0], b'diff --git a/readme b/readme')
        self.assertEqual(lines[6], b'+Hello there')

        self.assertEqual(files[5].orig_filename, b'OLDFILE')
        self.assertEqual(files[5].modified_filename, b'OLDFILE')
        self.assertEqual(files[5].orig_file_details, b'8ebcb01')
        self.assertEqual(files[5].modified_file_details, b'0000000')
        self.assertFalse(files[5].binary)
        self.assertTrue(files[5].deleted)
        self.assertFalse(files[5].is_symlink)
        self.assertEqual(files[5].insert_count, 0)
        self.assertEqual(files[5].delete_count, 1)
        lines = files[5].data.splitlines()
        self.assertEqual(len(lines), 7)
        self.assertEqual(lines[0], b'diff --git a/OLDFILE b/OLDFILE')
        self.assertEqual(lines[6], b'-Goodbye')

        self.assertEqual(files[6].orig_filename, b'readme2')
        self.assertEqual(files[6].modified_filename, b'readme2')
        self.assertEqual(files[6].orig_file_details, b'5e43098')
        self.assertEqual(files[6].modified_file_details, b'e248ef4')
        self.assertFalse(files[6].binary)
        self.assertFalse(files[6].deleted)
        self.assertFalse(files[6].is_symlink)
        self.assertEqual(files[6].insert_count, 1)
        self.assertEqual(files[6].delete_count, 1)
        lines = files[6].data.splitlines()
        self.assertEqual(len(lines), 7)
        self.assertEqual(lines[0], b'diff --git a/readme2 b/readme2')
        self.assertEqual(lines[6], b'+Hello there')

    def test_parse_diff_with_index_range(self):
        """Testing Git diff parsing with an index range"""
        diff = (b'diff --git a/foo/bar b/foo/bar2\n'
                b'similarity index 88%\n'
                b'rename from foo/bar\n'
                b'rename to foo/bar2\n'
                b'index 612544e4343bf04967eb5ea80257f6c64d6f42c7..'
                b'e88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1 100644\n'
                b'--- a/foo/bar\n'
                b'+++ b/foo/bar2\n'
                b'@ -1,1 +1,1 @@\n'
                b'-blah blah\n'
                b'+blah\n')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)
        self.assertEqual(files[0].orig_filename, b'foo/bar')
        self.assertEqual(files[0].modified_filename, b'foo/bar2')
        self.assertEqual(files[0].orig_file_details,
                         b'612544e4343bf04967eb5ea80257f6c64d6f42c7')
        self.assertEqual(files[0].modified_file_details,
                         b'e88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1')
        self.assertEqual(files[0].insert_count, 1)
        self.assertEqual(files[0].delete_count, 1)

    def test_parse_diff_with_deleted_binary_files(self):
        """Testing Git diff parsing with deleted binary files"""
        diff = (b'diff --git a/foo.bin b/foo.bin\n'
                b'deleted file mode 100644\n'
                b'Binary file foo.bin has changed\n'
                b'diff --git a/bar.bin b/bar.bin\n'
                b'deleted file mode 100644\n'
                b'Binary file bar.bin has changed\n')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 2)
        self.assertEqual(files[0].orig_filename, b'foo.bin')
        self.assertEqual(files[0].modified_filename, b'foo.bin')
        self.assertEqual(files[0].binary, True)
        self.assertEqual(files[0].deleted, True)
        self.assertFalse(files[0].is_symlink)
        self.assertEqual(files[0].insert_count, 0)
        self.assertEqual(files[0].delete_count, 0)
        self.assertEqual(files[1].orig_filename, b'bar.bin')
        self.assertEqual(files[1].modified_filename, b'bar.bin')
        self.assertEqual(files[1].binary, True)
        self.assertEqual(files[1].deleted, True)
        self.assertFalse(files[1].is_symlink)
        self.assertEqual(files[1].insert_count, 0)
        self.assertEqual(files[1].delete_count, 0)

    def test_parse_diff_with_all_headers(self):
        """Testing Git diff parsing and preserving all headers"""
        preamble = (b'From 38d8fa94a9aa0c5b27943bec31d94e880165f1e0 Mon Sep '
                    b'17 00:00:00 2001\n'
                    b'From: Example Joe <*****@*****.**>\n'
                    b'Date: Thu, 5 Apr 2012 00:41:12 -0700\n'
                    b'Subject: [PATCH 1/1] Sample patch.\n'
                    b'\n'
                    b'This is a test summary.\n'
                    b'\n'
                    b'With a description.\n'
                    b'---\n'
                    b' foo/bar |   2 -+n'
                    b' README  |   2 -+n'
                    b' 2 files changed, 2 insertions(+), 2 deletions(-)\n'
                    b'\n')
        diff1 = (b'diff --git a/foo/bar b/foo/bar2\n'
                 b'index 612544e4343bf04967eb5ea80257f6c64d6f42c7..'
                 b'e88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1 100644\n'
                 b'--- a/foo/bar\n'
                 b'+++ b/foo/bar2\n'
                 b'@ -1,1 +1,1 @@\n'
                 b'-blah blah\n'
                 b'+blah\n')
        diff2 = (b'diff --git a/README b/README\n'
                 b'index 712544e4343bf04967eb5ea80257f6c64d6f42c7..'
                 b'f88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1 100644\n'
                 b'--- a/README\n'
                 b'+++ b/README\n'
                 b'@ -1,1 +1,1 @@\n'
                 b'-blah blah\n'
                 b'+blah\n'
                 b'-\n'
                 b'1.7.1\n')
        diff = preamble + diff1 + diff2

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 2)
        self.assertEqual(files[0].orig_filename, b'foo/bar')
        self.assertEqual(files[0].modified_filename, b'foo/bar2')
        self.assertEqual(files[0].orig_file_details,
                         b'612544e4343bf04967eb5ea80257f6c64d6f42c7')
        self.assertEqual(files[0].modified_file_details,
                         b'e88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1')
        self.assertEqual(files[0].data, preamble + diff1)
        self.assertEqual(files[0].insert_count, 1)
        self.assertEqual(files[0].delete_count, 1)

        self.assertEqual(files[1].orig_filename, b'README')
        self.assertEqual(files[1].modified_filename, b'README')
        self.assertEqual(files[1].orig_file_details,
                         b'712544e4343bf04967eb5ea80257f6c64d6f42c7')
        self.assertEqual(files[1].modified_file_details,
                         b'f88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1')
        self.assertEqual(files[1].data, diff2)
        self.assertEqual(files[1].insert_count, 1)
        self.assertEqual(files[1].delete_count, 2)

    def test_parse_diff_revision(self):
        """Testing Git revision number parsing"""
        self.assertEqual(
            self.tool.parse_diff_revision(filename=b'doc/readme',
                                          revision=b'bf544ea'),
            (b'doc/readme', b'bf544ea'))
        self.assertEqual(
            self.tool.parse_diff_revision(filename=b'/dev/null',
                                          revision=b'bf544ea'),
            (b'/dev/null', PRE_CREATION))
        self.assertEqual(
            self.tool.parse_diff_revision(filename=b'/dev/null',
                                          revision=b'0000000'),
            (b'/dev/null', PRE_CREATION))

    def test_parse_diff_with_copy_and_rename_same_file(self):
        """Testing Git diff parsing with copy and rename of same file"""
        diff = (b'diff --git a/foo/bar b/foo/bar2\n'
                b'similarity index 100%\n'
                b'copy from foo/bar\n'
                b'copy to foo/bar2\n'
                b'diff --git a/foo/bar b/foo/bar3\n'
                b'similarity index 92%\n'
                b'rename from foo/bar\n'
                b'rename to foo/bar3\n'
                b'index 612544e4343bf04967eb5ea80257f6c64d6f42c7..'
                b'e88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1 100644\n'
                b'--- a/foo/bar\n'
                b'+++ b/foo/bar3\n'
                b'@@ -1,1 +1,1 @@\n'
                b'-blah blah\n'
                b'+blah\n')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 2)

        f = files[0]
        self.assertEqual(f.orig_filename, b'foo/bar')
        self.assertEqual(f.modified_filename, b'foo/bar2')
        self.assertEqual(f.orig_file_details, b'')
        self.assertEqual(f.modified_file_details, b'')
        self.assertEqual(f.insert_count, 0)
        self.assertEqual(f.delete_count, 0)
        self.assertFalse(f.moved)
        self.assertTrue(f.copied)
        self.assertFalse(f.is_symlink)

        f = files[1]
        self.assertEqual(f.orig_filename, b'foo/bar')
        self.assertEqual(f.modified_filename, b'foo/bar3')
        self.assertEqual(f.orig_file_details,
                         b'612544e4343bf04967eb5ea80257f6c64d6f42c7')
        self.assertEqual(f.modified_file_details,
                         b'e88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1')
        self.assertEqual(f.insert_count, 1)
        self.assertEqual(f.delete_count, 1)
        self.assertTrue(f.moved)
        self.assertFalse(f.copied)
        self.assertFalse(f.is_symlink)

    def test_parse_diff_with_mode_change_and_rename(self):
        """Testing Git diff parsing with mode change and rename"""
        diff = (b'diff --git a/foo/bar b/foo/bar2\n'
                b'old mode 100755\n'
                b'new mode 100644\n'
                b'similarity index 99%\n'
                b'rename from foo/bar\n'
                b'rename to foo/bar2\n'
                b'index 612544e4343bf04967eb5ea80257f6c64d6f42c7..'
                b'e88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1\n'
                b'--- a/foo/bar\n'
                b'+++ b/foo/bar2\n'
                b'@@ -1,1 +1,1 @@\n'
                b'-blah blah\n'
                b'+blah\n')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)

        f = files[0]
        self.assertEqual(f.orig_filename, b'foo/bar')
        self.assertEqual(f.modified_filename, b'foo/bar2')
        self.assertEqual(f.orig_file_details,
                         b'612544e4343bf04967eb5ea80257f6c64d6f42c7')
        self.assertEqual(f.modified_file_details,
                         b'e88b7f15c03d141d0bb38c8e49bb6c411ebfe1f1')
        self.assertEqual(f.insert_count, 1)
        self.assertEqual(f.delete_count, 1)
        self.assertTrue(f.moved)
        self.assertFalse(f.copied)
        self.assertFalse(f.is_symlink)

    def test_diff_git_line_without_a_b(self):
        """Testing parsing Git diff with deleted file without a/ and
        b/ filename prefixes
        """
        diff = (b'diff --git foo foo\n'
                b'deleted file mode 100644\n'
                b'index 612544e4343bf04967eb5ea80257f6c64d6f42c7..'
                b'0000000000000000000000000000000000000000\n')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)

        f = files[0]
        self.assertEqual(f.orig_filename, b'foo')
        self.assertEqual(f.modified_filename, b'foo')
        self.assertTrue(f.deleted)
        self.assertFalse(f.is_symlink)

    def test_diff_git_line_without_a_b_quotes(self):
        """Testing parsing Git diff with deleted file without a/ and
        b/ filename prefixes and with quotes
        """
        diff = (b'diff --git "foo" "foo"\n'
                b'deleted file mode 100644\n'
                b'index 612544e4343bf04967eb5ea80257f6c64d6f42c7..'
                b'0000000000000000000000000000000000000000\n')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)

        f = files[0]
        self.assertEqual(f.orig_filename, b'foo')
        self.assertEqual(f.modified_filename, b'foo')
        self.assertTrue(f.deleted)
        self.assertFalse(f.is_symlink)

    def test_diff_git_line_without_a_b_and_spaces(self):
        """Testing parsing Git diff with deleted file without a/ and
        b/ filename prefixes and with spaces
        """
        diff = (b'diff --git foo bar1 foo bar1\n'
                b'deleted file mode 100644\n'
                b'index 612544e4343bf04967eb5ea80257f6c64d6f42c7..'
                b'0000000000000000000000000000000000000000\n')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)

        f = files[0]
        self.assertEqual(f.orig_filename, b'foo bar1')
        self.assertEqual(f.modified_filename, b'foo bar1')
        self.assertTrue(f.deleted)
        self.assertFalse(f.is_symlink)

    def test_diff_git_line_without_a_b_and_spaces_quotes(self):
        """Testing parsing Git diff with deleted file without a/ and
        b/ filename prefixes and with space and quotes
        """
        diff = (b'diff --git "foo bar1" "foo bar1"\n'
                b'deleted file mode 100644\n'
                b'index 612544e4343bf04967eb5ea80257f6c64d6f42c7..'
                b'0000000000000000000000000000000000000000\n')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)

        f = files[0]
        self.assertEqual(f.orig_filename, b'foo bar1')
        self.assertEqual(f.modified_filename, b'foo bar1')

    def test_diff_git_line_without_a_b_and_spaces_changed(self):
        """Testing parsing Git diff with deleted file without a/ and
        b/ filename prefixes and with spaces, with filename changes
        """
        diff = (b'diff --git foo bar1 foo bar2\n'
                b'deleted file mode 100644\n'
                b'index 612544e4343bf04967eb5ea80257f6c64d6f42c7..'
                b'0000000000000000000000000000000000000000\n')

        with self.assertRaises(DiffParserError) as cm:
            self.tool.get_parser(diff).parse()

        self.assertTrue(
            six.text_type(cm.exception).startswith(
                'Unable to parse the "diff --git" line'))

    def test_diff_git_line_without_a_b_and_spaces_quotes_changed(self):
        """Testing parsing Git diff with deleted file without a/ and
        b/ filename prefixes and with spaces and quotes, with filename
        changes
        """
        diff = (b'diff --git "foo bar1" "foo bar2"\n'
                b'deleted file mode 100644\n'
                b'index 612544e4343bf04967eb5ea80257f6c64d6f42c7..'
                b'0000000000000000000000000000000000000000\n'
                b'diff --git "foo bar1" foo\n'
                b'deleted file mode 100644\n'
                b'index 612544e4343bf04967eb5ea80257f6c64d6f42c7..'
                b'0000000000000000000000000000000000000000\n'
                b'diff --git foo "foo bar1"\n'
                b'deleted file mode 100644\n'
                b'index 612544e4343bf04967eb5ea80257f6c64d6f42c7..'
                b'0000000000000000000000000000000000000000\n')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 3)

        f = files[0]
        self.assertEqual(f.orig_filename, b'foo bar1')
        self.assertEqual(f.modified_filename, b'foo bar2')
        self.assertTrue(f.deleted)
        self.assertFalse(f.is_symlink)

        f = files[1]
        self.assertEqual(f.orig_filename, b'foo bar1')
        self.assertEqual(f.modified_filename, b'foo')

        f = files[2]
        self.assertEqual(f.orig_filename, b'foo')
        self.assertEqual(f.modified_filename, b'foo bar1')

    def test_diff_git_symlink_added(self):
        """Testing parsing Git diff with symlink added"""
        diff = (b'diff --git a/link b/link\n'
                b'new file mode 120000\n'
                b'index 0000000..100b938\n'
                b'--- /dev/null\n'
                b'+++ b/link\n'
                b'@@ -0,0 +1 @@\n'
                b'+README\n'
                b'\\ No newline at end of file\n')
        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)

        f = files[0]
        self.assertEqual(f.orig_file_details, PRE_CREATION)
        self.assertEqual(f.modified_filename, b'link')
        self.assertTrue(f.is_symlink)

    def test_diff_git_symlink_changed(self):
        """Testing parsing Git diff with symlink changed"""
        diff = (b'diff --git a/link b/link\n'
                b'index 100b937..100b938 120000\n'
                b'--- a/link\n'
                b'+++ b/link\n'
                b'@@ -1 +1 @@\n'
                b'-README\n'
                b'\\ No newline at end of file\n'
                b'+README.md\n'
                b'\\ No newline at end of file\n')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)

        f = files[0]
        self.assertEqual(f.modified_filename, b'link')
        self.assertEqual(f.orig_filename, b'link')
        self.assertTrue(f.is_symlink)

    def test_diff_git_symlink_removed(self):
        """Testing parsing Git diff with symlink removed"""
        diff = (b'diff --git a/link b/link\n'
                b'deleted file mode 120000\n'
                b'index 100b938..0000000\n'
                b'--- a/link\n'
                b'+++ /dev/null\n'
                b'@@ -1 +0,0 @@\n'
                b'-README.txt\n'
                b'\\ No newline at end of file\n')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)

        f = files[0]
        self.assertEqual(f.orig_filename, b'link')
        self.assertTrue(f.deleted)
        self.assertTrue(f.is_symlink)

    def test_file_exists(self):
        """Testing GitTool.file_exists"""
        tool = self.tool

        self.assertTrue(tool.file_exists('readme', 'e965047'))
        self.assertTrue(tool.file_exists('readme', 'd6613f5'))

        self.assertFalse(tool.file_exists('readme', PRE_CREATION))
        self.assertFalse(tool.file_exists('readme', 'fffffff'))
        self.assertFalse(tool.file_exists('readme2', 'fffffff'))

        # These sha's are valid, but commit and tree objects, not blobs.
        self.assertFalse(tool.file_exists('readme', 'a62df6c'))
        self.assertFalse(tool.file_exists('readme2', 'ccffbb4'))

    def test_get_file(self):
        """Testing GitTool.get_file"""
        tool = self.tool

        content = tool.get_file('readme', PRE_CREATION)
        self.assertIsInstance(content, bytes)
        self.assertEqual(content, b'')

        content = tool.get_file('readme', 'e965047')
        self.assertIsInstance(content, bytes)
        self.assertEqual(content, b'Hello\n')

        content = tool.get_file('readme', 'd6613f5')
        self.assertIsInstance(content, bytes)
        self.assertEqual(content, b'Hello there\n')

        content = tool.get_file('readme')
        self.assertIsInstance(content, bytes)
        self.assertEqual(content, b'Hello there\n')

        with self.assertRaises(SCMError):
            tool.get_file('')

        with self.assertRaises(FileNotFoundError):
            tool.get_file('', '0000000')

        with self.assertRaises(FileNotFoundError):
            tool.get_file('hello', '0000000')

        with self.assertRaises(FileNotFoundError):
            tool.get_file('readme', '0000000')

    def test_parse_diff_revision_with_remote_and_short_SHA1_error(self):
        """Testing GitTool.parse_diff_revision with remote files and short
        SHA1 error
        """
        with self.assertRaises(ShortSHA1Error):
            self.remote_tool.parse_diff_revision(filename=b'README',
                                                 revision=b'd7e96b3')

    def test_get_file_with_remote_and_short_SHA1_error(self):
        """Testing GitTool.get_file with remote files and short SHA1 error"""
        with self.assertRaises(ShortSHA1Error):
            self.remote_tool.get_file('README', 'd7e96b3')

    def test_valid_repository_https_username(self):
        """Testing GitClient.is_valid_repository with an HTTPS URL and external
        credentials
        """
        client = GitClient('https://example.com/test.git',
                           username='******',
                           password='******')

        self.spy_on(client._run_git)
        client.is_valid_repository()

        self.assertEqual(client._run_git.calls[0].args[0], [
            'ls-remote', 'https://*****:*****@example.com/test.git',
            'HEAD'
        ])

    def test_raw_file_url_error(self):
        """Testing Repository.get_file re-fetches when raw file URL changes"""
        self.spy_on(self.remote_repository._get_file_uncached,
                    call_fake=lambda a, b, x, y, z: 'first')
        self.assertEqual(self.remote_repository.get_file('PATH', 'd7e96b3'),
                         'first')
        # Ensure output of fake result matches.
        self.remote_repository._get_file_uncached.unspy()
        self.spy_on(self.remote_repository._get_file_uncached,
                    call_fake=lambda a, b, x, y, z: 'second')
        # Grab from cache when no changes and change fake result to confirm
        # it is not called.
        self.assertEqual(self.remote_repository.get_file('PATH', 'd7e96b3'),
                         'first')
        self.remote_repository.raw_file_url = (
            'http://github.com/api/v2/yaml/blob/show/reviewboard/<revision>')
        # When raw_file_url changed, do not grab from cache and ensure output
        # equals second fake value.
        self.assertEqual(self.remote_repository.get_file('PATH', 'd7e96b3'),
                         'second')

    def test_get_file_exists_caching_with_raw_url(self):
        """Testing Repository.get_file_exists properly checks file existence in
        repository or cache when raw file URL changes
        """
        self.spy_on(self.remote_repository._get_file_exists_uncached,
                    call_fake=lambda a, b, x, y, z: True)
        # Use spy to put key into cache
        self.assertTrue(
            self.remote_repository.get_file_exists('PATH', 'd7e96b3'))
        # Remove spy to ensure key is still in cache without needing spy
        self.remote_repository._get_file_exists_uncached.unspy()
        self.assertTrue(
            self.remote_repository.get_file_exists('PATH', 'd7e96b3'))
        self.remote_repository.raw_file_url = (
            'http://github.com/api/v2/yaml/blob/show/reviewboard/<revision>')
        # Does not exist when raw_file_url changed because it is not cached.
        self.assertFalse(
            self.remote_repository.get_file_exists('PATH', 'd7e96b3'))
Ejemplo n.º 49
0
    def _test_ssh_with_site(self, repo_path, filename=None):
        """Helper for testing an SSH connection and using a Local Site.

        This will attempt to SSH into the local machine and connect to the
        given repository, using an SSH key and repository based on a Local
        Site. It will check the repository for validity and optionally fetch
        a file.

        If this is unable to connect to the local machine, the test will be
        flagged as skipped.

        Args:
            repo_path (unicode):
                The repository path to check.

            filename (unicode, optional):
                The optional file in the repository to fetch.
        """
        self._check_can_test_ssh()

        # Get the user's .ssh key, for use in the tests
        user_key = self.ssh_client.get_user_key()
        self.assertNotEqual(user_key, None)

        # Switch to a new SSH directory.
        self.tempdir = mkdtemp(prefix='rb-tests-home-')
        sshdir = os.path.join(self.tempdir, '.ssh')
        self._set_home(self.tempdir)

        self.assertEqual(sshdir, self.ssh_client.storage.get_ssh_dir())
        self.assertFalse(os.path.exists(os.path.join(sshdir, 'id_rsa')))
        self.assertFalse(os.path.exists(os.path.join(sshdir, 'id_dsa')))
        self.assertEqual(self.ssh_client.get_user_key(), None)

        tool_class = self.repository.tool

        # Make sure we aren't using the old SSH key. We want auth errors.
        repo = Repository(name='SSH Test', path=repo_path, tool=tool_class)
        tool = repo.get_scmtool()
        self.assertRaises(AuthenticationError,
                          lambda: tool.check_repository(repo_path))

        if filename:
            self.assertRaises(SCMError,
                              lambda: tool.get_file(filename, HEAD))

        for local_site_name in ('site-1',):
            local_site = LocalSite(name=local_site_name)
            local_site.save()

            repo = Repository(name='SSH Test', path=repo_path, tool=tool_class,
                              local_site=local_site)
            tool = repo.get_scmtool()

            ssh_client = SSHClient(namespace=local_site_name)
            self.assertEqual(ssh_client.storage.get_ssh_dir(),
                             os.path.join(sshdir, local_site_name))
            ssh_client.import_user_key(user_key)
            self.assertEqual(ssh_client.get_user_key(), user_key)

            # Make sure we can verify the repository and access files.
            tool.check_repository(repo_path, local_site_name=local_site_name)

            if filename:
                self.assertNotEqual(tool.get_file(filename, HEAD), None)
Ejemplo n.º 50
0
class PerforceTests(SpyAgency, SCMTestCase):
    """Unit tests for perforce.

    This uses the open server at public.perforce.com to test various
    pieces.  Because we have no control over things like pending
    changesets, not everything can be tested.
    """

    fixtures = ['test_scmtools']

    def setUp(self):
        super(PerforceTests, self).setUp()

        self.repository = Repository(name='Perforce.com',
                                     path='public.perforce.com:1666',
                                     username='******',
                                     encoding='none',
                                     tool=Tool.objects.get(name='Perforce'))

        try:
            self.tool = self.repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest('perforce/p4python is not installed')

    def tearDown(self):
        super(PerforceTests, self).tearDown()

        shutil.rmtree(os.path.join(settings.SITE_DATA_DIR, 'p4'),
                      ignore_errors=True)

    @online_only
    def test_changeset(self):
        """Testing PerforceTool.get_changeset"""
        desc = self.tool.get_changeset(157)
        self.assertEqual(desc.changenum, 157)
        self.assertEqual(type(desc.description), six.text_type)
        self.assertEqual(md5(desc.description.encode('utf-8')).hexdigest(),
                         'b7eff0ca252347cc9b09714d07397e64')

        expected_files = [
            '//public/perforce/api/python/P4Client/P4Clientmodule.cc',
            '//public/perforce/api/python/P4Client/p4.py',
            '//public/perforce/api/python/P4Client/review.py',
            '//public/perforce/python/P4Client/P4Clientmodule.cc',
            '//public/perforce/python/P4Client/p4.py',
            '//public/perforce/python/P4Client/review.py',
        ]

        for file, expected in zip_longest(desc.files, expected_files):
            self.assertEqual(file, expected)

        self.assertEqual(md5(desc.summary.encode('utf-8')).hexdigest(),
                         '99a335676b0e5821ffb2f7469d4d7019')

    @online_only
    def test_encoding(self):
        """Testing PerforceTool.get_changeset with a specified encoding"""
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          username='******',
                          tool=Tool.objects.get(name='Perforce'),
                          encoding='utf8')
        tool = repo.get_scmtool()

        try:
            tool.get_changeset(157)
            self.fail('Expected an error about unicode-enabled servers. Did '
                      'perforce.com turn on unicode for public.perforce.com?')
        except SCMError as e:
            # public.perforce.com doesn't have unicode enabled. Getting this
            # error means we at least passed the charset through correctly
            # to the p4 client.
            self.assertTrue('clients require a unicode enabled server' in
                            six.text_type(e))

    @online_only
    def test_changeset_broken(self):
        """Testing PerforceTool.get_changeset error conditions"""
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          username='******',
                          password='******',
                          encoding='none')

        try:
            tool = repo.get_scmtool()
        except ImportError:
            raise nose.SkipTest('perforce/p4python is not installed')

        self.assertRaises(AuthenticationError,
                          lambda: tool.get_changeset(157))

        repo = Repository(name='localhost:1',
                          path='localhost:1',
                          tool=Tool.objects.get(name='Perforce'))

        tool = repo.get_scmtool()
        self.assertRaises(RepositoryNotFoundError,
                          lambda: tool.get_changeset(1))

    @online_only
    def test_get_file(self):
        """Testing PerforceTool.get_file"""
        file = self.tool.get_file('//depot/foo', PRE_CREATION)
        self.assertEqual(file, b'')

        file = self.tool.get_file(
            '//public/perforce/api/python/P4Client/p4.py', 1)
        self.assertEqual(md5(file).hexdigest(),
                         '227bdd87b052fcad9369e65c7bf23fd0')

    @online_only
    def test_file_exists(self):
        """Testing PerforceTool.file_exists"""
        self.assertTrue(self.tool.file_exists(
            '//public/perforce/api/python/P4Client/p4.py', '1'))

        self.assertFalse(self.tool.file_exists(
            '//public/perforce/xxx-non-existent', '1'))

    @online_only
    def test_file_exists_with_pre_creation(self):
        """Testing PerforceTool.file_exists"""
        self.assertFalse(self.tool.file_exists('//depot/xxx-new-file',
                                               PRE_CREATION))

    @online_only
    def test_custom_host(self):
        """Testing Perforce client initialization with a custom P4HOST"""
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          username='******',
                          tool=Tool.objects.get(name='Perforce'),
                          encoding='utf8')
        repo.extra_data['p4_host'] = 'my-custom-host'

        tool = repo.get_scmtool()

        with tool.client.connect():
            self.assertEqual(tool.client.p4.host, 'my-custom-host')

    def test_ticket_login(self):
        """Testing Perforce with ticket-based logins"""
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          username='******',
                          password='******')
        repo.extra_data = {
            'use_ticket_auth': True,
        }

        client = repo.get_scmtool().client
        self.assertTrue(client.use_ticket_auth)

        self.spy_on(client.get_ticket_status, call_fake=lambda *args: {
            'user': '******',
            'expiration_secs': 100000,
        })

        self.spy_on(client.login, call_original=False)

        self.assertFalse(os.path.exists(os.path.join(
            settings.SITE_DATA_DIR, 'p4', 'p4tickets')))

        with client.connect():
            self.assertFalse(client.login.called)
            self.assertEqual(client.p4.ticket_file,
                             os.path.join(settings.SITE_DATA_DIR, 'p4',
                                          'p4tickets'))

    def test_ticket_login_with_expiring_ticket(self):
        """Testing Perforce with ticket-based logins with ticket close to
        expiring
        """
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          username='******',
                          password='******')
        repo.extra_data = {
            'use_ticket_auth': True,
        }

        client = repo.get_scmtool().client
        self.assertTrue(client.use_ticket_auth)

        self.spy_on(client.get_ticket_status, call_fake=lambda *args: {
            'user': '******',
            'expiration_secs': 99,
        })

        self.spy_on(client.login, call_original=False)

        with client.connect():
            self.assertIsNotNone(client.p4.ticket_file)
            self.assertTrue(client.login.called)
            self.assertEqual(client.p4.ticket_file,
                             os.path.join(settings.SITE_DATA_DIR, 'p4',
                                          'p4tickets'))

    def test_ticket_login_with_no_valid_ticket(self):
        """Testing Perforce with ticket-based logins without a valid ticket
        """
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          username='******',
                          password='******')
        repo.extra_data = {
            'use_ticket_auth': True,
        }

        client = repo.get_scmtool().client
        self.assertTrue(client.use_ticket_auth)

        self.spy_on(client.get_ticket_status, call_fake=lambda *args: None)
        self.spy_on(client.login, call_original=False)

        with client.connect():
            self.assertTrue(client.login.called)
            self.assertEqual(client.p4.ticket_file,
                             os.path.join(settings.SITE_DATA_DIR, 'p4',
                                          'p4tickets'))

    def test_ticket_login_with_different_user(self):
        """Testing Perforce with ticket-based logins with ticket for a
        different user
        """
        repo = Repository(name='Perforce.com',
                          path='public.perforce.com:1666',
                          tool=Tool.objects.get(name='Perforce'),
                          username='******',
                          password='******')
        repo.extra_data = {
            'use_ticket_auth': True,
        }

        client = repo.get_scmtool().client
        self.assertTrue(client.use_ticket_auth)

        self.spy_on(client.get_ticket_status, call_fake=lambda *args: {
            'user': '******',
            'expiration_secs': 100000,
        })

        self.spy_on(client.login, call_original=False)

        with client.connect():
            self.assertTrue(client.login.called)
            self.assertEqual(client.p4.ticket_file,
                             os.path.join(settings.SITE_DATA_DIR, 'p4',
                                          'p4tickets'))

    @add_fixtures(['test_site'])
    def test_ticket_login_with_local_site(self):
        """Testing Perforce with ticket-based logins with Local Sites"""
        repo = Repository(
            name='Perforce.com',
            path='public.perforce.com:1666',
            tool=Tool.objects.get(name='Perforce'),
            username='******',
            password='******',
            local_site=LocalSite.objects.get(name='local-site-1'))
        repo.extra_data = {
            'use_ticket_auth': True,
        }

        client = repo.get_scmtool().client
        self.assertTrue(client.use_ticket_auth)

        self.spy_on(client.get_ticket_status, call_fake=lambda *args: {
            'user': '******',
            'expiration_secs': 100000,
        })

        self.spy_on(client.login, call_original=False)

        with client.connect():
            self.assertFalse(client.login.called)
            self.assertEqual(client.p4.ticket_file,
                             os.path.join(settings.SITE_DATA_DIR, 'p4',
                                          'local-site-1', 'p4tickets'))

    @online_only
    def test_parse_diff_revision_with_revision_eq_0(self):
        """Testing Perforce.parse_diff_revision with revision == 0"""
        self.assertEqual(
            self.tool.parse_diff_revision(
                'xxx-foo.py', '//public/perforce/xxx-foo.py#0'),
            ('//public/perforce/xxx-foo.py', PRE_CREATION))

    @online_only
    def test_parse_diff_revision_with_revision_eq_1_and_existing(self):
        """Testing Perforce.parse_diff_revision with revision == 1 and existing
        file
        """
        self.assertEqual(
            self.tool.parse_diff_revision(
                'p4.p', '//public/perforce/api/python/P4Client/p4.py#1'),
            ('//public/perforce/api/python/P4Client/p4.py', '1'))

    @online_only
    def test_parse_diff_revision_with_revision_eq_1_and_new(self):
        """Testing Perforce.parse_diff_revision with revision == 1 and new file
        """
        self.assertEqual(
            self.tool.parse_diff_revision('xxx-newfile',
                                          '//public/perforce/xxx-newfile#1'),
            ('//public/perforce/xxx-newfile', PRE_CREATION))

    @online_only
    def test_parse_diff_revision_with_revision_gt_1(self):
        """Testing Perforce.parse_diff_revision with revision > 1"""
        self.assertEqual(
            self.tool.parse_diff_revision('xxx-foo.py',
                                          '//public/perforce/xxx-foo.py#2'),
            ('//public/perforce/xxx-foo.py', '2'))

    def test_empty_diff(self):
        """Testing Perforce empty diff parsing"""
        diff = b'==== //depot/foo/proj/README#2 ==M== /src/proj/README ====\n'

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, '//depot/foo/proj/README')
        self.assertEqual(file.origInfo, '//depot/foo/proj/README#2')
        self.assertEqual(file.newFile, '/src/proj/README')
        self.assertEqual(file.newInfo, '')
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertFalse(file.moved)
        self.assertEqual(file.data, diff)
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_binary_diff(self):
        """Testing Perforce binary diff parsing"""
        diff = (b'==== //depot/foo/proj/test.png#1 ==A== /src/proj/test.png '
                b'====\nBinary files /tmp/foo and /src/proj/test.png differ\n')

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, '//depot/foo/proj/test.png')
        self.assertEqual(file.origInfo, '//depot/foo/proj/test.png#1')
        self.assertEqual(file.newFile, '/src/proj/test.png')
        self.assertEqual(file.newInfo, '')
        self.assertEqual(file.data, diff)
        self.assertTrue(file.binary)
        self.assertFalse(file.deleted)
        self.assertFalse(file.moved)
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_deleted_diff(self):
        """Testing Perforce deleted diff parsing"""
        diff = (b'==== //depot/foo/proj/test.png#1 ==D== /src/proj/test.png '
                b'====\n')

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, '//depot/foo/proj/test.png')
        self.assertEqual(file.origInfo, '//depot/foo/proj/test.png#1')
        self.assertEqual(file.newFile, '/src/proj/test.png')
        self.assertEqual(file.newInfo, '')
        self.assertEqual(file.data, diff)
        self.assertFalse(file.binary)
        self.assertTrue(file.deleted)
        self.assertFalse(file.moved)
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_moved_file_diff(self):
        """Testing Perforce moved file diff parsing"""
        diff = (
            b'Moved from: //depot/foo/proj/test.txt\n'
            b'Moved to: //depot/foo/proj/test2.txt\n'
            b'--- //depot/foo/proj/test.txt  //depot/foo/proj/test.txt#2\n'
            b'+++ //depot/foo/proj/test2.txt  01-02-03 04:05:06\n'
            b'@@ -1 +1,2 @@\n'
            b'-test content\n'
            b'+updated test content\n'
            b'+added info\n'
        )

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, '//depot/foo/proj/test.txt')
        self.assertEqual(file.origInfo, '//depot/foo/proj/test.txt#2')
        self.assertEqual(file.newFile, '//depot/foo/proj/test2.txt')
        self.assertEqual(file.newInfo, '01-02-03 04:05:06')
        self.assertEqual(file.data, diff)
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertTrue(file.moved)
        self.assertEqual(file.data, diff)
        self.assertEqual(file.insert_count, 2)
        self.assertEqual(file.delete_count, 1)

    def test_moved_file_diff_no_changes(self):
        """Testing Perforce moved file diff parsing without changes"""
        diff = (b'==== //depot/foo/proj/test.png#5 ==MV== '
                b'//depot/foo/proj/test2.png ====\n')

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, '//depot/foo/proj/test.png')
        self.assertEqual(file.origInfo, '//depot/foo/proj/test.png#5')
        self.assertEqual(file.newFile, '//depot/foo/proj/test2.png')
        self.assertEqual(file.newInfo, '')
        self.assertEqual(file.data, diff)
        self.assertFalse(file.binary)
        self.assertFalse(file.deleted)
        self.assertTrue(file.moved)
        self.assertEqual(file.insert_count, 0)
        self.assertEqual(file.delete_count, 0)

    def test_empty_and_normal_diffs(self):
        """Testing Perforce empty and normal diff parsing"""
        diff1_text = (b'==== //depot/foo/proj/test.png#1 ==A== '
                      b'/src/proj/test.png ====\n')
        diff2_text = (b'--- test.c  //depot/foo/proj/test.c#2\n'
                      b'+++ test.c  01-02-03 04:05:06\n'
                      b'@@ -1 +1,2 @@\n'
                      b'-test content\n'
                      b'+updated test content\n'
                      b'+added info\n')
        diff = diff1_text + diff2_text

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 2)
        self.assertEqual(files[0].origFile, '//depot/foo/proj/test.png')
        self.assertEqual(files[0].origInfo, '//depot/foo/proj/test.png#1')
        self.assertEqual(files[0].newFile, '/src/proj/test.png')
        self.assertEqual(files[0].newInfo, '')
        self.assertFalse(files[0].binary)
        self.assertFalse(files[0].deleted)
        self.assertFalse(files[0].moved)
        self.assertEqual(files[0].data, diff1_text)
        self.assertEqual(files[0].insert_count, 0)
        self.assertEqual(files[0].delete_count, 0)

        self.assertEqual(files[1].origFile, 'test.c')
        self.assertEqual(files[1].origInfo, '//depot/foo/proj/test.c#2')
        self.assertEqual(files[1].newFile, 'test.c')
        self.assertEqual(files[1].newInfo, '01-02-03 04:05:06')
        self.assertFalse(files[1].binary)
        self.assertFalse(files[1].deleted)
        self.assertFalse(files[1].moved)
        self.assertEqual(files[1].data, diff2_text)
        self.assertEqual(files[1].insert_count, 2)
        self.assertEqual(files[1].delete_count, 1)

    def test_diff_file_normalization(self):
        """Testing perforce diff filename normalization"""
        parser = self.tool.get_parser('')
        self.assertEqual(parser.normalize_diff_filename('//depot/test'),
                         '//depot/test')

    def test_unicode_diff(self):
        """Testing Perforce diff parsing with unicode characters"""
        diff = ('--- tést.c  //depot/foo/proj/tést.c#2\n'
                '+++ tést.c  01-02-03 04:05:06\n'
                '@@ -1 +1,2 @@\n'
                '-tést content\n'
                '+updated test content\n'
                '+added info\n').encode('utf-8')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)
        self.assertEqual(files[0].origFile, 'tést.c')
        self.assertEqual(files[0].origInfo, '//depot/foo/proj/tést.c#2')
        self.assertEqual(files[0].newFile, 'tést.c')
        self.assertEqual(files[0].newInfo, '01-02-03 04:05:06')
        self.assertFalse(files[0].binary)
        self.assertFalse(files[0].deleted)
        self.assertFalse(files[0].moved)
        self.assertEqual(files[0].insert_count, 2)
        self.assertEqual(files[0].delete_count, 1)
Ejemplo n.º 51
0
class BZRTests(SCMTestCase):
    """Unit tests for bzr."""

    fixtures = ['test_scmtools']

    def setUp(self):
        super(BZRTests, self).setUp()

        if not is_exe_in_path('bzr'):
            raise nose.SkipTest()

        self.bzr_repo_path = os.path.join(os.path.dirname(__file__),
                                          '..', 'testdata', 'bzr_repo')
        self.bzr_ssh_path = ('bzr+ssh://localhost/%s'
                             % self.bzr_repo_path.replace('\\', '/'))
        self.bzr_sftp_path = ('sftp://localhost/%s'
                              % self.bzr_repo_path.replace('\\', '/'))
        self.repository = Repository(name='Bazaar',
                                     path='file://' + self.bzr_repo_path,
                                     tool=Tool.objects.get(name='Bazaar'))

        self.tool = self.repository.get_scmtool()

    def test_check_repository(self):
        """Testing BZRTool.check_repository"""
        self.tool.check_repository(self.repository.path)

    def test_check_repository_with_not_found(self):
        """Testing BZRTool.check_repository with repository not found"""
        with self.assertRaises(RepositoryNotFoundError):
            self.tool.check_repository('file:///dummy')

    def test_ssh(self):
        """Testing BZRTool with a SSH-backed repository"""
        self._test_ssh(self.bzr_ssh_path, 'README')

    def test_ssh_with_site(self):
        """Testing BZRTool with a SSH-backed repository with a LocalSite"""
        self._test_ssh_with_site(self.bzr_ssh_path, 'README')

    def test_sftp(self):
        """Testing BZRTool with a SFTP-backed repository"""
        try:
            self._test_ssh(self.bzr_sftp_path, 'README')
        except SCMError as e:
            err = six.text_type(e)

            if 'Installed bzr and paramiko modules are incompatible' in err:
                raise nose.SkipTest(err)

            raise

    def test_get_file(self):
        """Testing BZRTool.get_file"""
        content = self.tool.get_file('README', '2011-02-02 10:53:04 +0000')
        self.assertEqual(content, b'This is a test.\n')
        self.assertIsInstance(content, bytes)

    def test_get_file_with_timezone_offset(self):
        """Testing BZRTool.get_file with timezone offset"""
        content = self.tool.get_file('README', '2011-02-02 02:53:04 -0800')
        self.assertEqual(content, b'This is a test.\n')
        self.assertIsInstance(content, bytes)

    def test_get_file_with_non_utc_server_timezone(self):
        """Testing BZRTool.get_file with settings.TIME_ZONE != UTC"""
        old_timezone = os.environ[b'TZ']
        os.environ[b'TZ'] = b'US/Pacific'

        try:
            content = self.tool.get_file('README', '2011-02-02 02:53:04 -0800')
        finally:
            os.environ[b'TZ'] = old_timezone

        self.assertEqual(content, b'This is a test.\n')
        self.assertIsInstance(content, bytes)

    def test_get_file_with_revision_id(self):
        """Testing BZRTool.get_file with revision ID"""
        content = self.tool.get_file(
            'README',
            'revid:[email protected]')
        self.assertEqual(content, b'This is a test.\n')
        self.assertIsInstance(content, bytes)

    def test_get_file_with_unknown_file(self):
        """Testing BZRTool.get_file with unknown file"""
        with self.assertRaises(FileNotFoundError):
            self.tool.get_file('NOT_REAL', '2011-02-02 02:53:04 -0800')

    def test_get_file_with_unknown_revision(self):
        """Testing BZRTool.get_file with unknown revision"""
        with self.assertRaises(FileNotFoundError):
            self.tool.get_file('README', '9999-02-02 02:53:04 -0800')

    def test_get_file_with_invalid_revision(self):
        """Testing BZRTool.get_file with invalid revision"""
        with self.assertRaises(InvalidRevisionFormatError):
            self.tool.get_file('README', '\o/')

    def test_file_exists(self):
        """Testing BZRTool.files_exists"""
        self.assertTrue(self.tool.file_exists(
            'README',
            '2011-02-02 10:53:04 +0000'))

        self.assertFalse(self.tool.file_exists(
            'NOT_REAL',
            '2011-02-02 10:53:04 +0000'))
        self.assertFalse(self.tool.file_exists(
            'README',
            '9999-02-02 10:53:04 +0000'))

    def test_file_exists_with_timezone_offset(self):
        """Testing BZRTool.files_exists with timezone offset"""
        self.assertTrue(self.tool.file_exists(
            'README',
            '2011-02-02 02:53:04 -0800'))

    def test_file_exists_with_non_utc_server_timezone(self):
        """Testing BZRTool.files_exists with settings.TIME_ZONE != UTC"""
        old_timezone = os.environ[b'TZ']
        os.environ[b'TZ'] = b'US/Pacific'

        try:
            self.assertTrue(self.tool.file_exists(
                'README',
                '2011-02-02 02:53:04 -0800'))
        finally:
            os.environ[b'TZ'] = old_timezone

    def test_file_exists_with_revision_id(self):
        """Testing BZRTool.files_exists with revision ID"""
        self.assertTrue(self.tool.file_exists(
            'README',
            'revid:[email protected]'))

    def test_file_exists_with_invalid_revision(self):
        """Testing BZRTool.files_exists with invalid revision"""
        with self.assertRaises(InvalidRevisionFormatError):
            self.tool.file_exists('README', '\o/')
Ejemplo n.º 52
0
class PerforceStunnelTests(SCMTestCase):
    """Unit tests for perforce running through stunnel.

    Out of the box, Perforce doesn't support any kind of encryption on its
    connections. The recommended setup in this case is to run an stunnel server
    on the perforce server which bounces SSL connections to the normal p4 port.
    One can then start an stunnel on their client machine and connect via a
    localhost: P4PORT.

    For these tests, we set up an stunnel server which will accept secure
    connections and proxy (insecurely) to the public perforce server. We can
    then tell the Perforce SCMTool to connect securely to localhost.
    """

    fixtures = ['test_scmtools']

    def setUp(self):
        super(PerforceStunnelTests, self).setUp()

        if not is_exe_in_path('stunnel'):
            raise nose.SkipTest('stunnel is not installed')

        cert = os.path.join(os.path.dirname(__file__),
                            '..', 'testdata', 'stunnel.pem')
        self.proxy = STunnelProxy('public.perforce.com:1666')
        self.proxy.start_server(cert)

        # Find an available port to listen on
        path = 'stunnel:localhost:%d' % self.proxy.port

        self.repository = Repository(name='Perforce.com - secure',
                                     path=path,
                                     username='******',
                                     encoding='none',
                                     tool=Tool.objects.get(name='Perforce'))

        try:
            self.tool = self.repository.get_scmtool()
            self.tool.use_stunnel = True
        except ImportError:
            raise nose.SkipTest('perforce/p4python is not installed')

    def tearDown(self):
        super(PerforceStunnelTests, self).tearDown()

        self.proxy.shutdown()

    def test_changeset(self):
        """Testing PerforceTool.get_changeset with stunnel"""
        desc = self.tool.get_changeset(157)

        self.assertEqual(desc.changenum, 157)
        self.assertEqual(md5(desc.description.encode('utf-8')).hexdigest(),
                         'b7eff0ca252347cc9b09714d07397e64')

        expected_files = [
            '//public/perforce/api/python/P4Client/P4Clientmodule.cc',
            '//public/perforce/api/python/P4Client/p4.py',
            '//public/perforce/api/python/P4Client/review.py',
            '//public/perforce/python/P4Client/P4Clientmodule.cc',
            '//public/perforce/python/P4Client/p4.py',
            '//public/perforce/python/P4Client/review.py',
        ]

        for file, expected in zip_longest(desc.files, expected_files):
            self.assertEqual(file, expected)

        self.assertEqual(md5(desc.summary.encode('utf-8')).hexdigest(),
                         '99a335676b0e5821ffb2f7469d4d7019')

    def test_get_file(self):
        """Testing PerforceTool.get_file with stunnel"""
        file = self.tool.get_file('//depot/foo', PRE_CREATION)
        self.assertEqual(file, '')

        try:
            file = self.tool.get_file(
                '//public/perforce/api/python/P4Client/p4.py', 1)
        except Exception as e:
            if six.text_type(e).startswith('Connect to server failed'):
                raise nose.SkipTest(
                    'Connection to public.perforce.com failed.  No internet?')
            else:
                raise

        self.assertEqual(md5(file).hexdigest(),
                         '227bdd87b052fcad9369e65c7bf23fd0')
Ejemplo n.º 53
0
class CommonSVNTestCase(SpyAgency, SCMTestCase):
    """Common unit tests for Subversion.

    This is meant to be subclassed for each backend that wants to run
    the common set of tests.
    """

    backend = None
    backend_name = None
    fixtures = ['test_scmtools']

    def setUp(self):
        super(CommonSVNTestCase, self).setUp()

        self._old_backend_setting = settings.SVNTOOL_BACKENDS
        settings.SVNTOOL_BACKENDS = [self.backend]
        recompute_svn_backend()

        self.svn_repo_path = os.path.abspath(
            os.path.join(os.path.dirname(__file__),
                         '..', 'testdata', 'svn_repo'))
        self.svn_ssh_path = ('svn+ssh://localhost%s'
                             % self.svn_repo_path.replace('\\', '/'))
        self.repository = Repository(name='Subversion SVN',
                                     path='file://' + self.svn_repo_path,
                                     tool=Tool.objects.get(name='Subversion'))

        try:
            self.tool = self.repository.get_scmtool()
        except ImportError:
            raise nose.SkipTest('The %s backend could not be used. A '
                                'dependency may be missing.'
                                % self.backend)

        assert self.tool.client.__class__.__module__ == self.backend

    def tearDown(self):
        super(CommonSVNTestCase, self).tearDown()

        settings.SVNTOOL_BACKENDS = self._old_backend_setting
        recompute_svn_backend()

    def shortDescription(self):
        desc = super(CommonSVNTestCase, self).shortDescription()
        desc = desc.replace('<backend>', self.backend_name)

        return desc

    def test_ssh(self):
        """Testing SVN (<backend>) with a SSH-backed Subversion repository"""
        self._test_ssh(self.svn_ssh_path, 'trunk/doc/misc-docs/Makefile')

    def test_ssh_with_site(self):
        """Testing SVN (<backend>) with a SSH-backed Subversion repository
        with a LocalSite
        """
        self._test_ssh_with_site(self.svn_ssh_path,
                                 'trunk/doc/misc-docs/Makefile')

    def test_get_file(self):
        """Testing SVN (<backend>) get_file"""
        expected = (b'include ../tools/Makefile.base-vars\n'
                    b'NAME = misc-docs\n'
                    b'OUTNAME = svn-misc-docs\n'
                    b'INSTALL_DIR = $(DESTDIR)/usr/share/doc/subversion\n'
                    b'include ../tools/Makefile.base-rules\n')

        # There are 3 versions of this test in order to get 100% coverage of
        # the svn module.
        rev = Revision('2')
        file = 'trunk/doc/misc-docs/Makefile'

        value = self.tool.get_file(file, rev)
        self.assertTrue(isinstance(value, bytes))
        self.assertEqual(value, expected)

        self.assertEqual(self.tool.get_file('/' + file, rev), expected)

        self.assertEqual(
            self.tool.get_file(self.repository.path + '/' + file, rev),
            expected)

        self.assertTrue(self.tool.file_exists('trunk/doc/misc-docs/Makefile'))
        self.assertTrue(
            not self.tool.file_exists('trunk/doc/misc-docs/Makefile2'))

        self.assertRaises(FileNotFoundError, lambda: self.tool.get_file(''))

        self.assertRaises(FileNotFoundError,
                          lambda: self.tool.get_file('hello', PRE_CREATION))

    def test_revision_parsing(self):
        """Testing SVN (<backend>) revision number parsing"""
        self.assertEqual(
            self.tool.parse_diff_revision('', '(working copy)')[1],
            HEAD)
        self.assertEqual(
            self.tool.parse_diff_revision('', '   (revision 0)')[1],
            PRE_CREATION)

        self.assertEqual(self.tool.parse_diff_revision('', '(revision 1)')[1],
                         '1')
        self.assertEqual(self.tool.parse_diff_revision('', '(revision 23)')[1],
                         '23')

        # Fix for bug 2176
        self.assertEqual(
            self.tool.parse_diff_revision('', '\t(revision 4)')[1], '4')

        self.assertEqual(
            self.tool.parse_diff_revision(
                '', '2007-06-06 15:32:23 UTC (rev 10958)')[1],
            '10958')

        # Fix for bug 2632
        self.assertEqual(self.tool.parse_diff_revision('', '(revision )')[1],
                         PRE_CREATION)

        self.assertRaises(SCMError,
                          lambda: self.tool.parse_diff_revision('', 'hello'))

        # Verify that 'svn diff' localized revision strings parse correctly.
        self.assertEqual(self.tool.parse_diff_revision('', '(revisión: 5)')[1],
                         '5')
        self.assertEqual(self.tool.parse_diff_revision('',
                         '(リビジョン 6)')[1], '6')
        self.assertEqual(self.tool.parse_diff_revision('', '(版本 7)')[1],
                         '7')

    def test_revision_parsing_with_nonexistent(self):
        """Testing SVN (<backend>) revision parsing with "(nonexistent)"
        revision indicator
        """
        # English
        self.assertEqual(
            self.tool.parse_diff_revision('', '(nonexistent)')[1],
            PRE_CREATION)

        # German
        self.assertEqual(
            self.tool.parse_diff_revision('', '(nicht existent)')[1],
            PRE_CREATION)

        # Simplified Chinese
        self.assertEqual(
            self.tool.parse_diff_revision('', '(不存在的)')[1],
            PRE_CREATION)

    def test_revision_parsing_with_nonexistent_and_branches(self):
        """Testing SVN (<backend>) revision parsing with relocation
        information and nonexisitent revision specifier.
        """
        self.assertEqual(
            self.tool.parse_diff_revision(
                '', '(.../trunk) (nonexistent)')[1],
            PRE_CREATION)

        self.assertEqual(
            self.tool.parse_diff_revision(
                '', '(.../branches/branch-1.0)     (nicht existent)')[1],
            PRE_CREATION)

        self.assertEqual(
            self.tool.parse_diff_revision(
                '', '        (.../trunk)     (不存在的)')[1],
            PRE_CREATION)

    def test_interface(self):
        """Testing SVN (<backend>) with basic SVNTool API"""
        self.assertFalse(self.tool.diffs_use_absolute_paths)

        self.assertRaises(NotImplementedError,
                          lambda: self.tool.get_changeset(1))

    def test_binary_diff(self):
        """Testing SVN (<backend>) parsing SVN diff with binary file"""
        diff = (b'Index: binfile\n'
                b'============================================================'
                b'=======\n'
                b'Cannot display: file marked as a binary type.\n'
                b'svn:mime-type = application/octet-stream\n')

        file = self.tool.get_parser(diff).parse()[0]
        self.assertEqual(file.origFile, 'binfile')
        self.assertEqual(file.binary, True)

    def test_keyword_diff(self):
        """Testing SVN (<backend>) parsing diff with keywords"""
        # 'svn cat' will expand special variables in svn:keywords,
        # but 'svn diff' doesn't expand anything.  This causes the
        # patch to fail if those variables appear in the patch context.
        diff = (b'Index: Makefile\n'
                b'==========================================================='
                b'========\n'
                b'--- Makefile    (revision 4)\n'
                b'+++ Makefile    (working copy)\n'
                b'@@ -1,6 +1,7 @@\n'
                b' # $Id$\n'
                b' # $Rev$\n'
                b' # $Revision::     $\n'
                b'+# foo\n'
                b' include ../tools/Makefile.base-vars\n'
                b' NAME = misc-docs\n'
                b' OUTNAME = svn-misc-docs\n')

        filename = 'trunk/doc/misc-docs/Makefile'
        rev = Revision('4')
        file = self.tool.get_file(filename, rev)
        patch(diff, file, filename)

    def test_unterminated_keyword_diff(self):
        """Testing SVN (<backend>) parsing diff with unterminated keywords"""
        diff = (b'Index: Makefile\n'
                b'==========================================================='
                b'========\n'
                b'--- Makefile    (revision 4)\n'
                b'+++ Makefile    (working copy)\n'
                b'@@ -1,6 +1,7 @@\n'
                b' # $Id$\n'
                b' # $Id:\n'
                b' # $Rev$\n'
                b' # $Revision::     $\n'
                b'+# foo\n'
                b' include ../tools/Makefile.base-vars\n'
                b' NAME = misc-docs\n'
                b' OUTNAME = svn-misc-docs\n')

        filename = 'trunk/doc/misc-docs/Makefile'
        rev = Revision('5')
        file = self.tool.get_file(filename, rev)
        patch(diff, file, filename)

    def test_svn16_property_diff(self):
        """Testing SVN (<backend>) parsing SVN 1.6 diff with property changes
        """
        prop_diff = (
            b'Index:\n'
            b'======================================================'
            b'=============\n'
            b'--- (revision 123)\n'
            b'+++ (working copy)\n'
            b'Property changes on: .\n'
            b'______________________________________________________'
            b'_____________\n'
            b'Modified: reviewboard:url\n'
            b'## -1 +1 ##\n'
            b'-http://reviews.reviewboard.org\n'
            b'+http://reviews.reviewboard.org\n')
        bin_diff = (
            b'Index: binfile\n'
            b'======================================================='
            b'============\nCannot display: file marked as a '
            b'binary type.\nsvn:mime-type = application/octet-stream\n')
        diff = prop_diff + bin_diff

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)
        self.assertEqual(files[0].origFile, 'binfile')
        self.assertTrue(files[0].binary)
        self.assertEqual(files[0].insert_count, 0)
        self.assertEqual(files[0].delete_count, 0)

    def test_svn17_property_diff(self):
        """Testing SVN (<backend>) parsing SVN 1.7+ diff with property changes
        """
        prop_diff = (
            b'Index .:\n'
            b'======================================================'
            b'=============\n'
            b'--- .  (revision 123)\n'
            b'+++ .  (working copy)\n'
            b'\n'
            b'Property changes on: .\n'
            b'______________________________________________________'
            b'_____________\n'
            b'Modified: reviewboard:url\n'
            b'## -0,0 +1,3 ##\n'
            b'-http://reviews.reviewboard.org\n'
            b'+http://reviews.reviewboard.org\n'
            b'Added: myprop\n'
            b'## -0,0 +1 ##\n'
            b'+Property test.\n')
        bin_diff = (
            b'Index: binfile\n'
            b'======================================================='
            b'============\nCannot display: file marked as a '
            b'binary type.\nsvn:mime-type = application/octet-stream\n')
        diff = prop_diff + bin_diff

        files = self.tool.get_parser(diff).parse()

        self.assertEqual(len(files), 1)
        self.assertEqual(files[0].origFile, 'binfile')
        self.assertTrue(files[0].binary)
        self.assertEqual(files[0].insert_count, 0)
        self.assertEqual(files[0].delete_count, 0)

    def test_unicode_diff(self):
        """Testing SVN (<backend>) parsing diff with unicode characters"""
        diff = ('Index: Filé\n'
                '==========================================================='
                '========\n'
                '--- Filé    (revision 4)\n'
                '+++ Filé    (working copy)\n'
                '@@ -1,6 +1,7 @@\n'
                '+# foó\n'
                ' include ../tools/Makefile.base-vars\n'
                ' NAME = misc-docs\n'
                ' OUTNAME = svn-misc-docs\n').encode('utf-8')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)
        self.assertEqual(files[0].origFile, 'Filé')
        self.assertFalse(files[0].binary)
        self.assertEqual(files[0].insert_count, 1)
        self.assertEqual(files[0].delete_count, 0)

    def test_diff_with_spaces_in_filenames(self):
        """Testing SVN (<backend>) parsing diff with spaces in filenames"""
        diff = (b'Index: File with spaces\n'
                b'==========================================================='
                b'========\n'
                b'--- File with spaces    (revision 4)\n'
                b'+++ File with spaces    (working copy)\n'
                b'@@ -1,6 +1,7 @@\n'
                b'+# foo\n'
                b' include ../tools/Makefile.base-vars\n'
                b' NAME = misc-docs\n'
                b' OUTNAME = svn-misc-docs\n')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)
        self.assertEqual(files[0].origFile, 'File with spaces')
        self.assertFalse(files[0].binary)
        self.assertEqual(files[0].insert_count, 1)
        self.assertEqual(files[0].delete_count, 0)

    def test_diff_with_added_empty_file(self):
        """Testing parsing SVN diff with added empty file"""
        diff = (b'Index: empty-file\t(added)\n'
                b'==========================================================='
                b'========\n'
                b'--- empty-file\t(revision 0)\n'
                b'+++ empty-file\t(revision 0)\n')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)
        self.assertEqual(files[0].origFile, 'empty-file')
        self.assertEqual(files[0].newFile, 'empty-file')
        self.assertEqual(files[0].origInfo, '(revision 0)')
        self.assertEqual(files[0].newInfo, '(revision 0)')
        self.assertFalse(files[0].binary)
        self.assertFalse(files[0].deleted)
        self.assertEqual(files[0].insert_count, 0)
        self.assertEqual(files[0].delete_count, 0)

    def test_diff_with_deleted_empty_file(self):
        """Testing parsing SVN diff with deleted empty file"""
        diff = (b'Index: empty-file\t(deleted)\n'
                b'==========================================================='
                b'========\n'
                b'--- empty-file\t(revision 4)\n'
                b'+++ empty-file\t(working copy)\n')

        files = self.tool.get_parser(diff).parse()
        self.assertEqual(len(files), 1)
        self.assertEqual(files[0].origFile, 'empty-file')
        self.assertEqual(files[0].newFile, 'empty-file')
        self.assertEqual(files[0].origInfo, '(revision 4)')
        self.assertEqual(files[0].newInfo, '(working copy)')
        self.assertFalse(files[0].binary)
        self.assertTrue(files[0].deleted)
        self.assertEqual(files[0].insert_count, 0)
        self.assertEqual(files[0].delete_count, 0)

    def test_get_branches(self):
        """Testing SVN (<backend>) get_branches"""
        branches = self.tool.get_branches()

        self.assertEqual(len(branches), 3)
        self.assertEqual(branches[0], Branch(id='trunk', name='trunk',
                                             commit='9', default=True))
        self.assertEqual(branches[1], Branch(id='branches/branch1',
                                             name='branch1',
                                             commit='7', default=False))
        self.assertEqual(branches[2], Branch(id='top-level-branch',
                                             name='top-level-branch',
                                             commit='10', default=False))

    def test_get_commits(self):
        """Testing SVN (<backend>) get_commits"""
        commits = self.tool.get_commits(start='5')

        self.assertEqual(len(commits), 5)
        self.assertEqual(
            commits[0],
            Commit('chipx86',
                   '5',
                   '2010-05-21T09:33:40.893946',
                   'Add an unterminated keyword for testing bug #1523\n',
                   '4'))

        commits = self.tool.get_commits(start='7')
        self.assertEqual(len(commits), 7)
        self.assertEqual(
            commits[1],
            Commit('david',
                   '6',
                   '2013-06-13T07:43:04.725088',
                   'Add a branches directory',
                   '5'))

    def test_get_commits_with_branch(self):
        """Testing SVN (<backend>) get_commits with branch"""
        commits = self.tool.get_commits(branch='/branches/branch1', start='5')

        self.assertEqual(len(commits), 5)
        self.assertEqual(
            commits[0],
            Commit('chipx86',
                   '5',
                   '2010-05-21T09:33:40.893946',
                   'Add an unterminated keyword for testing bug #1523\n',
                   '4'))

        commits = self.tool.get_commits(branch='/branches/branch1', start='7')
        self.assertEqual(len(commits), 6)
        self.assertEqual(
            commits[0],
            Commit('david',
                   '7',
                   '2013-06-13T07:43:27.259554',
                   'Add a branch',
                   '5'))
        self.assertEqual(
            commits[1],
            Commit('chipx86',
                   '5',
                   '2010-05-21T09:33:40.893946',
                   'Add an unterminated keyword for testing bug #1523\n',
                   '4'))

    def test_get_commits_with_no_date(self):
        """Testing SVN (<backend>) get_commits with no date in commit"""
        def _get_log(*args, **kwargs):
            return [
                {
                    'author': 'chipx86',
                    'revision': '5',
                    'message': 'Commit 1',
                },
            ]

        self.spy_on(self.tool.client.get_log, _get_log)

        commits = self.tool.get_commits(start='5')

        self.assertEqual(len(commits), 1)
        self.assertEqual(
            commits[0],
            Commit('chipx86',
                   '5',
                   '',
                   'Commit 1'))

    def test_get_change(self):
        """Testing SVN (<backend>) get_change"""
        commit = self.tool.get_change('5')

        self.assertEqual(md5(commit.message.encode('utf-8')).hexdigest(),
                         '928336c082dd756e3f7af4cde4724ebf')
        self.assertEqual(md5(commit.diff.encode('utf-8')).hexdigest(),
                         '56e50374056931c03a333f234fa63375')

    def test_utf8_keywords(self):
        """Testing SVN (<backend>) with UTF-8 files with keywords"""
        self.repository.get_file('trunk/utf8-file.txt', '9')