ctdb-protocol: Fix marshalling for ctdb_uptime
[vlendec/samba-autobuild/.git] / ctdb / tests / src / pidfile_test.c
1 /*
2    pidfile tests
3
4    Copyright (C) Amitay Isaacs  2016
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "replace.h"
21 #include "system/wait.h"
22
23 #include <assert.h>
24
25 #include "common/pidfile.c"
26
27
28 /* create pid file, check pid file exists, check pid and remove pid file */
29 static void test1(const char *pidfile)
30 {
31         struct pidfile_context *pid_ctx;
32         int ret;
33         struct stat st;
34         FILE *fp;
35         pid_t pid;
36
37         ret = pidfile_context_create(NULL, pidfile, &pid_ctx);
38         assert(ret == 0);
39         assert(pid_ctx != NULL);
40
41         ret = stat(pidfile, &st);
42         assert(ret == 0);
43         assert(S_ISREG(st.st_mode));
44
45         fp = fopen(pidfile, "r");
46         assert(fp != NULL);
47         ret = fscanf(fp, "%d", &pid);
48         assert(ret == 1);
49         assert(pid == getpid());
50         fclose(fp);
51
52         TALLOC_FREE(pid_ctx);
53
54         ret = stat(pidfile, &st);
55         assert(ret == -1);
56 }
57
58 /* create pid file in two processes */
59 static void test2(const char *pidfile)
60 {
61         struct pidfile_context *pid_ctx;
62         pid_t pid, pid2;
63         int fd[2];
64         int ret;
65         size_t nread;
66         FILE *fp;
67         struct stat st;
68
69         ret = pipe(fd);
70         assert(ret == 0);
71
72         pid = fork();
73         assert(pid != -1);
74
75         if (pid == 0) {
76                 ssize_t nwritten;
77
78                 close(fd[0]);
79
80                 ret = pidfile_context_create(NULL, pidfile, &pid_ctx);
81                 assert(ret == 0);
82                 assert(pid_ctx != NULL);
83
84                 nwritten = write(fd[1], &ret, sizeof(ret));
85                 assert(nwritten == sizeof(ret));
86
87                 sleep(10);
88
89                 TALLOC_FREE(pid_ctx);
90
91                 nwritten = write(fd[1], &ret, sizeof(ret));
92                 assert(nwritten == sizeof(ret));
93
94                 exit(1);
95         }
96
97         close(fd[1]);
98
99         nread = read(fd[0], &ret, sizeof(ret));
100         assert(nread == sizeof(ret));
101         assert(ret == 0);
102
103         fp = fopen(pidfile, "r");
104         assert(fp != NULL);
105         ret = fscanf(fp, "%d", &pid2);
106         assert(ret == 1);
107         assert(pid == pid2);
108         fclose(fp);
109
110         ret = pidfile_context_create(NULL, pidfile, &pid_ctx);
111         assert(ret != 0);
112
113         nread = read(fd[0], &ret, sizeof(ret));
114         assert(nread == sizeof(ret));
115         assert(ret == 0);
116
117         ret = pidfile_context_create(NULL, pidfile, &pid_ctx);
118         assert(ret == 0);
119         assert(pid_ctx != NULL);
120
121         TALLOC_FREE(pid_ctx);
122
123         ret = stat(pidfile, &st);
124         assert(ret == -1);
125 }
126
127 /* create pid file, fork, try to remove pid file in separate process */
128 static void test3(const char *pidfile)
129 {
130         struct pidfile_context *pid_ctx;
131         pid_t pid;
132         int fd[2];
133         int ret;
134         size_t nread;
135         struct stat st;
136
137         ret = pidfile_context_create(NULL, pidfile, &pid_ctx);
138         assert(ret == 0);
139         assert(pid_ctx != NULL);
140
141         ret = pipe(fd);
142         assert(ret == 0);
143
144         pid = fork();
145         assert(pid != -1);
146
147         if (pid == 0) {
148                 ssize_t nwritten;
149
150                 close(fd[0]);
151
152                 TALLOC_FREE(pid_ctx);
153
154                 nwritten = write(fd[1], &ret, sizeof(ret));
155                 assert(nwritten == sizeof(ret));
156
157                 exit(1);
158         }
159
160         close(fd[1]);
161
162         nread = read(fd[0], &ret, sizeof(ret));
163         assert(nread == sizeof(ret));
164
165         ret = stat(pidfile, &st);
166         assert(ret == 0);
167
168         TALLOC_FREE(pid_ctx);
169
170         ret = stat(pidfile, &st);
171         assert(ret == -1);
172 }
173
174 /* create pid file, kill process, overwrite pid file in different process */
175 static void test4(const char *pidfile)
176 {
177         struct pidfile_context *pid_ctx;
178         pid_t pid, pid2;
179         int fd[2];
180         int ret;
181         size_t nread;
182         struct stat st;
183
184         ret = pipe(fd);
185         assert(ret == 0);
186
187         pid = fork();
188         assert(pid != -1);
189
190         if (pid == 0) {
191                 ssize_t nwritten;
192
193                 close(fd[0]);
194
195                 ret = pidfile_context_create(NULL, pidfile, &pid_ctx);
196
197                 nwritten = write(fd[1], &ret, sizeof(ret));
198                 assert(nwritten == sizeof(ret));
199
200                 sleep(99);
201                 exit(1);
202         }
203
204         close(fd[1]);
205
206         nread = read(fd[0], &ret, sizeof(ret));
207         assert(nread == sizeof(ret));
208         assert(ret == 0);
209
210         ret = stat(pidfile, &st);
211         assert(ret == 0);
212
213         ret = kill(pid, SIGKILL);
214         assert(ret == 0);
215
216         pid2 = waitpid(pid, &ret, 0);
217         assert(pid2 == pid);
218
219         ret = pidfile_context_create(NULL, pidfile, &pid_ctx);
220         assert(ret == 0);
221         assert(pid_ctx != NULL);
222
223         ret = stat(pidfile, &st);
224         assert(ret == 0);
225
226         TALLOC_FREE(pid_ctx);
227 }
228
229 int main(int argc, const char **argv)
230 {
231         if (argc != 2) {
232                 fprintf(stderr, "Usage: %s <pidfile>\n", argv[0]);
233                 exit(1);
234         }
235
236         test1(argv[1]);
237         test2(argv[1]);
238         test3(argv[1]);
239         test4(argv[1]);
240
241         return 0;
242 }