Esempio n. 1
0
def test_build_configuration_pinning(storage):
    config = dedent("""\
    jobs:
        - id: job-1
          function: jobcontrol.utils.testing:testing_job
          kwargs:
              retval: "original-retval"
    """)
    config = JobControlConfig.from_string(config)
    jc = JobControl(storage=storage, config=config)

    # ------------------------------------------------------------
    # Create a build with old configuration
    # ------------------------------------------------------------

    job = jc.get_job('job-1')
    build = job.create_build()
    build.run()
    build.refresh()
    assert build['finished'] and build['success']
    assert build['retval'] == 'original-retval'

    build = job.create_build()
    build_id = build.id  # Then stop using this object

    # ------------------------------------------------------------
    # Update the configuration
    # ------------------------------------------------------------

    config = dedent("""\
    jobs:
        - id: job-1
          function: jobcontrol.utils.testing:testing_job
          kwargs:
              retval: "new-retval"
    """)
    config = JobControlConfig.from_string(config)
    jc = JobControl(storage=storage, config=config)

    # ------------------------------------------------------------
    # Running that build will return the original return value

    build = jc.get_build(build_id)
    build.run()
    build.refresh()
    assert build['finished'] and build['success']
    assert build['retval'] == 'original-retval'

    # ------------------------------------------------------------
    # A freshly created build will return the new return value

    job = jc.get_job('job-1')
    build = job.create_build()
    build.run()
    build.refresh()
    assert build['finished'] and build['success']
    assert build['retval'] == 'new-retval'

    build = job.create_build()
    build_id = build.id  # Then stop using this object
Esempio n. 2
0
def test_build_configuration_pinning(storage):
    config = dedent("""\
    jobs:
        - id: job-1
          function: jobcontrol.utils.testing:testing_job
          kwargs:
              retval: "original-retval"
    """)
    config = JobControlConfig.from_string(config)
    jc = JobControl(storage=storage, config=config)

    # ------------------------------------------------------------
    # Create a build with old configuration
    # ------------------------------------------------------------

    job = jc.get_job('job-1')
    build = job.create_build()
    build.run()
    build.refresh()
    assert build['finished'] and build['success']
    assert build['retval'] == 'original-retval'

    build = job.create_build()
    build_id = build.id  # Then stop using this object

    # ------------------------------------------------------------
    # Update the configuration
    # ------------------------------------------------------------

    config = dedent("""\
    jobs:
        - id: job-1
          function: jobcontrol.utils.testing:testing_job
          kwargs:
              retval: "new-retval"
    """)
    config = JobControlConfig.from_string(config)
    jc = JobControl(storage=storage, config=config)

    # ------------------------------------------------------------
    # Running that build will return the original return value

    build = jc.get_build(build_id)
    build.run()
    build.refresh()
    assert build['finished'] and build['success']
    assert build['retval'] == 'original-retval'

    # ------------------------------------------------------------
    # A freshly created build will return the new return value

    job = jc.get_job('job-1')
    build = job.create_build()
    build.run()
    build.refresh()
    assert build['finished'] and build['success']
    assert build['retval'] == 'new-retval'

    build = job.create_build()
    build_id = build.id  # Then stop using this object
Esempio n. 3
0
def test_build_failure_nonserializable_exception(storage):
    """
    It only gets worse when we cannot even serialize the exception..
    But still, we can wrap it in a serialization error exception
    and be fine with it. Hopefully, we can keep the original traceback..
    """

    config = JobControlConfig.from_string("""
    jobs:
        - id: job-nse
          function: jobcontrol.utils.testing:job_raising_nonserializable
    """)
    jc = JobControl(storage=storage, config=config)

    # Run build for RAISE nonserializable
    # It should just fail with an exception in the post-run serialization
    # todo: We might even check the traceback for that..

    job = jc.get_job('job-nse')
    build = job.create_build()
    build.run()

    assert build['started']
    assert build['finished']
    assert not build['success']

    # WARNING! How to tell whether this job failed due to
    # the raised exception being serialized properly, or due
    # to the exception serialization failed?

    assert not isinstance(build['exception'], NonSerializableException)
    assert isinstance(build['exception'], ExceptionPlaceholder)
Esempio n. 4
0
def test_build_with_failure(storage):
    config = JobControlConfig.from_string("""
    jobs:
        - id: foo
          function: jobcontrol.utils.testing:testing_job
          kwargs:
              retval: "Foo Retval"
              fail: True
    """)
    jc = JobControl(storage=storage, config=config)

    job = jc.get_job('foo')
    build = job.create_build()
    build.run()

    assert build['started']
    assert build['finished']
    assert not build['success']
    assert not build['skipped']

    assert job.has_builds()
    assert not job.has_successful_builds()
    assert not job.has_running_builds()
    assert list(job.iter_builds()) == [build]
    assert list(job.iter_builds(success=True)) == []
    assert list(job.iter_builds(success=False)) == [build]

    assert isinstance(build['exception'], RuntimeError)
    assert isinstance(build['exception_tb'], TracebackInfo)
Esempio n. 5
0
def test_build_with_skip(storage):
    config = JobControlConfig.from_string("""
    jobs:
        - id: job-to-skip
          function: jobcontrol.utils.testing:testing_job
          kwargs:
              retval: "Foo Retval"
              skip: True
    """)
    jc = JobControl(storage=storage, config=config)

    job = jc.get_job('job-to-skip')
    build = job.create_build()
    build.run()

    assert build['started']
    assert build['finished']
    assert build['skipped']

    assert job.has_builds()
    assert not job.has_successful_builds()  # Skipped builds are ignored
    assert not job.has_running_builds()
    assert list(job.iter_builds()) == [build]
    assert list(job.iter_builds(skipped=False)) == []

    assert build['exception'] is None
    assert build['exception_tb'] is None
Esempio n. 6
0
def test_build_with_failure(storage):
    config = JobControlConfig.from_string("""
    jobs:
        - id: foo
          function: jobcontrol.utils.testing:testing_job
          kwargs:
              retval: "Foo Retval"
              fail: True
    """)
    jc = JobControl(storage=storage, config=config)

    job = jc.get_job('foo')
    build = job.create_build()
    build.run()

    assert build['started']
    assert build['finished']
    assert not build['success']
    assert not build['skipped']

    assert job.has_builds()
    assert not job.has_successful_builds()
    assert not job.has_running_builds()
    assert list(job.iter_builds()) == [build]
    assert list(job.iter_builds(success=True)) == []
    assert list(job.iter_builds(success=False)) == [build]

    assert isinstance(build['exception'], RuntimeError)
    assert isinstance(build['exception_tb'], TracebackInfo)
Esempio n. 7
0
def test_build_deletion(storage):
    func = 'jobcontrol.utils.testing:testing_job'

    config = {
        'jobs': [
            {'id': 'job-1', 'function': func},
        ]
    }

    jc = JobControl(storage=storage, config=config)

    job = jc.get_job('job-1')

    build_1 = job.create_build()
    build_1.run()

    assert len(list(job.iter_builds())) == 1

    build_2 = job.create_build()
    build_2.run()

    assert len(list(job.iter_builds())) == 2

    build_1.delete()

    assert len(list(job.iter_builds())) == 1
Esempio n. 8
0
def test_build_logging(storage):
    config = {
        'jobs': [
            {'id': 'job-with-logging',
             'function': 'jobcontrol.utils.testing:job_with_logging'},
        ]
    }

    jc = JobControl(storage=storage, config=config)
    job = jc.get_job('job-with-logging')

    build = job.create_build()
    build.run()
    build.refresh()

    assert build['finished'] and build['success']

    log_messages = build.iter_log_messages()
    messages_from_job = [
        msg for msg in log_messages
        if msg.name == 'jobcontrol.utils.testing.job_with_logging']

    assert len(messages_from_job) == 6

    assert messages_from_job[0].levelno == logging.DEBUG
    assert messages_from_job[0].message == 'This is a debug message'

    assert messages_from_job[0].args == ()
    assert isinstance(messages_from_job[0].created, datetime)
    assert messages_from_job[0].filename == 'testing.py'
    assert messages_from_job[0].function == 'job_with_logging'
    assert messages_from_job[0].level_name == 'DEBUG'
    assert messages_from_job[0].level == logging.DEBUG
    assert isinstance(messages_from_job[0].lineno, int)
    assert messages_from_job[0].module == 'testing'
    assert messages_from_job[0].message == 'This is a debug message'
    assert messages_from_job[0].msg == 'This is a debug message'
    assert messages_from_job[0].name == 'jobcontrol.utils.testing.job_with_logging'  # noqa
    assert isinstance(messages_from_job[0].pathname, basestring)
    assert messages_from_job[0].pathname.endswith('jobcontrol/utils/testing.py')  # noqa

    assert messages_from_job[0].exception is None
    assert messages_from_job[0].exception_tb is None

    assert messages_from_job[1].levelno == logging.INFO
    assert messages_from_job[1].message == 'This is an info message'

    assert messages_from_job[2].levelno == logging.WARNING
    assert messages_from_job[2].message == 'This is a warning message'

    assert messages_from_job[3].levelno == logging.ERROR
    assert messages_from_job[3].message == 'This is an error message'

    assert messages_from_job[4].levelno == logging.CRITICAL
    assert messages_from_job[4].message == 'This is a critical message'

    assert messages_from_job[5].levelno == logging.ERROR
    assert messages_from_job[5].message == 'This is an exception message'
    assert isinstance(messages_from_job[5].exception, ValueError)
    assert isinstance(messages_from_job[5].exception_tb, TracebackInfo)
Esempio n. 9
0
def test_build_deletion(storage):
    func = 'jobcontrol.utils.testing:testing_job'

    config = {
        'jobs': [
            {
                'id': 'job-1',
                'function': func
            },
        ]
    }

    jc = JobControl(storage=storage, config=config)

    job = jc.get_job('job-1')

    build_1 = job.create_build()
    build_1.run()

    assert len(list(job.iter_builds())) == 1

    build_2 = job.create_build()
    build_2.run()

    assert len(list(job.iter_builds())) == 2

    build_1.delete()

    assert len(list(job.iter_builds())) == 1
Esempio n. 10
0
def test_build_failure_nonserializable_exception(storage):
    """
    It only gets worse when we cannot even serialize the exception..
    But still, we can wrap it in a serialization error exception
    and be fine with it. Hopefully, we can keep the original traceback..
    """

    config = JobControlConfig.from_string("""
    jobs:
        - id: job-nse
          function: jobcontrol.utils.testing:job_raising_nonserializable
    """)
    jc = JobControl(storage=storage, config=config)

    # Run build for RAISE nonserializable
    # It should just fail with an exception in the post-run serialization
    # todo: We might even check the traceback for that..

    job = jc.get_job('job-nse')
    build = job.create_build()
    build.run()

    assert build['started']
    assert build['finished']
    assert not build['success']

    # WARNING! How to tell whether this job failed due to
    # the raised exception being serialized properly, or due
    # to the exception serialization failed?

    assert not isinstance(build['exception'], NonSerializableException)
    assert isinstance(build['exception'], ExceptionPlaceholder)
Esempio n. 11
0
def test_build_with_skip(storage):
    config = JobControlConfig.from_string("""
    jobs:
        - id: job-to-skip
          function: jobcontrol.utils.testing:testing_job
          kwargs:
              retval: "Foo Retval"
              skip: True
    """)
    jc = JobControl(storage=storage, config=config)

    job = jc.get_job('job-to-skip')
    build = job.create_build()
    build.run()

    assert build['started']
    assert build['finished']
    assert build['skipped']

    assert job.has_builds()
    assert not job.has_successful_builds()  # Skipped builds are ignored
    assert not job.has_running_builds()
    assert list(job.iter_builds()) == [build]
    assert list(job.iter_builds(skipped=False)) == []

    assert build['exception'] is None
    assert build['exception_tb'] is None
Esempio n. 12
0
def test_simple_build_run(storage):
    config = JobControlConfig.from_string("""
    jobs:
        - id: foo
          function: jobcontrol.utils.testing:testing_job
          kwargs:
              retval: "Foo Retval"
    """)
    jc = JobControl(storage=storage, config=config)

    job = jc.get_job('foo')

    assert job.has_builds() is False
    assert job.has_successful_builds() is False
    assert job.has_running_builds() is False
    assert job.is_outdated() is None
    assert job.can_be_built() is True

    # Create and run a build
    # ------------------------------------------------------------

    build = job.create_build()

    assert job.has_builds() is False  # "finished" builds only
    assert job.has_successful_builds() is False
    assert job.has_running_builds() is False
    assert job.is_outdated() is None
    assert job.can_be_built() is True
    assert list(job.iter_builds()) == [build]

    build.run()

    assert build['started'] is True
    assert build['finished'] is True
    assert build['success'] is True
    assert build['skipped'] is False
    assert build['retval'] == 'Foo Retval'

    assert job.has_builds() is True
    assert job.has_successful_builds() is True
    assert job.has_running_builds() is False
    assert job.is_outdated() is False
    assert job.can_be_built() is True
    assert list(job.iter_builds()) == [build]
Esempio n. 13
0
def test_simple_build_run(storage):
    config = JobControlConfig.from_string("""
    jobs:
        - id: foo
          function: jobcontrol.utils.testing:testing_job
          kwargs:
              retval: "Foo Retval"
    """)
    jc = JobControl(storage=storage, config=config)

    job = jc.get_job('foo')

    assert job.has_builds() is False
    assert job.has_successful_builds() is False
    assert job.has_running_builds() is False
    assert job.is_outdated() is None
    assert job.can_be_built() is True

    # Create and run a build
    # ------------------------------------------------------------

    build = job.create_build()

    assert job.has_builds() is False  # "finished" builds only
    assert job.has_successful_builds() is False
    assert job.has_running_builds() is False
    assert job.is_outdated() is None
    assert job.can_be_built() is True
    assert list(job.iter_builds()) == [build]

    build.run()

    assert build['started'] is True
    assert build['finished'] is True
    assert build['success'] is True
    assert build['skipped'] is False
    assert build['retval'] == 'Foo Retval'

    assert job.has_builds() is True
    assert job.has_successful_builds() is True
    assert job.has_running_builds() is False
    assert job.is_outdated() is False
    assert job.can_be_built() is True
    assert list(job.iter_builds()) == [build]
Esempio n. 14
0
def test_build_failure_due_to_nonserializable_object(storage):
    config = JobControlConfig.from_string("""
    jobs:
        - id: job-nso
          function: jobcontrol.utils.testing:job_returning_nonserializable
    """)
    jc = JobControl(storage=storage, config=config)

    job = jc.get_job('job-nso')
    build = job.create_build()
    build.run()

    assert build['started']
    assert build['finished']
    assert not build['success']

    assert isinstance(build['exception'], SerializationError)
    assert (  # The original exception message is kept..
        "TypeError('a class that defines __slots__ without defining "
        "__getstate__ cannot be pickled',)") in build['exception'].message
Esempio n. 15
0
def test_build_failure_due_to_nonserializable_object(storage):
    config = JobControlConfig.from_string("""
    jobs:
        - id: job-nso
          function: jobcontrol.utils.testing:job_returning_nonserializable
    """)
    jc = JobControl(storage=storage, config=config)

    job = jc.get_job('job-nso')
    build = job.create_build()
    build.run()

    assert build['started']
    assert build['finished']
    assert not build['success']

    assert isinstance(build['exception'], SerializationError)
    assert (  # The original exception message is kept..
        "TypeError('a class that defines __slots__ without defining "
        "__getstate__ cannot be pickled',)") in build['exception'].message
Esempio n. 16
0
def test_simple_build_deletion(storage):
    config = JobControlConfig.from_string("""
    jobs:
        - id: job-to-delete
          function: jobcontrol.utils.testing:testing_job
    """)
    jc = JobControl(storage=storage, config=config)

    job = jc.get_job('job-to-delete')

    build_1 = job.create_build()
    build_1.run()

    assert len(list(job.iter_builds())) == 1

    build_2 = job.create_build()
    build_2.run()

    assert len(list(job.iter_builds())) == 2

    build_1.delete()

    assert len(list(job.iter_builds())) == 1
Esempio n. 17
0
def test_simple_build_deletion(storage):
    config = JobControlConfig.from_string("""
    jobs:
        - id: job-to-delete
          function: jobcontrol.utils.testing:testing_job
    """)
    jc = JobControl(storage=storage, config=config)

    job = jc.get_job('job-to-delete')

    build_1 = job.create_build()
    build_1.run()

    assert len(list(job.iter_builds())) == 1

    build_2 = job.create_build()
    build_2.run()

    assert len(list(job.iter_builds())) == 2

    build_1.delete()

    assert len(list(job.iter_builds())) == 1
Esempio n. 18
0
def test_build_deletion_with_cleanup(storage):
    config = JobControlConfig.from_string("""
    jobs:
        - id: job-to-delete
          function: jobcontrol.utils.testing:job_creating_temp_file
          cleanup_function: jobcontrol.utils.testing:cleanup_temp_file
    """)
    jc = JobControl(storage=storage, config=config)

    job = jc.get_job('job-to-delete')

    build = job.create_build()
    build.run()

    assert build['finished'] and build['success']
    assert isinstance(build.retval, str)
    assert os.path.isfile(build.retval)

    assert len(list(job.iter_builds())) == 1

    build.delete()

    assert len(list(job.iter_builds())) == 0
    assert not os.path.isfile(build.retval)
Esempio n. 19
0
def test_build_deletion_with_cleanup(storage):
    config = JobControlConfig.from_string("""
    jobs:
        - id: job-to-delete
          function: jobcontrol.utils.testing:job_creating_temp_file
          cleanup_function: jobcontrol.utils.testing:cleanup_temp_file
    """)
    jc = JobControl(storage=storage, config=config)

    job = jc.get_job('job-to-delete')

    build = job.create_build()
    build.run()

    assert build['finished'] and build['success']
    assert isinstance(build.retval, str)
    assert os.path.isfile(build.retval)

    assert len(list(job.iter_builds())) == 1

    build.delete()

    assert len(list(job.iter_builds())) == 0
    assert not os.path.isfile(build.retval)
Esempio n. 20
0
def test_build_logging(storage):
    config = {
        'jobs': [
            {
                'id': 'job-with-logging',
                'function': 'jobcontrol.utils.testing:job_with_logging'
            },
        ]
    }

    jc = JobControl(storage=storage, config=config)
    job = jc.get_job('job-with-logging')

    build = job.create_build()
    build.run()
    build.refresh()

    assert build['finished'] and build['success']

    log_messages = build.iter_log_messages()
    messages_from_job = [
        msg for msg in log_messages
        if msg.name == 'jobcontrol.utils.testing.job_with_logging'
    ]

    assert len(messages_from_job) == 6

    assert messages_from_job[0].levelno == logging.DEBUG
    assert messages_from_job[0].message == 'This is a debug message'

    assert messages_from_job[0].args == ()
    assert isinstance(messages_from_job[0].created, datetime)
    assert messages_from_job[0].filename == 'testing.py'
    assert messages_from_job[0].function == 'job_with_logging'
    assert messages_from_job[0].level_name == 'DEBUG'
    assert messages_from_job[0].level == logging.DEBUG
    assert isinstance(messages_from_job[0].lineno, int)
    assert messages_from_job[0].module == 'testing'
    assert messages_from_job[0].message == 'This is a debug message'
    assert messages_from_job[0].msg == 'This is a debug message'
    assert messages_from_job[
        0].name == 'jobcontrol.utils.testing.job_with_logging'  # noqa
    assert isinstance(messages_from_job[0].pathname, basestring)
    assert messages_from_job[0].pathname.endswith(
        'jobcontrol/utils/testing.py')  # noqa

    assert messages_from_job[0].exception is None
    assert messages_from_job[0].exception_tb is None

    assert messages_from_job[1].levelno == logging.INFO
    assert messages_from_job[1].message == 'This is an info message'

    assert messages_from_job[2].levelno == logging.WARNING
    assert messages_from_job[2].message == 'This is a warning message'

    assert messages_from_job[3].levelno == logging.ERROR
    assert messages_from_job[3].message == 'This is an error message'

    assert messages_from_job[4].levelno == logging.CRITICAL
    assert messages_from_job[4].message == 'This is a critical message'

    assert messages_from_job[5].levelno == logging.ERROR
    assert messages_from_job[5].message == 'This is an exception message'
    assert isinstance(messages_from_job[5].exception, ValueError)
    assert isinstance(messages_from_job[5].exception_tb, TracebackInfo)
Esempio n. 21
0
def test_core_config_jobs(storage):
    config = JobControlConfig.from_string("""
    jobs:
        - id: foo
          function: mymodule.foo
          dependencies: []

        - id: bar
          function: mymodule.bar
          dependencies: ['foo']

        - id: baz
          function: mymodule.baz
          dependencies: ['foo', 'bar']
    """)
    jc = JobControl(storage=storage, config=config)

    job_foo = jc.get_job('foo')
    job_bar = jc.get_job('bar')
    job_baz = jc.get_job('baz')

    # Check jobs
    # ------------------------------------------------------------

    assert isinstance(job_foo, JobInfo)
    assert job_foo.id == 'foo'
    assert job_foo.config['id'] == 'foo'
    assert job_foo.config['function'] == 'mymodule.foo'
    assert job_foo.config['args'] == ()
    assert job_foo.config['kwargs'] == {}
    assert job_foo.config['dependencies'] == []
    assert list(job_foo.get_deps()) == []
    assert list(job_foo.get_revdeps()) == [job_bar, job_baz]
    assert job_foo.get_status() == 'not_built'
    assert list(job_foo.iter_builds()) == []
    assert job_foo.get_latest_successful_build() is None
    assert job_foo.has_builds() is False
    assert job_foo.has_successful_builds() is False
    assert job_foo.has_running_builds() is False
    assert job_foo.is_outdated() is None  # no builds..
    assert job_foo.can_be_built() is True

    assert isinstance(job_bar, JobInfo)
    assert job_bar.id == 'bar'
    assert job_bar.config['id'] == 'bar'
    assert job_bar.config['function'] == 'mymodule.bar'
    assert job_bar.config['args'] == ()
    assert job_bar.config['kwargs'] == {}
    assert job_bar.config['dependencies'] == ['foo']
    assert list(job_bar.get_deps()) == [job_foo]
    assert list(job_bar.get_revdeps()) == [job_baz]
    assert job_bar.get_status() == 'not_built'
    assert list(job_bar.iter_builds()) == []
    assert job_bar.get_latest_successful_build() is None
    assert job_bar.has_builds() is False
    assert job_bar.has_successful_builds() is False
    assert job_bar.has_running_builds() is False
    assert job_bar.is_outdated() is None  # no builds..
    assert job_bar.can_be_built() is False  # "foo" has no builds

    assert isinstance(job_baz, JobInfo)
    assert job_baz.id == 'baz'
    assert job_baz.config['id'] == 'baz'
    assert job_baz.config['function'] == 'mymodule.baz'
    assert job_baz.config['args'] == ()
    assert job_baz.config['kwargs'] == {}
    assert job_baz.config['dependencies'] == ['foo', 'bar']
    assert list(job_baz.get_deps()) == [job_foo, job_bar]
    assert list(job_baz.get_revdeps()) == []
    assert job_baz.get_status() == 'not_built'
    assert list(job_baz.iter_builds()) == []
    assert job_baz.get_latest_successful_build() is None
    assert job_baz.has_builds() is False
    assert job_baz.has_successful_builds() is False
    assert job_baz.has_running_builds() is False
    assert job_baz.is_outdated() is None  # no builds..
    assert job_baz.can_be_built() is False  # "foo" and "bar" have no builds

    # Exception on non-existing job

    with pytest.raises(NotFound):
        jc.get_job('does-not-exist')

    # Iterate jobs

    assert list(jc.iter_jobs()) == [job_foo, job_bar, job_baz]
Esempio n. 22
0
def test_job_status_reporting(storage):

    config = JobControlConfig.from_string("""
    jobs:
        - id: job-1
          function: jobcontrol.utils.testing:testing_job
        - id: job-2
          function: jobcontrol.utils.testing:testing_job
        - id: job-3
          function: jobcontrol.utils.testing:testing_job
          dependencies: ['job-1', 'job-2']
        - id: job-4
          function: jobcontrol.utils.testing:testing_job
          dependencies: ['job-3']

    """)
    jc = JobControl(storage=storage, config=config)

    # Check status of unbuilt jobs
    job_1 = jc.get_job('job-1')
    job_2 = jc.get_job('job-2')
    job_3 = jc.get_job('job-3')
    job_4 = jc.get_job('job-4')

    assert job_1.get_status() == 'not_built'
    assert job_2.get_status() == 'not_built'
    assert job_3.get_status() == 'not_built'
    assert job_4.get_status() == 'not_built'

    assert list(job_1.iter_builds()) == []
    assert job_1.get_latest_successful_build() is None
    assert job_1.has_builds() is False
    assert job_1.has_successful_builds() is False
    assert job_1.has_running_builds() is False
    assert job_1.is_outdated() is None  # IDK
    assert job_1.can_be_built() is True

    assert job_2.can_be_built() is True
    assert job_3.can_be_built() is False  # deps not met
    assert job_4.can_be_built() is False  # deps not met

    # ------------------------------------------------------------
    # Manually start a build for job 1, as we want to
    # check it is running, etc..
    # ------------------------------------------------------------

    build_1_1 = job_1.create_build()
    assert build_1_1['started'] is False
    assert build_1_1['finished'] is False
    assert job_1.has_builds() is False
    assert job_1.has_running_builds() is False

    assert job_1.get_status() == 'not_built'

    jc.storage.start_build(build_1_1.id)
    build_1_1.refresh()
    assert build_1_1['started'] is True
    assert build_1_1['finished'] is False
    assert job_1.has_builds() is False  # **Completed** builds..
    assert job_1.has_running_builds() is True

    # Note: "running" is not anymore reported as a state
    assert job_1.get_status() == 'not_built'

    jc.storage.finish_build(build_1_1.id, success=False)
    build_1_1.refresh()
    assert build_1_1['started'] is True
    assert build_1_1['finished'] is True
    assert build_1_1['success'] is False
    assert job_1.has_builds() is True
    assert job_1.has_successful_builds() is False
    assert job_1.has_running_builds() is False

    assert job_1.get_status() == 'failed'

    # ------------------------------------------------------------
    # Do it again, with a new build, which should succeed this time
    # ------------------------------------------------------------

    build_1_2 = job_1.create_build()
    build_1_2.run()
    build_1_2.refresh()

    assert len(list(job_1.iter_builds())) == 2
    assert build_1_2['started'] is True
    assert build_1_2['finished'] is True
    assert build_1_2['success'] is True
    assert job_1.has_builds() is True
    assert job_1.has_successful_builds() is True
    assert job_1.has_running_builds() is False

    assert job_1.get_status() == 'success'

    # ------------------------------------------------------------
    # Now build job 2 and make sure 3 becomes buildable
    # ------------------------------------------------------------

    assert job_3.can_be_built() is False
    build_2_1 = job_2.create_build()
    build_2_1.run()
    assert job_3.can_be_built() is True

    # Job 4 is still missing a build from 3
    assert job_4.can_be_built() is False
    job_3.create_build().run()
    assert job_4.can_be_built() is True

    assert job_2.get_status() == 'success'
    assert job_3.get_status() == 'success'
    assert job_4.get_status() == 'not_built'

    # ------------------------------------------------------------
    # Rebuild #1 to get #3 to be "outdated"
    # ------------------------------------------------------------

    assert job_3.is_outdated() is False
    job_1.create_build().run()
    assert job_3.is_outdated() is True
    assert job_3.get_status() == 'outdated'
Esempio n. 23
0
def test_core_config_jobs(storage):
    config = JobControlConfig.from_string("""
    jobs:
        - id: foo
          function: mymodule.foo
          dependencies: []

        - id: bar
          function: mymodule.bar
          dependencies: ['foo']

        - id: baz
          function: mymodule.baz
          dependencies: ['foo', 'bar']
    """)
    jc = JobControl(storage=storage, config=config)

    job_foo = jc.get_job('foo')
    job_bar = jc.get_job('bar')
    job_baz = jc.get_job('baz')

    # Check jobs
    # ------------------------------------------------------------

    assert isinstance(job_foo, JobInfo)
    assert job_foo.id == 'foo'
    assert job_foo.config['id'] == 'foo'
    assert job_foo.config['function'] == 'mymodule.foo'
    assert job_foo.config['args'] == ()
    assert job_foo.config['kwargs'] == {}
    assert job_foo.config['dependencies'] == []
    assert list(job_foo.get_deps()) == []
    assert list(job_foo.get_revdeps()) == [job_bar, job_baz]
    assert job_foo.get_status() == 'not_built'
    assert list(job_foo.iter_builds()) == []
    assert job_foo.get_latest_successful_build() is None
    assert job_foo.has_builds() is False
    assert job_foo.has_successful_builds() is False
    assert job_foo.has_running_builds() is False
    assert job_foo.is_outdated() is None  # no builds..
    assert job_foo.can_be_built() is True

    assert isinstance(job_bar, JobInfo)
    assert job_bar.id == 'bar'
    assert job_bar.config['id'] == 'bar'
    assert job_bar.config['function'] == 'mymodule.bar'
    assert job_bar.config['args'] == ()
    assert job_bar.config['kwargs'] == {}
    assert job_bar.config['dependencies'] == ['foo']
    assert list(job_bar.get_deps()) == [job_foo]
    assert list(job_bar.get_revdeps()) == [job_baz]
    assert job_bar.get_status() == 'not_built'
    assert list(job_bar.iter_builds()) == []
    assert job_bar.get_latest_successful_build() is None
    assert job_bar.has_builds() is False
    assert job_bar.has_successful_builds() is False
    assert job_bar.has_running_builds() is False
    assert job_bar.is_outdated() is None  # no builds..
    assert job_bar.can_be_built() is False  # "foo" has no builds

    assert isinstance(job_baz, JobInfo)
    assert job_baz.id == 'baz'
    assert job_baz.config['id'] == 'baz'
    assert job_baz.config['function'] == 'mymodule.baz'
    assert job_baz.config['args'] == ()
    assert job_baz.config['kwargs'] == {}
    assert job_baz.config['dependencies'] == ['foo', 'bar']
    assert list(job_baz.get_deps()) == [job_foo, job_bar]
    assert list(job_baz.get_revdeps()) == []
    assert job_baz.get_status() == 'not_built'
    assert list(job_baz.iter_builds()) == []
    assert job_baz.get_latest_successful_build() is None
    assert job_baz.has_builds() is False
    assert job_baz.has_successful_builds() is False
    assert job_baz.has_running_builds() is False
    assert job_baz.is_outdated() is None  # no builds..
    assert job_baz.can_be_built() is False  # "foo" and "bar" have no builds

    # Exception on non-existing job

    with pytest.raises(NotFound):
        jc.get_job('does-not-exist')

    # Iterate jobs

    assert list(jc.iter_jobs()) == [job_foo, job_bar, job_baz]
Esempio n. 24
0
def test_job_status_reporting(storage):

    config = JobControlConfig.from_string("""
    jobs:
        - id: job-1
          function: jobcontrol.utils.testing:testing_job
        - id: job-2
          function: jobcontrol.utils.testing:testing_job
        - id: job-3
          function: jobcontrol.utils.testing:testing_job
          dependencies: ['job-1', 'job-2']
        - id: job-4
          function: jobcontrol.utils.testing:testing_job
          dependencies: ['job-3']

    """)
    jc = JobControl(storage=storage, config=config)

    # Check status of unbuilt jobs
    job_1 = jc.get_job('job-1')
    job_2 = jc.get_job('job-2')
    job_3 = jc.get_job('job-3')
    job_4 = jc.get_job('job-4')

    assert job_1.get_status() == 'not_built'
    assert job_2.get_status() == 'not_built'
    assert job_3.get_status() == 'not_built'
    assert job_4.get_status() == 'not_built'

    assert list(job_1.iter_builds()) == []
    assert job_1.get_latest_successful_build() is None
    assert job_1.has_builds() is False
    assert job_1.has_successful_builds() is False
    assert job_1.has_running_builds() is False
    assert job_1.is_outdated() is None  # IDK
    assert job_1.can_be_built() is True

    assert job_2.can_be_built() is True
    assert job_3.can_be_built() is False  # deps not met
    assert job_4.can_be_built() is False  # deps not met

    # ------------------------------------------------------------
    # Manually start a build for job 1, as we want to
    # check it is running, etc..
    # ------------------------------------------------------------

    build_1_1 = job_1.create_build()
    assert build_1_1['started'] is False
    assert build_1_1['finished'] is False
    assert job_1.has_builds() is False
    assert job_1.has_running_builds() is False

    assert job_1.get_status() == 'not_built'

    jc.storage.start_build(build_1_1.id)
    build_1_1.refresh()
    assert build_1_1['started'] is True
    assert build_1_1['finished'] is False
    assert job_1.has_builds() is False  # **Completed** builds..
    assert job_1.has_running_builds() is True

    # Note: "running" is not anymore reported as a state
    assert job_1.get_status() == 'not_built'

    jc.storage.finish_build(build_1_1.id, success=False)
    build_1_1.refresh()
    assert build_1_1['started'] is True
    assert build_1_1['finished'] is True
    assert build_1_1['success'] is False
    assert job_1.has_builds() is True
    assert job_1.has_successful_builds() is False
    assert job_1.has_running_builds() is False

    assert job_1.get_status() == 'failed'

    # ------------------------------------------------------------
    # Do it again, with a new build, which should succeed this time
    # ------------------------------------------------------------

    build_1_2 = job_1.create_build()
    build_1_2.run()
    build_1_2.refresh()

    assert len(list(job_1.iter_builds())) == 2
    assert build_1_2['started'] is True
    assert build_1_2['finished'] is True
    assert build_1_2['success'] is True
    assert job_1.has_builds() is True
    assert job_1.has_successful_builds() is True
    assert job_1.has_running_builds() is False

    assert job_1.get_status() == 'success'

    # ------------------------------------------------------------
    # Now build job 2 and make sure 3 becomes buildable
    # ------------------------------------------------------------

    assert job_3.can_be_built() is False
    build_2_1 = job_2.create_build()
    build_2_1.run()
    assert job_3.can_be_built() is True

    # Job 4 is still missing a build from 3
    assert job_4.can_be_built() is False
    job_3.create_build().run()
    assert job_4.can_be_built() is True

    assert job_2.get_status() == 'success'
    assert job_3.get_status() == 'success'
    assert job_4.get_status() == 'not_built'

    # ------------------------------------------------------------
    # Rebuild #1 to get #3 to be "outdated"
    # ------------------------------------------------------------

    assert job_3.is_outdated() is False
    job_1.create_build().run()
    assert job_3.is_outdated() is True
    assert job_3.get_status() == 'outdated'