Skip to content

Commit

Permalink
Merge pull request eclipse-zenoh#210 from ZettaScaleLabs/add_integrat…
Browse files Browse the repository at this point in the history
…ion_tests

Add interation tests
  • Loading branch information
milyin authored Dec 4, 2023
2 parents 932bf60 + 1d200fd commit 108c20e
Show file tree
Hide file tree
Showing 5 changed files with 505 additions and 1 deletion.
13 changes: 12 additions & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,19 @@ add_custom_target(tests)
file(GLOB files "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
foreach(file ${files})
get_filename_component(target ${file} NAME_WE)

# Check the filename prefix to determine the test type
if (${file} MATCHES "^.*z_api_.*$")
set(test_type "unit")
elseif (${file} MATCHES "^.*z_int_.*$")
set(test_type "integration")
else()
message(FATAL_ERROR "Test file ${file} does not match any known type (z_api_ or z_int_)")
endif()

add_executable(${target} EXCLUDE_FROM_ALL ${file})
add_dependencies(tests ${target})

if(ZENOHC_BUILD_TESTS_WITH_STATIC_LIB)
add_dependencies(${target} zenohc::static)
target_link_libraries(${target} PRIVATE zenohc::static)
Expand All @@ -20,6 +31,6 @@ foreach(file ${files})

set_property(TARGET ${target} PROPERTY C_STANDARD 11)
# set_property(TARGET ${target} PROPERTY RUNTIME_OUTPUT_DIRECTORY "${cargo_target_dir}/tests")
add_test(NAME "test_${file}" COMMAND ${target})
add_test(NAME "${test_type}_${target}" COMMAND ${target})
endforeach()

155 changes: 155 additions & 0 deletions tests/z_int_helpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
//
// Copyright (c) 2023 ZettaScale Technology
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
//
// Contributors:
// ZettaScale Zenoh Team, <[email protected]>
//

//
// This file contains hepler macros and functions for integration testing, this
// file also contains the implementations, since it is assumed that the integration test
// consists of one file and is not expected to include this file in
// several other *.c files of one binary.
//

#pragma once

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
#undef VALID_PLATFORM
#else // def windows
#define VALID_PLATFORM 1

#include <errno.h>
#include <fcntl.h>
#include <semaphore.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#undef NDEBUG
#include <assert.h>

typedef int (*func_ptr_t)();

int run_timeouted_test(func_ptr_t functions[], int num_functions, int timeout_seconds) {
pid_t child_pids[num_functions];
int status;
int result = 0;

// Fork a child process for each function
for (int i = 0; i < num_functions; ++i) {
child_pids[i] = fork();
if (child_pids[i] == 0) {
// Child process
exit(functions[i]());
} else if (child_pids[i] < 0) {
// Error forking
perror("Error forking");
exit(EXIT_FAILURE);
}
}

// Wait for all processes to finish or timeout
int remaining_time = timeout_seconds * 10;
int remaining_children = num_functions;

while (remaining_time > 0 && remaining_children > 0 && result == 0) {
pid_t finished_pid = waitpid(-1, &status, WNOHANG);
if (finished_pid > 0) {
for (int i = 0; i < num_functions; ++i) {
if (finished_pid == child_pids[i]) {
child_pids[i] = 0;
--remaining_children;
if ((WIFEXITED(status) && WEXITSTATUS(status) != 0)) {
result = -1;
break;
}
}
}
} else if (finished_pid == 0) {
// No process finished yet
usleep(100000); // 0.1 sec
remaining_time--;
} else {
// Error in waitpid
perror("Error waiting for child process");
break;
}
}

if (remaining_time <= 0) {
fprintf(stderr, "Timeout reached\n");
}

// Check if the processes are still running and kill them if necessary
if (remaining_children != 0) {
for (int i = 0; i < num_functions; ++i) {
if (child_pids[i]) {
kill(child_pids[i], SIGKILL);
waitpid(child_pids[i], &status, 0);
}
}
result = -1;
}

return result;
};

#define SEM_INIT(sem, name) \
do { \
sem_unlink(name); \
sem = sem_open(name, O_CREAT | O_EXCL, 0666, 0); \
if (sem == SEM_FAILED) { \
perror("sem_open"); \
exit(-1); \
} \
} while (0)

#define SEM_DROP(sem, name) \
do { \
int r; \
r = sem_close(sem); \
if (r) { \
perror("sem_close"); \
exit(-1); \
}; \
r = sem_unlink(name); \
if (r) { \
perror("sem_close"); \
exit(-1); \
} \
} while (0)

#define SEM_WAIT(sem) \
do { \
int r; \
do { \
r = sem_wait(sem); \
if (r == -1 && errno != EINTR) { \
perror("sem_wait"); \
exit(-1); \
} \
} while (r != 0); \
} while (0)

#define SEM_POST(sem) \
do { \
int r; \
r = sem_post(sem); \
if (r) { \
perror("sem_post"); \
exit(-1); \
}; \
} while (0)

#endif // def windows
73 changes: 73 additions & 0 deletions tests/z_int_helpers_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//
// Copyright (c) 2023 ZettaScale Technology
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
//
// Contributors:
// ZettaScale Zenoh Team, <[email protected]>
//

#include "z_int_helpers.h"

#ifdef VALID_PLATFORM

int run_success() { return 0; }

int run_failed() { return 1; }

int run_hanged() {
while (1) {
sleep(1000);
};
return 0;
}

void all_success() {
func_ptr_t funcs[] = {run_success, run_success, run_success};
assert(run_timeouted_test(funcs, 3, 10) == 0);
}

void all_failed() {
func_ptr_t funcs[] = {run_failed, run_failed, run_failed};
assert(run_timeouted_test(funcs, 3, 10) == -1);
}

void first_failed() {
func_ptr_t funcs[] = {run_failed, run_success, run_success};
assert(run_timeouted_test(funcs, 3, 10) == -1);
}

void last_failed() {
func_ptr_t funcs[] = {run_success, run_success, run_failed};
assert(run_timeouted_test(funcs, 3, 10) == -1);
}

void all_hanged() {
func_ptr_t funcs[] = {run_hanged, run_hanged, run_hanged};
assert(run_timeouted_test(funcs, 3, 1) == -1);
}

void one_hanged() {
func_ptr_t funcs[] = {run_success, run_hanged, run_success};
assert(run_timeouted_test(funcs, 3, 1) == -1);
}

int main() {
all_success();
all_failed();
first_failed();
last_failed();
all_hanged();
one_hanged();

return 0;
}

#else
int main() { return 0; }
#endif // VALID_PLATFORM
Loading

0 comments on commit 108c20e

Please sign in to comment.