diff --git a/cmake/project.cmake b/cmake/project.cmake index 9a9d615..f013dcd 100644 --- a/cmake/project.cmake +++ b/cmake/project.cmake @@ -1,5 +1,5 @@ # SPDX-License-Identifier: MIT -set(SAMCONF_VERSION 0.75.4) +set(SAMCONF_VERSION 0.75.8) # Attention: Aside from the version, as many things as possible in this file # should be put into functions, as this solves potential issues with commands diff --git a/src/samconf/private/json_backend.c b/src/samconf/private/json_backend.c index b5af104..73df2d5 100644 --- a/src/samconf/private/json_backend.c +++ b/src/samconf/private/json_backend.c @@ -6,14 +6,24 @@ #include #include #include +#include +#include #include #include "samconf/config_backend.h" #include "samconf/samconf.h" +#include "samconf/samconf_types.h" samconfConfigStatusE_t samconfJsonBackendOpen(const char *location, samconfConfigBackend_t *backend) { json_object *root = NULL; + struct stat sb; + int s = stat(location, &sb); + if (s == -1 && errno == ENOENT) { + safuLogDebugF("%s does not exist", location); + return SAMCONF_CONFIG_NOT_FOUND; + } + root = json_object_from_file(location); if (!root) { diff --git a/src/samconf/private/samconf.c b/src/samconf/private/samconf.c index a52176e..31fd923 100644 --- a/src/samconf/private/samconf.c +++ b/src/samconf/private/samconf.c @@ -132,6 +132,7 @@ samconfConfigStatusE_t samconfLoad(const char *location, bool enforceSignature, } } else { safuLogErrF("Failed to lookup backend for %s.\n", location); + status = SAMCONF_CONFIG_NOT_FOUND; } } else { safuLogErrF("Failed to verify signature for %s.", location); @@ -234,25 +235,27 @@ static samconfConfigStatusE_t _extendWithDirectory(DIR *confDir, bool enforceSig static samconfConfigStatusE_t _extendWithLocation(const samconfConfigLocation_t *location, samconfConfig_t **const conf) { samconfConfigStatusE_t result = SAMCONF_CONFIG_NOT_FOUND; - DIR *confDir = opendir(location->path); - if (confDir != NULL) { - result = _extendWithDirectory(confDir, location->enforceSignature, location->path, conf); - if (result == SAMCONF_CONFIG_NOT_FOUND) { - safuLogWarnF("No config found in \"%s\"", location->path); - } else if (result == SAMCONF_CONFIG_OVERWRITE_NOT_ALLOWED) { - safuLogWarnF("merge rules don't allow anything in \"%s\" to be merged", location->path); - } else if (result != SAMCONF_CONFIG_OK) { - safuLogErrF("couldn't extend with \"%s\" (%d)", location->path, result); - } - closedir(confDir); - } else { - result = _extendWithSinglePath(location->path, location->enforceSignature, conf); - if (result == SAMCONF_CONFIG_NOT_FOUND) { - safuLogWarnF("no config could be found at \"%s\"", location->path); - } else if (result == SAMCONF_CONFIG_OVERWRITE_NOT_ALLOWED) { - safuLogWarnF("extending with \"%s\" not allowed by merge rules", location->path); - } else if (result != SAMCONF_CONFIG_OK) { - safuLogErrF("couldn't extend with \"%s\"", location->path); + if (location->path != NULL) { + DIR *confDir = opendir(location->path); + if (confDir != NULL) { + result = _extendWithDirectory(confDir, location->enforceSignature, location->path, conf); + if (result == SAMCONF_CONFIG_NOT_FOUND) { + safuLogWarnF("No config found in \"%s\"", location->path); + } else if (result == SAMCONF_CONFIG_OVERWRITE_NOT_ALLOWED) { + safuLogWarnF("merge rules don't allow anything in \"%s\" to be merged", location->path); + } else if (result != SAMCONF_CONFIG_OK) { + safuLogErrF("couldn't extend with \"%s\" (%d)", location->path, result); + } + closedir(confDir); + } else { + result = _extendWithSinglePath(location->path, location->enforceSignature, conf); + if (result == SAMCONF_CONFIG_NOT_FOUND) { + safuLogWarnF("no config could be found at \"%s\"", location->path); + } else if (result == SAMCONF_CONFIG_OVERWRITE_NOT_ALLOWED) { + safuLogWarnF("extending with \"%s\" not allowed by merge rules", location->path); + } else if (result != SAMCONF_CONFIG_OK) { + safuLogErrF("couldn't extend with \"%s\"", location->path); + } } } return result; @@ -285,9 +288,6 @@ samconfConfigStatusE_t samconfLoadAndMerge(const samconfConfigLocation_t locatio for (size_t i = 0; i < locationsSize; i++) { switch (locations[i].type) { case SAMCONF_CONFIG_LOCATION_TYPE_CONFIG: - if (locations[i].path == NULL) { - continue; - } tmpRes = samconfConfigMergeConfig(config, locations[i].config); break; case SAMCONF_CONFIG_LOCATION_TYPE_PATH: @@ -297,12 +297,11 @@ samconfConfigStatusE_t samconfLoadAndMerge(const samconfConfigLocation_t locatio safuLogWarn("not a valid config location"); continue; } - if (tmpRes == SAMCONF_CONFIG_OK) { + if (tmpRes == SAMCONF_CONFIG_INVALID_SIGNATURE || + (tmpRes == SAMCONF_CONFIG_ERROR && status != SAMCONF_CONFIG_INVALID_SIGNATURE)) { + status = tmpRes; + } else if (status == SAMCONF_CONFIG_NOT_FOUND && tmpRes == SAMCONF_CONFIG_OK) { status = SAMCONF_CONFIG_OK; - } else if (tmpRes == SAMCONF_CONFIG_OVERWRITE_NOT_ALLOWED && status == SAMCONF_CONFIG_OK) { - status = SAMCONF_CONFIG_OVERWRITE_NOT_ALLOWED; - } else { - safuLogWarnF("some error extending With location \"%s\"", locations[i].path); } } return status; diff --git a/src/samconf/public/samconf/samconf.h b/src/samconf/public/samconf/samconf.h index 74e0a51..e7cf938 100644 --- a/src/samconf/public/samconf/samconf.h +++ b/src/samconf/public/samconf/samconf.h @@ -18,22 +18,23 @@ samconfConfigStatusE_t samconfVerifySignature(const char *location); * * Returns: * SAMCONF_CONFIG_OK – on success. + * SAMCONF_CONFIG_NOT_FOUND - when path doesn't point to a configuration.. * SAMCONF_CONFIG_ERROR – on failure. ******************************************************************/ samconfConfigStatusE_t samconfLoad(const char *location, bool enforceSignature, samconfConfig_t **const config); /******************************************************************* - * Create a path to the config, upto the top most parent. + * Load all configs from multiple locations and merge them together * * Parameters: - * locations : a lisit of locations from where to assemble the configuration + * locations : a list of locations from where to assemble the configuration * locationsSize : the size of the locations list * config : the pointer in which to store the resulting config * * Returns: - * SAMCONF_CONFIG_OK – when at least one config could be loaded and merged successfully - * SAMCONF_CONFIG_OVERWRITE_NOT_ALLOWED - when the merge rules forbitt all the configs to be merged - * SAMCONF_CONFIG_NOT_FOUND - if none of the locations have any configs + * SAMCONF_CONFIG_OK – when nothing failed + * SAMCONF_CONFIG_INVALID_SIGNATURE - when at least one config has an invalid signature + * SAMCONF_CONFIG_NOT_FOUND - when no configuration was found. * SAMCONF_CONFIG_ERROR – on failure. ******************************************************************/ samconfConfigStatusE_t samconfLoadAndMerge(const samconfConfigLocation_t *locations, size_t locationsSize, diff --git a/test/utest/samconf/json_backend/samconfJsonBackendOpen/CMakeLists.txt b/test/utest/samconf/json_backend/samconfJsonBackendOpen/CMakeLists.txt index a3e15ad..f6a5873 100644 --- a/test/utest/samconf/json_backend/samconfJsonBackendOpen/CMakeLists.txt +++ b/test/utest/samconf/json_backend/samconfJsonBackendOpen/CMakeLists.txt @@ -8,7 +8,8 @@ create_unit_test( test_samconfJsonBackendOpen_utest SOURCES case_success_file.c - case_error_file.c + case_err_reading_file.c + case_err_file_not_found.c samconfJsonBackendOpen_utest.c LIBRARIES samconf_static diff --git a/test/utest/samconf/json_backend/samconfJsonBackendOpen/case_err_file_not_found.c b/test/utest/samconf/json_backend/samconfJsonBackendOpen/case_err_file_not_found.c new file mode 100644 index 0000000..4c7b7d6 --- /dev/null +++ b/test/utest/samconf/json_backend/samconfJsonBackendOpen/case_err_file_not_found.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT + +#include +#include +#include +#include + +#include "cmocka_mocks/mock_libc.h" +#include "samconf/samconf_types.h" +#include "samconfJsonBackendOpen_utest.h" + +int samconfTestSamconfJsonBackendOpenFileErrFileNotFoundSetup(UNUSED void **state) { + json_object *jobjDummy = malloc(sizeof(json_object *)); + *state = jobjDummy; + return 0; +} + +int samconfTestSamconfJsonBackendOpenFileErrFileNotFoundTeardown(UNUSED void **state) { + __real_free(*state); + return 0; +} + +void samconfTestSamconfJsonBackendOpenFileErrFileNotFound(UNUSED void **state) { + char path[] = "test.json"; + samconfConfigStatusE_t result = SAMCONF_CONFIG_ERROR; + samconfConfigBackend_t backend = { + .originalHandle = path, + .backendHandle = NULL, + }; + + TEST("samconfJsonBackendOpen with existing File input"); + SHOULD("%s", "return expected json_object inside struct"); + + MOCK_FUNC_AFTER_CALL(stat, 0); + expect_string(__wrap_stat, pathname, path); + expect_any(__wrap_stat, statbuf); + will_return_and_set_errno(__wrap_stat, -1, ENOENT); + + result = samconfJsonBackendOpen(path, &backend); + + assert_int_equal(result, SAMCONF_CONFIG_NOT_FOUND); + assert_string_equal(backend.originalHandle, path); +} diff --git a/test/utest/samconf/json_backend/samconfJsonBackendOpen/case_error_file.c b/test/utest/samconf/json_backend/samconfJsonBackendOpen/case_err_reading_file.c similarity index 65% rename from test/utest/samconf/json_backend/samconfJsonBackendOpen/case_error_file.c rename to test/utest/samconf/json_backend/samconfJsonBackendOpen/case_err_reading_file.c index 458c09e..b0cd938 100644 --- a/test/utest/samconf/json_backend/samconfJsonBackendOpen/case_error_file.c +++ b/test/utest/samconf/json_backend/samconfJsonBackendOpen/case_err_reading_file.c @@ -3,18 +3,20 @@ #include #include "cmocka_mocks/mock_jsonc.h" +#include "cmocka_mocks/mock_libc.h" #include "safu/mock_log.h" +#include "samconf/samconf_types.h" #include "samconfJsonBackendOpen_utest.h" -int samconfTestSamconfJsonBackendOpenFileErrorSetup(UNUSED void **state) { +int samconfTestSamconfJsonBackendOpenFileErrReadingFileSetup(UNUSED void **state) { return 0; } -int samconfTestSamconfJsonBackendOpenFileErrorTeardown(UNUSED void **state) { +int samconfTestSamconfJsonBackendOpenFileErrReadingFileTeardown(UNUSED void **state) { return 0; } -void samconfTestSamconfJsonBackendOpenFileError(UNUSED void **state) { +void samconfTestSamconfJsonBackendOpenFileErrReadingFile(UNUSED void **state) { samconfConfigStatusE_t result = SAMCONF_CONFIG_OK; char *path = "test.json"; @@ -26,6 +28,11 @@ void samconfTestSamconfJsonBackendOpenFileError(UNUSED void **state) { TEST("samconfJsonBackendOpen File Input with error"); SHOULD("%s", "Return Error Status and log error message"); + MOCK_FUNC_AFTER_CALL(stat, 0); + expect_string(__wrap_stat, pathname, path); + expect_any(__wrap_stat, statbuf); + will_return(__wrap_stat, 0); + MOCK_FUNC_AFTER_CALL(json_object_from_file, 0); expect_not_value(__wrap_json_object_from_file, filename, NULL); will_return(__wrap_json_object_from_file, NULL); diff --git a/test/utest/samconf/json_backend/samconfJsonBackendOpen/case_success_file.c b/test/utest/samconf/json_backend/samconfJsonBackendOpen/case_success_file.c index ab73bc6..bb5f2e2 100644 --- a/test/utest/samconf/json_backend/samconfJsonBackendOpen/case_success_file.c +++ b/test/utest/samconf/json_backend/samconfJsonBackendOpen/case_success_file.c @@ -25,9 +25,14 @@ void samconfTestSamconfJsonBackendOpenFileSuccess(UNUSED void **state) { .backendHandle = NULL, }; - TEST("samconfJsonBackendOpen with File input"); + TEST("samconfJsonBackendOpen with existing File input"); SHOULD("%s", "return expected json_object inside struct"); + MOCK_FUNC_AFTER_CALL(stat, 0); + expect_string(__wrap_stat, pathname, path); + expect_any(__wrap_stat, statbuf); + will_return(__wrap_stat, 0); + MOCK_FUNC_AFTER_CALL(json_object_from_file, 0); expect_string(__wrap_json_object_from_file, filename, path); will_return(__wrap_json_object_from_file, *state); diff --git a/test/utest/samconf/json_backend/samconfJsonBackendOpen/samconfJsonBackendOpen_utest.c b/test/utest/samconf/json_backend/samconfJsonBackendOpen/samconfJsonBackendOpen_utest.c index a02d2c7..2ca1e62 100644 --- a/test/utest/samconf/json_backend/samconfJsonBackendOpen/samconfJsonBackendOpen_utest.c +++ b/test/utest/samconf/json_backend/samconfJsonBackendOpen/samconfJsonBackendOpen_utest.c @@ -6,7 +6,8 @@ TEST_SUITE_FUNC_PROTOTYPES(samconfJsonBackendOpenUtest) int main() { const struct CMUnitTest tests[] = { TEST_CASE(samconfTestSamconfJsonBackendOpenFileSuccess), - TEST_CASE(samconfTestSamconfJsonBackendOpenFileError), + TEST_CASE(samconfTestSamconfJsonBackendOpenFileErrReadingFile), + TEST_CASE(samconfTestSamconfJsonBackendOpenFileErrFileNotFound), }; return RUN_TEST_SUITE(tests, samconfJsonBackendOpenUtest); diff --git a/test/utest/samconf/json_backend/samconfJsonBackendOpen/samconfJsonBackendOpen_utest.h b/test/utest/samconf/json_backend/samconfJsonBackendOpen/samconfJsonBackendOpen_utest.h index 1063623..ea21922 100644 --- a/test/utest/samconf/json_backend/samconfJsonBackendOpen/samconfJsonBackendOpen_utest.h +++ b/test/utest/samconf/json_backend/samconfJsonBackendOpen/samconfJsonBackendOpen_utest.h @@ -2,8 +2,11 @@ #ifndef SAMCONF_JSONBACKENDLOAD_UTEST_H #define SAMCONF_JSONBACKENDLOAD_UTEST_H +#include + #include "json_backend_utest.h" TEST_CASE_FUNC_PROTOTYPES(samconfTestSamconfJsonBackendOpenFileSuccess) -TEST_CASE_FUNC_PROTOTYPES(samconfTestSamconfJsonBackendOpenFileError) +TEST_CASE_FUNC_PROTOTYPES(samconfTestSamconfJsonBackendOpenFileErrReadingFile) +TEST_CASE_FUNC_PROTOTYPES(samconfTestSamconfJsonBackendOpenFileErrFileNotFound) #endif /* SAMCONF_JSONBACKENDLOAD_UTEST_H */ diff --git a/test/utest/samconf/samconf/samconfLoad/case_lookuperr.c b/test/utest/samconf/samconf/samconfLoad/case_lookuperr.c index 92c05ad..e1ef483 100644 --- a/test/utest/samconf/samconf/samconfLoad/case_lookuperr.c +++ b/test/utest/samconf/samconf/samconfLoad/case_lookuperr.c @@ -27,5 +27,5 @@ void samconfTestSamconfLoadLookupError(UNUSED void **state) { status = samconfLoad(location, false, &config); assert_ptr_equal(backend, (void *)0xdeadc0de); - assert_int_equal(status, SAMCONF_CONFIG_ERROR); + assert_int_equal(status, SAMCONF_CONFIG_NOT_FOUND); }