Add tests for 'continue' part of start_next_batch and component resubmit

This commit is contained in:
Jan Kaluza
2017-03-16 10:59:53 +01:00
parent c562cdfcf3
commit 830b1dd111
4 changed files with 128 additions and 20 deletions

View File

@@ -59,21 +59,6 @@ conf = init_config(app)
db = SQLAlchemy(app)
def get_url_for(*args, **kwargs):
"""
flask.url_for wrapper which creates the app_context on-the-fly.
"""
if has_app_context():
return url_for(*args, **kwargs)
# Localhost is right URL only when the scheduler runs on the same
# system as the web views.
app.config['SERVER_NAME'] = 'localhost'
with app.app_context():
return url_for(*args, **kwargs)
@app.errorhandler(ValidationError)
def validationerror_error(e):
"""Flask error handler for ValidationError exceptions"""
@@ -118,4 +103,20 @@ def notfound_error(e):
init_logging(conf)
log = getLogger(__name__)
def get_url_for(*args, **kwargs):
"""
flask.url_for wrapper which creates the app_context on-the-fly.
"""
if has_app_context():
return url_for(*args, **kwargs)
# Localhost is right URL only when the scheduler runs on the same
# system as the web views.
app.config['SERVER_NAME'] = 'localhost'
with app.app_context():
log.debug("WARNING: get_url_for() has been called without the Flask "
"app_context. That can lead to SQLAlchemy errors caused by "
"multiple session being used in the same time.")
return url_for(*args, **kwargs)
from module_build_service import views

View File

@@ -524,6 +524,8 @@ def format_mmd(mmd, scmurl):
raise UnprocessableEntity(err_msg)
def record_component_builds(scm, mmd, module, initial_batch = 1):
import koji # Placed here to avoid py2/py3 conflicts...
# Format the modulemd by putting in defaults and replacing streams that
# are branches with commit hashes
try:
@@ -574,10 +576,10 @@ def record_component_builds(scm, mmd, module, initial_batch = 1):
existing_build = models.ComponentBuild.query.filter_by(
module_id=module.id, package=pkg.name).first()
if existing_build and \
existing_build.state != models.BUILD_STATES['done']:
existing_build.state = models.BUILD_STATES['init']
db.session.add(existing_build)
if existing_build:
if existing_build.state != koji.BUILD_STATES['COMPLETE']:
existing_build.state = None
db.session.add(existing_build)
else:
# XXX: what about components that were present in previous
# builds but are gone now (component reduction)?

View File

@@ -33,6 +33,7 @@ from module_build_service.utils import get_scm_url_re
import module_build_service.pdc
app = module_build_service.app
app.config['SERVER_NAME'] = 'localhost'
conf = init_config(app)
def init_data():

View File

@@ -19,7 +19,8 @@
# SOFTWARE.
import unittest
from os import path
from os import path, mkdir
from shutil import copyfile
import vcr
import modulemd
from mock import patch
@@ -33,14 +34,46 @@ from mock import PropertyMock
import koji
import module_build_service.scheduler.handlers.components
from module_build_service.builder import GenericBuilder, KojiModuleBuilder
from tests import app
BASE_DIR = path.abspath(path.dirname(__file__))
CASSETTES_DIR = path.join(
path.abspath(path.dirname(__file__)), '..', 'vcr-request-data')
class MockedSCM(object):
def __init__(self, mocked_scm, name, mmd_filename, commit=None):
self.mocked_scm = mocked_scm
self.name = name
self.commit = commit
self.mmd_filename = mmd_filename
self.mocked_scm.return_value.checkout = self.checkout
self.mocked_scm.return_value.name = self.name
self.mocked_scm.return_value.branch = 'master'
self.mocked_scm.return_value.get_latest = self.get_latest
self.mocked_scm.return_value.commit = self.commit
self.mocked_scm.return_value.repository_root = "git://pkgs.stg.fedoraproject.org/modules/"
def checkout(self, temp_dir):
scm_dir = path.join(temp_dir, self.name)
mkdir(scm_dir)
base_dir = path.abspath(path.dirname(__file__))
copyfile(path.join(base_dir, '..', 'staged_data', self.mmd_filename),
path.join(scm_dir, self.name + ".yaml"))
return scm_dir
def get_latest(self, branch = 'master'):
return branch
class TestUtils(unittest.TestCase):
def setUp(self):
pass
def tearDown(self):
init_data()
@vcr.use_cassette(
path.join(CASSETTES_DIR, 'tests.test_utils.TestUtils.test_format_mmd'))
@patch('module_build_service.scm.SCM')
@@ -284,6 +317,40 @@ class TestUtils(unittest.TestCase):
self.assertTrue(str(cm.exception).endswith(' No value provided.'))
@patch('module_build_service.scm.SCM')
def test_resubmit(self, mocked_scm):
"""
Tests that the module resubmit reintializes the module state and
component states properly.
"""
MockedSCM(mocked_scm, 'testmodule', 'testmodule-bootstrap.yaml',
'620ec77321b2ea7b0d67d82992dda3e1d67055b4')
with app.app_context():
test_resuse_component_init_data()
# Mark the module build as failed, so we can resubmit it.
module_build = models.ModuleBuild.query.filter_by(id=2).one()
module_build.batch = 2
module_build.state = models.BUILD_STATES['failed']
module_build.version = 1
# Mark the components as COMPLETE/FAILED/CANCELED
components = module_build.component_builds
complete_component = components[0]
complete_component.state = koji.BUILD_STATES['COMPLETE']
failed_component = components[1]
failed_component.state = koji.BUILD_STATES['FAILED']
canceled_component = components[2]
canceled_component.state = koji.BUILD_STATES['CANCELED']
db.session.commit()
module_build_service.utils.submit_module_build_from_scm(
"Tom Brady", 'git://pkgs.stg.fedoraproject.org/modules/testmodule.git?#8fea453',
'master')
self.assertEqual(module_build.state, models.BUILD_STATES['wait'])
self.assertEqual(complete_component.state, koji.BUILD_STATES['COMPLETE'])
self.assertEqual(failed_component.state, None)
self.assertEqual(canceled_component.state, None)
class DummyModuleBuilder(GenericBuilder):
"""
@@ -360,6 +427,15 @@ class TestBatches(unittest.TestCase):
GenericBuilder.register_backend_class(KojiModuleBuilder)
def test_start_next_batch_build_reuse(self, default_buildroot_groups):
"""
Tests that start_next_batch_build:
1) Increments module.batch.
2) Can reuse all components in batch
3) Returns proper further_work messages for reused components.
4) Returns the fake Repo change message
5) Handling the further_work messages lead to proper tagging of
reused components.
"""
module_build = models.ModuleBuild.query.filter_by(id=2).one()
module_build.batch = 1
@@ -393,3 +469,31 @@ class TestBatches(unittest.TestCase):
# Check that packages have been tagged just once.
self.assertEqual(len(DummyModuleBuilder.TAGGED_COMPONENTS), 2)
def test_start_next_batch_continue(self, default_buildroot_groups):
"""
Tests that start_next_batch_build does not start new batch when
there are unbuilt components in the current one.
"""
module_build = models.ModuleBuild.query.filter_by(id=2).one()
module_build.batch = 2
# Mark the component as BUILDING.
building_component = module_build.current_batch()[0]
building_component.state = koji.BUILD_STATES['BUILDING']
db.session.commit()
builder = mock.MagicMock()
further_work = module_build_service.utils.start_next_batch_build(
conf, module_build, db.session, builder)
# Batch number should not increase.
self.assertEqual(module_build.batch, 2)
# Single component should be reused this time, second message is fake
# KojiRepoChange.
self.assertEqual(len(further_work), 2)
self.assertEqual(further_work[0].build_name, "perl-List-Compare")