diff --git a/src/cmake/modules/FindMaven.cmake b/src/cmake/modules/FindMaven.cmake index 5a2e3c3..02d2dbd 100644 --- a/src/cmake/modules/FindMaven.cmake +++ b/src/cmake/modules/FindMaven.cmake @@ -18,8 +18,13 @@ if(DEFINED ENV{M2_HOME}) endif() # Chocolatey installs packages under C:\ProgramData\chocolatey. -if(ENV{ProgramData} AND IS_DIRECTORY "$ENV{ProgramData}/chocolatey/bin") - list(APPEND _mvn_paths "$ENV{ProgramData}/chocolatey/bin") +if(NOT "$ENV{ProgramData}" STREQUAL "") + if(IS_DIRECTORY "$ENV{ProgramData}/chocolatey/bin") + list(APPEND _mvn_paths "$ENV{ProgramData}/chocolatey/bin") + endif() + if(IS_DIRECTORY "$ENV{ProgramData}/chocolatey/bin") + list(APPEND _dirs "$ENV{ProgramData}/chocolatey/lib/maven") + endif() endif() # Maven documentation mentions intalling maven under C:\Program Files on diff --git a/src/ddsrt/CMakeLists.txt b/src/ddsrt/CMakeLists.txt index cda6f18..2b5171a 100644 --- a/src/ddsrt/CMakeLists.txt +++ b/src/ddsrt/CMakeLists.txt @@ -66,6 +66,7 @@ list(APPEND headers "${include_path}/dds/ddsrt/misc.h" "${include_path}/dds/ddsrt/io.h" "${include_path}/dds/ddsrt/process.h" + "${include_path}/dds/ddsrt/dynlib.h" "${include_path}/dds/ddsrt/strtod.h" "${include_path}/dds/ddsrt/strtol.h" "${include_path}/dds/ddsrt/types.h") @@ -102,7 +103,7 @@ list(APPEND sources # network stack. In order to mix-and-match various compilers, architectures, # operating systems, etc input from the build system is required. foreach(feature atomics cdtors environ heap ifaddrs random rusage - sockets string sync threads time md5 process) + sockets string sync threads time md5 process dynlib) if(EXISTS "${include_path}/dds/ddsrt/${feature}.h") list(APPEND headers "${include_path}/dds/ddsrt/${feature}.h") file(GLOB @@ -176,6 +177,7 @@ target_sources(ddsrt INTERFACE ${sources}) set(CMAKE_THREAD_PREFER_PTHREAD TRUE) find_package(Threads REQUIRED) target_link_libraries(ddsrt INTERFACE Threads::Threads) +target_link_libraries(ddsrt INTERFACE ${CMAKE_DL_LIBS}) if(WIN32) target_link_libraries(ddsrt INTERFACE wsock32 ws2_32 iphlpapi bcrypt) diff --git a/src/ddsrt/include/dds/ddsrt/dynlib.h b/src/ddsrt/include/dds/ddsrt/dynlib.h new file mode 100644 index 0000000..1f9270e --- /dev/null +++ b/src/ddsrt/include/dds/ddsrt/dynlib.h @@ -0,0 +1,143 @@ + +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef DDSRT_LIBRARY_H +#define DDSRT_LIBRARY_H + +#include "dds/export.h" +#include "dds/ddsrt/types.h" +#include "dds/ddsrt/retcode.h" +#include "dds/ddsrt/attributes.h" + +#if defined (__cplusplus) +extern "C" { +#endif + + +//typedef void *ddsrt_dynlib_t; +typedef struct ddsrt_dynlib *ddsrt_dynlib_t; + + +/** + * @brief Load a dynamic shared library. + * + * The function ddsrt_dlopen() loads the dynamic shared object (shared library) + * file, identified by 'name', sets the handle parameter for the loaded library and + * returns the result with dds return code. + * + * If the 'translate' boolean is true, this function will first try to open the + * library with a translated 'name'. Translated in this context means that if + * "mylibrary" is provided, it will be translated into libmylibrary.so, + * libmylibrary.dylib or mylibrary.dll depending on the platform. + * This translation only happens when the given name does not contain + * a directory. + * If the function isn't able to load the library with the translated name, it + * will still try the given name. + * + * @param[in] name Library file name. + * @param[in] translate Automatic name translation on/off. + * @param[out] handle Library handle that will be assigned after successfull operation. It is assigned to NULL if loading fails. + * + * @returns A dds_retcode_t indicating success or failure. + * + * @retval DDS_RETCODE_OK + * Library handle was successfully loaded. + * @retval DDS_RETCODE_BAD_PARAM + * There is an invalid input in the parameter list + * @retval DDS_RETCODE_ERROR + * Loading failed. + * Use ddsrt_dlerror() to diagnose the failure. + */ +DDS_EXPORT dds_retcode_t +ddsrt_dlopen( + const char *name, + bool translate, + ddsrt_dynlib_t *handle) ddsrt_nonnull_all; + +/** + * @brief Close the library. + * + * The function ddsrt_dlclose() informs the system that the + * library, identified by 'handle', is no longer needed. + * will get the memory address of a symbol, + * identified by 'symbol', from a loaded library 'handle'. + * + * @param[in] handle Library handle. + * + * @returns A dds_retcode_t indicating success or failure. + * + * @retval DDS_RETCODE_OK + * Library handle was successfully closed. + * @retval DDS_RETCODE_ERROR + * Library closing failed. + * Use ddsrt_dlerror() to diagnose the failure. + */ +DDS_EXPORT dds_retcode_t +ddsrt_dlclose( + ddsrt_dynlib_t handle); + +/** + * @brief Get the memory address of a symbol. + * + * The function ddsrt_dlsym() will get the memory address of a symbol, + * identified by 'symbol', from a loaded library 'handle'. + * + * @param[in] handle Library handle. + * @param[in] symbol Symbol name. + * @param[out] address The memory address of the loaded symbol (void*). + * + * @returns A dds_retcode_t indicating success or failure. + * + * @retval DDS_RETCODE_OK + * Symbol was found in the loaded library. + * Address parameter is ready to use. + * @retval DDS_RETCODE_ERROR + * Symbol was not found. + * Use ddsrt_dlerror() to diagnose the failure. + */ +DDS_EXPORT dds_retcode_t +ddsrt_dlsym( + ddsrt_dynlib_t handle, + const char *symbol, + void **address); + +/** + * @brief Get the most recent library related error. + * + * The function ddsrt_dlerror() will return the most recent error of the operating system + * in human readable form. + * + * If no error was found, it's either due to the fact that there + * actually was no error since init or last ddsrt_dlerror() call, + * or due to an unknown unrelated error. + * + * As error reporting function can be used for different purposes, dssrt_dlerror + * function should be called immediately after calling ddsrt_dlopen or ddsrt_dlsym + * function. + * + * @returns A dds_retcode_t indicating success or failure. + * + * @retval DDS_RETCODE_OK + * Most recent library related error returned. + * @retval DDS_RETCODE_NOT_FOUND + * No library related error found. + */ +DDS_EXPORT dds_retcode_t +ddsrt_dlerror( + char *buf, + size_t buflen); + +#if defined (__cplusplus) +} +#endif + +#endif /* DDSRT_LIBRARY_H */ diff --git a/src/ddsrt/src/dynlib/posix/dynlib.c b/src/ddsrt/src/dynlib/posix/dynlib.c new file mode 100644 index 0000000..cb538d8 --- /dev/null +++ b/src/ddsrt/src/dynlib/posix/dynlib.c @@ -0,0 +1,95 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/io.h" + +dds_retcode_t ddsrt_dlopen(const char *name, bool translate, + ddsrt_dynlib_t *handle) { + dds_retcode_t retcode = DDS_RETCODE_OK; + + assert( handle ); + *handle = NULL; + + if ((translate) && (strrchr(name, '/') == NULL )) { + /* Add lib and suffix to the name and try to open. */ +#if __APPLE__ + static const char suffix[] = ".dylib"; +#else + static const char suffix[] = ".so"; +#endif + char* libName; + ddsrt_asprintf( &libName, "lib%s%s", name, suffix); + *handle = dlopen(libName, RTLD_GLOBAL | RTLD_NOW); + ddsrt_free(libName); + } + + if (*handle == NULL ) { + /* name contains a path, + * (auto)translate is disabled or + * dlopen on translated name failed. */ + *handle = dlopen(name, RTLD_GLOBAL | RTLD_NOW); + } + + if (*handle != NULL) { + retcode = DDS_RETCODE_OK; + } else { + retcode = DDS_RETCODE_ERROR; + } + + return retcode; +} + +dds_retcode_t ddsrt_dlclose(ddsrt_dynlib_t handle) { + + assert ( handle ); + return (dlclose(handle) == 0) ? DDS_RETCODE_OK : DDS_RETCODE_ERROR; + +} + +dds_retcode_t ddsrt_dlsym(ddsrt_dynlib_t handle, const char *symbol, + void **address) { + dds_retcode_t retcode = DDS_RETCODE_OK; + + assert( handle ); + assert( address ); + assert( symbol ); + + *address = dlsym(handle, symbol); + if (*address == NULL) { + retcode = DDS_RETCODE_ERROR; + } + + return retcode; +} + +dds_retcode_t ddsrt_dlerror(char *buf, size_t buflen) { + + const char *err; + dds_retcode_t retcode = DDS_RETCODE_OK; + + assert (buf ); + + err = dlerror(); + if (err == NULL) { + retcode = DDS_RETCODE_NOT_FOUND; + } else { + snprintf(buf, buflen, "%s", err); + } + + return retcode; +} + diff --git a/src/ddsrt/src/dynlib/windows/dynlib.c b/src/ddsrt/src/dynlib/windows/dynlib.c new file mode 100644 index 0000000..38e1688 --- /dev/null +++ b/src/ddsrt/src/dynlib/windows/dynlib.c @@ -0,0 +1,95 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/types.h" +#include "dds/ddsrt/string.h" + +dds_retcode_t ddsrt_dlopen(const char *name, bool translate, + ddsrt_dynlib_t *handle) { + dds_retcode_t retcode = DDS_RETCODE_OK; + + assert( handle ); + *handle = NULL; + + if ((translate) && (strrchr(name, '/') == NULL ) + && (strrchr(name, '\\') == NULL )) { + /* Add suffix to the name and try to open. */ + static const char suffix[] = ".dll"; + size_t len = strlen(name) + sizeof(suffix); + char* libName = ddsrt_malloc(len); + sprintf_s(libName, len, "%s%s", name, suffix); + *handle = LoadLibrary(libName); + ddsrt_free(libName); + } + + if (*handle == NULL) { + /* Name contains a path, + * (auto)translate is disabled or + * LoadLibrary on translated name failed. */ + *handle = LoadLibrary(name); + } + + if (*handle != NULL) { + retcode = DDS_RETCODE_OK; + } else { + retcode = DDS_RETCODE_ERROR; + } + + return retcode; +} + +dds_retcode_t ddsrt_dlclose(ddsrt_dynlib_t handle) { + + assert ( handle ); + return (FreeLibrary(handle) == 0) ? DDS_RETCODE_ERROR : DDS_RETCODE_OK; +} + +dds_retcode_t ddsrt_dlsym(ddsrt_dynlib_t handle, const char *symbol, + void **address) { + dds_retcode_t retcode = DDS_RETCODE_OK; + + assert( handle ); + assert( address ); + assert( symbol ); + + *address = GetProcAddress(handle, symbol); + if ( *address == NULL ) { + retcode = DDS_RETCODE_ERROR; + } + + return retcode; +} + +dds_retcode_t ddsrt_dlerror(char *buf, size_t buflen) { + + /* Hopefully (and likely), the last error is + * related to a Library action attempt. */ + DWORD err; + assert ( buf ); + + dds_retcode_t retcode = DDS_RETCODE_OK; + + err = GetLastError(); + if ( err == 0 ) { + retcode = DDS_RETCODE_NOT_FOUND; + } else { + retcode = ddsrt_strerror_r(err, buf, buflen); + } + + return retcode; + +} + diff --git a/src/ddsrt/tests/CMakeLists.txt b/src/ddsrt/tests/CMakeLists.txt index 02c92ef..db27665 100644 --- a/src/ddsrt/tests/CMakeLists.txt +++ b/src/ddsrt/tests/CMakeLists.txt @@ -10,9 +10,11 @@ # SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause # include(CUnit) +include(GenerateExportHeader) set(sources "atomics.c" + "dynlib.c" "environ.c" "heap.c" "ifaddrs.c" @@ -66,3 +68,47 @@ set(process_app_name "${CMAKE_CURRENT_BINARY_DIR}/process_app${CMAKE_EXECUTABLE_ configure_file( "process_test.h.in" "${CMAKE_CURRENT_BINARY_DIR}/include/process_test.h" @ONLY) + + +# Create a separate shared library that will be used to +# test dynamic library loading. +set(test_lib_name "dltestlib") +add_library(${test_lib_name} SHARED dllib.c) +# Force the lib to be at the same location, no matter what platform or build type. +set_target_properties( + ${test_lib_name} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_BINARY_DIR} + RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_BINARY_DIR} + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_BINARY_DIR} + LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_BINARY_DIR} + LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_CURRENT_BINARY_DIR} + LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_CURRENT_BINARY_DIR} ) +# Use proper export for this test lib. +generate_export_header(${test_lib_name} BASE_NAME LIB_TEST) +target_include_directories(${test_lib_name} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") +# Let the cunit application know the location and name of the library. +file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}" test_lib_native_dir) +file(TO_NATIVE_PATH "/" test_lib_sep) +string(REPLACE "\\" "\\\\" test_lib_dir ${test_lib_native_dir}) +string(REPLACE "\\" "\\\\" test_lib_sep ${test_lib_sep}) +configure_file("dl_test.h.in" "${CMAKE_CURRENT_BINARY_DIR}/include/dl_test.h" @ONLY) +# Let ctest set the proper library path when executing library tests. +unset(test_lib_tests) +process_cunit_source_file("dynlib.c" test_lib_header test_lib_suites test_lib_tests) +foreach(libtest ${test_lib_tests}) + string(REPLACE ":" ";" libtest ${libtest}) + list(GET libtest 0 suite) + list(GET libtest 1 test) + set(libtestname "CUnit_${suite}_${test}") + if("${CMAKE_HOST_SYSTEM}" MATCHES ".*Windows.*") + set_property(TEST ${libtestname} APPEND PROPERTY ENVIRONMENT "${test_lib_native_dir}") + else() + set_property(TEST ${libtestname} APPEND PROPERTY ENVIRONMENT "LD_LIBRARY_PATH=${test_lib_native_dir};$ENV{LD_LIBRARY_PATH}") + endif() +endforeach() + diff --git a/src/ddsrt/tests/dl_test.h.in b/src/ddsrt/tests/dl_test.h.in new file mode 100644 index 0000000..69a05ab --- /dev/null +++ b/src/ddsrt/tests/dl_test.h.in @@ -0,0 +1,22 @@ +/* + * Copyright(c) 2006 to 2018 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#ifndef DDSRT_TEST_DL_TEST_H +#define DDSRT_TEST_DL_TEST_H + +/* Get the library name information from cmake. */ +#define TEST_LIB_NAME "@test_lib_name@" +#define TEST_LIB_DIR "@test_lib_dir@" +#define TEST_LIB_SEP "@test_lib_sep@" +#define TEST_LIB_SUFFIX "@CMAKE_SHARED_LIBRARY_SUFFIX@" +#define TEST_LIB_PREFIX "@CMAKE_SHARED_LIBRARY_PREFIX@" + +#endif /* DDSRT_TEST_DL_TEST_H */ diff --git a/src/ddsrt/tests/dllib.c b/src/ddsrt/tests/dllib.c new file mode 100644 index 0000000..21086e6 --- /dev/null +++ b/src/ddsrt/tests/dllib.c @@ -0,0 +1,25 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include "lib_test_export.h" + +static int g_val = -1; + +LIB_TEST_EXPORT void set_int(int val) +{ + g_val = val; +} + +LIB_TEST_EXPORT int get_int(void) +{ + return g_val; +} + diff --git a/src/ddsrt/tests/dynlib.c b/src/ddsrt/tests/dynlib.c new file mode 100644 index 0000000..3c3fc2a --- /dev/null +++ b/src/ddsrt/tests/dynlib.c @@ -0,0 +1,197 @@ +/* + * Copyright(c) 2019 ADLINK Technology Limited and others + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License + * v. 1.0 which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + */ +#include +#include +#include +#include +#include "CUnit/Test.h" +#include "dds/ddsrt/heap.h" +#include "dds/ddsrt/string.h" +#include "dds/ddsrt/environ.h" +#include "dl_test.h" + +#define TEST_LIB_FILE ""TEST_LIB_PREFIX""TEST_LIB_NAME""TEST_LIB_SUFFIX"" +#define TEST_LIB_ABSOLUTE ""TEST_LIB_DIR""TEST_LIB_SEP""TEST_LIB_FILE"" + +#define TEST_ABORT_IF_NULL(var, msg) \ +do { \ + if (var == NULL) { \ + char buffer[256]; \ + r = ddsrt_dlerror(buffer, sizeof(buffer)); \ + CU_ASSERT_EQUAL_FATAL(r, DDS_RETCODE_OK); \ + printf("\n%s", buffer); \ + CU_FAIL_FATAL(msg); \ + } \ +} while(0) + + +/* + * Load a library. + */ +CU_Test(ddsrt_library, dlopen_path) +{ + dds_retcode_t r; + ddsrt_dynlib_t l; + + printf("Absolute lib: %s\n", TEST_LIB_ABSOLUTE); + r = ddsrt_dlopen(TEST_LIB_ABSOLUTE, false, &l); + CU_ASSERT_EQUAL(r, DDS_RETCODE_OK); + CU_ASSERT_PTR_NOT_NULL(l); + TEST_ABORT_IF_NULL(l, "ddsrt_dlopen() failed. Is the proper library path set?"); + + r = ddsrt_dlclose(l); + CU_ASSERT_EQUAL(r, DDS_RETCODE_OK); +} + +CU_Test(ddsrt_library, dlopen_file) +{ + dds_retcode_t r; + ddsrt_dynlib_t l; + + r = ddsrt_dlopen(TEST_LIB_FILE, false, &l); + CU_ASSERT_EQUAL(r, DDS_RETCODE_OK); + CU_ASSERT_PTR_NOT_NULL(l); + TEST_ABORT_IF_NULL(l, "ddsrt_dlopen() failed. Is the proper library path set?"); + + r = ddsrt_dlclose(l); + CU_ASSERT_EQUAL(r, DDS_RETCODE_OK); +} + +CU_Test(ddsrt_library, dlopen_name) +{ + dds_retcode_t r; + ddsrt_dynlib_t l; + + r = ddsrt_dlopen(TEST_LIB_NAME, true, &l); + CU_ASSERT_EQUAL(r, DDS_RETCODE_OK); + CU_ASSERT_PTR_NOT_NULL(l); + TEST_ABORT_IF_NULL(l, "ddsrt_dlopen() failed. Is the proper library path set?"); + + r = ddsrt_dlclose(l); + CU_ASSERT_EQUAL(r, DDS_RETCODE_OK); +} + +CU_Test(ddsrt_library, dlopen_unknown) +{ + char buffer[256]; + dds_retcode_t r; + ddsrt_dynlib_t l; + + r = ddsrt_dlopen("UnknownLib", false, &l); + + CU_ASSERT_PTR_NULL_FATAL(l); + + r = ddsrt_dlerror(buffer, sizeof(buffer)); + CU_ASSERT_EQUAL_FATAL(r, DDS_RETCODE_OK); + printf("\n%s", buffer); +} + +CU_Test(ddsrt_library, dlsym) +{ + dds_retcode_t r; + ddsrt_dynlib_t l; + void* f; + + r = ddsrt_dlopen(TEST_LIB_NAME, true, &l); + CU_ASSERT_PTR_NOT_NULL(l); + CU_ASSERT_EQUAL(r, DDS_RETCODE_OK); + TEST_ABORT_IF_NULL(l, "ddsrt_dlopen() failed. Is the proper library path set?"); + + r = ddsrt_dlsym(l, "get_int", &f); + CU_ASSERT_EQUAL(r, DDS_RETCODE_OK); + CU_ASSERT_PTR_NOT_NULL(f); + TEST_ABORT_IF_NULL(f, "ddsrt_dlsym(l, \"get_int\") failed."); + + r = ddsrt_dlclose(l); + CU_ASSERT_EQUAL(r, DDS_RETCODE_OK); +} + +CU_Test(ddsrt_library, dlsym_unknown) +{ + char buffer[256]; + dds_retcode_t r; + ddsrt_dynlib_t l; + void* f; + + r = ddsrt_dlopen(TEST_LIB_NAME, true, &l); + CU_ASSERT_PTR_NOT_NULL(l); + TEST_ABORT_IF_NULL(l,"ddsrt_dlopen() failed. Is the proper library path set?"); + + r = ddsrt_dlsym(l, "UnknownSym", &f); + CU_ASSERT_EQUAL(r, DDS_RETCODE_ERROR); + CU_ASSERT_PTR_NULL_FATAL(f); + + r = ddsrt_dlerror(buffer, sizeof(buffer)); + CU_ASSERT_EQUAL_FATAL(r, DDS_RETCODE_OK); + printf("\n%s", buffer); + + r = ddsrt_dlclose(l); + CU_ASSERT_EQUAL(r, DDS_RETCODE_OK); +} + +typedef void (*func_set_int)(int val); +typedef int (*func_get_int)(void); +CU_Test(ddsrt_library, call) +{ + int get_int = 0; + int set_int = 1234; + func_get_int f_get; + func_set_int f_set; + dds_retcode_t r; + ddsrt_dynlib_t l; + + r = ddsrt_dlopen(TEST_LIB_NAME, true, &l); + CU_ASSERT_PTR_NOT_NULL(l); + TEST_ABORT_IF_NULL(l, "ddsrt_dlopen() failed. Is the proper library path set?"); + + r = ddsrt_dlsym(l, "get_int", (void **)&f_get); + CU_ASSERT_PTR_NOT_NULL(f_get); + TEST_ABORT_IF_NULL(f_get, "ddsrt_dlsym(l, \"get_int\") failed."); + + r = ddsrt_dlsym(l, "set_int", (void **)&f_set); + CU_ASSERT_PTR_NOT_NULL(f_set); + TEST_ABORT_IF_NULL(f_set, "ddsrt_dlsym(l, \"set_int\") failed."); + + f_set(set_int); + get_int = f_get(); + CU_ASSERT_EQUAL(set_int, get_int); + + r = ddsrt_dlclose(l); + CU_ASSERT_EQUAL(r, DDS_RETCODE_OK); +} + +CU_Test(ddsrt_library, dlclose_error) +{ + dds_retcode_t r; + ddsrt_dynlib_t l; + + r = ddsrt_dlopen(TEST_LIB_NAME, true, &l); + CU_ASSERT_PTR_NOT_NULL(l); + TEST_ABORT_IF_NULL(l, "ddsrt_dlopen() failed. Is the proper library path set?"); + + r = ddsrt_dlclose(l); + CU_ASSERT_EQUAL(r, DDS_RETCODE_OK); + + r = ddsrt_dlclose( l ); /*already closed handle */ + CU_ASSERT_EQUAL(r, DDS_RETCODE_ERROR); + +} + +CU_Test(ddsrt_library, dlerror_notfound) +{ + char buffer[256]; + dds_retcode_t r; + ddsrt_dlerror(buffer, sizeof(buffer)); + r = ddsrt_dlerror(buffer, sizeof(buffer)); + CU_ASSERT_EQUAL(r, DDS_RETCODE_NOT_FOUND); + +}