Migrate to testrepository.

Needed to move some directory creation around to be contained within the
testcase, but with parallel testing, we shave 48 seconds off the run
time and go from around 60s to around 11. We're also now compatible with
future subunit-based fast-fail semantics when we grow them.

Change-Id: I6c7148c29d1edb5d9469a8c2afe4b31b2b340009
Reviewed-on: https://review.openstack.org/33352
Approved: James E. Blair <corvus@inaugust.com>
Reviewed-by: James E. Blair <corvus@inaugust.com>
Tested-by: Jenkins
This commit is contained in:
Monty Taylor 2013-06-17 17:22:42 -04:00 committed by Jenkins
parent 4998315d03
commit bc7588343f
7 changed files with 244 additions and 201 deletions

1
.gitignore vendored
View File

@ -2,6 +2,7 @@
*.egg-info *.egg-info
*.pyc *.pyc
.test .test
.testrepository
.tox .tox
AUTHORS AUTHORS
build/* build/*

4
.testr.conf Normal file
View File

@ -0,0 +1,4 @@
[DEFAULT]
test_command=OS_STDOUT_CAPTURE=1 OS_STDERR_CAPTURE=1 ${PYTHON:-python} -m subunit.run discover -t ./ tests $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=--list

View File

@ -28,10 +28,3 @@ console_scripts =
source-dir = doc/source source-dir = doc/source
build-dir = doc/build build-dir = doc/build
all_files = 1 all_files = 1
[nosetests]
verbosity=2
detailed-errors=1
cover-package = zuul
cover-html = true
cover-erase = true

View File

@ -1,7 +1,9 @@
hacking>=0.5.3,<0.6 hacking>=0.5.3,<0.6
coverage coverage
nose
nosehtmloutput
sphinx sphinx
docutils==0.9.1 docutils==0.9.1
fixtures>=0.3.12
python-subunit
testrepository>=0.0.13
testtools>=0.9.27

View File

@ -14,11 +14,12 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import unittest
import os import os
import re import re
import yaml
import testtools
import voluptuous import voluptuous
import yaml
import zuul.layoutvalidator import zuul.layoutvalidator
@ -27,7 +28,7 @@ FIXTURE_DIR = os.path.join(os.path.dirname(__file__),
LAYOUT_RE = re.compile(r'^(good|bad)_.*\.yaml$') LAYOUT_RE = re.compile(r'^(good|bad)_.*\.yaml$')
class testScheduler(unittest.TestCase): class testScheduler(testtools.TestCase):
def test_layouts(self): def test_layouts(self):
"""Test layout file validation""" """Test layout file validation"""
print print

View File

@ -14,28 +14,32 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import unittest
import ConfigParser import ConfigParser
import os from cStringIO import StringIO
import Queue
import hashlib import hashlib
import logging
import random
import json import json
import threading import logging
import time import os
import pprint import pprint
import Queue
import random
import re import re
import urllib2
import urlparse
import select import select
import statsd
import shutil import shutil
import socket import socket
import string import string
from cStringIO import StringIO import subprocess
import tempfile
import threading
import time
import urllib2
import urlparse
import git import git
import gear import gear
import fixtures
import statsd
import testtools
import zuul.scheduler import zuul.scheduler
import zuul.launcher.gearman import zuul.launcher.gearman
@ -49,18 +53,21 @@ CONFIG.read(os.path.join(FIXTURE_DIR, "zuul.conf"))
CONFIG.set('zuul', 'layout_config', CONFIG.set('zuul', 'layout_config',
os.path.join(FIXTURE_DIR, "layout.yaml")) os.path.join(FIXTURE_DIR, "layout.yaml"))
TMP_ROOT = os.environ.get("ZUUL_TEST_ROOT", "/tmp")
TEST_ROOT = os.path.join(TMP_ROOT, "zuul-test")
UPSTREAM_ROOT = os.path.join(TEST_ROOT, "upstream")
GIT_ROOT = os.path.join(TEST_ROOT, "git")
CONFIG.set('zuul', 'git_dir', GIT_ROOT)
logging.basicConfig(level=logging.DEBUG, logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(name)-32s ' format='%(asctime)s %(name)-32s '
'%(levelname)-8s %(message)s') '%(levelname)-8s %(message)s')
def repack_repo(path):
output = subprocess.Popen(
['git', '--git-dir=%s/.git' % path, 'repack', '-afd'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out = output.communicate()
if output.returncode:
raise Exception("git repack returned %d" % output.returncode)
return out
def random_sha1(): def random_sha1():
return hashlib.sha1(str(random.random())).hexdigest() return hashlib.sha1(str(random.random())).hexdigest()
@ -70,108 +77,13 @@ class ChangeReference(git.Reference):
_points_to_commits_only = True _points_to_commits_only = True
def init_repo(project):
parts = project.split('/')
path = os.path.join(UPSTREAM_ROOT, *parts[:-1])
if not os.path.exists(path):
os.makedirs(path)
path = os.path.join(UPSTREAM_ROOT, project)
repo = git.Repo.init(path)
repo.config_writer().set_value('user', 'email', 'user@example.com')
repo.config_writer().set_value('user', 'name', 'User Name')
repo.config_writer().write()
fn = os.path.join(path, 'README')
f = open(fn, 'w')
f.write("test\n")
f.close()
repo.index.add([fn])
repo.index.commit('initial commit')
master = repo.create_head('master')
repo.create_tag('init')
mp = repo.create_head('mp')
repo.head.reference = mp
f = open(fn, 'a')
f.write("test mp\n")
f.close()
repo.index.add([fn])
repo.index.commit('mp commit')
repo.head.reference = master
repo.head.reset(index=True, working_tree=True)
repo.git.clean('-x', '-f', '-d')
def add_fake_change_to_repo(project, branch, change_num, patchset, msg, fn,
large):
path = os.path.join(UPSTREAM_ROOT, project)
repo = git.Repo(path)
ref = ChangeReference.create(repo, '1/%s/%s' % (change_num,
patchset),
'refs/tags/init')
repo.head.reference = ref
repo.head.reset(index=True, working_tree=True)
repo.git.clean('-x', '-f', '-d')
path = os.path.join(UPSTREAM_ROOT, project)
if not large:
fn = os.path.join(path, fn)
f = open(fn, 'w')
f.write("test %s %s %s\n" % (branch, change_num, patchset))
f.close()
repo.index.add([fn])
else:
for fni in range(100):
fn = os.path.join(path, str(fni))
f = open(fn, 'w')
for ci in range(4096):
f.write(random.choice(string.printable))
f.close()
repo.index.add([fn])
return repo.index.commit(msg)
def ref_has_change(ref, change):
path = os.path.join(GIT_ROOT, change.project)
repo = git.Repo(path)
for commit in repo.iter_commits(ref):
if commit.message.strip() == ('%s-1' % change.subject):
return True
return False
def job_has_changes(*args):
job = args[0]
commits = args[1:]
if isinstance(job, FakeBuild):
parameters = job.parameters
else:
parameters = json.loads(job.arguments)
project = parameters['ZUUL_PROJECT']
path = os.path.join(GIT_ROOT, project)
repo = git.Repo(path)
ref = parameters['ZUUL_REF']
sha = parameters['ZUUL_COMMIT']
repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
repo_shas = [c.hexsha for c in repo.iter_commits(ref)]
commit_messages = ['%s-1' % commit.subject for commit in commits]
for msg in commit_messages:
if msg not in repo_messages:
return False
if repo_shas[0] != sha:
return False
return True
class FakeChange(object): class FakeChange(object):
categories = {'APRV': ('Approved', -1, 1), categories = {'APRV': ('Approved', -1, 1),
'CRVW': ('Code-Review', -2, 2), 'CRVW': ('Code-Review', -2, 2),
'VRFY': ('Verified', -2, 2)} 'VRFY': ('Verified', -2, 2)}
def __init__(self, gerrit, number, project, branch, subject, status='NEW'): def __init__(self, gerrit, number, project, branch, subject,
status='NEW', upstream_root=None):
self.gerrit = gerrit self.gerrit = gerrit
self.reported = 0 self.reported = 0
self.queried = 0 self.queried = 0
@ -204,9 +116,39 @@ class FakeChange(object):
'submitRecords': [], 'submitRecords': [],
'url': 'https://hostname/%s' % number} 'url': 'https://hostname/%s' % number}
self.upstream_root = upstream_root
self.addPatchset() self.addPatchset()
self.data['submitRecords'] = self.getSubmitRecords() self.data['submitRecords'] = self.getSubmitRecords()
def add_fake_change_to_repo(self, msg, fn, large):
path = os.path.join(self.upstream_root, self.project)
repo = git.Repo(path)
ref = ChangeReference.create(repo, '1/%s/%s' % (self.number,
self.latest_patchset),
'refs/tags/init')
repo.head.reference = ref
repo.head.reset(index=True, working_tree=True)
repo.git.clean('-x', '-f', '-d')
path = os.path.join(self.upstream_root, self.project)
if not large:
fn = os.path.join(path, fn)
f = open(fn, 'w')
f.write("test %s %s %s\n" %
(self.branch, self.number, self.latest_patchset))
f.close()
repo.index.add([fn])
else:
for fni in range(100):
fn = os.path.join(path, str(fni))
f = open(fn, 'w')
for ci in range(4096):
f.write(random.choice(string.printable))
f.close()
repo.index.add([fn])
return repo.index.commit(msg)
def addPatchset(self, files=[], large=False): def addPatchset(self, files=[], large=False):
self.latest_patchset += 1 self.latest_patchset += 1
if files: if files:
@ -214,9 +156,7 @@ class FakeChange(object):
else: else:
fn = '%s-%s' % (self.branch, self.number) fn = '%s-%s' % (self.branch, self.number)
msg = self.subject + '-' + str(self.latest_patchset) msg = self.subject + '-' + str(self.latest_patchset)
c = add_fake_change_to_repo(self.project, self.branch, c = self.add_fake_change_to_repo(msg, fn, large)
self.number, self.latest_patchset,
msg, fn, large)
ps_files = [{'file': '/COMMIT_MSG', ps_files = [{'file': '/COMMIT_MSG',
'type': 'ADDED'}, 'type': 'ADDED'},
{'file': 'README', {'file': 'README',
@ -360,7 +300,7 @@ class FakeChange(object):
self.data['status'] = 'MERGED' self.data['status'] = 'MERGED'
self.open = False self.open = False
path = os.path.join(UPSTREAM_ROOT, self.project) path = os.path.join(self.upstream_root, self.project)
repo = git.Repo(path) repo = git.Repo(path)
repo.heads[self.branch].commit = \ repo.heads[self.branch].commit = \
repo.commit(self.patchsets[-1]['revision']) repo.commit(self.patchsets[-1]['revision'])
@ -378,7 +318,8 @@ class FakeGerrit(object):
def addFakeChange(self, project, branch, subject): def addFakeChange(self, project, branch, subject):
self.change_number += 1 self.change_number += 1
c = FakeChange(self, self.change_number, project, branch, subject) c = FakeChange(self, self.change_number, project, branch, subject,
upstream_root=self.upstream_root)
self.changes[self.change_number] = c self.changes[self.change_number] = c
return c return c
@ -418,7 +359,8 @@ class BuildHistory(object):
class FakeURLOpener(object): class FakeURLOpener(object):
def __init__(self, fake_gerrit, url): def __init__(self, upstream_root, fake_gerrit, url):
self.upstream_root = upstream_root
self.fake_gerrit = fake_gerrit self.fake_gerrit = fake_gerrit
self.url = url self.url = url
@ -430,7 +372,7 @@ class FakeURLOpener(object):
ret += ('000000a31270149696713ba7e06f1beb760f20d359c4abed HEAD\x00' ret += ('000000a31270149696713ba7e06f1beb760f20d359c4abed HEAD\x00'
'multi_ack thin-pack side-band side-band-64k ofs-delta ' 'multi_ack thin-pack side-band side-band-64k ofs-delta '
'shallow no-progress include-tag multi_ack_detailed no-done\n') 'shallow no-progress include-tag multi_ack_detailed no-done\n')
path = os.path.join(UPSTREAM_ROOT, project) path = os.path.join(self.upstream_root, project)
repo = git.Repo(path) repo = git.Repo(path)
for ref in repo.refs: for ref in repo.refs:
r = ref.object.hexsha + ' ' + ref.path + '\n' r = ref.object.hexsha + ' ' + ref.path + '\n'
@ -440,8 +382,12 @@ class FakeURLOpener(object):
class FakeGerritTrigger(zuul.trigger.gerrit.Gerrit): class FakeGerritTrigger(zuul.trigger.gerrit.Gerrit):
def __init__(self, upstream_root, *args):
super(FakeGerritTrigger, self).__init__(*args)
self.upstream_root = upstream_root
def getGitUrl(self, project): def getGitUrl(self, project):
return os.path.join(UPSTREAM_ROOT, project.name) return os.path.join(self.upstream_root, project.name)
class FakeStatsd(threading.Thread): class FakeStatsd(threading.Thread):
@ -556,13 +502,14 @@ class FakeBuild(threading.Thread):
class FakeWorker(gear.Worker): class FakeWorker(gear.Worker):
def __init__(self, worker_id): def __init__(self, worker_id, test):
super(FakeWorker, self).__init__(worker_id) super(FakeWorker, self).__init__(worker_id)
self.gearman_jobs = {} self.gearman_jobs = {}
self.build_history = [] self.build_history = []
self.running_builds = [] self.running_builds = []
self.build_counter = 0 self.build_counter = 0
self.fail_tests = {} self.fail_tests = {}
self.test = test
self.hold_jobs_in_build = False self.hold_jobs_in_build = False
self.lock = threading.Lock() self.lock = threading.Lock()
@ -643,7 +590,7 @@ class FakeWorker(gear.Worker):
def shouldFailTest(self, name, ref): def shouldFailTest(self, name, ref):
l = self.fail_tests.get(name, []) l = self.fail_tests.get(name, [])
for change in l: for change in l:
if ref_has_change(ref, change): if self.test.ref_has_change(ref, change):
return True return True
return False return False
@ -710,25 +657,52 @@ class FakeGearmanServer(gear.Server):
self.log.debug("done releasing queued jobs %s (%s)" % (regex, qlen)) self.log.debug("done releasing queued jobs %s (%s)" % (regex, qlen))
class testScheduler(unittest.TestCase): class TestScheduler(testtools.TestCase):
log = logging.getLogger("zuul.test") log = logging.getLogger("zuul.test")
def setUp(self): def setUp(self):
if os.path.exists(TEST_ROOT): super(TestScheduler, self).setUp()
shutil.rmtree(TEST_ROOT) test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
os.makedirs(TEST_ROOT) try:
os.makedirs(UPSTREAM_ROOT) test_timeout = int(test_timeout)
os.makedirs(GIT_ROOT) except ValueError:
# If timeout value is invalid do not set a timeout.
test_timeout = 0
if test_timeout > 0:
self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or
os.environ.get('OS_STDOUT_CAPTURE') == '1'):
stdout = self.useFixture(fixtures.StringStream('stdout')).stream
self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or
os.environ.get('OS_STDERR_CAPTURE') == '1'):
stderr = self.useFixture(fixtures.StringStream('stderr')).stream
self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
self.useFixture(fixtures.NestedTempfile())
self.log_fixture = self.useFixture(fixtures.FakeLogger())
tmp_root = os.environ.get("ZUUL_TEST_ROOT", tempfile.mkdtemp())
self.test_root = os.path.join(tmp_root, "zuul-test")
self.upstream_root = os.path.join(self.test_root, "upstream")
self.git_root = os.path.join(self.test_root, "git")
CONFIG.set('zuul', 'git_dir', self.git_root)
if os.path.exists(self.test_root):
shutil.rmtree(self.test_root)
os.makedirs(self.test_root)
os.makedirs(self.upstream_root)
os.makedirs(self.git_root)
# For each project in config: # For each project in config:
init_repo("org/project") self.init_repo("org/project")
init_repo("org/project1") self.init_repo("org/project1")
init_repo("org/project2") self.init_repo("org/project2")
init_repo("org/project3") self.init_repo("org/project3")
init_repo("org/one-job-project") self.init_repo("org/one-job-project")
init_repo("org/nonvoting-project") self.init_repo("org/nonvoting-project")
init_repo("org/templated-project") self.init_repo("org/templated-project")
init_repo("org/node-project") self.init_repo("org/node-project")
self.statsd = FakeStatsd() self.statsd = FakeStatsd()
os.environ['STATSD_HOST'] = 'localhost' os.environ['STATSD_HOST'] = 'localhost'
@ -747,7 +721,7 @@ class testScheduler(unittest.TestCase):
self.config.readfp(cfg) self.config.readfp(cfg)
self.config.set('gearman', 'port', str(self.gearman_server.port)) self.config.set('gearman', 'port', str(self.gearman_server.port))
self.worker = FakeWorker('fake_worker') self.worker = FakeWorker('fake_worker', self)
self.worker.addServer('127.0.0.1', self.gearman_server.port) self.worker.addServer('127.0.0.1', self.gearman_server.port)
self.gearman_server.worker = self.worker self.gearman_server.worker = self.worker
@ -755,17 +729,19 @@ class testScheduler(unittest.TestCase):
def URLOpenerFactory(*args, **kw): def URLOpenerFactory(*args, **kw):
args = [self.fake_gerrit] + list(args) args = [self.fake_gerrit] + list(args)
return FakeURLOpener(*args, **kw) return FakeURLOpener(self.upstream_root, *args, **kw)
urllib2.urlopen = URLOpenerFactory urllib2.urlopen = URLOpenerFactory
self.launcher = zuul.launcher.gearman.Gearman(self.config, self.sched) self.launcher = zuul.launcher.gearman.Gearman(self.config, self.sched)
zuul.lib.gerrit.Gerrit = FakeGerrit zuul.lib.gerrit.Gerrit = FakeGerrit
self.gerrit = FakeGerritTrigger(self.config, self.sched) self.gerrit = FakeGerritTrigger(
self.upstream_root, self.config, self.sched)
self.gerrit.replication_timeout = 1.5 self.gerrit.replication_timeout = 1.5
self.gerrit.replication_retry_interval = 0.5 self.gerrit.replication_retry_interval = 0.5
self.fake_gerrit = self.gerrit.gerrit self.fake_gerrit = self.gerrit.gerrit
self.fake_gerrit.upstream_root = self.upstream_root
self.sched.setLauncher(self.launcher) self.sched.setLauncher(self.launcher)
self.sched.setTrigger(self.gerrit) self.sched.setTrigger(self.gerrit)
@ -790,7 +766,70 @@ class testScheduler(unittest.TestCase):
threads = threading.enumerate() threads = threading.enumerate()
if len(threads) > 1: if len(threads) > 1:
self.log.error("More than one thread is running: %s" % threads) self.log.error("More than one thread is running: %s" % threads)
#shutil.rmtree(TEST_ROOT) super(TestScheduler, self).tearDown()
def init_repo(self, project):
parts = project.split('/')
path = os.path.join(self.upstream_root, *parts[:-1])
if not os.path.exists(path):
os.makedirs(path)
path = os.path.join(self.upstream_root, project)
repo = git.Repo.init(path)
repo.config_writer().set_value('user', 'email', 'user@example.com')
repo.config_writer().set_value('user', 'name', 'User Name')
repo.config_writer().write()
fn = os.path.join(path, 'README')
f = open(fn, 'w')
f.write("test\n")
f.close()
repo.index.add([fn])
repo.index.commit('initial commit')
master = repo.create_head('master')
repo.create_tag('init')
mp = repo.create_head('mp')
repo.head.reference = mp
f = open(fn, 'a')
f.write("test mp\n")
f.close()
repo.index.add([fn])
repo.index.commit('mp commit')
repo.head.reference = master
repo.head.reset(index=True, working_tree=True)
repo.git.clean('-x', '-f', '-d')
def ref_has_change(self, ref, change):
path = os.path.join(self.git_root, change.project)
repo = git.Repo(path)
for commit in repo.iter_commits(ref):
if commit.message.strip() == ('%s-1' % change.subject):
return True
return False
def job_has_changes(self, *args):
job = args[0]
commits = args[1:]
if isinstance(job, FakeBuild):
parameters = job.parameters
else:
parameters = json.loads(job.arguments)
project = parameters['ZUUL_PROJECT']
path = os.path.join(self.git_root, project)
repo = git.Repo(path)
ref = parameters['ZUUL_REF']
sha = parameters['ZUUL_COMMIT']
repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
repo_shas = [c.hexsha for c in repo.iter_commits(ref)]
commit_messages = ['%s-1' % commit.subject for commit in commits]
for msg in commit_messages:
if msg not in repo_messages:
return False
if repo_shas[0] != sha:
return False
return True
def registerJobs(self): def registerJobs(self):
count = 0 count = 0
@ -1032,51 +1071,51 @@ class testScheduler(unittest.TestCase):
self.waitUntilSettled() self.waitUntilSettled()
assert len(self.builds) == 1 assert len(self.builds) == 1
assert self.builds[0].name == 'project-merge' assert self.builds[0].name == 'project-merge'
assert job_has_changes(self.builds[0], A) assert self.job_has_changes(self.builds[0], A)
self.worker.release('.*-merge') self.worker.release('.*-merge')
self.waitUntilSettled() self.waitUntilSettled()
assert len(self.builds) == 3 assert len(self.builds) == 3
assert self.builds[0].name == 'project-test1' assert self.builds[0].name == 'project-test1'
assert job_has_changes(self.builds[0], A) assert self.job_has_changes(self.builds[0], A)
assert self.builds[1].name == 'project-test2' assert self.builds[1].name == 'project-test2'
assert job_has_changes(self.builds[1], A) assert self.job_has_changes(self.builds[1], A)
assert self.builds[2].name == 'project-merge' assert self.builds[2].name == 'project-merge'
assert job_has_changes(self.builds[2], A, B) assert self.job_has_changes(self.builds[2], A, B)
self.worker.release('.*-merge') self.worker.release('.*-merge')
self.waitUntilSettled() self.waitUntilSettled()
assert len(self.builds) == 5 assert len(self.builds) == 5
assert self.builds[0].name == 'project-test1' assert self.builds[0].name == 'project-test1'
assert job_has_changes(self.builds[0], A) assert self.job_has_changes(self.builds[0], A)
assert self.builds[1].name == 'project-test2' assert self.builds[1].name == 'project-test2'
assert job_has_changes(self.builds[1], A) assert self.job_has_changes(self.builds[1], A)
assert self.builds[2].name == 'project-test1' assert self.builds[2].name == 'project-test1'
assert job_has_changes(self.builds[2], A, B) assert self.job_has_changes(self.builds[2], A, B)
assert self.builds[3].name == 'project-test2' assert self.builds[3].name == 'project-test2'
assert job_has_changes(self.builds[3], A, B) assert self.job_has_changes(self.builds[3], A, B)
assert self.builds[4].name == 'project-merge' assert self.builds[4].name == 'project-merge'
assert job_has_changes(self.builds[4], A, B, C) assert self.job_has_changes(self.builds[4], A, B, C)
self.worker.release('.*-merge') self.worker.release('.*-merge')
self.waitUntilSettled() self.waitUntilSettled()
assert len(self.builds) == 6 assert len(self.builds) == 6
assert self.builds[0].name == 'project-test1' assert self.builds[0].name == 'project-test1'
assert job_has_changes(self.builds[0], A) assert self.job_has_changes(self.builds[0], A)
assert self.builds[1].name == 'project-test2' assert self.builds[1].name == 'project-test2'
assert job_has_changes(self.builds[1], A) assert self.job_has_changes(self.builds[1], A)
assert self.builds[2].name == 'project-test1' assert self.builds[2].name == 'project-test1'
assert job_has_changes(self.builds[2], A, B) assert self.job_has_changes(self.builds[2], A, B)
assert self.builds[3].name == 'project-test2' assert self.builds[3].name == 'project-test2'
assert job_has_changes(self.builds[3], A, B) assert self.job_has_changes(self.builds[3], A, B)
assert self.builds[4].name == 'project-test1' assert self.builds[4].name == 'project-test1'
assert job_has_changes(self.builds[4], A, B, C) assert self.job_has_changes(self.builds[4], A, B, C)
assert self.builds[5].name == 'project-test2' assert self.builds[5].name == 'project-test2'
assert job_has_changes(self.builds[5], A, B, C) assert self.job_has_changes(self.builds[5], A, B, C)
self.worker.hold_jobs_in_build = False self.worker.hold_jobs_in_build = False
self.worker.release() self.worker.release()
@ -1133,9 +1172,9 @@ class testScheduler(unittest.TestCase):
# There should be one merge job at the head of each queue running # There should be one merge job at the head of each queue running
assert len(self.builds) == 2 assert len(self.builds) == 2
assert self.builds[0].name == 'project-merge' assert self.builds[0].name == 'project-merge'
assert job_has_changes(self.builds[0], A) assert self.job_has_changes(self.builds[0], A)
assert self.builds[1].name == 'project1-merge' assert self.builds[1].name == 'project1-merge'
assert job_has_changes(self.builds[1], B) assert self.job_has_changes(self.builds[1], B)
# Release the current merge builds # Release the current merge builds
self.worker.release('.*-merge') self.worker.release('.*-merge')
@ -1182,7 +1221,7 @@ class testScheduler(unittest.TestCase):
assert len(self.builds) == 1 assert len(self.builds) == 1
assert self.builds[0].name == 'project-merge' assert self.builds[0].name == 'project-merge'
assert job_has_changes(self.builds[0], A) assert self.job_has_changes(self.builds[0], A)
self.worker.release('.*-merge') self.worker.release('.*-merge')
self.waitUntilSettled() self.waitUntilSettled()
@ -1241,7 +1280,7 @@ class testScheduler(unittest.TestCase):
assert len(self.builds) == 0 assert len(self.builds) == 0
assert len(queue) == 1 assert len(queue) == 1
assert queue[0].name == 'build:project-merge' assert queue[0].name == 'build:project-merge'
assert job_has_changes(queue[0], A) assert self.job_has_changes(queue[0], A)
self.gearman_server.release('.*-merge') self.gearman_server.release('.*-merge')
self.waitUntilSettled() self.waitUntilSettled()
@ -1371,7 +1410,7 @@ class testScheduler(unittest.TestCase):
self.gearman_server.release() self.gearman_server.release()
self.waitUntilSettled() self.waitUntilSettled()
path = os.path.join(GIT_ROOT, "org/project") path = os.path.join(self.git_root, "org/project")
repo = git.Repo(path) repo = git.Repo(path)
repo_messages = [c.message.strip() for c in repo.iter_commits(ref)] repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
repo_messages.reverse() repo_messages.reverse()
@ -1466,7 +1505,7 @@ class testScheduler(unittest.TestCase):
self.gearman_server.release() self.gearman_server.release()
self.waitUntilSettled() self.waitUntilSettled()
path = os.path.join(GIT_ROOT, "org/project") path = os.path.join(self.git_root, "org/project")
repo = git.Repo(path) repo = git.Repo(path)
repo_messages = [c.message.strip() for c in repo.iter_commits(ref)] repo_messages = [c.message.strip() for c in repo.iter_commits(ref)]
repo_messages.reverse() repo_messages.reverse()
@ -1479,7 +1518,7 @@ class testScheduler(unittest.TestCase):
self.test_build_configuration() self.test_build_configuration()
self.test_build_configuration_branch() self.test_build_configuration_branch()
# C has been merged, undo that # C has been merged, undo that
path = os.path.join(UPSTREAM_ROOT, "org/project") path = os.path.join(self.upstream_root, "org/project")
repo = git.Repo(path) repo = git.Repo(path)
repo.heads.master.commit = repo.commit('init') repo.heads.master.commit = repo.commit('init')
self.test_build_configuration() self.test_build_configuration()
@ -1514,7 +1553,7 @@ class testScheduler(unittest.TestCase):
self.gearman_server.release() self.gearman_server.release()
self.waitUntilSettled() self.waitUntilSettled()
path = os.path.join(GIT_ROOT, "org/project") path = os.path.join(self.git_root, "org/project")
repo = git.Repo(path) repo = git.Repo(path)
repo_messages = [c.message.strip() repo_messages = [c.message.strip()
@ -1620,7 +1659,7 @@ class testScheduler(unittest.TestCase):
assert len(self.builds) == 1 assert len(self.builds) == 1
assert self.builds[0].name == 'project1-merge' assert self.builds[0].name == 'project1-merge'
assert job_has_changes(self.builds[0], A) assert self.job_has_changes(self.builds[0], A)
self.worker.release('.*-merge') self.worker.release('.*-merge')
self.waitUntilSettled() self.waitUntilSettled()
@ -1815,8 +1854,8 @@ class testScheduler(unittest.TestCase):
self.assertEmptyQueues() self.assertEmptyQueues()
self.worker.build_history = [] self.worker.build_history = []
path = os.path.join(GIT_ROOT, "org/project") path = os.path.join(self.git_root, "org/project")
os.system('git --git-dir=%s/.git repack -afd' % path) print repack_repo(path)
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A') A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
A.addApproval('CRVW', 2) A.addApproval('CRVW', 2)
@ -1834,10 +1873,10 @@ class testScheduler(unittest.TestCase):
# https://bugs.launchpad.net/zuul/+bug/1078946 # https://bugs.launchpad.net/zuul/+bug/1078946
A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A') A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A')
A.addPatchset(large=True) A.addPatchset(large=True)
path = os.path.join(UPSTREAM_ROOT, "org/project1") path = os.path.join(self.upstream_root, "org/project1")
os.system('git --git-dir=%s/.git repack -afd' % path) print repack_repo(path)
path = os.path.join(GIT_ROOT, "org/project1") path = os.path.join(self.git_root, "org/project1")
os.system('git --git-dir=%s/.git repack -afd' % path) print repack_repo(path)
A.addApproval('CRVW', 2) A.addApproval('CRVW', 2)
self.fake_gerrit.addEvent(A.addApproval('APRV', 1)) self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
@ -2107,26 +2146,26 @@ class testScheduler(unittest.TestCase):
assert len(refs) == 4 assert len(refs) == 4
# a ref should have a, not b, and should not be in project2 # a ref should have a, not b, and should not be in project2
assert ref_has_change(a_zref, A) assert self.ref_has_change(a_zref, A)
assert not ref_has_change(a_zref, B) assert not self.ref_has_change(a_zref, B)
assert not ref_has_change(a_zref, M2) assert not self.ref_has_change(a_zref, M2)
# b ref should have a and b, and should not be in project2 # b ref should have a and b, and should not be in project2
assert ref_has_change(b_zref, A) assert self.ref_has_change(b_zref, A)
assert ref_has_change(b_zref, B) assert self.ref_has_change(b_zref, B)
assert not ref_has_change(b_zref, M2) assert not self.ref_has_change(b_zref, M2)
# c ref should have a and b in 1, c in 2 # c ref should have a and b in 1, c in 2
assert ref_has_change(c_zref, A) assert self.ref_has_change(c_zref, A)
assert ref_has_change(c_zref, B) assert self.ref_has_change(c_zref, B)
assert ref_has_change(c_zref, C) assert self.ref_has_change(c_zref, C)
assert not ref_has_change(c_zref, D) assert not self.ref_has_change(c_zref, D)
# d ref should have a and b in 1, c and d in 2 # d ref should have a and b in 1, c and d in 2
assert ref_has_change(d_zref, A) assert self.ref_has_change(d_zref, A)
assert ref_has_change(d_zref, B) assert self.ref_has_change(d_zref, B)
assert ref_has_change(d_zref, C) assert self.ref_has_change(d_zref, C)
assert ref_has_change(d_zref, D) assert self.ref_has_change(d_zref, D)
self.worker.hold_jobs_in_build = False self.worker.hold_jobs_in_build = False
self.worker.release() self.worker.release()

View File

@ -5,9 +5,11 @@ envlist = pep8, pyflakes, py27
# Set STATSD env variables so that statsd code paths are tested. # Set STATSD env variables so that statsd code paths are tested.
setenv = STATSD_HOST=localhost setenv = STATSD_HOST=localhost
STATSD_PORT=8125 STATSD_PORT=8125
VIRTUAL_ENV={envdir}
deps = -r{toxinidir}/requirements.txt deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt -r{toxinidir}/test-requirements.txt
commands = nosetests --logging-format="%(asctime)s %(name)-32s %(levelname)-8s %(message)s" {posargs} commands =
python setup.py testr --slowest --testr-args='{posargs}'
[tox:jenkins] [tox:jenkins]
downloadcache = ~/cache/pip downloadcache = ~/cache/pip
@ -16,7 +18,8 @@ downloadcache = ~/cache/pip
commands = flake8 commands = flake8
[testenv:cover] [testenv:cover]
setenv = NOSE_WITH_COVERAGE=1 commands =
python setup.py testr --coverage
[testenv:pyflakes] [testenv:pyflakes]
deps = pyflakes deps = pyflakes