mirror of
https://github.com/boostorg/build.git
synced 2026-02-15 00:52:16 +00:00
Added a new internal Boost Build test checking Boost Build's project id handling.
[SVN r79939]
This commit is contained in:
320
v2/test/project_id.py
Executable file
320
v2/test/project_id.py
Executable file
@@ -0,0 +1,320 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright (C) 2012. Jurko Gospodnetic
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
# Tests Boost Build's project-id handling.
|
||||
|
||||
import BoostBuild
|
||||
|
||||
|
||||
def test_assigning_project_ids():
|
||||
t = BoostBuild.Tester(pass_toolset=False)
|
||||
t.write("jamroot.jam", """\
|
||||
import assert ;
|
||||
import modules ;
|
||||
import notfile ;
|
||||
import project ;
|
||||
|
||||
rule assert-project-id ( id ? : module-name ? )
|
||||
{
|
||||
module-name ?= [ CALLER_MODULE ] ;
|
||||
assert.result $(id) : project.attribute $(module-name) id ;
|
||||
}
|
||||
|
||||
# Project rule modifies the main project id.
|
||||
assert-project-id ; # Initial project id is empty
|
||||
project foo ; assert-project-id /foo ;
|
||||
project ; assert-project-id /foo ;
|
||||
project foo ; assert-project-id /foo ;
|
||||
project bar ; assert-project-id /bar ;
|
||||
project /foo ; assert-project-id /foo ;
|
||||
project "" ; assert-project-id /foo ;
|
||||
|
||||
# Calling the use-project rule does not modify the project's main id.
|
||||
use-project id1 : a ;
|
||||
# We need to load the 'a' Jamfile module manually as the use-project rule will
|
||||
# only schedule the load to be done after the current module load finishes.
|
||||
a-module = [ project.load "a" ] ;
|
||||
assert-project-id : $(a-module) ;
|
||||
use-project id2 : a ;
|
||||
assert-project-id : $(a-module) ;
|
||||
modules.call-in $(a-module) : project baz ;
|
||||
assert-project-id /baz : $(a-module) ;
|
||||
use-project id3 : a ;
|
||||
assert-project-id /baz : $(a-module) ;
|
||||
|
||||
# Make sure the project id still holds after all the scheduled use-project loads
|
||||
# complete. We do this by scheduling the assert for the Jam action scheduling
|
||||
# phase.
|
||||
notfile x : @assert-a-rule ;
|
||||
rule assert-a-rule ( target : : properties * )
|
||||
{
|
||||
assert-project-id /baz : $(a-module) ;
|
||||
}
|
||||
""")
|
||||
t.write("a/jamfile.jam", """\
|
||||
# Initial project id for this module is empty.
|
||||
assert-project-id ;
|
||||
""")
|
||||
t.run_build_system()
|
||||
t.cleanup()
|
||||
|
||||
|
||||
def test_assigning_using_project_ids_in_target_references():
|
||||
t = BoostBuild.Tester()
|
||||
__write_appender(t, "appender.jam")
|
||||
t.write("jamroot.jam", """\
|
||||
import type ;
|
||||
type.register AAA : _a ;
|
||||
type.register BBB : _b ;
|
||||
type.register CCC : _c ;
|
||||
|
||||
import appender ;
|
||||
appender.register aaa-to-bbb : AAA : BBB ;
|
||||
appender.register bbb-to-ccc : BBB : CCC ;
|
||||
|
||||
use-project id1 : b ;
|
||||
use-project /id2 : b ;
|
||||
|
||||
ccc c1 : /id1//target ;
|
||||
ccc c2 : /id2//target ;
|
||||
ccc c3 : /id3//target ;
|
||||
ccc c4 : b//target ;
|
||||
ccc c5 : /project-a1//target ;
|
||||
ccc c6 : /project-a2//target ;
|
||||
ccc c7 : /project-a3//target ;
|
||||
|
||||
use-project id3 : b ;
|
||||
""")
|
||||
t.write("b/source._a", "")
|
||||
t.write("b/jamfile.jam", """\
|
||||
project project-a1 ;
|
||||
project /project-a2 ;
|
||||
bbb target : source._a ;
|
||||
project /project-a3 ;
|
||||
""")
|
||||
|
||||
t.run_build_system()
|
||||
t.expect_addition("b/bin/$toolset/target._b")
|
||||
t.expect_addition("bin/$toolset/c%d._c" % x for x in range(1, 8))
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
def test_repeated_ids():
|
||||
t = BoostBuild.Tester()
|
||||
t.write("jamroot.jam", "project foo ; project foo ;")
|
||||
t.run_build_system()
|
||||
|
||||
t.write("a/jamfile.jam", "")
|
||||
t.write("jamroot.jam", "project foo ; use-project foo : a ;")
|
||||
t.run_build_system(status=1)
|
||||
t.expect_output_lines("""\
|
||||
error: Attempt to redeclare already registered project id '/foo'.
|
||||
error: Original project:
|
||||
error: Name: Jamfile<*>
|
||||
error: Main id: /foo
|
||||
error: File: jamroot.jam
|
||||
error: Location: .
|
||||
error: New project:
|
||||
error: File: a*jamfile.jam
|
||||
error: Location: a""")
|
||||
|
||||
t.write("jamroot.jam", "use-project foo : a ; project foo ;")
|
||||
t.run_build_system(status=1)
|
||||
t.expect_output_lines("""\
|
||||
error: Attempt to redeclare already registered project id '/foo'.
|
||||
error: Original project:
|
||||
error: Name: Jamfile<*>
|
||||
error: Main id: /foo
|
||||
error: File: jamroot.jam
|
||||
error: Location: .
|
||||
error: New project:
|
||||
error: File: a*jamfile.jam
|
||||
error: Location: a""")
|
||||
|
||||
t.write("jamroot.jam", """\
|
||||
import modules ;
|
||||
import project ;
|
||||
modules.call-in [ project.load a ] : project foo ;
|
||||
project foo ;
|
||||
""")
|
||||
t.run_build_system(status=1)
|
||||
t.expect_output_lines("""\
|
||||
error: at jamroot.jam:4
|
||||
error: Attempt to redeclare already registered project id '/foo'.
|
||||
error: Original project:
|
||||
error: Name: Jamfile<*>
|
||||
error: Main id: /foo
|
||||
error: File: a*jamfile.jam
|
||||
error: Location: a
|
||||
error: New project:
|
||||
error: File: jamroot.jam
|
||||
error: Location: .""")
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
def test_unresolved_project_references():
|
||||
t = BoostBuild.Tester()
|
||||
|
||||
__write_appender(t, "appender.jam")
|
||||
t.write("b/source._a", "")
|
||||
t.write("b/jamfile.jam", "bbb target : source._a ;")
|
||||
t.write("jamroot.jam", """\
|
||||
import type ;
|
||||
type.register AAA : _a ;
|
||||
type.register BBB : _b ;
|
||||
type.register CCC : _c ;
|
||||
|
||||
import appender ;
|
||||
appender.register aaa-to-bbb : AAA : BBB ;
|
||||
appender.register bbb-to-ccc : BBB : CCC ;
|
||||
|
||||
use-project foo : b ;
|
||||
|
||||
ccc c1 : b//target ;
|
||||
ccc c2 : /foo//target ;
|
||||
ccc c-invalid : invalid//target ;
|
||||
ccc c-root-invalid : /invalid//target ;
|
||||
ccc c-missing-root : foo//target ;
|
||||
ccc c-invalid-target : /foo//invalid ;
|
||||
""")
|
||||
|
||||
t.run_build_system(["c1", "c2"])
|
||||
t.expect_addition("b/bin/$toolset/debug/target._b")
|
||||
t.expect_addition("bin/$toolset/debug/c%s._c" % x for x in range(1, 3))
|
||||
t.expect_nothing_more()
|
||||
|
||||
t.run_build_system(["c-invalid"], status=1)
|
||||
t.expect_output_lines("""\
|
||||
error: Unable to find file or target named
|
||||
error: 'invalid//target'
|
||||
error: referred to from project at
|
||||
error: '.'
|
||||
error: could not resolve project reference 'invalid'""")
|
||||
|
||||
t.run_build_system(["c-root-invalid"], status=1)
|
||||
t.expect_output_lines("""\
|
||||
error: Unable to find file or target named
|
||||
error: '/invalid//target'
|
||||
error: referred to from project at
|
||||
error: '.'
|
||||
error: could not resolve project reference '/invalid'""")
|
||||
|
||||
t.run_build_system(["c-missing-root"], status=1)
|
||||
t.expect_output_lines("""\
|
||||
error: Unable to find file or target named
|
||||
error: 'foo//target'
|
||||
error: referred to from project at
|
||||
error: '.'
|
||||
error: could not resolve project reference 'foo' - possibly missing a """
|
||||
"leading slash ('/') character.")
|
||||
|
||||
t.run_build_system(["c-invalid-target"], status=1)
|
||||
t.expect_output_lines("""\
|
||||
error: Unable to find file or target named
|
||||
error: '/foo//invalid'
|
||||
error: referred to from project at
|
||||
error: '.'""")
|
||||
t.expect_output_lines("*could not resolve project reference*", False)
|
||||
|
||||
t.cleanup()
|
||||
|
||||
|
||||
def __write_appender(t, name):
|
||||
t.write(name,
|
||||
r"""# Copyright 2012 Jurko Gospodnetic
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
# Support for registering test generators that construct their targets by
|
||||
# simply appending their given input data, e.g. list of sources & targets.
|
||||
|
||||
import "class" : new ;
|
||||
import generators ;
|
||||
import modules ;
|
||||
import sequence ;
|
||||
|
||||
rule register ( id composing ? : source-types + : target-types + )
|
||||
{
|
||||
local caller-module = [ CALLER_MODULE ] ;
|
||||
id = $(caller-module).$(id) ;
|
||||
local g = [ new generator $(id) $(composing) : $(source-types) :
|
||||
$(target-types) ] ;
|
||||
$(g).set-rule-name $(__name__).appender ;
|
||||
generators.register $(g) ;
|
||||
return $(id) ;
|
||||
}
|
||||
|
||||
if [ modules.peek : NT ]
|
||||
{
|
||||
X = ")" ;
|
||||
ECHO_CMD = (echo. ;
|
||||
}
|
||||
else
|
||||
{
|
||||
X = \" ;
|
||||
ECHO_CMD = "echo $(X)" ;
|
||||
}
|
||||
|
||||
local appender-runs ;
|
||||
|
||||
# We set up separate actions for building each target in order to avoid having
|
||||
# to iterate over them in action (i.e. shell) code. We have to be extra careful
|
||||
# though to achieve the exact same effect as if doing all the work in just one
|
||||
# action. Otherwise Boost Jam might, under some circumstances, run only some of
|
||||
# our actions. To achieve this we register a series of actions for all the
|
||||
# targets (since they all have the same target list - either all or none of them
|
||||
# get run independent of which target actually needs to get built), each
|
||||
# building only a single target. Since all our actions use the same targets, we
|
||||
# can not use 'on-target' parameters to pass data to a specific action so we
|
||||
# pass them using the second 'sources' parameter which our actions then know how
|
||||
# to interpret correctly. This works well since Boost Jam does not automatically
|
||||
# add dependency relations between specified action targets & sources and so the
|
||||
# second argument, even though most often used to pass in a list of sources, can
|
||||
# actually be used for passing in any type of information.
|
||||
rule appender ( targets + : sources + : properties * )
|
||||
{
|
||||
appender-runs = [ CALC $(appender-runs:E=0) + 1 ] ;
|
||||
local target-index = 0 ;
|
||||
local target-count = [ sequence.length $(targets) ] ;
|
||||
local original-targets ;
|
||||
for t in $(targets)
|
||||
{
|
||||
target-index = [ CALC $(target-index) + 1 ] ;
|
||||
local appender-run = $(appender-runs) ;
|
||||
if $(targets[2])-defined
|
||||
{
|
||||
appender-run += [$(target-index)/$(target-count)] ;
|
||||
}
|
||||
append $(targets) : $(appender-run:J=" ") $(t) $(sources) ;
|
||||
}
|
||||
}
|
||||
|
||||
actions append
|
||||
{
|
||||
$(ECHO_CMD)-------------------------------------------------$(X)
|
||||
$(ECHO_CMD)Appender run: $(>[1])$(X)
|
||||
$(ECHO_CMD)Appender run: $(>[1])$(X)>> "$(>[2])"
|
||||
$(ECHO_CMD)Target group: $(<:J=' ')$(X)
|
||||
$(ECHO_CMD)Target group: $(<:J=' ')$(X)>> "$(>[2])"
|
||||
$(ECHO_CMD) Target: '$(>[2])'$(X)
|
||||
$(ECHO_CMD) Target: '$(>[2])'$(X)>> "$(>[2])"
|
||||
$(ECHO_CMD) Sources: '$(>[3-]:J=' ')'$(X)
|
||||
$(ECHO_CMD) Sources: '$(>[3-]:J=' ')'$(X)>> "$(>[2])"
|
||||
$(ECHO_CMD)=================================================$(X)
|
||||
$(ECHO_CMD)-------------------------------------------------$(X)>> "$(>[2])"
|
||||
}
|
||||
""")
|
||||
|
||||
|
||||
test_assigning_project_ids()
|
||||
test_assigning_using_project_ids_in_target_references()
|
||||
test_repeated_ids()
|
||||
test_unresolved_project_references()
|
||||
@@ -233,6 +233,7 @@ tests = ["absolute_sources",
|
||||
"print",
|
||||
"project_dependencies",
|
||||
"project_glob",
|
||||
"project_id",
|
||||
"project_root_constants",
|
||||
"project_root_rule",
|
||||
"project_test3",
|
||||
|
||||
Reference in New Issue
Block a user