diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 37a17923..9459628c 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -31,7 +31,7 @@ jobs: cd .. cp -r try ~ cd ~/try - bash ./test/run_tests.sh + scripts/run_tests.sh - name: Upload script uses: actions/upload-artifact@v2 @@ -107,7 +107,6 @@ jobs: with: ignore_paths: >- completions - test prerelease: needs: diff --git a/Vagrantfile b/Vagrantfile index fbfbf5df..fcf46c04 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -10,11 +10,11 @@ Vagrant.configure("2") do |config| debian.vm.box = "debian/testing64" debian.vm.provision "file", source: "./", destination: "/home/vagrant/try" debian.vm.provision "shell", privileged: false, inline: " - sudo apt update - sudo apt install -y git expect + sudo apt-get update + sudo apt-get install -y git expect sudo chown -R vagrant:vagrant try cd try - bash test/run_tests.sh + scripts/run_tests.sh " end @@ -23,8 +23,8 @@ Vagrant.configure("2") do |config| debianrustup.vm.box = "debian/testing64" debianrustup.vm.provision "file", source: "./", destination: "/home/vagrant/try" debianrustup.vm.provision "shell", privileged: false, inline: " - sudo apt update - sudo apt install -y curl + sudo apt-get update + sudo apt-get install -y curl sudo chown -R vagrant:vagrant try cd try mkdir rustup @@ -38,8 +38,8 @@ Vagrant.configure("2") do |config| debianlvm.vm.box = "debian/testing64" debianlvm.vm.provision "file", source: "./", destination: "/home/vagrant/try" debianlvm.vm.provision "shell", privileged: false, inline: " - sudo apt update - sudo apt install -y git expect lvm2 mergerfs + sudo apt-get update + sudo apt-get install -y git expect lvm2 mergerfs # Create an image for the lvm disk sudo fallocate -l 2G /root/lvm_disk.img @@ -65,7 +65,7 @@ Vagrant.configure("2") do |config| sudo chown -R vagrant:vagrant /mnt/lv0/try cd /mnt/lv0/try - bash test/run_tests.sh + scripts/run_tests.sh " end @@ -77,7 +77,7 @@ Vagrant.configure("2") do |config| sudo yum install -y git expect sudo chown -R vagrant:vagrant try cd try - TRY_TOP=$(pwd) bash test/run_tests.sh + TRY_TOP=$(pwd) scripts/run_tests.sh " end # @@ -89,7 +89,7 @@ Vagrant.configure("2") do |config| sudo yum install -y git expect sudo chown -R vagrant:vagrant try cd try - TRY_TOP=$(pwd) bash test/run_tests.sh + TRY_TOP=$(pwd) scripts/run_tests.sh " end end diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 00000000..e898754f --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,5 @@ +This directory holds utility scripts used in development of `try`. + +The `lint.sh` script runs basic file linting. + +The `run_tests.sh` script runs the test suite. diff --git a/scripts/lint.sh b/scripts/lint.sh index 712e83bf..0c827c66 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -129,7 +129,7 @@ done if [ "$NUM_WARNINGS" -eq 0 ] then - printf "✓ \033[32;1mLINT CHECK PASSED\033[0m\n" + printf "\033[32;1m✓ LINT CHECK PASSED\033[0m\n" else printf "\n❌ \033[31;1mLINT CHECK FAILED (%d warning%s)\033[0m\n" "$NUM_WARNINGS" "$(plural "$NUM_WARNINGS")" exit 1 diff --git a/scripts/run_tests.sh b/scripts/run_tests.sh new file mode 100755 index 00000000..18c494f1 --- /dev/null +++ b/scripts/run_tests.sh @@ -0,0 +1,94 @@ +#!/bin/sh + +: "${TRY_TOP=$(git rev-parse --show-toplevel --show-superproject-working-tree)}" +TEST_DIR="$TRY_TOP/test" + +# set the DEBUG env variable to see detailed output +DEBUG=${DEBUG:-0} + +# results saved here; clear out previous results +OUTPUT_DIR="$TRY_TOP/test/results" +rm -rf "$OUTPUT_DIR" +mkdir -p "$OUTPUT_DIR" +touch "$OUTPUT_DIR/result_status" + +TOTAL_TESTS=0 +PASSED_TESTS=0 +FAILING_TESTS="" + +run_test() +{ + test="$1" + name="$(basename "$test")" + + if ! [ -f "$test" ] + then + echo "Test '$name' does not exist (at path $test)." + return 1 + elif ! [ -x "$test" ] + then + echo "Test '$name' is not executable (at path $test)." + return 1 + fi + + # check if we can read from /run dir + ls /run/systemd >/dev/null || { + echo "Cannot read from /run/systemd, aborting test '$name'." >&2 + return 1 + } + + echo + printf "Running %s..." "$name" + + # actually run the test + "$test" + ec="$?" + + : $((TOTAL_TESTS += 1)) + if [ "$ec" -eq 0 ]; then + : $((PASSED_TESTS += 1)) + printf '\t\t\t' + echo "Test $name passed" >>"$OUTPUT_DIR/result_status" + printf '\tOK\n' + else + FAILING_TESTS="$FAILING_TESTS $name" + printf " non-zero exit status (%d)" "$ec" + echo "Test $name failed" >>"$OUTPUT_DIR/result_status" + printf '\t\tFAIL\n' + fi +} + +pats="$(mktemp)" +if [ "$#" -eq 0 ] +then + # if no patterns are specified + echo '.*' >"$pats" +else + printf "%s\n" "$@" >>"$pats" +fi + +TESTS="$(find "$TEST_DIR" -type f -executable -name '*.sh' | grep -f "$pats")" +rm "$pats" + +echo "=================| Try Tests |===================" +echo "Test directory: $WORKING_DIR" +echo "Results saved at: $OUTPUT_DIR" +echo +echo "Running $(echo "$TESTS" | wc -l) tests" +echo "=================================================" + +for test in $TESTS +do + run_test "$test" +done + +echo +echo "====================| Test Summary |====================" +echo "Failing tests:${FAILING_TESTS}" +echo "Summary: ${PASSED_TESTS}/${TOTAL_TESTS} tests passed." +echo "========================================================" + +if [ $PASSED_TESTS -ne $TOTAL_TESTS ] +then + exit 1 +fi diff --git a/test/README.md b/test/README.md new file mode 100644 index 00000000..a8d468c8 --- /dev/null +++ b/test/README.md @@ -0,0 +1,17 @@ +This directory holds tests and testing resources. + +`scripts/run_tests.sh` will run all of the tests in this directory +(and subdirectories); to be a test, a file must be: + + - a regular file + - executable + - end in `.sh` + +You can select a specific test by running `scripts/run_tests.sh a b`; +this will run tests that pass `a` _or_ `b` as grep patterns. + +Some files are named `.sh.skip`---these will always be skipped. Rename +them if you need to run them. + +Tests have a pretty standard preamble that should handle basic cleanup +functions. diff --git a/test/command_substitution.sh b/test/command_substitution.sh new file mode 100755 index 00000000..006c9d34 --- /dev/null +++ b/test/command_substitution.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +TRY_TOP="${TRY_TOP:-$(git rev-parse --show-toplevel --show-superproject-working-tree)}" +TRY="$TRY_TOP/try" + +cleanup() { + cd / + + if [ -d "$try_workspace" ] + then + rm -rf "$try_workspace" >/dev/null 2>&1 + fi + + if [ -f "$expected" ] + then + rm "$expected" + fi +} + +trap 'cleanup' EXIT + +try_workspace="$(mktemp -d)" +cd "$try_workspace" || return 9 + +# Set up expected output +expected="$(mktemp)" +pwd >"$expected" + +cat >script.sh <<"EOF" + mypwd="$(pwd)" + echo "$mypwd" +EOF + +"$TRY" sh script.sh >out.txt || return 1 + +diff -q "$expected" out.txt diff --git a/test/dev_urandom.sh b/test/dev_urandom.sh new file mode 100755 index 00000000..d193555c --- /dev/null +++ b/test/dev_urandom.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +TRY_TOP="${TRY_TOP:-$(git rev-parse --show-toplevel --show-superproject-working-tree)}" +TRY="$TRY_TOP/try" + +cleanup() { + cd / + + if [ -d "$try_workspace" ] + then + rm -rf "$try_workspace" >/dev/null 2>&1 + fi +} + +trap 'cleanup' EXIT + +try_workspace="$(mktemp -d)" +cd "$try_workspace" || return 9 + +# Ignore changes to foo +"$TRY" -y "head -c 5 /dev/urandom >target" || return 1 +[ -s target ] || return 2 diff --git a/test/empty_summary.sh b/test/empty_summary.sh new file mode 100755 index 00000000..9641a9d8 --- /dev/null +++ b/test/empty_summary.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +TRY_TOP="${TRY_TOP:-$(git rev-parse --show-toplevel --show-superproject-working-tree)}" +TRY="$TRY_TOP/try" + +cleanup() { + cd / + + if [ -d "$try_workspace" ] + then + rm -rf "$try_workspace" >/dev/null 2>&1 + fi + + if [ -d "$try_example_dir" ] + then + rm -rf "$try_example_dir" + fi +} + +trap 'cleanup' EXIT + +try_workspace="$(mktemp -d)" +cd "$try_workspace" || return 9 + +try_example_dir="$(mktemp -d)" +"$TRY" -D "$try_example_dir" -- echo hi >/dev/null || return 1 +"$TRY" summary "$try_example_dir" >summary.out + +# an empty summary returns exit status 1 +[ "$?" -eq 1 ] || return 2 + +# We want to return true if the following line is not found! +! grep -q -e "Changes detected in the following files:" summary.out diff --git a/test/exit_status.sh b/test/exit_status.sh new file mode 100755 index 00000000..7a6e7883 --- /dev/null +++ b/test/exit_status.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +TRY_TOP="${TRY_TOP:-$(git rev-parse --show-toplevel --show-superproject-working-tree)}" +TRY="$TRY_TOP/try" + +cleanup() { + cd / + + if [ -d "$try_workspace" ] + then + rm -rf "$try_workspace" >/dev/null 2>&1 + fi +} + +trap 'cleanup' EXIT + +try_workspace="$(mktemp -d)" +cd "$try_workspace" || return 9 + +"$TRY" exit 3 + +[ "$?" -eq 3 ] diff --git a/test/explore.sh b/test/explore.sh new file mode 100755 index 00000000..091711dd --- /dev/null +++ b/test/explore.sh @@ -0,0 +1,57 @@ +#!/bin/sh + +TRY_TOP="${TRY_TOP:-$(git rev-parse --show-toplevel --show-superproject-working-tree)}" +TRY="$TRY_TOP/try" + +cleanup() { + cd / + + if [ -d "$try_workspace" ] + then + rm -rf "$try_workspace" >/dev/null 2>&1 + fi +} + +trap 'cleanup' EXIT + +try_workspace="$(mktemp -d)" +cd "$try_workspace" || return 9 + +SHELL="/bin/bash --norc" +export SHELL +PS1="# " +export PS1 + +echo hi >expected.out + +cat >explore.exp <test.txt\r" + } + } +expect "#" +# Send exit +send \x04 + +# Ignore all output and just send a y at the end +expect "" +expect "Commit*" +send -- "y\r" +expect eof +EOF + +# Debug using the -d flag +expect explore.exp >/dev/null || return 1 + +diff -q expected.out test.txt diff --git a/test/fail.sh.skip b/test/fail.sh.skip new file mode 100755 index 00000000..f1fb7400 --- /dev/null +++ b/test/fail.sh.skip @@ -0,0 +1,5 @@ +#!/bin/sh +# +# rename this to fail.sh to force a CI failure (e.g., when testing CI changes) + +exit 1 diff --git a/test/hidden_variables.sh b/test/hidden_variables.sh new file mode 100755 index 00000000..6b745654 --- /dev/null +++ b/test/hidden_variables.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +TRY_TOP="${TRY_TOP:-$(git rev-parse --show-toplevel --show-superproject-working-tree)}" +TRY="$TRY_TOP/try" + +cleanup() { + cd / + + if [ -d "$try_workspace" ] + then + rm -rf "$try_workspace" >/dev/null 2>&1 + fi +} + +trap 'cleanup' EXIT + +try_workspace="$(mktemp -d)" +cd "$try_workspace" || return 9 + +# Set up expected output +echo 'no sandbox' >expected.out + +# SANDBOX_DIR should not be set in the final execution env +"$TRY" -y -- "echo \${SANDBOX_DIR-no sandbox}" >got.out 2>/dev/null || return 1 + +diff -q expected.out got.out diff --git a/test/ignore_flag.sh b/test/ignore_flag.sh new file mode 100755 index 00000000..360ea05b --- /dev/null +++ b/test/ignore_flag.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +TRY_TOP="${TRY_TOP:-$(git rev-parse --show-toplevel --show-superproject-working-tree)}" +TRY="$TRY_TOP/try" + +cleanup() { + cd / + + if [ -d "$try_workspace" ] + then + rm -rf "$try_workspace" >/dev/null 2>&1 + fi +} + +trap 'cleanup' EXIT + +try_workspace="$(mktemp -d)" +cd "$try_workspace" || return 9 + +# Set up expected output +touch expected.bar + +# Ignore changes to foo +"$TRY" -y -i foo1 -i foo2 "touch foo1.txt; touch foo2.txt; touch bar.txt" || return 1 + +diff -q expected.bar bar.txt || return 2 +! [ -f foo1.txt ] || return 3 +! [ -f foo2.txt ] || return 4 diff --git a/test/missing_unionfs_mergerfs.sh b/test/missing_unionfs_mergerfs.sh new file mode 100755 index 00000000..38b3f305 --- /dev/null +++ b/test/missing_unionfs_mergerfs.sh @@ -0,0 +1,40 @@ +#!/bin/sh +# +# checking that try works when mergerfs/unionfs are not present (but also not necessary) + +TRY_TOP="${TRY_TOP:-$(git rev-parse --show-toplevel --show-superproject-working-tree)}" +TRY="$TRY_TOP/try" + +cleanup() { + cd / + + if [ -d "$try_workspace" ] + then + rm -rf "$try_workspace" >/dev/null 2>&1 + fi + + if [ -d "$new_bin_dir" ] + then + rm -rf "$new_bin_dir" + fi +} + +trap 'cleanup' EXIT + +# particularly important that we run in mktemp: in some test machines, +# the cwd is mounted, hence inaccessable. +try_workspace="$(mktemp -d)" +cd "$try_workspace" || return 9 + +new_bin_dir="$(mktemp -d)" +mkdir "$new_bin_dir/usr" +# -s makes symlinks +cp -rs /usr/bin "$new_bin_dir/usr/bin" + +# Delete mergerfs and unionfs and set the new PATH to the temporary directory +rm -f "$new_bin_dir/usr/bin/mergerfs" 2>/dev/null +rm -f "$new_bin_dir/usr/bin/unionfs" 2>/dev/null + +echo hi >expected +PATH="$new_bin_dir/usr/bin" "$TRY" -y "echo hi" >target 2>/dev/null || return 1 +diff -q expected target || return 2 diff --git a/test/mkdir_on_file.sh b/test/mkdir_on_file.sh new file mode 100755 index 00000000..4322e670 --- /dev/null +++ b/test/mkdir_on_file.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +TRY_TOP="${TRY_TOP:-$(git rev-parse --show-toplevel --show-superproject-working-tree)}" +TRY="$TRY_TOP/try" + +cleanup() { + cd / + + if [ -d "$try_workspace" ] + then + rm -rf "$try_workspace" >/dev/null 2>&1 + fi +} + +trap 'cleanup' EXIT + +try_workspace="$(mktemp -d)" +cd "$try_workspace" || return 9 + +# Set up expected output +touch target +mkdir expected + +"$TRY" -y "rm target; mkdir target" || return 1 +diff -qr expected target diff --git a/test/nonexistent_sandbox.sh b/test/nonexistent_sandbox.sh new file mode 100755 index 00000000..31d47fea --- /dev/null +++ b/test/nonexistent_sandbox.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +TRY_TOP="${TRY_TOP:-$(git rev-parse --show-toplevel --show-superproject-working-tree)}" +TRY="$TRY_TOP/try" + +cleanup() { + cd / + + if [ -d "$try_workspace" ] + then + rm -rf "$try_workspace" >/dev/null 2>&1 + fi + + # shouldn't fire + if [ -d "$try_example_dir" ] + then + rm -rf "$try_example_dir" + fi +} + +trap 'cleanup' EXIT + +try_workspace="$(mktemp -d)" +cp "$TRY_TOP/test/resources/file.txt.gz" "$try_workspace/" +cd "$try_workspace" || return 9 + +try_example_dir="non-existent" +! [ -d "$try_example_dir" ] || exit 2 +! "$TRY" -D $try_example_dir "touch file_1.txt" 2>/dev/null && +! "$TRY" summary $try_example_dir 2>/dev/null && +! "$TRY" commit $try_example_dir 2>/dev/null && +! "$TRY" explore $try_example_dir 2>/dev/null diff --git a/test/pipeline.sh b/test/pipeline.sh new file mode 100755 index 00000000..fa9d66d0 --- /dev/null +++ b/test/pipeline.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +TRY_TOP="${TRY_TOP:-$(git rev-parse --show-toplevel --show-superproject-working-tree)}" +TRY="$TRY_TOP/try" + +cleanup() { + cd / + + if [ -d "$try_workspace" ] + then + rm -rf "$try_workspace" >/dev/null 2>&1 + fi + + if [ -f "$expected" ] + then + rm "$expected" + fi +} + +trap 'cleanup' EXIT + +try_workspace="$(mktemp -d)" +cp "$TRY_TOP/test/resources/file.txt.gz" "$try_workspace/" +cd "$try_workspace" || return 9 + +# Set up expected output +expected="$(mktemp)" +echo 'TesT' >"$expected" + +"$TRY" 'echo test | tr t T' >out.txt || return 1 + +diff -q "$expected" out.txt diff --git a/test/reuse_problematic_sandbox.sh b/test/reuse_problematic_sandbox.sh new file mode 100755 index 00000000..2cac0204 --- /dev/null +++ b/test/reuse_problematic_sandbox.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +TRY_TOP="${TRY_TOP:-$(git rev-parse --show-toplevel --show-superproject-working-tree)}" +TRY="$TRY_TOP/try" + +cleanup() { + cd / + + if [ -d "$try_workspace" ] + then + rm -rf "$try_workspace" >/dev/null 2>&1 + fi + + if [ -d "$try_example_dir" ] + then + rm -rf "$try_example_dir" + fi +} + +trap 'cleanup' EXIT + +try_workspace="$(mktemp -d)" +cp "$TRY_TOP/test/resources/file.txt.gz" "$try_workspace/" +cd "$try_workspace" || return 9 + +try_example_dir=$(mktemp -d) +"$TRY" -D "$try_example_dir" "touch file_1.txt; echo test >file_2.txt; rm file.txt.gz" || return 1 + +# KK 2023-06-29 This test is meant to modify the sandbox directory in an illegal way, +# at the moment, this modification will be caught as illegal by `try`, +# but it doesn't seem to both overlayfs at all. +# TODO: Extend this with more problematic overlayfs modifications. +touch "$try_example_dir/temproot/bin/foo" +! "$TRY" -D "$try_example_dir" "rm file_1.txt; echo test2 >>file_2.txt; touch file.txt.gz" 2>/dev/null diff --git a/test/reuse_sandbox.sh b/test/reuse_sandbox.sh new file mode 100755 index 00000000..573f778d --- /dev/null +++ b/test/reuse_sandbox.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +TRY_TOP="${TRY_TOP:-$(git rev-parse --show-toplevel --show-superproject-working-tree)}" +TRY="$TRY_TOP/try" + +cleanup() { + cd / + + if [ -d "$try_workspace" ] + then + rm -rf "$try_workspace" >/dev/null 2>&1 + fi + + if [ -d "$try_example_dir" ] + then + rm -rf "$try_example_dir" + fi + + if [ -f "$expected1" ] + then + rm "$expected1" + fi + + if [ -f "$expected2" ] + then + rm "$expected2" + fi +} + +trap 'cleanup' EXIT + +try_workspace="$(mktemp -d)" +cp "$TRY_TOP/test/resources/file.txt.gz" "$try_workspace/" +cd "$try_workspace" || return 9 + +expected1="$(mktemp)" +expected2="$(mktemp)" +echo test >"$expected1" +echo test2 >>"$expected1" +touch "$expected2" + +try_example_dir="$(mktemp -d)" +"$TRY" -D "$try_example_dir" "touch file_1.txt; echo test >file_2.txt; rm file.txt.gz" || return 1 +"$TRY" -D "$try_example_dir" "rm file_1.txt; echo test2 >>file_2.txt; touch file.txt.gz" || return 2 +"$TRY" commit "$try_example_dir" || return 3 + +! [ -f file_1.txt ] || return 4 +diff -q "$expected1" file_2.txt || return 5 +diff -q "$expected2" file.txt.gz || return 6 diff --git a/test/run_tests.sh b/test/run_tests.sh deleted file mode 100755 index edf76ef4..00000000 --- a/test/run_tests.sh +++ /dev/null @@ -1,522 +0,0 @@ -#!/bin/bash - -export TRY_TOP=${TRY_TOP:-$(git rev-parse --show-toplevel --show-superproject-working-tree)} -export WORKING_DIR="$TRY_TOP/test" -export RESOURCE_DIR="$WORKING_DIR/resources" - -echo "=================| Try Tests |===================" -echo "Test directory: $WORKING_DIR" -echo "Resource directory: $RESOURCE_DIR" - -## Set the DEBUG env variable to see detailed output -DEBUG=${DEBUG:-0} - - -try="$TRY_TOP/try" - -try_workspace="$TRY_TOP/test/try_workspace" - -# Results saved here -output_dir="$TRY_TOP/test/results" - -echo "try test workspace: $try_workspace" -echo "Results saved at: $output_dir" -echo "=================================================" - -# Clear previous test results -rm -rf "$output_dir" -mkdir -p "$output_dir" -touch "$output_dir/result_status" - -cleanup() -{ - rm -rf "$try_workspace" - mkdir "$try_workspace" -} - -TOTAL_TESTS=0 -PASSED_TESTS=0 -FAILING_TESTS="" - -test_read_from_run_dir() -{ - ls /run/systemd > /dev/null - if [ $? -ne 0 ]; then - echo "Cannot read from /run/systemd." - return 1 - fi -} - -run_test() -{ - cleanup - local test=$1 - - if [ "$(type -t $test)" != "function" ]; then - echo "$test is not a function! FAIL" - return 1 - fi - - # Check if we can read from /run dir - test_read_from_run_dir - - echo - echo -n "Running $test..." - - # Run test - : $((TOTAL_TESTS += 1)) - $test "$try_workspace" - test_try_ec=$? - - if [ $test_try_ec -eq 0 ]; then - : $((PASSED_TESTS += 1)) - echo -ne '\t\t\t' - echo "$test passed" >> $output_dir/result_status - echo -e '\tOK' - else - FAILING_TESTS="$FAILING_TESTS $test" - echo -n " non-zero ec ($test_try_ec)" - echo "$test failed" >> $output_dir/result_status - echo -e '\t\tFAIL' - fi -} - -test_unzip_no_flag() -{ - local try_workspace=$1 - cp $RESOURCE_DIR/file.txt.gz "$try_workspace/" - cd "$try_workspace/" - - ## Set up expected output - echo 'Hello World!' >expected.out - - "$try" -y gunzip file.txt.gz || return 1 - diff -q expected.out file.txt -} - -test_unzip_D_flag_commit() -{ - local try_workspace=$1 - cp $RESOURCE_DIR/file.txt.gz "$try_workspace/" - cd "$try_workspace/" - - ## Set up expected output - echo 'Hello World!' >expected.out - - try_example_dir=$(mktemp -d) - "$try" -D $try_example_dir gunzip file.txt.gz || return 1 - $try commit $try_example_dir - diff -q expected.out file.txt -} - -test_unzip_D_flag_commit_without_cleanup() -{ - local try_workspace=$1 - cp $RESOURCE_DIR/* "$try_workspace/" - cd "$try_workspace/" - - try_example_dir=$(mktemp -d) - "$try" -D $try_example_dir gunzip file.txt.gz || return 1 - if ! [ -d "$try_example_dir" ]; then - echo "try_example_dir disappeared with no commit" - return 1 - fi - "$try" commit $try_example_dir || return 1 - if ! [ -d "$try_example_dir" ]; then - echo "try_example_dir disappeared after manual commit" - return 1 - fi -} - -# KK 2023-07-06 This test checks whether try has correctly cleaned up its temporary directories -# but is not working now. I am leaving it in so that its logic can be reused for a new test. -# -# test_touch_and_rm_with_cleanup() -# { -# local try_workspace=$1 -# cp $RESOURCE_DIR/file.txt.gz "$try_workspace/" -# cd "$try_workspace/" - -# : ${TMPDIR=/tmp} - -# orig_tmp=$(ls "$TMPDIR") -# "$try" -y -- "touch file_1.txt; echo test > file_2.txt; rm file.txt.gz" || return 1 -# new_tmp=$(ls "$TMPDIR") - -# if ! diff -q <(echo "$orig_tmp") <(echo "$new_tmp") -# then -# echo "temporary directory was not cleaned up; diff:" -# diff --color -u <(echo "$orig_tmp") <(echo "$new_tmp") -# return 1 -# fi -# } - -test_touch_and_rm_no_flag() -{ - local try_workspace=$1 - cp $RESOURCE_DIR/file.txt.gz "$try_workspace/" - cd "$try_workspace/" - - ## Set up expected output - touch expected1.txt - echo 'test' >expected2.txt - - "$try" -y "touch file_1.txt; echo test > file_2.txt; rm file.txt.gz" || return 1 - - diff -q expected1.txt file_1.txt && - diff -q expected2.txt file_2.txt && - [ ! -f file.txt.gz ] -} - -test_touch_and_rm_D_flag_commit() -{ - local try_workspace=$1 - cp $RESOURCE_DIR/file.txt.gz "$try_workspace/" - cd "$try_workspace/" - - ## Set up expected output - touch expected1.txt - echo 'test' >expected2.txt - - try_example_dir=$(mktemp -d) - "$try" -D $try_example_dir "touch file_1.txt; echo test > file_2.txt; rm file.txt.gz" || return 1 - $try commit $try_example_dir - - diff -q expected1.txt file_1.txt && - diff -q expected2.txt file_2.txt && - [ ! -f file.txt.gz ] -} - -test_reuse_sandbox() -{ - local try_workspace=$1 - cp $RESOURCE_DIR/file.txt.gz "$try_workspace/" - cd "$try_workspace/" - - ## Set up expected output - echo 'test' >expected2.txt - echo 'test2' >>expected2.txt - touch expected3.out - - try_example_dir=$(mktemp -d) - "$try" -D $try_example_dir "touch file_1.txt; echo test > file_2.txt; rm file.txt.gz" - "$try" -D $try_example_dir "rm file_1.txt; echo test2 >> file_2.txt; touch file.txt.gz" - $try commit $try_example_dir - - [ ! -f file_1.txt ] && - diff -q expected2.txt file_2.txt && - diff -q expected3.out file.txt.gz -} - -test_reuse_problematic_sandbox() -{ - local try_workspace=$1 - cp $RESOURCE_DIR/file.txt.gz "$try_workspace/" - cd "$try_workspace/" - - ## Set up expected output - echo 'test' >expected2.txt - echo 'test2' >>expected2.txt - touch expected3.out - - try_example_dir=$(mktemp -d) - "$try" -D $try_example_dir "touch file_1.txt; echo test > file_2.txt; rm file.txt.gz" - - ## KK 2023-06-29 This test is meant to modify the sandbox directory in an illegal way, - ## at the moment, this modification will be caught as illegal by `try`, - ## but it doesn't seem to both overlayfs at all. - ## TODO: Extend this with more problematic overlayfs modifications. - touch "$try_example_dir/temproot/bin/foo" - ! "$try" -D $try_example_dir "rm file_1.txt; echo test2 >> file_2.txt; touch file.txt.gz" 2> /dev/null -} - -test_non_existent_sandbox() -{ - local try_workspace=$1 - cp $RESOURCE_DIR/file.txt.gz "$try_workspace/" - cd "$try_workspace/" - - try_example_dir="non-existent" - ! "$try" -D $try_example_dir "touch file_1.txt" 2>/dev/null && - ! "$try" summary $try_example_dir 2>/dev/null && - ! "$try" commit $try_example_dir 2>/dev/null && - ! "$try" explore $try_example_dir 2>/dev/null -} - -test_pipeline() -{ - local try_workspace=$1 - cd "$try_workspace/" - - ## Set up expected output - echo 'TesT' >expected.out - - "$try" 'echo test | tr t T' > out.txt || return 1 - - diff -q expected.out out.txt -} - -test_cmd_sbst_and_var() -{ - local try_workspace=$1 - cd "$try_workspace/" - - ## Set up expected output - echo $(pwd) >expected.out - - cat >script.sh <<"EOF" -echo $(pwd) -EOF - - "$try" sh script.sh >out.txt || return 1 - - diff -q expected.out out.txt -} - -test_explore() -{ - local try_workspace=$1 - cd "$try_workspace/" - - SHELL="/bin/bash --norc" - export SHELL - PS1="# " - export PS1 - - echo hi >expected.out - - cat >explore.exp <test.txt\r" - } - } -expect "#" -## Send `exit` -send \x04 - -## Ignore all output and just send a y at the end -expect "" -expect "Commit*" -send -- "y\r" -expect eof -EOF - ## Debug using the -d flag - expect explore.exp >/dev/null - - diff -q expected.out test.txt -} - -test_summary() -{ - local try_workspace=$1 - cp $RESOURCE_DIR/file.txt.gz "$try_workspace/" - cd "$try_workspace/" - - ## Set up expected output - touch expected1.txt - echo 'test' >expected2.txt - - echo 'fail' >file_2.txt - touch target - - try_example_dir=$(mktemp -d) - "$try" -D $try_example_dir "touch file_1.txt; echo test > file_2.txt; rm file.txt.gz; rm target; mkdir target; mkdir new_dir" - "$try" summary $try_example_dir > summary.out - - ## Check that the summary correctly identifies every change - grep -qx "$PWD/file_1.txt (added)" /dev/null - "$try" summary $try_example_dir > summary.out - - ## We want to return true if the following line is not found! - ! grep -q "Changes detected in the following files:" target" - [ -s target ] -} - -## This test is checking if try works when mergerfs/unionfs are not present (but also not necessary) -test_echo_no_unionfs_mergerfs() -{ - local try_workspace=$1 - cd "$try_workspace/" - - ## Create a new /bin and /usr/bin without mergerfs and unionfs - new_bin_dir=$(mktemp -d) - mkdir "$new_bin_dir/usr" - cp -rs /usr/bin "$new_bin_dir/usr/bin" - - ## Delete mergerfs and unionfs and set the new PATH to the temporary directory - rm -f "$new_bin_dir/usr/bin/mergerfs" 2>/dev/null - rm -f "$new_bin_dir/usr/bin/unionfs" 2>/dev/null - - ## We are running this in a mktemp since in some test machines, - ## the cwd is mounted, hence inaccessable. - cd $(mktemp -d) - echo hi >expected - PATH="$new_bin_dir/usr/bin" "$try" -y "echo hi" >target 2>/dev/null - diff -q expected target -} - -test_exit_status() { - local try_workspace=$1 - cp $RESOURCE_DIR/file.txt.gz "$try_workspace/" - cd "$try_workspace/" - - "$try" exit 3 - - [ "$?" -eq 3 ] -} - -test_hidden_variables() { - local try_workspace=$1 - cd "$try_workspace/" - - ## Set up expected output - echo 'no sandbox' >expected.out - - ## SANDBOX_DIR should not be set in the final execution env - "$try" -y -- "echo \${SANDBOX_DIR-no sandbox}" >got.out 2>/dev/null - echo $? - ec=$? - - echo expected - cat expected.out - echo got - cat got.out - - [ "$ec" -eq 0 ] && diff -q expected.out got.out - -} - -# a test that deliberately fails (for testing CI changes) -test_fail() { - if [ "$1" = "$bash" ] - then - (exit 1) - else - (exit 2) - fi -} - -# We run all tests composed with && to exit on the first that fails -if [ "$#" -eq 0 ]; then - run_test test_unzip_no_flag - run_test test_unzip_D_flag_commit - run_test test_touch_and_rm_no_flag - run_test test_touch_and_rm_D_flag_commit - run_test test_exit_status - # run_test test_touch_and_rm_with_cleanup - run_test test_unzip_D_flag_commit_without_cleanup - run_test test_reuse_sandbox - run_test test_reuse_problematic_sandbox - run_test test_non_existent_sandbox - run_test test_pipeline - run_test test_cmd_sbst_and_var - run_test test_summary - run_test test_explore - run_test test_empty_summary - run_test test_mkdir_on_file - run_test test_ignore_flag - run_test test_dev - run_test test_echo_no_unionfs_mergerfs - run_test test_hidden_variables - -# uncomment this to force a failure -# run_test test_fail - -else - for testname in $@ - do - run_test "$testname" "$2" - done -fi - -if type lsb_release > /dev/null ; then - distro=$(lsb_release -i -s) -elif [ -e /etc/os-release ] ; then - distro=$(awk -F= '$1 == "ID" {print $2}' /etc/os-release) -fi - -distro=$(printf '%s\n' "$distro" | LC_ALL=C tr '[:upper:]' '[:lower:]') -# do different things depending on distro -case "$distro" in - freebsd*) - # change sed to gsed - sed () { - gsed $@ - } - ;; - *) - ;; -esac - -echo -echo "====================| Test Summary |====================" -echo "Failing tests:${FAILING_TESTS}" -echo "Summary: ${PASSED_TESTS}/${TOTAL_TESTS} tests passed." -echo "========================================================" - -if [ $PASSED_TESTS -ne $TOTAL_TESTS ] -then - exit 1 -fi diff --git a/test/summary.sh b/test/summary.sh new file mode 100755 index 00000000..7ff817af --- /dev/null +++ b/test/summary.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +TRY_TOP="${TRY_TOP-$(git rev-parse --show-toplevel --show-superproject-working-tree)}" +TRY="$TRY_TOP/try" + +cleanup() { + cd / + + if [ -d "$try_workspace" ] + then + rm -rf "$try_workspace" >/dev/null 2>&1 + fi + + if [ -d "$try_example_dir" ] + then + rm -rf "$try_example_dir" + fi +} + +trap 'cleanup' EXIT + +try_workspace="$(mktemp -d)" +cd "$try_workspace" || return 9 + +cp "$TRY_TOP/test/resources/file.txt.gz" "$try_workspace/" + +# Set up expected output +touch expected1.txt +echo 'test' >expected2.txt + +echo 'fail' >file_2.txt +touch target + +try_example_dir=$(mktemp -d) +"$TRY" -D "$try_example_dir" "touch file_1.txt; echo test >file_2.txt; rm file.txt.gz; rm target; mkdir target; mkdir new_dir" || return 1 +"$TRY" summary "$try_example_dir" >summary.out || return 2 + +# Check that the summary correctly identifies every change +grep -qx -e "$PWD/file_1.txt (added)" summary.out || return 3 +grep -qx -e "$PWD/file_2.txt (modified)" summary.out || return 4 +grep -qx -e "$PWD/file.txt.gz (deleted)" summary.out || return 5 +grep -qx -e "$PWD/target (replaced with dir)" summary.out || return 6 +grep -qx -e "$PWD/new_dir (created dir)" summary.out || return 7 diff --git a/test/touch_and_rm_D_flag_commit.sh b/test/touch_and_rm_D_flag_commit.sh new file mode 100755 index 00000000..760343a3 --- /dev/null +++ b/test/touch_and_rm_D_flag_commit.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +TRY_TOP="${TRY_TOP:-$(git rev-parse --show-toplevel --show-superproject-working-tree)}" +TRY="$TRY_TOP/try" + +cleanup() { + cd / + + if [ -d "$try_workspace" ] + then + rm -rf "$try_workspace" >/dev/null 2>&1 + fi + + if [ -d "$try_example_dir" ] + then + rm -rf "$try_example_dir" + fi + + if [ -f "$expected1" ] + then + rm "$expected1" + fi + + if [ -f "$expected2" ] + then + rm "$expected2" + fi +} + +trap 'cleanup' EXIT + +try_workspace="$(mktemp -d)" +cp "$TRY_TOP/test/resources/file.txt.gz" "$try_workspace/" +cd "$try_workspace" || return 9 + +expected1="$(mktemp)" +expected2="$(mktemp)" +touch "$expected1" +echo 'test' >"$expected2" + +try_example_dir="$(mktemp -d)" +"$TRY" -D "$try_example_dir" "touch file_1.txt; echo test >file_2.txt; rm file.txt.gz" || return 1 +"$TRY" commit "$try_example_dir" || return 2 + +diff -q "$expected1" file_1.txt || return 3 +diff -q "$expected2" file_2.txt || return 4 +! [ -f file.txt.gz ] || return 5 diff --git a/test/touch_and_rm_no_flag.sh b/test/touch_and_rm_no_flag.sh new file mode 100755 index 00000000..7e371fb8 --- /dev/null +++ b/test/touch_and_rm_no_flag.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +TRY_TOP="${TRY_TOP:-$(git rev-parse --show-toplevel --show-superproject-working-tree)}" +TRY="$TRY_TOP/try" + +cleanup() { + cd / + + if [ -d "$try_workspace" ] + then + rm -rf "$try_workspace" >/dev/null 2>&1 + fi + + if [ -f "$expected1" ] + then + rm "$expected1" + fi + + if [ -f "$expected2" ] + then + rm "$expected2" + fi +} + +trap 'cleanup' EXIT + +try_workspace="$(mktemp -d)" +cp "$TRY_TOP/test/resources/file.txt.gz" "$try_workspace/" +cd "$try_workspace" || return 9 + +expected1="$(mktemp)" +expected2="$(mktemp)" +touch "$expected1" +echo 'test' >"$expected2" + +"$TRY" -y "touch file_1.txt; echo test > file_2.txt; rm file.txt.gz" || return 1 + +diff -q "$expected1" file_1.txt || return 2 +diff -q "$expected2" file_2.txt || return 3 +! [ -f file.txt.gz ] || return 4 diff --git a/test/touch_and_rm_with_cleanup.sh.skip b/test/touch_and_rm_with_cleanup.sh.skip new file mode 100755 index 00000000..f2154016 --- /dev/null +++ b/test/touch_and_rm_with_cleanup.sh.skip @@ -0,0 +1,37 @@ +#!/bin/sh + +TRY_TOP=${TRY_TOP:-$(git rev-parse --show-toplevel --show-superproject-working-tree)} +TRY="$TRY_TOP/try" +RESOURCE_DIR="$TRY_TOP/test/resources" + +cleanup() { + if [ -d "$try_workspace" ] + then + rm -rf "$try_workspace" + fi + + if [ -d "$try_example_dir" ] + then + rm -rf "$try_example_dir" + fi +} + +trap 'cleanup' EXIT + +try_workspace="$(mktemp -d)" + +cp $RESOURCE_DIR/file.txt.gz "$try_workspace/" +cd "$try_workspace/" + +: ${TMPDIR=/tmp} + +orig_tmp=$(ls "$TMPDIR") +"$try" -y -- "touch file_1.txt; echo test > file_2.txt; rm file.txt.gz" || return 1 +new_tmp=$(ls "$TMPDIR") + +if ! diff -q <(echo "$orig_tmp") <(echo "$new_tmp") +then + echo "temporary directory was not cleaned up; diff:" + diff --color -u <(echo "$orig_tmp") <(echo "$new_tmp") + return 1 +fi diff --git a/test/unzip_D_flag_commit.sh b/test/unzip_D_flag_commit.sh new file mode 100755 index 00000000..19b75778 --- /dev/null +++ b/test/unzip_D_flag_commit.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +TRY_TOP="${TRY_TOP:-$(git rev-parse --show-toplevel --show-superproject-working-tree)}" +TRY="$TRY_TOP/try" + +cleanup() { + cd / + + if [ -d "$try_workspace" ] + then + rm -rf "$try_workspace" >/dev/null 2>&1 + fi + + if [ -d "$try_example_dir" ] + then + rm -rf "$try_example_dir" + fi + + if [ -f "$expected" ] + then + rm "$expected" + fi +} + +trap 'cleanup' EXIT + +try_workspace=$(mktemp -d) +cd "$try_workspace" || return 9 + +# Set up expected output +expected="$(mktemp)" +echo 'Hello World!' >"$expected" +cp "$TRY_TOP/test/resources/file.txt.gz" "$try_workspace/" + +try_example_dir="$(mktemp -d)" +"$TRY" -D "$try_example_dir" gunzip file.txt.gz || return 1 +"$TRY" commit "$try_example_dir" || return 2 +diff -q "$expected" file.txt || return 3 diff --git a/test/unzip_D_flag_commit_without_cleanup.sh b/test/unzip_D_flag_commit_without_cleanup.sh new file mode 100755 index 00000000..5af0e5c8 --- /dev/null +++ b/test/unzip_D_flag_commit_without_cleanup.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +TRY_TOP="${TRY_TOP:-$(git rev-parse --show-toplevel --show-superproject-working-tree)}" +TRY="$TRY_TOP/try" + +cleanup() { + cd / + + if [ -d "$try_workspace" ] + then + rm -rf "$try_workspace" >/dev/null 2>&1 + fi + + if [ -d "$try_example_dir" ] + then + rm -rf "$try_example_dir" + fi +} + +trap 'cleanup' EXIT + +try_workspace="$(mktemp -d)" +cd "$try_workspace" || return 9 + +cp "$TRY_TOP/test/resources/file.txt.gz" "$try_workspace/" +try_example_dir="$(mktemp -d)" + +"$TRY" -D "$try_example_dir" gunzip file.txt.gz || return 1 +if ! [ -d "$try_example_dir" ]; then + echo "try_example_dir disappeared with no commit" + return 1 +fi +"$TRY" commit "$try_example_dir" || return 1 +if ! [ -d "$try_example_dir" ]; then + echo "try_example_dir disappeared after manual commit" + return 1 +fi diff --git a/test/unzip_no_flag.sh b/test/unzip_no_flag.sh new file mode 100755 index 00000000..c8b784a5 --- /dev/null +++ b/test/unzip_no_flag.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +TRY_TOP="${TRY_TOP:-$(git rev-parse --show-toplevel --show-superproject-working-tree)}" +TRY="$TRY_TOP/try" + +cleanup() { + cd / + + if [ -d "$try_workspace" ] + then + rm -rf "$try_workspace" >/dev/null 2>&1 + fi + + if [ -f "$expected" ] + then + rm "$expected" + fi +} + +trap 'cleanup' EXIT + +try_workspace="$(mktemp -d)" +cd "$try_workspace" || return 9 + +# Set up expected output +expected="$(mktemp)" +echo 'Hello World!' >"$expected" + +cp "$TRY_TOP/test/resources/file.txt.gz" "$try_workspace/" + +"$TRY" -y gunzip file.txt.gz || return 1 +diff -q "$expected" file.txt