1#! /bin/sh
2
3# $Id: check_make_unix_cmake.sh 633243 2021-06-15 18:16:21Z ivanov $
4# Author:  Vladimir Ivanov, NCBI
5#
6###########################################################################
7#
8# Compile a check script and copy necessary files to run tests in the
9# UNIX build tree.
10#
11# Usage:
12#    check_make_unix.sh <test_list> <signature> <build_dir> <top_srcdir> <target_dir> <check_script>
13#
14#    test_list       - a list of tests (it build with "make check_r")
15#                      (default: "<build_dir>/check.sh.list")
16#    signature       - build signature
17#    build_dir       - path to UNIX build tree like".../build/..."
18#                      (default: will try determine path from current work
19#                      directory -- root of build tree )
20#    top_srcdir      - path to the root src directory
21#                      (default: will try determine path from current work
22#                      directory -- root of build tree )
23#    target_dir      - path where the check script and logs will be created
24#                      (default: current dir)
25#    check_script    - name of the check script (without path).
26#                      (default: "check.sh" / "<target_dir>/check.sh")
27#
28#    If any parameter is skipped that will be used default value for it.
29#
30# Note:
31#    Work with UNIX build tree only (any configuration).
32#
33###########################################################################
34
35# Load configuration options
36x_check_scripts_dir=`dirname "$0"`
37x_scripts_dir=`dirname "$x_check_scripts_dir"`
38x_scripts_dir=`dirname "$x_scripts_dir"`
39. ${x_check_scripts_dir}/check_setup.cfg
40
41
42# Parameters
43
44res_out="check.sh"
45res_list="$res_out.list"
46
47# Fields delimiters in the list
48# (this symbols used directly in the "sed" command)
49x_delim=" ____ "
50x_delim_internal="~"
51x_tmp="/var/tmp"
52
53x_date_format="%m/%d/%Y %H:%M:%S"
54
55x_list=$1
56x_signature=$2
57x_build_dir=$3
58x_top_srcdir=$4
59x_target_dir=$5
60x_out=$6
61x_out_name=$x_out
62x_buildcfg=$7
63
64if test "$x_buildcfg" != ""; then
65  x_buildcfg="/$x_buildcfg"
66fi
67
68# Detect Cygwin
69case `uname -s` in
70   CYGWIN* ) cygwin=true  ;;
71   *)        cygwin=false ;;
72esac
73
74# Check for build dir
75if test ! -z "$x_build_dir"; then
76   if test ! -d "$x_build_dir"; then
77      echo "Build directory \"$x_build_dir\" don't exist."
78      exit 1
79   fi
80   x_build_dir=`(cd "$x_build_dir"; pwd | sed -e 's/\/$//g')`
81else
82   # Get build dir name from the current path
83   x_build_dir=`pwd | sed -e 's%/build.*$%%'`
84   if test -d "$x_build_dir/build"; then
85      x_build_dir="$x_build_dir/build"
86   fi
87fi
88
89x_conf_dir=`dirname "$x_build_dir"`
90x_bin_dir=`(cd "$x_build_dir/../bin"; pwd | sed -e 's/\/$//g')`
91
92# Check for top_srcdir
93if test ! -z "$x_top_srcdir"; then
94   if test ! -d "$x_top_srcdir"; then
95      echo "Top source directory \"$x_top_srcdir\" don't exist."
96      exit 1
97   fi
98   x_root_dir=`(cd "$x_top_srcdir"; pwd | sed -e 's/\/$//g')`
99else
100   # Get top src dir name from the script directory
101   x_root_dir=`dirname "$x_scripts_dir"`
102fi
103
104# Check for target dir
105if test ! -z "$x_target_dir"; then
106   if test ! -d "$x_target_dir"; then
107      echo "Target directory \"$x_target_dir\" don't exist."
108      exit 1
109   fi
110    x_target_dir=`(cd "$x_target_dir"; pwd | sed -e 's/\/$//g')`
111else
112   x_target_dir=`pwd`
113fi
114
115# Check for a imported project or intree project
116if test -f Makefile.out ; then
117   x_import_prj="yes"
118   x_import_root=`sed -ne 's/^import_root *= *//p' Makefile`
119   # x_compile_dir="`pwd | sed -e 's%/internal/c++/src.*$%%g'`/internal/c++/src"
120   x_compile_dir=`cd $x_import_root; pwd`
121else
122   x_import_prj="no"
123#   x_compile_dir="$x_build_dir"
124   x_compile_dir="$x_target_dir$x_buildcfg"
125fi
126
127if test -z "$x_list"; then
128   x_list="$x_target_dir/$res_list"
129fi
130
131if test -z "$x_out"; then
132   x_out="$x_target_dir$x_buildcfg/$res_out"
133else
134   x_out="$x_target_dir$x_buildcfg/$x_out_name"
135fi
136
137x_script_name=`echo "$x_out" | sed -e 's%^.*/%%'`
138
139# Check for a list file
140if test ! -f "$x_list"; then
141   echo "Check list file \"$x_list\" not found."
142   exit 1
143fi
144
145# Features detection
146x_features=""
147for f in `ls $x_conf_dir/status/*.enabled | sort -df`; do
148   f=`echo $f | sed 's|^.*/status/\(.*\).enabled$|\1|g'`
149   x_features="$x_features$f "
150done
151
152
153#echo ----------------------------------------------------------------------
154#echo "Imported project  :" $x_import_prj
155#echo "C++ root dir      :" $x_root_dir
156#echo "Configuration dir :" $x_conf_dir
157#echo "Build dir         :" $x_build_dir
158#echo "Compile dir       :" $x_compile_dir
159#echo "Target dir        :" $x_target_dir
160#echo "Check script      :" $x_out
161#echo ----------------------------------------------------------------------
162
163#//////////////////////////////////////////////////////////////////////////
164if test ! -d "${x_target_dir}${x_buildcfg}"; then
165  mkdir -p "${x_target_dir}${x_buildcfg}"
166fi
167cat > $x_out <<EOF
168#! /bin/sh
169
170buildcfg="${x_buildcfg}"
171checkroot="$x_target_dir"
172checkdir="\${checkroot}\${buildcfg}"
173
174root_dir="$x_root_dir"
175#build_dir="$x_build_dir"
176build_dir="\${checkdir}"
177conf_dir="$x_conf_dir"
178#compile_dir="$x_compile_dir"
179compile_dir="\${checkdir}"
180bin_dir="$x_bin_dir\${buildcfg}"
181script_dir="$x_scripts_dir"
182script="\${checkroot}/$x_out_name"
183cygwin=$cygwin
184signature="$x_signature"
185sendmail=''
186domain='@ncbi.nlm.nih.gov'
187
188test -d "\${checkdir}" || mkdir -p "\${checkdir}"
189#res_journal="\$script.journal"
190#res_log="\$script.log"
191#res_list="$x_list"
192#res_concat="\$script.out"
193#res_concat_err="\$script.out_err"
194res_journal="\${checkdir}/${x_out_name}.journal"
195res_log="\${checkdir}/${x_out_name}.log"
196res_list="\${checkroot}/${x_out_name}.list"
197res_log="\${checkdir}/${x_out_name}.out"
198res_concat_err="\${checkdir}/${x_out_name}.out_err"
199
200# Define both senses to accommodate shells lacking !
201is_run=false
202no_run=true
203is_report_err=false
204no_report_err=true
205
206
207# Include COMMON.SH
208. \${script_dir}/common/common.sh
209
210
211# Printout USAGE info and exit
212
213Usage() {
214   cat <<EOF_usage
215
216USAGE:  $x_script_name {run | clean | concat | concat_err}
217
218 run         Run the tests. Create output file ("*.test_out") for each test, 
219             plus journal and log files. 
220 clean       Remove all files created during the last "run" and this script 
221             itself.
222 concat      Concatenate all files created during the last "run" into one big 
223             file "\$res_log".
224 concat_err  Like previous. But into the file "\$res_concat_err" 
225             will be added outputs of failed tests only.
226
227ERROR:  \$1
228EOF_usage
229# Undocumented commands:
230#     report_err  Report failed tests directly to developers.
231
232    exit 1
233}
234
235if test \$# -ne 1; then
236   Usage "Invalid number of arguments."
237fi
238
239
240# Action
241
242method="\$1"
243
244case "\$method" in
245#----------------------------------------------------------
246   run )
247      is_run=true
248      no_run=false
249      # See RunTest() below
250      ;;
251#----------------------------------------------------------
252   clean )
253      x_files=\`cat \$res_journal | sed -e 's/ /%gj_s4%/g'\`
254      for x_file in \$x_files; do
255         x_file=\`echo "\$x_file" | sed -e 's/%gj_s4%/ /g'\`
256         rm -f \$x_file > /dev/null
257      done
258      rm -f \$res_journal \$res_log \$res_list \$res_concat \$res_concat_err > /dev/null
259      rm -f \$script > /dev/null
260      exit 0
261      ;;
262#----------------------------------------------------------
263   concat )
264      rm -f "\$res_concat"
265      ( 
266      cat \$res_log
267      x_files=\`cat \$res_journal | sed -e 's/ /%gj_s4%/g'\`
268      for x_file in \$x_files; do
269         x_file=\`echo "\$x_file" | sed -e 's/%gj_s4%/ /g'\`
270         echo 
271         echo 
272         cat \$x_file
273      done
274      ) >> \$res_concat
275      exit 0
276      ;;
277#----------------------------------------------------------
278   concat_err )
279      rm -f "\$res_concat_err"
280      ( 
281      cat \$res_log | egrep 'ERR \[|TO  -'
282      x_files=\`cat \$res_journal | sed -e 's/ /%gj_s4%/g'\`
283      for x_file in \$x_files; do
284         x_file=\`echo "\$x_file" | sed -e 's/%gj_s4%/ /g'\`
285         x_code=\`cat \$x_file | grep -c '@@@ EXIT CODE:'\`
286         test \$x_code -ne 0 || continue
287         x_good=\`cat \$x_file | grep -c '@@@ EXIT CODE: 0'\`
288         if test \$x_good -ne 1; then
289            echo 
290            echo 
291            cat \$x_file
292         fi
293      done
294      ) >> \$res_concat_err
295      exit 0
296      ;;
297#----------------------------------------------------------
298   report_err )
299      # This method works inside NCBI only 
300      test "\$NCBI_CHECK_MAILTO_AUTHORS." = 'Y.'  ||  exit 0;
301      if test -x /usr/sbin/sendmail; then
302         sendmail="/usr/sbin/sendmail -oi"
303      elif test -x /usr/lib/sendmail; then
304         sendmail="/usr/lib/sendmail -oi"
305      else
306         echo sendmail not found on this platform
307         exit 0
308      fi
309      is_report_err=true
310      no_report_err=false
311      # See RunTest() below
312      ;;
313#----------------------------------------------------------
314   * )
315      Usage "Invalid method name \$method."
316      ;;
317esac
318
319
320#//////////////////////////////////////////////////////////////////////////
321
322
323trap "touch \${checkdir}/check.failed; exit 1"  1 2 15
324rm \${checkdir}/check.failed \${checkdir}/check.success > /dev/null 2>&1 
325
326# Set log_site for tests
327NCBI_APPLOG_SITE=testcxx
328export NCBI_APPLOG_SITE
329
330# Include configuration file
331. \${checkroot}/check.cfg
332if test -z "\$NCBI_CHECK_TOOLS"; then
333   NCBI_CHECK_TOOLS="regular"
334fi
335# Check timeout multiplier (increase default check timeout in x times)
336if test -z "\$NCBI_CHECK_TIMEOUT_MULT"; then
337   NCBI_CHECK_TIMEOUT_MULT=1
338fi
339export NCBI_CHECK_TIMEOUT_DEFAULT=$NCBI_CHECK_TIMEOUT_DEFAULT
340
341# Path to test data, used by some scripts and applications
342if test -z "\$NCBI_TEST_DATA"; then
343    if [ \$cygwin = true ]; then
344       NCBI_TEST_DATA=//snowman/win-coremake/Scripts/test_data
345    elif test -d /Volumes/ncbiapdata/test_data; then
346       NCBI_TEST_DATA=/Volumes/ncbiapdata/test_data
347    else
348       NCBI_TEST_DATA=/am/ncbiapdata/test_data
349    fi
350    export NCBI_TEST_DATA
351fi
352# Add synonym for it, see: include/common/test_data_path.h (CXX-9239)
353if test -z "\$NCBI_TEST_DATA_PATH"; then
354    NCBI_TEST_DATA_PATH=\$NCBI_TEST_DATA
355    export NCBI_TEST_DATA_PATH
356fi
357
358# Valgrind/Helgrind configurations
359VALGRIND_SUP="\${script_dir}/common/check/valgrind.supp"
360VALGRIND_CMD="--tool=memcheck --suppressions=\$VALGRIND_SUP"
361HELGRIND_CMD="--tool=helgrind --suppressions=\$VALGRIND_SUP"
362if (valgrind --ncbi --help) >/dev/null 2>&1; then
363    VALGRIND_CMD="--ncbi \$VALGRIND_CMD" # --ncbi must be the first option!
364    HELGRIND_CMD="--ncbi \$HELGRIND_CMD" # --ncbi must be the first option!
365fi
366
367# Leak- and Thread- Sanitizers (GCC 7.3, -fsanitize= flags)
368LSAN_OPTIONS="suppressions=\${script_dir}/common/check/lsan.supp:exitcode=0"
369export LSAN_OPTIONS
370TSAN_OPTIONS="suppressions=\${script_dir}/common/check/tsan.supp"
371export TSAN_OPTIONS
372
373# Disable BOOST tests to catch asynchronous system failures
374# (signals on *NIX platforms or structured exceptions on Windows)
375BOOST_TEST_CATCH_SYSTEM_ERRORS=no
376export BOOST_TEST_CATCH_SYSTEM_ERRORS
377
378BOOST_TEST_COLOR_OUTPUT=no
379export BOOST_TEST_COLOR_OUTPUT
380
381# Export some global vars
382top_srcdir="\$root_dir"
383export top_srcdir
384FEATURES="$x_features"
385export FEATURES
386
387# Redirect output for C++ diagnostic framework to stderr,
388# except if using under 'export_project' tool.
389if test -z "\$NCBI_EXPORT_PROJECT"; then
390    NCBI_CONFIG__LOG__FILE="-"
391    export NCBI_CONFIG__LOG__FILE
392fi
393
394# Add additional necessary directories to PATH: current, build, scripts, utility and $HOME/bin (for Ubuntu).
395PATH="\${script_dir}/common/impl:\$NCBI/bin/_production/CPPCORE:\$HOME/bin:.:\${build_dir}:\${bin_dir}:\${PATH}"
396export PATH
397
398# Export bin and lib pathes
399CFG_BIN="\${conf_dir}/bin\${buildcfg}"
400CFG_LIB="\${conf_dir}/lib\${buildcfg}"
401export CFG_BIN CFG_LIB
402
403# Define time-guard script to run tests from other scripts
404check_exec="\${script_dir}/common/check/check_exec.sh"
405CHECK_EXEC="\${script_dir}/common/check/check_exec_test.sh"
406CHECK_EXEC_STDIN="\$CHECK_EXEC -stdin"
407CHECK_SIGNATURE="\$signature"
408export CHECK_EXEC
409export CHECK_EXEC_STDIN
410export CHECK_SIGNATURE
411
412# Debug tools to get stack/back trace (except running under memory checkers)
413NCBI_CHECK_STACK_TRACE=''
414NCBI_CHECK_BACK_TRACE=''
415if test "\$NCBI_CHECK_TOOLS" = "regular"; then
416   if (which gdb) >/dev/null 2>&1; then
417       NCBI_CHECK_BACK_TRACE='gdb --batch --quiet -ex "thread apply all bt" -ex "quit"'
418   fi
419   if (which gstack) >/dev/null 2>&1; then
420       NCBI_CHECK_STACK_TRACE='gstack'
421   fi
422   export NCBI_CHECK_BACK_TRACE
423   export NCBI_CHECK_STACK_TRACE
424fi
425
426# Use AppLog-style output format in the testsuite by default
427if test -z "\$DIAG_OLD_POST_FORMAT"; then
428    DIAG_OLD_POST_FORMAT=false
429    export DIAG_OLD_POST_FORMAT
430fi
431
432# Avoid possible hangs on Mac OS X.
433DYLD_BIND_AT_LAUNCH=1
434export DYLD_BIND_AT_LAUNCH
435
436case " \$FEATURES " in
437    *\ MaxDebug\ * )
438         case "\$signature" in
439	     *-linux* ) MALLOC_DEBUG_=2; export MALLOC_DEBUG_ ;;
440         esac
441         case "\$signature" in
442             GCC* | ICC* ) NCBI_CHECK_TIMEOUT_MULT=20 ;;
443         esac
444         ;;
445esac
446
447# Check on linkerd and set backup
448echo test | nc -w 1 linkerd 4142 > /dev/null 2>&1
449if test \$? -ne 0;  then
450   NCBI_CONFIG__ID2SNP__PTIS_NAME="pool.linkerd-proxy.service.bethesda-dev.consul.ncbi.nlm.nih.gov:4142"
451   export NCBI_CONFIG__ID2SNP__PTIS_NAME
452fi
453
454EOF
455
456if test -n "$x_conf_dir"  -a  -d "$x_conf_dir/lib";  then
457   cat >> $x_out <<EOF
458# Add a library path for running tests
459. \${script_dir}/common/common.sh
460COMMON_AddRunpath "\$conf_dir/lib\${buildcfg}"
461EOF
462else
463   echo "WARNING:  Cannot find path to the library dir."
464fi
465# Add additional path for imported projects to point to local /lib first
466if test "$x_import_prj" = "yes"; then
467    local_lib=`(cd "$x_compile_dir/../lib"; pwd | sed -e 's/\/$//g')`
468    if test -n "$local_lib"  -a  -d "$local_lib";  then
469   cat >> $x_out <<EOF
470COMMON_AddRunpath "$local_lib"
471EOF
472    fi
473fi
474
475
476#//////////////////////////////////////////////////////////////////////////
477
478cat >> $x_out <<EOF
479
480# Check for automated build
481is_automated=false
482is_db_load=false
483if test -n "\$NCBI_AUTOMATED_BUILD"; then
484   is_automated=true
485   if test -n "\$NCBI_CHECK_DB_LOAD"; then
486      is_db_load=true
487   fi
488fi
489
490# Check for some executables
491have_ncbi_applog=false
492if (ncbi_applog generate) >/dev/null 2>&1; then
493   have_ncbi_applog=true
494fi
495have_uptime=false
496if (which uptime) >/dev/null 2>&1; then
497   have_uptime=true
498fi
499
500
501#//////////////////////////////////////////////////////////////////////////
502
503
504# Run
505count_ok=0
506count_err=0
507count_timeout=0
508count_absent=0
509count_total=0
510
511if \$is_run; then
512   rm -f "\$res_journal"
513   rm -f "\$res_log"
514   #rm -f "$x_build_dir/test_stat_load.log"
515fi
516
517# Set app limits:
518# Only if $NCBI_CHECK_SETLIMITS not set to 0 before, or not configured with -with-max-debug.
519# Some tools that use this configure flag, like AddressSanitizer, can fail if limited.
520
521is_max_debug=false
522if test -f "\${conf_dir}/status/MaxDebug.enabled"; then
523   is_max_debug=true
524fi
525if test "\$NCBI_CHECK_SETLIMITS" != "0"  -a  ! \$is_max_debug; then
526   ulimit -c 1000000
527   ulimit -n 8192
528   if [ \$cygwin = false ]; then
529       if test "\$NCBI_CHECK_TOOLS" = "regular"; then
530          ulimit -v 48000000
531       else
532          # Increase memory limits if run under check tool
533          ulimit -v 64000000
534       fi
535   fi
536fi
537
538
539# Run one test
540
541RunTest()
542{
543    # Parameters
544    IFS=';'; rargs=(\$1); unset IFS;
545    x_work_dir_tail=\${rargs[0]};
546    x_test=\${rargs[1]};
547    x_app=\${rargs[2]};
548    x_run=\${rargs[3]};
549    x_alias=\${rargs[10]};
550    x_name=\${rargs[4]};
551    x_files=\${rargs[5]};
552    x_timeout=\${rargs[6]};
553    x_requires=\${rargs[7]};
554    x_authors=\${rargs[8]};
555    x_resources=\${rargs[9]};
556    r_id=\$2
557
558    test -z "\$x_timeout"  &&  x_timeout=\$NCBI_CHECK_TIMEOUT_DEFAULT
559    x_work_dir="\$checkdir/\$x_work_dir_tail"
560    x_done="\$checkdir/~\$x_name"
561    x_wlog_dir="\$x_work_dir"
562    x_work_dir="\$x_work_dir/~\$x_name"
563    x_log="$x_tmp/\$\$.~\$x_name.out"
564    x_info="$x_tmp/\$\$.~\$x_name.info"
565
566    if test -f "/etc/nologin"; then
567        echo "Nologin detected, probably host going to reboot. Skipping test:" \$x_name
568        touch "\$checkdir/~RUN_CHECKS.next"
569        return 0
570    fi
571    if \$is_report_err; then
572        # Authors are not defined for this test
573        if test -z "\$x_authors"; then
574            touch "\$checkdir/~RUN_CHECKS.next"
575            return 0
576        fi
577    fi
578    test -d \${x_work_dir} || mkdir -p \${x_work_dir}
579
580    for x_req in \$x_requires; do
581      t_sub=\${x_req::1}
582      t_res="yes"
583      if test \$t_sub = "-"; then
584          t_sub=\${x_req:1}
585          if test -f "\$conf_dir/status/\$t_sub.enabled" ; then
586            t_res="no"
587          fi
588      else
589          t_sub=\${x_req}
590          if test ! -f "\$conf_dir/status/\$t_sub.enabled" ; then
591            t_res="no"
592          fi
593      fi
594      if test "\$t_res" = "no"; then
595           x_test_out="\$x_wlog_dir/\$x_name.test_out\$x_ext"
596           echo NCBI_UNITTEST_SKIPPED > \$x_test_out
597           echo "t_cmd=\\"[\$r_id/\$x_TestsTotal \$x_work_dir_tail] \$x_name (unmet CHECK_REQUIRES=\$x_req)\\"" > \$x_info
598           echo "t_test_out=\\"\$x_test_out\\"" >> \$x_info
599           mv \$x_info "\${x_done}.done"
600           touch "\$checkdir/~RUN_CHECKS.next"
601           rm -rf "\${x_work_dir}"
602           return 0
603      fi
604    done
605
606    if test -n "\$x_resources"; then
607        for r in \$x_resources ; do
608            if test \$r = "SERIAL"; then
609                while ! mkdir "\$checkdir/~\$r.lock" 2>/dev/null
610                do
611	                sleep 1
612                done
613                r_count=\`ls \${checkdir}/*.in_progress 2>/dev/null | wc -w | sed -e 's/ //g'\`
614                while test \$r_count -gt 0; do
615                    sleep 1
616                    r_count=\`ls \${checkdir}/*.in_progress 2>/dev/null | wc -w | sed -e 's/ //g'\`
617                done
618            fi
619        done
620    fi
621
622    touch "\${x_done}.in_progress"
623    if test -f "\${x_done}.done"; then 
624        rm -f "\${x_done}.done"
625    fi
626    touch "\$checkdir/~RUN_CHECKS.next"
627
628    if test -n "\$x_resources"; then
629        for r in \$x_resources ; do
630            if test \$r != "SERIAL"; then
631                while ! mkdir "\$checkdir/~\$r.lock" 2>/dev/null
632                do
633	                sleep 1
634                done
635            fi
636        done
637    fi
638
639    if test -n "\$x_files"; then
640        for i in \$x_files ; do
641            x_copy="\$root_dir/src/\$x_work_dir_tail/\$i"
642            if test -f "\$x_copy"  -o  -d "\$x_copy"; then
643                cp -rf "\$x_copy" "\$x_work_dir"
644                test -d "\$x_work_dir/\$i" &&  find "\$x_work_dir/\$i" -name .svn -print | xargs rm -rf
645            else
646                echo "[\$x_work_dir_tail] \$x_name: Warning:  The copied object \"\$x_copy\" should be a file or directory!"
647                continue
648            fi
649        done
650    fi
651
652    # Run test under all specified check tools   
653    for tool in \$NCBI_CHECK_TOOLS; do
654
655        saved_phid=''
656
657        tool_lo=\`echo \$tool | tr '[A-Z]' '[a-z]'\`
658        tool_up=\`echo \$tool | tr '[a-z]' '[A-Z]'\`
659        
660        case "\$tool_lo" in
661            regular | valgrind | helgrind ) ;;
662                             * ) continue ;;
663        esac
664        
665        x_cmd="[\$r_id/\$x_TestsTotal \$x_work_dir_tail] \$x_name"
666        if test \$tool_lo = "regular"; then
667           #x_cmd="[\$x_work_dir_tail] \$x_name"
668           x_test_out="\$x_wlog_dir/\$x_name.test_out\$x_ext"
669           x_test_rep="\$x_wlog_dir/\$x_name.test_rep\$x_ext"
670           x_boost_rep="\$x_wlog_dir/\$x_name.boost_rep\$x_ext"
671        else
672           #x_cmd="[\$x_work_dir_tail] \$tool_up \$x_name"
673           x_test_out="\$x_wlog_dir/\$x_name.test_out\$x_ext.\$tool_lo"
674           x_test_rep="\$x_wlog_dir/\$x_name.test_rep\$x_ext.\$tool_lo"
675           x_boost_rep="\$x_wlog_dir/\$x_name.boost_rep\$x_ext.\$tool_lo"
676        fi
677
678   
679        if \$is_run && \$is_automated; then
680           echo "\$signature \$NCBI_CHECK_OS_NAME" > "\$x_test_rep"
681           echo "\$x_work_dir_tail" >> "\$x_test_rep"
682           echo "\$x_run" >> "\$x_test_rep"
683           echo "\$x_alias" >> "\$x_test_rep"
684           NCBI_BOOST_REPORT_FILE="\$x_boost_rep"
685           if $cygwin; then
686               export NCBI_BOOST_REPORT_FILE="\$(cygpath -w "\$x_boost_rep")"
687           else
688               export NCBI_BOOST_REPORT_FILE
689           fi
690        fi
691
692        # Check existence of the test's application directory
693        if test -d "\$x_work_dir"; then
694
695            # Goto the test's directory 
696            cd "\$x_work_dir"
697
698            # Run test if it exist
699            if test -f "\$x_app" -o -f "\$bin_dir/\$x_app"; then
700
701                _RLD_ARGS="-log \$x_log"
702                export _RLD_ARGS
703
704                # Fix empty parameters (replace "" to \"\", '' to \'\')
705                x_run_fix=\`echo "\$x_run" | sed -e 's/""/\\\\\\\\\\"\\\\\\\\\\"/g' -e "s/''/\\\\\\\\\\'\\\\\\\\\\'/g"\`
706
707                # Define check tool variables
708                NCBI_CHECK_TOOL=\`eval echo "\$"NCBI_CHECK_\${tool_up}""\`
709                case "\$tool_lo" in
710                regular  ) ;;
711                valgrind | helgrind ) 
712                           if test "\$tool_lo" = "valgrind"; then
713                              NCBI_CHECK_TOOL="\$NCBI_CHECK_VALGRIND \$VALGRIND_CMD" 
714                           else
715                              NCBI_CHECK_TOOL="\$NCBI_CHECK_VALGRIND \$HELGRIND_CMD" 
716                           fi
717                           NCBI_CHECK_TIMEOUT_MULT=15
718                           NCBI_RUN_UNDER_VALGRIND="yes"
719                           export NCBI_RUN_UNDER_VALGRIND
720                           NCBI_RUN_UNDER_CHECK_TOOL="yes"
721                           export NCBI_RUN_UNDER_CHECK_TOOL
722                           ;;
723                esac
724                export NCBI_CHECK_TOOL
725                CHECK_TIMEOUT=\`expr \$x_timeout \* \$NCBI_CHECK_TIMEOUT_MULT\`
726                export CHECK_TIMEOUT
727
728                # Just need to report errors to authors?
729                if \$is_report_err; then
730                    test -f "\$x_test_out" || continue
731                    x_code=\`cat \$x_test_out | grep -c '@@@ EXIT CODE:'\`
732                    test \$x_code -ne 0 || continue
733                    x_good=\`cat \$x_test_out | grep -c '@@@ EXIT CODE: 0'\`
734                    if test \$x_good -eq 1; then
735                        continue
736                    fi
737                    MailToAuthors "\$x_authors" "\$x_test_out"
738                    continue
739                fi
740         
741                echo \$x_run | grep '\.sh' > /dev/null 2>&1 
742                if test \$? -eq 0;  then
743                    # Run script without any check tools.
744                    # It will be applied inside script using \$CHECK_EXEC.
745                    xx_run="\$x_run_fix"
746                else
747                    # Run under check tool
748                    xx_run="\$NCBI_CHECK_TOOL \$x_run_fix"
749                fi
750
751                # Write header to output file 
752                (
753                    echo "======================================================================"
754                    echo "\$x_name"
755                    echo "======================================================================"
756                    echo 
757                    if test "\$x_run" != "\$x_name"; then
758                       echo "Command line: \$x_run"
759                       echo 
760                    fi
761                    if test -n "\$NCBI_CHECK_ENV_SETTINGS"; then
762                       echo "NCBI_CHECK_ENV_SETTINGS:"
763                       for env in \$NCBI_CHECK_ENV_SETTINGS; do
764                           echo "    \$env = \`eval echo '$'\$env\`"
765                       done
766                       echo
767                    fi
768                ) > \$x_test_out 2>&1
769
770                # Remove old core file if any
771                corefile="\$x_work_dir/core"
772                rm -f "\$corefile" > /dev/null 2>&1
773                rm -f check_exec.pid > /dev/null 2>&1
774
775                # Generate PHID and SID, to use it by any application in the current test,
776                # and for loading test statistics later (test_stat_load -> ncbi_applog),
777                # to have same values in Applog.
778                logfile=\$NCBI_CONFIG__LOG__FILE
779                NCBI_CONFIG__LOG__FILE=
780                export NCBI_CONFIG__LOG__FILE
781                if \$have_ncbi_applog; then
782                   eval "\`ncbi_applog generate -phid -sid -format=shell-export | tr -d '\r'\`"
783                   if \$is_run && \$is_db_load; then
784                      # Use generated PHID for test statistics, and sub-PHID.1 for test itself
785                      saved_phid=\$NCBI_LOG_HIT_ID
786                      NCBI_LOG_HIT_ID=\$NCBI_LOG_HIT_ID.1
787                      export NCBI_LOG_HIT_ID
788                      # Create a file in the cirrent directory with initial sub-PHID
789                      # (will be incremented by $CHECK_EXEC, if any)
790                      echo "0" > \$NCBI_LOG_HIT_ID
791                   fi
792                fi
793                NCBI_CONFIG__LOG__FILE=\$logfile
794                export NCBI_CONFIG__LOG__FILE
795
796                # Run check
797                start_time="\`date +'$x_date_format'\`"
798                        
799                # Use separate shell to run test.
800                # This will allow to know execution time for applications with timeout.
801                # Also, process guard works better if used after "time -p".
802                launch_sh="$x_tmp/launch.\$\$.~\$x_name.sh"
803cat > \$launch_sh <<EOF_launch
804#! /bin/sh
805exec time -p \$check_exec \`eval echo \$xx_run\`
806EOF_launch
807                chmod a+x \$launch_sh
808                \$launch_sh >\$x_log 2>&1
809                result=\$?
810                stop_time="\`date +'$x_date_format'\`"
811                if \${have_uptime}; then
812                    load_avg="\`uptime | sed -e 's/.*averages*: *\(.*\) *$/\1/' -e 's/[, ][, ]*/ /g'\`"
813                else
814                    load_avg="unavailable"
815                fi
816                rm \$launch_sh
817
818                LC_ALL=C sed -e '/ ["][$][@]["].*\$/ {
819                        s/^.*: //
820                        s/ ["][$][@]["].*$//
821                }' \$x_log >> \$x_test_out
822
823                # RunID
824                runpid='?'
825                test -f check_exec.pid  &&  runpid="\`cat check_exec.pid\`"
826                runid="\`date -u +%y%m%d%H%M%S\`-\$runpid-\`uname -n\`"
827                runid="\`echo \$runid | tr -d '\n\r'\`"
828                rm -f check_exec.pid > /dev/null 2>&1
829                
830                # Get application execution time
831                exec_time=\`\${checkroot}/sysdep.sh tl 7 \$x_log | tr '\n\r' '%%' | tr -d '\000-\037' | tr  -d '\176-\377'\`
832                echo \$exec_time | egrep 'real [0-9]|Maximum execution .* is exceeded' > /dev/null 2>&1 
833                if test \$? -eq 0;  then
834                    exec_time=\`echo \$exec_time |   \\
835                                sed -e 's/%%/%/g'    \\
836                                    -e 's/%$//'      \\
837                                    -e 's/%/, /g'    \\
838                                    -e 's/[ ] */ /g' \\
839                                    -e 's/^.*\(Maximum execution [0-9][0-9]* is exceeded\).*$/\1/' \\
840                                    -e 's/^.*\(real [0-9][0-9]*[.][0-9][0-9]*\)/\1/' \\
841                                    -e 's/\(sys [0-9][0-9]*[.][0-9][0-9]*\).*/\1/'\`
842                else
843                    exec_time='unparsable timing stats'
844                fi
845               
846                rm -f \$x_log
847
848                # Analize check tool output
849                case "\$tool_lo" in
850                    valgrind | helgrind ) 
851                               summary_all=\`grep -c 'ERROR SUMMARY:' \$x_test_out\`
852                               summary_ok=\`grep -c 'ERROR SUMMARY: 0 ' \$x_test_out\`
853                               # The number of given lines can be zero.
854                               # In some cases we can lost valgrind's summary.
855                               if test \$summary_all -ne \$summary_ok; then
856                                   result=254
857                               fi
858                               ;;
859                    * )
860                               # GCC Sanitizer can fails with a 0 exit code
861                               if \$is_max_debug; then
862                                   grep '==ERROR: AddressSanitizer:' \$x_test_out > /dev/null 2>&1 
863                                   if test \$? -eq 0;  then
864                                      result=253
865                                   fi
866                               fi
867                    
868                esac
869
870                # Write result of the test into the his output file
871                echo "Start time   : \$start_time"   >> \$x_test_out
872                echo "Stop time    : \$stop_time"    >> \$x_test_out
873                echo "Load averages: \$load_avg"     >> \$x_test_out
874                echo >> \$x_test_out
875                echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" >> \$x_test_out
876                echo "@@@ EXIT CODE: \$result" >> \$x_test_out
877
878                if test -f "\$corefile"; then
879                    echo "@@@ CORE DUMPED" >> \$x_test_out
880                    if test -d "\$bin_dir" -a -f "\$bin_dir/\$x_test"; then
881                        mv "\$corefile" "\$bin_dir/\$x_test.core"
882                    else
883                        rm -f "\$corefile"
884                    fi
885                fi
886
887                echo "t_cmd=\\"\$x_cmd\\"" > \$x_info
888                echo "t_test_out=\\"\$x_test_out\\"" >> \$x_info
889                echo "t_exec_time=\\"\$exec_time\\"" >> \$x_info
890                echo "t_result=\\"\$result\\"" >> \$x_info
891
892                # Write results
893                if \$is_automated; then
894                    if grep NCBI_UNITTEST_DISABLED \$x_test_out >/dev/null; then
895                        echo "DIS" >> "\$x_test_rep"
896
897                    elif grep NCBI_UNITTEST_SKIPPED \$x_test_out >/dev/null; then
898                        echo "SKP" >> "\$x_test_rep"
899
900                    elif grep NCBI_UNITTEST_TIMEOUTS_BUT_NO_ERRORS \$x_test_out >/dev/null; then
901                        echo "TO" >> "\$x_test_rep"
902
903                    elif echo "\$exec_time" | egrep 'Maximum execution .* is exceeded' >/dev/null || egrep "Maximum execution .* is exceeded" \$x_test_out >/dev/null; then
904                        echo "TO" >> "\$x_test_rep"
905
906                    elif test \$result -eq 0; then
907                        echo "OK" >> "\$x_test_rep"
908
909                    else
910                        echo "ERR" >> "\$x_test_rep"
911                    fi
912                    echo "\$start_time" >> "\$x_test_rep"
913                    echo "\$result"     >> "\$x_test_rep"
914                    echo "\$exec_time"  >> "\$x_test_rep"
915                    echo "\$x_authors"  >> "\$x_test_rep"
916                    echo "\$load_avg"   >> "\$x_test_rep"
917                    echo "\$runid"      >> "\$x_test_rep"
918                fi
919
920            else  # Run test if it exist
921                if \$is_run; then
922                    echo "t_cmd=\\"\$x_cmd\\"" > \$x_info
923                    echo "t_test_out=\\"\$x_test_out\\"" >> \$x_info
924                    if \$is_automated; then
925                        echo "ABS"         >> "\$x_test_rep"
926                        echo "\`date +'$x_date_format'\`" >> "\$x_test_rep"
927                        echo "\$x_authors" >> "\$x_test_rep"
928                    fi
929                fi
930            fi
931
932        else  # Check existence of the test's application directory
933            if \$is_run; then
934                # Test application is absent
935                echo "t_cmd=\\"\$x_cmd\\"" > \$x_info
936                echo "t_test_out=\\"\$x_test_out\\"" >> \$x_info
937                if \$is_automated; then
938                    echo "ABS"         >> "\$x_test_rep"
939                    echo "\`date +'$x_date_format'\`" >> "\$x_test_rep"
940                    echo "\$x_authors" >> "\$x_test_rep"
941                fi
942            fi
943        fi
944
945        # Load test results to Database and Applog immediately after a test.
946        # Always load test results for automated builds on a 'run' command.
947        
948        if \$is_run && \$is_db_load; then
949            while ! mkdir "\$checkdir/~test_stat_load.lock" 2>/dev/null
950            do
951	            sleep 1
952            done
953           if test -n "\$saved_phid";  then
954              NCBI_LOG_HIT_ID=\$saved_phid
955              export NCBI_LOG_HIT_ID
956           fi
957           case \`uname -s\` in
958              CYGWIN* )
959                test_stat_load "\$(cygpath -w "\$x_test_rep")" "\$(cygpath -w "\$x_test_out")" "\$(cygpath -w "\$x_boost_rep")" "\$(cygpath -w "\$top_srcdir/build_info")" >> "\${checkdir}/test_stat_load.log" 2>&1 ;;
960              IRIX* )
961                test_stat_load.sh "\$x_test_rep" "\$x_test_out" "\$x_boost_rep" "\$top_srcdir/build_info" >> "\${checkdir}/test_stat_load.log" 2>&1 ;;
962              * )
963                test_stat_load "\$x_test_rep" "\$x_test_out" "\$x_boost_rep" "\$top_srcdir/build_info" >> "\${checkdir}/test_stat_load.log" 2>&1 ;;
964            esac
965            echo >> "\${checkdir}/test_stat_load.log" 2>&1
966            rm -rf "\$checkdir/~test_stat_load.lock"
967        fi
968        if test \$is_run  -a  -n "\$saved_phid"; then
969            rm -f \$saved_phid* > /dev/null 2>&1
970        fi
971        
972    done  # Run test under all specified check tools   
973
974    if test -n "\$x_resources"; then
975        rev_resources=""
976        for r in \$x_resources ; do
977            rev_resources="\$r \${rev_resources}"
978        done
979        for r in \$rev_resources ; do
980            rm -rf "\$checkdir/~\$r.lock"
981        done
982    fi
983    if test -f \$x_info; then 
984        mv \$x_info "\${x_done}.done"
985    else
986        touch "\${x_done}.done"
987    fi
988    rm "\${x_done}.in_progress"
989    rm -rf "\${x_work_dir}" 2>/dev/null
990    if test \$? -ne 0;  then
991        sleep 1
992        rm -rf "\${x_work_dir}" 2>/dev/null
993    fi
994}
995
996MailToAuthors()
997{
998   # The limit on the sending email size in Kbytes
999   mail_limit=1024
1000
1001   test -z "\$sendmail"  &&  return 0
1002   test -z "\$1"  &&  return 0
1003   x_authors=""
1004   for author in \$1; do
1005       x_authors="\$x_authors \$author\$domain"
1006   done
1007   x_logfile="\$2"
1008   tmp="./check_mailtoauthors.tmp.\$\$.\`basename \$x_logfile\`"
1009   
1010   echo '-----------------------'
1011   echo "Send results of the test \$x_app to \$x_authors"
1012   echo '-----------------------'
1013        echo "To: \$x_authors"
1014        echo "Subject: [WATCHERS] \$x_app | \$signature"
1015        echo
1016        echo \$x_cmd
1017        echo
1018   echo "cmd = \$sendmail \$x_authors"
1019   
1020   COMMON_LimitTextFileSize \$x_logfile \$tmp \$mail_limit
1021   {
1022        echo "To: \$x_authors"
1023        echo "Subject: [WATCHERS] \$x_app | \$signature"
1024        echo
1025        echo \$x_cmd
1026        echo
1027        cat \$tmp
1028        echo 
1029        cat \$top_srcdir/build_info
1030   } | \$sendmail \$x_authors
1031   echo '-----------------------'
1032   rm -f \$tmp > /dev/null
1033}
1034
1035ProcessDone()
1036{
1037    while true; do
1038        sleep 2
1039        p_done=\`ls \${checkdir}/*.started 2>/dev/null\`
1040        if test -n "\$p_done"; then
1041            for p_file in \$p_done; do
1042                cat \$p_file
1043                rm \$p_file
1044            done
1045        fi
1046        p_done=\`ls \${checkdir}/*.done 2>/dev/null\`
1047        if test -n "\$p_done"; then
1048            for p_file in \$p_done; do
1049                source \$p_file
1050                if test ! -e "\$t_test_out"; then
1051                    echo "ABS --  \$t_cmd"
1052                    echo "ABS --  \$t_cmd" >> \$res_log
1053                    count_absent=\`expr \$count_absent + 1\`
1054                    rm -f \$p_file
1055                    continue
1056                fi
1057                echo "\$t_test_out" >> \$res_journal
1058                count_total=\`expr \$count_total + 1\`
1059                # Write result on the screen
1060                if grep NCBI_UNITTEST_DISABLED \$t_test_out >/dev/null; then
1061                    echo "DIS --  \$t_cmd"
1062                    echo "DIS --  \$t_cmd" >> \$res_log
1063                    count_absent=\`expr \$count_absent + 1\`
1064
1065                elif grep NCBI_UNITTEST_SKIPPED \$t_test_out >/dev/null; then
1066                    echo "SKP --  \$t_cmd"
1067                    echo "SKP --  \$t_cmd" >> \$res_log
1068                    count_absent=\`expr \$count_absent + 1\`
1069
1070                elif grep NCBI_UNITTEST_TIMEOUTS_BUT_NO_ERRORS \$t_test_out >/dev/null; then
1071                    echo "TO  --  \$t_cmd"
1072                    echo "TO  --  \$t_cmd" >> \$res_log
1073                    count_timeout=\`expr \$count_timeout + 1\`
1074
1075                elif echo "\$t_exec_time" | egrep 'Maximum execution .* is exceeded' >/dev/null || egrep "Maximum execution .* is exceeded" \$t_test_out >/dev/null; then
1076                    echo "TO  --  \$t_cmd     (\$t_exec_time)"
1077                    echo "TO  --  \$t_cmd     (\$t_exec_time)" >> \$res_log
1078                    count_timeout=\`expr \$count_timeout + 1\`
1079
1080                elif test \$t_result -eq 0; then
1081                    echo "OK  --  \$t_cmd     (\$t_exec_time)"
1082                    echo "OK  --  \$t_cmd     (\$t_exec_time)" >> \$res_log
1083                    count_ok=\`expr \$count_ok + 1\`
1084
1085                else
1086                    echo "ERR [\$t_result] --  \$t_cmd     (\$t_exec_time)"
1087                    echo "ERR [\$t_result] --  \$t_cmd     (\$t_exec_time)" >> \$res_log
1088                    count_err=\`expr \$count_err + 1\`
1089                fi
1090                rm -f \$p_file
1091            done
1092        else
1093            if test -e "\$checkdir/~DONE"; then
1094                break
1095            fi
1096        fi
1097    done
1098    rm "\$checkdir/~DONE"
1099}
1100
1101AddJob()
1102{
1103    a_pid="\$1"
1104    a_name="\$2"
1105    a_id="\$3"
1106
1107    if test "\${a_pid}" -gt 0; then
1108        echo "        Start \$a_id: \${a_name} (\$a_pid)" > "\$checkdir/~\$a_name.started"
1109        while test ! -e "\$checkdir/~RUN_CHECKS.next"; do
1110            if test -e "\$checkdir/~SERIAL.lock"; then
1111                sleep 2
1112            else
1113                sleep .1
1114            fi
1115        done
1116        rm "\$checkdir/~RUN_CHECKS.next"
1117    fi
1118    while test -e "\$checkdir/~SERIAL.lock"; do
1119        sleep 2
1120    done
1121
1122    if test "\${a_pid}" -gt 0; then
1123        if test -n "\$NTEST_PARALLEL_LEVEL"; then
1124            a_maxjob=\$NTEST_PARALLEL_LEVEL
1125        elif test -n "\$CTEST_PARALLEL_LEVEL"; then
1126            a_maxjob=\$CTEST_PARALLEL_LEVEL
1127        elif test -n "\$NUMBER_OF_PROCESSORS"; then
1128            a_maxjob=\$NUMBER_OF_PROCESSORS
1129        else
1130            a_maxjob=4
1131        fi
1132    else
1133        a_maxjob=0
1134    fi
1135
1136    a_run=\`ls \${checkdir}/*.in_progress 2>/dev/null\`
1137    a_run=\`echo \$a_run | wc -w | sed -e 's/ //g'\`
1138    if test "\${a_run}" -ne "\${a_run}"; then
1139echo "error:  1 a_run = \$a_run"
1140        a_run=0
1141    fi
1142
1143    while test "\$a_run" -ge "\$a_maxjob"; do
1144        sleep 1
1145        a_run=\`ls \${checkdir}/*.in_progress 2>/dev/null\`
1146        a_run=\`echo \$a_run | wc -w | sed -e 's/ //g'\`
1147        if test "\${a_run}" -ne "\${a_run}"; then
1148echo "error:  2 a_run = \$a_run"
1149            break
1150        fi
1151        if test "\${a_run}" -le 0; then
1152            break
1153        fi
1154    done
1155    if test "\${a_maxjob}" -le 0; then
1156        touch "\$checkdir/~DONE"
1157    fi
1158}
1159
1160#//////////////////////////////////////////////////////////////////////////
1161# Run tests
1162
1163RunJobs()
1164{
1165    res_list=\$1
1166    x_i=0
1167    while read x_row; do
1168        x_row=\`echo "\$x_row" | sed -e 's/ ____ /;/g' | sed -e 's/ ____/;/g' | sed -e 's/ ;/;/g'\`
1169        IFS=';'; arrIN=(\$x_row); unset IFS;
1170        x_name=\${arrIN[4]};
1171        x_i=\`expr \$x_i + 1\`
1172
1173        RunTest "\$x_row" "\$x_i" &
1174        AddJob "\$!" "\$x_name" "\$x_i"
1175    done < "\$res_list"
1176    AddJob "0" "" "" ""
1177}
1178
1179rm -rf "\$checkdir/~*" 2>/dev/null
1180locks=\`ls -d \${checkdir}/~*.lock 2>/dev/null | wc -w | sed -e 's/ //g'\`
1181if test \$locks -ne 0; then
1182  echo "ERROR: there are locks in \${checkdir}" 1>&2
1183  exit 1
1184fi
1185x_test=""
1186x_TestsTotal=\`cat "\$res_list" | wc -l | sed -e 's/ //g'\`
1187x_START=\$SECONDS
1188RunJobs "\$res_list" &
1189ProcessDone
1190x_DURATION=\`expr \$SECONDS - \$x_START\`
1191echo
1192echo "Total Test time (real) = \${x_DURATION} sec"
1193
1194if \$is_run; then
1195   # Write result of the tests execution
1196   echo
1197   echo "Succeeded : \$count_ok"
1198   echo "Timeout   : \$count_timeout"
1199   echo "Failed    : \$count_err"
1200   echo "Absent    : \$count_absent"
1201   echo
1202   if test \$count_err -eq 0; then
1203      echo
1204      echo "******** ALL TESTS COMPLETED SUCCESSFULLY ********"
1205      echo
1206   fi
1207fi
1208
1209if test \$count_err -eq 0; then
1210   touch \${checkdir}/check.success
1211else 
1212   touch \${checkdir}/check.failed
1213fi
1214
1215exit \$count_err
1216EOF
1217
1218# Set execute mode to script
1219chmod a+x "$x_out"
1220
1221exit 0
1222