aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/CMakeLists.txt2
-rw-r--r--tests/test_docker.c2
-rw-r--r--tests/test_strlist.c15
-rw-r--r--tests/test_utils.c10
-rw-r--r--tests/test_wheel.c275
-rw-r--r--tests/test_wheelinfo.c91
6 files changed, 315 insertions, 80 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 08ef833..dd68231 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -44,7 +44,7 @@ foreach(source_file ${source_files})
add_test(${test_executable} ${test_executable})
set_tests_properties(${test_executable}
PROPERTIES
- TIMEOUT 240)
+ TIMEOUT 600)
set_tests_properties(${test_executable}
PROPERTIES
SKIP_RETURN_CODE 127)
diff --git a/tests/test_docker.c b/tests/test_docker.c
index d60522f..b0cf381 100644
--- a/tests/test_docker.c
+++ b/tests/test_docker.c
@@ -41,7 +41,7 @@ void test_docker_build_and_script_and_save() {
if (!pushd("test_docker_build")) {
stasis_testing_write_ascii("Dockerfile", dockerfile_contents);
STASIS_ASSERT(docker_build(".", "-t test_docker_build", cap_suite.build) == 0, "docker build test failed");
- STASIS_ASSERT(docker_script("test_docker_build", "uname -a", 0) == 0, "simple docker container script execution failed");
+ STASIS_ASSERT(docker_script("test_docker_build", "--rm", "uname -a", 0) == 0, "simple docker container script execution failed");
STASIS_ASSERT(docker_save("test_docker_build", ".", STASIS_DOCKER_IMAGE_COMPRESSION) == 0, "saving a simple image failed");
STASIS_ASSERT(docker_exec("load < test_docker_build.tar.*", 0) == 0, "loading a simple image failed");
docker_exec("image rm -f test_docker_build", 0);
diff --git a/tests/test_strlist.c b/tests/test_strlist.c
index 47722c0..38343f4 100644
--- a/tests/test_strlist.c
+++ b/tests/test_strlist.c
@@ -200,6 +200,20 @@ void test_strlist_append_tokenize() {
guard_strlist_free(&list);
}
+void test_strlist_appendf() {
+ const char *fmt = "%c %s %d";
+ struct StrList *list;
+ list = strlist_init();
+ const int len = strlist_appendf(NULL, fmt, 'a', "abc", strlen(fmt));
+ STASIS_ASSERT(strlist_appendf(&list, fmt, 'a', "abc", strlen(fmt)) == len, "length of formatted string should be 7");
+ const char *item = strlist_item(list, 0);
+ STASIS_ASSERT(item != NULL, "valid pointer expected, item should not be NULL");
+ STASIS_ASSERT(strncmp(item, "a", 1) == 0, "first character should be 'a'");
+ STASIS_ASSERT(strncmp(item + 2, "abc", 3) == 0, "string should be 'abc'");
+ STASIS_ASSERT(strncmp(item + 6, "8", 1) == 0, "length of the raw format should be 8");
+ guard_strlist_free(&list);
+}
+
void test_strlist_copy() {
struct StrList *list = strlist_init();
struct StrList *list_copy;
@@ -628,6 +642,7 @@ void test_strlist_item_as_long_double() {
int main(int argc, char *argv[]) {
STASIS_TEST_BEGIN_MAIN();
STASIS_TEST_FUNC *tests[] = {
+ test_strlist_appendf,
test_strlist_init,
test_strlist_free,
test_strlist_append,
diff --git a/tests/test_utils.c b/tests/test_utils.c
index 0e2eb7b..cfe79e0 100644
--- a/tests/test_utils.c
+++ b/tests/test_utils.c
@@ -213,17 +213,21 @@ void test_git_clone_and_describe() {
// test git_describe is functional
char *taginfo_none = git_describe(".");
STASIS_ASSERT(taginfo_none != NULL, "should be a git hash, not NULL");
+ puts(taginfo_none);
+ STASIS_ASSERT(is_git_sha(taginfo_none) == true, "not a git hash");
system("git tag -a 1.0.0 -m Mock");
system("git push --tags origin");
- char *taginfo = git_describe(".");
+ const char *taginfo = git_describe(".");
+ puts(taginfo);
STASIS_ASSERT(taginfo != NULL, "should be 1.0.0, not NULL");
- STASIS_ASSERT(strcmp(taginfo, "1.0.0") == 0, "just-created tag was not described correctly");
+ STASIS_ASSERT(startswith(taginfo, "1.0.0") == true, "just-created tag was not described correctly");
chdir("..");
char *taginfo_outer = git_describe(repo);
+ puts(taginfo_outer);
STASIS_ASSERT(taginfo_outer != NULL, "should be 1.0.0, not NULL");
- STASIS_ASSERT(strcmp(taginfo_outer, "1.0.0") == 0, "just-created tag was not described correctly (out-of-dir invocation)");
+ STASIS_ASSERT(startswith(taginfo_outer, "1.0.0") == true, "just-created tag was not described correctly (out-of-dir invocation)");
char *taginfo_bad = git_describe("abc1234_not_here_or_there");
STASIS_ASSERT(taginfo_bad == NULL, "a repository that shouldn't exist... exists and has a tag.");
diff --git a/tests/test_wheel.c b/tests/test_wheel.c
index 6818b22..1eabb1b 100644
--- a/tests/test_wheel.c
+++ b/tests/test_wheel.c
@@ -1,91 +1,216 @@
+#include "delivery.h"
#include "testing.h"
+#include "str.h"
#include "wheel.h"
-void test_get_wheel_file() {
- struct testcase {
- const char *filename;
- struct Wheel expected;
- };
- struct testcase tc[] = {
- {
- // Test for "build tags"
- .filename = "btpackage-1.2.3-mytag-py2.py3-none-any.whl",
- .expected = {
- .file_name = "btpackage-1.2.3-mytag-py2.py3-none-any.whl",
- .version = "1.2.3",
- .distribution = "btpackage",
- .build_tag = "mytag",
- .platform_tag = "any",
- .python_tag = "py2.py3",
- .abi_tag = "none",
- .path_name = ".",
- }
- },
- {
- // Test for universal package format
- .filename = "anypackage-1.2.3-py2.py3-none-any.whl",
- .expected = {
- .file_name = "anypackage-1.2.3-py2.py3-none-any.whl",
- .version = "1.2.3",
- .distribution = "anypackage",
- .build_tag = NULL,
- .platform_tag = "any",
- .python_tag = "py2.py3",
- .abi_tag = "none",
- .path_name = ".",
- }
- },
- {
- // Test for binary package format
- .filename = "binpackage-1.2.3-cp311-cp311-linux_x86_64.whl",
- .expected = {
- .file_name = "binpackage-1.2.3-cp311-cp311-linux_x86_64.whl",
- .version = "1.2.3",
- .distribution = "binpackage",
- .build_tag = NULL,
- .platform_tag = "linux_x86_64",
- .python_tag = "cp311",
- .abi_tag = "cp311",
- .path_name = ".",
- }
- },
- };
+char cwd_start[PATH_MAX];
+char cwd_workspace[PATH_MAX];
+int conda_is_installed = 0;
+static char conda_prefix[PATH_MAX] = {0};
+struct Delivery ctx;
+static const char *testpkg_filename = "testpkg/dist/testpkg-1.0.0-py3-none-any.whl";
+
+
+static void test_wheel_package() {
+ const char *filename = testpkg_filename;
+ struct Wheel *wheel = NULL;
+ int state = wheel_package(&wheel, filename);
+ STASIS_ASSERT(state != WHEEL_PACKAGE_E_ALLOC, "Cannot fail to allocate memory for package structure");
+ STASIS_ASSERT(state != WHEEL_PACKAGE_E_GET, "Cannot fail to parse wheel");
+ STASIS_ASSERT(state != WHEEL_PACKAGE_E_GET_METADATA, "Cannot fail to read wheel metadata");
+ STASIS_ASSERT(state != WHEEL_PACKAGE_E_GET_RECORDS, "Cannot fail reading wheel path records");
+ STASIS_ASSERT(state != WHEEL_PACKAGE_E_GET_ENTRY_POINT, "Cannot fail reading wheel entry points");
+ STASIS_ASSERT(state == WHEEL_PACKAGE_E_SUCCESS, "Wheel file should be usable");
+ STASIS_ASSERT(wheel != NULL, "wheel cannot be NULL");
+ STASIS_ASSERT(wheel != NULL, "wheel_package failed to initialize wheel struct");
+ STASIS_ASSERT(wheel->record != NULL, "Record cannot be NULL");
+ STASIS_ASSERT(wheel->num_record > 0, "Record count cannot be zero");
+ STASIS_ASSERT(wheel->tag != NULL, "Package tag list cannot be NULL");
+ STASIS_ASSERT(wheel->generator != NULL, "Generator field cannot be NULL");
+ STASIS_ASSERT(wheel->top_level != NULL, "Top level directory name cannot be NULL");
+ STASIS_ASSERT(wheel->wheel_version != NULL, "Wheel version cannot be NULL");
+ STASIS_ASSERT(wheel->metadata != NULL, "Metadata cannot be NULL");
+ STASIS_ASSERT(wheel->metadata->name != NULL, "Metadata::name cannot be NULL");
+ STASIS_ASSERT(wheel->metadata->version != NULL, "Metadata::version cannot be NULL");
+ STASIS_ASSERT(wheel->metadata->metadata_version != NULL, "Metadata::version (of metadata) cannot be NULL");
+
+ // Implied test against key/id getters. If wheel_show_info segfaults, that functionality is broken.
+ STASIS_ASSERT(wheel_show_info(wheel) == 0, "wheel_show_info should never fail. Enum(s) might be out of sync with META_*_KEYS array(s)");
+
+ // Get data from DIST
+ const struct WheelValue dist_version = wheel_get_value_by_name(wheel, WHEEL_FROM_DIST, "Wheel-Version");
+ STASIS_ASSERT(dist_version.type == WHEELVAL_STR, "Wheel dist version value must be a string");
+ STASIS_ASSERT_FATAL(dist_version.data != NULL, "Wheel dist version value must not be NULL");
+ STASIS_ASSERT(dist_version.count, "Wheel value must be populated");
+
+ // Get data from METADATA
+ const struct WheelValue meta_name = wheel_get_value_by_name(wheel, WHEEL_FROM_METADATA, "Metadata-Version");
+ STASIS_ASSERT(meta_name.type == WHEELVAL_STR, "Wheel metadata version value must be a string");
+ STASIS_ASSERT_FATAL(meta_name.data != NULL, "Wheel metadata version value must not be NULL");
+ STASIS_ASSERT(meta_name.count, "Wheel metadata version value must be populated");
+
+ wheel_package_free(&wheel);
+ STASIS_ASSERT(wheel == NULL, "wheel struct should be NULL after free");
+}
+
+static void mock_python_package() {
+ const char *pyproject_toml_data = "[build-system]\n"
+ "requires = [\"setuptools >= 77.0.3\"]\n"
+ "build-backend = \"setuptools.build_meta\"\n"
+ "\n"
+ "[project]\n"
+ "name = \"testpkg\"\n"
+ "version = \"1.0.0\"\n"
+ "authors = [{name = \"STASIS Team\", email = \"stasis@not-a-real-domain.tld\"}]\n"
+ "description = \"A STASIS test package\"\n"
+ "readme = \"README.md\"\n"
+ "license = \"BSD-3-Clause\"\n"
+ "classifiers = [\"Programming Language :: Python :: 3\"]\n"
+ "\n"
+ "[project.urls]\n"
+ "Homepage = \"https://not-a-real-address.tld\"\n"
+ "Documentation = \"https://not-a-real-address.tld/docs\"\n"
+ "Repository = \"https://not-a-real-address.tld/repo.git\"\n"
+ "Issues = \"https://not-a-real-address.tld/tracker\"\n"
+ "Changelog = \"https://not-a-real-address.tld/changes\"\n";
+ const char *readme = "# testpkg\n\nThis is a test package, for testing.\n";
- 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_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");
- STASIS_ASSERT(wheel->distribution && strcmp(wheel->distribution, test->expected.distribution) == 0, "mismatched distribution (package name)");
- STASIS_ASSERT(wheel->platform_tag && strcmp(wheel->platform_tag, test->expected.platform_tag) == 0, "mismatched platform tag ([platform]_[architecture])");
- STASIS_ASSERT(wheel->python_tag && strcmp(wheel->python_tag, test->expected.python_tag) == 0, "mismatched python tag (python version)");
- STASIS_ASSERT(wheel->abi_tag && strcmp(wheel->abi_tag, test->expected.abi_tag) == 0, "mismatched abi tag (python compatibility version)");
- if (wheel->build_tag) {
- STASIS_ASSERT(strcmp(wheel->build_tag, test->expected.build_tag) == 0,
- "mismatched build tag (optional arbitrary string)");
- }
- wheel_free(&wheel);
+ mkdir("testpkg", 0755);
+ mkdir("testpkg/src", 0755);
+ mkdir("testpkg/src/testpkg", 0755);
+ if (touch("testpkg/src/testpkg/__init__.py")) {
+ fprintf(stderr, "unable to write __init__.py");
+ exit(1);
+ }
+ if (touch("testpkg/README.md")) {
+ fprintf(stderr, "unable to write README.md");
+ exit(1);
+ }
+ if (stasis_testing_write_ascii("testpkg/pyproject.toml", pyproject_toml_data)) {
+ perror("unable to write pyproject.toml");
+ exit(1);
+ }
+ if (stasis_testing_write_ascii("testpkg/README.md", readme)) {
+ perror("unable to write readme");
+ exit(1);
+ }
+ if (pip_exec("install build")) {
+ fprintf(stderr, "unable to install build tool using pip\n");
+ exit(1);
+ }
+ if (python_exec("-m build -w ./testpkg")) {
+ fprintf(stderr, "unable build test package");
+ exit(1);
}
}
int main(int argc, char *argv[]) {
STASIS_TEST_BEGIN_MAIN();
STASIS_TEST_FUNC *tests[] = {
- test_get_wheel_file,
+ test_wheel_package,
};
- // Create mock package directories, and files
- mkdir("binpackage", 0755);
- touch("binpackage/binpackage-1.2.3-cp311-cp311-linux_x86_64.whl");
- mkdir("anypackage", 0755);
- touch("anypackage/anypackage-1.2.3-py2.py3-none-any.whl");
- mkdir("btpackage", 0755);
- touch("btpackage/btpackage-1.2.3-mytag-py2.py3-none-any.whl");
+ char ws[] = "workspace_XXXXXX";
+ if (!mkdtemp(ws)) {
+ perror("mkdtemp");
+ exit(1);
+ }
+ getcwd(cwd_start, sizeof(cwd_start) - 1);
+ mkdir(ws, 0755);
+ chdir(ws);
+ getcwd(cwd_workspace, sizeof(cwd_workspace) - 1);
+
+ snprintf(conda_prefix, strlen(cwd_workspace) + strlen("conda") + 2, "%s/conda", cwd_workspace);
+
+ const char *mockinidata = "[meta]\n"
+ "name = mock\n"
+ "version = 1.0.0\n"
+ "rc = 1\n"
+ "mission = generic\n"
+ "python = 3.11\n"
+ "[conda]\n"
+ "installer_name = Miniforge3\n"
+ "installer_version = 24.3.0-0\n"
+ "installer_platform = {{env:STASIS_CONDA_PLATFORM}}\n"
+ "installer_arch = {{env:STASIS_CONDA_ARCH}}\n"
+ "installer_baseurl = https://github.com/conda-forge/miniforge/releases/download/24.3.0-0\n";
+ stasis_testing_write_ascii("mock.ini", mockinidata);
+ struct INIFILE *ini = ini_open("mock.ini");
+ ctx._stasis_ini_fp.delivery = ini;
+ ctx._stasis_ini_fp.delivery_path = realpath("mock.ini", NULL);
+
+ const char *sysconfdir = getenv("STASIS_SYSCONFDIR");
+ globals.sysconfdir = strdup(sysconfdir ? sysconfdir : STASIS_SYSCONFDIR);
+ ctx.storage.root = strdup(cwd_workspace);
+ char *cfgfile = join((char *[]) {globals.sysconfdir, "stasis.ini", NULL}, "/");
+ if (!cfgfile) {
+ perror("unable to create path to global config");
+ exit(1);
+ }
+
+ ctx._stasis_ini_fp.cfg = ini_open(cfgfile);
+ if (!ctx._stasis_ini_fp.cfg) {
+ fprintf(stderr, "unable to open config file, %s\n", cfgfile);
+ exit(1);
+ }
+ ctx._stasis_ini_fp.cfg_path = realpath(cfgfile, NULL);
+ if (!ctx._stasis_ini_fp.cfg_path) {
+ fprintf(stderr, "unable to determine absolute path of config, %s\n", cfgfile);
+ exit(1);
+ }
+ guard_free(cfgfile);
+
+ setenv("LANG", "C", 1);
+ if (bootstrap_build_info(&ctx)) {
+ fprintf(stderr, "bootstrap_build_info failed\n");
+ exit(1);
+ }
+ if (delivery_init(&ctx, INI_READ_RENDER)) {
+ fprintf(stderr, "delivery_init failed\n");
+ exit(1);
+ }
+
+ char *install_url = calloc(255, sizeof(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);
+ guard_free(install_url);
+
+ if (conda_activate(ctx.storage.conda_install_prefix, "base")) {
+ fprintf(stderr, "conda_activate failed\n");
+ exit(1);
+ }
+ if (conda_exec("install -y boa conda-build")) {
+ fprintf(stderr, "conda_exec failed\n");
+ exit(1);
+ }
+ if (conda_setup_headless()) {
+ fprintf(stderr, "conda_setup_headless failed\n");
+ exit(1);
+ }
+ if (conda_env_create("testpkg", ctx.meta.python, NULL)) {
+ fprintf(stderr, "conda_env_create failed\n");
+ exit(1);
+ }
+ if (conda_activate(ctx.storage.conda_install_prefix, "testpkg")) {
+ fprintf(stderr, "conda_activate failed\n");
+ exit(1);
+ }
+
+ mock_python_package();
STASIS_TEST_RUN(tests);
+
+ if (chdir(cwd_start) < 0) {
+ fprintf(stderr, "chdir failed\n");
+ exit(1);
+ }
+ if (rmtree(cwd_workspace)) {
+ perror(cwd_workspace);
+ }
+ delivery_free(&ctx);
+ globals_free();
+
STASIS_TEST_END_MAIN();
+
} \ No newline at end of file
diff --git a/tests/test_wheelinfo.c b/tests/test_wheelinfo.c
new file mode 100644
index 0000000..1abbeac
--- /dev/null
+++ b/tests/test_wheelinfo.c
@@ -0,0 +1,91 @@
+#include "testing.h"
+#include "wheelinfo.h"
+
+void test_wheelinfo_get() {
+ struct testcase {
+ const char *filename;
+ struct WheelInfo expected;
+ };
+ struct testcase tc[] = {
+ {
+ // Test for "build tags"
+ .filename = "btpackage-1.2.3-mytag-py2.py3-none-any.whl",
+ .expected = {
+ .file_name = "btpackage-1.2.3-mytag-py2.py3-none-any.whl",
+ .version = "1.2.3",
+ .distribution = "btpackage",
+ .build_tag = "mytag",
+ .platform_tag = "any",
+ .python_tag = "py2.py3",
+ .abi_tag = "none",
+ .path_name = ".",
+ }
+ },
+ {
+ // Test for universal package format
+ .filename = "anypackage-1.2.3-py2.py3-none-any.whl",
+ .expected = {
+ .file_name = "anypackage-1.2.3-py2.py3-none-any.whl",
+ .version = "1.2.3",
+ .distribution = "anypackage",
+ .build_tag = NULL,
+ .platform_tag = "any",
+ .python_tag = "py2.py3",
+ .abi_tag = "none",
+ .path_name = ".",
+ }
+ },
+ {
+ // Test for binary package format
+ .filename = "binpackage-1.2.3-cp311-cp311-linux_x86_64.whl",
+ .expected = {
+ .file_name = "binpackage-1.2.3-cp311-cp311-linux_x86_64.whl",
+ .version = "1.2.3",
+ .distribution = "binpackage",
+ .build_tag = NULL,
+ .platform_tag = "linux_x86_64",
+ .python_tag = "cp311",
+ .abi_tag = "cp311",
+ .path_name = ".",
+ }
+ },
+ };
+
+ struct WheelInfo *doesnotexist = wheelinfo_get("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 WheelInfo *wheel = wheelinfo_get(".", 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");
+ STASIS_ASSERT(wheel->distribution && strcmp(wheel->distribution, test->expected.distribution) == 0, "mismatched distribution (package name)");
+ STASIS_ASSERT(wheel->platform_tag && strcmp(wheel->platform_tag, test->expected.platform_tag) == 0, "mismatched platform tag ([platform]_[architecture])");
+ STASIS_ASSERT(wheel->python_tag && strcmp(wheel->python_tag, test->expected.python_tag) == 0, "mismatched python tag (python version)");
+ STASIS_ASSERT(wheel->abi_tag && strcmp(wheel->abi_tag, test->expected.abi_tag) == 0, "mismatched abi tag (python compatibility version)");
+ if (wheel->build_tag) {
+ STASIS_ASSERT(strcmp(wheel->build_tag, test->expected.build_tag) == 0,
+ "mismatched build tag (optional arbitrary string)");
+ }
+ wheelinfo_free(&wheel);
+ }
+}
+
+int main(int argc, char *argv[]) {
+ STASIS_TEST_BEGIN_MAIN();
+ STASIS_TEST_FUNC *tests[] = {
+ test_wheelinfo_get,
+ };
+
+ // Create mock package directories, and files
+ mkdir("binpackage", 0755);
+ touch("binpackage/binpackage-1.2.3-cp311-cp311-linux_x86_64.whl");
+ mkdir("anypackage", 0755);
+ touch("anypackage/anypackage-1.2.3-py2.py3-none-any.whl");
+ mkdir("btpackage", 0755);
+ touch("btpackage/btpackage-1.2.3-mytag-py2.py3-none-any.whl");
+
+ STASIS_TEST_RUN(tests);
+ STASIS_TEST_END_MAIN();
+} \ No newline at end of file