mirror of
https://pagure.io/fm-orchestrator.git
synced 2026-02-03 05:03:43 +08:00
Add tests for 'continue' part of start_next_batch and component resubmit
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)?
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user