diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/CMakeLists.txt | 4 | ||||
-rw-r--r-- | tests/data/generic.ini | 18 | ||||
-rw-r--r-- | tests/rt_generic.sh | 19 | ||||
-rw-r--r-- | tests/test_artifactory.c | 2 | ||||
-rw-r--r-- | tests/test_conda.c | 6 | ||||
-rw-r--r-- | tests/test_docker.c | 2 | ||||
-rw-r--r-- | tests/test_download.c | 1 | ||||
-rw-r--r-- | tests/test_ini.c | 2 | ||||
-rw-r--r-- | tests/test_junitxml.c | 1 | ||||
-rw-r--r-- | tests/test_multiprocessing.c | 127 | ||||
-rw-r--r-- | tests/test_recipe.c | 2 | ||||
-rw-r--r-- | tests/test_str.c | 4 | ||||
-rw-r--r-- | tests/test_wheel.c | 6 |
13 files changed, 181 insertions, 13 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 62f58a9..f4380e0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -5,8 +5,8 @@ include_directories( find_program(BASH_PROGRAM bash) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/tests) set(CTEST_BINARY_DIRECTORY ${PROJECT_BINARY_DIR}/tests) -set(nix_gnu_cflags -Wno-error -Wno-unused-parameter -Wno-discarded-qualifiers) -set(nix_clang_cflags -Wno-unused-parameter -Wno-incompatible-pointer-types-discards-qualifiers) +set(nix_gnu_cflags -Wno-format-truncation -Wno-error -Wno-unused-parameter -Wno-unused-result -Wno-discarded-qualifiers) +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) diff --git a/tests/data/generic.ini b/tests/data/generic.ini index c1e5c9c..fd67ed7 100644 --- a/tests/data/generic.ini +++ b/tests/data/generic.ini @@ -17,6 +17,7 @@ installer_baseurl = https://github.com/conda-forge/miniforge/releases/download/{ ;conda_packages = pip_packages = firewatch==0.0.4 + tweakwcs==0.8.8 [runtime] @@ -25,8 +26,21 @@ PYTHONUNBUFFERED = 1 [test:firewatch] repository = https://github.com/astroconda/firewatch -script = +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] @@ -36,7 +50,7 @@ dest = {{ meta.mission }}/{{ info.build_name }}/ [deploy:docker] -;registry = bytesalad.stsci.edu +registry = bytesalad.stsci.edu image_compression = zstd -v -9 -c build_args = SNAPSHOT_INPUT={{ info.release_name }}.yml diff --git a/tests/rt_generic.sh b/tests/rt_generic.sh index 6da953d..6e4454c 100644 --- a/tests/rt_generic.sh +++ b/tests/rt_generic.sh @@ -6,10 +6,16 @@ if [ -n "$GITHUB_TOKEN" ] && [ -z "$STASIS_GH_TOKEN"]; then else export STASIS_GH_TOKEN="anonymous" fi +python_versions=( + 3.10 + 3.11 + 3.12 +) topdir=$(pwd) ws="rt_workspace" +rm -rf "$ws" mkdir -p "$ws" ws="$(realpath $ws)" @@ -28,9 +34,12 @@ popd pushd "$ws" type -P stasis type -P stasis_indexer + retcode=0 - stasis --no-docker --no-artifactory --unbuffered -v "$topdir"/generic.ini - retcode=$? + for py_version in "${python_versions[@]}"; do + stasis --python "$py_version" --no-docker --no-artifactory --unbuffered -v "$topdir"/generic.ini + retcode+=$? + done set +x @@ -54,7 +63,7 @@ pushd "$ws" for cond in "${fail_on_main[@]}"; do if grep --color -H -n "$cond" "$x" >&2; then echo "ERROR DETECTED IN $x!" >&2 - retcode=2 + retcode+=1 fi done done @@ -94,6 +103,8 @@ pushd "$ws" done popd -rm -rf "$ws" +if [ -z "$RT_KEEP_WORKSPACE" ]; then + rm -rf "$ws" +fi exit $retcode
\ No newline at end of file diff --git a/tests/test_artifactory.c b/tests/test_artifactory.c index 1a21f0e..2c732fa 100644 --- a/tests/test_artifactory.c +++ b/tests/test_artifactory.c @@ -1,4 +1,6 @@ #include "testing.h" +#include "artifactory.h" +#include "delivery.h" // Import private functions from core extern int delivery_init_platform(struct Delivery *ctx); diff --git a/tests/test_conda.c b/tests/test_conda.c index 72217fc..2ed869a 100644 --- a/tests/test_conda.c +++ b/tests/test_conda.c @@ -1,4 +1,6 @@ #include "testing.h" +#include "conda.h" +#include "delivery.h" char cwd_start[PATH_MAX]; char cwd_workspace[PATH_MAX]; @@ -38,8 +40,8 @@ struct Delivery ctx; void test_conda_installation() { char *install_url = calloc(255, sizeof(install_url)); - delivery_get_installer_url(&ctx, install_url); - delivery_get_installer(&ctx, install_url); + delivery_get_conda_installer_url(&ctx, install_url); + delivery_get_conda_installer(&ctx, install_url); delivery_install_conda(ctx.conda.installer_path, ctx.storage.conda_install_prefix); STASIS_ASSERT_FATAL(access(ctx.storage.conda_install_prefix, F_OK) == 0, "conda was not installed correctly"); STASIS_ASSERT_FATAL(conda_activate(ctx.storage.conda_install_prefix, "base") == 0, "unable to activate base environment"); diff --git a/tests/test_docker.c b/tests/test_docker.c index 04a73aa..6eec53c 100644 --- a/tests/test_docker.c +++ b/tests/test_docker.c @@ -1,4 +1,6 @@ #include "testing.h" +#include "docker.h" + struct DockerCapabilities cap_suite; void test_docker_capable() { diff --git a/tests/test_download.c b/tests/test_download.c index cee7683..ad8724e 100644 --- a/tests/test_download.c +++ b/tests/test_download.c @@ -1,4 +1,5 @@ #include "testing.h" +#include "download.h" void test_download() { struct testcase { diff --git a/tests/test_ini.c b/tests/test_ini.c index 2579e21..e4a7808 100644 --- a/tests/test_ini.c +++ b/tests/test_ini.c @@ -86,11 +86,13 @@ void test_ini_setval_getval() { STASIS_ASSERT(ini_getval(ini, "default", "a", INIVAL_TYPE_STR, render_mode, &val) == 0, "failed to get value"); STASIS_ASSERT(strcmp(val.as_char_p, "a") != 0, "unexpected value loaded from modified variable"); STASIS_ASSERT(strcmp(val.as_char_p, "changed") == 0, "unexpected value loaded from modified variable"); + guard_free(val.as_char_p); STASIS_ASSERT(ini_setval(&ini, INI_SETVAL_APPEND, "default", "a", " twice") == 0, "failed to set value"); STASIS_ASSERT(ini_getval(ini, "default", "a", INIVAL_TYPE_STR, render_mode, &val) == 0, "failed to get value"); STASIS_ASSERT(strcmp(val.as_char_p, "changed") != 0, "unexpected value loaded from modified variable"); STASIS_ASSERT(strcmp(val.as_char_p, "changed twice") == 0, "unexpected value loaded from modified variable"); + guard_free(val.as_char_p); ini_free(&ini); remove(filename); } diff --git a/tests/test_junitxml.c b/tests/test_junitxml.c index 9b2181e..7111249 100644 --- a/tests/test_junitxml.c +++ b/tests/test_junitxml.c @@ -1,4 +1,5 @@ #include "testing.h" +#include "junitxml.h" void test_junitxml_testsuite_read() { struct JUNIT_Testsuite *testsuite; diff --git a/tests/test_multiprocessing.c b/tests/test_multiprocessing.c new file mode 100644 index 0000000..b9cd309 --- /dev/null +++ b/tests/test_multiprocessing.c @@ -0,0 +1,127 @@ +#include "testing.h" +#include "multiprocessing.h" + +static struct MultiProcessingPool *pool; +char *commands[] = { + "sleep 1; true", + "sleep 2; uname -a", + "sleep 3; /bin/echo hello world", + "sleep 4; true", + "sleep 5; uname -a", + "sleep 6; /bin/echo hello world", +}; + +void test_mp_pool_init() { + STASIS_ASSERT((pool = mp_pool_init("mypool", "mplogs")) != NULL, "Pool initialization failed"); + STASIS_ASSERT_FATAL(pool != NULL, "Should not be NULL"); + STASIS_ASSERT(pool->num_alloc == MP_POOL_TASK_MAX, "Wrong number of default records"); + STASIS_ASSERT(pool->num_used == 0, "Wrong number of used records"); + STASIS_ASSERT(strcmp(pool->log_root, "mplogs") == 0, "Wrong log root directory"); + STASIS_ASSERT(strcmp(pool->ident, "mypool") == 0, "Wrong identity"); + + int data_bad_total = 0; + for (size_t i = 0; i < pool->num_alloc; i++) { + int data_bad = 0; + struct MultiProcessingTask *task = &pool->task[i]; + + data_bad += task->status == 0 ? 0 : 1; + data_bad += task->pid == 0 ? 0 : 1; + data_bad += task->parent_pid == 0 ? 0 : 1; + data_bad += task->signaled_by == 0 ? 0 : 1; + data_bad += task->time_data.t_start.tv_nsec == 0 ? 0 : 1; + data_bad += task->time_data.t_start.tv_sec == 0 ? 0 : 1; + data_bad += task->time_data.t_stop.tv_nsec == 0 ? 0 : 1; + data_bad += task->time_data.t_stop.tv_sec == 0 ? 0 : 1; + data_bad += (int) strlen(task->ident) == 0 ? 0 : 1; + data_bad += (int) strlen(task->parent_script) == 0 ? 0 : 1; + if (data_bad) { + SYSERROR("%s.task[%zu] has garbage values!", pool->ident, i); + SYSERROR(" ident: %s", task->ident); + SYSERROR(" status: %d", task->status); + SYSERROR(" pid: %d", task->pid); + SYSERROR(" parent_pid: %d", task->parent_pid); + SYSERROR(" signaled_by: %d", task->signaled_by); + SYSERROR(" t_start.tv_nsec: %ld", task->time_data.t_start.tv_nsec); + SYSERROR(" t_start.tv_sec: %ld", task->time_data.t_start.tv_sec); + SYSERROR(" t_stop.tv_nsec: %ld", task->time_data.t_stop.tv_nsec); + SYSERROR(" t_stop.tv_sec: %ld", task->time_data.t_stop.tv_sec); + data_bad_total++; + } + } + STASIS_ASSERT(data_bad_total == 0, "Task array is not pristine"); + mp_pool_free(&pool); +} + +void test_mp_task() { + pool = mp_pool_init("mypool", "mplogs"); + + if (pool) { + for (size_t i = 0; i < sizeof(commands) / sizeof(*commands); i++) { + struct MultiProcessingTask *task; + char task_name[100] = {0}; + sprintf(task_name, "mytask%zu", i); + STASIS_ASSERT_FATAL((task = mp_pool_task(pool, task_name, NULL, commands[i])) != NULL, "Task should not be NULL"); + STASIS_ASSERT(task->pid == MP_POOL_PID_UNUSED, "PID should be non-zero at this point"); + STASIS_ASSERT(task->parent_pid == MP_POOL_PID_UNUSED, "Parent PID should be non-zero"); + STASIS_ASSERT(task->status == -1, "Status should be -1 (not started yet)"); + STASIS_ASSERT(strcmp(task->ident, task_name) == 0, "Wrong task identity"); + STASIS_ASSERT(strstr(task->log_file, pool->log_root) != NULL, "Log file path must be in log_root"); + } + } +} + +void test_mp_pool_join() { + STASIS_ASSERT(mp_pool_join(pool, get_cpu_count(), 0) == 0, "Pool tasks should have not have failed"); + for (size_t i = 0; i < pool->num_used; i++) { + struct MultiProcessingTask *task = &pool->task[i]; + STASIS_ASSERT(task->pid == MP_POOL_PID_UNUSED, "Task should be marked as unused"); + STASIS_ASSERT(task->status == 0, "Task status should be zero (success)"); + } +} + +void test_mp_pool_free() { + mp_pool_free(&pool); + STASIS_ASSERT(pool == NULL, "Should be NULL"); +} + +void test_mp_pool_workflow() { + struct testcase { + const char *input_cmd; + int input_join_flags; + int expected_result; + int expected_status; + int expected_signal; + }; + struct testcase tc[] = { + {.input_cmd = "true && kill $$", .input_join_flags = 0, .expected_result = 1, .expected_status = 0, .expected_signal = SIGTERM}, + {.input_cmd = "false || kill $$", .input_join_flags = 0, .expected_result = 1, .expected_status = 0, .expected_signal = SIGTERM}, + {.input_cmd = "true", .input_join_flags = 0,.expected_result = 0, .expected_status = 0, .expected_signal = 0}, + {.input_cmd = "false", .input_join_flags = 0, .expected_result = 1, .expected_status = 1, .expected_signal = 0}, + }; + for (size_t i = 0; i < sizeof(tc) / sizeof(*tc); i++) { + struct testcase *test = &tc[i]; + struct MultiProcessingPool *p; + struct MultiProcessingTask *task; + STASIS_ASSERT((p = mp_pool_init("workflow", "mplogs")) != NULL, "Failed to initialize pool"); + STASIS_ASSERT((task = mp_pool_task(p, "task", NULL, (char *) test->input_cmd)) != NULL, "Failed to queue task"); + STASIS_ASSERT(mp_pool_join(p, get_cpu_count(), test->input_join_flags) == test->expected_result, "Unexpected result"); + STASIS_ASSERT(task->status == test->expected_status, "Unexpected status"); + STASIS_ASSERT(task->signaled_by == test->expected_signal, "Unexpected signal"); + STASIS_ASSERT(task->pid == MP_POOL_PID_UNUSED, "Unexpected PID. Should be marked UNUSED."); + mp_pool_show_summary(p); + mp_pool_free(&p); + } +} + +int main(int argc, char *argv[]) { + STASIS_TEST_BEGIN_MAIN(); + STASIS_TEST_FUNC *tests[] = { + test_mp_pool_init, + test_mp_task, + test_mp_pool_join, + test_mp_pool_free, + test_mp_pool_workflow, + }; + STASIS_TEST_RUN(tests); + STASIS_TEST_END_MAIN(); +} diff --git a/tests/test_recipe.c b/tests/test_recipe.c index 8e2c470..7c55cd5 100644 --- a/tests/test_recipe.c +++ b/tests/test_recipe.c @@ -1,4 +1,6 @@ #include "testing.h" +#include "relocation.h" +#include "recipe.h" static void make_local_recipe(const char *localdir) { char path[PATH_MAX] = {0}; diff --git a/tests/test_str.c b/tests/test_str.c index 85c3b78..4991c1c 100644 --- a/tests/test_str.c +++ b/tests/test_str.c @@ -79,6 +79,7 @@ void test_strdup_array_and_strcmp_array() { for (size_t outer = 0; outer < sizeof(tc) / sizeof(*tc); outer++) { char **result = strdup_array((char **) tc[outer].data); STASIS_ASSERT(strcmp_array((const char **) result, tc[outer].expected) == 0, "array members were different"); + GENERIC_ARRAY_FREE(result); } const struct testcase tc_bad[] = { @@ -94,6 +95,7 @@ void test_strdup_array_and_strcmp_array() { for (size_t outer = 0; outer < sizeof(tc_bad) / sizeof(*tc_bad); outer++) { char **result = strdup_array((char **) tc_bad[outer].data); STASIS_ASSERT(strcmp_array((const char **) result, tc_bad[outer].expected) != 0, "array members were identical"); + GENERIC_ARRAY_FREE(result); } } @@ -242,7 +244,7 @@ void test_join_ex() { }; for (size_t i = 0; i < sizeof(tc) / sizeof(*tc); i++) { char *result; - result = join_ex(tc[i].delim, "a", "b", "c", "d", "e", NULL); + result = join_ex((char *) tc[i].delim, "a", "b", "c", "d", "e", NULL); STASIS_ASSERT(strcmp(result ? result : "", tc[i].expected) == 0, "failed to join array"); guard_free(result); } diff --git a/tests/test_wheel.c b/tests/test_wheel.c index 99ac97c..6818b22 100644 --- a/tests/test_wheel.c +++ b/tests/test_wheel.c @@ -1,4 +1,5 @@ #include "testing.h" +#include "wheel.h" void test_get_wheel_file() { struct testcase { @@ -50,12 +51,12 @@ void test_get_wheel_file() { }, }; - struct Wheel *doesnotexist = get_wheel_file("doesnotexist", "doesnotexist-0.0.1-py2.py3-none-any.whl", (char *[]) {"not", NULL}, WHEEL_MATCH_ANY); + struct Wheel *doesnotexist = get_wheel_info("doesnotexist", "doesnotexist-0.0.1-py2.py3-none-any.whl", (char *[]) {"not", NULL}, WHEEL_MATCH_ANY); STASIS_ASSERT(doesnotexist == NULL, "returned non-NULL on error"); for (size_t i = 0; i < sizeof(tc) / sizeof(*tc); i++) { struct testcase *test = &tc[i]; - struct Wheel *wheel = get_wheel_file(".", test->expected.distribution, (char *[]) {(char *) test->expected.version, NULL}, WHEEL_MATCH_ANY); + struct Wheel *wheel = get_wheel_info(".", test->expected.distribution, (char *[]) {(char *) test->expected.version, NULL}, WHEEL_MATCH_ANY); STASIS_ASSERT(wheel != NULL, "result should not be NULL!"); STASIS_ASSERT(wheel->file_name && strcmp(wheel->file_name, test->expected.file_name) == 0, "mismatched file name"); STASIS_ASSERT(wheel->version && strcmp(wheel->version, test->expected.version) == 0, "mismatched version"); @@ -67,6 +68,7 @@ void test_get_wheel_file() { STASIS_ASSERT(strcmp(wheel->build_tag, test->expected.build_tag) == 0, "mismatched build tag (optional arbitrary string)"); } + wheel_free(&wheel); } } |