#!/bin/bash # COLORS RED="\001\e[0;31m\002" GREEN="\001\e[0;32m\002" YELLOW="\001\e[0;33m\002" BLUE="\001\e[0;34m\002" MAGENTA="\001\e[0;35m\002" CYAN="\001\e[0;36m\002" WHITE="\001\e[0;37m\002" B_RED="\001\e[1;31m\002" B_GREEN="\001\e[1;32m\002" B_YELLOW="\001\e[1;33m\002" B_BLUE="\001\e[1;34m\002" B_MAGENTA="\001\e[1;35m\002" B_CYAN="\001\e[1;36m\002" B_WHITE="\001\e[1;37m\002" ENDCO="\001\e[0m\002" # copy the executable to current directory rm -rf ./minishell cp ../../minishell . # globale variables UNIT_TEST=0 SUCCESS_TEST=0 TOTAL_TEST=0 TOTAL_SUCCESS=0 LINE_NUMBER=0 OPTION=0 PRINT=0 mkdir -p ./logs echo "" > ./logs/bash_log.txt echo "" > ./logs/minishell_log.txt BASH_LOG="./logs/bash_log.txt" MINISHELL_LOG="./logs/minishell_log.txt" # default list of files to be use default_files="\ ut_builtins.sh ut_exit_status.sh ut_expensions.sh ut_heredocs.sh ut_pipes.sh ut_redirections.sh ut_vrac.sh" # print usage function print_usage { echo -en "$GREEN" echo " usage :" echo -en "$ENDCO" echo -en "$CYAN" echo " > bash test_unit.sh [options] [list files...]" echo -en "$ENDCO" echo "" echo -en "$GREEN" echo " if no files are given in parameters, the defaults will be used" echo " defaults files :" echo -en "$ENDCO" echo -en "$CYAN" echo "$default_files" echo -en "$ENDCO" echo "" echo -en "$GREEN" echo " options :" echo -en "$ENDCO" echo -en "$CYAN" echo " help - print usage" echo " -p1 - prints errors" echo " -p2 - prints errors and commands" echo " -p3 - prints errors and commands and errors output" echo -en "$ENDCO" echo "" echo -en "$GREEN" echo " tests files are formated with the following rules :" echo -en "$ENDCO" echo -en "$CYAN" echo " - a line starting with # is skipped" echo " - an empty line separate two sets of commands" echo " - other lines are commands" echo " - multiples lines in a row are executed as following commands" echo -en "$ENDCO" echo "" } # check for arguments, like options or files list # if no file in arguments, default file list is used list_files="$default_files" if [ $# -gt 0 ] then START=1 if [ "$1" == "help" ] then print_usage START=0 elif [ "$1" == "-p1" ] then PRINT=1 OPTION=1 elif [ "$1" == "-p2" ] then PRINT=2 OPTION=1 elif [ "$1" == "-p3" ] then PRINT=3 OPTION=1 fi if [ $OPTION -eq 1 ] then if [ $# -eq 1 ] then START=0 else START=2 fi fi if [ $START -gt 0 ] then list_files="" for (( i = $START ; i <= "$#" ; i++ )) do if [ -e "${!i}" ] then if [ -n "$list_files" ] then list_files+=$'\n' fi list_files+="${!i}" else print_usage echo " \"${!i}\" is not a valid file or option, see usage above" fi done fi fi # if print option, print next command function print_next_command { TEXT=$1 CMD=$2 COLOR=$3 INDENT="$(for (( i=1; i<=${#TEXT}; i++ )); do echo -n ' '; done)" echo -en $COLOR"$TEXT"$YELLOW echo -n "${CMD//$'\n'/$'\n'$INDENT}" echo -e $ENDCO } # function that will launch the command in bash and minishell and compare them function test_minishell { # if -p2|3, print which command is about to be executed if [ $PRINT -gt 1 ] then NEXT_CMD="command line $(( $LINE_NUMBER - 1 )) : " print_next_command "$NEXT_CMD" "$@" "$CYAN" fi # execute commands in bash, and logs results bash_execution=$( echo "$@" | bash 2>/dev/null ) echo -e $B_WHITE"\n\n$@\n-----------"$ENDCO >>$BASH_LOG echo "$bash_execution" >> $BASH_LOG minishell_execution=$( echo "$@" | ./minishell 2>/dev/null ) echo -e $B_WHITE"\n\n$@\n-----------"$ENDCO >>$MINISHELL_LOG echo "$minishell_execution" >> $MINISHELL_LOG #compare output if [ "$bash_execution" = "$minishell_execution" ] then (( SUCCESS_TEST++ )) (( TOTAL_SUCCESS++ )) else # if -p1..3 print error for command if [ $PRINT -eq 1 ] then ERROR_CMD="ERROR line $(( $LINE_NUMBER - 1 )), command : " print_next_command "$ERROR_CMD" "$@" "$B_RED" elif [ $PRINT -eq 2 ] then echo -e $B_RED" "'\'" ERROR"$ENDCO elif [ $PRINT -eq 3 ] then echo -e $B_RED" "'\'" ERROR"$ENDCO echo -e $B_MAGENTA"[bash execution] :"$ENDCO echo "$@" | bash -i echo "" echo -e $B_MAGENTA"[minishell execution] :"$ENDCO echo "$@" | ./minishell echo "" fi fi } # function to print the results # receive parameters : file name, numerator, denominator function print_results { echo -en $B_WHITE"results for $1 : "$ENDCO if [ $2 -eq 0 ] then echo -en $B_RED $2 $ENDCO elif [ $2 -eq $3 ] then echo -en $B_GREEN $2 $ENDCO else echo -en $B_MAGENTA $2 $ENDCO fi echo -e $B_WHITE"/ $3"$ENDCO } # the main loop: go through the files and call the compare func on each commands # parse tests files line by line, grouping lines non-separated by an empty line # if line start with # it's ignore for i in $list_files do filename=$i echo -e "\n"$B_YELLOW"test file : $i"$ENDCO command_test="" LINE_NUMBER=0 LAST_LINE_NUMBER=$(wc -l < $filename) UNIT_TEST=0 SUCCESS_TEST=0 # write name of file in log files echo -en $B_YELLOW "\n\n\nfile: $filename\n" $ENDCO >>$BASH_LOG echo -en $B_YELLOW "\n\n\nfile: $filename\n" $ENDCO >>$MINISHELL_LOG # do the loop while read line do (( LINE_NUMBER++ )) if [ -n "$line" ] then # if line start with # skip it if [ "${line:0:1}" != "#" ] then if [ "$command_test" == "" ] then command_test="$line" else command_test+=$'\n' command_test+="$line" fi if [ $LINE_NUMBER -eq $LAST_LINE_NUMBER ] then (( UNIT_TEST++ )) (( TOTAL_TEST++ )) test_minishell "$command_test" fi fi elif [ -z "$line" ] && [ -n "$command_test" ] then (( UNIT_TEST++ )) (( TOTAL_TEST++ )) test_minishell "$command_test" command_test="" fi done < $filename print_results $i $SUCCESS_TEST $UNIT_TEST done # print the total results if [ -n "$list_files" ] then echo "" print_results "all" $TOTAL_SUCCESS $TOTAL_TEST fi # ask to show the diff read -p 'you want to see the diff ? (y?)' DIFF if [[ "${DIFF,,}" =~ y|yes ]] then diff -y --width=100 --color=always "$BASH_LOG" "$MINISHELL_LOG" fi