Exemple #1
0
    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_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, str)
        self.assertEqual(tool.client.client_name, 'test-client')
Exemple #3
0
    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')))
    def test_run_worker_with_unverified_cert_new(self):
        """Testing PerforceTool.run_worker with new unverified certificate"""
        self.repository.path = 'p4.example.com:1666'

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

        fingerprint = \
            'A0:B1:C2:D3:E4:F5:6A:7B:8C:9D:E0:F1:2A:3B:4C:5D:6E:7F:A1:B2'

        err_msg = (
            "The authenticity of '1.2.3.4:1666' can't be established,\\n"
            "this may be your first attempt to connect to this P4PORT.\\n"
            "The fingerprint for the key sent to your client is\\n"
            "%s\\n"
            "To allow connection use the 'p4 trust' command.\\n"
            % fingerprint
        )

        expected_msg = (
            'The SSL certificate for this repository (hostname '
            '"p4.example.com:1666", fingerprint "%s") was not verified and '
            'might not be safe. This certificate needs to be verified before '
            'the repository can be accessed.'
            % fingerprint
        )

        with self.assertRaisesMessage(UnverifiedCertificateError,
                                      expected_msg):
            with client.run_worker():
                raise P4Exception(err_msg)
    def test_run_worker_with_unverified_cert_changed_error(self):
        """Testing PerforceTool.run_worker with unverified certificate and
        cert changed error
        """
        self.repository.path = 'p4.example.com:1666'

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

        fingerprint = \
            'A0:B1:C2:D3:E4:F5:6A:7B:8C:9D:E0:F1:2A:3B:4C:5D:6E:7F:A1:B2'

        err_msg = (
            "******* WARNING P4PORT IDENTIFICATION HAS CHANGED! *******\\n"
            "It is possible that someone is intercepting your connection\\n"
            "to the Perforce P4PORT '1.2.3.4:1666'\\n"
            "If this is not a scheduled key change, then you should contact\\n"
            "your Perforce administrator.\\n"
            "The fingerprint for the mismatched key sent to your client is\\n"
            "%s\n"
            "To allow connection use the 'p4 trust' command.\n" % fingerprint)

        expected_msg = (
            'The SSL certificate for this repository (hostname '
            '"p4.example.com:1666", fingerprint "%s") was not verified and '
            'might not be safe. This certificate needs to be verified before '
            'the repository can be accessed.' % fingerprint)

        with self.assertRaisesMessage(UnverifiedCertificateError,
                                      expected_msg):
            with client.run_worker():
                raise P4Exception(err_msg)
    def test_fields(self):
        """Testing PerforceTool authentication form fields"""
        form = PerforceTool.create_auth_form()

        self.assertEqual(list(form.fields), ['username', 'password'])
        self.assertEqual(form['username'].help_text, '')
        self.assertEqual(form['username'].label, 'Username')
        self.assertEqual(form['password'].help_text, '')
        self.assertEqual(form['password'].label, 'Password')
    def test_load(self):
        """Tetting PerforceTool authentication form load"""
        repository = self.create_repository(tool_name='Perforce',
                                            username='******',
                                            password='******')

        form = PerforceTool.create_auth_form(repository=repository)
        form.load()

        self.assertEqual(form['username'].value(), 'test-user')
        self.assertEqual(form['password'].value(), 'test-pass')
    def test_save(self):
        """Tetting PerforceTool authentication form save"""
        repository = self.create_repository(tool_name='Perforce')

        form = PerforceTool.create_auth_form(repository=repository,
                                             data={
                                                 'username': '******',
                                                 'password': '******',
                                             })
        self.assertTrue(form.is_valid())
        form.save()

        self.assertEqual(repository.username, 'test-user')
        self.assertEqual(repository.password, 'test-pass')
    def test_load(self):
        """Tetting PerforceTool repository form load"""
        repository = self.create_repository(
            tool_name='Perforce',
            path='example.com:123/cvsroot/test',
            mirror_path=':pserver:example.com:/cvsroot/test',
            extra_data={
                'use_ticket_auth': True,
            })

        form = PerforceTool.create_repository_form(repository=repository)
        form.load()

        self.assertEqual(form['path'].value(), 'example.com:123/cvsroot/test')
        self.assertEqual(form['mirror_path'].value(),
                         ':pserver:example.com:/cvsroot/test')
        self.assertTrue(form['use_ticket_auth'].value())
    def test_save(self):
        """Tetting PerforceTool repository form save"""
        repository = self.create_repository(tool_name='Perforce')
        self.assertIsNone(repository.extra_data.get('use_ticket_auth'))

        form = PerforceTool.create_repository_form(
            repository=repository,
            data={
                'path': 'ssl:perforce.example.com:1666',
                'mirror_path': 'mirror.example.com:1666',
                'use_ticket_auth': True,
            })
        self.assertTrue(form.is_valid())
        form.save()

        self.assertEqual(repository.path, 'ssl:perforce.example.com:1666')
        self.assertEqual(repository.mirror_path, 'mirror.example.com:1666')
        self.assertTrue(repository.extra_data.get('use_ticket_auth'))
Exemple #11
0
    def test_fields(self):
        """Testing PerforceTool repository form fields"""
        form = PerforceTool.create_repository_form()

        self.assertEqual(list(form.fields),
                         ['path', 'mirror_path', 'use_ticket_auth'])
        self.assertEqual(form['path'].help_text,
                         'The Perforce port identifier (P4PORT) for the '
                         'repository. If your server is set up to use SSL '
                         '(2012.1+), prefix the port with "ssl:". If your '
                         'server connection is secured with stunnel (2011.x '
                         'or older), prefix the port with "stunnel:".')
        self.assertEqual(form['path'].label, 'Path')
        self.assertEqual(form['mirror_path'].help_text, '')
        self.assertEqual(form['mirror_path'].label, 'Mirror Path')
        self.assertEqual(form['use_ticket_auth'].help_text, '')
        self.assertEqual(form['use_ticket_auth'].label,
                         'Use ticket-based authentication')
Exemple #12
0
    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 parse_change_desc(changedesc, changenum):
        changeset = PerforceTool.parse_change_desc(changedesc, changenum)

        if not changeset:
            return None

        # VMware's perforce changeset template is just the basic perforce one
        # with a bunch of extra fields at the end of the description.  We
        # leave the summary and file list as-is, and process the description
        # field to populate a couple more members of the ChangeSet object and
        # remove a lot of stuff that reviewers don't care about.
        sections = ['QA Notes:',
                    'Testing Done:',
                    'Documentation Notes:',
                    'Bug Number:',
                    'Reviewed by:',
                    'Approved by:',
                    'Breaks vmcore compatibility:',
                    'Breaks vmkernel compatibility:',
                    'Breaks vmkdrivers compatibility:',
                    'Mailto:',
                    'Merge to:']

        lines = changeset.description.split('\n')

        # First we go through and find the line numbers that start each section.
        # We then sort these line numbers so we can slice out each individual
        # section of text.
        locations = {}
        for i, line in enumerate(lines):
            for section in sections:
                if line.startswith(section):
                    locations[i] = section
        section_indices = sorted(locations.keys())

        # Pull the branch name out of the file list
        branches = []
        for file in changeset.files:
            try:
                branch = file.split('/')[4]
                if branch not in branches:
                    branches.append(branch)
            except IndexError:
                pass
        branch = ', '.join(branches)

        try:
            # The interesting part of the description field contains everything up
            # to the first marked section.
            changeset.description = '\n'.join(lines[:section_indices[0]])
        except IndexError:
            # If none of the sections exist, just return the changeset as-is
            return changeset

        # Now pull out each individual section.  This gives us a dictionary
        # mapping section name to a string.  We special-case "Merge to:" in
        # here, since it can appear multiple times.
        sections = {}
        branches = [branch]
        for start, end in zip(section_indices, section_indices[:1]):
            name = locations[start]
            if name == 'Merge to:':
                # Include merge information in the branch field
                m = re.match(r'Merge to: (?P<branch>[\w\-]+): (?P<type>[A-Z]+)',
                             lines[start])
                if m:
                    if m.group('type') == 'YES':
                        branches.append(m.group('branch'))
                    elif m.group('type') == 'MANUAL':
                        branches.append(m.group('branch') + ' (manual)')

            else:
                sections[name] = '\n'.join(lines[start:end])[len(name):].strip()

        changeset.branch = ' \u2192 '.join(branches)

        changeset.testing_done = sections.get('Testing Done:')

        try:
            changeset.bugs_closed = re.split(r"[, ]+", sections['Bug Number:'])
        except KeyError:
            pass

        return changeset
Exemple #14
0
    def parse_change_desc(changedesc, changenum):
        changeset = PerforceTool.parse_change_desc(changedesc, changenum)

        if not changeset:
            return None

        # VMware's perforce changeset template is just the basic perforce one
        # with a bunch of extra fields at the end of the description.  We
        # leave the summary and file list as-is, and process the description
        # field to populate a couple more members of the ChangeSet object and
        # remove a lot of stuff that reviewers don't care about.
        sections = ['QA Notes:',
                    'Testing Done:',
                    'Documentation Notes:',
                    'Bug Number:',
                    'Reviewed by:',
                    'Approved by:',
                    'Breaks vmcore compatibility:',
                    'Breaks vmkernel compatibility:',
                    'Breaks vmkdrivers compatibility:',
                    'Mailto:',
                    'Merge to:']

        lines = changeset.description.split('\n')

        # First we go through and find the line numbers that start each
        # section. We then sort these line numbers so we can slice out
        # each individual section of text.
        locations = {}
        for i, line in enumerate(lines):
            for section in sections:
                if line.startswith(section):
                    locations[i] = section
        section_indices = sorted(locations.keys())

        # Pull the branch name out of the file list
        branches = []
        for file in changeset.files:
            try:
                branch = file.split('/')[4]
                if branch not in branches:
                    branches.append(branch)
            except IndexError:
                pass
        branch = ', '.join(branches)

        try:
            # The interesting part of the description field contains everything
            # up to the first marked section.
            changeset.description = '\n'.join(lines[:section_indices[0]])
        except IndexError:
            # If none of the sections exist, just return the changeset as-is
            return changeset

        # Now pull out each individual section.  This gives us a dictionary
        # mapping section name to a string.  We special-case "Merge to:" in
        # here, since it can appear multiple times.
        sections = {}
        branches = [branch]
        for start, end in zip(section_indices, section_indices[:1]):
            name = locations[start]
            if name == 'Merge to:':
                # Include merge information in the branch field
                m = re.match(
                    r'Merge to: (?P<branch>[\w\-]+): (?P<type>[A-Z]+)',
                    lines[start])
                if m:
                    if m.group('type') == 'YES':
                        branches.append(m.group('branch'))
                    elif m.group('type') == 'MANUAL':
                        branches.append(m.group('branch') + ' (manual)')

            else:
                sections[name] = \
                    '\n'.join(lines[start:end])[len(name):].strip()

        changeset.branch = ' \u2192 '.join(branches)

        changeset.testing_done = sections.get('Testing Done:')

        try:
            changeset.bugs_closed = re.split(r"[, ]+", sections['Bug Number:'])
        except KeyError:
            pass

        return changeset
Exemple #15
0
    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)