Tizen 2.1 base
[platform/upstream/gcd.git] / dispatch-1.0 / testing / harness.c
1 /*
2  * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
3  *
4  * @APPLE_APACHE_LICENSE_HEADER_START@
5  * 
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  * 
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  * 
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  * 
18  * @APPLE_APACHE_LICENSE_HEADER_END@
19  */
20
21 #include "config/config.h"
22
23 #include <dispatch/dispatch.h>
24 #include <assert.h>
25 #include <spawn.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <signal.h>
30 #include <mach/clock_types.h>
31
32 #include "dispatch_test.h"
33
34 extern char **environ;
35
36 int
37 main(int argc, char *argv[])
38 {
39         dispatch_source_t proc;
40         dispatch_source_t sig;
41         int res;
42         pid_t pid;
43
44         if (argc < 2) {
45                 fprintf(stderr, "usage: harness [...]\n");
46                 exit(1);
47         }
48
49         //
50         // Start the test in a suspended state.  Will send SIGCONT once ready.
51         //
52
53         posix_spawnattr_t attr;
54         res = posix_spawnattr_init(&attr);
55         assert(res == 0);
56         res = posix_spawnattr_setflags(&attr, POSIX_SPAWN_START_SUSPENDED);
57         assert(res == 0);
58
59         int i;
60         char** newargv = calloc(argc, sizeof(void*));
61         for (i = 1; i < argc; ++i) {
62                 newargv[i-1] = argv[i];
63         }
64         newargv[i-1] = NULL;
65
66         res = posix_spawnp(&pid, newargv[0], NULL, &attr, newargv, environ);
67         if (res) {
68                 errno = res;
69                 perror(newargv[0]);
70                 exit(EXIT_FAILURE);
71         }
72         //fprintf(stderr, "pid = %d\n", pid);
73         assert(pid > 0);
74
75         //
76         // Monitor the test process exit status.
77         //
78
79         dispatch_queue_t main_q = dispatch_get_main_queue();
80
81         proc = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, pid, DISPATCH_PROC_EXIT, main_q);
82         assert(proc);
83         
84         dispatch_source_set_event_handler(proc, ^{
85                 int status;
86                 int res2 = waitpid(pid, &status, 0);
87                 assert(res2 != -1);
88                 test_long("Process exited", WEXITSTATUS(status) | WTERMSIG(status), 0);
89                 exit(0);
90         });
91         
92         dispatch_resume(proc);
93         
94         //
95         // Forcibly stop currently running test after 30 second timeout.
96         //
97
98         uint64_t timeout = 30LL * NSEC_PER_SEC;
99
100         dispatch_after(dispatch_time(DISPATCH_TIME_NOW, timeout), main_q, ^{
101                 kill(pid, SIGKILL);
102                 fprintf(stderr, "Terminating unresponsive process (%0.1lfs)\n", (double)timeout/NSEC_PER_SEC);
103         });
104
105         //
106         // Control-c forcibly stops currently running test.
107         //
108
109         // Ignore the default signal handler so that dispatch can handle it.
110         signal(SIGINT, SIG_IGN);
111
112         sig = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGINT, 0, main_q);
113         assert(sig);
114
115         dispatch_source_set_event_handler(sig, ^{
116                 fprintf(stderr, "Terminating process due to signal\n");
117                 kill(pid, SIGKILL);
118         });
119         dispatch_resume(sig);
120
121         //
122         // Start the test.
123         //
124
125         kill(pid, SIGCONT);
126
127         dispatch_main();
128
129         return 0;
130 }