#!/bin/bash # Local example $./run.unittest.sh :0 5.12.5 /media/sf_VMSHARE PYCOMMON="" # use anything other that "" to use pycommon as SquishQt API lib source # TODO pycommon is not needed right? reportDir="" function readTestsList() { TESTS_LIST=() input=$WORKING_DIR/scripts/build/tst_names.lst while read -r line do if [ "$line" != "" ]; then TESTS_LIST+=($line) fi done < "$input" } function getSupportFunctions() { if [[ ! -d "supportscript" ]] then git clone ssh://git@192.168.10.132:7999/bl/supportscript.git fi source ./supportscript/supportscript.sh } # shellcheck disable=SC2120 function setup_Script_Environment() { if [ -z "$RUN_FOR_LOCAL" ];then #is NOT local getSupportFunctions fi # --- keep Test Folder folder PWD=$(pwd) WORKING_DIR=$PWD # --- keep Local Project Folder LOCAL_PROJECT_DIR=$HOME/Projects # --- setup local or server Environment DISPLAY_NO=:10.0 QT_VER="" DENALI_SQUISH=denaliSquish # TODO what are these for local? Do we still need them? if [ ! -z "$RUN_FOR_LOCAL" ];then #is local DISPLAY_NO=:0 QT_VER="5.12.5" SERVER_DIR="/media/sf_VMSHARE" #Setting up Display number if [ ! -z "$1" ]; then DISPLAY_NO=$1 fi #setup Qt dir version if [ ! -z "$2" ]; then QT_VER=$2 fi #Setting up server folder if [ ! -z "$1" ]; then SERVER_DIR=$3 fi fi # --- setup common SQUISH_SERVER_PORT=4322 QT_DIR="/opt/Qt$QT_VER/5.12.5/gcc_64" SQUISH_DIR="/opt/squishqt" COCO_DIR="/opt/SquishCoco" # Create the folder and a status report csv file PROJECT_NAME_INDEX=0 PROJECT_CHECKOUT_INDEX=8 COMMON_CHECKOUT_INDEX=9 BUILD_ONLY_FLAG_INDEX=10 local isBuildLocal=false setBuildVariables ${buildSpecs[@]} REPORT_DIR=$(getRemoteCopyAddress "DEN_UI" ${buildSpecs[$PROJECT_CHECKOUT_INDEX]}) reportDir=$REPORT_DIR STATUS_REPORT=$(createStatusReport "application" $REPORT_DIR $isBuildLocal) # Call this function to check if the repository has to be tagged or not tagUIRepository getCommitHashes $STATUS_REPORT ${buildSpecs[$PROJECT_NAME_INDEX]} ${buildSpecs[$PROJECT_CHECKOUT_INDEX]} \ ${buildSpecs[$COMMON_CHECKOUT_INDEX]} "" ${buildSpecs[$PROJECT_CHECKOUT_INDEX]} BUILD_DIR=build BUILD_PATH=$WORKING_DIR/$BUILD_DIR REPORT=Report LOG=Logs REPORT_PATH=$WORKING_DIR/$REPORT LOG_PATH=$REPORT_PATH/$LOG UNITTEST_RESULT=0 } function setup_System_Environment() { # TODO why are these exported? export PATH=$PATH:$QT_DIR/bin/:$QT_DIR/lib export PATH=$COCO_DIR/wrapper/bin/:$COCO_DIR/bin/:$PATH export LD_LIBRARY_PATH=$QT_DIR/lib export DISPLAY=$DISPLAY_NO export DISPLAY_SQUISHQT=97 if [ ! -z "$PYCOMMON" ]; then export PYTHONPATH=$WORKING_DIR/common/pycommon/squishapi/:$PYTHONPATH fi } getAlarmMapping() { local currentDir=$(pwd) ../scripts/build/alarmMapping ../common/common/ ../application/sources/model/hd/alarm/ cd ../application # For good measures add email and user name all the time git config --global user.email "dnavaei@diality.com" git config --global user.name "Dara Navaei" git add sources/model/hd/alarm/MAlarmMapping.cpp git commit -m "Bamboo Commit: Updated MAlarmMapping.cpp" git push origin cd $currentDir cp ../scripts/build/AlarmMapping.csv $reportDir } function make_Directories() { echo " ------------------------------ Create the Report output/log folder" mkdir -p $LOG_PATH echo " ------------------------------ Create the UnitTest results folder" mkdir -p $REPORT_PATH/UnitTest echo " ------------------------------ Build Application " mkdir $BUILD_PATH cd $BUILD_PATH } function clone_Repositories() { # TODO this function is not needed anymore cd $WORKING_DIR echo " ------------------------------ Clone Denali " if [ -z "$RUN_FOR_LOCAL" ]; then git clone ssh://git@dvm-linux02:7999/bl/setupscript.git ./setupscript/projectsetup.sh ${buildSpecs[$PROJECT_NAME_INDEX]} ${buildSpecs[$PROJECT_CHECKOUT_INDEX]} \ ${buildSpecs[$COMMON_CHECKOUT_INDEX]} else cp -r $LOCAL_PROJECT_DIR/application application cp -r $LOCAL_PROJECT_DIR/common common fi echo " ------------------------------ Clone the Test Suites" if [ -z "$RUN_FOR_LOCAL" ]; then git clone ssh://git@dvm-linux02:7999/ui/testsuites.git testsuites local currentDir=$(pwd) if [[ ! -z ${buildSpecs[$PROJECT_CHECKOUT_INDEX]} ]] then cd testsuites git checkout ${buildSpecs[$PROJECT_CHECKOUT_INDEX]} cd $currentDir fi # If the checkout branch/tag is not master, create and install # Dialin of the specified branch/tag if [[ ${buildSpecs[$PROJECT_CHECKOUT_INDEX]} != "master" ]] then cd testsuites rm -rf venv virtualenv --python=python3.6 venv source venv/bin/activate pip3 install git+ssh://git@192.168.10.132:7999/vv/dialin.git@${buildSpecs[$PROJECT_CHECKOUT_INDEX]} else cd testsuites/tools ./setup_env.sh ${buildSpecs[$PROJECT_CHECKOUT_INDEX]} fi # Updated paths.ini # Cannot use sudo in an automated script # The path to workspace_UI has been updated in /opt/squishqt/etc/paths.ini manually #sudo python3 update_paths.py --squishqt $SQUISH_DIR else cp -r $LOCAL_PROJECT_DIR/testsuites testsuites fi } function build_WithCoverage() { # ------------------------------ run qmake $QT_DIR/bin/qmake \ $WORKING_DIR/application/denali.pro \ -spec linux-g++ \ CONFIG+=qtquickcompiler \ CONFIG+="$1" \ CONFIG+=CodeCoverage \ TARGET="$1" # ------------------------------ run make /usr/bin/make \ LINK=csg++ AR=csar CXX=csg++ CC=csgcc -j4 \ 2> $LOG_PATH/build_for_"$1".err \ | tee $LOG_PATH/build_for_"$1".log # ------------------------------ clear for next build /usr/bin/make clean } function run_QtTest() { # ------------------------------ build_WithCoverage build_WithCoverage "$1" # ------------------------------ run the test ./"$1" -o -,txt \ 2> $LOG_PATH/QtTest_"$1".err \ | tee $LOG_PATH/QtTest_"$1".log # ------------------------------ check result UNITTEST_RESULT=$((UNITTEST_RESULT+$?)) } function start_xvfb() { # Starts a virtual display if [ $# -eq 0 ] then echo "Usage: $0 new_display_number" return 1 fi echo "start_xvfb: Display: $1" xvfb-run --server-num=$1 --server-args="-ac -screen 0 1280x1024x24" dbus-run-session xfwm4 & XVFB_PID=$! echo "XVFB_PID: $XVFB_PID" } function stop_xvfb() { if [[ ! -z $XVFB_PID ]]; then kill -9 $XVFB_PID fi # in case it was left running with an unknown PID killall run-xvfb killall Xvfb sleep 2 } function start_SquishServer() { echo " ------------------------------ Starting the Squish Server" stop_xvfb start_xvfb $DISPLAY_SQUISHQT $SQUISH_DIR/bin/squishserver \ --config addAUT $DENALI_SQUISH \ $WORKING_DIR/$BUILD_DIR/ \ 2> $LOG_PATH/squishqtserver.err \ | tee $LOG_PATH/squishqtserver.log DISPLAY=:$DISPLAY_SQUISHQT $SQUISH_DIR/bin/squishserver \ 1>> $LOG_PATH/squishqtserver.log \ 2>> $LOG_PATH/squishqtserver.err & # has to be & } function stop_SquishServer() { echo " ------------------------------ Stopping the Squish Server" $SQUISH_DIR/bin/squishserver --stop stop_xvfb $DISPLAY_SQUISHQT } function start_SquishRunner() { echo " ------------------------------ Starting tests" $SQUISH_DIR/bin/squishrunner \ --testsuite testsuites \ --exitCodeOnFail 10000 \ --reportgen html,$REPORT_PATH/UnitTest \ 2> $LOG_PATH/squishqtrunner.err \ | tee $LOG_PATH/squishqtrunner.log UNITTEST_RESULT=$((UNITTEST_RESULT+$?)) } function run_SquishQt() { cd $BUILD_PATH # ------------------------------ cocoInstrumentation build_WithCoverage $DENALI_SQUISH cd $WORKING_DIR start_SquishRunner } function run_Tests() { for test in ${TESTS_LIST[@]};do run_QtTest $test done copy_TestsResults start_SquishServer run_SquishQt stop_SquishServer } function check_TestResults() { failedUnitTests=() targetedCoverage=100 cd $REPORT_DIR cd Coverage/index_html # In the index.html, get the Coverage section (exact pattern) # Parse everything that is from .*prg0 to the tag # In the parsed section, get everything from .*prg2"> to % percentage=$(cat index.html | awk '/\yCoverage\y/' | sed -e 's/.*prg0//' -e 's/<\/PRE>.*//' | \ sed -e 's/.*prg2">//' -e 's/%.*//' | grep -o -E '[0-9]+([.][0-9]+)') # Remove the floating point of the number percentage=${percentage%.*} echo "Code Coverage is $percentage%" # Check if the coverage percentage is less than 100% if [[ $percentage -lt $targetedCoverage ]] then echo "Coverage test failed!" echo "Coverage Test, Failed, $percentage%" >> $STATUS_REPORT else echo "Coverage test passed!" echo "Coverage Test, Passed, $percentage%" >> $STATUS_REPORT fi echo "" >> $STATUS_REPORT cd $REPORT_DIR cd UnitTest # In the unit test folder, get the all the .log files logFiles=$(find . -type f -iname "*.log") for file in ${logFiles[@]} do # Inside each log file, find the exact pattern of Totals # Find the commas and print the 4th one which is the number of failed cases failures=$(cat $file | awk '/\yTotals\y/' | awk '/,/ {print $4}' | grep -o -E '[0-9]+') skipped=$(cat $file | awk '/\yTotals\y/' | awk '/,/ {print $6}' | grep -o -E '[0-9]+') blackListed=$(cat $file | awk '/\yTotals\y/' | awk '/,/ {print $6}' | grep -o -E '[0-9]+') # Remove ./ from the file name file=${file##*/} echo "$file has $failures failed cases" # Check if the number of failures is greater than 0 if [[ $failures -gt 0 ]] then failedUnitTests+=("$file,Failed_Cases,$failures") fi # Check if the number of skipped tests is greater than 0 if [[ $skipped -gt 0 ]] then failedUnitTests+=("$file,Skipped_Cases,$skipped") fi # Check if the number of blacklisted tests is greater than 0 if [[ $blackListed -gt 0 ]] then failedUnitTests+=("$file,BlackListed_Cases,$blackListed") fi done # If the list is not empty, the test has failed if [[ ! -z ${failedUnitTests[@]} ]] then echo "Unit Test, Failed" >> $STATUS_REPORT for test in ${failedUnitTests[@]} do echo $test >> $STATUS_REPORT done else echo "Unit Test, Passed" >> $STATUS_REPORT fi # Go to data folder cd data # Check for ERROR or FATAL in the results-v1.js file. # NOTE: ERROR or FATAL must be all upper case, it is case sensitive # -w is used to only search the exact word and not other words that contain # ERROR or FATAL local unitTestCoverage=$(cat results-v1.js | grep -w "ERROR\|FATAL") # If there are any errors, Check for the word PASS # NOTE: PASS is upper case. If there is an ERROR or FATAL, there should not be a PASS if [[ ! -z $unitTestCoverage ]] then local unitTestCoveragePct=$(echo $unitTestCoverage | grep "PASS") if [[ -z $unitTestCoveragePct ]] then echo "Unit Test Coverage, Failed" >> $STATUS_REPORT fi else echo "Unit Test Coverage, Passed" >> $STATUS_REPORT fi echo "" >> $STATUS_REPORT } function copy_TestsResults() { cp $LOG_PATH/QtTest*.log $REPORT_PATH/UnitTest/ } function mergeCoverages() { echo " ------------------------------ Merging the excecution report databases" local csmes="" for test in ${TESTS_LIST[@]};do csmes+=$BUILD_PATH/$test.csmes" " done cmmerge -o $BUILD_DIR/denali.csmes \ $BUILD_PATH/$DENALI_SQUISH.csmes\ $csmes \ 2> $LOG_PATH/cmmerge.err \ | tee $LOG_PATH/cmmerge.log } function importCoverage() { echo " ------------------------------ Importing the execution report into the coverage database" local csexe="" for test in ${TESTS_LIST[@]};do cmcsexeimport \ -m $BUILD_PATH/denali.csmes \ -t $test \ -e $BUILD_PATH/$test.csexe \ 2> $LOG_PATH/cmcsexeimport_$test.err \ | tee $LOG_PATH/cmcsexeimport_$test.log done cmcsexeimport \ -m $BUILD_PATH/denali.csmes \ -t Squish \ -e $BUILD_PATH/$DENALI_SQUISH.csexe \ 2> $LOG_PATH/cmcsexeimport_squish.err \ | tee $LOG_PATH/cmcsexeimport_squish.log } function reportCoverage() { echo " ------------------------------ Generating the coverage report" cmreport \ --csmes=$BUILD_PATH/denali.csmes \ --html=$REPORT_PATH/Coverage/index \ 2> $LOG_PATH/cmreport.err \ | tee $LOG_PATH/cmreport.log } function copy_TestsResults_IntoServer() { echo " ------------------------------ Copy the reports to server" cp -rd $REPORT_PATH/* $REPORT_DIR sync;sync;sync; } function main() { setup_Script_Environment setup_System_Environment # has to be after setup_Script_Environment ran clone_Repositories make_Directories getAlarmMapping if [[ ${buildSpecs[$BUILD_ONLY_FLAG_INDEX]} == false ]] then readTestsList run_Tests mergeCoverages importCoverage reportCoverage copy_TestsResults_IntoServer check_TestResults fi } main