aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Sardara <msardara@cisco.com>2020-09-07 19:58:45 +0200
committerMauro Sardara <msardara@cisco.com>2020-09-09 09:37:22 +0000
commit91529a777fd3f56aeadef19dc25e196ba2e1cc51 (patch)
tree215433c0715cbaf74c25f4c6c2893907bda146bc
parentaba0a8ce4aeae0392b71658e9afaedc0d857a1a7 (diff)
[HICN-636] Add gtest framework and first tests for loop.
Signed-off-by: Mauro Sardara <msardara@cisco.com> Change-Id: I133c8adda125c430aa9c4a35fb63bf1d8585afe9 Signed-off-by: Mauro Sardara <msardara@cisco.com>
-rw-r--r--cmake/Modules/BuildMacros.cmake14
-rw-r--r--cmake/Modules/GTestImport.cmake32
-rw-r--r--hicn-light/CMakeLists.txt12
-rw-r--r--hicn-light/src/hicn/CMakeLists.txt4
-rw-r--r--hicn-light/src/hicn/base/CMakeLists.txt4
-rw-r--r--hicn-light/src/hicn/base/loop.c1
-rw-r--r--hicn-light/src/hicn/base/test/CMakeLists.txt25
-rw-r--r--hicn-light/src/hicn/base/test/test-loop.cc291
-rw-r--r--hicn-light/src/hicn/command_line/daemon/CMakeLists.txt2
9 files changed, 366 insertions, 19 deletions
diff --git a/cmake/Modules/BuildMacros.cmake b/cmake/Modules/BuildMacros.cmake
index d360d26af..ed95259b2 100644
--- a/cmake/Modules/BuildMacros.cmake
+++ b/cmake/Modules/BuildMacros.cmake
@@ -217,19 +217,5 @@ macro(build_library lib)
endif()
endmacro()
-add_custom_target(${PROJECT_NAME}_cleanup_profiling_data
- "find" "." "-name" "*.gcda" "-delete"
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- COMMENT "Cleanup previous profiling data."
-)
-
-macro(AddTest testFile)
- add_executable(${ARGV0} ${ARGV0}.cc)
- target_link_libraries(${ARGV0} ${TARGET_TRANSPORT_STATIC} ${GTEST_LIBRARIES})
- add_test(${ARGV0} ${ARGV0})
- set_target_properties(${ARGV0} PROPERTIES FOLDER Test)
- add_dependencies(${ARGV0} ${PROJECT_NAME}_cleanup_profiling_data)
-endmacro(AddTest)
-
include(IosMacros)
include(WindowsMacros)
diff --git a/cmake/Modules/GTestImport.cmake b/cmake/Modules/GTestImport.cmake
new file mode 100644
index 000000000..938dec786
--- /dev/null
+++ b/cmake/Modules/GTestImport.cmake
@@ -0,0 +1,32 @@
+# Copyright (c) 2020 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+##################################
+# Download and install GoogleTest
+
+include(ExternalProject)
+ExternalProject_Add(gtest
+ URL https://github.com/google/googletest/archive/v1.10.x.zip
+ PREFIX ${CMAKE_BINARY_DIR}/gtest
+ INSTALL_COMMAND ""
+)
+
+ExternalProject_Get_Property(gtest source_dir binary_dir)
+
+message (STATUS "GTest include dir: ${source_dir}/googlemock/include ${source_dir}/googletest/include)")
+message (STATUS "GTest libs: ${binary_dir}/lib/libgmock_main.a ${binary_dir}/lib/libgmock.a ${binary_dir}/lib/libgtest_main.a ${binary_dir}/lib/libgtest.a")
+
+set(GTEST_INCLUDE_DIRS ${source_dir}/googlemock/include ${source_dir}/googletest/include)
+set(GTEST_LIBRARIES ${binary_dir}/lib/libgmock_main.a ${binary_dir}/lib/libgmock.a ${binary_dir}/lib/libgtest_main.a ${binary_dir}/lib/libgtest.a)
+
+enable_testing() \ No newline at end of file
diff --git a/hicn-light/CMakeLists.txt b/hicn-light/CMakeLists.txt
index dd7d7fcc2..5d0d59b43 100644
--- a/hicn-light/CMakeLists.txt
+++ b/hicn-light/CMakeLists.txt
@@ -84,9 +84,9 @@ find_package(Threads REQUIRED)
set(LIBHICN_LIGHT hicn-light)
set(LIBHICN_LIGHT_STATIC ${LIBHICN_LIGHT}.static)
+set(LIBHICN_LIGHT_SHARED ${LIBHICN_LIGHT}.shared)
set(HICN_LIGHT_LINK_LIBRARIES
- ${LIBHICN_LIGHT_STATIC}
${HICN_LIBRARIES}
${LIBEVENT_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
@@ -114,6 +114,16 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
message(STATUS "Set \"-undefined dynamic_lookup\" for shared libraries")
endif()
+if (BUILD_TESTS)
+ include (GTestImport)
+
+ if(${CMAKE_VERSION} VERSION_GREATER "3.10.0")
+ include (GoogleTest)
+ else()
+ include (CTest)
+ endif()
+endif()
+
add_subdirectory(src/hicn)
# Install service file in linux systems
diff --git a/hicn-light/src/hicn/CMakeLists.txt b/hicn-light/src/hicn/CMakeLists.txt
index 29b76da25..4ecd5e2a0 100644
--- a/hicn-light/src/hicn/CMakeLists.txt
+++ b/hicn-light/src/hicn/CMakeLists.txt
@@ -65,10 +65,10 @@ else()
endif()
build_library(${LIBHICN_LIGHT}
- STATIC ${LIB_BUILD_TYPE}
+ STATIC SHARED ${LIB_BUILD_TYPE}
SOURCES ${SOURCE_FILES}
INSTALL_HEADERS ${TO_INSTALL_HEADER_FILES}
- LINK_LIBRARIES ${LIBRARIES}
+ LINK_LIBRARIES ${HICN_LIGHT_LINK_LIBRARIES}
DEPENDS ${DEPENDENCIES}
COMPONENT ${HICN_LIGHT}
INCLUDE_DIRS ${HICN_LIGHT_INCLUDE_DIRS}
diff --git a/hicn-light/src/hicn/base/CMakeLists.txt b/hicn-light/src/hicn/base/CMakeLists.txt
index 5b2677ed1..6e5ed4a3e 100644
--- a/hicn-light/src/hicn/base/CMakeLists.txt
+++ b/hicn-light/src/hicn/base/CMakeLists.txt
@@ -36,3 +36,7 @@ set(TO_INSTALL_HEADER_FILES
${HEADER_FILES}
PARENT_SCOPE
)
+
+if (BUILD_TESTS)
+ add_subdirectory(test)
+endif() \ No newline at end of file
diff --git a/hicn-light/src/hicn/base/loop.c b/hicn-light/src/hicn/base/loop.c
index 34aa94d6e..6e477f85a 100644
--- a/hicn-light/src/hicn/base/loop.c
+++ b/hicn-light/src/hicn/base/loop.c
@@ -156,7 +156,6 @@ ERR_EVENT_ADD:
int loop_event_unregister(event_t *event)
{
- assert(event->event_type == EVTYPE_FD);
event_del(&event->raw_event);
return 0;
}
diff --git a/hicn-light/src/hicn/base/test/CMakeLists.txt b/hicn-light/src/hicn/base/test/CMakeLists.txt
new file mode 100644
index 000000000..03c5a89b5
--- /dev/null
+++ b/hicn-light/src/hicn/base/test/CMakeLists.txt
@@ -0,0 +1,25 @@
+# Copyright (c) 2017-2019 Cisco and/or its affiliates.
+
+include(BuildMacros)
+
+list(APPEND TESTS
+ test-loop
+)
+
+foreach(test ${TESTS})
+ build_executable(${test}
+ NO_INSTALL
+ SOURCES ${test}.cc
+ LINK_LIBRARIES ${LIBHICN_LIGHT_SHARED} ${GTEST_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}
+ INCLUDE_DIRS ${HICN_LIGHT_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS}
+ DEPENDS gtest ${LIBHICN_LIGHT_SHARED}
+ COMPONENT ${HICN_LIGHT}
+ DEFINITIONS "${COMPILER_DEFINITIONS}"
+ )
+
+ if(${CMAKE_VERSION} VERSION_GREATER "3.10.0")
+ gtest_discover_tests(${test}-bin TEST_PREFIX new:)
+ else()
+ add_test(NAME ${test}-bin COMMAND ${test})
+ endif()
+endforeach()
diff --git a/hicn-light/src/hicn/base/test/test-loop.cc b/hicn-light/src/hicn/base/test/test-loop.cc
new file mode 100644
index 000000000..44684ef0e
--- /dev/null
+++ b/hicn-light/src/hicn/base/test/test-loop.cc
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2020 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <netinet/in.h>
+
+extern "C" {
+#include <hicn/base/loop.h>
+}
+
+class LoopTest : public ::testing::Test {
+ static constexpr uint16_t BUFFER_SIZE = 1024;
+ protected:
+ LoopTest()
+ : server_port_(9191),
+ loop_(nullptr),
+ timer_tick_(2000),
+ connection_socket_(-1),
+ event_(nullptr),
+ timer_(nullptr) {
+ }
+
+ virtual ~LoopTest() {
+ // You can do clean-up work that doesn't throw exceptions here.
+ }
+
+ // If the constructor and destructor are not enough for setting up
+ // and cleaning up each test, you can define the following methods:
+
+ virtual void SetUp() {
+ // Code here will be called immediately after the constructor (right
+ // before each test).
+ }
+
+ virtual void TearDown() {
+ // Code here will be called immediately after each test (right
+ // before the destructor).
+ }
+
+ static int onFirstTimerExpiration(void *owner, int fd, void* arg) {
+ std::cout << "This function should never be called" << std::endl;
+ EXPECT_TRUE(false);
+ return -1;
+ }
+
+ static int onSecondTimerExpiration(void *owner, int fd, void* arg) {
+ std::cout << "First timer expired. Cancel second timer." << std::endl;
+ LoopTest *test = (LoopTest *)(arg);
+ loop_event_unregister(test->timer_);
+ return 0;
+ }
+
+ static int onTimerExpiration(void *owner, int fd, void* arg) {
+ // Create client socket
+ struct sockaddr_in addr;
+ int client_socket;
+ LoopTest *test = (LoopTest *)(arg);
+
+ client_socket = socket(AF_INET, SOCK_STREAM, 0);
+ if (client_socket == -1) {
+ perror("socket");
+ return -1;
+ }
+
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(test->server_port_);
+
+ if (connect(client_socket, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1) {
+ perror("connect");
+ return -1;
+ }
+
+ if (send(client_socket, "Hello, world!\n", 14, 0) == -1){
+ perror("send");
+ return -1;
+ }
+
+ close(client_socket);
+ loop_event_unregister(test->timer_);
+
+ return 0;
+ }
+
+ static int onNewConnection(void *owner, int fd, void* arg) {
+ LoopTest *test = (LoopTest *)arg;
+ struct sockaddr_in addr;
+ addr.sin_addr.s_addr = INADDR_ANY;
+ addr.sin_family = AF_INET;
+
+ socklen_t addr_len = sizeof(struct sockaddr_in);
+ int ret;
+
+ int client_fd = accept(test->connection_socket_, (struct sockaddr*)(&addr), &addr_len);
+ if (client_fd == -1) {
+ if (errno != EAGAIN && errno != EWOULDBLOCK) {
+ fprintf(stderr, "accept failed");
+ }
+
+ perror("accept");
+ return -1;
+ }
+
+ // Read whatever data available and close connection.
+ ret = read(client_fd, test->buffer, BUFFER_SIZE);
+ if (ret < 0) {
+ perror("read");
+ return -1;
+ }
+
+ test->buffer[ret] = '\0';
+ std::cout << "Received: " << (char*)test->buffer << std::endl;
+
+ close(client_fd);
+ loop_event_unregister(test->event_);
+
+ return 0;
+ }
+
+ void createTcpSocketServer() {
+ struct sockaddr_in addr;
+ int ret;
+
+ /* Create local socket. */
+
+ connection_socket_ = socket(AF_INET, SOCK_STREAM, 0);
+ if (connection_socket_ == -1) {
+ perror("socket");
+ return;
+ }
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(server_port_);
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ ret = bind(connection_socket_, (const struct sockaddr *) &addr,
+ sizeof(struct sockaddr_in));
+ if (ret == -1) {
+ perror("bind");
+ return;
+ }
+
+ ret = listen(connection_socket_, 20);
+ if (ret == -1) {
+ perror("listen");
+ return;
+ }
+}
+
+ uint16_t server_port_;
+ loop_t *loop_;
+ unsigned timer_tick_;
+ int connection_socket_;
+ event_t *event_;
+ event_t *timer_;
+ char buffer[BUFFER_SIZE];
+};
+
+TEST_F(LoopTest, LoopCreate)
+{
+ loop_ = loop_create();
+ EXPECT_TRUE(loop_ != NULL);
+}
+
+TEST_F(LoopTest, LoopFree)
+{
+ loop_ = loop_create();
+ loop_free (loop_);
+ EXPECT_TRUE(loop_ != NULL);
+}
+
+TEST_F(LoopTest, EventCreateAndFree)
+{
+ int ret;
+
+ // Fake fd
+ int fd = 1;
+ loop_ = loop_create();
+
+ ret = loop_fd_event_create(&event_, loop_, fd, nullptr, &LoopTest::onNewConnection, this);
+ EXPECT_TRUE(ret >= 0);
+ EXPECT_TRUE(event_);
+
+ // Register the event
+ ret = loop_fd_event_register(event_);
+ EXPECT_TRUE(ret >= 0);
+
+ // Unregister the event
+ ret = loop_event_unregister(event_);
+ EXPECT_TRUE(ret >= 0);
+
+ // Free event loop
+ loop_free (loop_);
+}
+
+TEST_F(LoopTest, TimerCreateAndCancel)
+{
+ int ret;
+ event_t *timer2;
+ loop_ = loop_create();
+
+ ret = loop_timer_create(&timer_, loop_, nullptr, &LoopTest::onFirstTimerExpiration, this);
+ EXPECT_TRUE(ret >= 0);
+ EXPECT_TRUE(timer_);
+
+ ret = loop_timer_create(&timer2, loop_, nullptr, &LoopTest::onSecondTimerExpiration, this);
+ EXPECT_TRUE(ret >= 0);
+ EXPECT_TRUE(timer2);
+
+ // Register the 1st timer
+ ret = loop_timer_register(timer_, timer_tick_);
+ EXPECT_TRUE(ret >= 0);
+
+ // Register the 2nd timer
+ ret = loop_timer_register(timer2, timer_tick_ / 2);
+ EXPECT_TRUE(ret >= 0);
+
+ loop_dispatch(loop_);
+
+ loop_undispatch(loop_);
+
+ // Unregister the events
+ ret = loop_event_unregister(timer_);
+ ret += loop_event_unregister(timer2);
+ EXPECT_TRUE(ret >= 0);
+
+ // Free event loop
+ loop_free (loop_);
+}
+
+TEST_F(LoopTest, LoopDispatch)
+{
+ int ret;
+
+ // Create new unix socket
+ createTcpSocketServer();
+ loop_ = loop_create();
+
+ ret = loop_fd_event_create(&event_, loop_, connection_socket_, nullptr, &LoopTest::onNewConnection, this);
+ EXPECT_TRUE(ret >= 0);
+ EXPECT_TRUE(event_);
+
+ ret = loop_fd_event_register(event_);
+ EXPECT_TRUE(ret >= 0);
+
+ // Create timer.
+ ret = loop_timer_create(&timer_, loop_, nullptr, &LoopTest::onTimerExpiration, this);
+ EXPECT_TRUE(ret >= 0);
+ EXPECT_TRUE(timer_);
+
+ ret = loop_timer_register(timer_, timer_tick_);
+ EXPECT_TRUE(ret >= 0);
+
+ // Start event dispatching
+ loop_dispatch(loop_);
+
+ // Stop dispatching
+ loop_undispatch(loop_);
+
+ // Free events
+ loop_event_free(timer_);
+ loop_event_free(event_);
+
+ // Free event loop
+ loop_free (loop_);
+}
+
+int main(int argc, char **argv)
+{
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/hicn-light/src/hicn/command_line/daemon/CMakeLists.txt b/hicn-light/src/hicn/command_line/daemon/CMakeLists.txt
index 1ab8a4e6f..8606c8f89 100644
--- a/hicn-light/src/hicn/command_line/daemon/CMakeLists.txt
+++ b/hicn-light/src/hicn/command_line/daemon/CMakeLists.txt
@@ -17,7 +17,7 @@ list(APPEND DAEMON_SRC
if (NOT DISABLE_EXECUTABLES)
build_executable(${HICN_LIGHT_DAEMON}
SOURCES ${DAEMON_SRC}
- LINK_LIBRARIES ${HICN_LIGHT_LINK_LIBRARIES}
+ LINK_LIBRARIES ${LIBHICN_LIGHT_STATIC}
DEPENDS ${LIBHICN_LIGHT_STATIC}
COMPONENT ${HICN_LIGHT}
DEFINITIONS ${COMPILER_DEFINITIONS}