diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2020-07-02 10:53:55 -0400 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2020-07-02 10:53:55 -0400 |
commit | 5803dc0fdb911a67ad9ca1ef9600edc58331d55a (patch) | |
tree | 0289621a8a98b3dd91a7d9b0e35ec62b5c160e24 | |
parent | 8e0934853a374eb340ee0dd96fd21a3d7c74183d (diff) | |
download | splitfits-5803dc0fdb911a67ad9ca1ef9600edc58331d55a.tar.gz |
Add basic test framework and a few tests
-rw-r--r-- | CMakeLists.txt | 6 | ||||
-rwxr-xr-x | test.sh | 184 | ||||
-rw-r--r-- | tests/test_split.sh | 35 | ||||
-rw-r--r-- | tests/test_usage.sh | 9 |
4 files changed, 234 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index ea12358..5287d06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,5 +5,11 @@ set(CMAKE_C_STANDARD 99) add_executable(splitfits splitfits.c) +file(GLOB TEST_FRAMEWORK "tests") +file(COPY "test.sh" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) +file(COPY ${TEST_FRAMEWORK} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + +add_custom_target(check "${CMAKE_CURRENT_BINARY_DIR}/test.sh") + install(TARGETS splitfits RUNTIME) @@ -0,0 +1,184 @@ +#!/usr/bin/env bash +set -o pipefail + +RTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +test_program=${RTDIR}/splitfits +test_data=${RTDIR}/data +test_data_remote=https://nx.astroconda.org/repository +test_data_remote_auth=${test_data_remote_auth:-} +test_data_upload=generic/spb-splitfits/$(git describe --always) + +get_data_exists() { + local url + local response + + url="${test_data_remote}/$1" + if [[ -z $url ]]; then + echo "get_data_exists: requires a path relative to $test_data_remote" + exit 1 + fi + + response=$(curl -s --head "$url" | head -n 1 | awk '{print $2}') + if (( $response != 200 )); then + return 1; + fi + return 0; +} + +get_data() { + local url + local filename + + if [[ ! -d "${test_data}" ]]; then + mkdir -p "${test_data}" + fi + + url="${test_data_remote}/$1" + if [[ -z $url ]]; then + echo "get_data: requires a path relative to $test_data_remote" + exit 1 + fi + + filename=$(basename $url) + if ! get_data_exists "$1"; then + echo "${url}: not found on remote server" >&2 + return 1 + fi + + if ! (cd $test_data && curl -L -O "$url"); then + echo "Could not download data" >&2 + return 1 + fi + + echo "$test_data/$filename"; +} + +put_data() { + local url + local filename + + url="${test_data_remote}/$2" + filename="$1" + + if [[ -z $url ]]; then + echo "put_data: requires a path relative to $test_data_remote" + return 1 + fi + + if ! curl -s --user "${test_data_remote_auth}" --upload-file "${filename}" "${url}/${filename}"; then + echo "Could not upload '${filename}' to '${url}'" >&2 + return 1 + fi + + return 0 +} + +put_result() { + local src; + local dest; + src="$1" + dest="$2" + + if [[ ! -d "$src" ]]; then + echo "push_result: source directory does not exist: ${src}" >&2 + return 1 + fi + + if [[ -z "$dest" ]]; then + echo "push_result: requires a destination relative to ${test_data_remote}" >&2 + return 1 + fi + + for f in $(find "${src}" -type f); do + echo "Uploading '$f' to '$dest'" + if ! put_data "$f" "${dest}"; then + echo "Failed uploading '$src' to '$dest'" >&2 + return 1 + fi + done; + return 0 +} + +read_tests() { + for f in "${RTDIR}"/tests/test_*; do + source "$f" || return 0 + done + return 1 +} + +export_tests() { + tests=( + $(declare -f | cut -d ' ' -f 1 | grep -E '^test_') + ) + total_passed=0 + total_failed=0 + total_tests=${#tests[@]} +} + +run_tests() { + for (( i=0; i < ${total_tests}; i++ )); do + just_failed=0 + test_case="${tests[$i]}" + rm -rf "${test_case}" + mkdir -p "${test_case}" + pushd "${test_case}" &>/dev/null + log_file="output_${test_case}.log" + + /bin/echo -n -e "[$i] ${test_case}... " + "$test_case" 2>&1 | tee ${log_file} &>/dev/null + retval=$? + + if [[ "$retval" -ne "0" ]]; then + echo "FAILED ($retval)" + (( just_failed++ )) + (( total_failed++ )) + else + echo "PASSED" + (( total_passed++ )) + fi + + if [[ ${just_failed} -ne 0 ]] && [[ -s ${log_file} ]]; then + echo "# OUTPUT:" + cat "${log_file}" + fi + popd &>/dev/null + done + + # Upload all artifacts in all test directories + if [[ -n "$test_data_remote_auth" ]]; then + echo + for (( i=0; i < ${total_tests}; i++ )); do + test_case="${tests[i]}" + put_result ${test_case} ${test_data_upload} + done + fi +} + +check_runtime() { + if [[ ! -f "${test_program}" ]]; then + echo "Tests cannot run without: ${test_program}" >&2 + exit 1 + fi +} + +show_stats() { + printf "\n%d test(s): %d passed, %d failed\n" ${total_tests} ${total_passed} ${total_failed} +} + +# main program +check_runtime + +if read_tests; then + echo "Failed to aggregate tests." >&2 + exit 1 +fi + +export_tests +run_tests +show_stats + +if (( total_failed )); then + exit 1 +fi + +exit 0 diff --git a/tests/test_split.sh b/tests/test_split.sh new file mode 100644 index 0000000..141e320 --- /dev/null +++ b/tests/test_split.sh @@ -0,0 +1,35 @@ +test_splitfits_data1() { + local datafile + local retval + + retval=0 + datafile=$(get_data generic/fits/sample.fits) + [[ ! -f ${datafile} ]] && return 1 + + if ! ${test_program} -o ${test_case} ${datafile}; then + return 1 + fi + + set +x + return $retval +} + +test_splitfits_combine_data1() { + local datafile + local retval + + retval=0 + datafile=$(get_data generic/fits/sample.fits) + [[ ! -f ${datafile} ]] && return 1 + + if ! ${test_program} -o ${test_case} ${datafile}; then + return 1 + fi + + if ! ${test_program} -c ${test_case}/$(basename ${datafile}).part_map; then + return 1 + fi + + set +x + return $retval +} diff --git a/tests/test_usage.sh b/tests/test_usage.sh new file mode 100644 index 0000000..2a257d9 --- /dev/null +++ b/tests/test_usage.sh @@ -0,0 +1,9 @@ +test_splitfits_usage_longopt() { + ${test_program} --help + return $? +} + +test_splitfits_usage_shortopt() { + ${test_program} -h + return $? +} |