def test_send_messages_cancel(self, mock_post): u = self.create_updater() # got the cancel signal self.load_messages(u) response_data = {"status": "OK", "command": "cancel"} mock_post.return_value = test_utils.Response(response_data) u.send_messages() self.assertEqual(u.messages, []) self.assertEqual(mock_post.call_count, 3)
def test_is_member(self, mock_get): # Username should match api = self.server.api() ret = api.is_member(self.build_user.name, self.build_user) self.assertTrue(ret) # Is a member mock_get.return_value = utils.Response([{ 'username': self.build_user.name }]) ret = api.is_member("foo", self.build_user) self.assertIs(ret, True) # Not a member mock_get.return_value = utils.Response([{'username': "******"}]) ret = api.is_member("foo", self.build_user) self.assertIs(ret, False)
def test_edit_comment(self, mock_patch, mock_del, mock_get, mock_post): user = utils.get_test_user() api = user.api() mock_get.return_value = utils.Response() ProcessCommands.edit_comment(api, user, "some_url", "Some message", "Some re") self.assertEqual(mock_get.call_count, 1) # 1 call to get the current comments self.assertEqual(mock_del.call_count, 0) self.assertEqual(mock_patch.call_count, 0) self.assertEqual(mock_post.call_count, 1) # 1 call to post the comment # Only 1 existing comment, should just update it c0 = { "user": { "login": user.name }, "body": "some message", "url": "url" } mock_get.return_value = utils.Response([c0]) ProcessCommands.edit_comment(api, user, "some_url", "some other message", "some me") self.assertEqual(mock_get.call_count, 2) self.assertEqual(mock_del.call_count, 0) self.assertEqual(mock_patch.call_count, 1) # Updates the existing comment self.assertEqual(mock_post.call_count, 1) # 2 existing comment, 1 should be deleted and 1 should be updated c1 = { "user": { "login": user.name }, "body": "some message 2", "url": "url" } mock_get.return_value = utils.Response([c0, c1]) ProcessCommands.edit_comment(api, user, "some_url", "some other message", "some me") self.assertEqual(mock_get.call_count, 3) self.assertEqual(mock_del.call_count, 1) self.assertEqual(mock_patch.call_count, 2) self.assertEqual(mock_post.call_count, 1)
def test_delete(self, mock_delete): mock_delete.return_value = utils.Response() self.api.delete("url") self.assertIs(self.api._bad_response, False) self.assertEqual(self.api.errors(), []) mock_delete.side_effect = Exception("Bam!") self.api.delete("url") self.assertIs(self.api._bad_response, True) self.assertNotEqual(self.api.errors(), [])
def test_last_sha(self, mock_get): branch = utils.create_branch(user=self.user) mock_get.return_value = utils.Response( json_data={branch.name: { 'raw_node': '123' }}) sha = self.gapi.last_sha(self.user.name, branch.repository.name, branch.name) self.assertEqual(sha, '123') mock_get.return_value = utils.Response({}) sha = self.gapi.last_sha(self.user.name, branch.repository.name, branch.name) self.assertEqual(sha, None) mock_get.side_effect = Exception("Bam!") sha = self.gapi.last_sha(self.user.name, branch.repository.name, branch.name) self.assertEqual(sha, None)
def test_send_messages_invalid_json(self, mock_post): u = self.create_updater() # server not responding correctly response_data = {"bad_key": "val"} self.load_messages(u) mock_post.call_count = 0 mock_post.return_value = test_utils.Response(response_data) u.send_messages() self.assertEqual(u.messages, []) self.assertEqual(mock_post.call_count, 3)
def test_send_messages_ok(self, mock_post): u = self.create_updater() mock_post.return_value = test_utils.Response({"status": "OK"}) items = self.load_messages(u) self.assertEqual(u.messages, items) self.assertEqual(mock_post.call_count, 0) # should be cleared u.send_messages() self.assertEqual(u.messages, []) self.assertEqual(mock_post.call_count, 3)
def test_create_issue_on_fail(self, mock_get, mock_post, mock_patch): j = utils.create_job() get_data = [{"title": "foo", "number": 1}] mock_get.return_value = utils.Response(get_data) mock_post.return_value = utils.Response({"html_url": "<html_url>"}) mock_patch.return_value = utils.Response({"html_url": "<html_url>"}) git_config = utils.github_config(remote_update=True) with self.settings(INSTALLED_GITSERVERS=[git_config]): utils.update_job(j, status=models.JobStatus.SUCCESS) j.event.cause = models.Event.PULL_REQUEST j.event.save() # Don't do anything on a PR UpdateRemoteStatus.create_issue_on_fail(j) self.assertEqual(mock_get.call_count, 0) self.assertEqual(mock_post.call_count, 0) self.assertEqual(mock_patch.call_count, 0) j.event.cause = models.Event.PUSH j.event.save() # Don't do anything unless it is a failure UpdateRemoteStatus.create_issue_on_fail(j) self.assertEqual(mock_get.call_count, 0) self.assertEqual(mock_post.call_count, 0) self.assertEqual(mock_patch.call_count, 0) utils.update_job(j, status=models.JobStatus.FAILED) # Don't do anything unless the recipe wants to create an issue UpdateRemoteStatus.create_issue_on_fail(j) self.assertEqual(mock_get.call_count, 0) self.assertEqual(mock_post.call_count, 0) self.assertEqual(mock_patch.call_count, 0) j.recipe.create_issue_on_fail = True j.recipe.create_issue_on_fail_message = "Additional message" j.recipe.save() # Should create new issue UpdateRemoteStatus.create_issue_on_fail(j) self.assertEqual(mock_get.call_count, 1) self.assertEqual(mock_post.call_count, 1) self.assertEqual(mock_patch.call_count, 0)
def test_create_event_summary(self, mock_get, mock_post): mock_get.return_value = utils.Response() mock_post.return_value = utils.Response() ev = utils.create_event() ev.comments_url = 'url' ev.save() j0 = utils.create_job(event=ev) config = utils.create_build_config("config1") j0.recipe.build_configs.add(config) utils.create_job(event=ev, recipe=j0.recipe, config=config) r1 = utils.create_recipe(name="r1") j1 = utils.create_job(recipe=r1, event=ev) j0.recipe.depends_on.add(r1) with self.settings(INSTALLED_GITSERVERS=[ utils.github_config(post_event_summary=False, remote_update=True) ]): # Not posting the summary so we should not do anything UpdateRemoteStatus.create_event_summary(ev) self.assertEqual(mock_post.call_count, 0) self.assertEqual(mock_get.call_count, 0) with self.settings(INSTALLED_GITSERVERS=[ utils.github_config(post_event_summary=True, remote_update=True) ]): # Configured to post the summary UpdateRemoteStatus.create_event_summary(ev) self.assertEqual(mock_post.call_count, 1) # 1 for adding comment self.assertEqual(mock_get.call_count, 1) # 1 for getting current comments utils.update_job(j1, status=models.JobStatus.FAILED, complete=True, invalidated=True) utils.create_step_result(job=j1, status=models.JobStatus.FAILED) self.assertEqual(len(ev.get_unrunnable_jobs()), 2) UpdateRemoteStatus.create_event_summary(ev) self.assertEqual(mock_post.call_count, 2) self.assertEqual(mock_get.call_count, 2)
def test_get_json_value(self): with self.assertRaises(Exception): github.oauth.get_json_value(None, 'name') response = utils.Response({'name': 'value'}) with self.assertRaises(oauth_api.OAuthException): auth = self.server.auth() auth.get_json_value(response, 'foo') val = auth.get_json_value(response, 'name') self.assertEqual(val, 'value')
def test_send_messages_bad_first(self, mock_post): u = self.create_updater() # server not responding on first response response_data = {"status": "OK"} items = self.load_messages(u) mock_post.call_count = 0 mock_post.return_value = test_utils.Response(response_data, do_raise=True) u.send_messages() self.assertEqual(u.messages, items) self.assertEqual(mock_post.call_count, 1)
def test_edit_pr_comment(self, mock_edit): # should just return api = self.server.api() api.edit_pr_comment(None, None) self.assertEqual(mock_edit.call_count, 0) with self.settings( INSTALLED_GITSERVERS=[utils.gitlab_config( remote_update=True)]): comment = {"url": "some_url"} api = self.server.api() # bad response mock_edit.return_value = utils.Response(status_code=400) api.edit_pr_comment(comment, "new msg") self.assertEqual(mock_edit.call_count, 1) # good response mock_edit.return_value = utils.Response() api.edit_pr_comment(comment, "new msg") self.assertEqual(mock_edit.call_count, 2)
def test_get_repos(self, mock_get): mock_get.return_value = utils.Response( json_data={'message': 'message'}, status_code=404) repos = self.gapi.get_repos(self.client.session) # shouldn't be any repos self.assertEqual(len(repos), 0) repo1 = {'owner': self.user.name, 'name': 'repo1'} repo2 = {'owner': self.user.name, 'name': 'repo2'} mock_get.return_value = utils.Response(json_data=[repo1, repo2]) repos = self.gapi.get_repos(self.client.session) self.assertEqual(len(repos), 2) session = self.client.session session[self.gapi._repos_key] = ['newrepo1'] session[self.gapi._org_repos_key] = ['org/repo1'] session.save() repos = self.gapi.get_repos(self.client.session) self.assertEqual(len(repos), 1) self.assertEqual(repos[0], 'newrepo1')
def test_get_json_value(self): with self.assertRaises(Exception): bitbucket.oauth.get_json_value(None, 'name') auth = self.server.auth() response = utils.Response({"name": "value"}) with self.assertRaises(oauth_api.OAuthException): auth.get_json_value(response, 'foo') val = auth.get_json_value(response, 'name') self.assertEqual(val, 'value')
def test_is_collaborator(self, mock_get): # user is repo owner api = self.server.api() self.assertTrue(api.is_collaborator(self.owner, self.repo)) user2 = utils.create_user('user2', server=self.server) # a collaborator repo = utils.create_repo(user=user2) mock_get.return_value = utils.Response([{ 'username': self.build_user.name }]) self.assertTrue(api.is_collaborator(self.build_user, repo)) # not a collaborator mock_get.return_value = utils.Response([{'username': '******'}]) self.assertFalse(api.is_collaborator(self.build_user, repo)) # some random problem mock_get.side_effect = Exception("Bam!") self.assertFalse(api.is_collaborator(self.build_user, repo))
def test_post_json(self, mock_post): u = self.create_updater() in_data = {'foo': 'bar'} response_data = utils.create_json_response() url = 'foo' # test the non error operation mock_post.return_value = test_utils.Response(response_data) ret = u.post_json(url, in_data) self.assertEqual(ret, response_data) mock_post.return_value = test_utils.Response(response_data, do_raise=True) #check when the server responds incorrectly ret = u.post_json(url, in_data) self.assertEqual(ret, None) #check when the server gives bad request mock_post.return_value = test_utils.Response(response_data, status_code=400) ret = u.post_json(url, in_data) self.assertEqual(ret, {"status": "OK", "command": "stop"})
def test_install_webhooks(self, mock_post, mock_get): get_data = [] webhook_url = reverse('ci:gitlab:webhook', args=[self.build_user.build_key]) base = self.server.server_config().get("civet_base_url", "") callback_url = "%s%s" % (base, webhook_url) get_data.append({ 'merge_requests_events': 'true', 'push_events': 'true', 'url': 'no_url' }) mock_get.return_value = utils.Response(get_data) mock_post.return_value = utils.Response({'errors': 'error'}, status_code=404) # with this data it should try to install the hook but there is an error api = self.server.api() with self.assertRaises(GitException): api.install_webhooks(self.build_user, self.repo) # with this data it should do the hook mock_post.return_value = utils.Response() api.install_webhooks(self.build_user, self.repo) # with this data the hook already exists get_data.append({ 'merge_requests_events': 'true', 'push_events': 'true', 'url': callback_url }) api.install_webhooks(self.build_user, self.repo) with self.settings(INSTALLED_GITSERVERS=[ utils.gitlab_config(install_webhook=False) ]): # this should just return api = self.server.api() mock_get.call_count = 0 api.install_webhooks(self.build_user, self.repo) self.assertEqual(mock_get.call_count, 0)
def test_get_project_access_level(self, mock_get): # Can't get user information api = self.server.api() empty_response = utils.Response({}) mock_get.return_value = empty_response path_with_namespace = '%s/%s' % (self.repo.user.name, self.repo.name) level = api._get_project_access_level(path_with_namespace) self.assertEqual(level, "Unknown") user_json = self.get_json_file("user.json") user_data = json.loads(user_json) mock_get.return_value = None namespace_data = {"namespace": {"id": 999}} user_response = utils.Response(user_data) bad_response = utils.Response({}, status_code=400) namespace_response = utils.Response(namespace_data) # Got user information but failed to get member information # Then failed to get namespace information mock_get.side_effect = [user_response, bad_response, bad_response] level = api._get_project_access_level(path_with_namespace) self.assertEqual(level, "Unknown") # Got user information but failed to get member information # Then got namespace information but failed to get member information mock_get.side_effect = [ user_response, bad_response, namespace_response, bad_response ] level = api._get_project_access_level(path_with_namespace) self.assertEqual(level, "Unknown") members_json = self.get_json_file("project_member.json") members_data = json.loads(members_json) members_response = utils.Response(members_data) # Got user information but failed to get member information # Then got namespace information and group information mock_get.side_effect = [ user_response, bad_response, namespace_response, members_response ] level = api._get_project_access_level(path_with_namespace) self.assertEqual(level, "Reporter") # Got user information and user is a member mock_get.side_effect = [user_response, members_response] level = api._get_project_access_level(path_with_namespace) self.assertEqual(level, "Reporter") # Make sure differenct access levels work members_data["access_level"] = 30 mock_get.side_effect = [user_response, utils.Response(members_data)] level = api._get_project_access_level(path_with_namespace) self.assertEqual(level, "Developer") mock_get.side_effect = Exception("Bam!") level = api._get_project_access_level(path_with_namespace) self.assertEqual(level, "Unknown")
def test_process_commands_to_api(self, mock_del, mock_get, mock_post): """ This should succeed down to the GitHub API level. """ mock_del.return_value = utils.Response() mock_get.return_value = utils.Response() mock_post.return_value = utils.Response() update_key = "CIVET_CLIENT_SUBMODULE_UPDATES" post_key = "CIVET_CLIENT_POST_MESSAGE" result = self.create_step_result( "PREVIOUS\n%s=libmesh\n%s=My message" % (update_key, post_key)) ev = result.job.event job = result.job ev.cause = models.Event.PULL_REQUEST ev.comments_url = "some url" ev.save() step = job.recipe.steps.first() utils.create_step_environment( name="CIVET_SERVER_POST_ON_SUBMODULE_UPDATE", value="1", step=step) ProcessCommands.process_commands(job) step.step_environment.all().delete() utils.create_step_environment(name="CIVET_SERVER_POST_COMMENT", value="1", step=step) ProcessCommands.process_commands(job) utils.create_step_environment(name="CIVET_SERVER_POST_REMOVE_OLD", value="1", step=step) ProcessCommands.process_commands(job) utils.create_step_environment(name="CIVET_SERVER_POST_EDIT_EXISTING", value="1", step=step) ProcessCommands.process_commands(job)
def test_find_job(self, mock_post, mock_get): g = self.create_getter() j0 = {"config": "unknown_config", "id": 1} j1 = {"config": g.client_info["build_configs"][0], "id": 2} jobs = [j0, j1] mock_get.return_value = test_utils.Response({"jobs": jobs}) response_data = utils.create_json_response() response_data['job_info'] = {'recipe_name': 'test'} mock_post.return_value = test_utils.Response(response_data) # normal operation self.set_counts() result = g.find_job() self.compare_counts() self.assertEqual(result, response_data) # no jobs mock_get.return_value = test_utils.Response([]) self.set_counts() result = g.find_job() self.compare_counts() self.assertEqual(result, None)
def test_claim_job(self, mock_post): g = self.create_getter() j0 = {"config": "unknown_config", "id": 1} j1 = {"config": g.client_info["build_configs"][0], "id": 2} jobs = [j0, j1] response_data = utils.create_json_response() response_data['job_info'] = {'recipe_name': 'test'} mock_post.return_value = test_utils.Response(response_data) # successfull operation self.set_counts() ret = g.claim_job(jobs) self.compare_counts() self.assertEqual(response_data, ret) # didn't succeed response_data["success"] = False mock_post.return_value = test_utils.Response(response_data) self.set_counts() ret = g.claim_job(jobs) self.compare_counts() self.assertEqual(ret, None) # no jobs with matching config jobs = [j1] self.set_counts() ret = g.claim_job(jobs) self.compare_counts() self.assertEqual(ret, None) # try when server problems mock_post.return_value = test_utils.Response(response_data, do_raise=True) self.set_counts() ret = g.claim_job(jobs) self.compare_counts() self.assertEqual(ret, None)
def test_ping_servers(self, mock_post): u = self.create_updater() mock_post.return_value = test_utils.Response({"not_empty": True}) u.client_info["server_update_interval"] = 1 # not enough elapsed time from creation u.ping_servers() self.assertEqual(mock_post.call_count, 0) time.sleep(1) # normal ping u.ping_servers() self.assertEqual(mock_post.call_count, 2) # we shouldn't ping since we just did u.ping_servers() self.assertEqual(mock_post.call_count, 2)
def test_get_all_repos(self, mock_get): mock_get.return_value = utils.Response([]) api = self.server.api() repos = api.get_all_repos(self.build_user.name) # shouldn't be any repos self.assertEqual(len(repos), 0) data = [ { 'path_with_namespace': "name/repo1" }, { 'path_with_namespace': "name/repo2" }, { 'path_with_namespace': "other/repo1" }, { 'path_with_namespace': "other/repo2" }, ] mock_get.return_value = utils.Response(data) repos = api.get_all_repos("name") self.assertEqual(len(repos), 4)
def test_user_access(self, mock_get): out = StringIO() mock_get.return_value = utils.Response(status_code=404) with self.assertRaises(CommandError): management.call_command("user_access", stdout=out) with self.assertRaises(models.GitUser.DoesNotExist): management.call_command("user_access", "--master", "nobody", stdout=out) with self.assertRaises(CommandError): management.call_command("user_access", "--master", self.owner.name, stdout=out) out = StringIO() management.call_command("user_access", "--master", self.build_user.name, stdout=out) repo1 = {'name': 'repo1', 'owner': {'login': '******'}} repo2 = {'name': 'repo2', 'owner': {'login': '******'}} mock_get.side_effect = [ utils.Response([repo1]), utils.Response([repo2]) ] out = StringIO() management.call_command("user_access", "--master", self.build_user.name, "--user", "owner", stdout=out)
def test_check_automerge(self, mock_get): mock_get.return_value = utils.Response() e0 = utils.create_event(cause=models.Event.PUSH) e0.cause = models.Event.PULL_REQUEST e0.status = models.JobStatus.SUCCESS e0.pull_request = utils.create_pr() e0.save() with self.settings( INSTALLED_GITSERVERS=[utils.github_config( remote_update=True)]): # Not configured for automerge UpdateRemoteStatus.check_automerge(e0) self.assertEqual(mock_get.call_count, 0) auto_merge_settings = { "auto_merge_label": "Auto Merge", "auto_merge_require_review": False, "auto_merge_enabled": True, } repo = e0.base.branch.repository repo_settings = { "%s/%s" % (repo.user.name, repo.name): auto_merge_settings } git_config = utils.github_config(remote_update=True, repo_settings=repo_settings) with self.settings(INSTALLED_GITSERVERS=[git_config]): # Only works for pull requests e0.cause = models.Event.PUSH e0.save() UpdateRemoteStatus.check_automerge(e0) self.assertEqual(mock_get.call_count, 0) # Only works if the event status is SUCCESS e0.cause = models.Event.PULL_REQUEST e0.status = models.JobStatus.FAILED_OK e0.pull_request = utils.create_pr() e0.save() UpdateRemoteStatus.check_automerge(e0) self.assertEqual(mock_get.call_count, 0) e0.status = models.JobStatus.SUCCESS e0.save() # Should try to auto merge UpdateRemoteStatus.check_automerge(e0) self.assertEqual(mock_get.call_count, 1)
def test_get_open_prs(self, mock_get): repo = utils.create_repo(server=self.server) api = self.server.api() pr0 = {"title": "some title", "id": 123, "links": {"html": "some url"}} pr0_ret = { "title": "some title", "number": 123, "html_url": "some url" } mock_get.return_value = utils.Response({"values": [pr0]}) prs = api.get_open_prs(repo.user.name, repo.name) self.assertEqual([pr0_ret], prs) mock_get.side_effect = Exception("BAM!") prs = api.get_open_prs(repo.user.name, repo.name) self.assertEqual(prs, None)
def test_pr_comment(self, mock_post): # no real state that we can check, so just go for coverage with self.settings( INSTALLED_GITSERVERS=[utils.gitlab_config( remote_update=True)]): mock_post.return_value = utils.Response(json_data="some json") api = self.server.api() # valid post api.pr_comment('url', 'message') # bad post mock_post.side_effect = Exception("BAM!") api.pr_comment('url', 'message') # should just return api.pr_comment('url', 'message')
def test_pull_request_bad_source(self, mock_get): """ Sometimes the user hasn't given moosetest access to their repository and an error occurs. It is hard to check if a successful comment has happened but just try to get coverage. """ data = self.get_data('pr_open_01.json') pr_data = json.loads(data) # Simulate an error on the server while getting the source branch mock_get.return_value = utils.Response(status_code=404) url = reverse('ci:gitlab:webhook', args=[self.build_user.build_key]) self.set_counts() response = self.client_post_json(url, pr_data) self.assertEqual(response.status_code, 400) self.compare_counts()
def test_bad_output(self, mock_post): u = self.create_updater() mock_post.return_value = test_utils.Response({"not_empty": True}) item = { "server": u.main_server, "job_id": 0, "url": "url", "payload": { "output": b'foo \xe0 \xe0 bar' } } u.message_q.put(item) u.post_message(item) self.assertEqual(item["payload"]["output"], "foo \ufffd \ufffd bar") # Enforce a JSON serializable error class BadObject(object): pass item["payload"]["foo"] = BadObject() with self.assertRaises(ServerUpdater.StopException): u.post_message(item)
def test_callback(self, mock_get, mock_fetch_token): user = utils.get_test_user() auth = self.server.auth() mock_fetch_token.return_value = { 'access_token': '1234', 'token_type': 'bearer', 'scope': 'repo' } mock_get.return_value = utils.Response( {auth._callback_user_key: user.name}) session = self.client.session session[auth._state_key] = 'state' session.save() url = reverse('ci:github:callback', args=[self.server.name]) response = self.client.post(url) self.assertEqual(response.status_code, 302) mock_fetch_token.side_effect = Exception('Bam!') url = reverse('ci:github:callback', args=[self.server.name]) response = self.client.post(url) self.assertEqual(response.status_code, 302)