Exemplo n.º 1
0
def test_variables():
    """Check that an action's variables are properly substituted."""

    variable = feature('variable', attributes=incidental)

    class A(action):

        var = map(variable, join)
        command = 'echo $(var)'

    a = artefact('a', attrs=notfile | always)
    b = artefact('b', attrs=notfile | always)
    c = artefact('c', attrs=notfile | always)
    echo = action('echo', 'echo $(variable)')
    pye = action('pyecho', pyecho, ['variable'])
    a = rule(A(), a, features=variable('A'))
    b = rule(echo, b, a, features=variable('B'))
    c = rule(pye, c, b, features=variable('C'))
    with patch('faber.action.action.__status__') as recipe:
        assert a.update()
        (_, _, _, _, output, _), kwds = recipe.call_args_list[-1]
        assert output.strip() == 'A'
        assert b.update()
        (_, _, _, _, output, _), kwds = recipe.call_args_list[-1]
        assert output.strip() == 'B'
        assert c.update()
        (_, _, _, _, output, _), kwds = recipe.call_args_list[-1]
        assert output.strip() == "c <- b (variable=['C'])"
Exemplo n.º 2
0
def test_implicit_rule():

    a1 = action('a1', 'something')
    a2 = action('a2', 'something')
    a3 = action('a3', 'something')
    c_ = artefact('c', type=c)
    cc = artefact('cc', type=cxx)
    o = artefact('o', type=obj)
    l = artefact('l', type=lib)
    assembly.implicit_rule(a1, obj, c)
    assembly.implicit_rule(a2, obj, cxx)
    assembly.implicit_rule(a3, lib, obj)
    with patch('faber.assembly.explicit_rule') as rule:
        assembly.rule(o, c_)
        assembly.rule(o, cc)
        assert rule.call_count == 2
        assert (rule.call_args_list[0][0][0] is a1
                and rule.call_args_list[0][0][1] is o)
        assert (rule.call_args_list[1][0][0] is a2
                and rule.call_args_list[1][0][1] is o)

    with patch('faber.assembly.explicit_rule') as rule:
        assembly.rule(l, cc)
        assert rule.call_count == 2
        assert (rule.call_args_list[0][0][0] is a2
                and rule.call_args_list[0][1]['attrs'] & intermediate)
        assert (rule.call_args_list[1][0][0] is a3
                and rule.call_args_list[1][0][1] is l)
Exemplo n.º 3
0
def test_composite():
    """Test the workflow of faber.config.try_compile"""

    src = rule(fileutils.touch, 'src', attrs=intermediate | always)
    obj = artefact('obj', attrs=intermediate)
    check = artefact('check', attrs=notfile)

    def assemble(targets, sources):
        rule(fileutils.copy,
             obj,
             src,
             attrs=intermediate,
             module=targets[0].module)

    # make a dependency graph
    ass = rule(assemble, 'ass', attrs=notfile | always)
    # make a binary
    depend(obj, dependencies=ass)
    # and test it
    check = alias(check, obj)

    with patch('faber.action.action.__status__') as recipe:
        scheduler.update([check])
        (_, status, _, _, _, _), kwds = recipe.call_args_list[-1]
        assert recipe.call_count == 3
        assert status is True
Exemplo n.º 4
0
def test_noop():
    """Check that an artefact won't be updated if a dependent artefact is up to date."""
    a = artefact('a', attrs=notfile)
    b = artefact('b', attrs=notfile)
    b = rule(pyecho, b, a)
    with patch('faber.scheduler._report_recipe') as recipe:
        assert scheduler.update(b)
        assert not recipe.called
Exemplo n.º 5
0
def test_noop():
    """Check that an artefact won't be updated if a dependent artefact is up to date."""
    a = artefact('a', attrs=notfile)
    b = artefact('b', attrs=notfile)
    b = rule(pyecho, b, a)
    with patch('faber.action.action.__status__') as recipe:
        assert b.update()
        assert not recipe.called
Exemplo n.º 6
0
def test_late():
    """Test that a "late" dependency raises an error."""

    a = artefact('a', attrs=notfile | always)
    assert scheduler.update(a)
    with pytest.raises(scheduler.DependencyError):
        b = artefact('b', attrs=notfile)
        depend(a, b)
Exemplo n.º 7
0
def test_fail():
    """Check that an artefact won't be updated if a dependent artefact's recipe failed."""
    a = artefact('a', attrs=notfile | always)
    b = artefact('b', attrs=notfile)
    fail = action('failing', 'fail')
    a = rule(fail, a)
    b = rule(pyecho, b, a)
    with patch('faber.scheduler._report_recipe'):
        assert not scheduler.update(b)
Exemplo n.º 8
0
def test_nocare():
    """Check that an artefact will be updated if a dependent artefact's recipe failed
    but was marked as nocare."""
    a = artefact('a', attrs=notfile | always | nocare)
    b = artefact('b', attrs=notfile)
    fail = action('failing', 'fail')
    a = rule(fail, a)
    b = rule(pyecho, b, a)
    with patch('faber.scheduler._report_recipe') as recipe:
        assert scheduler.update(b)
        (_, _, _, _, _, output, _), kwds = recipe.call_args_list[-1]
        assert output.strip() == 'b <- a'
Exemplo n.º 9
0
def test_call():
    a = action()
    b = artefact('b', attrs=notfile)
    c = artefact('c', attrs=notfile)
    with pytest.raises(ValueError) as e:
        a(b, c)
    assert 'not implemented' in str(e.value)

    with capture_output() as (out, err):
        a = action('echo', 'echo $(<)')
        a([b])
    assert out.getvalue().strip() == 'test.b'
    assert err.getvalue() == ''
Exemplo n.º 10
0
def test_action():
    """Check that an action's status is reported upon completion."""
    a = artefact('a', attrs=notfile | always)
    b = artefact('b', attrs=notfile)
    c = artefact('c', attrs=notfile)
    a = rule(pyecho, a)
    b = rule(pyecho, b, a)
    c = rule(pyecho, c, b)
    with patch('faber.scheduler._report_recipe') as recipe:
        assert scheduler.update(b)
        (_, _, _, _, _, output, _), kwds = recipe.call_args_list[-1]
        assert output.strip() == 'b <- a'
        assert scheduler.update(c)
        (_, _, _, _, _, output, _), kwds = recipe.call_args_list[-1]
        assert output.strip() == 'c <- b'
Exemplo n.º 11
0
def test_late_cycle():
    """Test that the scheduler detects dependency cycles
    created in recipes."""

    a = artefact('a', attrs=notfile | always)
    b = artefact('b', attrs=notfile | always)
    c = artefact('c', attrs=notfile | always)

    def generator(targets, sources):
        depend(b, c)  # create cycle !

    b = rule(generator, b, a)
    echo = action('echo', 'echo $(<) $(>)')
    c = rule(echo, c, b)
    with pytest.raises(scheduler.DependencyError):
        assert scheduler.update(c)
Exemplo n.º 12
0
def test_recipe():
    """Check that an artefact's __recipe__ method is called to report
    the execution of the recipe updating it."""
    a = artefact('a', attrs=notfile | always)
    b = artefact('b', attrs=notfile | always)
    c = artefact('c', attrs=notfile | always)
    a = rule(pyecho, a)
    b = rule(pyecho, b, a)
    c = rule(pyecho, c, b)
    with patch('faber.action.action.__status__') as recipe:
        assert b.update()
        (_, _, _, _, output, _), kwds = recipe.call_args_list[-1]
        assert output.strip() == 'b <- a'
        assert c.update()
        (_, _, _, _, output, _), kwds = recipe.call_args_list[-1]
        assert output.strip() == 'c <- b'
Exemplo n.º 13
0
def test_composite():
    """Test the workflow of faber.artefacts.binary"""

    src = rule(fileutils.touch, 'src')
    bin = artefact('bin')

    def assemble(targets, sources):
        obj = rule(fileutils.copy,
                   'obj',
                   src,
                   attrs=intermediate,
                   module=targets[0].module)
        rule(fileutils.copy,
             bin,
             obj,
             attrs=intermediate,
             module=targets[0].module)

    def test(targets, sources):
        print('testing {}'.format(sources[0].name))
        assert exists(sources[0]._filename)

    # make a dependency graph
    ass = rule(assemble, 'ass', attrs=notfile | always)
    # make a binary
    depend(bin, ass)
    # and test it
    test = rule(test, 'test', bin, attrs=notfile)

    with patch('faber.scheduler._report_recipe') as recipe:
        scheduler.update([test])
        (_, _, status, _, _, output, _), kwds = recipe.call_args_list[-1]
        assert output == 'testing bin\n'
        assert status == 0
Exemplo n.º 14
0
def test_cycle():
    """Test that the scheduler detects dependency cycles."""

    echo = action('echo', 'echo $(<) $(>)')
    a = artefact('a', attrs=notfile | always)
    b = rule(echo, 'b', a, attrs=notfile)
    with pytest.raises(scheduler.DependencyError):
        a = rule(echo, a, b)
Exemplo n.º 15
0
def test_conditional_dependency():
    """Test the workflow of conditional dependencies"""

    name = feature('name', attributes=multi|path|incidental)
    # artefact to compute the condition
    a = rule(None, 'a', attrs=notfile|always)
    fs = set(name(a.filename))
    # conditional artefact
    b1 = rule(pyecho, 'b1', features=fs, attrs=notfile|always)
    b2 = rule(pyecho, 'b2', features=fs, attrs=notfile|always)
    # c gets built unconditionally
    # but will include b1 or b2 only if condition is met
    c = artefact('c', attrs=notfile)
    c = rule(pyecho, c, dependencies=[placeholder(c, b1, set.name == ''),
                                      placeholder(c, b2, set.name != '')])
    with patch('faber.action.action.__status__') as recipe:
        scheduler.update(c)
        output = [i[0][4].strip() for i in recipe.call_args_list]
        assert 'b1 <-' not in output and 'b2 <-' in output
Exemplo n.º 16
0
def test_dynamic_dependencies():
    """Test whether it's possible to add dependencies while the scheduler is already running."""

    c = artefact('c', attrs=notfile)

    def inject_deps(self, *args, **kwds):
        d = rule(pyecho, 'd', attrs=notfile | always)
        depend(c, d)
        print('ddeps.b')

    a = rule(pyecho, 'a', attrs=notfile | always)
    b = rule(action('dg', inject_deps), 'b', a, attrs=notfile)
    c = rule(pyecho, c, b)
    with patch('faber.scheduler._report_recipe') as recipe:
        assert scheduler.update(b)
        (_, _, _, _, _, output, _), kwds = recipe.call_args_list[-1]
        assert output.strip() == 'ddeps.b'
        assert scheduler.update(c)
        # verify that d is actually updated before c
        output = [i[0][5].strip() for i in recipe.call_args_list]
        assert 'd <-' in output
Exemplo n.º 17
0
def test_dynamic_recipe():
    """Test whether it's possible to add a recipe while the scheduler is already running."""

    c = artefact('c', attrs=notfile)

    def generate(*args, **kwds):
        """generate the graph for c."""
        a = rule(pyecho, 'a', attrs=notfile | always)
        a1 = rule(pyecho, 'a1', a, attrs=notfile | always)
        a2 = rule(pyecho, 'a2', a1, attrs=notfile | always)
        rule(
            pyecho,
            c,
            a2,
        )

    b = rule(generate, 'b', attrs=notfile | always)
    depend(c, b)
    with patch('faber.scheduler._report_recipe') as recipe:
        assert scheduler.update(c)
        output = [i[0][5].strip() for i in recipe.call_args_list]
        assert output[-1] == 'c <- a2'
Exemplo n.º 18
0
def test_multi():
    """TBD"""

    # workflow:
    # b1 needs to be updated, but doing that also updates b2
    # this means c2 (dependent on b2) will also be updated.
    a = artefact('a', attrs=notfile)
    b1 = artefact('b1', attrs=notfile)
    b2 = artefact('b2', attrs=notfile | always)
    c1 = artefact('c1', attrs=notfile)
    c2 = artefact('c2', attrs=notfile)
    d = artefact('d', attrs=notfile)
    rule(pyecho, a)
    rule(pyecho, [b1, b2], a)
    rule(pyecho, c1, b1)
    rule(pyecho, c2, b2)
    rule(pyecho, d, [c1, c2])
    with patch('faber.scheduler._report_recipe') as recipe:
        assert scheduler.update(d)
        output = [i[0][4].strip() for i in recipe.call_args_list]
        assert output[0] == 'b1 b2 <- a'
        assert 'c2 <- b2' in output
        # sets aren't ordered, so we check for both possibilities
        assert output[-1] in ('d <- c1 c2', 'd <- c2 c1')