#!/bin/bash # cmcsexeimport --csmes coco/tst_models/tst_models.csmes --title tst_models --csexe coco/tst_models/tst_models.csexe 2>coco/log/tst_models_cmcsexeimport.err | tee coco/tst_models/tst_models_cmcsexeimport.log # cmreport --csmes=tst_models/tst_models.csmes --html=Report/index 2>coco/log/tst_models_cmreport.err | tee coco/tst_models/tst_models_cmreport.log ERR_TESTSUITE=10000 ERR_COCO_SERVER_CONNECTION=1001 ERR_CANBUS_SETUP=1002 COCO_SERVER=192.168.10.41 QT_VER=5.15.10 QT_PATH="/opt/Qt$QT_VER/$QT_VER/gcc_64/bin" QT_TESTS_LIST_FILE=tst_names.lst QT_TESTS_LIST_PATH=$HOME/Projects/scripts/local/ APPLICATION_DIR=application TESTSUITE_DIR=testsuites WORKING_DIR=coco LOG_DIR=logs BUILD_DIR=build MERGE_DIR=merge REPORT_DIR=report DENALI_SQUISH=denaliSquish REPORT_TYPE="html" COVERAGE_METHOD="" COVERAGE_NAME="" PROJECT_PATH=$HOME/Projects WORKING_PATH=$HOME/coco REPORT_PATH=$WORKING_PATH/$REPORT_DIR LOG_PATH=$WORKING_PATH/$LOG_DIR BUILD_PATH=$WORKING_PATH/$BUILD_DIR MERGE_PATH=$WORKING_PATH/$MERGE_DIR AUT_PATH="$BUILD_PATH/$DENALI_SQUISH" APPLICATION_PATH=$PROJECT_PATH/$APPLICATION_DIR TESTSUITE_PATH=$PROJECT_PATH/$TESTSUITE_DIR VCAN_SCRIPT=$PROJECT_PATH/scripts/setupCAN/setupVCAN.sh SQUISH_SERVER=/opt/squish-for-qt-7.1-20230505-1514/bin/squishserver SQUISH_RUNNER=/opt/squish-for-qt-7.1-20230505-1514/bin/squishrunner REPORT_COCO=$REPORT_PATH/coco REPORT_SQUISH=$REPORT_PATH/squish REPORT_QTTEST=$REPORT_PATH/qttest SEPARATION_LINE="------------------------------------------------------------------------------" ##### ---------- HELPER ----------------------------------------------------------------------------------------------- function generate_alarm_mapping() { echo " ------------------------------ Generating the alarms mapping" local start_time=`date` echo $SEPARATION_LINE 2>&1 | tee -a $SUMMARY_LOG echo "Generating the alarms mapping - $start_time" 2>&1 | tee -a $SUMMARY_LOG # alarmMapping must run in the application folder. pushd $APPLICATION_PATH ./alarmMapping.sh local end_time=`date` elapsed_time "$start_time" "$end_time" "Alarms mapping completed - elapsed time" popd } ##### ---------- SERVER ----------------------------------------------------------------------------------------------- ##### ---------- SERVER COCO ------------------------------------------------------------------------------------------ function server_coco_check() { ping "$COCO_SERVER" -c 2 -W 1 if [ "$?" != "0" ]; then echo " ------------------------------ Coco Lic Server unreachable" echo "*** Coco Lic Server unreachable ***" 2>&1 | tee -a $SUMMARY_LOG exit $ERR_COCO_SERVER_CONNECTION fi } ##### ---------- SERVER SQUISH ---------------------------------------------------------------------------------------- function server_squish_start() { echo " ------------------------------ Starting the Squish Server" echo "Starting the Squish Server" 2>&1 | tee -a $SUMMARY_LOG # configuring the server $SQUISH_SERVER \ --config addAUT $DENALI_SQUISH \ $AUT_PATH/ \ 2> $LOG_PATH/squishqtserver.err \ | tee $LOG_PATH/squishqtserver.log # running the server $SQUISH_SERVER & # must have '&' } function server_squish_run() { echo " ------------------------------ Starting tests $TESTSUITE_PATH" echo "Starting tests $TESTSUITE_PATH" 2>&1 | tee -a $SUMMARY_LOG $SQUISH_RUNNER \ --testsuite $TESTSUITE_PATH \ --reportgen html,$REPORT_SQUISH \ 2> $LOG_PATH/squishqtrunner.err \ | tee $LOG_PATH/squishqtrunner.log } function server_squish_stop() { echo " ------------------------------ Stopping the Squish Server" echo "Stopping the Squish Server" 2>&1 | tee -a $SUMMARY_LOG $SQUISH_SERVER --stop } ##### ---------- INIT ------------------------------------------------------------------------------------------------- function cleanup_directories() { echo "Removing directories..." 2>&1 | tee -a $SUMMARY_LOG rm -frd $WORKING_PATH mkdir -p $WORKING_PATH mkdir -p $LOG_PATH mkdir -p $MERGE_PATH mkdir -p $REPORT_PATH mkdir -p $REPORT_COCO mkdir -p $REPORT_SQUISH mkdir -p $REPORT_QTTEST } date_to_timestamp() { date -d "$1" +"%s" } function elapsed_time() { start_timestamp=$(date_to_timestamp "$1") end_timestamp=$(date_to_timestamp "$2") title="Elapsed time" # Check if $3 (title) has any value if [ -n "$3" ]; then title="$3" fi time_difference=$((end_timestamp - start_timestamp)) minutes=$((time_difference / 60)) seconds=$((time_difference % 60)) echo "$title $minutes minutes and $seconds seconds" 2>&1 | tee -a $SUMMARY_LOG } function get_report_options(){ REPORT_TYPE="html" # --coverage-mcc: Report multiple condition code coverage measurements. # --coverage-mcdc: Report MC/DC coverage measurements. # --coverage-condition: Report condition coverage measurements. # --coverage-decision: Report decision coverage measurements. # --line-coverage: Report line coverage measurements. # --function-coverage: Report function coverage measurements. COVERAGE_NAME="" COVERAGE_METHOD="" for param in "$@"; do case $param in "--html") REPORT_TYPE="html" ;; "--csv") REPORT_TYPE="csv" ;; "--mcc") COVERAGE_METHOD=" --coverage-mcc " COVERAGE_NAME="_mcc" ;; "--mcdc") COVERAGE_METHOD=" --coverage-mcdc " COVERAGE_NAME="_mcdc" ;; "--condition") COVERAGE_METHOD=" --coverage-condition " COVERAGE_NAME="_condition" ;; "--decision") COVERAGE_METHOD=" --coverage-decision " COVERAGE_NAME="_decision" ;; "--line") COVERAGE_METHOD=" --line-coverage " COVERAGE_NAME="_line" ;; "--function") COVERAGE_METHOD=" --function-coverage " COVERAGE_NAME="_function" ;; *) # Handle unknown parameters ;; esac done if [ -z "$COVERAGE_NAME" ]; then echo "*** Warning *** No coverage method selected! Using default 'Condition coverage'" 2>&1 | tee -a $SUMMARY_LOG COVERAGE_METHOD=" --coverage-condition " COVERAGE_NAME="_condition" fi } function copy_report_folder() { # make a copy of the report folder using folder name with coverage method used if [ -d "$REPORT_PATH" ]; then local new_name="$WORKING_PATH/report$1$COVERAGE_NAME" # remove folder if it exists if [ -d "$new_name" ]; then rm -rf $new_name fi echo "Copying $REPORT_PATH to new folder $new_name" 2>&1 | tee -a $SUMMARY_LOG cp -r $REPORT_PATH $new_name fi } function usage(){ echo "Usage:" echo "run.coco.sh [options]" echo " --build Build and compile the application" echo " --run Run testsuite" echo " --merge Merge test results" echo " --report [type] [coverage method] Generate html or csv report" echo " type options: " echo " --html Default" echo " --csv Comma separated value" echo " coverage method options:" echo " --condition (Default) - Report condition coverage measurements" echo " --mcc Report multiple condition code coverage measurements" echo " --mcdc Report MC/DC coverage measurements" echo " --decision Report decision coverage measurements" echo " --line Report line coverage measurements" echo " --function Report function coverage measurements" echo "" echo " --reports [type] [coverage method] Create separate reports" echo " --all [type] [coverage method] Perform all phases: Build, run, merge, and reports" } ##### ---------- TESTS ------------------------------------------------------------------------------------------------ function tests_copy_list() { cp $QT_TESTS_LIST_PATH/$QT_TESTS_LIST_FILE $WORKING_PATH } function tests_read_list() { QT_TESTS_LIST=() # initialize empty array # read a line at a time from file named $QT_TESTS_LIST_FILE. echo "Test List:" 2>&1 | tee -a $SUMMARY_LOG echo " ------------------------------ Test List:" while read -r line do # remove leading spaces, remove lines that starts with #, store result in test test=`echo $line | sed -e 's/^[[:space:]]*//' | sed -e '/^#/d'` # if test is not empty then add it to the array if [ "$test" != "" ]; then QT_TESTS_LIST+=($test) echo " - $test" 2>&1 | tee -a $SUMMARY_LOG fi done < "$QT_TESTS_LIST_FILE" } function tests_setup() { if [ $($VCAN_SCRIPT) -eq 0 ];then echo " ------------------------------ Canbus setup failed" echo "*** Canbus setup failed ***" 2>&1 | tee -a $SUMMARY_LOG exit $ERR_CANBUS_SETUP fi } function tests_run() { for test in ${QT_TESTS_LIST[@]};do pushd $BUILD_PATH/$test if [ "$test" == "$DENALI_SQUISH" ]; then server_squish_start server_squish_run server_squish_stop else $BUILD_PATH/$test/$test \ 2> $LOG_PATH/$test.err \ | tee $REPORT_QTTEST/$test.report fi popd done } ##### ---------- COVERAGE --------------------------------------------------------------------------------------------- function coverage_build() { echo " ------------------------------ Run qmake" echo $(pwd) local start_time=`date` echo $SEPARATION_LINE 2>&1 | tee -a $SUMMARY_LOG echo "Building - $1 - $start_time" 2>&1 | tee -a $SUMMARY_LOG $QT_PATH/qmake \ $APPLICATION_PATH/denali.pro \ -spec linux-g++ \ CONFIG+="$1" \ CONFIG+=CodeCoverage \ TARGET="$BUILD_PATH/$1/$1" echo "Run make" /usr/bin/make \ LINK=csg++ AR=csar CXX=csg++ CC=csgcc -j4 \ 2> "$LOG_PATH/build_$1".err \ | tee "$LOG_PATH/build_$1".log /usr/bin/make clean rm *.csmes echo " ------------------------------ Cleaned for next build" local end_time=`date` elapsed_time "$start_time" "$end_time" "Building completed - elapsed time" } function coverage_merge() { # Use utility "cmmerge" to merge several instrumentation databases (.csmes file) together # cmmerge -o ... local start_time=`date` echo $SEPARATION_LINE 2>&1 | tee -a $SUMMARY_LOG echo "Merging the excecution report databases - $start_time" 2>&1 | tee -a $SUMMARY_LOG echo " ------------------------------ Merging the excecution report databases" local csmes="" # Get all csmes reports from each test case for test in ${QT_TESTS_LIST[@]};do csmes+="$BUILD_PATH/$test/$test.csmes " done cmmerge \ -o $MERGE_PATH/$MERGE_DIR.csmes \ $csmes \ 2> $LOG_PATH/$MERGE_DIR.err \ | tee $LOG_PATH/$MERGE_DIR.log local end_time=`date` elapsed_time "$start_time" "$end_time" "Merging completed - elapsed time" } function coverage_import() { local start_time=`date` echo $SEPARATION_LINE 2>&1 | tee -a $SUMMARY_LOG echo "Importing execution report into coverage database - $start_time" 2>&1 | tee -a $SUMMARY_LOG echo " ------------------------------ Importing the execution report into the coverage database" local csexe="" for test in ${QT_TESTS_LIST[@]};do echo $BUILD_PATH/$test/$test.csexe cmcsexeimport \ --csmes=$MERGE_PATH/$MERGE_DIR.csmes \ --title=$test \ --csexe=$BUILD_PATH/$test/$test.csexe \ 2> $LOG_PATH/import_$test.err \ | tee $LOG_PATH/import_$test.log done local end_time=`date` elapsed_time "$start_time" "$end_time" "Importing completed - elapsed time" } function coverage_report() { # cmreport – Code coverage report generation utility # Coverage method options # --coverage-mcc: Report multiple condition code coverage measurements. # --coverage-mcdc: Report MC/DC coverage measurements. # --coverage-condition: Report condition coverage measurements. # --coverage-decision: Report decision coverage measurements. # --line-coverage: Report line coverage measurements. # --function-coverage: Report function coverage measurements. # #REPORT_TYPE="html" REPORT_CMD="--html=$REPORT_COCO/index" if [[ "$REPORT_TYPE" == "csv" ]]; then REPORT_TYPE="csv" REPORT_FILE=report_out.csv REPORT_CMD="--csv-excel=$REPORT_FILE" fi local start_time=`date` echo $SEPARATION_LINE 2>&1 | tee -a $SUMMARY_LOG echo "Generating coverage report - $start_time" 2>&1 | tee -a $SUMMARY_LOG echo " ------------------------------ Generating the coverage report <$REPORT_TYPE>" cmreport \ $COVERAGE_METHOD \ --csmes=$MERGE_PATH/$MERGE_DIR.csmes \ $REPORT_CMD \ 2> $LOG_PATH/report.err \ | tee $LOG_PATH/report.log if [[ "$REPORT_TYPE" == "csv" ]]; then mv report_out.csv report/ fi echo " ------------------------------ Out file location : $(pwd)/$REPORT_COCO/$REPORT_FILE" local end_time=`date` echo "Single report generated: $(pwd)/$REPORT_COCO/$REPORT_FILE - $end_time" 2>&1 | tee -a $SUMMARY_LOG elapsed_time "$start_time" "$end_time" "" echo "" } function separate_coverage_reports() { echo "Processing separate execution reports" > $LOG_PATH/$MERGE_DIR.err | tee $LOG_PATH/$MERGE_DIR.log # Each Loop iteration do: # 1) Get csmes value # 2) Execute coverage using coco command "cmcsexeimport" # 3) Execute coverage report using coco command "cmreport" for test in ${QT_TESTS_LIST[@]};do local start_time=`date` csmes="$BUILD_PATH/$test/$test.csmes" # coverage import echo $BUILD_PATH/$test/$test.csexe cmcsexeimport --csmes=$csmes --title==$test --csexe=$BUILD_PATH/$test/$test.csexe \ 2> $LOG_PATH/import_$test.err | tee $LOG_PATH/import_$test.log fname=$(basename "$csmes") # remove path REPORT_FILE="${fname%.*}" # remove extension #REPORT_TYPE="html" REPORT_CMD="--html=$REPORT_COCO/$REPORT_FILE" # .html echo $SEPARATION_LINE 2>&1 | tee -a $SUMMARY_LOG echo "Generating report ${REPORT_FILE}.${REPORT_TYPE} - $start_time" 2>&1 | tee -a $SUMMARY_LOG if [[ "$REPORT_TYPE" == "csv" ]]; then REPORT_TYPE="csv" REPORT_FILE="${REPORT_FILE}.csv" REPORT_CMD="--csv-excel=$REPORT_FILE" fi echo "$COVERAGE_METHOD" cmreport \ $COVERAGE_METHOD --csmes=$csmes $REPORT_CMD \ 2> $LOG_PATH/report.err | tee $LOG_PATH/report.log if [[ "$REPORT_TYPE" == "csv" ]]; then mv report_out.csv report/ fi local end_time=`date` echo "Report generation completed - `date` " 2>&1 | tee -a $SUMMARY_LOG elapsed_time "$start_time" "$end_time" "" echo "" done } # Different functions callld from main entry that correspond to the phases: # build # run # merge # report # reports # all function build_phase() { server_coco_check cleanup_directories local start_time=`date` echo "$SEPARATION_LINE" 2>&1 | tee -a $SUMMARY_LOG echo "Starting Build Phase $start_time" 2>&1 | tee -a $SUMMARY_LOG echo "$SEPARATION_LINE" 2>&1 | tee -a $SUMMARY_LOG cd $WORKING_PATH tests_copy_list tests_read_list generate_alarm_mapping for test in ${QT_TESTS_LIST[@]};do coverage_build $test done local end_time=`date` echo "*** Build phase completed *** `date`" 2>&1 | tee -a $SUMMARY_LOG elapsed_time "$start_time" "$end_time" "Build phase elapsedd time" } function run_phase() { touch $LOG_PATH/sun_summary.log local start_time=`date` echo "$SEPARATION_LINE" 2>&1 | tee -a $SUMMARY_LOG echo "Starting Run Phase $start_time" 2>&1 | tee -a $SUMMARY_LOG echo "$SEPARATION_LINE" 2>&1 | tee -a $SUMMARY_LOG cd $WORKING_PATH tests_read_list tests_run local end_time=`date` echo "*** Run phase completed *** `date`" 2>&1 | tee -a $SUMMARY_LOG elapsed_time "$start_time" "$end_time" "Run phase elapsed time" } function merge_phase() { local start_time=`date` echo "$SEPARATION_LINE" 2>&1 | tee -a $SUMMARY_LOG echo "Starting Merge Phase $start_time" 2>&1 | tee -a $SUMMARY_LOG echo "$SEPARATION_LINE" 2>&1 | tee -a $SUMMARY_LOG server_coco_check cd $WORKING_PATH tests_read_list # generate Q_TESTS_LIST coverage_merge coverage_import local end_time=`date` echo "*** Merge phase completed *** `date`" 2>&1 | tee -a $SUMMARY_LOG elapsed_time "$start_time" "$end_time" "Merge phase elapsed time" } function single_report_phase() { local start_time=`date` echo "$SEPARATION_LINE" 2>&1 | tee -a $SUMMARY_LOG echo "Generating SingleReport Phase $start_time" 2>&1 | tee -a $SUMMARY_LOG echo "Coverage Method: $COVERAGE_METHOD" 2>&1 | tee -a $SUMMARY_LOG echo "Report Type: $REPORT_TYPE" 2>&1 | tee -a $SUMMARY_LOG echo "$SEPARATION_LINE" 2>&1 | tee -a $SUMMARY_LOG server_coco_check cd $WORKING_PATH coverage_report "$2" local end_time=`date` echo "*** Single global report phase completed *** `date`" 2>&1 | tee -a $SUMMARY_LOG elapsed_time "$start_time" "$end_time" "Single report generation phase elapsed time " } function separate_report_phase() { local start_time=`date` echo "$SEPARATION_LINE" 2>&1 | tee -a $SUMMARY_LOG echo "Generating Separte Reports Phase $start_time" 2>&1 | tee -a $SUMMARY_LOG echo "Coverage Method: $COVERAGE_METHOD" 2>&1 | tee -a $SUMMARY_LOG echo "Report Type: $REPORT_TYPE" 2>&1 | tee -a $SUMMARY_LOG echo "$SEPARATION_LINE" 2>&1 | tee -a $SUMMARY_LOG server_coco_check cd $WORKING_PATH tests_read_list # generate Q_TESTS_LIST separate_coverage_reports "$2" local end_time=`date` echo "*** Separte Reports phase completed *** `date`" 2>&1 | tee -a $SUMMARY_LOG elapsed_time "$start_time" "$end_time" "Seperate report generation phase elapsed time" } ##### ---------- MAIN ------------------------------------------------------------------------------------------------- clear # if --help or no parameters provided then show usage if [ "$1" == "" ] || [ "$1" == "--help" ]; then usage exit 0 fi # Check if the SUMMARY_LOG file exists, if not create it # summary log provides brief description of script task being executed, timestamp, and elapsed time # summary.log will be recreated when build option is triggered. # Entries will be appended since last build option SUMMARY_LOG="$LOG_PATH/summary.log" if [ ! -f "$SUMMARY_LOG" ]; then # Create the log file with a timestamp header echo "$SEPARATION_LINE" > "$SUMMARY_LOG" echo "Summary Log - created on $(date)" >> "$SUMMARY_LOG" echo "$SEPARATION_LINE" >> "$SUMMARY_LOG" echo " " >> "$SUMMARY_LOG" fi app_start_time=`date` # used to calculate entire script elapsed time at the end if [ "$1" == "--build" ]; then build_phase elif [ "$1" == "--run" ]; then run_phase elif [ "$1" == "--merge" ]; then merge_phase elif [ "$1" == "--report" ]; then get_report_options "$@" # report Type, coverage_method single_report_phase copy_report_folder "_single" # make a copy of the report folder using coveerage method used elif [ "$1" == "--reports" ]; then get_report_options "$@" # report Type, coverage_method separate_report_phase copy_report_folder "_multi" # make a copy of the report folder using coveerage method used elif [ "$1" == "--all" ]; then get_report_options "$@" # report Type, coverage_method build_phase run_phase merge_phase single_report_phase separate_report_phase copy_report_folder "_all" # make a copy of the report folder using coverage method used else usage exit 1 fi echo "$SEPARATION_LINE" 2>&1 | tee -a $SUMMARY_LOG echo "End of script - $(date)" 2>&1 | tee -a $SUMMARY_LOG echo "$SEPARATION_LINE" 2>&1 | tee -a $SUMMARY_LOG app_end_time=`date` elapsed_time "$app_start_time" "$app_end_time" "Total phase(s) elapsed time"