The Pedigree Project 0.1
ipc-contract-test/main.c
1#define _GNU_SOURCE
2#include <errno.h>
3#include <signal.h>
4#include <stdio.h>
5#include <string.h>
6#include <time.h>
7#include <unistd.h>
8
9#include <sys/wait.h>
10
11int ipc_test_messages(void);
12int ipc_test_semaphores(void);
13int ipc_test_mqueues(void);
14int ipc_test_shared_memory(void);
15int ipc_test_shared_memory_exec(int argc, char** argv);
16int ipc_test_mqueue_exec(int argc, char** argv);
17
18static int run(const char* name, int (*test)(void)) {
19 printf("IPC-CONTRACT: BEGIN %s\n", name);
20 fflush(stdout);
21 pid_t child = fork();
22 if (child < 0) {
23 perror("fork");
24 return -1;
25 }
26 if (!child) {
27 alarm(90);
28 int result = test();
29 fflush(stdout);
30 fflush(stderr);
31 _exit(result ? 1 : 0);
32 }
33 struct timespec started, now;
34 clock_gettime(CLOCK_MONOTONIC, &started);
35 for (;;) {
36 int status = 0;
37 pid_t result = waitpid(child, &status, WNOHANG);
38 if (result == child) {
39 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
40 printf("IPC-CONTRACT: PASS %s\n", name);
41 return 0;
42 }
43 printf("IPC-CONTRACT: FAIL %s status=%d\n", name, status);
44 return -1;
45 }
46 if (result < 0 && errno != EINTR) {
47 perror("waitpid");
48 kill(child, SIGKILL);
49 return -1;
50 }
51 clock_gettime(CLOCK_MONOTONIC, &now);
52 if (now.tv_sec - started.tv_sec > 100) {
53 kill(child, SIGKILL);
54 while (waitpid(child, &status, 0) < 0 && errno == EINTR) {
55 }
56 printf("IPC-CONTRACT: FAIL %s timeout\n", name);
57 return -1;
58 }
59 struct timespec pause = {0, 10000000};
60 nanosleep(&pause, NULL);
61 }
62}
63
64int main(int argc, char** argv) {
65 if (argc > 1 && !strcmp(argv[1], "shm-exec")) {
66 return ipc_test_shared_memory_exec(argc, argv);
67 }
68 if (argc > 1 && !strcmp(argv[1], "mq-exec")) {
69 return ipc_test_mqueue_exec(argc, argv);
70 }
71 static const struct {
72 const char* name;
73 int (*test)(void);
74 } suites[] = {{"messages", ipc_test_messages},
75 {"semaphores", ipc_test_semaphores},
76 {"mqueues", ipc_test_mqueues},
77 {"shared-memory", ipc_test_shared_memory}};
78 int selected = 0;
79 for (unsigned i = 0; i < sizeof suites / sizeof suites[0]; ++i) {
80 if (argc > 1 && strcmp(argv[1], suites[i].name)) {
81 continue;
82 }
83 selected = 1;
84 if (run(suites[i].name, suites[i].test)) {
85 return 1;
86 }
87 }
88 if (!selected) {
89 fprintf(stderr, "Unknown IPC contract suite\n");
90 return 2;
91 }
92 puts("IPC-CONTRACT: END PASS");
93 return 0;
94}