Dynamic library loading functions were added to ddsrt

ddsrt_dlopen ddsrt_dlclose ddsrt_dlsym and ddsrt_dlerror functions can be used
in posix and windows platforms that support dynamic loading

Signed-off-by: Kurtulus Oksuztepe <kurtulus.oksuztepe@adlinktech.com>
This commit is contained in:
Kurtulus Oksuztepe 2019-07-01 16:33:24 +02:00 committed by eboasson
parent 98cf8e2ae5
commit a65d3db7c8
9 changed files with 633 additions and 3 deletions

View file

@ -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()

View file

@ -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 */

25
src/ddsrt/tests/dllib.c Normal file
View file

@ -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;
}

197
src/ddsrt/tests/dynlib.c Normal file
View file

@ -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 <stdio.h>
#include <string.h>
#include <assert.h>
#include <dds/ddsrt/dynlib.h>
#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);
}