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')
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'))
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')
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
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
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)