def test_get_files__one_file(self): changes = DiffCollection(self.one_file) result = changes.get_files() expected = [ "View/Helper/AssetCompressHelper.php" ] eq_(expected, result)
def test_get_files__two_files__ignore_pattern(self): changes = DiffCollection(self.two_files) expected = [ "Console/Command/Task/AssetBuildTask.php", ] ignore = ['Test/**'] result = changes.get_files(ignore_patterns=ignore) self.assertEqual(expected, result)
def test_get_files__two_files(self): changes = DiffCollection(self.two_files) result = changes.get_files() expected = [ "Console/Command/Task/AssetBuildTask.php", "Test/test_files/View/Parse/single.ctp", ] eq_(expected, result)
def test_get_files__two_files__ignore_pattern(self): changes = DiffCollection(self.two_files) expected = [ "Console/Command/Task/AssetBuildTask.php", ] ignore = ['Test/**'] result = changes.get_files(ignore_patterns=ignore) eq_(expected, result)
def test_has_line_changed__single_line(self): filename = 'some.js' pull_file = create_pull_files(self.single_line_add_json) changes = DiffCollection(pull_file) self.assertTrue(changes.has_line_changed(filename, 1)) self.assertFalse(changes.has_line_changed(filename, 0)) self.assertFalse(changes.has_line_changed(filename, 2))
def test_get_files__ignore_pattern__multiple_wildcard(self): data = load_fixture('multiple_wildcard_pull_request.json') changes = DiffCollection(create_pull_files(data)) expected = [ "buildpacks/buildpack-ruby/tests/ruby-sinatra/test_web.rb", ] ignore = ['buildpacks/*/tests/*/test.sh'] result = changes.get_files(ignore_patterns=ignore) self.assertEqual(expected, result)
def test_get_files__ignore_pattern__multiple_wildcard(self): data = load_fixture('multiple_wildcard_pull_request.json') changes = DiffCollection(create_pull_files(data)) expected = [ "buildpacks/buildpack-ruby/tests/ruby-sinatra/test_web.rb", ] ignore = ['buildpacks/*/tests/*/test.sh'] result = changes.get_files(ignore_patterns=ignore) eq_(expected, result)
def test_first_changed_line(self): changes = DiffCollection(self.two_files) filename = 'Console/Command/Task/AssetBuildTask.php' assert changes.first_changed_line('not there') is None assert changes.first_changed_line(filename) == 117 filename = "Test/test_files/View/Parse/single.ctp" assert changes.first_changed_line(filename) == 3
def test_get_files__two_files__append_base(self): changes = DiffCollection(self.two_files) expected = [ "/some/path/Console/Command/Task/AssetBuildTask.php", "/some/path/Test/test_files/View/Parse/single.ctp", ] result = changes.get_files(append_base="/some/path/") eq_(expected, result) result = changes.get_files(append_base="/some/path") eq_(expected, result)
def test_add__with_diff_containing_block_offset(self): res = [PullFile(f) for f in json.loads(self.block_offset)] changes = DiffCollection(res) problems = Problems(changes=changes) line_num = 32 problems.add('somefile.py', line_num, 'Not good') eq_(1, len(problems)) result = problems.all('somefile.py') eq_(changes.line_position('somefile.py', line_num), result[0].position, 'Offset should be transformed to match value in changes')
def test_add__with_diff_containing_block_offset(self): res = Resource.loads(self.block_offset) changes = DiffCollection(res) problems = Problems(changes=changes) line_num = 32 problems.add('somefile.py', line_num, 'Not good') eq_(1, len(problems)) result = problems.all('somefile.py') eq_(changes.line_position('somefile.py', line_num), result[0].position, 'Offset should be transformed to match value in changes')
def test_has_line_changed__two_files(self): changes = DiffCollection(self.two_files) filename = 'Console/Command/Task/AssetBuildTask.php' # True for additions self.assertTrue(changes.has_line_changed(filename, 117)) self.assertTrue(changes.has_line_changed(filename, 119)) # Should return false if the line was a deletion self.assertFalse(changes.has_line_changed(filename, 148)) # Should return false for unchanged self.assertFalse(changes.has_line_changed(filename, 145))
class Processor(object): def __init__(self, client, number, head, target_path): self._client = client self._number = number self._head = head self._target_path = target_path self._changes = None self._problems = Problems(target_path) self._review = Review(client, number) def load_changes(self): log.info('Loading pull request patches from github.') files = self._client.pull_requests.list_files(self._number) pull_request_patches = files.all() self._changes = DiffCollection(pull_request_patches) self._problems.set_changes(self._changes) def run_tools(self, review_config): if self._changes is None: raise RuntimeError('No loaded changes, cannot run tools. ' 'Try calling load_changes first.') files_to_check = self._changes.get_files( append_base=self._target_path, ignore_patterns=review_config.ignore_patterns()) tools.run( review_config, self._problems, files_to_check, self._target_path) def publish(self, wait_time=0): self._problems.limit_to_changes() self._review.publish(self._problems, self._head, wait_time)
class Processor(object): def __init__(self, client, number, head, target_path): self._client = client self._number = number self._head = head self._target_path = target_path self._changes = None self._problems = Problems(target_path) self._review = Review(client, number) def load_changes(self): log.info('Loading pull request patches from github.') files = self._client.pull_requests.list_files(self._number) pull_request_patches = files.all() self._changes = DiffCollection(pull_request_patches) self._problems.set_changes(self._changes) def run_tools(self, repo_config): if not self._changes: raise RuntimeError('No loaded changes, cannot run tools. ' 'Try calling load_changes first.') files_to_check = self._changes.get_files(append_base=self._target_path) tools.run(repo_config, self._problems, files_to_check, self._target_path) def publish(self, wait_time=0): self._problems.limit_to_changes() self._review.publish(self._problems, self._head, wait_time)
def test_limit_to_changes__remove_problems(self): res = map(lambda f: PullFile(f), json.loads(self.two_files_json)) changes = DiffCollection(res) # Setup some fake problems. filename_1 = 'Console/Command/Task/AssetBuildTask.php' errors = ( (None, None, 'This is a general comment'), (filename_1, 117, 'Something bad'), (filename_1, 119, 'Something else bad'), (filename_1, 130, 'Filtered out, as line is not changed'), ) self.problems.add_many(errors) filename_2 = 'Test/test_files/View/Parse/single.ctp' errors = ( (filename_2, 2, 'Filtered out'), (filename_2, 3, 'Something bad'), (filename_2, 7, 'Filtered out'), ) self.problems.add_many(errors) self.problems.set_changes(changes) self.problems.limit_to_changes() result = self.problems.all(filename_1) eq_(2, len(result)) expected = [(None, None, 'This is a general comment'), (filename_1, 117, 'Something bad'), (filename_1, 119, 'Something else bad')] eq_(result.sort(), expected.sort()) result = self.problems.all(filename_2) eq_(1, len(result)) expected = [Comment(filename_2, 3, 3, 'Something bad')] eq_(result, expected)
def test_add__with_diff_containing_block_offset(self): res = [ PullFile(f, self.session) for f in json.loads(self.block_offset) ] changes = DiffCollection(res) problems = Problems(changes=changes) line_num = 32 problems.add('somefile.py', line_num, 'Not good') self.assertEqual(1, len(problems)) result = problems.all('somefile.py') first_result = result[0] self.assertIsInstance(first_result, Comment) self.assertEqual( changes.line_position('somefile.py', line_num), first_result.position, 'Offset should be transformed to match value in changes')
def test_add__with_diff_containing_block_offset(self): res = [ PullFile(f, self.session) for f in json.loads(self.block_offset) ] changes = DiffCollection(res) problems = Problems(changes=changes) line_num = 32 problems.add('somefile.py', line_num, 'Not good') self.assertEqual(1, len(problems)) result = problems.all('somefile.py') first_result = result[0] self.assertIsInstance(first_result, Comment) self.assertEqual( changes.line_position('somefile.py', line_num), first_result.position, 'Offset should be transformed to match value in changes' )
class Processor(object): _client = None _number = None _head = None _target_path = None _changes = None _problems = None _review = None _config = None def __init__(self, client, number, head, target_path, config=None): self._client = client self._number = number self._head = head self._target_path = target_path self._problems = Problems(target_path) self._review = Review(client, number) if config is None: config = {} self._config = config def load_changes(self): log.info('Loading pull request patches from github.') files = self._client.pull_requests.list_files(self._number) pull_request_patches = files.all() self._changes = DiffCollection(pull_request_patches) self._problems.set_changes(self._changes) def run_tools(self, review_config): if self._changes is None: raise RuntimeError('No loaded changes, cannot run tools. ' 'Try calling load_changes first.') files_to_check = self._changes.get_files( append_base=self._target_path, ignore_patterns=review_config.ignore_patterns()) commits_to_check = self.get_commits(self._number) tools.run( review_config, self._problems, files_to_check, commits_to_check, self._target_path) def publish(self): self._problems.limit_to_changes() self._review.publish( self._problems, self._head, self._config.get('SUMMARY_THRESHOLD')) def get_commits(self, number): return self._client.pull_requests.list_commits(number).all()
def test_publish_review_empty_comment(self): problems = Problems(changes=DiffCollection([])) review = Review(self.repo, self.pr, self.config) sha = 'abc123' review.publish_review(problems, sha) assert self.pr.create_comment.called, 'Should create a comment' msg = ('Could not review pull request. ' 'It may be too large, or contain no reviewable changes.') self.pr.create_comment.assert_called_with(msg)
class Processor(object): _repository = None _pull_request = None _target_path = None _changes = None _problems = None _review = None _config = None def __init__(self, repository, pull_request, target_path, config=None): config = config if config else {} self._config = config self._repository = repository self._pull_request = pull_request self._target_path = target_path self._problems = Problems(target_path) self._review = Review(repository, pull_request, config) def load_changes(self): log.info('Loading pull request patches from github.') files = self._pull_request.files() self._changes = DiffCollection(files) self._problems.set_changes(self._changes) def run_tools(self, review_config): if self._changes is None: raise RuntimeError('No loaded changes, cannot run tools. ' 'Try calling load_changes first.') files_to_check = self._changes.get_files( append_base=self._target_path, ignore_patterns=review_config.ignore_patterns()) commits_to_check = self._pull_request.commits() log.debug("_problems before tools: %s" % len(self._problems)) self._problems = tools.run( review_config, self._problems, files_to_check, commits_to_check, self._target_path) log.debug("_problems after tools: %s" % len(self._problems)) def publish(self): self._problems.limit_to_changes() self._review.publish( self._problems, self._pull_request.head, self._config.get('SUMMARY_THRESHOLD'))
def test_publish_review_empty_comment_add_ok_label(self): problems = Problems(changes=DiffCollection([])) tst_config = build_review_config(fixer_ini, {'OK_LABEL': 'No lint'}) review = Review(self.repo, self.pr, tst_config) sha = 'abc123' review.publish_review(problems, sha) assert self.pr.create_comment.called, 'ok comment should be added.' assert self.pr.remove_label.called, 'label should be removed.' self.pr.remove_label.assert_called_with(tst_config['OK_LABEL']) msg = ('Could not review pull request. ' 'It may be too large, or contain no reviewable changes.') self.pr.create_comment.assert_called_with(msg)
def test_publish_review_empty_comment_with_comment_status(self): tst_config = build_review_config(fixer_ini, {'PULLREQUEST_STATUS': True}) problems = Problems(changes=DiffCollection([])) review = Review(self.repo, self.pr, tst_config) sha = 'abc123' review.publish_review(problems, sha) assert self.pr.create_comment.called, 'Should create a comment' msg = ('Could not review pull request. ' 'It may be too large, or contain no reviewable changes.') self.repo.create_status.assert_called_with(self.pr.head, 'success', msg) self.pr.create_comment.assert_called_with(msg)
class Processor(object): _repository = None _pull_request = None _target_path = None _changes = None _problems = None _review = None _config = None def __init__(self, repository, pull_request, target_path, config=None): config = config if config else {} self._config = config self._repository = repository self._pull_request = pull_request self._target_path = target_path self._problems = Problems(target_path) self._review = Review(repository, pull_request, config) def load_changes(self): log.info('Loading pull request patches from github.') files = self._pull_request.files() self._changes = DiffCollection(files) self._problems.set_changes(self._changes) def run_tools(self, review_config): if self._changes is None: raise RuntimeError('No loaded changes, cannot run tools. ' 'Try calling load_changes first.') files_to_check = self._changes.get_files( append_base=self._target_path, ignore_patterns=review_config.ignore_patterns()) commits_to_check = self._pull_request.commits() tools.run(review_config, self._problems, files_to_check, commits_to_check, self._target_path) def publish(self): self._problems.limit_to_changes() self._review.publish(self._problems, self._pull_request.head, self._config.get('SUMMARY_THRESHOLD'))
def test_limit_to_changes__remove_problems(self): res = [ PullFile(f, self.session) for f in json.loads(self.two_files_json) ] changes = DiffCollection(res) # Setup some fake problems. filename_1 = 'Console/Command/Task/AssetBuildTask.php' errors = ( Comment(None, None, None, 'This is a general comment'), Comment(filename_1, 117, 117, 'Something bad'), Comment(filename_1, 119, 119, 'Something else bad'), Comment(filename_1, 130, 130, 'Filtered out, line is not changed'), ) self.problems.add_many(errors) filename_2 = 'Test/test_files/View/Parse/single.ctp' errors = ( Comment(filename_2, 2, 2, 'Filtered out'), Comment(filename_2, 3, 3, 'Something bad'), Comment(filename_2, 7, 7, 'Filtered out'), ) self.problems.add_many(errors) self.problems.set_changes(changes) self.problems.limit_to_changes() result = self.problems.all(filename_1) self.assertEqual(2, len(result)) expected = [ Comment(filename_1, 117, 117, 'Something bad'), Comment(filename_1, 119, 119, 'Something else bad')] self.assertEqual(len(result), len(expected)) self.assertEqual(result, expected) result = self.problems.all(filename_2) self.assertEqual(1, len(result)) expected = [ Comment(filename_2, 3, 3, 'Something bad') ] self.assertEqual(result, expected)
def test_limit_to_changes__first_line_in_diff(self): res = [ PullFile(f, self.session) for f in json.loads(self.two_files_json) ] changes = DiffCollection(res) # Add problems filename = 'Test/test_files/View/Parse/single.ctp' errors = ( Comment(filename, 5, 5, 'Something bad'), Comment(filename, Comment.FIRST_LINE_IN_DIFF, 0, 'First line!'), Comment(filename, 7, 7, 'Filtered out'), ) self.problems.add_many(errors) self.problems.set_changes(changes) self.problems.limit_to_changes() result = self.problems.all(filename) self.assertEqual(2, len(result)) expected = [ Comment(filename, 5, 5, 'Something bad'), Comment(filename, 3, 3, 'First line!'), ] self.assertEqual(result, expected)
def test_create_one_element(self): changes = DiffCollection(self.one_file) eq_(1, len(changes)) self.assert_instances(changes, 1, Diff)
def test_parsing_diffs__renamed_file_and_blob_no_log(self, log): DiffCollection(self.renamed_files) eq_(False, log.warn.called) eq_(False, log.error.called)
def test_parsing_diffs__renamed_file_and_blob(self): changes = DiffCollection(self.renamed_files) eq_(0, len(changes), 'Should be no files as a blob and a rename happened') eq_([], changes.get_files())
def test_parsing_diffs_removed__file(self): changes = DiffCollection(self.removed_files) eq_(0, len(changes), 'Should be no files as the file was removed') eq_([], changes.get_files())
def load_changes(self): log.info('Loading pull request patches from github.') files = list(self._repository.pull_request(self._number).files()) self._changes = DiffCollection(files) self._problems.set_changes(self._changes)
def test_has_line_changed__no_line(self): changes = DiffCollection(self.two_files) self.assertFalse( changes.has_line_changed('Console/Command/Task/AssetBuildTask.php', 99999))
def load_changes(self): log.info('Loading pull request patches from github.') files = self._client.pull_requests.list_files(self._number) pull_request_patches = files.all() self._changes = DiffCollection(pull_request_patches) self._problems.set_changes(self._changes)
def test_parsing_diffs_removed__file(self): changes = DiffCollection(self.removed_files) self.assertEqual(0, len(changes), 'Should be no files as the file was removed') self.assertEqual([], changes.get_files())
def test_has_line_changed__no_line(self): changes = DiffCollection(self.two_files) self.assertFalse(changes.has_line_changed( 'Console/Command/Task/AssetBuildTask.php', 99999))
def load_changes(self): log.info('Loading pull request patches from github.') files = self._pull_request.files() self._changes = DiffCollection(files) self.problems.set_changes(self._changes)
def test_parsing_diffs__renamed_file_and_blob(self): changes = DiffCollection(self.renamed_files) self.assertEqual(0, len(changes), 'Should be no files as a blob and a rename happened') self.assertEqual([], changes.get_files())
class Processor(object): _repository = None _pull_request = None _target_path = None _changes = None _review = None _config = None problems = None def __init__(self, repository, pull_request, target_path, config): self._config = config self._repository = repository self._pull_request = pull_request self._target_path = target_path self.problems = Problems() self._review = Review(repository, pull_request, config) def load_changes(self): log.info('Loading pull request patches from github.') files = self._pull_request.files() self._changes = DiffCollection(files) self.problems.set_changes(self._changes) def run_tools(self): if self._changes is None: raise RuntimeError('No loaded changes, cannot run tools. ' 'Try calling load_changes first.') config = self._config files_to_check = self._changes.get_files( ignore_patterns=config.ignore_patterns()) commits_to_check = self._pull_request.commits() tool_list = tools.factory(config, self.problems, self._target_path) if config.fixers_enabled(): self.apply_fixers(tool_list, files_to_check) tools.run(tool_list, files_to_check, commits_to_check) def apply_fixers(self, tool_list, files_to_check): try: fixer_context = fixers.create_context( self._config, self._target_path, self._repository, self._pull_request, ) fixer_diff = fixers.run_fixers(tool_list, self._target_path, files_to_check) fixers.apply_fixer_diff(self._changes, fixer_diff, fixer_context) except (ConfigurationError, WorkflowError) as e: log.info('Fixer application failed. Got %s', e) message = u'Unable to apply fixers. {}'.format(e) self.problems.add(InfoComment(message)) fixers.rollback_changes(self._target_path, self._pull_request.head) except Exception as e: log.info( 'Fixer application failed, ' 'rolling back working tree. Got %s', e) fixers.rollback_changes(self._target_path, self._pull_request.head) def publish(self, check_run_id=None): self.problems.limit_to_changes() if check_run_id: self._review.publish_checkrun(self.problems, check_run_id) else: self._review.publish_review(self.problems, self._pull_request.head)
def test_has_line_changed__no_file(self): changes = DiffCollection(self.two_files) self.assertFalse(changes.has_line_changed('derp', 99))
def load_changes(self): log.info('Loading pull request patches from github.') files = self._pull_request.files() self._changes = DiffCollection(files) self._problems.set_changes(self._changes)
def test_create_two_files(self): changes = DiffCollection(self.two_files) eq_(2, len(changes)) self.assert_instances(changes, 2, Diff)
class Processor(object): _repository = None _pull_request = None _target_path = None _changes = None _review = None _config = None problems = None def __init__(self, repository, pull_request, target_path, config): self._config = config self._repository = repository self._pull_request = pull_request self._target_path = target_path self.problems = Problems() self._review = Review(repository, pull_request, config) def load_changes(self): log.info('Loading pull request patches from github.') files = self._pull_request.files() self._changes = DiffCollection(files) self.problems.set_changes(self._changes) def run_tools(self): if self._changes is None: raise RuntimeError('No loaded changes, cannot run tools. ' 'Try calling load_changes first.') config = self._config files_to_check = self._changes.get_files( ignore_patterns=config.ignore_patterns() ) commits_to_check = self._pull_request.commits() tool_list = tools.factory( config, self.problems, self._target_path) if config.fixers_enabled(): self.apply_fixers(tool_list, files_to_check) tools.run(tool_list, files_to_check, commits_to_check) def apply_fixers(self, tool_list, files_to_check): try: fixer_context = fixers.create_context( self._config, self._target_path, self._repository, self._pull_request, ) fixer_diff = fixers.run_fixers( tool_list, self._target_path, files_to_check) fixers.apply_fixer_diff( self._changes, fixer_diff, fixer_context) except (ConfigurationError, WorkflowError) as e: log.info('Fixer application failed. Got %s', e) message = u'Unable to apply fixers. {}'.format(e) self.problems.add(InfoComment(message)) except Exception as e: log.info('Fixer application failed, ' 'rolling back working tree. Got %s', e) fixers.rollback_changes(self._target_path) def publish(self, check_run_id=None): self.problems.limit_to_changes() if check_run_id: self._review.publish_checkrun( self.problems, check_run_id) else: self._review.publish_review( self.problems, self._pull_request.head)
def test_get_files__one_file(self): changes = DiffCollection(self.one_file) result = changes.get_files() expected = ["View/Helper/AssetCompressHelper.php"] eq_(expected, result)