diff options
| -rw-r--r-- | .github/workflows/cmake-multi-platform.yml | 1 | ||||
| -rw-r--r-- | src/lib/core/conda.c | 4 | ||||
| -rw-r--r-- | tests/CMakeLists.txt | 16 | ||||
| -rw-r--r-- | tests/README.md | 48 | ||||
| -rw-r--r-- | tests/_rt_boilerplate.sh | 27 | ||||
| -rw-r--r-- | tests/_test_boilerplate.c | 12 | ||||
| -rw-r--r-- | tests/data/generic_based_on.ini | 65 | ||||
| -rw-r--r-- | tests/data/generic_based_on.yml | 9 | ||||
| -rw-r--r-- | tests/rt_generic.sh | 125 | ||||
| -rw-r--r-- | tests/rt_generic_based_on.sh | 30 | ||||
| -rw-r--r-- | tests/setup.sh | 267 | ||||
| -rw-r--r-- | tests/test_download.c | 21 | ||||
| -rw-r--r-- | tests/test_junitxml.c | 4 | 
13 files changed, 514 insertions, 115 deletions
| diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index f141141..ef41555 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -58,6 +58,7 @@ jobs:          -DCMAKE_C_COMPILER=${{ matrix.c_compiler }}          -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}          -DBUILD_TESTING=ON +        -DBUILD_TESTING_RT=ON          -S ${{ github.workspace }}      - name: Build diff --git a/src/lib/core/conda.c b/src/lib/core/conda.c index 5954f20..c2cea0e 100644 --- a/src/lib/core/conda.c +++ b/src/lib/core/conda.c @@ -218,11 +218,13 @@ int conda_activate(const char *root, const char *env_name) {      const char *init_script_mamba = "/etc/profile.d/mamba.sh";      char path_conda[PATH_MAX] = {0};      char path_mamba[PATH_MAX] = {0}; +    char path_bin[PATH_MAX] = {0};      char logfile[PATH_MAX] = {0};      struct Process proc;      memset(&proc, 0, sizeof(proc));      // Where to find conda's init scripts +    sprintf(path_bin, "%s/bin", root);      sprintf(path_conda, "%s%s", root, init_script_conda);      sprintf(path_mamba, "%s%s", root, init_script_mamba); @@ -256,7 +258,7 @@ int conda_activate(const char *root, const char *env_name) {      // Fully activate conda and record its effect on the runtime environment      char command[PATH_MAX * 3]; -    snprintf(command, sizeof(command) - 1, "set -a; source %s; source %s; conda activate %s &>/dev/null; env -0", path_conda, path_mamba, env_name); +    snprintf(command, sizeof(command) - 1, "set -a; source %s; source %s; PATH=\"%s:$PATH\" conda activate %s &>/dev/null; env -0", path_conda, path_mamba, path_bin, env_name);      int retval = shell(&proc, command);      if (retval) {          // it didn't work; drop out for cleanup diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0da290f..e35d88d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,17 +9,25 @@ set(nix_gnu_cflags -Wno-format-truncation -Wno-error -Wno-unused-parameter -Wno-  set(nix_clang_cflags -Wno-format-truncation -Wno-unused-parameter -Wno-unused-result -Wno-incompatible-pointer-types-discards-qualifiers)  set(win_msvc_cflags /Wall) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/data/generic.ini ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/data/result.xml ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/data/result_error.xml ${CMAKE_CURRENT_BINARY_DIR} COPYONLY)  file(GLOB source_files "test_*.c") +file(GLOB rt_files "rt_*.sh") +set(ext_pattern "(^.*/|\\.[^.]*$)") + +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data +        DESTINATION ${CMAKE_CURRENT_BINARY_DIR})  if (BASH_PROGRAM AND BUILD_TESTING_RT) +    foreach(rt_file ${rt_files}) +        file(REAL_PATH ${rt_file} rt_name) +        string(REGEX REPLACE ${ext_pattern} "" rt_name ${rt_file}) +        add_test (${rt_name} ${BASH_PROGRAM} ${rt_file}) +    endforeach() +    add_test (rt_generic_based_on ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/rt_generic_based_on.sh)      add_test (rt_generic ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/rt_generic.sh)  endif()  foreach(source_file ${source_files}) -    string(REGEX REPLACE "(^.*/|\\.[^.]*$)" "" test_executable ${source_file}) +    string(REGEX REPLACE ${ext_pattern} "" test_executable ${source_file})      add_executable(${test_executable} ${source_file})      if (CMAKE_C_COMPILER_ID STREQUAL "GNU")          target_compile_options(${test_executable} PRIVATE ${nix_cflags} ${nix_gnu_cflags}) diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..bb1f896 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,48 @@ +# Testing STASIS + +## Unit tests + +Rules: + +* Use the boilerplate `_test_boilerplate.c` +  * ```shell +    cp _test_boilerplate.c test_mynewtest.c +    ``` +* Test file names start with `test_` (`test_file.c`) +* Test functions start with `test_` (`void test_function()`) +* Test suites can be skipped by returning `127` from `main()` +* PASS, FAIL, and SKIP conditions are set by the assertion macros `STASIS_{ASSERT,ASSERT_FATAL,SKIP_IF}` +* Parametrized tests should implement an array of `struct testcase` +  * The `testcase` structure should be local to each `test_` function +  * The `testcase` variables are freeform +  * Example: +    ```c +    void test_function() { +        struct testcase { +            int your; +            int variables; +            int here; +        }; +        struct testcase tc[] = { +            {.your = 0, .variables = 1, .here = 2}, +            {.your = 3, .variables = 4, .here = 5}, +            // ... +        }; +        for (size_t i = 0; i < sizeof(tc) / sizeof(*tc); i++) { +            // STASIS_ASSERT()s here +        } +    } +    ``` +     +## Regression test (RT) + +Rules: + +* Regression tests are shell scripts (BASH) +* Use the boilerplate `_rt_boilerplate.sh` +  * ```shell +    cp _rt_boilerplate.sh rt_mynewtest.sh +    ``` +* Test file names start with `rt_` (`rt_file.sh`) +* Test function names are freeform, however they must be executed using `run_command()` (`run_command test_function`) +* Test suites can be skipped by returning `127` from the shell script
\ No newline at end of file diff --git a/tests/_rt_boilerplate.sh b/tests/_rt_boilerplate.sh new file mode 100644 index 0000000..22a2688 --- /dev/null +++ b/tests/_rt_boilerplate.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +here="$(dirname ${BASH_SOURCE[0]})" +source $here/setup.sh + +TEST_NAME= + +#test_fails() { +#    return 1 +#} +# +#test_passes() { +#    return 0 +#} +# +#test_skips() { +#    return 127 +#} + +setup_workspace "$TEST_NAME" + +#run_command test_fails +#run_command test_passes +#run_command test_skips +#run_command false  # fails +#run_command true   # passes + +teardown_workspace "$TEST_NAME"
\ No newline at end of file diff --git a/tests/_test_boilerplate.c b/tests/_test_boilerplate.c index 1d7734b..b13568d 100644 --- a/tests/_test_boilerplate.c +++ b/tests/_test_boilerplate.c @@ -1,16 +1,24 @@  #include "testing.h" +/*  void test_NAME() {      struct testcase {      }; -    STASIS_ASSERT(); +    struct testcase tc[] = { +        { // ... }, +    } + +    for (size_t i = 0; i < sizeof(tc) / sizeof(*tc); i++) { +        // STASIS_ASSERT(); +    }  } + */  int main(int argc, char *argv[]) {      STASIS_TEST_BEGIN_MAIN();      STASIS_TEST_FUNC *tests[] = { -        test_NAME, +        //test_NAME,      };      STASIS_TEST_RUN(tests);      STASIS_TEST_END_MAIN(); diff --git a/tests/data/generic_based_on.ini b/tests/data/generic_based_on.ini new file mode 100644 index 0000000..1c993ea --- /dev/null +++ b/tests/data/generic_based_on.ini @@ -0,0 +1,65 @@ +[meta] +mission = generic +name = GENERIC +version = 1.2.3 +rc = 1 +final = false +based_on = {{ env:TEST_DATA }}/generic_based_on.yml +python = 3.11 + + +[conda] +installer_name = Miniforge3 +installer_version = 24.3.0-0 +installer_platform = {{env:STASIS_CONDA_PLATFORM}} +installer_arch = {{env:STASIS_CONDA_ARCH}} +installer_baseurl = https://github.com/conda-forge/miniforge/releases/download/{{conda.installer_version}} +;conda_packages = +pip_packages = +    firewatch==0.0.4 +    tweakwcs==0.8.8 + + +[runtime] +CPPFLAGS = ${CPPFLAGS} -fpermissive +PYTHONUNBUFFERED = 1 + + +[test:firewatch] +repository = https://github.com/astroconda/firewatch +script_setup = +    pip install -e '.' +script = +    firewatch -c conda-forge -p ${STASIS_CONDA_PLATFORM_SUBDIR} | grep -E ' python-[0-9]' + + +[test:tweakwcs] +repository = https://github.com/spacetelescope/tweakwcs +script_setup = +    pip install -e '.[test]' +script = +    pytest \ +        -r fEsx \ +        --basetemp="{{ func:basetemp_dir() }}" \ +        --junitxml="{{ func:junitxml_file() }}" + + +[deploy:artifactory:delivery] +files = +    {{ storage.output_dir }}/** +dest = {{ meta.mission }}/{{ info.build_name }}/ + + +[deploy:docker] +registry = bytesalad.stsci.edu +image_compression = zstd -v -9 -c +build_args = +    SNAPSHOT_INPUT={{ info.release_name }}.yml +    SNAPSHOT_PKGDIR=packages +tags = +    {{ meta.name }}:{{ info.build_number }}-py{{ meta.python_compact }} +    {{ deploy.docker.registry }}/{{ meta.name }}:{{ info.build_number }}-py{{ meta.python_compact }} +test_script = +    source /etc/profile +    python -m pip freeze +    mamba info diff --git a/tests/data/generic_based_on.yml b/tests/data/generic_based_on.yml new file mode 100644 index 0000000..3ab97a7 --- /dev/null +++ b/tests/data/generic_based_on.yml @@ -0,0 +1,9 @@ +channels: +  - conda-forge +dependencies: +  - pip +  - python +  - setuptools +  - pip: +    - firewatch==0.0.3 +    - tweakwcs==0.8.7
\ No newline at end of file diff --git a/tests/rt_generic.sh b/tests/rt_generic.sh index 6e4454c..674f6f0 100644 --- a/tests/rt_generic.sh +++ b/tests/rt_generic.sh @@ -1,110 +1,31 @@  #!/usr/bin/env bash -set -x -unset STASIS_SYSCONFDIR -if [ -n "$GITHUB_TOKEN" ] && [ -z "$STASIS_GH_TOKEN"]; then -    export STASIS_GH_TOKEN="$GITHUB_TOKEN" -else -    export STASIS_GH_TOKEN="anonymous" -fi -python_versions=( -    3.10 +here="$(dirname ${BASH_SOURCE[0]})" +source $here/setup.sh + +TEST_NAME=generic +PYTHON_VERSIONS=(      3.11 -    3.12  ) -topdir=$(pwd) - -ws="rt_workspace" -rm -rf "$ws" -mkdir -p "$ws" -ws="$(realpath $ws)" - -prefix="$ws"/local -mkdir -p "$prefix" - -bdir="$ws"/build -mkdir -p "$bdir" - -pushd "$bdir" -cmake -DCMAKE_INSTALL_PREFIX="$prefix" -DCMAKE_BUILD_TYPE=Debug "${topdir}"/../.. -make install -export PATH="$prefix/bin:$PATH" -popd - -pushd "$ws" -    type -P stasis -    type -P stasis_indexer -    retcode=0 - -    for py_version in "${python_versions[@]}"; do -        stasis --python "$py_version" --no-docker --no-artifactory --unbuffered -v "$topdir"/generic.ini -        retcode+=$? -    done - -    set +x - -    echo "#### Files ####" -    find stasis/*/output | sort -    echo - -    echo "#### Contents ####" -    files=$(find stasis/*/output -type f \( -name '*.yml' -o -name '*.md' -o -name '*.stasis' -o -name '*.ini' \) | sort) -    for x in $files; do -        echo -        echo "FILENAME: $x" -        echo -        cat "$x" -        echo "[EOF]" -        echo - -        fail_on_main=( -            "(null)" -        ) -        for cond in "${fail_on_main[@]}"; do -            if grep --color -H -n "$cond" "$x" >&2; then -                echo "ERROR DETECTED IN $x!" >&2 -                retcode+=1 -            fi -        done -    done - -    # Something above failed, so drop out. Don't bother indexing. -    # Don't clean up either. -    (( retcode )) && exit $retcode - -    fail_on_indexer=( -        "(null)" -    ) -    logfile="stasis_indexer.log" -    set -x -    stasis_indexer --web --unbuffered -v stasis/* 2>&1 | tee "$logfile" -    retcode=$? - -    set +x -    echo "#### Files ####" -    find output +setup_workspace "$TEST_NAME" +run_command install_stasis +for py_version in "${PYTHON_VERSIONS[@]}"; do +    run_command run_stasis --python "$py_version" \ +        --no-docker \ +        --no-artifactory \ +        "$TEST_DATA"/"$TEST_NAME".ini +done -    for cond in "${fail_on_indexer[@]}"; do -        if grep --color -H -n "$cond" "$logfile" >&2; then -            echo "ERROR DETECTED IN INDEX OPERATION!" >&2 -            exit 1 -        fi -    done +check_output_add "(null)" +run_command check_output_stasis_dir stasis/*/output +check_output_reset -    echo "#### Contents ####" -    files=$(find output -type f \( -name '*.html' \) | sort) -    for x in $files; do -        echo -        echo "FILENAME: $x" -        echo -        cat "$x" -        echo "[EOF]" -        echo -    done -popd +# NOTE: indexer default output directory is "output" +check_output_add "(null)" +run_command run_stasis_indexer stasis +run_command check_output_indexed_dir output +check_output_reset -if [ -z "$RT_KEEP_WORKSPACE" ]; then -    rm -rf "$ws" -fi +run_command assert_file_contains "$LOGFILE_STASIS" "USE EXTERNAL" "External packages should have been used" -exit $retcode
\ No newline at end of file +teardown_workspace "$TEST_NAME"
\ No newline at end of file diff --git a/tests/rt_generic_based_on.sh b/tests/rt_generic_based_on.sh new file mode 100644 index 0000000..7d78399 --- /dev/null +++ b/tests/rt_generic_based_on.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +here="$(dirname ${BASH_SOURCE[0]})" +source $here/setup.sh + +TEST_NAME=generic_based_on +PYTHON_VERSIONS=( +    3.11 +) +setup_workspace "$TEST_NAME" +run_command install_stasis + +ln -s "$TEST_DATA"/"$TEST_NAME".yml +for py_version in "${PYTHON_VERSIONS[@]}"; do +    run_command run_stasis --python "$py_version" \ +        --no-docker \ +        --no-artifactory \ +        "$TEST_DATA"/"$TEST_NAME".ini +done + +check_output_add "(null)" +run_command check_output_stasis_dir stasis/*/output +check_output_reset + +# NOTE: indexer default output directory is "output" +check_output_add "(null)" +run_command run_stasis_indexer stasis +run_command check_output_indexed_dir output +check_output_reset + +teardown_workspace "$TEST_NAME" diff --git a/tests/setup.sh b/tests/setup.sh new file mode 100644 index 0000000..0875cac --- /dev/null +++ b/tests/setup.sh @@ -0,0 +1,267 @@ +#!/usr/bin/env bash +set -o pipefail + +export LOGFILE_STASIS="stasis.log" +export LOGFILE_INDEXER="stasis_indexer.log" +export CHECK_OUTPUT_PATTERNS=() + +unset STASIS_SYSCONFDIR +if [ -n "$GITHUB_TOKEN" ] && [ -z "$STASIS_GH_TOKEN"]; then +    export STASIS_GH_TOKEN="$GITHUB_TOKEN" +else +    export STASIS_GH_TOKEN="anonymous" +fi + +if [[ -z "$PYTHON_VERSIONS" ]]; then +    PYTHON_VERSIONS=( +        3.10 +        3.11 +        3.12 +    ) +fi + +setup_script_dir="$(dirname ${BASH_SOURCE[0]})" +export TOPDIR=$(pwd) +export TEST_DATA="$TOPDIR"/data + +WS_DEFAULT=rt_workspace_ +setup_workspace() { +    if [ -z "$1" ]; then +        echo "setup_workspace requires a name argument" >&2 +        return 1 +    fi +    WORKSPACE="${WS_DEFAULT}$1" +    rm -rf "$WORKSPACE" +    if ! mkdir -p "$WORKSPACE"; then +        echo "directory creation failed. cannot continue" >&2 +        return 1; +    fi +    WORKSPACE="$(realpath $WORKSPACE)" +     +    export PREFIX="$WORKSPACE"/local +    if ! mkdir -p "$PREFIX"; then +        echo "directory creation failed. cannot continue" >&2 +        return 1; +    fi + +    export BUILD_DIR="$WORKSPACE"/build +    if ! mkdir -p "$BUILD_DIR"; then +        echo "directory creation failed. cannot continue" >&2 +        return 1; +    fi + +    pushd "$WORKSPACE" +    export LANG="C" +    export HOME="$WORKSPACE" +    . /etc/profile +} + +teardown_workspace() { +    if [ -z "$1" ]; then +        echo "teardown_workspace requires a workspace path" >&2 +        return 1 +    elif ! [[ ${WS_DEFAULT}$1 =~ ${WS_DEFAULT}.* ]]; then +        echo "$1 is not a valid workspace" >&2 +        return 1 +    fi +    popd +    clean_up +} + +install_stasis() { +    pushd "$BUILD_DIR" +    if ! cmake -DCMAKE_INSTALL_PREFIX="$PREFIX" -DCMAKE_BUILD_TYPE=Debug "${TOPDIR}"/../..; then +        echo "cmake failed" >&2 +        return 1 +    fi + +    if ! make install; then +        echo "make failed" >&2 +        return 1 +    fi + +    export PATH="$PREFIX/bin:$PATH" +    hash -r +    if ! type -P stasis; then +        echo "stasis program not on PATH" >&2 +        return 1 +    fi + +    if ! type -P stasis_indexer; then +        echo "stasis_indexer program not on PATH" >&2 +        return 1 +    fi +    popd +} + + +STASIS_TEST_RESULT_FAIL=0 +STASIS_TEST_RESULT_PASS=0 +STASIS_TEST_RESULT_SKIP=0 +run_command() { +    local logfile="$(mktemp).log" +    local cmd="${@}" +    local lines_on_error=100 +    /bin/echo "Testing: $cmd " + +    $cmd &>"$logfile" +    code=$? +    if (( code )); then +        if (( code == 127 )); then +            echo "... SKIP" +            (( STASIS_TEST_RESULT_SKIP++ )) +        else +            echo "... FAIL" +            if (( $(wc -c "$logfile" | cut -d ' ' -f 1) > 1 )); then +                echo "#" +                echo "# Last $lines_on_error line(s) follow:" +                echo "#" +                tail -n $lines_on_error "$logfile" +            fi +            (( STASIS_TEST_RESULT_FAIL++ )) +        fi +    else +        echo "... PASS" +        (( STASIS_TEST_RESULT_PASS++ )) +    fi +    rm -f "$logfile" +} + +run_summary() { +    local total=$(( STASIS_TEST_RESULT_PASS + STASIS_TEST_RESULT_FAIL + STASIS_TEST_RESULT_SKIP)) +    echo +    echo "[RT] ${STASIS_TEST_RESULT_PASS} tests passed, ${STASIS_TEST_RESULT_FAIL} failed, ${STASIS_TEST_RESULT_SKIP} skipped out of ${total}" +    echo +} + +run_stasis() { +    local logfile="$LOGFILE_STASIS" +    $(type -P stasis) --unbuffered -v $@ 2>&1 | tee "$logfile" +} + +run_stasis_indexer() { +    local logfile="$LOGFILE_INDEXER" +    local root="$1" +    if [ -z "$root" ]; then +        echo "run_stasis_indexer root directory cannot be empty" >&2 +        exit 1 +    fi +    $(type -P stasis_indexer) --web --unbuffered -v "$root"/* 2>&1 | tee "$logfile" +} + +check_output_add() { +    local pattern="$1" +    CHECK_OUTPUT_PATTERNS+=("$pattern") +} + +check_output_reset() { +    CHECK_OUTPUT_PATTERNS=() +} + +check_output_stasis_dir() { +    local retcode=0 +    local startdir="$1" +    local logfile="$LOGFILE_STASIS" + +    echo "#### Files ####" +    find $startdir | sort +    echo + +    echo "#### Contents ####" +    files=$(find $startdir -type f \( -name "$logfile" -o -name '*.yml' -o -name '*.md' -o -name '*.stasis' -o -name '*.ini' \) | sort) +    for x in $files; do +        echo +        echo "FILENAME: $x" +        echo +        if [ "$x" == "$logfile" ]; then +            # do not print thousands of lines of output we _just_ sat through +            echo "Output omitted" +        else +            cat "$x" +            echo "[EOF]" +        fi +        echo + +        for cond in "${CHECK_OUTPUT_PATTERNS[@]}"; do +            if grep --color -H -n "$cond" "$x" >&2; then +                echo "ERROR DETECTED IN $x!" >&2 +                retcode+=1 +            fi +        done +    done + +    if (( retcode )); then +        return 1 +    else +        return 0 +    fi +} + +check_output_indexed_dir() { +    local retcode=0 +    local startdir="$1" +    local logfile="$2" + +    echo "#### Files ####" +    find $startdir | sort + +    for cond in "${CHECK_OUTPUT_PATTERNS[@]}"; do +        if grep --color -H -n "$cond" "$logfile" >&2; then +            echo "ERROR DETECTED IN INDEX OPERATION!" >&2 +            retcode+=1 +        fi +    done + +    echo "#### Contents ####" +    files=$(find $startdir -type f \( -name '*.html' \) | sort) +    for x in $files; do +        echo +        echo "FILENAME: $x" +        echo +        cat "$x" +        echo "[EOF]" +        echo +    done +    if (( retcode )); then +        return 1 +    else +        return 0 +    fi +} + +assert_eq() { +    local a="$1" +    local b="$2" +    local msg="$3" +    if [[ "$a" == "$b" ]]; then +        return 0 +    else +        [[ -n "$msg" ]] && echo "'$a' != '$b' :: $msg" >&2 +        return 1 +    fi +} + +assert_file_contains() { +    local file="$1" +    local str="$2" +    local msg="$3" +    if grep -E "$str" "$file" &>/dev/null; then +        return 0 +    else +        [[ -n "$msg" ]] && echo "'$str' not in file '$file' :: $msg" >&2 +        return 1 +    fi +} + +clean_up() { +    if [ -z "$RT_KEEP_WORKSPACE" ] && [ -d "$WORKSPACE" ]; then +        rm -rf "$WORKSPACE" +    fi + +    run_summary +    if (( STASIS_TEST_RESULT_FAIL )); then +        exit 1 +    else +        exit 0 +    fi +}
\ No newline at end of file diff --git a/tests/test_download.c b/tests/test_download.c index ad8724e..714e614 100644 --- a/tests/test_download.c +++ b/tests/test_download.c @@ -2,15 +2,20 @@  #include "download.h"  void test_download() { +    enum MATCH_STYLE { +        match_begins=0, +        match_contains, +    };      struct testcase {          const char *url;          long http_code; +        enum MATCH_STYLE style;          const char *data;          const char *errmsg;      };      struct testcase tc[] = { -            {.url = "https://ssb.stsci.edu/jhunk/stasis_test/test_download.txt", .http_code = 200L, .data = "It works!\n", .errmsg = NULL}, -            {.url = "https://ssb.stsci.edu/jhunk/stasis_test/test_download.broken", .http_code = 404L, .data = "<html", .errmsg = NULL}, +            {.url = "https://ssb.stsci.edu/jhunk/stasis_test/test_download.txt", .http_code = 200L, .data = "It works!\n", .style = match_begins, .errmsg = NULL}, +            {.url = "https://ssb.stsci.edu/jhunk/stasis_test/test_download.broken", .http_code = 404L, .data = "404", .style = match_contains, .errmsg = NULL},              {.url = "https://example.tld", .http_code = -1L, .data = NULL, .errmsg = "Couldn't resolve host name"},      }; @@ -28,10 +33,18 @@ void test_download() {          }          STASIS_ASSERT(http_code == tc[i].http_code, "expecting non-error HTTP code"); -        char **data = file_readlines(filename, 0, 100, NULL); +        //char **data = file_readlines(filename, 0, 100, NULL); +        char *data = stasis_testing_read_ascii(filename);          if (http_code >= 0) {              STASIS_ASSERT(data != NULL, "data should not be null"); -            STASIS_ASSERT(strncmp(data[0], tc[i].data, strlen(tc[i].data)) == 0, "data file does not match the expected contents"); +            printf("FILE: %s\nLOCAL: '%s'\nREMOTE: '%s'\n", tc[i].url, data, tc[i].data); +            if (tc[i].style == match_begins) { +                STASIS_ASSERT(strncmp(data, tc[i].data, strlen(tc[i].data)) == 0, "data file does not begin with the expected contents"); +            } else if (tc[i].style == match_contains) { +                STASIS_ASSERT(strstr(data, tc[i].data) != NULL, "data file does not contain the expected contents"); +            } else { +                STASIS_ASSERT(false, "Unrecognized matching mode"); +            }          } else {              STASIS_ASSERT(http_code == -1, "http_code should be -1 on fatal curl error");              STASIS_ASSERT(data == NULL, "data should be NULL on fatal curl error"); diff --git a/tests/test_junitxml.c b/tests/test_junitxml.c index 7111249..e222b56 100644 --- a/tests/test_junitxml.c +++ b/tests/test_junitxml.c @@ -3,7 +3,7 @@  void test_junitxml_testsuite_read() {      struct JUNIT_Testsuite *testsuite; -    STASIS_ASSERT_FATAL((testsuite = junitxml_testsuite_read("result.xml")) != NULL, "failed to load testsuite data"); +    STASIS_ASSERT_FATAL((testsuite = junitxml_testsuite_read("data/result.xml")) != NULL, "failed to load testsuite data");      STASIS_ASSERT(testsuite->name != NULL, "Test suite must be named");      STASIS_ASSERT(testsuite->skipped > 0, "missed skipped tests");      STASIS_ASSERT(testsuite->failures > 0, "missed failed tests"); @@ -44,7 +44,7 @@ void test_junitxml_testsuite_read() {  void test_junitxml_testsuite_read_error() {      struct JUNIT_Testsuite *testsuite; -    STASIS_ASSERT_FATAL((testsuite = junitxml_testsuite_read("result_error.xml")) != NULL, "failed to load testsuite data"); +    STASIS_ASSERT_FATAL((testsuite = junitxml_testsuite_read("data/result_error.xml")) != NULL, "failed to load testsuite data");      STASIS_ASSERT(testsuite->name != NULL, "test suite must be named");      STASIS_ASSERT(testsuite->skipped == 0, "should not have any skipped tests"); | 
