1c236dfe93
Rather than using the FakeLogger fixture, which always attaches the log stream as a detail, use standard loggers that output to a stringio, and then, only if a test fails, attach the full log as a detail. This allows us to report full debug-level logs for failing tests in the gate (which normally has a limit on how large subunit files can be). Change-Id: I9e6509b7b69838d29582b040ef22f1d66010d45e
4775 lines
192 KiB
Python
Executable File
4775 lines
192 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
# Copyright 2012 Hewlett-Packard Development Company, L.P.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import json
|
|
import os
|
|
import re
|
|
import shutil
|
|
import time
|
|
from unittest import skip
|
|
|
|
import git
|
|
from six.moves import urllib
|
|
import testtools
|
|
|
|
import zuul.change_matcher
|
|
import zuul.scheduler
|
|
import zuul.rpcclient
|
|
import zuul.model
|
|
|
|
from tests.base import (
|
|
ZuulTestCase,
|
|
repack_repo,
|
|
)
|
|
|
|
|
|
class TestScheduler(ZuulTestCase):
|
|
tenant_config_file = 'config/single-tenant/main.yaml'
|
|
|
|
def test_jobs_launched(self):
|
|
"Test that jobs are launched and a change is merged"
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
A.addApproval('code-review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(self.getJobFromHistory('project-merge').result,
|
|
'SUCCESS')
|
|
self.assertEqual(self.getJobFromHistory('project-test1').result,
|
|
'SUCCESS')
|
|
self.assertEqual(self.getJobFromHistory('project-test2').result,
|
|
'SUCCESS')
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertEqual(self.getJobFromHistory('project-test1').node,
|
|
'image1')
|
|
|
|
# TODOv3(jeblair): we may want to report stats by tenant (also?).
|
|
self.assertReportedStat('gerrit.event.comment-added', value='1|c')
|
|
self.assertReportedStat('zuul.pipeline.gate.current_changes',
|
|
value='1|g')
|
|
self.assertReportedStat('zuul.pipeline.gate.job.project-merge.SUCCESS',
|
|
kind='ms')
|
|
self.assertReportedStat('zuul.pipeline.gate.job.project-merge.SUCCESS',
|
|
value='1|c')
|
|
self.assertReportedStat('zuul.pipeline.gate.resident_time', kind='ms')
|
|
self.assertReportedStat('zuul.pipeline.gate.total_changes',
|
|
value='1|c')
|
|
self.assertReportedStat(
|
|
'zuul.pipeline.gate.org.project.resident_time', kind='ms')
|
|
self.assertReportedStat(
|
|
'zuul.pipeline.gate.org.project.total_changes', value='1|c')
|
|
|
|
for build in self.builds:
|
|
self.assertEqual(build.parameters['ZUUL_VOTING'], '1')
|
|
|
|
def test_initial_pipeline_gauges(self):
|
|
"Test that each pipeline reported its length on start"
|
|
self.assertReportedStat('zuul.pipeline.gate.current_changes',
|
|
value='0|g')
|
|
self.assertReportedStat('zuul.pipeline.check.current_changes',
|
|
value='0|g')
|
|
|
|
def test_job_branch(self):
|
|
"Test the correct variant of a job runs on a branch"
|
|
self.create_branch('org/project', 'stable')
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'stable', 'A')
|
|
A.addApproval('code-review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(self.getJobFromHistory('project-test1').result,
|
|
'SUCCESS')
|
|
self.assertEqual(self.getJobFromHistory('project-test2').result,
|
|
'SUCCESS')
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2,
|
|
"A should report start and success")
|
|
self.assertIn('gate', A.messages[1],
|
|
"A should transit gate")
|
|
self.assertEqual(self.getJobFromHistory('project-test1').node,
|
|
'image2')
|
|
|
|
def test_parallel_changes(self):
|
|
"Test that changes are tested in parallel and merged in series"
|
|
|
|
self.launch_server.hold_jobs_in_build = True
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
|
|
A.addApproval('code-review', 2)
|
|
B.addApproval('code-review', 2)
|
|
C.addApproval('code-review', 2)
|
|
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(B.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(C.addApproval('approved', 1))
|
|
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.builds), 1)
|
|
self.assertEqual(self.builds[0].name, 'project-merge')
|
|
self.assertTrue(self.builds[0].hasChanges(A))
|
|
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.builds), 3)
|
|
self.assertEqual(self.builds[0].name, 'project-test1')
|
|
self.assertTrue(self.builds[0].hasChanges(A))
|
|
self.assertEqual(self.builds[1].name, 'project-test2')
|
|
self.assertTrue(self.builds[1].hasChanges(A))
|
|
self.assertEqual(self.builds[2].name, 'project-merge')
|
|
self.assertTrue(self.builds[2].hasChanges(A, B))
|
|
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.builds), 5)
|
|
self.assertEqual(self.builds[0].name, 'project-test1')
|
|
self.assertTrue(self.builds[0].hasChanges(A))
|
|
self.assertEqual(self.builds[1].name, 'project-test2')
|
|
self.assertTrue(self.builds[1].hasChanges(A))
|
|
|
|
self.assertEqual(self.builds[2].name, 'project-test1')
|
|
self.assertTrue(self.builds[2].hasChanges(A, B))
|
|
self.assertEqual(self.builds[3].name, 'project-test2')
|
|
self.assertTrue(self.builds[3].hasChanges(A, B))
|
|
|
|
self.assertEqual(self.builds[4].name, 'project-merge')
|
|
self.assertTrue(self.builds[4].hasChanges(A, B, C))
|
|
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.builds), 6)
|
|
self.assertEqual(self.builds[0].name, 'project-test1')
|
|
self.assertTrue(self.builds[0].hasChanges(A))
|
|
self.assertEqual(self.builds[1].name, 'project-test2')
|
|
self.assertTrue(self.builds[1].hasChanges(A))
|
|
|
|
self.assertEqual(self.builds[2].name, 'project-test1')
|
|
self.assertTrue(self.builds[2].hasChanges(A, B))
|
|
self.assertEqual(self.builds[3].name, 'project-test2')
|
|
self.assertTrue(self.builds[3].hasChanges(A, B))
|
|
|
|
self.assertEqual(self.builds[4].name, 'project-test1')
|
|
self.assertTrue(self.builds[4].hasChanges(A, B, C))
|
|
self.assertEqual(self.builds[5].name, 'project-test2')
|
|
self.assertTrue(self.builds[5].hasChanges(A, B, C))
|
|
|
|
self.launch_server.hold_jobs_in_build = False
|
|
self.launch_server.release()
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.builds), 0)
|
|
|
|
self.assertEqual(len(self.history), 9)
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(B.data['status'], 'MERGED')
|
|
self.assertEqual(C.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertEqual(B.reported, 2)
|
|
self.assertEqual(C.reported, 2)
|
|
|
|
def test_failed_changes(self):
|
|
"Test that a change behind a failed change is retested"
|
|
self.launch_server.hold_jobs_in_build = True
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
A.addApproval('code-review', 2)
|
|
B.addApproval('code-review', 2)
|
|
|
|
self.launch_server.failJob('project-test1', A)
|
|
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(B.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
self.assertBuilds([dict(name='project-merge', changes='1,1')])
|
|
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
# A/project-merge is complete
|
|
self.assertBuilds([
|
|
dict(name='project-test1', changes='1,1'),
|
|
dict(name='project-test2', changes='1,1'),
|
|
dict(name='project-merge', changes='1,1 2,1'),
|
|
])
|
|
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
# A/project-merge is complete
|
|
# B/project-merge is complete
|
|
self.assertBuilds([
|
|
dict(name='project-test1', changes='1,1'),
|
|
dict(name='project-test2', changes='1,1'),
|
|
dict(name='project-test1', changes='1,1 2,1'),
|
|
dict(name='project-test2', changes='1,1 2,1'),
|
|
])
|
|
|
|
# Release project-test1 for A which will fail. This will
|
|
# abort both running B jobs and relaunch project-merge for B.
|
|
self.builds[0].release()
|
|
self.waitUntilSettled()
|
|
|
|
self.orderedRelease()
|
|
self.assertHistory([
|
|
dict(name='project-merge', result='SUCCESS', changes='1,1'),
|
|
dict(name='project-merge', result='SUCCESS', changes='1,1 2,1'),
|
|
dict(name='project-test1', result='FAILURE', changes='1,1'),
|
|
dict(name='project-test1', result='ABORTED', changes='1,1 2,1'),
|
|
dict(name='project-test2', result='ABORTED', changes='1,1 2,1'),
|
|
dict(name='project-test2', result='SUCCESS', changes='1,1'),
|
|
dict(name='project-merge', result='SUCCESS', changes='2,1'),
|
|
dict(name='project-test1', result='SUCCESS', changes='2,1'),
|
|
dict(name='project-test2', result='SUCCESS', changes='2,1'),
|
|
], ordered=False)
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(B.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertEqual(B.reported, 2)
|
|
|
|
def test_independent_queues(self):
|
|
"Test that changes end up in the right queues"
|
|
|
|
self.launch_server.hold_jobs_in_build = True
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
|
|
C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
|
|
A.addApproval('code-review', 2)
|
|
B.addApproval('code-review', 2)
|
|
C.addApproval('code-review', 2)
|
|
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(B.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(C.addApproval('approved', 1))
|
|
|
|
self.waitUntilSettled()
|
|
|
|
# There should be one merge job at the head of each queue running
|
|
self.assertBuilds([
|
|
dict(name='project-merge', changes='1,1'),
|
|
dict(name='project-merge', changes='2,1'),
|
|
])
|
|
|
|
# Release the current merge builds
|
|
self.builds[0].release()
|
|
self.waitUntilSettled()
|
|
self.builds[0].release()
|
|
self.waitUntilSettled()
|
|
# Release the merge job for project2 which is behind project1
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
|
|
# All the test builds should be running:
|
|
self.assertBuilds([
|
|
dict(name='project-test1', changes='1,1'),
|
|
dict(name='project-test2', changes='1,1'),
|
|
dict(name='project-test1', changes='2,1'),
|
|
dict(name='project-test2', changes='2,1'),
|
|
dict(name='project1-project2-integration', changes='2,1'),
|
|
dict(name='project-test1', changes='2,1 3,1'),
|
|
dict(name='project-test2', changes='2,1 3,1'),
|
|
dict(name='project1-project2-integration', changes='2,1 3,1'),
|
|
])
|
|
|
|
self.orderedRelease()
|
|
self.assertHistory([
|
|
dict(name='project-merge', result='SUCCESS', changes='1,1'),
|
|
dict(name='project-merge', result='SUCCESS', changes='2,1'),
|
|
dict(name='project-merge', result='SUCCESS', changes='2,1 3,1'),
|
|
dict(name='project-test1', result='SUCCESS', changes='1,1'),
|
|
dict(name='project-test2', result='SUCCESS', changes='1,1'),
|
|
dict(name='project-test1', result='SUCCESS', changes='2,1'),
|
|
dict(name='project-test2', result='SUCCESS', changes='2,1'),
|
|
dict(
|
|
name='project1-project2-integration',
|
|
result='SUCCESS',
|
|
changes='2,1'),
|
|
dict(name='project-test1', result='SUCCESS', changes='2,1 3,1'),
|
|
dict(name='project-test2', result='SUCCESS', changes='2,1 3,1'),
|
|
dict(name='project1-project2-integration',
|
|
result='SUCCESS',
|
|
changes='2,1 3,1'),
|
|
])
|
|
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(B.data['status'], 'MERGED')
|
|
self.assertEqual(C.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertEqual(B.reported, 2)
|
|
self.assertEqual(C.reported, 2)
|
|
|
|
def test_failed_change_at_head(self):
|
|
"Test that if a change at the head fails, jobs behind it are canceled"
|
|
|
|
self.launch_server.hold_jobs_in_build = True
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
|
|
A.addApproval('code-review', 2)
|
|
B.addApproval('code-review', 2)
|
|
C.addApproval('code-review', 2)
|
|
|
|
self.launch_server.failJob('project-test1', A)
|
|
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(B.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(C.addApproval('approved', 1))
|
|
|
|
self.waitUntilSettled()
|
|
|
|
self.assertBuilds([
|
|
dict(name='project-merge', changes='1,1'),
|
|
])
|
|
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
|
|
self.assertBuilds([
|
|
dict(name='project-test1', changes='1,1'),
|
|
dict(name='project-test2', changes='1,1'),
|
|
dict(name='project-test1', changes='1,1 2,1'),
|
|
dict(name='project-test2', changes='1,1 2,1'),
|
|
dict(name='project-test1', changes='1,1 2,1 3,1'),
|
|
dict(name='project-test2', changes='1,1 2,1 3,1'),
|
|
])
|
|
|
|
self.release(self.builds[0])
|
|
self.waitUntilSettled()
|
|
|
|
# project-test2, project-merge for B
|
|
self.assertBuilds([
|
|
dict(name='project-test2', changes='1,1'),
|
|
dict(name='project-merge', changes='2,1'),
|
|
])
|
|
# Unordered history comparison because the aborts can finish
|
|
# in any order.
|
|
self.assertHistory([
|
|
dict(name='project-merge', result='SUCCESS',
|
|
changes='1,1'),
|
|
dict(name='project-merge', result='SUCCESS',
|
|
changes='1,1 2,1'),
|
|
dict(name='project-merge', result='SUCCESS',
|
|
changes='1,1 2,1 3,1'),
|
|
dict(name='project-test1', result='FAILURE',
|
|
changes='1,1'),
|
|
dict(name='project-test1', result='ABORTED',
|
|
changes='1,1 2,1'),
|
|
dict(name='project-test2', result='ABORTED',
|
|
changes='1,1 2,1'),
|
|
dict(name='project-test1', result='ABORTED',
|
|
changes='1,1 2,1 3,1'),
|
|
dict(name='project-test2', result='ABORTED',
|
|
changes='1,1 2,1 3,1'),
|
|
], ordered=False)
|
|
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.orderedRelease()
|
|
|
|
self.assertBuilds([])
|
|
self.assertHistory([
|
|
dict(name='project-merge', result='SUCCESS',
|
|
changes='1,1'),
|
|
dict(name='project-merge', result='SUCCESS',
|
|
changes='1,1 2,1'),
|
|
dict(name='project-merge', result='SUCCESS',
|
|
changes='1,1 2,1 3,1'),
|
|
dict(name='project-test1', result='FAILURE',
|
|
changes='1,1'),
|
|
dict(name='project-test1', result='ABORTED',
|
|
changes='1,1 2,1'),
|
|
dict(name='project-test2', result='ABORTED',
|
|
changes='1,1 2,1'),
|
|
dict(name='project-test1', result='ABORTED',
|
|
changes='1,1 2,1 3,1'),
|
|
dict(name='project-test2', result='ABORTED',
|
|
changes='1,1 2,1 3,1'),
|
|
dict(name='project-merge', result='SUCCESS',
|
|
changes='2,1'),
|
|
dict(name='project-merge', result='SUCCESS',
|
|
changes='2,1 3,1'),
|
|
dict(name='project-test2', result='SUCCESS',
|
|
changes='1,1'),
|
|
dict(name='project-test1', result='SUCCESS',
|
|
changes='2,1'),
|
|
dict(name='project-test2', result='SUCCESS',
|
|
changes='2,1'),
|
|
dict(name='project-test1', result='SUCCESS',
|
|
changes='2,1 3,1'),
|
|
dict(name='project-test2', result='SUCCESS',
|
|
changes='2,1 3,1'),
|
|
], ordered=False)
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(B.data['status'], 'MERGED')
|
|
self.assertEqual(C.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertEqual(B.reported, 2)
|
|
self.assertEqual(C.reported, 2)
|
|
|
|
def test_failed_change_in_middle(self):
|
|
"Test a failed change in the middle of the queue"
|
|
|
|
self.launch_server.hold_jobs_in_build = True
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
|
|
A.addApproval('code-review', 2)
|
|
B.addApproval('code-review', 2)
|
|
C.addApproval('code-review', 2)
|
|
|
|
self.launch_server.failJob('project-test1', B)
|
|
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(B.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(C.addApproval('approved', 1))
|
|
|
|
self.waitUntilSettled()
|
|
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(len(self.builds), 6)
|
|
self.assertEqual(self.builds[0].name, 'project-test1')
|
|
self.assertEqual(self.builds[1].name, 'project-test2')
|
|
self.assertEqual(self.builds[2].name, 'project-test1')
|
|
self.assertEqual(self.builds[3].name, 'project-test2')
|
|
self.assertEqual(self.builds[4].name, 'project-test1')
|
|
self.assertEqual(self.builds[5].name, 'project-test2')
|
|
|
|
self.release(self.builds[2])
|
|
self.waitUntilSettled()
|
|
|
|
# project-test1 and project-test2 for A
|
|
# project-test2 for B
|
|
# project-merge for C (without B)
|
|
self.assertEqual(len(self.builds), 4)
|
|
self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 2)
|
|
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
|
|
# project-test1 and project-test2 for A
|
|
# project-test2 for B
|
|
# project-test1 and project-test2 for C
|
|
self.assertEqual(len(self.builds), 5)
|
|
|
|
tenant = self.sched.abide.tenants.get('tenant-one')
|
|
items = tenant.layout.pipelines['gate'].getAllItems()
|
|
builds = items[0].current_build_set.getBuilds()
|
|
self.assertEqual(self.countJobResults(builds, 'SUCCESS'), 1)
|
|
self.assertEqual(self.countJobResults(builds, None), 2)
|
|
builds = items[1].current_build_set.getBuilds()
|
|
self.assertEqual(self.countJobResults(builds, 'SUCCESS'), 1)
|
|
self.assertEqual(self.countJobResults(builds, 'FAILURE'), 1)
|
|
self.assertEqual(self.countJobResults(builds, None), 1)
|
|
builds = items[2].current_build_set.getBuilds()
|
|
self.assertEqual(self.countJobResults(builds, 'SUCCESS'), 1)
|
|
self.assertEqual(self.countJobResults(builds, None), 2)
|
|
|
|
self.launch_server.hold_jobs_in_build = False
|
|
self.launch_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(len(self.builds), 0)
|
|
self.assertEqual(len(self.history), 12)
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(B.data['status'], 'NEW')
|
|
self.assertEqual(C.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertEqual(B.reported, 2)
|
|
self.assertEqual(C.reported, 2)
|
|
|
|
def test_failed_change_at_head_with_queue(self):
|
|
"Test that if a change at the head fails, queued jobs are canceled"
|
|
|
|
self.gearman_server.hold_jobs_in_queue = True
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
|
|
A.addApproval('code-review', 2)
|
|
B.addApproval('code-review', 2)
|
|
C.addApproval('code-review', 2)
|
|
|
|
self.launch_server.failJob('project-test1', A)
|
|
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(B.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(C.addApproval('approved', 1))
|
|
|
|
self.waitUntilSettled()
|
|
queue = self.gearman_server.getQueue()
|
|
self.assertEqual(len(self.builds), 0)
|
|
self.assertEqual(len(queue), 1)
|
|
self.assertEqual(queue[0].name, 'launcher:launch')
|
|
job_args = json.loads(queue[0].arguments)
|
|
self.assertEqual(job_args['job'], 'project-merge')
|
|
self.assertEqual(job_args['items'][0]['number'], '%d' % A.number)
|
|
|
|
self.gearman_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.gearman_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.gearman_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
queue = self.gearman_server.getQueue()
|
|
|
|
self.assertEqual(len(self.builds), 0)
|
|
self.assertEqual(len(queue), 6)
|
|
|
|
self.assertEqual(
|
|
json.loads(queue[0].arguments)['job'], 'project-test1')
|
|
self.assertEqual(
|
|
json.loads(queue[1].arguments)['job'], 'project-test2')
|
|
self.assertEqual(
|
|
json.loads(queue[2].arguments)['job'], 'project-test1')
|
|
self.assertEqual(
|
|
json.loads(queue[3].arguments)['job'], 'project-test2')
|
|
self.assertEqual(
|
|
json.loads(queue[4].arguments)['job'], 'project-test1')
|
|
self.assertEqual(
|
|
json.loads(queue[5].arguments)['job'], 'project-test2')
|
|
|
|
self.release(queue[0])
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(len(self.builds), 0)
|
|
queue = self.gearman_server.getQueue()
|
|
self.assertEqual(len(queue), 2) # project-test2, project-merge for B
|
|
self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 0)
|
|
|
|
self.gearman_server.hold_jobs_in_queue = False
|
|
self.gearman_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(len(self.builds), 0)
|
|
self.assertEqual(len(self.history), 11)
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(B.data['status'], 'MERGED')
|
|
self.assertEqual(C.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertEqual(B.reported, 2)
|
|
self.assertEqual(C.reported, 2)
|
|
|
|
@skip("Disabled for early v3 development")
|
|
def _test_time_database(self, iteration):
|
|
self.launch_server.hold_jobs_in_build = True
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
A.addApproval('code-review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
time.sleep(2)
|
|
|
|
data = json.loads(self.sched.formatStatusJSON())
|
|
found_job = None
|
|
for pipeline in data['pipelines']:
|
|
if pipeline['name'] != 'gate':
|
|
continue
|
|
for queue in pipeline['change_queues']:
|
|
for head in queue['heads']:
|
|
for item in head:
|
|
for job in item['jobs']:
|
|
if job['name'] == 'project-merge':
|
|
found_job = job
|
|
break
|
|
|
|
self.assertIsNotNone(found_job)
|
|
if iteration == 1:
|
|
self.assertIsNotNone(found_job['estimated_time'])
|
|
self.assertIsNone(found_job['remaining_time'])
|
|
else:
|
|
self.assertIsNotNone(found_job['estimated_time'])
|
|
self.assertTrue(found_job['estimated_time'] >= 2)
|
|
self.assertIsNotNone(found_job['remaining_time'])
|
|
|
|
self.launch_server.hold_jobs_in_build = False
|
|
self.launch_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
@skip("Disabled for early v3 development")
|
|
def test_time_database(self):
|
|
"Test the time database"
|
|
|
|
self._test_time_database(1)
|
|
self._test_time_database(2)
|
|
|
|
def test_two_failed_changes_at_head(self):
|
|
"Test that changes are reparented correctly if 2 fail at head"
|
|
|
|
self.launch_server.hold_jobs_in_build = True
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
|
|
A.addApproval('code-review', 2)
|
|
B.addApproval('code-review', 2)
|
|
C.addApproval('code-review', 2)
|
|
|
|
self.launch_server.failJob('project-test1', A)
|
|
self.launch_server.failJob('project-test1', B)
|
|
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(B.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(C.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(len(self.builds), 6)
|
|
self.assertEqual(self.builds[0].name, 'project-test1')
|
|
self.assertEqual(self.builds[1].name, 'project-test2')
|
|
self.assertEqual(self.builds[2].name, 'project-test1')
|
|
self.assertEqual(self.builds[3].name, 'project-test2')
|
|
self.assertEqual(self.builds[4].name, 'project-test1')
|
|
self.assertEqual(self.builds[5].name, 'project-test2')
|
|
|
|
self.assertTrue(self.builds[0].hasChanges(A))
|
|
self.assertTrue(self.builds[2].hasChanges(A))
|
|
self.assertTrue(self.builds[2].hasChanges(B))
|
|
self.assertTrue(self.builds[4].hasChanges(A))
|
|
self.assertTrue(self.builds[4].hasChanges(B))
|
|
self.assertTrue(self.builds[4].hasChanges(C))
|
|
|
|
# Fail change B first
|
|
self.release(self.builds[2])
|
|
self.waitUntilSettled()
|
|
|
|
# restart of C after B failure
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(len(self.builds), 5)
|
|
self.assertEqual(self.builds[0].name, 'project-test1')
|
|
self.assertEqual(self.builds[1].name, 'project-test2')
|
|
self.assertEqual(self.builds[2].name, 'project-test2')
|
|
self.assertEqual(self.builds[3].name, 'project-test1')
|
|
self.assertEqual(self.builds[4].name, 'project-test2')
|
|
|
|
self.assertTrue(self.builds[1].hasChanges(A))
|
|
self.assertTrue(self.builds[2].hasChanges(A))
|
|
self.assertTrue(self.builds[2].hasChanges(B))
|
|
self.assertTrue(self.builds[4].hasChanges(A))
|
|
self.assertFalse(self.builds[4].hasChanges(B))
|
|
self.assertTrue(self.builds[4].hasChanges(C))
|
|
|
|
# Finish running all passing jobs for change A
|
|
self.release(self.builds[1])
|
|
self.waitUntilSettled()
|
|
# Fail and report change A
|
|
self.release(self.builds[0])
|
|
self.waitUntilSettled()
|
|
|
|
# restart of B,C after A failure
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(len(self.builds), 4)
|
|
self.assertEqual(self.builds[0].name, 'project-test1') # B
|
|
self.assertEqual(self.builds[1].name, 'project-test2') # B
|
|
self.assertEqual(self.builds[2].name, 'project-test1') # C
|
|
self.assertEqual(self.builds[3].name, 'project-test2') # C
|
|
|
|
self.assertFalse(self.builds[1].hasChanges(A))
|
|
self.assertTrue(self.builds[1].hasChanges(B))
|
|
self.assertFalse(self.builds[1].hasChanges(C))
|
|
|
|
self.assertFalse(self.builds[2].hasChanges(A))
|
|
# After A failed and B and C restarted, B should be back in
|
|
# C's tests because it has not failed yet.
|
|
self.assertTrue(self.builds[2].hasChanges(B))
|
|
self.assertTrue(self.builds[2].hasChanges(C))
|
|
|
|
self.launch_server.hold_jobs_in_build = False
|
|
self.launch_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(len(self.builds), 0)
|
|
self.assertEqual(len(self.history), 21)
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(B.data['status'], 'NEW')
|
|
self.assertEqual(C.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertEqual(B.reported, 2)
|
|
self.assertEqual(C.reported, 2)
|
|
|
|
def test_patch_order(self):
|
|
"Test that dependent patches are tested in the right order"
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
|
|
A.addApproval('code-review', 2)
|
|
B.addApproval('code-review', 2)
|
|
C.addApproval('code-review', 2)
|
|
|
|
M2 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M2')
|
|
M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
|
|
M2.setMerged()
|
|
M1.setMerged()
|
|
|
|
# C -> B -> A -> M1 -> M2
|
|
# M2 is here to make sure it is never queried. If it is, it
|
|
# means zuul is walking down the entire history of merged
|
|
# changes.
|
|
|
|
C.setDependsOn(B, 1)
|
|
B.setDependsOn(A, 1)
|
|
A.setDependsOn(M1, 1)
|
|
M1.setDependsOn(M2, 1)
|
|
|
|
self.fake_gerrit.addEvent(C.addApproval('approved', 1))
|
|
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(B.data['status'], 'NEW')
|
|
self.assertEqual(C.data['status'], 'NEW')
|
|
|
|
self.fake_gerrit.addEvent(B.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
|
|
self.waitUntilSettled()
|
|
self.assertEqual(M2.queried, 0)
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(B.data['status'], 'MERGED')
|
|
self.assertEqual(C.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertEqual(B.reported, 2)
|
|
self.assertEqual(C.reported, 2)
|
|
|
|
def test_needed_changes_enqueue(self):
|
|
"Test that a needed change is enqueued ahead"
|
|
# A Given a git tree like this, if we enqueue
|
|
# / \ change C, we should walk up and down the tree
|
|
# B G and enqueue changes in the order ABCDEFG.
|
|
# /|\ This is also the order that you would get if
|
|
# *C E F you enqueued changes in the order ABCDEFG, so
|
|
# / the ordering is stable across re-enqueue events.
|
|
# D
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
|
|
D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
|
|
E = self.fake_gerrit.addFakeChange('org/project', 'master', 'E')
|
|
F = self.fake_gerrit.addFakeChange('org/project', 'master', 'F')
|
|
G = self.fake_gerrit.addFakeChange('org/project', 'master', 'G')
|
|
B.setDependsOn(A, 1)
|
|
C.setDependsOn(B, 1)
|
|
D.setDependsOn(C, 1)
|
|
E.setDependsOn(B, 1)
|
|
F.setDependsOn(B, 1)
|
|
G.setDependsOn(A, 1)
|
|
|
|
A.addApproval('code-review', 2)
|
|
B.addApproval('code-review', 2)
|
|
C.addApproval('code-review', 2)
|
|
D.addApproval('code-review', 2)
|
|
E.addApproval('code-review', 2)
|
|
F.addApproval('code-review', 2)
|
|
G.addApproval('code-review', 2)
|
|
self.fake_gerrit.addEvent(C.addApproval('approved', 1))
|
|
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(B.data['status'], 'NEW')
|
|
self.assertEqual(C.data['status'], 'NEW')
|
|
self.assertEqual(D.data['status'], 'NEW')
|
|
self.assertEqual(E.data['status'], 'NEW')
|
|
self.assertEqual(F.data['status'], 'NEW')
|
|
self.assertEqual(G.data['status'], 'NEW')
|
|
|
|
# We're about to add approvals to changes without adding the
|
|
# triggering events to Zuul, so that we can be sure that it is
|
|
# enqueing the changes based on dependencies, not because of
|
|
# triggering events. Since it will have the changes cached
|
|
# already (without approvals), we need to clear the cache
|
|
# first.
|
|
for connection in self.connections.connections.values():
|
|
connection.maintainCache([])
|
|
|
|
self.launch_server.hold_jobs_in_build = True
|
|
A.addApproval('approved', 1)
|
|
B.addApproval('approved', 1)
|
|
D.addApproval('approved', 1)
|
|
E.addApproval('approved', 1)
|
|
F.addApproval('approved', 1)
|
|
G.addApproval('approved', 1)
|
|
self.fake_gerrit.addEvent(C.addApproval('approved', 1))
|
|
|
|
for x in range(8):
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.hold_jobs_in_build = False
|
|
self.launch_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(B.data['status'], 'MERGED')
|
|
self.assertEqual(C.data['status'], 'MERGED')
|
|
self.assertEqual(D.data['status'], 'MERGED')
|
|
self.assertEqual(E.data['status'], 'MERGED')
|
|
self.assertEqual(F.data['status'], 'MERGED')
|
|
self.assertEqual(G.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertEqual(B.reported, 2)
|
|
self.assertEqual(C.reported, 2)
|
|
self.assertEqual(D.reported, 2)
|
|
self.assertEqual(E.reported, 2)
|
|
self.assertEqual(F.reported, 2)
|
|
self.assertEqual(G.reported, 2)
|
|
self.assertEqual(self.history[6].changes,
|
|
'1,1 2,1 3,1 4,1 5,1 6,1 7,1')
|
|
|
|
def test_source_cache(self):
|
|
"Test that the source cache operates correctly"
|
|
self.launch_server.hold_jobs_in_build = True
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
X = self.fake_gerrit.addFakeChange('org/project', 'master', 'X')
|
|
A.addApproval('code-review', 2)
|
|
B.addApproval('code-review', 2)
|
|
|
|
M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
|
|
M1.setMerged()
|
|
|
|
B.setDependsOn(A, 1)
|
|
A.setDependsOn(M1, 1)
|
|
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(X.getPatchsetCreatedEvent(1))
|
|
|
|
self.waitUntilSettled()
|
|
|
|
for build in self.builds:
|
|
if build.parameters['ZUUL_PIPELINE'] == 'check':
|
|
build.release()
|
|
self.waitUntilSettled()
|
|
for build in self.builds:
|
|
if build.parameters['ZUUL_PIPELINE'] == 'check':
|
|
build.release()
|
|
self.waitUntilSettled()
|
|
|
|
self.fake_gerrit.addEvent(B.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.log.debug("len %s" % self.fake_gerrit._change_cache.keys())
|
|
# there should still be changes in the cache
|
|
self.assertNotEqual(len(self.fake_gerrit._change_cache.keys()), 0)
|
|
|
|
self.launch_server.hold_jobs_in_build = False
|
|
self.launch_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(B.data['status'], 'MERGED')
|
|
self.assertEqual(A.queried, 2) # Initial and isMerged
|
|
self.assertEqual(B.queried, 3) # Initial A, refresh from B, isMerged
|
|
|
|
def test_can_merge(self):
|
|
"Test whether a change is ready to merge"
|
|
# TODO: move to test_gerrit (this is a unit test!)
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
tenant = self.sched.abide.tenants.get('tenant-one')
|
|
source = tenant.layout.pipelines['gate'].source
|
|
|
|
# TODO(pabelanger): As we add more source / trigger APIs we should make
|
|
# it easier for users to create events for testing.
|
|
event = zuul.model.TriggerEvent()
|
|
event.trigger_name = 'gerrit'
|
|
event.change_number = '1'
|
|
event.patch_number = '2'
|
|
|
|
a = source.getChange(event)
|
|
mgr = tenant.layout.pipelines['gate'].manager
|
|
self.assertFalse(source.canMerge(a, mgr.getSubmitAllowNeeds()))
|
|
|
|
A.addApproval('code-review', 2)
|
|
a = source.getChange(event, refresh=True)
|
|
self.assertFalse(source.canMerge(a, mgr.getSubmitAllowNeeds()))
|
|
|
|
A.addApproval('approved', 1)
|
|
a = source.getChange(event, refresh=True)
|
|
self.assertTrue(source.canMerge(a, mgr.getSubmitAllowNeeds()))
|
|
|
|
@skip("Disabled for early v3 development")
|
|
def test_build_configuration_conflict(self):
|
|
"Test that merge conflicts are handled"
|
|
|
|
self.gearman_server.hold_jobs_in_queue = True
|
|
A = self.fake_gerrit.addFakeChange('org/conflict-project',
|
|
'master', 'A')
|
|
A.addPatchset(['conflict'])
|
|
B = self.fake_gerrit.addFakeChange('org/conflict-project',
|
|
'master', 'B')
|
|
B.addPatchset(['conflict'])
|
|
C = self.fake_gerrit.addFakeChange('org/conflict-project',
|
|
'master', 'C')
|
|
A.addApproval('code-review', 2)
|
|
B.addApproval('code-review', 2)
|
|
C.addApproval('code-review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(B.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(C.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.reported, 1)
|
|
self.assertEqual(B.reported, 1)
|
|
self.assertEqual(C.reported, 1)
|
|
|
|
self.gearman_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.gearman_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.gearman_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(len(self.history), 2) # A and C merge jobs
|
|
|
|
self.gearman_server.hold_jobs_in_queue = False
|
|
self.gearman_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(B.data['status'], 'NEW')
|
|
self.assertEqual(C.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertEqual(B.reported, 2)
|
|
self.assertEqual(C.reported, 2)
|
|
self.assertEqual(len(self.history), 6)
|
|
|
|
def test_post(self):
|
|
"Test that post jobs run"
|
|
|
|
e = {
|
|
"type": "ref-updated",
|
|
"submitter": {
|
|
"name": "User Name",
|
|
},
|
|
"refUpdate": {
|
|
"oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
|
|
"newRev": "d479a0bfcb34da57a31adb2a595c0cf687812543",
|
|
"refName": "master",
|
|
"project": "org/project",
|
|
}
|
|
}
|
|
self.fake_gerrit.addEvent(e)
|
|
self.waitUntilSettled()
|
|
|
|
job_names = [x.name for x in self.history]
|
|
self.assertEqual(len(self.history), 1)
|
|
self.assertIn('project-post', job_names)
|
|
|
|
def test_post_ignore_deletes(self):
|
|
"Test that deleting refs does not trigger post jobs"
|
|
|
|
e = {
|
|
"type": "ref-updated",
|
|
"submitter": {
|
|
"name": "User Name",
|
|
},
|
|
"refUpdate": {
|
|
"oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
|
|
"newRev": "0000000000000000000000000000000000000000",
|
|
"refName": "master",
|
|
"project": "org/project",
|
|
}
|
|
}
|
|
self.fake_gerrit.addEvent(e)
|
|
self.waitUntilSettled()
|
|
|
|
job_names = [x.name for x in self.history]
|
|
self.assertEqual(len(self.history), 0)
|
|
self.assertNotIn('project-post', job_names)
|
|
|
|
def test_post_ignore_deletes_negative(self):
|
|
"Test that deleting refs does trigger post jobs"
|
|
|
|
self.updateConfigLayout('layout-dont-ignore-ref-deletes')
|
|
self.sched.reconfigure(self.config)
|
|
|
|
e = {
|
|
"type": "ref-updated",
|
|
"submitter": {
|
|
"name": "User Name",
|
|
},
|
|
"refUpdate": {
|
|
"oldRev": "90f173846e3af9154517b88543ffbd1691f31366",
|
|
"newRev": "0000000000000000000000000000000000000000",
|
|
"refName": "master",
|
|
"project": "org/project",
|
|
}
|
|
}
|
|
self.fake_gerrit.addEvent(e)
|
|
self.waitUntilSettled()
|
|
|
|
job_names = [x.name for x in self.history]
|
|
self.assertEqual(len(self.history), 1)
|
|
self.assertIn('project-post', job_names)
|
|
|
|
@skip("Disabled for early v3 development")
|
|
def test_build_configuration_branch_interaction(self):
|
|
"Test that switching between branches works"
|
|
self.test_build_configuration()
|
|
self.test_build_configuration_branch()
|
|
# C has been merged, undo that
|
|
path = os.path.join(self.upstream_root, "org/project")
|
|
repo = git.Repo(path)
|
|
repo.heads.master.commit = repo.commit('init')
|
|
self.test_build_configuration()
|
|
|
|
def test_dependent_changes_dequeue(self):
|
|
"Test that dependent patches are not needlessly tested"
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
|
|
A.addApproval('code-review', 2)
|
|
B.addApproval('code-review', 2)
|
|
C.addApproval('code-review', 2)
|
|
|
|
M1 = self.fake_gerrit.addFakeChange('org/project', 'master', 'M1')
|
|
M1.setMerged()
|
|
|
|
# C -> B -> A -> M1
|
|
|
|
C.setDependsOn(B, 1)
|
|
B.setDependsOn(A, 1)
|
|
A.setDependsOn(M1, 1)
|
|
|
|
self.launch_server.failJob('project-merge', A)
|
|
|
|
self.fake_gerrit.addEvent(C.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(B.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertEqual(B.data['status'], 'NEW')
|
|
self.assertEqual(B.reported, 2)
|
|
self.assertEqual(C.data['status'], 'NEW')
|
|
self.assertEqual(C.reported, 2)
|
|
self.assertEqual(len(self.history), 1)
|
|
|
|
def test_failing_dependent_changes(self):
|
|
"Test that failing dependent patches are taken out of stream"
|
|
self.launch_server.hold_jobs_in_build = True
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
|
|
D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
|
|
E = self.fake_gerrit.addFakeChange('org/project', 'master', 'E')
|
|
A.addApproval('code-review', 2)
|
|
B.addApproval('code-review', 2)
|
|
C.addApproval('code-review', 2)
|
|
D.addApproval('code-review', 2)
|
|
E.addApproval('code-review', 2)
|
|
|
|
# E, D -> C -> B, A
|
|
|
|
D.setDependsOn(C, 1)
|
|
C.setDependsOn(B, 1)
|
|
|
|
self.launch_server.failJob('project-test1', B)
|
|
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(D.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(C.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(B.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(E.addApproval('approved', 1))
|
|
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
|
|
self.launch_server.hold_jobs_in_build = False
|
|
for build in self.builds:
|
|
if build.parameters['ZUUL_CHANGE'] != '1':
|
|
build.release()
|
|
self.waitUntilSettled()
|
|
|
|
self.launch_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertIn('Build succeeded', A.messages[1])
|
|
self.assertEqual(B.data['status'], 'NEW')
|
|
self.assertEqual(B.reported, 2)
|
|
self.assertIn('Build failed', B.messages[1])
|
|
self.assertEqual(C.data['status'], 'NEW')
|
|
self.assertEqual(C.reported, 2)
|
|
self.assertIn('depends on a change', C.messages[1])
|
|
self.assertEqual(D.data['status'], 'NEW')
|
|
self.assertEqual(D.reported, 2)
|
|
self.assertIn('depends on a change', D.messages[1])
|
|
self.assertEqual(E.data['status'], 'MERGED')
|
|
self.assertEqual(E.reported, 2)
|
|
self.assertIn('Build succeeded', E.messages[1])
|
|
self.assertEqual(len(self.history), 18)
|
|
|
|
def test_head_is_dequeued_once(self):
|
|
"Test that if a change at the head fails it is dequeued only once"
|
|
# If it's dequeued more than once, we should see extra
|
|
# aborted jobs.
|
|
|
|
self.launch_server.hold_jobs_in_build = True
|
|
A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
|
|
B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
|
|
C = self.fake_gerrit.addFakeChange('org/project1', 'master', 'C')
|
|
A.addApproval('code-review', 2)
|
|
B.addApproval('code-review', 2)
|
|
C.addApproval('code-review', 2)
|
|
|
|
self.launch_server.failJob('project-test1', A)
|
|
self.launch_server.failJob('project-test2', A)
|
|
self.launch_server.failJob('project1-project2-integration', A)
|
|
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(B.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(C.addApproval('approved', 1))
|
|
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(len(self.builds), 1)
|
|
self.assertEqual(self.builds[0].name, 'project-merge')
|
|
self.assertTrue(self.builds[0].hasChanges(A))
|
|
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(len(self.builds), 9)
|
|
self.assertEqual(self.builds[0].name, 'project-test1')
|
|
self.assertEqual(self.builds[1].name, 'project-test2')
|
|
self.assertEqual(self.builds[2].name, 'project1-project2-integration')
|
|
self.assertEqual(self.builds[3].name, 'project-test1')
|
|
self.assertEqual(self.builds[4].name, 'project-test2')
|
|
self.assertEqual(self.builds[5].name, 'project1-project2-integration')
|
|
self.assertEqual(self.builds[6].name, 'project-test1')
|
|
self.assertEqual(self.builds[7].name, 'project-test2')
|
|
self.assertEqual(self.builds[8].name, 'project1-project2-integration')
|
|
|
|
self.release(self.builds[0])
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(len(self.builds), 3) # test2,integration, merge for B
|
|
self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 6)
|
|
|
|
self.launch_server.hold_jobs_in_build = False
|
|
self.launch_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(len(self.builds), 0)
|
|
self.assertEqual(len(self.history), 20)
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(B.data['status'], 'MERGED')
|
|
self.assertEqual(C.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertEqual(B.reported, 2)
|
|
self.assertEqual(C.reported, 2)
|
|
|
|
def test_nonvoting_job(self):
|
|
"Test that non-voting jobs don't vote."
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/nonvoting-project',
|
|
'master', 'A')
|
|
A.addApproval('code-review', 2)
|
|
self.launch_server.failJob('nonvoting-project-test2', A)
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertEqual(
|
|
self.getJobFromHistory('nonvoting-project-merge').result,
|
|
'SUCCESS')
|
|
self.assertEqual(
|
|
self.getJobFromHistory('nonvoting-project-test1').result,
|
|
'SUCCESS')
|
|
self.assertEqual(
|
|
self.getJobFromHistory('nonvoting-project-test2').result,
|
|
'FAILURE')
|
|
|
|
for build in self.builds:
|
|
self.assertEqual(build.parameters['ZUUL_VOTING'], '0')
|
|
|
|
def test_check_queue_success(self):
|
|
"Test successful check queue jobs."
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1)
|
|
self.assertEqual(self.getJobFromHistory('project-merge').result,
|
|
'SUCCESS')
|
|
self.assertEqual(self.getJobFromHistory('project-test1').result,
|
|
'SUCCESS')
|
|
self.assertEqual(self.getJobFromHistory('project-test2').result,
|
|
'SUCCESS')
|
|
|
|
def test_check_queue_failure(self):
|
|
"Test failed check queue jobs."
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
self.launch_server.failJob('project-test2', A)
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1)
|
|
self.assertEqual(self.getJobFromHistory('project-merge').result,
|
|
'SUCCESS')
|
|
self.assertEqual(self.getJobFromHistory('project-test1').result,
|
|
'SUCCESS')
|
|
self.assertEqual(self.getJobFromHistory('project-test2').result,
|
|
'FAILURE')
|
|
|
|
def test_dependent_behind_dequeue(self):
|
|
"test that dependent changes behind dequeued changes work"
|
|
# This complicated test is a reproduction of a real life bug
|
|
self.sched.reconfigure(self.config)
|
|
|
|
self.launch_server.hold_jobs_in_build = True
|
|
A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
|
|
B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
|
|
C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
|
|
D = self.fake_gerrit.addFakeChange('org/project2', 'master', 'D')
|
|
E = self.fake_gerrit.addFakeChange('org/project2', 'master', 'E')
|
|
F = self.fake_gerrit.addFakeChange('org/project3', 'master', 'F')
|
|
D.setDependsOn(C, 1)
|
|
E.setDependsOn(D, 1)
|
|
A.addApproval('code-review', 2)
|
|
B.addApproval('code-review', 2)
|
|
C.addApproval('code-review', 2)
|
|
D.addApproval('code-review', 2)
|
|
E.addApproval('code-review', 2)
|
|
F.addApproval('code-review', 2)
|
|
|
|
A.fail_merge = True
|
|
|
|
# Change object re-use in the gerrit trigger is hidden if
|
|
# changes are added in quick succession; waiting makes it more
|
|
# like real life.
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
self.fake_gerrit.addEvent(B.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
|
|
self.fake_gerrit.addEvent(C.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
self.fake_gerrit.addEvent(D.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
self.fake_gerrit.addEvent(E.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
self.fake_gerrit.addEvent(F.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
|
|
# all jobs running
|
|
|
|
# Grab pointers to the jobs we want to release before
|
|
# releasing any, because list indexes may change as
|
|
# the jobs complete.
|
|
a, b, c = self.builds[:3]
|
|
a.release()
|
|
b.release()
|
|
c.release()
|
|
self.waitUntilSettled()
|
|
|
|
self.launch_server.hold_jobs_in_build = False
|
|
self.launch_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(B.data['status'], 'MERGED')
|
|
self.assertEqual(C.data['status'], 'MERGED')
|
|
self.assertEqual(D.data['status'], 'MERGED')
|
|
self.assertEqual(E.data['status'], 'MERGED')
|
|
self.assertEqual(F.data['status'], 'MERGED')
|
|
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertEqual(B.reported, 2)
|
|
self.assertEqual(C.reported, 2)
|
|
self.assertEqual(D.reported, 2)
|
|
self.assertEqual(E.reported, 2)
|
|
self.assertEqual(F.reported, 2)
|
|
|
|
self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 15)
|
|
self.assertEqual(len(self.history), 44)
|
|
|
|
def test_merger_repack(self):
|
|
"Test that the merger works after a repack"
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
A.addApproval('code-review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(self.getJobFromHistory('project-merge').result,
|
|
'SUCCESS')
|
|
self.assertEqual(self.getJobFromHistory('project-test1').result,
|
|
'SUCCESS')
|
|
self.assertEqual(self.getJobFromHistory('project-test2').result,
|
|
'SUCCESS')
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertEmptyQueues()
|
|
self.build_history = []
|
|
|
|
path = os.path.join(self.git_root, "org/project")
|
|
print(repack_repo(path))
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
A.addApproval('code-review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(self.getJobFromHistory('project-merge').result,
|
|
'SUCCESS')
|
|
self.assertEqual(self.getJobFromHistory('project-test1').result,
|
|
'SUCCESS')
|
|
self.assertEqual(self.getJobFromHistory('project-test2').result,
|
|
'SUCCESS')
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
|
|
def test_merger_repack_large_change(self):
|
|
"Test that the merger works with large changes after a repack"
|
|
# https://bugs.launchpad.net/zuul/+bug/1078946
|
|
# This test assumes the repo is already cloned; make sure it is
|
|
tenant = self.sched.abide.tenants.get('tenant-one')
|
|
url = self.fake_gerrit.getGitUrl(
|
|
tenant.layout.project_configs.get('org/project1'))
|
|
self.merge_server.merger.addProject('org/project1', url)
|
|
A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
|
|
A.addPatchset(large=True)
|
|
path = os.path.join(self.upstream_root, "org/project1")
|
|
print(repack_repo(path))
|
|
path = os.path.join(self.git_root, "org/project1")
|
|
print(repack_repo(path))
|
|
|
|
A.addApproval('code-review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(self.getJobFromHistory('project-merge').result,
|
|
'SUCCESS')
|
|
self.assertEqual(self.getJobFromHistory('project-test1').result,
|
|
'SUCCESS')
|
|
self.assertEqual(self.getJobFromHistory('project-test2').result,
|
|
'SUCCESS')
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
|
|
def test_new_patchset_dequeues_old(self):
|
|
"Test that a new patchset causes the old to be dequeued"
|
|
# D -> C (depends on B) -> B (depends on A) -> A -> M
|
|
self.launch_server.hold_jobs_in_build = True
|
|
M = self.fake_gerrit.addFakeChange('org/project', 'master', 'M')
|
|
M.setMerged()
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
|
|
D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
|
|
A.addApproval('code-review', 2)
|
|
B.addApproval('code-review', 2)
|
|
C.addApproval('code-review', 2)
|
|
D.addApproval('code-review', 2)
|
|
|
|
C.setDependsOn(B, 1)
|
|
B.setDependsOn(A, 1)
|
|
A.setDependsOn(M, 1)
|
|
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(B.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(C.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(D.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
B.addPatchset()
|
|
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
|
|
self.waitUntilSettled()
|
|
|
|
self.launch_server.hold_jobs_in_build = False
|
|
self.launch_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertEqual(B.data['status'], 'NEW')
|
|
self.assertEqual(B.reported, 2)
|
|
self.assertEqual(C.data['status'], 'NEW')
|
|
self.assertEqual(C.reported, 2)
|
|
self.assertEqual(D.data['status'], 'MERGED')
|
|
self.assertEqual(D.reported, 2)
|
|
self.assertEqual(len(self.history), 9) # 3 each for A, B, D.
|
|
|
|
def test_new_patchset_check(self):
|
|
"Test a new patchset in check"
|
|
|
|
self.launch_server.hold_jobs_in_build = True
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
tenant = self.sched.abide.tenants.get('tenant-one')
|
|
check_pipeline = tenant.layout.pipelines['check']
|
|
|
|
# Add two git-dependent changes
|
|
B.setDependsOn(A, 1)
|
|
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
# A live item, and a non-live/live pair
|
|
items = check_pipeline.getAllItems()
|
|
self.assertEqual(len(items), 3)
|
|
|
|
self.assertEqual(items[0].change.number, '1')
|
|
self.assertEqual(items[0].change.patchset, '1')
|
|
self.assertFalse(items[0].live)
|
|
|
|
self.assertEqual(items[1].change.number, '2')
|
|
self.assertEqual(items[1].change.patchset, '1')
|
|
self.assertTrue(items[1].live)
|
|
|
|
self.assertEqual(items[2].change.number, '1')
|
|
self.assertEqual(items[2].change.patchset, '1')
|
|
self.assertTrue(items[2].live)
|
|
|
|
# Add a new patchset to A
|
|
A.addPatchset()
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
|
|
self.waitUntilSettled()
|
|
|
|
# The live copy of A,1 should be gone, but the non-live and B
|
|
# should continue, and we should have a new A,2
|
|
items = check_pipeline.getAllItems()
|
|
self.assertEqual(len(items), 3)
|
|
|
|
self.assertEqual(items[0].change.number, '1')
|
|
self.assertEqual(items[0].change.patchset, '1')
|
|
self.assertFalse(items[0].live)
|
|
|
|
self.assertEqual(items[1].change.number, '2')
|
|
self.assertEqual(items[1].change.patchset, '1')
|
|
self.assertTrue(items[1].live)
|
|
|
|
self.assertEqual(items[2].change.number, '1')
|
|
self.assertEqual(items[2].change.patchset, '2')
|
|
self.assertTrue(items[2].live)
|
|
|
|
# Add a new patchset to B
|
|
B.addPatchset()
|
|
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
|
|
self.waitUntilSettled()
|
|
|
|
# The live copy of B,1 should be gone, and it's non-live copy of A,1
|
|
# but we should have a new B,2 (still based on A,1)
|
|
items = check_pipeline.getAllItems()
|
|
self.assertEqual(len(items), 3)
|
|
|
|
self.assertEqual(items[0].change.number, '1')
|
|
self.assertEqual(items[0].change.patchset, '2')
|
|
self.assertTrue(items[0].live)
|
|
|
|
self.assertEqual(items[1].change.number, '1')
|
|
self.assertEqual(items[1].change.patchset, '1')
|
|
self.assertFalse(items[1].live)
|
|
|
|
self.assertEqual(items[2].change.number, '2')
|
|
self.assertEqual(items[2].change.patchset, '2')
|
|
self.assertTrue(items[2].live)
|
|
|
|
self.builds[0].release()
|
|
self.waitUntilSettled()
|
|
self.builds[0].release()
|
|
self.waitUntilSettled()
|
|
self.launch_server.hold_jobs_in_build = False
|
|
self.launch_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.reported, 1)
|
|
self.assertEqual(B.reported, 1)
|
|
self.assertEqual(self.history[0].result, 'ABORTED')
|
|
self.assertEqual(self.history[0].changes, '1,1')
|
|
self.assertEqual(self.history[1].result, 'ABORTED')
|
|
self.assertEqual(self.history[1].changes, '1,1 2,1')
|
|
self.assertEqual(self.history[2].result, 'SUCCESS')
|
|
self.assertEqual(self.history[2].changes, '1,2')
|
|
self.assertEqual(self.history[3].result, 'SUCCESS')
|
|
self.assertEqual(self.history[3].changes, '1,1 2,2')
|
|
|
|
def test_abandoned_gate(self):
|
|
"Test that an abandoned change is dequeued from gate"
|
|
|
|
self.launch_server.hold_jobs_in_build = True
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
A.addApproval('code-review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.builds), 1, "One job being built (on hold)")
|
|
self.assertEqual(self.builds[0].name, 'project-merge')
|
|
|
|
self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
|
|
self.waitUntilSettled()
|
|
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
|
|
self.assertBuilds([])
|
|
self.assertHistory([
|
|
dict(name='project-merge', result='ABORTED', changes='1,1')],
|
|
ordered=False)
|
|
self.assertEqual(A.reported, 1,
|
|
"Abandoned gate change should report only start")
|
|
|
|
def test_abandoned_check(self):
|
|
"Test that an abandoned change is dequeued from check"
|
|
|
|
self.launch_server.hold_jobs_in_build = True
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
tenant = self.sched.abide.tenants.get('tenant-one')
|
|
check_pipeline = tenant.layout.pipelines['check']
|
|
|
|
# Add two git-dependent changes
|
|
B.setDependsOn(A, 1)
|
|
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
# A live item, and a non-live/live pair
|
|
items = check_pipeline.getAllItems()
|
|
self.assertEqual(len(items), 3)
|
|
|
|
self.assertEqual(items[0].change.number, '1')
|
|
self.assertFalse(items[0].live)
|
|
|
|
self.assertEqual(items[1].change.number, '2')
|
|
self.assertTrue(items[1].live)
|
|
|
|
self.assertEqual(items[2].change.number, '1')
|
|
self.assertTrue(items[2].live)
|
|
|
|
# Abandon A
|
|
self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
|
|
self.waitUntilSettled()
|
|
|
|
# The live copy of A should be gone, but the non-live and B
|
|
# should continue
|
|
items = check_pipeline.getAllItems()
|
|
self.assertEqual(len(items), 2)
|
|
|
|
self.assertEqual(items[0].change.number, '1')
|
|
self.assertFalse(items[0].live)
|
|
|
|
self.assertEqual(items[1].change.number, '2')
|
|
self.assertTrue(items[1].live)
|
|
|
|
self.launch_server.hold_jobs_in_build = False
|
|
self.launch_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(len(self.history), 4)
|
|
self.assertEqual(self.history[0].result, 'ABORTED',
|
|
'Build should have been aborted')
|
|
self.assertEqual(A.reported, 0, "Abandoned change should not report")
|
|
self.assertEqual(B.reported, 1, "Change should report")
|
|
|
|
@skip("Disabled for early v3 development")
|
|
def test_abandoned_not_timer(self):
|
|
"Test that an abandoned change does not cancel timer jobs"
|
|
|
|
self.launch_server.hold_jobs_in_build = True
|
|
|
|
# Start timer trigger - also org/project
|
|
self.updateConfigLayout(
|
|
'tests/fixtures/layout-idle.yaml')
|
|
self.sched.reconfigure(self.config)
|
|
self.registerJobs()
|
|
# The pipeline triggers every second, so we should have seen
|
|
# several by now.
|
|
time.sleep(5)
|
|
self.waitUntilSettled()
|
|
# Stop queuing timer triggered jobs so that the assertions
|
|
# below don't race against more jobs being queued.
|
|
self.updateConfigLayout(
|
|
'tests/fixtures/layout-no-timer.yaml')
|
|
self.sched.reconfigure(self.config)
|
|
self.registerJobs()
|
|
self.assertEqual(len(self.builds), 2, "Two timer jobs")
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.builds), 3, "One change plus two timer jobs")
|
|
|
|
self.fake_gerrit.addEvent(A.getChangeAbandonedEvent())
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(len(self.builds), 2, "Two timer jobs remain")
|
|
|
|
self.launch_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
def test_zuul_url_return(self):
|
|
"Test if ZUUL_URL is returning when zuul_url is set in zuul.conf"
|
|
self.assertTrue(self.sched.config.has_option('merger', 'zuul_url'))
|
|
self.launch_server.hold_jobs_in_build = True
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
A.addApproval('code-review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(len(self.builds), 1)
|
|
for build in self.builds:
|
|
self.assertTrue('ZUUL_URL' in build.parameters)
|
|
|
|
self.launch_server.hold_jobs_in_build = False
|
|
self.launch_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
def test_new_patchset_dequeues_old_on_head(self):
|
|
"Test that a new patchset causes the old to be dequeued (at head)"
|
|
# D -> C (depends on B) -> B (depends on A) -> A -> M
|
|
self.launch_server.hold_jobs_in_build = True
|
|
M = self.fake_gerrit.addFakeChange('org/project', 'master', 'M')
|
|
M.setMerged()
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
|
|
D = self.fake_gerrit.addFakeChange('org/project', 'master', 'D')
|
|
A.addApproval('code-review', 2)
|
|
B.addApproval('code-review', 2)
|
|
C.addApproval('code-review', 2)
|
|
D.addApproval('code-review', 2)
|
|
|
|
C.setDependsOn(B, 1)
|
|
B.setDependsOn(A, 1)
|
|
A.setDependsOn(M, 1)
|
|
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(B.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(C.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(D.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
A.addPatchset()
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
|
|
self.waitUntilSettled()
|
|
|
|
self.launch_server.hold_jobs_in_build = False
|
|
self.launch_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertEqual(B.data['status'], 'NEW')
|
|
self.assertEqual(B.reported, 2)
|
|
self.assertEqual(C.data['status'], 'NEW')
|
|
self.assertEqual(C.reported, 2)
|
|
self.assertEqual(D.data['status'], 'MERGED')
|
|
self.assertEqual(D.reported, 2)
|
|
self.assertEqual(len(self.history), 7)
|
|
|
|
def test_new_patchset_dequeues_old_without_dependents(self):
|
|
"Test that a new patchset causes only the old to be dequeued"
|
|
self.launch_server.hold_jobs_in_build = True
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
|
|
A.addApproval('code-review', 2)
|
|
B.addApproval('code-review', 2)
|
|
C.addApproval('code-review', 2)
|
|
|
|
self.fake_gerrit.addEvent(C.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(B.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
B.addPatchset()
|
|
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
|
|
self.waitUntilSettled()
|
|
|
|
self.launch_server.hold_jobs_in_build = False
|
|
self.launch_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertEqual(B.data['status'], 'NEW')
|
|
self.assertEqual(B.reported, 2)
|
|
self.assertEqual(C.data['status'], 'MERGED')
|
|
self.assertEqual(C.reported, 2)
|
|
self.assertEqual(len(self.history), 9)
|
|
|
|
def test_new_patchset_dequeues_old_independent_queue(self):
|
|
"Test that a new patchset causes the old to be dequeued (independent)"
|
|
self.launch_server.hold_jobs_in_build = True
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
C = self.fake_gerrit.addFakeChange('org/project', 'master', 'C')
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
|
|
self.fake_gerrit.addEvent(C.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
B.addPatchset()
|
|
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(2))
|
|
self.waitUntilSettled()
|
|
|
|
self.launch_server.hold_jobs_in_build = False
|
|
self.launch_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'NEW')
|
|
self.assertEqual(A.reported, 1)
|
|
self.assertEqual(B.data['status'], 'NEW')
|
|
self.assertEqual(B.reported, 1)
|
|
self.assertEqual(C.data['status'], 'NEW')
|
|
self.assertEqual(C.reported, 1)
|
|
self.assertEqual(len(self.history), 10)
|
|
self.assertEqual(self.countJobResults(self.history, 'ABORTED'), 1)
|
|
|
|
def test_noop_job(self):
|
|
"Test that the internal noop job works"
|
|
A = self.fake_gerrit.addFakeChange('org/noop-project', 'master', 'A')
|
|
A.addApproval('code-review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(len(self.gearman_server.getQueue()), 0)
|
|
self.assertTrue(self.sched._areAllBuildsComplete())
|
|
self.assertEqual(len(self.history), 0)
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
|
|
def test_no_job_project(self):
|
|
"Test that reports with no jobs don't get sent"
|
|
A = self.fake_gerrit.addFakeChange('org/no-jobs-project',
|
|
'master', 'A')
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
# Change wasn't reported to
|
|
self.assertEqual(A.reported, False)
|
|
|
|
# Check queue is empty afterwards
|
|
tenant = self.sched.abide.tenants.get('tenant-one')
|
|
check_pipeline = tenant.layout.pipelines['check']
|
|
items = check_pipeline.getAllItems()
|
|
self.assertEqual(len(items), 0)
|
|
|
|
self.assertEqual(len(self.history), 0)
|
|
|
|
def test_zuul_refs(self):
|
|
"Test that zuul refs exist and have the right changes"
|
|
self.launch_server.hold_jobs_in_build = True
|
|
M1 = self.fake_gerrit.addFakeChange('org/project1', 'master', 'M1')
|
|
M1.setMerged()
|
|
M2 = self.fake_gerrit.addFakeChange('org/project2', 'master', 'M2')
|
|
M2.setMerged()
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
|
|
B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
|
|
C = self.fake_gerrit.addFakeChange('org/project2', 'master', 'C')
|
|
D = self.fake_gerrit.addFakeChange('org/project2', 'master', 'D')
|
|
A.addApproval('code-review', 2)
|
|
B.addApproval('code-review', 2)
|
|
C.addApproval('code-review', 2)
|
|
D.addApproval('code-review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(B.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(C.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(D.addApproval('approved', 1))
|
|
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
self.launch_server.release('.*-merge')
|
|
self.waitUntilSettled()
|
|
|
|
a_zref = b_zref = c_zref = d_zref = None
|
|
a_build = b_build = c_build = d_build = None
|
|
for x in self.builds:
|
|
if x.parameters['ZUUL_CHANGE'] == '3':
|
|
a_zref = x.parameters['ZUUL_REF']
|
|
a_build = x
|
|
elif x.parameters['ZUUL_CHANGE'] == '4':
|
|
b_zref = x.parameters['ZUUL_REF']
|
|
b_build = x
|
|
elif x.parameters['ZUUL_CHANGE'] == '5':
|
|
c_zref = x.parameters['ZUUL_REF']
|
|
c_build = x
|
|
elif x.parameters['ZUUL_CHANGE'] == '6':
|
|
d_zref = x.parameters['ZUUL_REF']
|
|
d_build = x
|
|
if a_build and b_build and c_build and d_build:
|
|
break
|
|
|
|
# There are... four... refs.
|
|
self.assertIsNotNone(a_zref)
|
|
self.assertIsNotNone(b_zref)
|
|
self.assertIsNotNone(c_zref)
|
|
self.assertIsNotNone(d_zref)
|
|
|
|
# And they should all be different
|
|
refs = set([a_zref, b_zref, c_zref, d_zref])
|
|
self.assertEqual(len(refs), 4)
|
|
|
|
# should have a, not b, and should not be in project2
|
|
self.assertTrue(a_build.hasChanges(A))
|
|
self.assertFalse(a_build.hasChanges(B, M2))
|
|
|
|
# should have a and b, and should not be in project2
|
|
self.assertTrue(b_build.hasChanges(A, B))
|
|
self.assertFalse(b_build.hasChanges(M2))
|
|
|
|
# should have a and b in 1, c in 2
|
|
self.assertTrue(c_build.hasChanges(A, B, C))
|
|
self.assertFalse(c_build.hasChanges(D))
|
|
|
|
# should have a and b in 1, c and d in 2
|
|
self.assertTrue(d_build.hasChanges(A, B, C, D))
|
|
|
|
self.launch_server.hold_jobs_in_build = False
|
|
self.launch_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertEqual(B.data['status'], 'MERGED')
|
|
self.assertEqual(B.reported, 2)
|
|
self.assertEqual(C.data['status'], 'MERGED')
|
|
self.assertEqual(C.reported, 2)
|
|
self.assertEqual(D.data['status'], 'MERGED')
|
|
self.assertEqual(D.reported, 2)
|
|
|
|
def test_rerun_on_error(self):
|
|
"Test that if a worker fails to run a job, it is run again"
|
|
self.launch_server.hold_jobs_in_build = True
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
A.addApproval('code-review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.builds[0].run_error = True
|
|
self.launch_server.hold_jobs_in_build = False
|
|
self.launch_server.release()
|
|
self.waitUntilSettled()
|
|
self.assertEqual(self.countJobResults(self.history, 'RUN_ERROR'), 1)
|
|
self.assertEqual(self.countJobResults(self.history, 'SUCCESS'), 3)
|
|
|
|
def test_statsd(self):
|
|
"Test each of the statsd methods used in the scheduler"
|
|
import extras
|
|
statsd = extras.try_import('statsd.statsd')
|
|
statsd.incr('test-incr')
|
|
statsd.timing('test-timing', 3)
|
|
statsd.gauge('test-gauge', 12)
|
|
self.assertReportedStat('test-incr', '1|c')
|
|
self.assertReportedStat('test-timing', '3|ms')
|
|
self.assertReportedStat('test-gauge', '12|g')
|
|
|
|
@skip("Disabled for early v3 development")
|
|
def test_stuck_job_cleanup(self):
|
|
"Test that pending jobs are cleaned up if removed from layout"
|
|
# This job won't be registered at startup because it is not in
|
|
# the standard layout, but we need it to already be registerd
|
|
# for when we reconfigure, as that is when Zuul will attempt
|
|
# to run the new job.
|
|
self.worker.registerFunction('build:gate-noop')
|
|
self.gearman_server.hold_jobs_in_queue = True
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
A.addApproval('code-review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.gearman_server.getQueue()), 1)
|
|
|
|
self.updateConfigLayout(
|
|
'tests/fixtures/layout-no-jobs.yaml')
|
|
self.sched.reconfigure(self.config)
|
|
self.waitUntilSettled()
|
|
|
|
self.gearman_server.release('gate-noop')
|
|
self.waitUntilSettled()
|
|
self.assertEqual(len(self.gearman_server.getQueue()), 0)
|
|
self.assertTrue(self.sched._areAllBuildsComplete())
|
|
|
|
self.assertEqual(len(self.history), 1)
|
|
self.assertEqual(self.history[0].name, 'gate-noop')
|
|
self.assertEqual(self.history[0].result, 'SUCCESS')
|
|
|
|
def test_file_head(self):
|
|
# This is a regression test for an observed bug. A change
|
|
# with a file named "HEAD" in the root directory of the repo
|
|
# was processed by a merger. It then was unable to reset the
|
|
# repo because of:
|
|
# GitCommandError: 'git reset --hard HEAD' returned
|
|
# with exit code 128
|
|
# stderr: 'fatal: ambiguous argument 'HEAD': both revision
|
|
# and filename
|
|
# Use '--' to separate filenames from revisions'
|
|
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
A.addPatchset({'HEAD': ''})
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
|
|
self.waitUntilSettled()
|
|
|
|
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
self.assertIn('Build succeeded', A.messages[0])
|
|
self.assertIn('Build succeeded', B.messages[0])
|
|
|
|
def test_file_jobs(self):
|
|
"Test that file jobs run only when appropriate"
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
A.addPatchset({'pip-requires': 'foo'})
|
|
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
|
A.addApproval('code-review', 2)
|
|
B.addApproval('code-review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.fake_gerrit.addEvent(B.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
testfile_jobs = [x for x in self.history
|
|
if x.name == 'project-testfile']
|
|
|
|
self.assertEqual(len(testfile_jobs), 1)
|
|
self.assertEqual(testfile_jobs[0].changes, '1,2')
|
|
self.assertEqual(A.data['status'], 'MERGED')
|
|
self.assertEqual(A.reported, 2)
|
|
self.assertEqual(B.data['status'], 'MERGED')
|
|
self.assertEqual(B.reported, 2)
|
|
|
|
def _test_irrelevant_files_jobs(self, should_skip):
|
|
"Test that jobs with irrelevant-files filter run only when appropriate"
|
|
self.updateConfigLayout('layout-irrelevant-files')
|
|
self.sched.reconfigure(self.config)
|
|
|
|
if should_skip:
|
|
files = {'ignoreme': 'ignored\n'}
|
|
else:
|
|
files = {'respectme': 'please!\n'}
|
|
|
|
change = self.fake_gerrit.addFakeChange('org/project',
|
|
'master',
|
|
'test irrelevant-files',
|
|
files=files)
|
|
self.fake_gerrit.addEvent(change.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
tested_change_ids = [x.changes[0] for x in self.history
|
|
if x.name == 'project-test-irrelevant-files']
|
|
|
|
if should_skip:
|
|
self.assertEqual([], tested_change_ids)
|
|
else:
|
|
self.assertIn(change.data['number'], tested_change_ids)
|
|
|
|
def test_irrelevant_files_match_skips_job(self):
|
|
self._test_irrelevant_files_jobs(should_skip=True)
|
|
|
|
def test_irrelevant_files_no_match_runs_job(self):
|
|
self._test_irrelevant_files_jobs(should_skip=False)
|
|
|
|
def test_inherited_jobs_keep_matchers(self):
|
|
self.updateConfigLayout('layout-inheritance')
|
|
self.sched.reconfigure(self.config)
|
|
|
|
files = {'ignoreme': 'ignored\n'}
|
|
|
|
change = self.fake_gerrit.addFakeChange('org/project',
|
|
'master',
|
|
'test irrelevant-files',
|
|
files=files)
|
|
self.fake_gerrit.addEvent(change.getPatchsetCreatedEvent(1))
|
|
self.waitUntilSettled()
|
|
|
|
run_jobs = set([build.name for build in self.history])
|
|
|
|
self.assertEqual(set(['project-test-nomatch-starts-empty',
|
|
'project-test-nomatch-starts-full']), run_jobs)
|
|
|
|
@skip("Disabled for early v3 development")
|
|
def test_test_config(self):
|
|
"Test that we can test the config"
|
|
self.sched.testConfig(self.config.get('zuul', 'tenant_config'),
|
|
self.connections)
|
|
|
|
@skip("Disabled for early v3 development")
|
|
def test_queue_names(self):
|
|
"Test shared change queue names"
|
|
project1 = self.sched.layout.projects['org/project1']
|
|
project2 = self.sched.layout.projects['org/project2']
|
|
q1 = self.sched.layout.pipelines['gate'].getQueue(project1)
|
|
q2 = self.sched.layout.pipelines['gate'].getQueue(project2)
|
|
self.assertEqual(q1.name, 'integration')
|
|
self.assertEqual(q2.name, 'integration')
|
|
|
|
self.updateConfigLayout(
|
|
'tests/fixtures/layout-bad-queue.yaml')
|
|
with testtools.ExpectedException(
|
|
Exception, "More than one name assigned to change queue"):
|
|
self.sched.reconfigure(self.config)
|
|
|
|
def test_queue_precedence(self):
|
|
"Test that queue precedence works"
|
|
|
|
self.gearman_server.hold_jobs_in_queue = True
|
|
self.launch_server.hold_jobs_in_build = True
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
|
A.addApproval('code-review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
|
|
self.waitUntilSettled()
|
|
self.gearman_server.hold_jobs_in_queue = False
|
|
self.gearman_server.release()
|
|
self.waitUntilSettled()
|
|
|
|
# Run one build at a time to ensure non-race order:
|
|
self.orderedRelease()
|
|
self.launch_server.hold_jobs_in_build = False
|
|
self.waitUntilSettled()
|
|
|
|
self.log.debug(self.history)
|
|
self.assertEqual(self.history[0].pipeline, 'gate')
|
|
self.assertEqual(self.history[1].pipeline, 'check')
|
|
self.assertEqual(self.history[2].pipeline, 'gate')
|
|
self.assertEqual(self.history[3].pipeline, 'gate')
|
|
self.assertEqual(self.history[4].pipeline, 'check')
|
|
self.assertEqual(self.history[5].pipeline, 'check')
|
|
|
|
@skip("Disabled for early v3 development")
|
|
def test_json_status(self):
|
|
"Test that we can retrieve JSON status info"
|
|
self.launch_server.hold_jobs_in_build = True
|
|
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
|
A.addApproval('code-review', 2)
|
|
self.fake_gerrit.addEvent(A.addApproval('approved', 1))
|
|
self.waitUntilSettled()
|
|
|
|
self.launch_server.release('project-merge')
|
|
self.waitUntilSettled()
|
|