Skip to content

Commit

Permalink
[TEST] Add unit test for custom connection
Browse files Browse the repository at this point in the history
Add unit test for custom connection
*linnnstreamer-edge-cusom.so is not real implementation just for test

Signed-off-by: gichan2-jang <[email protected]>
  • Loading branch information
gichan-jang committed Aug 21, 2024
1 parent 017173f commit 70dce85
Show file tree
Hide file tree
Showing 6 changed files with 512 additions and 59 deletions.
24 changes: 17 additions & 7 deletions include/nnstreamer-edge-custom.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,18 @@
#ifndef __NNSTREAMER_EDGE_CUSTOM_H__
#define __NNSTREAMER_EDGE_CUSTOM_H__

#include <stdint.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "nnstreamer-edge.h"

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/**
* @brief NNStreamer Edge custom connection definition. This is used to define a custom connsction. The user should implement the functions and provide them using nns_edge_custom_get_instance(). Refer to the example in nnstreamer-edge-custom.c for more details.
*/
typedef struct _NnsEdgeCustomDef
{
char *(*nns_edge_get_connection_type) ();
const char *(*nns_edge_custom_get_description) ();
int (*nns_edge_custom_create) (void **priv);
int (*nns_edge_custom_close) (void *priv);
int (*nns_edge_custom_start) (void *priv);
Expand All @@ -33,8 +36,15 @@ typedef struct _NnsEdgeCustomDef
int (*nns_edge_custom_send_data) (void *priv, nns_edge_data_h data_h);
int (*nns_edge_custom_set_option) (void *priv, const char *key, const char *value);
char *(*nns_edge_custom_get_option) (void *priv, const char *key);
} NnsEdgeCustomDef;
} nns_edge_custom_s;

/**
* @brief Get nns edge custom connection instance.
*/
void* nns_edge_custom_get_instance ();

void* nns_edge_custom_get_handle ();

#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __NNSTREAMER_EDGE_CUSTOM_H__ */
3 changes: 3 additions & 0 deletions packaging/nnstreamer-edge.spec
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ popd

%if 0%{?unit_test}
LD_LIBRARY_PATH=./src bash %{test_script} ./tests/unittest_nnstreamer-edge
LD_LIBRARY_PATH=./src:./tests bash %{test_script} ./tests/unittest_nnstreamer-edge-custom

%if 0%{?mqtt_support}
LD_LIBRARY_PATH=./src bash %{test_script} ./tests/unittest_nnstreamer-edge-mqtt
Expand Down Expand Up @@ -181,6 +182,8 @@ rm -rf %{buildroot}
%manifest nnstreamer-edge.manifest
%defattr(-,root,root,-)
%{_bindir}/unittest_nnstreamer-edge
%{_bindir}/unittest_nnstreamer-edge-custom
%{_libdir}/libnnstreamer-edge-custom-test.so*

%if 0%{?mqtt_support}
%{_bindir}/unittest_nnstreamer-edge-mqtt
Expand Down
181 changes: 129 additions & 52 deletions src/libnnstreamer-edge/nnstreamer-edge-internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@
*/
#define N_BACKLOG 10

/**
* @brief Data structure for edge custom connection.
*/
typedef struct
{
void *dl_handle;
void *instance;
void *priv;
} custom_connection_s;

/**
* @brief Data structure for edge handle.
*/
Expand Down Expand Up @@ -74,7 +84,9 @@ typedef struct

/* MQTT or AITT handle */
void *broker_h;
void *custom_h;

/* Data for custom connection */
custom_connection_s custom;
} nns_edge_handle_s;

/**
Expand Down Expand Up @@ -924,10 +936,10 @@ _nns_edge_send_thread (void *thread_data)
break;
case NNS_EDGE_CONNECT_TYPE_CUSTOM:
{
NnsEdgeCustomDef *custom_h = (NnsEdgeCustomDef *) eh->custom_h;
ret = custom_h->nns_edge_custom_send_data (eh->broker_h, data_h);
nns_edge_custom_s *custom_h = (nns_edge_custom_s *) eh->custom.instance;
ret = custom_h->nns_edge_custom_send_data (eh->custom.priv, data_h);
if (NNS_EDGE_ERROR_NONE != ret)
nns_edge_loge ("Failed to send data via MCF connection.");
nns_edge_loge ("Failed to send data via nns edge custom connection.");
break;
}
default:
Expand Down Expand Up @@ -1297,7 +1309,9 @@ _nns_edge_create_handle (const char *id, nns_edge_node_type_e node_type,
eh->sending = false;
eh->listener_fd = -1;
eh->caps_str = nns_edge_strdup ("");
eh->custom_h = NULL;
eh->custom.dl_handle = NULL;
eh->custom.instance = NULL;
eh->custom.priv = NULL;

ret = nns_edge_metadata_create (&eh->metadata);
if (ret != NNS_EDGE_ERROR_NONE) {
Expand All @@ -1319,6 +1333,34 @@ _nns_edge_create_handle (const char *id, nns_edge_node_type_e node_type,
return ret;
}

/**
* @brief Load custom lib and get edge custom instance.
*/
static int
_nns_edge_load_custom_library (nns_edge_h edge_h, const char *lib_path)
{
nns_edge_handle_s *eh = (nns_edge_handle_s *) edge_h;

eh->custom.dl_handle = dlopen (lib_path, RTLD_LAZY);
if (NULL == eh->custom.dl_handle) {
nns_edge_loge ("Failed to open custom lib: %s", dlerror ());
return NNS_EDGE_ERROR_UNKNOWN;
}

void *(*getCustomHandle) () =
(void *(*)()) dlsym (eh->custom.dl_handle, "nns_edge_custom_get_instance");
if (!getCustomHandle) {
nns_edge_loge ("Failed to find nns_edge_custom_get_instance: %s",
dlerror ());
dlclose (eh->custom.dl_handle);
eh->custom.dl_handle = NULL;
return NNS_EDGE_ERROR_UNKNOWN;
}

eh->custom.instance = (nns_edge_custom_s *) getCustomHandle ();
return 0;
}

/**
* @brief Create edge custom handle.
*/
Expand All @@ -1328,8 +1370,7 @@ nns_edge_custom_create_handle (const char *id, const char *lib_path,
{
int ret = NNS_EDGE_ERROR_NONE;
nns_edge_handle_s *eh;
void *custom_handle;
NnsEdgeCustomDef *custom_h;
nns_edge_custom_s *custom_h;

if (node_type < 0 || node_type >= NNS_EDGE_NODE_TYPE_UNKNOWN) {
nns_edge_loge ("Invalid param, set exact node type.");
Expand All @@ -1354,23 +1395,15 @@ nns_edge_custom_create_handle (const char *id, const char *lib_path,
eh = (nns_edge_handle_s *) * edge_h;
eh->connect_type = NNS_EDGE_CONNECT_TYPE_CUSTOM;

custom_handle = dlopen (lib_path, RTLD_LAZY);
if (custom_handle) {
void *(*getCustomHandle) () =
(void *(*)()) dlsym (custom_handle, "nns_edge_custom_get_handle");
if (!getCustomHandle) {
nns_edge_loge ("Failed to find nns_edge_custom_get_handle: %s",
dlerror ());
return NNS_EDGE_ERROR_UNKNOWN;
}
eh->custom_h = getCustomHandle ();
} else {
nns_edge_loge ("Failed to open custom handle: %s]\n", dlerror ());
return NNS_EDGE_ERROR_INVALID_PARAMETER;;
ret = _nns_edge_load_custom_library (*edge_h, lib_path);
if (NNS_EDGE_ERROR_NONE != ret) {
nns_edge_loge
("Failed to load custom lib. Please check the custom lib path or permission.");
return ret;
}

custom_h = (NnsEdgeCustomDef *) eh->custom_h;
ret = custom_h->nns_edge_custom_create (&eh->broker_h);
custom_h = (nns_edge_custom_s *) eh->custom.instance;
ret = custom_h->nns_edge_custom_create (&eh->custom.priv);
if (NNS_EDGE_ERROR_NONE != ret) {
nns_edge_loge ("Failed to create custom connection handle.");
}
Expand Down Expand Up @@ -1431,6 +1464,33 @@ nns_edge_create_handle (const char *id, nns_edge_connect_type_e connect_type,
return ret;
}

/**
* @brief Start the nnstreamer edge custom.
*/
static int
_nns_edge_custom_start (nns_edge_handle_s * eh)
{
int ret = NNS_EDGE_ERROR_NONE;
nns_edge_custom_s *custom_h = (nns_edge_custom_s *) eh->custom.instance;

ret = custom_h->nns_edge_custom_start (eh->custom.priv);
if (NNS_EDGE_ERROR_NONE != ret) {
nns_edge_loge ("Failed to start edge custom connection");
return ret;
}

ret = custom_h->nns_edge_custom_set_event_cb (eh->custom.priv, eh->event_cb,
eh->user_data);
if (NNS_EDGE_ERROR_NONE != ret) {
nns_edge_loge ("Failed to set event callback to custom connection.");
return ret;
}

ret = _nns_edge_create_send_thread (eh);

return ret;
}

/**
* @brief Start the nnstreamer edge.
*/
Expand All @@ -1454,18 +1514,10 @@ nns_edge_start (nns_edge_h edge_h)
nns_edge_lock (eh);

if (NNS_EDGE_CONNECT_TYPE_CUSTOM == eh->connect_type) {
NnsEdgeCustomDef *custom_h = (NnsEdgeCustomDef *) eh->custom_h;
ret = custom_h->nns_edge_custom_start (eh->broker_h);
ret = _nns_edge_custom_start (edge_h);
if (NNS_EDGE_ERROR_NONE != ret) {
nns_edge_loge ("Failed to start edge custom connection");
}
ret = custom_h->nns_edge_custom_set_event_cb (eh->broker_h, eh->event_cb,
eh->user_data);
if (NNS_EDGE_ERROR_NONE != ret) {
nns_edge_loge ("Failed to set event callback to custom connection.");
goto done;
}
ret = _nns_edge_create_send_thread (eh);
goto done;
}

Expand Down Expand Up @@ -1556,6 +1608,22 @@ nns_edge_start (nns_edge_h edge_h)
return ret;
}

/**
* @brief Stop the nnstreamer edge custom connection.
*/
static int
_nns_edge_custom_stop (nns_edge_handle_s * eh)
{
int ret = NNS_EDGE_ERROR_NONE;
nns_edge_custom_s *custom_h = (nns_edge_custom_s *) eh->custom.instance;
ret = custom_h->nns_edge_custom_stop (eh->custom.priv);
if (NNS_EDGE_ERROR_NONE != ret) {
nns_edge_loge ("Failed to stop nns edge custom connection");
}

return ret;
}

/**
* @brief Stop the nnstreamer edge.
*/
Expand All @@ -1577,20 +1645,35 @@ nns_edge_stop (nns_edge_h edge_h)
}

nns_edge_lock (eh);
if (!eh->is_started) {
nns_edge_logi ("Edge is not started yet. Nothing to stop.");
goto done;
}

if (NNS_EDGE_CONNECT_TYPE_CUSTOM == eh->connect_type) {
NnsEdgeCustomDef *custom_h = (NnsEdgeCustomDef *) eh->custom_h;
ret = custom_h->nns_edge_custom_stop (eh->broker_h);
if (NNS_EDGE_ERROR_NONE != ret) {
nns_edge_loge ("Failed to stop MCF");
}
ret = _nns_edge_custom_stop (eh);
}

eh->is_started = FALSE;

done:
nns_edge_unlock (eh);
return ret;
}

static void
_nns_edge_custom_release (nns_edge_handle_s * eh)
{
nns_edge_custom_s *custom_h = (nns_edge_custom_s *) eh->custom.instance;
int ret = custom_h->nns_edge_custom_close (eh->custom.priv);
if (NNS_EDGE_ERROR_NONE != ret) {
nns_edge_loge ("Failed to stop nns edge custom connection");
}
dlclose (eh->custom.dl_handle);
eh->custom.instance = NULL;
eh->custom.dl_handle = NULL;
}

/**
* @brief Release the given handle.
*/
Expand All @@ -1610,8 +1693,7 @@ nns_edge_release_handle (nns_edge_h edge_h)
return NNS_EDGE_ERROR_INVALID_PARAMETER;
}

if (eh->is_started)
nns_edge_stop (eh);
nns_edge_stop (eh);

nns_edge_lock (eh);

Expand All @@ -1629,12 +1711,7 @@ nns_edge_release_handle (nns_edge_h edge_h)
break;
case NNS_EDGE_CONNECT_TYPE_CUSTOM:
{
NnsEdgeCustomDef *custom_h = (NnsEdgeCustomDef *) eh->custom_h;
int ret = custom_h->nns_edge_custom_close (eh->broker_h);
if (NNS_EDGE_ERROR_NONE != ret) {
nns_edge_loge ("Failed to stop MCF");
}
dlclose (eh->custom_h);
_nns_edge_custom_release (eh);
break;
}
default:
Expand Down Expand Up @@ -1879,8 +1956,8 @@ nns_edge_connect (nns_edge_h edge_h, const char *dest_host, int dest_port)
goto done;
}
} else if (NNS_EDGE_CONNECT_TYPE_CUSTOM == eh->connect_type) {
NnsEdgeCustomDef *custom_h = (NnsEdgeCustomDef *) eh->custom_h;
ret = custom_h->nns_edge_custom_connect (eh->broker_h);
nns_edge_custom_s *custom_h = (nns_edge_custom_s *) eh->custom.instance;
ret = custom_h->nns_edge_custom_connect (eh->custom.priv);
if (ret != NNS_EDGE_ERROR_NONE) {
nns_edge_loge ("Failed to connect to custom connection.");
goto done;
Expand Down Expand Up @@ -1952,8 +2029,8 @@ nns_edge_is_connected (nns_edge_h edge_h)
return NNS_EDGE_ERROR_NONE;

if (NNS_EDGE_CONNECT_TYPE_CUSTOM == eh->connect_type) {
NnsEdgeCustomDef *custom_h = (NnsEdgeCustomDef *) eh->custom_h;
return custom_h->nns_edge_custom_is_connected (eh->broker_h);
nns_edge_custom_s *custom_h = (nns_edge_custom_s *) eh->custom.instance;
return custom_h->nns_edge_custom_is_connected (eh->custom.priv);
}

conn_data = (nns_edge_conn_data_s *) eh->connections;
Expand Down Expand Up @@ -2127,8 +2204,8 @@ nns_edge_set_info (nns_edge_h edge_h, const char *key, const char *value)
}

if (NNS_EDGE_CONNECT_TYPE_CUSTOM == eh->connect_type) {
NnsEdgeCustomDef *custom_h = (NnsEdgeCustomDef *) eh->custom_h;
ret = custom_h->nns_edge_custom_set_option (eh->broker_h, key, value);
nns_edge_custom_s *custom_h = (nns_edge_custom_s *) eh->custom.instance;
ret = custom_h->nns_edge_custom_set_option (eh->custom.priv, key, value);
}

nns_edge_unlock (eh);
Expand Down Expand Up @@ -2195,8 +2272,8 @@ nns_edge_get_info (nns_edge_h edge_h, const char *key, char **value)
}

if (NNS_EDGE_CONNECT_TYPE_CUSTOM == eh->connect_type) {
NnsEdgeCustomDef *custom_h = (NnsEdgeCustomDef *) eh->custom_h;
*value = custom_h->nns_edge_custom_get_option (eh->broker_h, key);
nns_edge_custom_s *custom_h = (nns_edge_custom_s *) eh->custom.instance;
*value = custom_h->nns_edge_custom_get_option (eh->custom.priv, key);
}

nns_edge_unlock (eh);
Expand Down
14 changes: 14 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ TARGET_INCLUDE_DIRECTORIES(unittest_nnstreamer-edge PRIVATE ${EDGE_REQUIRE_PKGS_
TARGET_LINK_LIBRARIES(unittest_nnstreamer-edge ${TEST_REQUIRE_PKGS_LDFLAGS} ${NNS_EDGE_LIB_NAME})
INSTALL (TARGETS unittest_nnstreamer-edge DESTINATION ${BIN_INSTALL_DIR})

# Custom connection lib for unit test
SET(NNS_EDGE_CUSTOM_LIB_NAME nnstreamer-edge-custom-test)
SET(NNS_EDGE_CUSTOM_SRCS ${NNS_EDGE_SRCS} nnstreamer-edge-custom.c)
ADD_LIBRARY(${NNS_EDGE_CUSTOM_LIB_NAME} SHARED ${NNS_EDGE_CUSTOM_SRCS})
SET_TARGET_PROPERTIES(${NNS_EDGE_CUSTOM_LIB_NAME} PROPERTIES VERSION ${SO_VERSION})
TARGET_INCLUDE_DIRECTORIES(${NNS_EDGE_CUSTOM_LIB_NAME} PRIVATE ${EDGE_REQUIRE_PKGS_INCLUDE_DIRS} ${INCLUDE_DIR} ${NNS_EDGE_SRC_DIR})
TARGET_LINK_LIBRARIES(${NNS_EDGE_CUSTOM_LIB_NAME} ${TEST_REQUIRE_PKGS_LDFLAGS} ${NNS_EDGE_LIB_NAME})
INSTALL (TARGETS ${NNS_EDGE_CUSTOM_LIB_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR})

ADD_EXECUTABLE(unittest_nnstreamer-edge-custom unittest_nnstreamer-edge-custom.cc)
TARGET_INCLUDE_DIRECTORIES(unittest_nnstreamer-edge-custom PRIVATE ${EDGE_REQUIRE_PKGS_INCLUDE_DIRS} ${INCLUDE_DIR} ${NNS_EDGE_SRC_DIR})
TARGET_LINK_LIBRARIES(unittest_nnstreamer-edge-custom ${TEST_REQUIRE_PKGS_LDFLAGS} ${NNS_EDGE_LIB_NAME} ${NNS_EDGE_CUSTOM_LIB_NAME})
INSTALL (TARGETS unittest_nnstreamer-edge-custom DESTINATION ${BIN_INSTALL_DIR})

# AITT test
IF(AITT_SUPPORT)
ADD_EXECUTABLE(unittest_nnstreamer-edge-aitt unittest_nnstreamer-edge-aitt.cc)
Expand Down
Loading

0 comments on commit 70dce85

Please sign in to comment.