예제 #1
0
def check_for_existing_boost_build_jam(t):
    """
      This test depends on no boost-build.jam file existing in any of the
    folders along the current folder's path. If it does exist, not only would
    this test fail but it could point to a completely wrong Boost Build
    installation, thus causing headaches when attempting to diagnose the
    problem. That is why we explicitly check for this scenario.

    """
    problem = find_up_to_root(t.workdir, "boost-build.jam")
    if problem:
        BoostBuild.annotation(
            "misconfiguration", """\
This test expects to be run from a folder with no 'boost-build.jam' file in any
of the folders along its path.

Working folder:
  '%s'

Problematic boost-build.jam found at:
  '%s'

Please remove this file or change the test's working folder and rerun the test.
""" % (t.workdir, problem))
        t.fail_test(1, dump_stdio=False, dump_stack=False)
예제 #2
0
def test_raw_empty():
    whitespace_in = "  \n\n\r\r\v\v\t\t   \t   \r\r   \n\n"

    #   We tell the testing system to read its child process output as raw
    # binary data but the bjam process we run will read its input file and
    # write out its output as text, i.e. convert all of our "\r\n" sequences to
    # "\n" on input and all of its "\n" characters back to "\r\n" on output.
    # This means that any lone "\n" input characters not preceded by "\r" will
    # get an extra "\r" added in front of it on output.
    whitespace_out = whitespace_in.replace("\r\n", "\n").replace("\n", "\r\n")

    t = BoostBuild.Tester(["-d2", "-d+4"],
                          pass_toolset=0,
                          use_test_config=False)
    t.write(
        "file.jam", """\
actions do_empty {%s}
JAMSHELL = %% ;
do_empty all ;
""" % (whitespace_in))
    t.run_build_system(["-ffile.jam"], universal_newlines=False)
    t.expect_output_lines("do_empty all")
    t.expect_output_lines("Executing raw command directly", False)
    if "\r\n%s\r\n" % whitespace_out not in t.stdout():
        BoostBuild.annotation(
            "failure", "Whitespace action content not found "
            "on stdout.")
        t.fail_test(1, dump_difference=False)
    t.cleanup()
예제 #3
0
def test_raw_empty():
    whitespace_in = "  \n\n\r\r\v\v\t\t   \t   \r\r   \n\n"

    #   We tell the testing system to read its child process output as raw
    # binary data but the bjam process we run will read its input file and
    # write out its output as text, i.e. convert all of our "\r\n" sequences to
    # "\n" on input and all of its "\n" characters back to "\r\n" on output.
    # This means that any lone "\n" input characters not preceded by "\r" will
    # get an extra "\r" added in front of it on output.
    whitespace_out = whitespace_in.replace("\r\n", "\n").replace("\n", "\r\n")

    t = BoostBuild.Tester(["-d2", "-d+4"], pass_d0=False, pass_toolset=0,
        use_test_config=False)
    t.write("file.jam", """\
actions do_empty {%s}
JAMSHELL = %% ;
do_empty all ;
""" % (whitespace_in))
    t.run_build_system(["-ffile.jam"], universal_newlines=False)
    t.expect_output_lines("do_empty all")
    t.expect_output_lines("Executing raw command directly", False)
    if "\r\n%s\r\n" % whitespace_out not in t.stdout():
        BoostBuild.annotation("failure", "Whitespace action content not found "
            "on stdout.")
        t.fail_test(1, dump_difference=False)
    t.cleanup()
예제 #4
0
파일: startup_v2.py 프로젝트: Kirija/XPIR
def check_for_existing_boost_build_jam(t):
    """
      This test depends on no boost-build.jam file existing in any of the
    folders along the current folder's path. If it does exist, not only would
    this test fail but it could point to a completely wrong Boost Build
    installation, thus causing headaches when attempting to diagnose the
    problem. That is why we explicitly check for this scenario.

    """
    problem = find_up_to_root(t.workdir, "boost-build.jam")
    if problem:
        BoostBuild.annotation("misconfiguration", """\
This test expects to be run from a folder with no 'boost-build.jam' file in any
of the folders along its path.

Working folder:
  '%s'

Problematic boost-build.jam found at:
  '%s'

Please remove this file or change the test's working folder and rerun the test.
""" % (t.workdir, problem))
        t.fail_test(1, dump_stdio=False, dump_stack=False)
예제 #5
0
#ifdef ERROR
#error ERROR defined
#endif
#ifndef OK
#error ERROR not defined
#endif
''')

# Don't check the status immediately, so that we have a chance
# to print config.log.  Also, we need a minimum of d2 to make
# sure that we always see the commands and output.
t.run_build_system(['-sOBJECT_FILE=' + linker_input, '-d2'], status=None)

if t.status != 0:
    log_file = t.read('bin/config.log')
    BoostBuild.annotation("config.log", log_file)
    t.fail_test(True)

t.expect_output_lines(['    - has --illegal-flag-cpp   : no*',
                       '    - has -DMACRO_CPP          : yes*',
                       '    - has --illegal-flag-c     : no*',
                       '    - has -DMACRO_C            : yes*',
                       '    - has --illegal-flag-link  : no*',
                       '    - has *bin*/input.* : yes*'])
t.expect_addition('bin/$toolset/debug*/fail_cpp.obj')
t.expect_addition('bin/$toolset/debug*/pass_cpp.obj')
t.expect_addition('bin/$toolset/debug*/fail_c.obj')
t.expect_addition('bin/$toolset/debug*/pass_c.obj')
t.expect_addition('bin/$toolset/debug*/fail_link.obj')
t.expect_addition('bin/$toolset/debug*/pass_link.obj')
예제 #6
0
def _info(*values):
    values = list(values) + [""]
    BoostBuild.annotation(tag, "\n".join(str(x) for x in values))
예제 #7
0
    typedef void type;
};
typedef time_waster<true, 10, void>::type type;
int g() { return 0; }
""")

tester.write("jamroot.jam", """\
obj test2 : test2.cpp ;
obj test1 : test1.cpp : <dependency>test2 ;
install test2i : test2 : <dependency>test1 ;
""")

tester.run_build_system()
tester.expect_addition("bin/$toolset/debug*/test2.obj")
tester.expect_addition("bin/$toolset/debug*/test1.obj")
tester.expect_addition("test2i/test2.obj")
tester.expect_nothing_more()

test2src = tester.read("test2i/test2.obj")
test2dest = tester.read("bin/$toolset/debug*/test2.obj")
if test2src != test2dest:
    BoostBuild.annotation("failure", "The object file was not copied "
        "correctly")
    tester.fail_test(1)

tester.run_build_system(["-d1"])
tester.expect_output_lines("common.copy*", False)
tester.expect_nothing_more()

tester.cleanup()
예제 #8
0
def test_raw_nt(n=None, error=False):
    t = BoostBuild.Tester(["-d1", "-d+4"], pass_d0=False, pass_toolset=0,
        use_test_config=False)

    cmd_prefix = "%s -c \"print('XXX: " % executable
    cmd_suffix = "')\""
    cmd_extra_length = len(cmd_prefix) + len(cmd_suffix)

    if n == None:
        n = cmd_extra_length

    data_length = n - cmd_extra_length
    if data_length < 0:
        BoostBuild.annotation("failure", """\
Can not construct Windows command of desired length. Requested command length
too short for the current test configuration.
    Requested command length: %d
    Minimal supported command length: %d
""" % (n, cmd_extra_length))
        t.fail_test(1, dump_difference=False)

    #   Each $(Xx10-1) variable contains X words of 9 characters each, which,
    # including spaces between words, brings the total number of characters in
    # its string representation to X * 10 - 1 (X * 9 characters + (X - 1)
    # spaces).
    t.write("file.jam", """\
ten = 0 1 2 3 4 5 6 7 8 9 ;

1x10-1 = 123456789 ;
10x10-1 = $(ten)12345678 ;
100x10-1 = $(ten)$(ten)1234567 ;
1000x10-1 = $(ten)$(ten)$(ten)123456 ;

actions do_echo
{
    %s%s%s
}
JAMSHELL = %% ;
do_echo all ;
""" % (cmd_prefix, string_of_length(data_length), cmd_suffix))
    if error:
        expected_status = 1
    else:
        expected_status = 0
    t.run_build_system(["-ffile.jam"], status=expected_status)
    if error:
        t.expect_output_lines("Executing raw command directly", False)
        t.expect_output_lines("do_echo action is too long (%d, max 32766):" % n
            )
        t.expect_output_lines("XXX: *", False)
    else:
        t.expect_output_lines("Executing raw command directly")
        t.expect_output_lines("do_echo action is too long*", False)

        m = re.search("^XXX: (.*)$", t.stdout(), re.MULTILINE)
        if not m:
            BoostBuild.annotation("failure", "Expected output line starting "
                "with 'XXX: ' not found.")
            t.fail_test(1, dump_difference=False)
        if len(m.group(1)) != data_length:
            BoostBuild.annotation("failure", """Unexpected output data length.
    Expected: %d
    Received: %d""" % (n, len(m.group(1))))
            t.fail_test(1, dump_difference=False)

    t.cleanup()
예제 #9
0
 def __assertionFailure(self, message):
     BoostBuild.annotation("failure", "Internal test assertion failure "
                                      "- %s" % message)
     self.__tester.fail_test(1)
def test_basic():
    t = BoostBuild.Tester(pass_d0=False)
    __write_appender(t, "appender.jam")
    t.write("a.cpp", "")
    t.write("b.cxx", "")
    t.write("c.tui", "")
    t.write("d.wd", "")
    t.write("e.cpp", "")
    t.write("x.l", "")
    t.write("y.x_pro", "")
    t.write("z.cpp", "")
    t.write("lib/c.cpp", "int bar() { return 0; }\n")
    t.write("lib/jamfile.jam", "my-lib auxilliary : c.cpp ;")
    t.write(
        "jamroot.jam", r"""import appender ;
            
            import "class" : new ;
            import generators ;
            import type ;
            
            
            ################################################################################
            #
            #   We use our own custom EXE, LIB & OBJ target generators as using the regular
            # ones would force us to have to deal with different compiler/linker specific
            # 'features' that really have nothing to do with this test. For example, IBM XL
            # C/C++ for AIX, V12.1 (Version: 12.01.0000.0000) compiler exits with a non-zero
            # exit code and thus fails our build when run with a source file using an
            # unknown suffix like '.marked_cpp'.
            #
            ################################################################################
            
            type.register MY_EXE : my_exe ;
            type.register MY_LIB : my_lib ;
            type.register MY_OBJ : my_obj ;
            
            appender.register compile-c : C : MY_OBJ ;
            appender.register compile-cpp : CPP : MY_OBJ ;
            appender.register link-lib composing : MY_OBJ : MY_LIB ;
            appender.register link-exe composing : MY_OBJ MY_LIB : MY_EXE ;
            
            
            ################################################################################
            #
            # LEX --> C
            #
            ################################################################################
            
            type.register LEX : l ;
            
            appender.register lex-to-c : LEX : C ;
            
            
            ################################################################################
            #
            #        /--> tUI_H --\
            # tUI --<              >--> CPP
            #        \------------/
            #
            ################################################################################
            
            type.register tUI : tui ;
            type.register tUI_H : tui_h ;
            
            appender.register ui-to-cpp : tUI tUI_H : CPP ;
            appender.register ui-to-h : tUI : tUI_H ;
            
            
            ################################################################################
            #
            #          /--> X1 --\
            # X_PRO --<           >--> CPP
            #          \--> X2 --/
            #
            ################################################################################
            
            type.register X1 : x1 ;
            type.register X2 : x2 ;
            type.register X_PRO : x_pro ;
            
            appender.register x1-x2-to-cpp : X1 X2 : CPP ;
            appender.register x-pro-to-x1-x2 : X_PRO : X1 X2 ;
            
            
            ################################################################################
            #
            #   When the main target type is NM_EXE, build OBJ from CPP-MARKED and not from
            # anything else, e.g. directly from CPP.
            #
            ################################################################################
            
            type.register CPP_MARKED : marked_cpp : CPP ;
            type.register POSITIONS : positions ;
            type.register NM.TARGET.CPP : target_cpp : CPP ;
            type.register NM_EXE : : MY_EXE ;
            
            appender.register marked-to-target-cpp : CPP_MARKED : NM.TARGET.CPP ;
            appender.register cpp-to-marked-positions : CPP : CPP_MARKED POSITIONS ;
            
            class nm::target::cpp-obj-generator : generator
            {
                rule __init__ ( id )
                {
                    generator.__init__ $(id) : NM.TARGET.CPP : MY_OBJ ;
                    generator.set-rule-name appender.appender ;
                }
            
                rule requirements ( )
                {
                    return <main-target-type>NM_EXE ;
                }
            
                rule run ( project name ? : properties * : source : multiple ? )
                {
                    if [ $(source).type ] = CPP
                    {
                        local converted = [ generators.construct $(project) : NM.TARGET.CPP
                            : $(properties) : $(source) ] ;
                        if $(converted)
                        {
                            return [ generators.construct $(project) : MY_OBJ :
                                $(properties) : $(converted[2]) ] ;
                        }
                    }
                }
            }
            generators.register [ new nm::target::cpp-obj-generator target-obj ] ;
            generators.override target-obj : all ;
            
            
            ################################################################################
            #
            # A more complex test case scenario with the following generators:
            #  1. WHL --> CPP, WHL_LR0, H, H(%_symbols)
            #  2. DLP --> CPP
            #  3. WD --> WHL(%_parser) DLP(%_lexer)
            #  4. A custom generator of higher priority than generators 1. & 2. that helps
            #     disambiguate between them when generating CPP files from WHL and DLP
            #     sources.
            #
            ################################################################################
            
            type.register WHL : whl ;
            type.register DLP : dlp ;
            type.register WHL_LR0 : lr0 ;
            type.register WD : wd ;
            
            local whale-generator-id = [ appender.register whale : WHL : CPP WHL_LR0 H
                H(%_symbols) ] ;
            local dolphin-generator-id = [ appender.register dolphin : DLP : CPP ] ;
            appender.register wd : WD : WHL(%_parser) DLP(%_lexer) ;
            
            class wd-to-cpp : generator
            {
                rule __init__ ( id : sources * : targets * )
                {
                    generator.__init__ $(id) : $(sources) : $(targets) ;
                }
            
                rule run ( project name ? : property-set : source )
                {
                    local new-sources = $(source) ;
                    if ! [ $(source).type ] in WHL DLP
                    {
                        local r1 = [ generators.construct $(project) $(name) : WHL :
                            $(property-set) : $(source) ] ;
                        local r2 = [ generators.construct $(project) $(name) : DLP :
                            $(property-set) : $(source) ] ;
                        new-sources = [ sequence.unique $(r1[2-]) $(r2[2-]) ] ;
                    }
            
                    local result ;
                    for local i in $(new-sources)
                    {
                        local t = [ generators.construct $(project) $(name) : CPP :
                            $(property-set) : $(i) ] ;
                        result += $(t[2-]) ;
                    }
                    return $(result) ;
                }
            }
            generators.override $(__name__).wd-to-cpp : $(whale-generator-id) ;
            generators.override $(__name__).wd-to-cpp : $(dolphin-generator-id) ;
            generators.register [ new wd-to-cpp $(__name__).wd-to-cpp : : CPP ] ;
            
            
            ################################################################################
            #
            # Declare build targets.
            #
            ################################################################################
            
            # This should not cause two CPP --> MY_OBJ constructions for a.cpp or b.cpp.
            my-exe a : a.cpp b.cxx obj_1 obj_2 c.tui d.wd x.l y.x_pro lib//auxilliary ;
            my-exe f : a.cpp b.cxx obj_1 obj_2 lib//auxilliary ;
            
            # This should cause two CPP --> MY_OBJ constructions for z.cpp.
            my-obj obj_1 : z.cpp ;
            my-obj obj_2 : z.cpp ;
            
            nm-exe e : e.cpp ;
            """)

    t.run_build_system()
    t.expect_addition("bin/$toolset/debug/" * BoostBuild.List(
        "a.my_exe "
        "a.my_obj b.my_obj c.tui_h c.cpp c.my_obj d_parser.whl d_lexer.dlp "
        "d_parser.cpp d_lexer.cpp d_lexer.my_obj d_parser.lr0 d_parser.h "
        "d_parser.my_obj d_parser_symbols.h x.c x.my_obj y.x1 y.x2 y.cpp "
        "y.my_obj e.marked_cpp e.positions e.target_cpp e.my_obj e.my_exe "
        "f.my_exe obj_1.my_obj obj_2.my_obj"))
    t.expect_addition("lib/bin/$toolset/debug/" *
                      BoostBuild.List("c.my_obj "
                                      "auxilliary.my_lib"))
    t.expect_nothing_more()

    folder = "bin/$toolset/debug"
    t.expect_content_lines("%s/obj_1.my_obj" % folder, "     Sources: 'z.cpp'")
    t.expect_content_lines("%s/obj_2.my_obj" % folder, "     Sources: 'z.cpp'")
    t.expect_content_lines("%s/a.my_obj" % folder, "     Sources: 'a.cpp'")

    lines = t.stdout().splitlines()
    source_lines = [x for x in lines if re.match("^     Sources: '", x)]
    if not __match_count_is(source_lines, "'z.cpp'", 2):
        BoostBuild.annotation("failure", "z.cpp must be compiled exactly "
                              "twice.")
        t.fail_test(1)
    if not __match_count_is(source_lines, "'a.cpp'", 1):
        BoostBuild.annotation("failure", "a.cpp must be compiled exactly "
                              "once.")
        t.fail_test(1)
    t.cleanup()
예제 #11
0
def run_tests(critical_tests, other_tests):
    """
      Runs first the critical_tests and then the other_tests.

      Writes the name of the first failed test to test_results.txt. Critical
    tests are run in the specified order, other tests are run starting with the
    one that failed first on the last test run.

    """
    last_failed = last_failed_test()
    other_tests = reorder_tests(other_tests, last_failed)
    all_tests = critical_tests + other_tests

    invocation_dir = os.getcwd()
    max_test_name_len = 10
    for x in all_tests:
        if len(x) > max_test_name_len:
            max_test_name_len = len(x)

    pass_count = 0
    failures_count = 0

    for test in all_tests:
        if not xml:
            print ("%%-%ds :" % max_test_name_len % test),

        passed = 0
        try:
            __import__(test)
            passed = 1
        except KeyboardInterrupt:
            """This allows us to abort the testing manually using Ctrl-C."""
            raise
        except SystemExit:
            """This is the regular way our test scripts are supposed to report
            test failures."""
        except:
            exc_type, exc_value, exc_tb = sys.exc_info()
            try:
                BoostBuild.annotation("failure - unhandled exception", "%s - " "%s" % (exc_type.__name__, exc_value))
                BoostBuild.annotate_stack_trace(exc_tb)
            finally:
                #   Explicitly clear a hard-to-garbage-collect traceback
                # related reference cycle as per documented sys.exc_info()
                # usage suggestion.
                del exc_tb

        if passed:
            pass_count += 1
        else:
            failures_count += 1
            if failures_count == 1:
                f = open(os.path.join(invocation_dir, "test_results.txt"), "w")
                try:
                    f.write(test)
                finally:
                    f.close()

        #   Restore the current directory, which might have been changed by the
        # test.
        os.chdir(invocation_dir)

        if not xml:
            if passed:
                print ("PASSED")
            else:
                print ("FAILED")
        else:
            rs = "succeed"
            if not passed:
                rs = "fail"
            print """
<test-log library="build" test-name="%s" test-type="run" toolset="%s" test-program="%s" target-directory="%s">
<run result="%s">""" % (
                test,
                toolset,
                "tools/build/v2/test/" + test + ".py",
                "boost/bin.v2/boost.build.tests/" + toolset + "/" + test,
                rs,
            )
            if not passed:
                BoostBuild.flush_annotations(1)
            print """
</run>
</test-log>
"""
        sys.stdout.flush()  # Makes testing under emacs more entertaining.
        BoostBuild.clear_annotations()

    # Erase the file on success.
    if failures_count == 0:
        open("test_results.txt", "w").close()

    if not xml:
        print """
        === Test summary ===
        PASS: %d
        FAIL: %d
        """ % (
            pass_count,
            failures_count,
        )
예제 #12
0
파일: test_all.py 프로젝트: zha0/openedr
def run_tests(critical_tests, other_tests):
    """
      Runs first the critical_tests and then the other_tests.

      Writes the name of the first failed test to test_results.txt. Critical
    tests are run in the specified order, other tests are run starting with the
    one that failed first on the last test run.

    """
    last_failed = last_failed_test()
    other_tests = reorder_tests(other_tests, last_failed)
    all_tests = critical_tests + other_tests

    invocation_dir = os.getcwd()
    max_test_name_len = 10
    for x in all_tests:
        if len(x) > max_test_name_len:
            max_test_name_len = len(x)

    pass_count = 0
    failures_count = 0

    for test in all_tests:
        if not xml:
            print("%%-%ds :" % max_test_name_len % test),

        passed = 0
        try:
            __import__(test)
            passed = 1
        except KeyboardInterrupt:
            """This allows us to abort the testing manually using Ctrl-C."""
            raise
        except SystemExit:
            """This is the regular way our test scripts are supposed to report
            test failures."""
        except:
            exc_type, exc_value, exc_tb = sys.exc_info()
            try:
                BoostBuild.annotation(
                    "failure - unhandled exception", "%s - "
                    "%s" % (exc_type.__name__, exc_value))
                BoostBuild.annotate_stack_trace(exc_tb)
            finally:
                #   Explicitly clear a hard-to-garbage-collect traceback
                # related reference cycle as per documented sys.exc_info()
                # usage suggestion.
                del exc_tb

        if passed:
            pass_count += 1
        else:
            failures_count += 1
            if failures_count == 1:
                f = open(os.path.join(invocation_dir, "test_results.txt"), "w")
                try:
                    f.write(test)
                finally:
                    f.close()

        #   Restore the current directory, which might have been changed by the
        # test.
        os.chdir(invocation_dir)

        if not xml:
            if passed:
                print("PASSED")
            else:
                print("FAILED")
                BoostBuild.flush_annotations()
        else:
            rs = "succeed"
            if not passed:
                rs = "fail"
            print """
<test-log library="build" test-name="%s" test-type="run" toolset="%s" test-program="%s" target-directory="%s">
<run result="%s">""" % (test, toolset, "tools/build/v2/test/" + test + ".py",
                        "boost/bin.v2/boost.build.tests/" + toolset + "/" +
                        test, rs)
            if not passed:
                BoostBuild.flush_annotations(1)
            print """
</run>
</test-log>
"""
        sys.stdout.flush()  # Makes testing under emacs more entertaining.
        BoostBuild.clear_annotations()

    # Erase the file on success.
    if failures_count == 0:
        open("test_results.txt", "w").close()

    if not xml:
        print """
        === Test summary ===
        PASS: %d
        FAIL: %d
        """ % (pass_count, failures_count)

    # exit with failure with failures
    if failures_count > 0:
        sys.exit(1)
예제 #13
0
tester.write(
    "jamroot.jam", """
obj test2 : test2.cpp ;
obj test1 : test1.cpp : <dependency>test2 ;
install test2i : test2 : <dependency>test1 ;
""")

tester.run_build_system()

tester.expect_addition("bin/$toolset/debug/test2.obj")
tester.expect_addition("bin/$toolset/debug/test1.obj")
tester.expect_addition("test2i/test2.obj")
tester.expect_nothing_more()

test2src = tester.read("test2i/test2.obj")
test2dest = tester.read("bin/$toolset/debug/test2.obj")

if test2src != test2dest:
    BoostBuild.annotation("failure",
                          "The object file was not copied correctly")
    tester.fail_test(1)

del test2src
del test2dest

tester.run_build_system("-d1")
tester.expect_output_line("common.copy*", expected_to_exist=False)
tester.expect_nothing_more()

tester.cleanup()
예제 #14
0
def test_basic():
    t = BoostBuild.Tester(pass_d0=False)
    __write_appender(t, "appender.jam")
    t.write("a.cpp", "")
    t.write("b.cxx", "")
    t.write("c.tui", "")
    t.write("d.wd", "")
    t.write("e.cpp", "")
    t.write("x.l", "")
    t.write("y.x_pro", "")
    t.write("z.cpp", "")
    t.write("lib/c.cpp", "int bar() { return 0; }\n")
    t.write("lib/jamfile.jam", "my-lib auxilliary : c.cpp ;")
    t.write("jamroot.jam",
r"""import appender ;

import "class" : new ;
import generators ;
import type ;


################################################################################
#
#   We use our own custom EXE, LIB & OBJ target generators as using the regular
# ones would force us to have to deal with different compiler/linker specific
# 'features' that really have nothing to do with this test. For example, IBM XL
# C/C++ for AIX, V12.1 (Version: 12.01.0000.0000) compiler exits with a non-zero
# exit code and thus fails our build when run with a source file using an
# unknown suffix like '.marked_cpp'.
#
################################################################################

type.register MY_EXE : my_exe ;
type.register MY_LIB : my_lib ;
type.register MY_OBJ : my_obj ;

appender.register compile-c : C : MY_OBJ ;
appender.register compile-cpp : CPP : MY_OBJ ;
appender.register link-lib composing : MY_OBJ : MY_LIB ;
appender.register link-exe composing : MY_OBJ MY_LIB : MY_EXE ;


################################################################################
#
# LEX --> C
#
################################################################################

type.register LEX : l ;

appender.register lex-to-c : LEX : C ;


################################################################################
#
#        /--> tUI_H --\
# tUI --<              >--> CPP
#        \------------/
#
################################################################################

type.register tUI : tui ;
type.register tUI_H : tui_h ;

appender.register ui-to-cpp : tUI tUI_H : CPP ;
appender.register ui-to-h : tUI : tUI_H ;


################################################################################
#
#          /--> X1 --\
# X_PRO --<           >--> CPP
#          \--> X2 --/
#
################################################################################

type.register X1 : x1 ;
type.register X2 : x2 ;
type.register X_PRO : x_pro ;

appender.register x1-x2-to-cpp : X1 X2 : CPP ;
appender.register x-pro-to-x1-x2 : X_PRO : X1 X2 ;


################################################################################
#
#   When the main target type is NM_EXE, build OBJ from CPP-MARKED and not from
# anything else, e.g. directly from CPP.
#
################################################################################

type.register CPP_MARKED : marked_cpp : CPP ;
type.register POSITIONS : positions ;
type.register NM.TARGET.CPP : target_cpp : CPP ;
type.register NM_EXE : : MY_EXE ;

appender.register marked-to-target-cpp : CPP_MARKED : NM.TARGET.CPP ;
appender.register cpp-to-marked-positions : CPP : CPP_MARKED POSITIONS ;

class nm::target::cpp-obj-generator : generator
{
    rule __init__ ( id )
    {
        generator.__init__ $(id) : NM.TARGET.CPP : MY_OBJ ;
        generator.set-rule-name appender.appender ;
    }

    rule requirements ( )
    {
        return <main-target-type>NM_EXE ;
    }

    rule run ( project name ? : properties * : source : multiple ? )
    {
        if [ $(source).type ] = CPP
        {
            local converted = [ generators.construct $(project) : NM.TARGET.CPP
                : $(properties) : $(source) ] ;
            if $(converted)
            {
                return [ generators.construct $(project) : MY_OBJ :
                    $(properties) : $(converted[2]) ] ;
            }
        }
    }
}
generators.register [ new nm::target::cpp-obj-generator target-obj ] ;
generators.override target-obj : all ;


################################################################################
#
# A more complex test case scenario with the following generators:
#  1. WHL --> CPP, WHL_LR0, H, H(%_symbols)
#  2. DLP --> CPP
#  3. WD --> WHL(%_parser) DLP(%_lexer)
#  4. A custom generator of higher priority than generators 1. & 2. that helps
#     disambiguate between them when generating CPP files from WHL and DLP
#     sources.
#
################################################################################

type.register WHL : whl ;
type.register DLP : dlp ;
type.register WHL_LR0 : lr0 ;
type.register WD : wd ;

local whale-generator-id = [ appender.register whale : WHL : CPP WHL_LR0 H
    H(%_symbols) ] ;
local dolphin-generator-id = [ appender.register dolphin : DLP : CPP ] ;
appender.register wd : WD : WHL(%_parser) DLP(%_lexer) ;

class wd-to-cpp : generator
{
    rule __init__ ( id : sources * : targets * )
    {
        generator.__init__ $(id) : $(sources) : $(targets) ;
    }

    rule run ( project name ? : property-set : source )
    {
        local new-sources = $(source) ;
        if ! [ $(source).type ] in WHL DLP
        {
            local r1 = [ generators.construct $(project) $(name) : WHL :
                $(property-set) : $(source) ] ;
            local r2 = [ generators.construct $(project) $(name) : DLP :
                $(property-set) : $(source) ] ;
            new-sources = [ sequence.unique $(r1[2-]) $(r2[2-]) ] ;
        }

        local result ;
        for local i in $(new-sources)
        {
            local t = [ generators.construct $(project) $(name) : CPP :
                $(property-set) : $(i) ] ;
            result += $(t[2-]) ;
        }
        return $(result) ;
    }
}
generators.override $(__name__).wd-to-cpp : $(whale-generator-id) ;
generators.override $(__name__).wd-to-cpp : $(dolphin-generator-id) ;
generators.register [ new wd-to-cpp $(__name__).wd-to-cpp : : CPP ] ;


################################################################################
#
# Declare build targets.
#
################################################################################

# This should not cause two CPP --> MY_OBJ constructions for a.cpp or b.cpp.
my-exe a : a.cpp b.cxx obj_1 obj_2 c.tui d.wd x.l y.x_pro lib//auxilliary ;
my-exe f : a.cpp b.cxx obj_1 obj_2 lib//auxilliary ;

# This should cause two CPP --> MY_OBJ constructions for z.cpp.
my-obj obj_1 : z.cpp ;
my-obj obj_2 : z.cpp ;

nm-exe e : e.cpp ;
""")

    t.run_build_system()
    t.expect_addition("bin/$toolset/debug/" * BoostBuild.List("a.my_exe "
        "a.my_obj b.my_obj c.tui_h c.cpp c.my_obj d_parser.whl d_lexer.dlp "
        "d_parser.cpp d_lexer.cpp d_lexer.my_obj d_parser.lr0 d_parser.h "
        "d_parser.my_obj d_parser_symbols.h x.c x.my_obj y.x1 y.x2 y.cpp "
        "y.my_obj e.marked_cpp e.positions e.target_cpp e.my_obj e.my_exe "
        "f.my_exe obj_1.my_obj obj_2.my_obj"))
    t.expect_addition("lib/bin/$toolset/debug/" * BoostBuild.List("c.my_obj "
        "auxilliary.my_lib"))
    t.expect_nothing_more()

    folder = "bin/$toolset/debug"
    t.expect_content_lines("%s/obj_1.my_obj" % folder, "     Sources: 'z.cpp'")
    t.expect_content_lines("%s/obj_2.my_obj" % folder, "     Sources: 'z.cpp'")
    t.expect_content_lines("%s/a.my_obj" % folder, "     Sources: 'a.cpp'")

    lines = t.stdout().splitlines()
    source_lines = [x for x in lines if re.match("^     Sources: '", x)]
    if not __match_count_is(source_lines, "'z.cpp'", 2):
        BoostBuild.annotation("failure", "z.cpp must be compiled exactly "
            "twice.")
        t.fail_test(1)
    if not __match_count_is(source_lines, "'a.cpp'", 1):
        BoostBuild.annotation("failure", "a.cpp must be compiled exactly "
            "once.")
        t.fail_test(1)
    t.cleanup()
def _info(*values):
    values = list(values) + [""]
    BoostBuild.annotation(tag, "\n".join(str(x) for x in values))
예제 #16
0
def test_raw_nt(n=None, error=False):
    t = BoostBuild.Tester(["-d1", "-d+4"],
                          pass_toolset=0,
                          use_test_config=False)

    cmd_prefix = "%s -c \"print('XXX: " % executable
    cmd_suffix = "')\""
    cmd_extra_length = len(cmd_prefix) + len(cmd_suffix)

    if n == None:
        n = cmd_extra_length

    data_length = n - cmd_extra_length
    if data_length < 0:
        BoostBuild.annotation(
            "failure", """\
Can not construct Windows command of desired length. Requested command length
too short for the current test configuration.
    Requested command length: %d
    Minimal supported command length: %d
""" % (n, cmd_extra_length))
        t.fail_test(1, dump_difference=False)

    #   Each $(Xx10-1) variable contains X words of 9 characters each, which,
    # including spaces between words, brings the total number of characters in
    # its string representation to X * 10 - 1 (X * 9 characters + (X - 1)
    # spaces).
    t.write(
        "file.jam", """\
ten = 0 1 2 3 4 5 6 7 8 9 ;

1x10-1 = 123456789 ;
10x10-1 = $(ten)12345678 ;
100x10-1 = $(ten)$(ten)1234567 ;
1000x10-1 = $(ten)$(ten)$(ten)123456 ;

actions do_echo
{
    %s%s%s
}
JAMSHELL = %% ;
do_echo all ;
""" % (cmd_prefix, string_of_length(data_length), cmd_suffix))
    if error:
        expected_status = 1
    else:
        expected_status = 0
    t.run_build_system(["-ffile.jam"], status=expected_status)
    if error:
        t.expect_output_lines("Executing raw command directly", False)
        t.expect_output_lines("do_echo action is too long (%d, max 32766):" %
                              n)
        t.expect_output_lines("XXX: *", False)
    else:
        t.expect_output_lines("Executing raw command directly")
        t.expect_output_lines("do_echo action is too long*", False)

        m = re.search("^XXX: (.*)$", t.stdout(), re.MULTILINE)
        if not m:
            BoostBuild.annotation(
                "failure", "Expected output line starting "
                "with 'XXX: ' not found.")
            t.fail_test(1, dump_difference=False)
        if len(m.group(1)) != data_length:
            BoostBuild.annotation(
                "failure", """Unexpected output data length.
    Expected: %d
    Received: %d""" % (n, len(m.group(1))))
            t.fail_test(1, dump_difference=False)

    t.cleanup()
예제 #17
0
 def __assertionFailure(self, message):
     BoostBuild.annotation("failure", "Internal test assertion failure "
         "- %s" % message)
     self.__tester.fail_test(1)
예제 #18
0
#ifdef ERROR
#error ERROR defined
#endif
#ifndef OK
#error ERROR not defined
#endif
''')

# Don't check the status immediately, so that we have a chance
# to print config.log.  Also, we need a minimum of d2 to make
# sure that we always see the commands and output.
t.run_build_system(['-sOBJECT_FILE=' + linker_input, '-d2'], status=None)

if t.status != 0:
    log_file = t.read('bin/config.log')
    BoostBuild.annotation("config.log", log_file)
    t.fail_test(True)

t.expect_output_lines(['    - has --illegal-flag-cpp   : no',
                       '    - has -DMACRO_CPP          : yes',
                       '    - has --illegal-flag-c     : no',
                       '    - has -DMACRO_C            : yes',
                       '    - has --illegal-flag-link  : no',
                       '    - has *bin*/input.* : yes'])
t.expect_addition('bin/$toolset/debug*/fail_cpp.obj')
t.expect_addition('bin/$toolset/debug*/pass_cpp.obj')
t.expect_addition('bin/$toolset/debug*/fail_c.obj')
t.expect_addition('bin/$toolset/debug*/pass_c.obj')
t.expect_addition('bin/$toolset/debug*/fail_link.obj')
t.expect_addition('bin/$toolset/debug*/pass_link.obj')