forked from eclipse-zenoh/zenoh-c
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request eclipse-zenoh#210 from ZettaScaleLabs/add_integrat…
…ion_tests Add interation tests
- Loading branch information
Showing
5 changed files
with
505 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.