2020-04-22 17:38:25 +02:00
# Copyright 2020 MongoDB Inc.
2020-01-07 19:48:42 +01:00
#
2020-04-22 17:38:25 +02:00
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
2020-01-07 19:48:42 +01:00
#
2020-04-22 17:38:25 +02:00
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2020-01-07 19:48:42 +01:00
#
import os
2021-08-04 23:11:45 +02:00
import SCons
2020-01-07 19:48:42 +01:00
2022-08-05 07:24:49 +02:00
from SCons . Node . Alias import default_ans
2021-08-04 23:11:45 +02:00
import auto_install_binaries
_proof_scanner_cache_key = " proof_scanner_cache "
_associated_proof = " associated_proof_key "
2022-05-25 00:55:22 +02:00
2021-08-04 23:11:45 +02:00
def proof_generator_command_scanner_func ( node , env , path ) :
results = getattr ( node . attributes , _proof_scanner_cache_key , None )
if results is not None :
return results
results = env . GetTransitivelyInstalledFiles ( node )
setattr ( node . attributes , _proof_scanner_cache_key , results )
return results
2022-05-25 00:55:22 +02:00
2021-08-04 23:11:45 +02:00
proof_generator_command_scanner = SCons . Scanner . Scanner (
function = proof_generator_command_scanner_func ,
path_function = None ,
recursive = True ,
)
2022-05-25 00:55:22 +02:00
2021-08-04 23:11:45 +02:00
def auto_prove_task ( env , component , role ) :
entry = auto_install_binaries . get_alias_map_entry ( env , component , role )
return [
getattr ( f . attributes , _associated_proof ) for f in entry . files
if hasattr ( f . attributes , _associated_proof )
]
2020-04-28 20:25:40 +02:00
2022-05-25 00:55:22 +02:00
2021-08-04 23:11:45 +02:00
def generate_test_execution_aliases ( env , test ) :
2020-04-28 20:25:40 +02:00
installed = [ test ]
if env . get ( " AUTO_INSTALL_ENABLED " , False ) and env . GetAutoInstalledFiles ( test ) :
installed = env . GetAutoInstalledFiles ( test )
2020-01-07 19:48:42 +01:00
2021-08-04 23:11:45 +02:00
target_name = os . path . basename ( installed [ 0 ] . path )
2022-05-12 22:42:32 +02:00
test_env = env . Clone ( )
test_env [ ' ENV ' ] [ ' TMPDIR ' ] = test_env . Dir ( ' $LOCAL_TMPDIR ' ) . abspath
target_command = test_env . Command (
2021-08-04 23:11:45 +02:00
target = f " #+ { target_name } " ,
source = installed [ 0 ] ,
action = " $( $ICERUN $) $ {SOURCES[0]} $UNITTEST_FLAGS " ,
2020-01-07 19:48:42 +01:00
NINJA_POOL = " console " ,
)
2021-08-04 23:11:45 +02:00
env . Pseudo ( target_command )
env . Alias ( " test-execution-aliases " , target_command )
2020-01-07 19:48:42 +01:00
for source in test . sources :
source_base_name = os . path . basename ( source . get_path ( ) )
# Strip suffix
dot_idx = source_base_name . rfind ( " . " )
suffix = source_base_name [ dot_idx : ]
2021-05-06 02:12:00 +02:00
if suffix in env [ " TEST_EXECUTION_SUFFIX_DENYLIST " ] :
2020-01-07 19:48:42 +01:00
continue
source_name = source_base_name [ : dot_idx ]
2022-05-04 16:53:36 +02:00
# We currently create two types of commands: legacy and verbose
# ex legacy command: cancelable_operation_context_test
# ex verbose command: db_unittest_test_cancelable_operation_context_test
# i.e. Verbose incorporates the name of the unittest binary, while
# legacy only has the source file name.
# We always create the verbose command, but we only create the legacy
# command if there isn't a conflict between the target_name and
# source_name. Legacy commands must be unique
2022-05-12 22:42:32 +02:00
verbose_source_command = test_env . Command (
2022-05-04 16:53:36 +02:00
target = f " #+ { target_name } - { source_name } " ,
2021-08-04 23:11:45 +02:00
source = installed [ 0 ] ,
action =
" $( $ICERUN $) $ {SOURCES[0]} -fileNameFilter $TEST_SOURCE_FILE_NAME $UNITTEST_FLAGS " ,
2020-01-07 19:48:42 +01:00
TEST_SOURCE_FILE_NAME = source_name ,
NINJA_POOL = " console " ,
)
2022-05-04 16:53:36 +02:00
env . Pseudo ( verbose_source_command )
env . Alias ( ' test-execution-aliases ' , verbose_source_command )
if target_name == source_name :
continue
2022-08-05 07:24:49 +02:00
if default_ans . lookup ( f ' + { source_name } ' ) is not None :
2022-05-04 16:53:36 +02:00
raise SCons . Errors . BuildError (
2022-08-05 07:24:49 +02:00
str ( verbose_source_command [ 0 ] ) ,
f " There exists multiple unittests with a source file named { source_name } : { source . abspath } and { env . Alias ( f ' + { source_name } ' ) [ 0 ] . children ( ) [ 1 ] . abspath } "
2022-05-04 16:53:36 +02:00
)
2022-08-05 07:24:49 +02:00
env . Alias ( f ' + { source_name } ' , [ verbose_source_command , source ] )
2021-08-04 23:11:45 +02:00
2022-05-12 22:42:32 +02:00
proof_generator_command = test_env . Command (
2021-08-04 23:11:45 +02:00
target = [
' $ {SOURCE} .log ' ,
' $ {SOURCE} .status ' ,
] ,
source = installed [ 0 ] ,
action = SCons . Action . Action ( " $PROOF_GENERATOR_COMMAND " , " $PROOF_GENERATOR_COMSTR " ) ,
source_scanner = proof_generator_command_scanner ,
)
# We assume tests are provable by default, but some tests may not
# be. Such tests can be tagged with UNDECIDABLE_TEST=True. If a
# test isn't provable, we disable caching its results and require
# it to be always rebuilt.
if installed [ 0 ] . env . get ( ' UNDECIDABLE_TEST ' , False ) :
env . NoCache ( proof_generator_command )
env . AlwaysBuild ( proof_generator_command )
2022-05-12 22:42:32 +02:00
proof_analyzer_command = test_env . Command (
2021-08-04 23:11:45 +02:00
target = ' $ {SOURCES[1].base} .proof ' ,
source = proof_generator_command ,
action = SCons . Action . Action ( " $PROOF_ANALYZER_COMMAND " , " $PROOF_ANALYZER_COMSTR " ) ,
)
proof_analyzer_alias = env . Alias (
f " prove- { target_name } " ,
proof_analyzer_command ,
)
2020-01-07 19:48:42 +01:00
2021-08-04 23:11:45 +02:00
setattr ( installed [ 0 ] . attributes , _associated_proof , proof_analyzer_alias )
2020-01-07 19:48:42 +01:00
2021-08-04 23:11:45 +02:00
# TODO: Should we enable proof at the file level?
2020-01-07 19:48:42 +01:00
2022-05-25 00:55:22 +02:00
2020-01-07 19:48:42 +01:00
def exists ( env ) :
return True
def generate ( env ) :
# Used for Ninja generator to collect the test execution aliases
env . Alias ( " test-execution-aliases " )
env . AddMethod ( generate_test_execution_aliases , " GenerateTestExecutionAliases " )
2021-05-06 02:12:00 +02:00
env [ " TEST_EXECUTION_SUFFIX_DENYLIST " ] = env . get (
" TEST_EXECUTION_SUFFIX_DENYLIST " ,
[ " .in " ] ,
2020-01-07 19:48:42 +01:00
)
2021-08-04 23:11:45 +02:00
env . AppendUnique ( AIB_TASKS = {
" prove " : ( auto_prove_task , False ) ,
} )
# TODO: Should we have some sort of prefix_xdir for the output location for these? Something like
# $PREFIX_VARCACHE and which in our build is pre-populated to $PREFIX/var/cache/mongo or similar?
if env [ ' PLATFORM ' ] == ' win32 ' :
env [ " PROOF_GENERATOR_COMMAND " ] = " $( $ICERUN $) $ {SOURCES[0]} $UNITTEST_FLAGS > $ {TARGETS[0]} 2>&1 & call echo % ^errorlevel % > $ {TARGETS[1]} "
# Keeping this here for later, but it only works if cmd.exe is
# launched with /V, and SCons doesn't do that.
#
# env["PROOF_ANALYZER_COMMAND"] = "set /p nextErrorLevel=<${SOURCES[1]} & if \"!nextErrorLevel!\"==\"0 \" (type nul > $TARGET) else (exit 1)"
#
# Instead, use grep! I mean findstr.
env [ " PROOF_ANALYZER_COMMAND " ] = " findstr /B /L 0 $ {SOURCES[1]} && (type nul > $TARGET) || (exit 1) "
else :
env [ " PROOF_GENERATOR_COMMAND " ] = " $( $ICERUN $) $ {SOURCES[0]} $UNITTEST_FLAGS > $ {TARGETS[0]} 2>&1 ; echo $? > $ {TARGETS[1]} "
env [ " PROOF_ANALYZER_COMMAND " ] = " if $$(exit $$(cat $ {SOURCES[1]} )) ; then touch $TARGET ; else exit 1 ; fi "
# TODO: Condition this on verbosity
env [ ' PROOF_GENERATOR_COMSTR ' ] = " Running test $ {SOURCES[0]} "
env [ ' PROOF_ANALYZER_COMSTR ' ] = " Analyzing test results in $ {SOURCES[1]} "