def test_invalidate_client(self, mock_collab): job = utils.create_job() client = utils.create_client() client2 = utils.create_client(name="client2") mock_collab.return_value = True url = reverse('ci:invalidate', args=[job.pk]) post_data = {} self.set_counts() response = self.client.post(url, data=post_data) self.assertEqual(response.status_code, 302) #redirect self.compare_counts(ready=1, invalidated=1, num_changelog=1) self.check_job_invalidated(job) job.client = client job.save() self.set_counts() post_data["client_list"] = client.pk response = self.client.post(url, data=post_data) self.assertEqual(response.status_code, 302) #redirect self.compare_counts(num_changelog=1) self.check_job_invalidated(job, True, client) self.set_counts() post_data["client_list"] = client2.pk response = self.client.post(url, data=post_data) self.assertEqual(response.status_code, 302) #redirect self.compare_counts(num_changelog=1) self.check_job_invalidated(job, True, client2) self.set_counts() post_data["client_list"] = 0 response = self.client.post(url, data=post_data) self.assertEqual(response.status_code, 302) #redirect self.compare_counts(num_changelog=1) self.check_job_invalidated(job, False)
def setUp(self): self.client = Client() self.factory = RequestFactory() for i in range(5): repo = utils.create_repo(name="repo%s" % i) repo.active = True repo.status = models.JobStatus.SUCCESS repo.save() for j in range(2): b = utils.create_branch(name="branch%s" % j, repo=repo) b.status = models.JobStatus.SUCCESS b.save() for j in range(3): b = repo.branches.first() pr = utils.create_pr(title="pr%s" % j, number=j+1, repo=repo) pr.closed = False pr.status = models.JobStatus.SUCCESS pr.save() ev = utils.create_event(user=repo.user, branch1=b, branch2=b, commit1="%s" % j) ev.pull_request = pr ev.save() for k in range(3): r = utils.create_recipe(name="%s%s" % (repo.name, k), repo=repo, branch=b) r.private = False r.save() job = utils.create_job(recipe=r, event=ev) job.status = models.JobStatus.SUCCESS job.client = utils.create_client(name="client%s/%s" % (repo.name, k)) job.save() utils.create_step_result(job=job) utils.create_osversion() utils.create_loadedmodule()
def test_update_status(self, mock_allowed): mock_allowed.return_value = True ev = self.create_event_with_jobs() job = ev.jobs.first() url = reverse('ci:view_job', args=[job.pk]) self.get(url) self.check_job(job) job.ready = True job.client = utils.create_client() job.save() job.recipe.private = False job.recipe.save() self.wait_for_js() self.check_js_error() # job wasn't ready so JS didn't update it with self.assertRaises(Exception): self.check_job(job) self.get(url) self.check_job(job) job.status = models.JobStatus.SUCCESS job.complete = True job.invalidated = True job.save() self.wait_for_js() self.check_job(job)
def test_view_client(self): user = utils.get_test_user() with self.settings(INSTALLED_GITSERVERS=[utils.github_config(authorized_users=[])]): url = reverse('ci:view_client', args=[1000,]) response = self.client.get(url) self.assertEqual(response.status_code, 404) client = utils.create_client() # not logged in url = reverse('ci:view_client', args=[client.pk,]) response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertContains(response, "You are not allowed") # logged in but not on the authorized list utils.simulate_login(self.client.session, user) response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertContains(response, "You are not allowed") with self.settings(INSTALLED_GITSERVERS=[utils.github_config(authorized_users=[user.name])]): # logged in and on the authorized list response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertNotContains(response, "You are not allowed") # Should be cached response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertNotContains(response, "You are not allowed")
def test_invalidate(self, mock_collab): # only post is allowed url = reverse('ci:invalidate', args=[1000]) self.set_counts() response = self.client.get(url) self.assertEqual(response.status_code, 405) # not allowed self.compare_counts() # invalid job self.set_counts() response = self.client.post(url) self.assertEqual(response.status_code, 404) # not found self.compare_counts() # can't invalidate step_result = utils.create_step_result() job = step_result.job job.event.pull_request = utils.create_pr() job.event.comments_url = "some url" job.event.save() mock_collab.return_value = False url = reverse('ci:invalidate', args=[job.pk]) self.set_counts() response = self.client.post(url) self.assertEqual(response.status_code, 403) # forbidden self.compare_counts() # valid client = utils.create_client() job.client = client job.save() post_data = {"post_to_pr": "on", "comment": "some comment", "same_client": None, } mock_collab.return_value = True self.set_counts() response = self.client.post(url, data=post_data) self.assertEqual(response.status_code, 302) #redirect self.compare_counts(ready=1, invalidated=1, num_changelog=1) job.refresh_from_db() redir_url = reverse('ci:view_job', args=[job.pk]) self.assertRedirects(response, redir_url) self.check_job_invalidated(job) post_data["same_client"] = "on" utils.create_step_result(job=job) job.client = client job.save() self.set_counts() response = self.client.post(url, data=post_data) self.assertEqual(response.status_code, 302) #redirect self.compare_counts(num_changelog=1) job.refresh_from_db() self.assertRedirects(response, redir_url) self.check_job_invalidated(job, True, client)
def create_running_job(self): user = utils.get_test_user() job = utils.create_job(user=user) result = utils.create_step_result(job=job) client = utils.create_client() job.client = client job.event.cause = models.Event.PULL_REQUEST job.status = models.JobStatus.RUNNING job.save() return job, result
def test_complete_step_result_bad_client(self): job, result = self.create_running_job() post_data = self.create_complete_step_result_post_data(result.position) # bad client client2 = utils.create_client(name='other_client') url = self.complete_step_result_url(job, name=client2.name) self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 400) # bad request
def handle(self, *args, **options): factory = RequestFactory() client = utils.create_client() job = utils.create_job() user = job.recipe.build_user orig_recipe_dir = settings.RECIPE_BASE_DIR recipe_dir = utils.create_recipe_dir() settings.RECIPE_BASE_DIR = recipe_dir try: args = [user.build_key, client.name] request = factory.get(reverse("ci:client:ready_jobs", args=args)) reply = views.ready_jobs(request, user.build_key, client.name) args = [user.build_key, job.config.name, client.name] claim_job_url = reverse("ci:client:claim_job", args=args) data = json.dumps({"job_id": job.pk}) request = factory.post(claim_job_url, data, content_type="application/json") reply = views.claim_job(request, user.build_key, job.config.name, client.name) if reply.status_code == 200: this_file = os.path.realpath(__file__) test_dir = os.path.join(os.path.dirname(this_file), "..", "..", "..", "client", "tests") fname = os.path.join(os.path.abspath(test_dir), "claim_response.json") # to makes diffs better, hardcode job and recipe ids data = json.loads(reply.content) data["job_id"] = 1 data["job_info"]["job_id"] = 1 data["job_info"]["environment"]["job_id"] = 1 data["job_info"]["environment"]["recipe_id"] = 1 data["job_info"]["environment"]["CIVET_JOB_ID"] = 1 data["job_info"]["environment"]["CIVET_RECIPE_ID"] = 1 self.stdout.write("Writing: %s" % fname) with open(fname, "w") as f: json.dump(data, f, indent=2, sort_keys=True) f.write("\n") else: self.stderr.write(reply.status_code) self.stderr.write(reply.content) except Exception as e: self.stderr.write(traceback.format_exc()) self.stderr.write("Error occurred: %s" % e) job.recipe.delete() shutil.rmtree(recipe_dir) settings.RECIPE_BASE_DIR = orig_recipe_dir settings.RECIPE_BASE_DIR = orig_recipe_dir
def test_client_list(self, mock_allowed): mock_allowed.return_value = False for i in range(10): c = utils.create_client(name="client%s" % i) c.status = models.Client.RUNNING c.save() # not allowed response = self.client.get(reverse('ci:client_list')) self.assertEqual(response.status_code, 200) for c in models.Client.objects.all(): self.assertNotContains(response, c.name) # allowed mock_allowed.return_value = True response = self.client.get(reverse('ci:client_list')) self.assertEqual(response.status_code, 200) for i in range(10): name = "client%s" % i self.assertContains(response, name) self.assertContains(response, 'status_%i" class="client_Running"' % (i+1)) inactive = [] for i in range(5): c = models.Client.objects.get(name="client%s" % i) # we need to do it like this because a save() will automatically update it to current time models.Client.objects.filter(pk=c.pk).update(last_seen=c.last_seen - datetime.timedelta(seconds=120)) inactive.append(c.name) response = self.client.get(reverse('ci:client_list')) self.assertEqual(response.status_code, 200) for i in range(10): name = "client%s" % i self.assertContains(response, name) if name in inactive: self.assertContains(response, 'status_%i" class="client_NotSeen"' % (i+1)) else: self.assertContains(response, 'status_%i" class="client_Running"' % (i+1)) for name in inactive: c = models.Client.objects.get(name=name) models.Client.objects.filter(pk=c.pk).update(last_seen=c.last_seen - datetime.timedelta(seconds=2*7*24*60*60)) response = self.client.get(reverse('ci:client_list')) self.assertEqual(response.status_code, 200) for c in models.Client.objects.all(): if c.name in inactive: self.assertNotContains(response, c.name) self.assertEqual(c.status, models.Client.DOWN) else: self.assertContains(response, c.name)
def check_output(self, output, os_name, os_version, os_other, mods): user = utils.get_test_user() job = utils.create_job(user=user) step_result = utils.create_step_result(job=job) step_result.output = output step_result.save() client = utils.create_client() job.client = client job.save() ParseOutput.set_job_info(job) job.refresh_from_db() self.assertEqual(job.operating_system.name, os_name) self.assertEqual(job.operating_system.version, os_version) self.assertEqual(job.operating_system.other, os_other) self.check_modules(job, mods)
def test_job_finished_unrunnable(self, mock_status): user = utils.get_test_user() r0 = utils.create_recipe(name='recipe0', user=user) r1 = utils.create_recipe(name='recipe1', user=user) r2 = utils.create_recipe(name='recipe2', user=user) r2.depends_on.add(r1) r1.depends_on.add(r0) j0 = utils.create_job(user=user, recipe=r0) utils.create_job(user=user, recipe=r1) utils.create_job(user=user, recipe=r2) post_data = {'seconds': 0, 'complete': True} client = utils.create_client() j0.client = client j0.save() step_result = utils.create_step_result(job=j0) step_result.status = models.JobStatus.FAILED step_result.save() # should be ok url = reverse('ci:client:job_finished', args=[user.build_key, client.name, j0.pk]) self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts(num_events_completed=1, num_jobs_completed=1, active_branches=1) self.assertEqual(response.status_code, 200) self.assertEqual( mock_status.call_count, 3) # 1 for the job complete update and 2 for the won't run update step_result.status = models.JobStatus.SUCCESS step_result.save() self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts(ready=1) self.assertEqual(response.status_code, 200) self.assertEqual(mock_status.call_count, 4) # 1 for the job complete update
def test_invalidate_event(self, mock_collab): # only post is allowed url = reverse('ci:invalidate_event', args=[1000]) self.set_counts() response = self.client.get(url) self.assertEqual(response.status_code, 405) # not allowed self.compare_counts() # invalid event self.set_counts() response = self.client.post(url) self.assertEqual(response.status_code, 404) # not found self.compare_counts() # can't invalidate j0, j1, j2, j3 = utils.create_test_jobs() mock_collab.return_value = False url = reverse('ci:invalidate_event', args=[j0.event.pk]) self.set_counts() response = self.client.post(url) self.assertEqual(response.status_code, 302) # redirect with error message self.compare_counts() client = utils.create_client() for j in [j0, j1, j2, j3]: j.client = client j.ready = True j.complete = True j.status = models.JobStatus.SUCCESS j.event.complete = False j.save() # valid post_data = {'same_client': None} mock_collab.return_value = True self.set_counts() response = self.client.post(url, data=post_data) self.assertEqual(response.status_code, 302) #redirect self.compare_counts(ready=-3, num_jobs_completed=-4, invalidated=4, num_changelog=4) redir_url = reverse('ci:view_event', args=[j0.event.pk]) for j in [j0, j1, j2, j3]: j.refresh_from_db() self.assertRedirects(response, redir_url) self.assertEqual(j.step_results.count(), 0) self.assertFalse(j.complete) self.assertTrue(j.active) self.assertTrue(j.invalidated) self.assertFalse(j.same_client) self.assertEqual(j.client, None) self.assertEqual(j.seconds.seconds, 0) self.assertEqual(j.status, models.JobStatus.NOT_STARTED) self.assertFalse(j.event.complete) self.assertEqual(j.event.status, models.JobStatus.NOT_STARTED) self.assertTrue(j0.ready) self.assertFalse(j1.ready) self.assertFalse(j2.ready) self.assertFalse(j3.ready) # valid for j in [j0, j1, j2, j3]: j.client = client j.ready = True j.complete = True j.status = models.JobStatus.SUCCESS j.event.complete = False j.save() utils.create_step_result(job=j) post_data = {'same_client': 'on'} self.set_counts() response = self.client.post(url, data=post_data) self.assertEqual(response.status_code, 302) #redirect self.compare_counts(num_changelog=4, ready=-3, num_jobs_completed=-4) for j in [j0, j1, j2, j3]: j.refresh_from_db() self.assertRedirects(response, redir_url) self.assertEqual(j.step_results.count(), 0) self.assertFalse(j.complete) self.assertTrue(j.active) self.assertTrue(j.invalidated) self.assertTrue(j.same_client) self.assertEqual(j.client, client) self.assertEqual(j.seconds.seconds, 0) self.assertEqual(j.status, models.JobStatus.NOT_STARTED) self.assertFalse(j.event.complete) self.assertEqual(j.event.status, models.JobStatus.NOT_STARTED) self.assertTrue(j0.ready) self.assertFalse(j1.ready) self.assertFalse(j2.ready) self.assertFalse(j3.ready) post_data["comment"] = "some comment" post_data["post_to_pr"] = "on" self.set_counts() response = self.client.post(url, data=post_data) self.assertEqual(response.status_code, 302) #redirect self.compare_counts(num_changelog=4) # Make sure when the first job completes the other # jobs will become ready j0.complete = True j0.status = models.JobStatus.SUCCESS j0.save() self.set_counts() j0.event.make_jobs_ready() self.compare_counts(ready=2) self.assertFalse(j0.event.check_done())
def test_job_results(self, mock_allowed, mock_is_collaborator): mock_is_collaborator.return_value = False mock_allowed.return_value = True url = reverse('ci:ajax:job_results') # no parameters response = self.client.get(url) self.assertEqual(response.status_code, 400) client = utils.create_client() step_result = utils.create_step_result() step_result.complete = True step_result.save() step_result.job.save() data = {'last_request': 10, 'job_id': 0} # not signed in, not a collaborator response = self.client.get(url, data) self.assertEqual(response.status_code, 404) data['job_id'] = step_result.job.pk recipe = step_result.job.recipe recipe.private = True recipe.save() # not signed in, not a collaborator on a private recipe response = self.client.get(url, data) self.assertEqual(response.status_code, 403) recipe.private = False recipe.save() # recipe no longer private, should work response = self.client.get(url, data) self.assertEqual(response.status_code, 200) json_data = response.json() self.assertEqual(json_data['job_info']['client_name'], '') self.assertEqual(json_data['job_info']['client_url'], '') user = utils.get_test_user() utils.simulate_login(self.client.session, user) mock_is_collaborator.return_value = True recipe.private = True recipe.save() job = step_result.job job.client = client job.save() # should work now response = self.client.get(url, data) self.assertEqual(response.status_code, 200) json_data = response.json() self.assertIn('job_info', json_data) self.assertIn('results', json_data) self.assertEqual(step_result.job.pk, json_data['job_info']['id']) self.assertEqual(step_result.pk, json_data['results'][0]['id']) self.assertEqual(json_data['job_info']['client_name'], client.name) # should work now but return no results since nothing has changed data['last_request'] = json_data['last_request'] + 10 response = self.client.get(url, data) self.assertEqual(response.status_code, 200) json_data = response.json() self.assertIn('job_info', json_data) self.assertIn('results', json_data) # job_info is always returned self.assertNotEqual('', json_data['job_info']) self.assertEqual([], json_data['results']) self.assertEqual(json_data['job_info']['client_name'], '')
def test_ready_jobs_client(self): user = utils.get_test_user() client = utils.create_client() request = self.factory.get('/') client_ip = views.get_client_ip(request) client.ip = client_ip client.save() url = reverse('ci:client:ready_jobs', args=[user.build_key, client.name]) r0 = utils.create_recipe(name='recipe0', user=user) r1 = utils.create_recipe(name='recipe1', user=user) j0 = utils.create_job(user=user, recipe=r0) j1 = utils.create_job(user=user, recipe=r1) utils.update_job(j0, ready=True, complete=False, status=models.JobStatus.RUNNING, client=client) utils.update_job(j1, ready=True, active=True, status=models.JobStatus.NOT_STARTED) # we have a client trying to get ready jobs but # there is a job that is in the RUNNING state # associated with that client. That must mean # that the client previously stopped without letting the # server know, so the previous job should get # canceled self.set_counts() response = self.client.get(url) self.compare_counts(canceled=1, num_jobs_completed=1, num_changelog=1, active_branches=1) self.assertEqual(response.status_code, 200) j0.refresh_from_db() self.assertEqual(j0.status, models.JobStatus.CANCELED) # if all jobs are in running, the event should be canceled utils.update_job(j0, complete=False, status=models.JobStatus.RUNNING) utils.update_job(j1, complete=False, status=models.JobStatus.RUNNING, client=client) self.set_counts() response = self.client.get(url) self.compare_counts(canceled=2, num_jobs_completed=2, num_changelog=2, events_canceled=1, num_events_completed=1) self.assertEqual(response.status_code, 200) j0.refresh_from_db() self.assertEqual(j0.status, models.JobStatus.CANCELED) j1.refresh_from_db() self.assertEqual(j1.status, models.JobStatus.CANCELED) # Try again, nothing should change self.set_counts() response = self.client.get(url) self.compare_counts() self.assertEqual(response.status_code, 200)
def test_update_step_result(self): user = utils.get_test_user() job = utils.create_job(user=user) result = utils.create_step_result(job=job) client = utils.create_client() client2 = utils.create_client(name='other_client') job.client = client job.event.cause = models.Event.PULL_REQUEST job.status = models.JobStatus.RUNNING job.save() post_data = { 'step_num': result.position, 'output': 'output', 'time': 5, 'complete': True, 'exit_status': 0 } url = reverse('ci:client:update_step_result', args=[user.build_key, client.name, result.pk]) # only post allowed self.set_counts() response = self.client.get(url) self.compare_counts() self.assertEqual(response.status_code, 405) # not allowed # bad step result url = reverse('ci:client:update_step_result', args=[user.build_key, client.name, 0]) self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 400) # bad request # unknown client url = reverse('ci:client:update_step_result', args=[user.build_key, 'unknown_client', result.pk]) self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 400) # bad request # bad client url = reverse('ci:client:update_step_result', args=[user.build_key, client2.name, result.pk]) self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 400) # bad request # ok url = reverse('ci:client:update_step_result', args=[user.build_key, client.name, result.pk]) self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 200) data = response.json() self.assertEqual(data["status"], "OK") self.assertEqual(data["command"], None) result.refresh_from_db() self.assertEqual(result.status, models.JobStatus.RUNNING) # test when the user invalidates a job while it is running job.status = models.JobStatus.NOT_STARTED job.save() self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 200) result.refresh_from_db() data = response.json() self.assertEqual(result.status, models.JobStatus.NOT_STARTED) self.assertEqual(data["status"], "OK") self.assertEqual(data["command"], "cancel") # test when the user cancel a job while it is running job.status = models.JobStatus.CANCELED job.save() self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 200) result.refresh_from_db() data = response.json() self.assertEqual(result.status, models.JobStatus.CANCELED) self.assertEqual(data["status"], "OK") self.assertEqual(data["command"], "cancel") # a step exited with nonzero, make sure we don't do the # next step job.status = models.JobStatus.RUNNING job.save() post_data['exit_status'] = 1 self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 200) result.refresh_from_db() self.assertEqual(result.exit_status, 1) self.assertEqual(result.status, models.JobStatus.RUNNING)
def test_start_step_result(self): user = utils.get_test_user() job = utils.create_job(user=user) result = utils.create_step_result(job=job) client = utils.create_client() client2 = utils.create_client(name='other_client') job.client = client job.event.cause = models.Event.PULL_REQUEST job.event.pr = utils.create_pr() job.event.save() job.save() post_data = { 'step_num': result.position, 'output': 'output', 'time': 5, 'complete': True, 'exit_status': 0 } url = reverse('ci:client:start_step_result', args=[user.build_key, client.name, result.pk]) # only post allowed self.set_counts() response = self.client.get(url) self.compare_counts() self.assertEqual(response.status_code, 405) # not allowed # bad step result url = reverse('ci:client:start_step_result', args=[user.build_key, client.name, 0]) self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 400) # bad request # unknown client url = reverse('ci:client:start_step_result', args=[user.build_key, 'unknown_client', result.pk]) self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 400) # bad request # bad client url = reverse('ci:client:start_step_result', args=[user.build_key, client2.name, result.pk]) self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 400) # bad request # ok url = reverse('ci:client:start_step_result', args=[user.build_key, client.name, result.pk]) self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 200) result.refresh_from_db() self.assertEqual(result.status, models.JobStatus.RUNNING) data = response.json() self.assertEqual(data["command"], None) self.assertEqual(data["status"], "OK") # If a job got canceled, make sure it sends the command to the client job.status = models.JobStatus.CANCELED job.save() self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 200) result.refresh_from_db() self.assertEqual(result.status, models.JobStatus.CANCELED) data = response.json() self.assertEqual(data["command"], "cancel") self.assertEqual(data["status"], "OK")
def test_job_finished(self): user = utils.get_test_user() job = utils.create_job(user=user) step_result = utils.create_step_result(job=job) step_result.output = self.get_file("ubuntu_gcc_output.txt") step_result.save() client = utils.create_client() client2 = utils.create_client(name='other_client') job.client = client job.save() job.event.comments_url = 'http://localhost' job.event.save() post_data = {'seconds': 0, 'complete': True} url = reverse('ci:client:job_finished', args=[user.build_key, client.name, job.pk]) # only post allowed self.set_counts() response = self.client.get(url) self.compare_counts() self.assertEqual(response.status_code, 405) # not allowed # bad url url = reverse('ci:client:job_finished', args=[user.build_key, client.name, 0]) self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 400) # bad request # unknown client url = reverse('ci:client:job_finished', args=[user.build_key, 'unknown_client', job.pk]) self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 400) # bad request # bad client url = reverse('ci:client:job_finished', args=[user.build_key, client2.name, job.pk]) self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 400) # bad request # should be ok url = reverse('ci:client:job_finished', args=[user.build_key, client.name, job.pk]) self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts(num_events_completed=1, num_jobs_completed=1) self.assertEqual(response.status_code, 200) data = response.json() self.assertIn('message', data) self.assertEqual(data['status'], 'OK') job.refresh_from_db() self.assertTrue(job.complete) self.assertEqual(job.operating_system.name, "Ubuntu") self.assertEqual(job.operating_system.version, "14.04") self.assertEqual(job.operating_system.other, "trusty") self.check_modules(job, [ 'moose/.gcc_4.9.1', 'moose/.tbb', 'moose/.mpich-3.1.2_gcc', 'moose/.mpich_petsc-3.6.3-gcc-superlu', 'moose-tools', 'moose/.ccache', 'moose/.vtk-6', 'moose-dev-gcc', ]) job2 = utils.create_job(event=job.event) job2.ready = False job2.complete = False job2.status = models.JobStatus.NOT_STARTED job2.active = True job2.save() # should be ok. Make sure jobs get ready after one is finished. url = reverse('ci:client:job_finished', args=[user.build_key, client.name, job.pk]) self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts(ready=1) self.assertEqual(response.status_code, 200) data = response.json() self.assertIn('message', data) self.assertEqual(data['status'], 'OK') job2 = models.Job.objects.get(pk=job2.pk) self.assertTrue(job2.ready)
def test_job_finished_status(self): user = utils.get_test_user() recipe = utils.create_recipe(user=user) job = utils.create_job(recipe=recipe, user=user) step0 = utils.create_step(name='step0', recipe=recipe) step1 = utils.create_step(name='step1', recipe=recipe, position=1) step0_result = utils.create_step_result(step=step0, job=job) step1_result = utils.create_step_result(step=step1, job=job) step0_result.status = models.JobStatus.FAILED_OK step0_result.save() step1_result.status = models.JobStatus.SUCCESS step1_result.save() client = utils.create_client() job.client = client job.save() job.event.comments_url = 'http://localhost' job.event.pull_request = utils.create_pr() job.event.save() url = reverse('ci:client:job_finished', args=[user.build_key, client.name, job.pk]) # A step has FAILED_OK # So final status is FAILED_OK and we update the PR post_data = {'seconds': 0, 'complete': True} with patch('ci.github.api.GitHubAPI') as mock_api: self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts(num_events_completed=1, num_jobs_completed=1) self.assertEqual(response.status_code, 200) self.assertTrue(mock_api.called) self.assertTrue(mock_api.return_value.update_pr_status.called) job.refresh_from_db() self.assertEqual(job.status, models.JobStatus.FAILED_OK) os_obj = models.OSVersion.objects.get(name="Other") self.assertEqual(job.operating_system.pk, os_obj.pk) self.assertEqual(job.loaded_modules.count(), 1) self.assertEqual(job.loaded_modules.first().name, "None") # A step FAILED # So final status is FAILED and we update the PR step0_result.status = models.JobStatus.FAILED step0_result.save() with patch('ci.github.api.GitHubAPI') as mock_api: self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 200) self.assertTrue(mock_api.called) self.assertTrue(mock_api.return_value.update_pr_status.called) job.refresh_from_db() self.assertEqual(job.status, models.JobStatus.FAILED) step0_result.status = models.JobStatus.SUCCESS step0_result.save() # All steps passed # So final status is SUCCESS and we update the PR with patch('ci.github.api.GitHubAPI') as mock_api: self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 200) self.assertTrue(mock_api.called) self.assertTrue(mock_api.return_value.update_pr_status.called) job.refresh_from_db() self.assertEqual(job.status, models.JobStatus.SUCCESS) step0_result.status = models.JobStatus.FAILED step0_result.save() # A step FAILED # So final status is FAILED and we update the PR with patch('ci.github.api.GitHubAPI') as mock_api: self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 200) self.assertTrue(mock_api.called) self.assertTrue(mock_api.return_value.update_pr_status.called) job.refresh_from_db() self.assertEqual(job.status, models.JobStatus.FAILED)
def test_claim_job(self): # no jobs to claim ret = self.getter.claim_job([]) self.assertEqual(ret, None) # successfull operation self.job.ready = True self.job.active = True self.job.complete = False self.job.save() jobs = [self.create_job_dict(self.job)] self.set_counts() ret = self.getter.claim_job(jobs) self.compare_counts(num_clients=1, active_branches=1) data = self.claim_job_dict(self.job) self.assertEqual(ret, data) # bad job self.job.status = models.JobStatus.RUNNING self.job.save() self.set_counts() ret = self.getter.claim_job(jobs) self.compare_counts() self.assertEqual(ret, None) # job was set invalidated and to run on same client self.job.status = models.JobStatus.NOT_STARTED self.job.invalidated = True self.job.same_client = True self.job.client = test_utils.create_client(name="another client") self.job.save() self.set_counts() ret = self.getter.claim_job(jobs) self.compare_counts() self.assertEqual(ret, None) # no jobs with matching config self.job.invalidated = False self.job.client = None self.job.config.name = "foobar" self.job.config.save() self.job.save() self.set_counts() ret = self.getter.claim_job(jobs) self.compare_counts() self.assertEqual(ret, None) # bad server with patch.object(requests, "post") as mock_post: mock_post.return_value = test_utils.Response(json_data={}) self.client_info["server"] = "dummy_server" self.set_counts() ret = self.getter.claim_job(jobs) self.compare_counts() self.assertEqual(ret, None) mock_post.side_effect = Exception("BAM!") self.set_counts() ret = self.getter.claim_job(jobs) self.compare_counts() self.assertEqual(ret, None)
def test_claim_job(self): post_data = {'job_id': 0} user = utils.get_test_user() url = reverse('ci:client:claim_job', args=[user.build_key, 'testconfig', 'testClient']) # only post allowed self.set_counts() response = self.client.get(url) self.compare_counts() self.assertEqual(response.status_code, 405) # not allowed # setup a ready job job = utils.create_job(user=user) job.ready = True job.active = True job.event.cause = models.Event.PULL_REQUEST pr = utils.create_pr() job.event.pull_request = pr job.event.save() job.status = models.JobStatus.NOT_STARTED job_id = job.pk job.save() # bad config post_data = {'job_id': job_id} self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 400) # bad request # config different than job utils.create_build_config(name="otherBuildConfig") config2 = models.BuildConfig.objects.exclude(pk=job.config.pk).first() url = reverse('ci:client:claim_job', args=[user.build_key, config2.name, 'testClient']) post_data = {'job_id': job_id} self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 400) # bad request # bad job url = reverse('ci:client:claim_job', args=[user.build_key, job.config.name, 'testClient']) post_data = {'job_id': 0} self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 400) # bad request # valid job, should be ok post_data = {'job_id': job_id} self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts(num_clients=1) self.assertEqual(response.status_code, 200) data = response.json() self.assertEqual(data['job_id'], job_id) self.assertEqual(data['status'], 'OK') job.refresh_from_db() job.event.refresh_from_db() job.event.pull_request.refresh_from_db() self.assertEqual(job.status, models.JobStatus.RUNNING) self.assertEqual(job.event.status, models.JobStatus.RUNNING) self.assertEqual(job.event.pull_request.status, models.JobStatus.RUNNING) # create a job with a newer event. # This allows to test the update_status() function event2 = utils.create_event(commit1="2345", commit2="2345") job2 = utils.create_job(user=user, event=event2) job2.ready = True job2.active = True job2.event.cause = models.Event.PULL_REQUEST job2.event.pull_request = pr job2.event.save() job2.status = models.JobStatus.NOT_STARTED job2.save() job.status = models.JobStatus.NOT_STARTED job.client = None job.save() job.event.status = models.JobStatus.SUCCESS job.event.save() job.event.pull_request.status = models.JobStatus.SUCCESS job.event.pull_request.save() # valid job, should be ok, shouldn't update the status since # there is a newer event self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 200) data = response.json() self.assertEqual(data['job_id'], job_id) self.assertEqual(data['status'], 'OK') job.refresh_from_db() job.event.refresh_from_db() job.event.pull_request.refresh_from_db() self.assertEqual(job.status, models.JobStatus.RUNNING) self.assertEqual(job.event.status, models.JobStatus.RUNNING) # there is a newer event so this event doesn't update the PullRequest status self.assertEqual(job.event.pull_request.status, models.JobStatus.SUCCESS) # valid job, but wrong client job.invalidated = True job.same_client = True job.status = models.JobStatus.NOT_STARTED client = utils.create_client(name='old_client') job.client = client job.save() self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 400) # valid job, and correct client url = reverse('ci:client:claim_job', args=[user.build_key, job.config.name, client.name]) self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts() self.assertEqual(response.status_code, 200) data = response.json() self.assertEqual(data['job_id'], job_id) self.assertEqual(data['status'], 'OK') # valid job, and job client was null, should go through job.client = None job.save() url = reverse('ci:client:claim_job', args=[user.build_key, job.config.name, 'new_client']) self.set_counts() response = self.client_post_json(url, post_data) self.compare_counts(num_clients=1) self.assertEqual(response.status_code, 200) data = response.json() self.assertEqual(data['job_id'], job_id) self.assertEqual(data['status'], 'OK') job.refresh_from_db() job.event.refresh_from_db() job.event.pull_request.refresh_from_db() self.assertEqual(job.status, models.JobStatus.RUNNING) self.assertEqual(job.event.status, models.JobStatus.RUNNING) # there is a newer event so this event doesn't update the PullRequest status self.assertEqual(job.event.pull_request.status, models.JobStatus.SUCCESS)