aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@users.noreply.github.com>2024-08-12 15:11:17 -0400
committerGitHub <noreply@github.com>2024-08-12 15:11:17 -0400
commit95672b2e7a6cc0c07306893d5bb0b80ee3570f7a (patch)
tree7167084154e521b1c82945d7e0405dbe524074ad
parentdd2768ddcd61172cc58311fa51138281144397ae (diff)
downloadstasis-95672b2e7a6cc0c07306893d5bb0b80ee3570f7a.tar.gz
More unit tests (and fixing bugs) (#23)
* Add test_artifactory.c to suite * Add test_ini_getval_wrapper to ini.c * basic ini_getval_TYPE() conversion checks * bugfix: use strtof in INIVAL_TYPE_FLOAT case * Include stdio.h to pull in FILE structure * bugfix: free data at index during strlist_set operation * Previous behavior of setting the pointer to NULL introduced a subtle memory leak * Set strlist error when index it out of range * Import private delivery functions required for mock context creation * Remove static declaration * populate_delivery_cfg() * Add test_junitxml.c * Fix duplicate define value for JUNIT_RESULT_STATE_ERROR * Add static junit test data * Copy test data to current test directory
-rw-r--r--include/ini.h1
-rw-r--r--include/junitxml.h2
-rw-r--r--src/delivery.c2
-rw-r--r--src/ini.c3
-rw-r--r--src/strlist.c3
-rw-r--r--tests/CMakeLists.txt2
-rw-r--r--tests/data/result.xml10
-rw-r--r--tests/data/result_error.xml24
-rw-r--r--tests/test_artifactory.c129
-rw-r--r--tests/test_ini.c99
-rw-r--r--tests/test_junitxml.c82
11 files changed, 352 insertions, 5 deletions
diff --git a/include/ini.h b/include/ini.h
index 2992a37..3d0565b 100644
--- a/include/ini.h
+++ b/include/ini.h
@@ -2,6 +2,7 @@
#ifndef STASIS_INI_H
#define STASIS_INI_H
+#include <stdio.h>
#include <stddef.h>
#include <stdbool.h>
diff --git a/include/junitxml.h b/include/junitxml.h
index 504b8e4..777ee27 100644
--- a/include/junitxml.h
+++ b/include/junitxml.h
@@ -6,7 +6,7 @@
#define JUNIT_RESULT_STATE_NONE 0
#define JUNIT_RESULT_STATE_FAILURE 1
#define JUNIT_RESULT_STATE_SKIPPED 2
-#define JUNIT_RESULT_STATE_ERROR 2
+#define JUNIT_RESULT_STATE_ERROR 3
/**
* Represents a failed test case
diff --git a/src/delivery.c b/src/delivery.c
index eaa2b06..2b5e781 100644
--- a/src/delivery.c
+++ b/src/delivery.c
@@ -607,7 +607,7 @@ static int populate_delivery_ini(struct Delivery *ctx, int render_mode) {
return 0;
}
-static int populate_delivery_cfg(struct Delivery *ctx, int render_mode) {
+int populate_delivery_cfg(struct Delivery *ctx, int render_mode) {
struct INIFILE *cfg = ctx->_stasis_ini_fp.cfg;
if (!cfg) {
return -1;
diff --git a/src/ini.c b/src/ini.c
index dfbd817..42891ef 100644
--- a/src/ini.c
+++ b/src/ini.c
@@ -170,7 +170,7 @@ int ini_getval(struct INIFILE *ini, char *section_name, char *key, int type, int
result->as_double = (double) strtod(data_copy, NULL);
break;
case INIVAL_TYPE_FLOAT:
- result->as_float = (float) strtod(data_copy, NULL);
+ result->as_float = strtof(data_copy, NULL);
break;
case INIVAL_TYPE_STR:
result->as_char_p = strdup(data_copy);
@@ -638,7 +638,6 @@ struct INIFILE *ini_open(const char *filename) {
}
if (isempty(value)) {
//printf("%s is probably long raw data\n", key);
- //ini_data_set_hint(&ini, current_section, key, INIVAL_TYPE_STR_ARRAY);
hint = INIVAL_TYPE_STR_ARRAY;
multiline_data = 1;
no_data = 1;
diff --git a/src/strlist.c b/src/strlist.c
index d1bb926..de76744 100644
--- a/src/strlist.c
+++ b/src/strlist.c
@@ -315,11 +315,12 @@ size_t strlist_count(struct StrList *pStrList) {
void strlist_set(struct StrList **pStrList, size_t index, char *value) {
char *tmp = NULL;
if (*pStrList == NULL || index > strlist_count(*pStrList)) {
+ strlist_errno = STRLIST_E_OUT_OF_RANGE;
return;
}
if (value == NULL) {
- (*pStrList)->data[index] = NULL;
+ guard_free((*pStrList)->data[index]);
} else {
tmp = realloc((*pStrList)->data[index], (strlen(value) + 1) * sizeof(char *));
if (!tmp) {
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index f06638e..62f58a9 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -10,6 +10,8 @@ set(nix_clang_cflags -Wno-unused-parameter -Wno-incompatible-pointer-types-disca
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 files "test_*.c")
if (BASH_PROGRAM)
diff --git a/tests/data/result.xml b/tests/data/result.xml
new file mode 100644
index 0000000..81df70f
--- /dev/null
+++ b/tests/data/result.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?><testsuites><testsuite name="pytest" errors="0" failures="2" skipped="1" tests="4" time="0.022" timestamp="2024-08-12T13:52:02.624944-04:00" hostname="examplehost"><testcase classname="test_simple" name="test_skip" time="0.000"><skipped type="pytest.skip" message="unconditional skip">/example/test_simple.py:4: unconditional skip</skipped></testcase><testcase classname="test_simple" name="test_fail" time="0.000"><failure message="assert False">def test_fail():
+ print("oh no, this test failed.", file=sys.stderr)
+&gt; assert False
+E assert False
+
+test_simple.py:10: AssertionError</failure></testcase><testcase classname="test_simple" name="test_success" time="0.000" /><testcase classname="test_simple" name="test_error" time="0.000"><failure message="RuntimeError: uh oh, a runtime error">def test_error():
+&gt; raise RuntimeError("uh oh, a runtime error")
+E RuntimeError: uh oh, a runtime error
+
+test_simple.py:17: RuntimeError</failure></testcase></testsuite></testsuites>
diff --git a/tests/data/result_error.xml b/tests/data/result_error.xml
new file mode 100644
index 0000000..cbb7a86
--- /dev/null
+++ b/tests/data/result_error.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?><testsuites><testsuite name="pytest" errors="1" failures="0" skipped="0" tests="1" time="0.077" timestamp="2024-08-12T13:58:07.030762-04:00" hostname="examplehost"><testcase classname="" name="test_simple" time="0.000"><error message="collection failure">/example/miniforge3/envs/test/lib/python3.11/site-packages/_pytest/python.py:493: in importtestmodule
+ mod = import_path(
+/example/miniforge3/envs/test/lib/python3.11/site-packages/_pytest/pathlib.py:582: in import_path
+ importlib.import_module(module_name)
+/example/miniforge3/envs/test/lib/python3.11/importlib/__init__.py:126: in import_module
+ return _bootstrap._gcd_import(name[level:], package, level)
+&lt;frozen importlib._bootstrap&gt;:1204: in _gcd_import
+ ???
+&lt;frozen importlib._bootstrap&gt;:1176: in _find_and_load
+ ???
+&lt;frozen importlib._bootstrap&gt;:1147: in _find_and_load_unlocked
+ ???
+&lt;frozen importlib._bootstrap&gt;:690: in _load_unlocked
+ ???
+/example/miniforge3/envs/test/lib/python3.11/site-packages/_pytest/assertion/rewrite.py:165: in exec_module
+ source_stat, co = _rewrite_test(fn, self.config)
+/example/miniforge3/envs/test/lib/python3.11/site-packages/_pytest/assertion/rewrite.py:345: in _rewrite_test
+ tree = ast.parse(source, filename=strfn)
+/example/miniforge3/envs/test/lib/python3.11/ast.py:50: in parse
+ return compile(source, filename, mode, flags,
+E File "/tmp/bleh/test_simple.py", line 17
+E syntax error here
+E ^^^^^
+E SyntaxError: invalid syntax</error></testcase></testsuite></testsuites>
diff --git a/tests/test_artifactory.c b/tests/test_artifactory.c
new file mode 100644
index 0000000..1a21f0e
--- /dev/null
+++ b/tests/test_artifactory.c
@@ -0,0 +1,129 @@
+#include "testing.h"
+
+// Import private functions from core
+extern int delivery_init_platform(struct Delivery *ctx);
+extern int populate_delivery_cfg(struct Delivery *ctx, int render_mode);
+
+struct JFRT_Auth gauth;
+struct JFRT_Auth gnoauth;
+struct Delivery ctx;
+const char *gbuild_name = "test_stasis_jf_build_collect_env";
+const char *gbuild_num = "1";
+
+// Delete a build
+// For now, I'm keeping these out of the core library.
+static int jfrog_cli_rt_build_delete(struct JFRT_Auth *auth, char *build_name, char *build_num) {
+ char cmd[STASIS_BUFSIZ];
+ memset(cmd, 0, sizeof(cmd));
+ snprintf(cmd, sizeof(cmd) - 1, "--build \"%s/%s\"", build_name, build_num);
+ return jfrog_cli(auth, "rt", "delete", cmd);
+}
+
+static int jfrog_cli_rt_delete(struct JFRT_Auth *auth, char *pattern) {
+ char cmd[STASIS_BUFSIZ];
+ memset(cmd, 0, sizeof(cmd));
+ snprintf(cmd, sizeof(cmd) - 1, "\"%s\"", pattern);
+ return jfrog_cli(auth, "rt", "delete", cmd);
+}
+
+void test_jfrog_cli_rt_ping() {
+ STASIS_ASSERT_FATAL(jfrog_cli_rt_ping(&gauth) == 0, "server ping failed.");
+ STASIS_ASSERT(jfrog_cli_rt_ping(&gnoauth) != 0, "server ping should have failed; auth context is empty.");
+}
+
+void test_jfrog_cli_rt_build_collect_publish() {
+ struct JFRT_Upload upload;
+ jfrt_upload_init(&upload);
+
+ char *filename = "empty_file.txt";
+ touch(filename);
+ upload.build_name = gbuild_name;
+ upload.build_number = gbuild_num;
+ STASIS_ASSERT(jfrog_cli_rt_upload(&gauth, &upload, filename, getenv("STASIS_JF_REPO")) == 0, "jf upload failed");
+ STASIS_ASSERT(jfrog_cli_rt_build_collect_env(&gauth, gbuild_name, gbuild_num) == 0, "jf environment collection failed");
+ STASIS_ASSERT(jfrog_cli_rt_build_publish(&gauth, gbuild_name, gbuild_num) == 0, "jf publish build failed");
+ STASIS_ASSERT(jfrog_cli_rt_build_delete(&gauth, gbuild_name, gbuild_num) == 0, "jf delete build failed");
+}
+
+void test_jfrog_cli_rt_upload() {
+ struct JFRT_Upload upload;
+ jfrt_upload_init(&upload);
+
+ char *filename = "empty_file_upload.txt";
+ touch(filename);
+ STASIS_ASSERT(jfrog_cli_rt_upload(&gauth, &upload, filename, getenv("STASIS_JF_REPO")) == 0, "jf upload failed");
+}
+
+void test_jfrog_cli_rt_download() {
+ struct JFRT_Download dl;
+ memset(&dl, 0, sizeof(dl));
+
+ char *filename = "empty_file_upload.txt";
+ char path[PATH_MAX] = {0};
+ sprintf(path, "%s/%s", getenv("STASIS_JF_REPO"), filename);
+ STASIS_ASSERT(jfrog_cli_rt_download(&gauth, &dl, filename, ".") == 0, "jf download failed");
+ STASIS_ASSERT(jfrog_cli_rt_delete(&gauth, path) == 0, "jf delete test artifact failed");
+}
+
+int main(int argc, char *argv[]) {
+ STASIS_TEST_BEGIN_MAIN();
+ memset(&gauth, 0, sizeof(gauth));
+ memset(&gnoauth, 0, sizeof(gnoauth));
+ memset(&ctx, 0, sizeof(ctx));
+
+ const char *basedir = realpath(".", NULL);
+ const char *ws = "workspace";
+ mkdir(ws, 0755);
+ if (pushd(ws)) {
+ SYSERROR("failed to change directory to %s", ws);
+ STASIS_ASSERT_FATAL(true, "workspace creation failed");
+ }
+
+ // enable messages from the jf tool
+ globals.verbose = true;
+
+ // create a limited delivery context
+ path_store(&ctx.storage.tools_dir, PATH_MAX, ".", "tools");
+ path_store(&ctx.storage.build_dir, PATH_MAX, ".", "build");
+ path_store(&ctx.storage.tmpdir, PATH_MAX, ".", "tmp");
+ const char *sysconfdir = getenv("STASIS_SYSCONFDIR");
+ if (!sysconfdir) {
+ sysconfdir = STASIS_SYSCONFDIR;
+ }
+
+ char path[PATH_MAX] = {0};
+ sprintf(path, "%s/bin:%s", ctx.storage.tools_dir, getenv("PATH"));
+ setenv("PATH", path, 1);
+
+ // The default config contains the URL information to download jfrog-cli
+ char cfg_path[PATH_MAX] = {0};
+ if (strstr(sysconfdir, "..")) {
+ sprintf(cfg_path, "%s/%s/stasis.ini", basedir, sysconfdir);
+ } else {
+ sprintf(cfg_path, "%s/stasis.ini", sysconfdir);
+ }
+ ctx._stasis_ini_fp.cfg = ini_open(cfg_path);
+ if (!ctx._stasis_ini_fp.cfg) {
+ SYSERROR("%s: configuration is invalid", cfg_path);
+ return STASIS_TEST_SUITE_SKIP;
+ }
+ delivery_init_platform(&ctx);
+ populate_delivery_cfg(&ctx, INI_READ_RENDER);
+ delivery_init_artifactory(&ctx);
+
+ // Skip this suite if we're not configured to use it
+ if (jfrt_auth_init(&gauth)) {
+ SYSERROR("%s", "Not configured to test Artifactory. Skipping.");
+ return STASIS_TEST_SUITE_SKIP;
+ }
+
+ STASIS_TEST_FUNC *tests[] = {
+ test_jfrog_cli_rt_ping,
+ test_jfrog_cli_rt_build_collect_publish,
+ test_jfrog_cli_rt_upload,
+ test_jfrog_cli_rt_download,
+ };
+ STASIS_TEST_RUN(tests);
+ popd();
+ STASIS_TEST_END_MAIN();
+} \ No newline at end of file
diff --git a/tests/test_ini.c b/tests/test_ini.c
index 7fb13a0..2579e21 100644
--- a/tests/test_ini.c
+++ b/tests/test_ini.c
@@ -95,6 +95,104 @@ void test_ini_setval_getval() {
remove(filename);
}
+void test_ini_getval_wrappers() {
+ int render_mode = INI_READ_RENDER;
+ const char *filename = "ini_open.ini";
+ const char *data = "[default]\n"
+ "char_01a=-1\n"
+ "char_01b=127\n"
+ "uchar_01a=0\n"
+ "uchar_01b=255\n"
+ "short_01a=-1\n"
+ "short_01b=1\n"
+ "ushort_01a=0\n"
+ "ushort_01b=1\n"
+ "int_01a=-1\n"
+ "int_01b=1\n"
+ "uint_01a=0\n"
+ "uint_01b=1\n"
+ "long_01a=-1\n"
+ "long_01b=1\n"
+ "ulong_01a=0\n"
+ "ulong_01b=1\n"
+ "llong_01a=-1\n"
+ "llong_01b=1\n"
+ "ullong_01a=0\n"
+ "ullong_01b=1\n"
+ "float_01a=-1.5\n"
+ "float_01b=1.5\n"
+ "double_01a=-1.5\n"
+ "double_01b=1.5\n";
+ struct INIFILE *ini = NULL;
+ int err = 0;
+
+ stasis_testing_write_ascii(filename, data);
+ ini = ini_open(filename);
+ STASIS_ASSERT_FATAL(ini != NULL, "could not open test data");
+
+ STASIS_ASSERT(ini_getval_char(ini, "default", "char_01a", render_mode, &err) == -1, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: char");
+ STASIS_ASSERT(ini_getval_char(ini, "default", "char_01b", render_mode, &err) == 127, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: char");
+
+ STASIS_ASSERT(ini_getval_uchar(ini, "default", "uchar_01a", render_mode, &err) == 0, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: uchar");
+ STASIS_ASSERT(ini_getval_uchar(ini, "default", "uchar_01b", render_mode, &err) == 255, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: uchar");
+
+ STASIS_ASSERT(ini_getval_short(ini, "default", "short_01a", render_mode, &err) == -1, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: short");
+ STASIS_ASSERT(ini_getval_short(ini, "default", "short_01b", render_mode, &err) == 1, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: short");
+
+ STASIS_ASSERT(ini_getval_ushort(ini, "default", "ushort_01a", render_mode, &err) == 0, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: ushort");
+ STASIS_ASSERT(ini_getval_ushort(ini, "default", "ushort_01b", render_mode, &err) == 1, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: ushort");
+
+ STASIS_ASSERT(ini_getval_int(ini, "default", "int_01a", render_mode, &err) == -1, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: int");
+ STASIS_ASSERT(ini_getval_int(ini, "default", "int_01b", render_mode, &err) == 1, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: int");
+
+ STASIS_ASSERT(ini_getval_uint(ini, "default", "uint_01a", render_mode, &err) == 0, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: uint");
+ STASIS_ASSERT(ini_getval_uint(ini, "default", "uint_01b", render_mode, &err) == 1, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: uint");
+
+ STASIS_ASSERT(ini_getval_long(ini, "default", "long_01a", render_mode, &err) == -1, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: long");
+ STASIS_ASSERT(ini_getval_long(ini, "default", "long_01b", render_mode, &err) == 1, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: long");
+
+ STASIS_ASSERT(ini_getval_ulong(ini, "default", "ulong_01a", render_mode, &err) == 0, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: ulong");
+ STASIS_ASSERT(ini_getval_ulong(ini, "default", "ulong_01b", render_mode, &err) == 1, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: ulong");
+
+ STASIS_ASSERT(ini_getval_llong(ini, "default", "llong_01a", render_mode, &err) == -1, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: llong");
+ STASIS_ASSERT(ini_getval_llong(ini, "default", "llong_01b", render_mode, &err) == 1, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: llong");
+
+ STASIS_ASSERT(ini_getval_ullong(ini, "default", "ullong_01a", render_mode, &err) == 0, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: ullong");
+ STASIS_ASSERT(ini_getval_ullong(ini, "default", "ullong_01b", render_mode, &err) == 1, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: ullong");
+
+ STASIS_ASSERT(ini_getval_float(ini, "default", "float_01a", render_mode, &err) == -1.5F, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: float");
+ STASIS_ASSERT(ini_getval_float(ini, "default", "float_01b", render_mode, &err) == 1.5F, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: float");
+
+ STASIS_ASSERT(ini_getval_double(ini, "default", "double_01a", render_mode, &err) == -1.5L, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: double");
+ STASIS_ASSERT(ini_getval_double(ini, "default", "double_01b", render_mode, &err) == 1.5L, "returned unexpected value");
+ STASIS_ASSERT(err == 0, "failed to convert type: double");
+
+ ini_free(&ini);
+}
+
int main(int argc, char *argv[]) {
STASIS_TEST_BEGIN_MAIN();
STASIS_TEST_FUNC *tests[] = {
@@ -103,6 +201,7 @@ int main(int argc, char *argv[]) {
test_ini_section_search,
test_ini_has_key,
test_ini_setval_getval,
+ test_ini_getval_wrappers,
};
STASIS_TEST_RUN(tests);
STASIS_TEST_END_MAIN();
diff --git a/tests/test_junitxml.c b/tests/test_junitxml.c
new file mode 100644
index 0000000..9b2181e
--- /dev/null
+++ b/tests/test_junitxml.c
@@ -0,0 +1,82 @@
+#include "testing.h"
+
+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(testsuite->name != NULL, "Test suite must be named");
+ STASIS_ASSERT(testsuite->skipped > 0, "missed skipped tests");
+ STASIS_ASSERT(testsuite->failures > 0, "missed failed tests");
+ STASIS_ASSERT(testsuite->errors == 0, "should not have errored tests");
+ STASIS_ASSERT(testsuite->tests > 0, "missed tests");
+
+ for (size_t i = 0; i < testsuite->_tc_inuse; i++) {
+ struct JUNIT_Testcase *testcase = testsuite->testcase[i];
+ STASIS_ASSERT_FATAL(testcase->name != NULL, "test case should not be NULL");
+ STASIS_ASSERT(testcase->name != NULL, "name should not be NULL");
+ STASIS_ASSERT(testcase->classname != NULL, "classname should not be NULL");
+
+ switch (testcase->tc_result_state_type) {
+ case JUNIT_RESULT_STATE_SKIPPED:
+ STASIS_ASSERT(testcase->result_state.skipped != NULL, "skipped state set, but data pointer was null");
+ STASIS_ASSERT(testcase->result_state.skipped->message != NULL, "data pointer set, but message pointer was null");
+ break;
+ case JUNIT_RESULT_STATE_FAILURE:
+ STASIS_ASSERT(testcase->result_state.failure != NULL, "failure state set, but data pointer was null");
+ STASIS_ASSERT(testcase->result_state.failure->message != NULL, "data pointer set, but message pointer was null");
+ break;
+ case JUNIT_RESULT_STATE_ERROR:
+ STASIS_ASSERT(testcase->result_state.error != NULL, "error state set, but data pointer was null");
+ STASIS_ASSERT(testcase->result_state.error->message != NULL, "data pointer set, but message pointer was null");
+ break;
+ case JUNIT_RESULT_STATE_NONE:
+ STASIS_ASSERT(testcase->result_state.failure == NULL, "success, but has an failure record");
+ STASIS_ASSERT(testcase->result_state.skipped == NULL, "success, but has a skipped record ");
+ STASIS_ASSERT(testcase->result_state.error == NULL, "success, but has an error record");
+ break;
+ default:
+ SYSERROR("unknown test case result type (%d)", testcase->tc_result_state_type);
+ break;
+ }
+ }
+ junitxml_testsuite_free(&testsuite);
+}
+
+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(testsuite->name != NULL, "test suite must be named");
+ STASIS_ASSERT(testsuite->skipped == 0, "should not have any skipped tests");
+ STASIS_ASSERT(testsuite->failures == 0, "should not have any failures, only errors");
+ STASIS_ASSERT(testsuite->errors > 0, "missed failed tests");
+ STASIS_ASSERT(testsuite->tests > 0, "missed tests");
+ STASIS_ASSERT(testsuite->timestamp != NULL, "Test suite must have a timestamp");
+
+ for (size_t i = 0; i < testsuite->_tc_inuse; i++) {
+ struct JUNIT_Testcase *testcase = testsuite->testcase[i];
+ STASIS_ASSERT_FATAL(testcase->name != NULL, "test case should not be NULL");
+ STASIS_ASSERT(testcase->name != NULL, "name should not be NULL");
+ STASIS_ASSERT(testcase->classname != NULL, "classname should not be NULL");
+
+ switch (testcase->tc_result_state_type) {
+ case JUNIT_RESULT_STATE_ERROR:
+ STASIS_ASSERT(testcase->result_state.error != NULL, "error state set, but data pointer was null");
+ STASIS_ASSERT(testcase->result_state.error->message != NULL, "data pointer set, but message pointer was null");
+ break;
+ default:
+ SYSERROR("unexpected test case result type (%d)", testcase->tc_result_state_type);
+ break;
+ }
+ }
+ junitxml_testsuite_free(&testsuite);
+}
+
+int main(int argc, char *argv[]) {
+ STASIS_TEST_BEGIN_MAIN();
+ STASIS_TEST_FUNC *tests[] = {
+ test_junitxml_testsuite_read,
+ test_junitxml_testsuite_read_error,
+ };
+ STASIS_TEST_RUN(tests);
+ STASIS_TEST_END_MAIN();
+} \ No newline at end of file