diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e63c4189d..2d17cd088 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,8 +30,8 @@ jobs: export JAVA_HOME=$HOME/.java/$JDK_DIR echo "JAVA_HOME=$JAVA_HOME" >> $GITHUB_ENV echo "$JAVA_HOME/bin" >> $GITHUB_PATH - - name: Install diffstat - run: sudo apt-get install diffstat + - name: Install diffstat and checkbashisms + run: sudo apt-get -y install diffstat devscripts - name: Install Carton uses: perl-actions/install-with-cpanm@v1 with: diff --git a/README_DEVELOPER.md b/README_DEVELOPER.md index 29b55381f..3df2c9799 100644 --- a/README_DEVELOPER.md +++ b/README_DEVELOPER.md @@ -153,3 +153,9 @@ final data set, if this is still the case. Related, the test patches (.test.patch) stored in the repo are also not used. I think we should remove these as well. Source patches are manually minimized, but test patches are not -- these can be easily regenerated by running a diff between the buggy and fixed revisions. + +#### Style + +Because shell scripts are error-prone, we run a style checker on them. CI will +not pass if the style checker issues warnings. Please address each warning by +either correcting the problem or suppressing the warning. diff --git a/framework/lib/test_generation/bin/_tool.source b/framework/lib/test_generation/bin/_tool.source index 991ac7f3c..eba018413 100755 --- a/framework/lib/test_generation/bin/_tool.source +++ b/framework/lib/test_generation/bin/_tool.source @@ -24,6 +24,7 @@ die() { check_env() { local var="$1" local val + # shellcheck disable=SC2086 val="$(eval echo \$$var)" [ -z "$val" ] && die "Variable $var not set!" } diff --git a/framework/test/test_bug_mining.sh b/framework/test/test_bug_mining.sh index bfe68a795..7d57f3ac1 100755 --- a/framework/test/test_bug_mining.sh +++ b/framework/test/test_bug_mining.sh @@ -7,7 +7,7 @@ set -e -HERE=$(cd "$(dirname "$0")" && pwd) || (echo "cannot cd to $(dirname "$0")" && exit 1) +HERE="$(cd "$(dirname "$0")" && pwd)" || (echo "cannot cd to $(dirname "$0")" && exit 1) # Import helper subroutines and variables, and init Defects4J source "$HERE/test.include" || exit 1 @@ -16,7 +16,6 @@ init BUG_MINING_FRAMEWORK_DIR="$BASE_DIR/framework/bug-mining" [ -d "$BUG_MINING_FRAMEWORK_DIR" ] || die "$BUG_MINING_FRAMEWORK_DIR does not exist" -RESOURCES_INPUT_DIR="$HERE/resources/input/bug-mining" RESOURCES_OUTPUT_DIR="$HERE/resources/output/bug-mining" _check_output() { @@ -233,8 +232,8 @@ test_analyze_project() { [ -s "$work_dir/$failing_tests" ] || die "No failing test cases has been reported" # Same number of failing tests - local actual_num_failing_tests; actual_num_failing_tests=$(grep -a "^--- " "$work_dir/$failing_tests" | wc -l) - local expected_num_failing_tests; expected_num_failing_tests=$(grep -a "^--- " "$RESOURCES_OUTPUT_DIR/$failing_tests" | wc -l) + local actual_num_failing_tests; actual_num_failing_tests=$(grep -c -a "^--- " "$work_dir/$failing_tests") + local expected_num_failing_tests; expected_num_failing_tests=$(grep -c -a "^--- " "$RESOURCES_OUTPUT_DIR/$failing_tests") if [ "$actual_num_failing_tests" -ne "$expected_num_failing_tests" ]; then echo "Expected failing tests:" grep -a "^--- " "$RESOURCES_OUTPUT_DIR/$failing_tests" diff --git a/framework/test/test_cp.sh b/framework/test/test_cp.sh index f91c3ae26..b65cb8573 100755 --- a/framework/test/test_cp.sh +++ b/framework/test/test_cp.sh @@ -5,7 +5,7 @@ # ################################################################################ -HERE=$(cd "$(dirname "$0")" && pwd) || (echo "cannot cd to $(dirname "$0")" && exit 1) +HERE="$(cd "$(dirname "$0")" && pwd)" || (echo "cannot cd to $(dirname "$0")" && exit 1) # Import helper subroutines and variables, and init Defects4J source "$HERE/test.include" || exit 1 diff --git a/framework/test/test_d4j_query.sh b/framework/test/test_d4j_query.sh index ccc5d43ac..9e5a5a1f4 100755 --- a/framework/test/test_d4j_query.sh +++ b/framework/test/test_d4j_query.sh @@ -5,14 +5,14 @@ # ################################################################################ -HERE=$(cd "$(dirname "$0")" && pwd) || (echo "cannot cd to $(dirname "$0")" && exit 1) +HERE="$(cd "$(dirname "$0")" && pwd)" || (echo "cannot cd to $(dirname "$0")" && exit 1) # Import helper subroutines and variables, and init Defects4J source "$HERE/test.include" || exit 1 init -$BASE_DIR/framework/bin/defects4j query -p Collections -H >> $HERE"/temp" -result=`diff $HERE/temp $HERE/resources/output/d4j-query/1` +"$BASE_DIR"/framework/bin/defects4j query -p Collections -H >> "$HERE"/temp +result=$(diff "$HERE"/temp "$HERE"/resources/output/d4j-query/1) [ "$result" == "" ] || die "query \"-p Collections\" -H failed: $result" diff --git a/framework/test/test_export_command.sh b/framework/test/test_export_command.sh index ab36b358e..ed3daee86 100755 --- a/framework/test/test_export_command.sh +++ b/framework/test/test_export_command.sh @@ -10,7 +10,7 @@ # ################################################################################ -HERE=$(cd "$(dirname "$0")" && pwd) || (echo "cannot cd to $(dirname "$0")" && exit 1) +HERE="$(cd "$(dirname "$0")" && pwd)" || (echo "cannot cd to $(dirname "$0")" && exit 1) # Import helper subroutines and variables, and init Defects4J source "$HERE/test.include" || exit 1 diff --git a/framework/test/test_fix_test_suite.sh b/framework/test/test_fix_test_suite.sh index 9960c7a40..44f11440f 100755 --- a/framework/test/test_fix_test_suite.sh +++ b/framework/test/test_fix_test_suite.sh @@ -5,7 +5,7 @@ # ################################################################################ -HERE=$(cd "$(dirname "$0")" && pwd) || (echo "cannot cd to $(dirname "$0")" && exit 1) +HERE="$(cd "$(dirname "$0")" && pwd)" || (echo "cannot cd to $(dirname "$0")" && exit 1) # Import helper subroutines and variables, and init Defects4J source "$HERE/test.include" || exit 1 diff --git a/framework/test/test_gen_tests.sh b/framework/test/test_gen_tests.sh index 1a43e66d1..04ada7eef 100755 --- a/framework/test/test_gen_tests.sh +++ b/framework/test/test_gen_tests.sh @@ -12,7 +12,7 @@ # ################################################################################ -HERE=$(cd `dirname $0` && pwd) +HERE="$(cd "$(dirname "$0")" && pwd)" || (echo "cannot cd to $(dirname "$0")" && exit 1) # Import helper subroutines and variables, and init Defects4J source "$HERE/test.include" || exit 1 diff --git a/framework/test/test_monitor_test.sh b/framework/test/test_monitor_test.sh index 3843b3079..fef880bb2 100755 --- a/framework/test/test_monitor_test.sh +++ b/framework/test/test_monitor_test.sh @@ -6,7 +6,7 @@ # ################################################################################ -HERE=$(cd `dirname $0` && pwd) +HERE="$(cd "$(dirname "$0")" && pwd)" || (echo "cannot cd to $(dirname "$0")" && exit 1) # Import helper subroutines and variables, and init Defects4J source "$HERE/test.include" || exit 1 @@ -18,11 +18,11 @@ vid=${bid}f work_dir=$TMP_DIR/$pid-$vid # Checkout buggy version -defects4j checkout -p $pid -v $vid -w $work_dir || die "checkout program version $pid-$vid" +defects4j checkout -p $pid -v $vid -w "$work_dir" || die "checkout program version $pid-$vid" actual="$(mktemp)" expected="resources/monitor.test.expected" # Compile buggy version -defects4j monitor.test -t org.apache.commons.codec.binary.HexTest -w $work_dir > "$actual" || die "compile program version $pid-$vid" +defects4j monitor.test -t org.apache.commons.codec.binary.HexTest -w "$work_dir" > "$actual" || die "compile program version $pid-$vid" cmp "$actual" "$expected" || die "compare actual vs. expected output: $actual vs. $expected" diff --git a/framework/test/test_mutation_analysis.sh b/framework/test/test_mutation_analysis.sh index d2579711c..b42c8a316 100755 --- a/framework/test/test_mutation_analysis.sh +++ b/framework/test/test_mutation_analysis.sh @@ -7,7 +7,7 @@ # TODO: There is some code duplication in this test script, which we can avoid # by extracting the mutation analysis workflow into a parameterized function. -HERE=$(cd "$(dirname "$0")" && pwd) || (echo "cannot cd to $(dirname "$0")" && exit 1) +HERE="$(cd "$(dirname "$0")" && pwd)" || (echo "cannot cd to $(dirname "$0")" && exit 1) # Import helper subroutines and variables, and init Defects4J source "$HERE/test.include" || exit 1 @@ -56,10 +56,10 @@ _check_mutation_result() { # Columns of summary (csv) file: # MutantsGenerated,MutantsRetained,MutantsCovered,MutantsKilled,MutantsLive,RuntimePreprocSeconds,RuntimeAnalysisSeconds - local act_mut_gen=$(tail -n1 "$summary_file" | cut -f1 -d',') - local act_mut_ret=$(tail -n1 "$summary_file" | cut -f2 -d',') - local act_mut_cov=$(tail -n1 "$summary_file" | cut -f3 -d',') - local act_mut_kill=$(tail -n1 "$summary_file" | cut -f4 -d',') + local act_mut_gen; act_mut_gen=$(tail -n1 "$summary_file" | cut -f1 -d',') + local act_mut_ret; act_mut_ret=$(tail -n1 "$summary_file" | cut -f2 -d',') + local act_mut_cov; act_mut_cov=$(tail -n1 "$summary_file" | cut -f3 -d',') + local act_mut_kill; act_mut_kill=$(tail -n1 "$summary_file" | cut -f4 -d',') [ "$act_mut_gen" -eq "$exp_mut_gen" ] || die "Unexpected number of mutants generated (expected: $exp_mut_gen, actual: $act_mut_gen)!" [ "$act_mut_ret" -eq "$exp_mut_ret" ] || die "Unexpected number of mutants retained (expected: $exp_mut_ret, actual: $act_mut_ret)!" diff --git a/framework/test/test_mutation_cmd.sh b/framework/test/test_mutation_cmd.sh index df0e0c83c..de0eb9b5b 100755 --- a/framework/test/test_mutation_cmd.sh +++ b/framework/test/test_mutation_cmd.sh @@ -16,7 +16,7 @@ source test.include # Print usage message and exit usage() { - local known_pids=$(defects4j pids) + local known_pids; known_pids=$(defects4j pids) echo "usage: $0 -p [-b ... | -b ... ]" echo "Project ids:" for pid in $known_pids; do @@ -31,9 +31,10 @@ while getopts ":p:b:" opt; do p) PID="$OPTARG" ;; b) if [[ "$OPTARG" =~ ^[0-9]*\.\.[0-9]*$ ]]; then + # shellcheck disable=SC1083,2086 BUGS="$BUGS $(eval echo {$OPTARG})" else - BUGS="$BUGS $OPTARG" + BUGS="$BUGS $OPTARG" fi ;; \?) @@ -59,20 +60,20 @@ init # Run all bugs, unless otherwise specified if [ "$BUGS" == "" ]; then - BUGS="$(get_bug_ids $BASE_DIR/framework/projects/$PID/$BUGS_CSV_ACTIVE)" + BUGS="$(get_bug_ids "$BASE_DIR/framework/projects/$PID/$BUGS_CSV_ACTIVE")" fi # Create log file -script_name=$(echo $script | sed 's/\.sh$//') -LOG="$TEST_DIR/${script_name}$(printf '_%s_%s' $PID $$).log" -OUT_DIR="$TEST_DIR/${script_name}$(printf '_%s_%s' $PID $$).mutation_summary" -mkdir -p $OUT_DIR +script_name_without_sh=${script//.sh/} +LOG="$TEST_DIR/${script_name_without_sh}$(printf '_%s_%s' "$PID" $$).log" +OUT_DIR="$TEST_DIR/${script_name_without_sh}$(printf '_%s_%s' "$PID" $$).mutation_summary" +mkdir -p "$OUT_DIR" # Reproduce all bugs (and log all results), regardless of whether errors occur HALT_ON_ERROR=0 test_dir=$(mktemp -d) -for bid in $(echo $BUGS); do +for bid in $BUGS; do # Skip all bug ids that do not exist in the active-bugs csv if ! grep -q "^$bid," "$BASE_DIR/framework/projects/$PID/$BUGS_CSV_ACTIVE"; then warn "Skipping bug ID that is not listed in active-bugs csv: $PID-$bid" @@ -82,12 +83,12 @@ for bid in $(echo $BUGS); do # Test mutation analysis for the fixed version only. vid="${bid}f" work_dir="$test_dir/$PID-$vid" - defects4j checkout -p $PID -v "$vid" -w "$work_dir" || die "checkout: $PID-$vid" + defects4j checkout -p "$PID" -v "$vid" -w "$work_dir" || die "checkout: $PID-$vid" defects4j mutation -w "$work_dir" || die "mutation: $PID-$vid" cat "$work_dir/summary.csv" > "$OUT_DIR/$bid" done -rm -rf $test_dir +rm -rf "$test_dir" HALT_ON_ERROR=1 # Print a summary of what went wrong @@ -95,7 +96,7 @@ if [ $ERROR != 0 ]; then printf '=%.s' $(seq 1 80) 1>&2 echo 1>&2 echo "The following errors occurred:" 1>&2 - cat $LOG 1>&2 + cat "$LOG" 1>&2 fi # Indicate whether an error occurred diff --git a/framework/test/test_sanity_check.sh b/framework/test/test_sanity_check.sh index 71b6f8a15..49c4dd3be 100755 --- a/framework/test/test_sanity_check.sh +++ b/framework/test/test_sanity_check.sh @@ -5,7 +5,7 @@ # ################################################################################ -HERE=$(cd `dirname $0` && pwd) +HERE="$(cd "$(dirname "$0")" && pwd)" || (echo "cannot cd to $(dirname "$0")" && exit 1) # Import helper subroutines and variables, and init Defects4J source "$HERE/test.include" || exit 1 diff --git a/framework/test/test_style.sh b/framework/test/test_style.sh index 45631b40b..814e45619 100755 --- a/framework/test/test_style.sh +++ b/framework/test/test_style.sh @@ -19,4 +19,3 @@ done for file in "$TOPLEVEL"/init.sh "$TOPLEVEL"/framework/lib/test_generation/bin/_tool.source ; do shellcheck -x -P SCRIPTDIR --format=gcc "$file" done - diff --git a/framework/test/test_tutorial.sh b/framework/test/test_tutorial.sh index 06fa6fb49..81007047b 100755 --- a/framework/test/test_tutorial.sh +++ b/framework/test/test_tutorial.sh @@ -5,7 +5,7 @@ # ################################################################################ -HERE=$(cd `dirname $0` && pwd) +HERE="$(cd "$(dirname "$0")" && pwd)" || (echo "cannot cd to $(dirname "$0")" && exit 1) # Import helper subroutines and variables, and init Defects4J source "$HERE/test.include" || exit 1 diff --git a/framework/test/test_verify_bugs.sh b/framework/test/test_verify_bugs.sh index 65e94946f..c84bdc4c0 100755 --- a/framework/test/test_verify_bugs.sh +++ b/framework/test/test_verify_bugs.sh @@ -17,7 +17,7 @@ # ################################################################################ -HERE=$(cd `dirname $0` && pwd) +HERE="$(cd "$(dirname "$0")" && pwd)" || (echo "cannot cd to $(dirname "$0")" && exit 1) # Import helper subroutines and variables, and init Defects4J source "$HERE/test.include" || exit 1 @@ -25,7 +25,7 @@ init # Print usage message and exit usage() { - local known_pids=$(defects4j pids) + local known_pids; known_pids=$(defects4j pids) echo "usage: $0 -p [-b ... | -b ... ] [-D]" echo "Project ids:" for pid in $known_pids; do @@ -35,14 +35,14 @@ usage() { } # Run only relevant tests by default -TEST_FLAG="-r" +TEST_FLAG_OR_EMPTY="-r" # Debugging is off by default DEBUG="" # Check arguments while getopts ":p:b:AD" opt; do case $opt in - A) TEST_FLAG="" + A) TEST_FLAG_OR_EMPTY="" ;; D) DEBUG="-D" ;; @@ -115,7 +115,7 @@ for bid in $BUGS ; do vid=${bid}$v defects4j checkout -p "$PID" -v "$vid" -w "$work_dir" || die "checkout: $PID-$vid" defects4j compile -w "$work_dir" || die "compile: $PID-$vid" - defects4j test $TEST_FLAG -w "$work_dir" || die "run relevant tests: $PID-$vid" + defects4j test $TEST_FLAG_OR_EMPTY -w "$work_dir" || die "run relevant tests: $PID-$vid" cat "$work_dir/failing_tests" > "$DIR_FAILING/$vid" @@ -143,7 +143,7 @@ for bid in $BUGS ; do done if [ "$DEBUG" != "-D" ]; then - rm -rf $TMP_DIR + rm -rf "$TMP_DIR" fi HALT_ON_ERROR=1 diff --git a/init.sh b/init.sh index cdb7acdde..d4a66079e 100755 --- a/init.sh +++ b/init.sh @@ -188,6 +188,7 @@ COVEREDCLASS_JAR="covered-class-${RANDOOP_VERSION}.jar" (cd "$DIR_LIB_GEN" && ln -sf "randoop-${RANDOOP_VERSION}/$RANDOOP_JAR" "randoop-current.jar") (cd "$DIR_LIB_GEN" && ln -sf "randoop-${RANDOOP_VERSION}/$REPLACECALL_JAR" "replacecall-current.jar") (cd "$DIR_LIB_GEN" && ln -sf "randoop-${RANDOOP_VERSION}/$COVEREDCLASS_JAR" "covered-class-current.jar") +(cd "$DIR_LIB_GEN" && ln -sf "randoop-${RANDOOP_VERSION}/jacocoagent.jar" "jacocoagent.jar") ################################################################################ #