⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 testing.jam

📁 C++的一个好库。。。现在很流行
💻 JAM
📖 第 1 页 / 共 2 页
字号:
#  (C) Copyright David Abrahams 2002. 
#  (C) Copyright Vladimir Prus 2002-2003. 
#  Permission to copy, use, modify, sell and
#  distribute this software is granted provided this copyright notice appears in
#  all copies. This software is provided "as is" without express or implied
#  warranty, and with no claim as to its suitability for any purpose.

#  This module implements regression testing framework. It declares a number of 
#  main target rules, which perform some action, and if the results are ok,
#  creates an output file.
#  
#  The exact list of rules is:
#  'compile'       -- creates .test file if compilation of sources was successfull
#  'compile-fail'  -- creates .test file if compilation of sources failed
#  'run'           -- creates .test file is running of executable produced from
#                     sources was successfull. Also leaves behing .output file
#                     with the output from program run.
#  'run-fail'      -- same as above, but .test file is created if running fails.
#
#  In all cases, presense of .test file is an incication that
#  the test passed. For more convenient reporting, you might want to use C++ Boost
#  regression testing utilities, see
#  http://www.boost.org/more/regression.html
#
#  For historical reason, a 'unit-test' rule is available which
#  has the same syntax as 'exe' and behaves just like 'run'.

# Things to do:
#  - Teach compiler_status handle Jamfile.v2.
# Notes:
#  - <no-warn> is not implemented, since in Como-specific, and it's not clear how
#     to implement it
#  - std::locale-support is not impelemted (it's used in one test).

  
import targets ;
import "class" : new ;
import property ;
import feature ;
import toolset ;
import alias ;
import type ;
import generators ;
import project ;
import property-set ;
import virtual-target ;
import path ;
import os ;
import common ;
import sequence ;
import errors ;

rule init ( ) { }

# The feature which controls the name of program used to
# lanch test programs. 
feature.feature testing.launcher : : optional free ;
feature.feature test-info : : free incidental ;
feature.feature testing.arg : : free incidental ;
feature.feature testing.input-file : : free dependency ;

# Register target types.
type.register TEST : test ;
type.register COMPILE : : TEST ;
type.register COMPILE_FAIL : : TEST ;
type.register RUN_OUTPUT : run ;
type.register RUN : : TEST ;
type.register RUN_FAIL : : TEST ;
type.register UNIT_TEST : passed : TEST ;

# Declare the rules which create main targets. 
# While the 'type' module already creates rules with the same names for us,
# we need extra convenience: default name of main target, so write
# our own versions.

# Helper rule. Create a test target, using basename of first source if no
# target name is explicitly passed. Remembers the created target in
# a global variable.
rule make-test ( target-type : sources + : requirements * : target-name ? )
{
    target-name ?= $(sources[1]:D=:S=) ;

    local project = [ project.current ] ;
    # The <location-prefix> forces the build system for generate paths in the form
    # $build_dir/array1.test/gcc/debug
    # This is necessary to allow post-processing tools to work.
    local t = 
      [ targets.create-typed-target 
          [ type.type-from-rule-name $(target-type) ] : $(project)
            : $(target-name) : $(sources) 
            : $(requirements) <location-prefix>$(target-name).test ] ;
    
    # Remember the test (for --dump-test). 
    # A good way would be to collect all given a project.
    # This has some technical problems: e.g. we can't call this dump from
    # Jamfile since projects referred by 'build-project' are not available until
    # whole Jamfile is loaded.
    .all-tests += $(t) ;
    return $(t) ;    
}

rule compile ( sources + : requirements * : target-name ? )
{    
    return [ make-test compile : $(sources) : $(requirements) : $(target-name) ] ;
}

rule compile-fail ( sources + : requirements * : target-name ? )
{    
    return [ make-test compile-fail : $(sources) : $(requirements) : $(target-name) ] ;
}

rule handle-input-files ( input-files * )
{
    if $(input-files[2])
    {
        # Check that sorting made when creating property-set instance
        # won't change the ordering.
        if [ sequence.insertion-sort $(input-files) ] != $(input-files)
        {
            errors.user-error "Names of input files must be sorted alphabetically"
              : "due to internal limitations" ;
        }        
    }
    return <testing.input-file>$(input-files) ;
}


rule run ( sources + : args * : input-files * : requirements * : target-name ? 
    : default-build * )
{      
    requirements += <testing.arg>$(args:J=" ") ;
    requirements += [ handle-input-files $(input-files) ] ;
    return [ make-test run : $(sources) : $(requirements) : $(target-name) ] ;
}

rule run-fail ( sources + : args * : input-files * : requirements * : target-name ? 
    : default-build * )
{    
    requirements += <testing.arg>$(args:J=" ") ;    
    requirements += [ handle-input-files $(input-files) ] ;
    return [ make-test run-fail : $(sources) : $(requirements) : $(target-name) ] ;
}


# Rule for grouping tests in suites.
rule test-suite ( suite-name : tests + ) 
{
    # In V2, if 'tests' are instances of 'abstract-target', they will be considered
    # 'inline-targets' and will suffer some adjustments. This will not be compatible
    # with V1 behaviour, so we get names of 'tests' and use them.
    local names ;
    for local t in $(tests)
    {
        names += [ $(t).name ] ;
    }    
    modules.call-in [ CALLER_MODULE ] : alias $(suite-name) : $(names) ;
}

# For all main target in 'project-module', 
# which are typed target with type derived from 'TEST', 
# produce some interesting information.
rule dump-tests # ( project-module )
{
    for local t in $(.all-tests)
    {
        dump-test $(t) ;
    }    
}

# Given a project location, compute the name of Boost library
local rule get-library-name ( path )
{
    # Path is in normalized form, so all slashes are forward.

    local match1 = [ MATCH /libs/(.*)/(test|example) : $(path) ] ;
    local match2 = [ MATCH /libs/(.*)$ : $(path) ] ;
    local match3 = [ MATCH (/status$) : $(path) ] ;

    if $(match1) { return $(match1[0]) ; }
    else if $(match2) { return $(match2[0]) ; }
    else if $(match3) { return "" ; }
    else if --dump-tests in [ modules.peek : ARGV ] 
    { 
        EXIT Cannot extract library name from path $(path) ; 
    }
}


# Take a target (instance of 'basic-target') and prints 
# - its type
# - its name
# - comments specified via the <test-info> property
# - relative location of all source from the project root.
rule dump-test ( target )
{
    local type = [ $(target).type ] ;
    local name = [ $(target).name ] ;
    local project = [ $(target).project ] ;
    
    local project-root = [ $(project).get project-root ] ;
    local library = [ get-library-name 
        [ path.root [ $(project).get location ] [ path.pwd ] ] ] ;
    if $(library)
    {
        name = $(library)/$(name) ;
    }
        
    local sources = [ $(target).sources ] ;
    local source-files ;
    for local s in $(sources)
    {
        if [ class.is-a $(s) : file-reference ] 
        {
            source-files += 
              [ path.relative 
                  [ path.root [ $(s).location ] [ path.pwd ] ]
                  [ path.root $(project-root) [ path.pwd ] ] ] ;
        }                
    }
          
    local r = [ $(target).requirements ] ;
    # Extract values of the <test-info> feature
    local test-info = [ $(r).get <test-info> ] ;
    
    # Format them into a single string of quoted strings
    test-info = \"$(test-info:J=\"\ \")\" ;
    
    ECHO boost-test($(type)) \"$(name)\" 
      [$(test-info)]            

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -