rvm  1.11
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test-exec.cc
Go to the documentation of this file.
1 #include "config.h"
2 
3 #ifdef HAVE_UNISTD_H
4 #include <unistd.h>
5 #endif
6 
7 #include <string>
8 #include <cstring>
9 #include <cassert>
10 
11 #include "asserts.h"
12 #include "error.h"
13 #include "fs.h"
14 #include "exec.h"
15 #include "fdstream.h"
16 
17 // static char confdir[4096] = { 0 };
18 
19 void test1(void)
20 {
21  execute exe;
22  bool thrown = false;
23  int c = 0;
24 
25  assert(!exe.child_started());
26  assert(!exe.child_running());
27  try {
28  exe.fork();
29  }
30  catch (error &e) {
31  thrown = true;
32  }
33  assert(!thrown);
34  if (exe.is_child()) {
35  // std::cerr << "Child exiting now" << std::endl;
36  exe.exit(0);
37  }
38  assert(exe.child_started());
39  while (exe.child_running() && (c < 5)) {
40  // std::cout << "Child is running, waiting..." << std::endl;
41  c++;
42  sleep(1);
43  }
44  assert(!exe.child_running());
45  assert(exe.child_exited());
46  assert(exe.child_exited_normally());
47  assert(!exe.child_signaled());
48  assert(exe.child_exit_code() == 0);
49  assert(exe.child_signal_no() == 0);
50  assert(exe.child_exited_success());
51 }
52 
53 void test2(void)
54 {
55  execute exe;
56 
57  exe.fork();
58  if (exe.is_parent()) {
59  char const *msg_to_child = "Message from parent";
60  char msg_from_child[4096] = { 0 };
61  char msg_from_err[4096] = { 0 };
62 
63  assert(exe.child_running());
64  assert(!exe.child_exited());
65  assert(!exe.child_exited_normally());
66  assert(!exe.child_signaled());
67  assert(exe.child_exit_code() == 0);
68  assert(exe.child_signal_no() == 0);
69  assert(!exe.child_exited_success());
70 
71  if (write(exe.in_fd(), msg_to_child, strlen(msg_to_child))
72  != (int)strlen(msg_to_child))
73  throw(ERROR(errno,"Error writing to child's input pipe"));
74  if (read(exe.out_fd(), msg_from_child, 4096) == 0)
75  throw(ERROR(errno,"Error reading from child's output pipe"));
76  if (read(exe.err_fd(), msg_from_err, 4096) == 0)
77  throw(ERROR(errno,"Error reading from child's error pipe"));
78 
79  exe.wait();
80 
81  assert(static_cast<std::string>(msg_from_child) == "Message from child");
82  assert(static_cast<std::string>(msg_from_err) == "Message from child err");
83  assert(!exe.child_running());
84  assert(exe.child_exited());
85  assert(exe.child_exited_normally());
86  assert(!exe.child_signaled());
87  assert(exe.child_exit_code() == 0);
88  assert(exe.child_signal_no() == 0);
89  assert(exe.child_exited_success());
90  }
91  if (exe.is_child()) {
92  char msg_from_parent[4096] = { 0 };
93  char const *msg_to_parent = "Message from child";
94  char const *msg_to_err = "Message from child err";
95 
96  if (read(exe.in_fd(), msg_from_parent, 4096) == 0)
97  throw(ERROR(errno,"Error reading input from parent"));
98  if (write(exe.out_fd(), msg_to_parent, strlen(msg_to_parent))
99  != (int)strlen(msg_to_parent))
100  throw(ERROR(errno,"Error writing output to parent"));
101  if (write(exe.err_fd(), msg_to_err, strlen(msg_to_err))
102  != (int)strlen(msg_to_err))
103  throw(ERROR(errno,"Error writing error to parent"));
104 
105  assert(static_cast<std::string>(msg_from_parent) == "Message from parent");
106 
107  exe.exit();
108  }
109 }
110 
111 void test3(void)
112 {
113  execute exe;
114 
115  exe.fork();
116  if (exe.is_parent()) {
117  char const *msg_to_child = "Message from parent";
118  char msg_from_child[4096] = { 0 };
119  char msg_from_err[4096] = { 0 };
120  char extra_msg[4096] = { 0 };
121  int extra_msg_length = 0;
122  int i;
123 
124  assert(exe.child_running());
125  assert(!exe.child_exited());
126  assert(!exe.child_exited_normally());
127  assert(!exe.child_signaled());
128  assert(exe.child_exit_code() == 0);
129  assert(exe.child_signal_no() == 0);
130  assert(!exe.child_exited_success());
131 
132  assert(exe.in_ready());
133  assert(!exe.out_ready());
134  assert(!exe.err_ready());
135 
136  sleep(1);
137 
138  assert(exe.in_ready());
139  assert(!exe.out_ready());
140  assert(!exe.err_ready());
141 
142  if (write(exe.in_fd(), msg_to_child, strlen(msg_to_child))
143  != (int)strlen(msg_to_child))
144  throw(ERROR(errno,"Error writing to child's input pipe"));
145 
146  sleep(1);
147 
148  assert(exe.in_ready());
149  assert(exe.out_ready());
150  assert(exe.err_ready());
151 
152  if (read(exe.out_fd(), msg_from_child, 4096) == 0)
153  throw(ERROR(errno,"Error reading from child's output pipe"));
154 
155  sleep(1);
156 
157  assert(exe.in_ready());
158  assert(exe.out_ready());
159  assert(exe.err_ready());
160 
161  if (read(exe.err_fd(), msg_from_err, 4096) == 0)
162  throw(ERROR(errno,"Error reading from child's error pipe"));
163 
164  sleep(1);
165 
166  assert(exe.in_ready());
167  assert(exe.out_ready());
168  assert(exe.err_ready());
169 
170  if (exe.out_ready()) {
171  for (i = 0; i < 4096; extra_msg[i++] = 0);
172  extra_msg_length = read(exe.out_fd(), extra_msg, 4096);
173  }
174  assert(extra_msg_length == 0);
175  if (exe.err_ready()) {
176  for (i = 0; i < 4096; extra_msg[i++] = 0);
177  extra_msg_length = read(exe.err_fd(), extra_msg, 4096);
178  }
179  assert(extra_msg_length == 0);
180 
181  exe.wait();
182 
183  assert(static_cast<std::string>(msg_from_child) == "Message from child");
184  assert(static_cast<std::string>(msg_from_err) == "Message from child err");
185  assert(!exe.child_running());
186  assert(exe.child_exited());
187  assert(exe.child_exited_normally());
188  assert(!exe.child_signaled());
189  assert(exe.child_exit_code() == 0);
190  assert(exe.child_signal_no() == 0);
191  assert(exe.child_exited_success());
192  }
193  if (exe.is_child()) {
194  char msg_from_parent[4096] = { 0 };
195  char const *msg_to_parent = "Message from child";
196  char const *msg_to_err = "Message from child err";
197 
198  if (read(exe.in_fd(), msg_from_parent, 4096) == 0)
199  throw(ERROR(errno,"Error reading input from parent"));
200  if (write(exe.out_fd(), msg_to_parent, strlen(msg_to_parent))
201  != (int)strlen(msg_to_parent))
202  throw(ERROR(errno,"Error writing output to parent"));
203  if (write(exe.err_fd(), msg_to_err, strlen(msg_to_err))
204  != (int)strlen(msg_to_err))
205  throw(ERROR(errno,"Error writing error to parent"));
206 
207  assert(static_cast<std::string>(msg_from_parent) == "Message from parent");
208 
209  exe.exit();
210  }
211 }
212 
213 void test4(void)
214 {
215  execute exe;
216 
217  exe.fork();
218  if (exe.is_parent()) {
219  assert(exe.child_running());
220  assert(!exe.child_exited());
221  assert(!exe.child_exited_normally());
222  assert(!exe.child_signaled());
223  assert(exe.child_exit_code() == 0);
224  assert(exe.child_signal_no() == 0);
225  assert(!exe.child_exited_success());
226 
227  exe.wait();
228 
229  assert(!exe.child_running());
230  assert(exe.child_exited());
231  assert(!exe.child_exited_normally());
232  assert(!exe.child_signaled());
233  assert(exe.child_exit_code() == 5);
234  assert(exe.child_signal_no() == 0);
235  assert(!exe.child_exited_success());
236  }
237  else {
238  sleep(1);
239  exe.exit(5);
240  }
241 }
242 
243 void test5(void)
244 {
245  execute exe1, exe2;
246 
247  exe1.fork();
248  if (exe1.is_child()) {
249  // std::cerr << "child exe1 pid = " << exe1.my_pid() << std::endl;
250  sleep(10);
251  // std::cerr << "Child exe1 exiting" << std::endl;
252  exe1.exit(0);
253  }
254 
255  exe2.fork();
256  if (exe2.is_child()) {
257  // std::cerr << "child exe2 pid = " << exe2.my_pid() << std::endl;
258  sleep(20);
259  // std::cerr << "Child exe2 exiting" << std::endl;
260  exe2.exit(0);
261  }
262 
263  assert(exe1.child_running());
264  assert(exe2.child_running());
265 
266  exe1.wait();
267 
268  assert(exe1.child_exited());
269  assert(!exe1.child_running());
270  assert(exe1.child_exited_success());
271  assert(!exe2.child_exited());
272  assert(exe2.child_running());
273  assert(!exe2.child_exited_success());
274 
275  exe2.wait();
276 
277  assert(exe1.child_exited());
278  assert(!exe1.child_running());
279  assert(exe1.child_exited_success());
280  assert(exe2.child_exited());
281  assert(!exe2.child_running());
282  assert(exe2.child_exited_success());
283 }
284 
285 void test6(void)
286 {
287  execute exe1, exe2;
288 
289  exe1.fork();
290  if (exe1.is_child()) {
291  // std::cerr << "child exe1 pid = " << exe1.my_pid() << std::endl;
292  sleep(1000);
293  // std::cerr << "Child exe1 exiting" << std::endl;
294  exe1.exit(0);
295  }
296 
297  exe2.fork();
298  if (exe2.is_child()) {
299  // std::cerr << "child exe2 pid = " << exe2.my_pid() << std::endl;
300  sleep(1000);
301  // std::cerr << "Child exe2 exiting" << std::endl;
302  exe2.exit(0);
303  }
304 
305  assert(exe1.child_running());
306  assert(exe2.child_running());
307 
308  exe1.kill_child();
309  while (exe1.child_running()); // Wait for the child to die
310 
311  assert(exe1.child_exited());
312  assert(!exe1.child_running());
313  assert(!exe1.child_exited_success());
314  assert(exe1.child_signal_no() == SIGKILL);
315  assert(!exe2.child_exited());
316  assert(exe2.child_running());
317  assert(!exe2.child_exited_success());
318 
319  exe2.kill_child();
320  while (exe2.child_running()); // Wait for the child to die
321 
322  assert(exe1.child_exited());
323  assert(!exe1.child_running());
324  assert(!exe1.child_exited_success());
325  assert(exe1.child_signal_no() == SIGKILL);
326  assert(exe2.child_exited());
327  assert(!exe2.child_running());
328  assert(!exe2.child_exited_success());
329  assert(exe2.child_signal_no() == SIGKILL);
330 }
331 
332 void test7(void)
333 {
334  execute exe;
335 
336  exe.fork();
337  if (exe.is_parent()) {
338  assert(exe.child_running());
339  assert(!exe.child_exited());
340  assert(!exe.child_exited_normally());
341  assert(!exe.child_signaled());
342  assert(exe.child_exit_code() == 0);
343  assert(exe.child_signal_no() == 0);
344 
345  exe.signal_child(SIGINT);
346  exe.wait();
347 
348  assert(!exe.child_running());
349  assert(exe.child_exited());
350  assert(exe.child_exited_normally());
351  assert(!exe.child_exited_success());
352  assert(exe.child_signaled());
353  assert(exe.child_exit_code() == 0);
354  assert(exe.child_signal_no() == SIGINT);
355  }
356  else {
357  sleep(5);
358  exe.exit(5);
359  }
360 }
361 
362 void test8(void)
363 {
364  execute exe;
365  std::string command = "sleep 5 ; /bin/ls -1 ./test-exec.cc";
366  char buffer[4096] = { 0 };
367  int num_bytes;
368 
369  exe.exec(command);
370 
371  assert(exe.child_running());
372  assert(!exe.child_exited());
373  assert(!exe.child_exited_normally());
374  assert(!exe.child_signaled());
375  assert(exe.child_exit_code() == 0);
376  assert(exe.child_signal_no() == 0);
377  assert(exe.in_ready());
378  assert(!exe.out_ready());
379  assert(!exe.err_ready());
380 
381  for (num_bytes = 0; num_bytes < 4096; buffer[num_bytes++] = 0);
382  num_bytes = read(exe.out_fd(), buffer, 4096);
383  assert(num_bytes = 15);
384  assert(static_cast<std::string>(buffer) == static_cast<std::string>("./test-exec.cc\n"));
385 
386  for (num_bytes = 0; num_bytes < 4096; buffer[num_bytes++] = 0);
387  num_bytes = read(exe.err_fd(), buffer, 4096);
388  assert(num_bytes == 0);
389  assert(static_cast<std::string>(buffer).size() == 0);
390 
391  exe.wait();
392 
393  assert(!exe.child_running());
394  assert(exe.child_exited());
395  assert(exe.child_exited_normally());
396  assert(!exe.child_signaled());
397  assert(exe.child_exit_code() == 0);
398  assert(exe.child_signal_no() == 0);
399  assert(exe.in_ready());
400  assert(exe.out_ready());
401  assert(exe.err_ready());
402 }
403 
404 void test9(void)
405 {
406  execute exe;
407  std::string command;
408  std::vector<std::string> argv;
409  char buffer[4096] = { 0 };
410  int num_bytes;
411 
412  command = "/bin/ls";
413  argv.push_back(std::string("-1"));
414  argv.push_back(std::string("./test-exec.cc"));
415  exe.exec(command, argv);
416 
417  // assert(exe.child_running());
418  // assert(!exe.child_exited());
419  // assert(!exe.child_exited_normally());
420  // assert(!exe.child_signaled());
421  // assert(exe.child_exit_code() == 0);
422  // assert(exe.child_signal_no() == 0);
423  // assert(exe.in_ready());
424  // assert(!exe.out_ready());
425  // assert(!exe.err_ready());
426 
427  for (num_bytes = 0; num_bytes < 4096; buffer[num_bytes++] = 0);
428  num_bytes = read(exe.out_fd(), buffer, 4096);
429  assert(num_bytes = 15);
430  assert(static_cast<std::string>(buffer) == static_cast<std::string>("./test-exec.cc\n"));
431 
432  for (num_bytes = 0; num_bytes < 4096; buffer[num_bytes++] = 0);
433  num_bytes = read(exe.err_fd(), buffer, 4096);
434  assert(num_bytes == 0);
435  assert(static_cast<std::string>(buffer).size() == 0);
436 
437  exe.wait();
438 
439  assert(!exe.child_running());
440  assert(exe.child_exited());
441  assert(exe.child_exited_normally());
442  assert(!exe.child_signaled());
443  assert(exe.child_exit_code() == 0);
444  assert(exe.child_signal_no() == 0);
445  assert(exe.in_ready());
446  assert(exe.out_ready());
447  assert(exe.err_ready());
448 }
449 
450 void test10(void)
451 {
452  execute exe;
453  ofdstream fdout;
454 
455  exe.fork();
456  if (exe.is_parent()) {
457  char const *msg_to_child = "Message from parent";
458  char msg_from_child[4096] = { 0 };
459  char msg_from_err[4096] = { 0 };
460 
461  assert(exe.child_running());
462  assert(!exe.child_exited());
463  assert(!exe.child_exited_normally());
464  assert(!exe.child_signaled());
465  assert(exe.child_exit_code() == 0);
466  assert(exe.child_signal_no() == 0);
467  assert(fdout.good());
468 
469  fdout.attach(exe.in_fd());
470  fdout << msg_to_child;
471  fdout.flush();
472 
473  assert(fdout.good());
474 
475  if (read(exe.out_fd(), msg_from_child, 4096) == 0)
476  throw(ERROR(errno,"Error reading from child's output pipe"));
477  if (read(exe.err_fd(), msg_from_err, 4096) == 0)
478  throw(ERROR(errno,"Error reading from child's error pipe"));
479 
480  exe.wait();
481 
482  assert(fdout.good());
483 
484  assert(static_cast<std::string>(msg_from_child) == "Message from child");
485  assert(static_cast<std::string>(msg_from_err) == "Message from child err");
486  assert(!exe.child_running());
487  assert(exe.child_exited());
488  assert(exe.child_exited_normally());
489  assert(!exe.child_signaled());
490  assert(exe.child_exit_code() == 0);
491  assert(exe.child_signal_no() == 0);
492  }
493  else {
494  char msg_from_parent[4096] = { 0 };
495  char const *msg_to_parent = "Message from child";
496  char const *msg_to_err = "Message from child err";
497 
498  if (read(exe.in_fd(), msg_from_parent, 4096) == 0)
499  throw(ERROR(errno,"Error reading input from parent"));
500  if (write(exe.out_fd(), msg_to_parent, strlen(msg_to_parent))
501  != (int)strlen(msg_to_parent))
502  throw(ERROR(errno,"Error writing output to parent"));
503  if (write(exe.err_fd(), msg_to_err, strlen(msg_to_err))
504  != (int)strlen(msg_to_err))
505  throw(ERROR(errno,"Error writing error to parent"));
506 
507  assert(static_cast<std::string>(msg_from_parent) == "Message from parent");
508 
509  exe.exit();
510  }
511 }
512 
513 void test11(void)
514 {
515  execute exe;
516  ofdstream fdout;
517  ifdstream fdin;
518 
519  exe.fork();
520  if (exe.is_parent()) {
521  char const *msg_to_child = "Message from parent";
522  char msg_from_child[4096] = { 0 };
523  char msg_from_err[4096] = { 0 };
524 
525  assert(exe.child_running());
526  assert(!exe.child_exited());
527  assert(!exe.child_exited_normally());
528  assert(!exe.child_signaled());
529  assert(exe.child_exit_code() == 0);
530  assert(exe.child_signal_no() == 0);
531 
532  fdout.attach(exe.in_fd());
533  fdout << msg_to_child;
534  fdout.flush();
535 
536  fdin.attach(exe.out_fd());
537  fdin.get(msg_from_child,4096);
538 
539  if (read(exe.err_fd(), msg_from_err, 4096) == 0)
540  throw(ERROR(errno,"Error reading from child's error pipe"));
541 
542  exe.wait();
543 
544  assert(static_cast<std::string>(msg_from_child) == "Message from child");
545  assert(static_cast<std::string>(msg_from_err) == "Message from child err");
546  assert(!exe.child_running());
547  assert(exe.child_exited());
548  assert(exe.child_exited_normally());
549  assert(!exe.child_signaled());
550  assert(exe.child_exit_code() == 0);
551  assert(exe.child_signal_no() == 0);
552  }
553  else {
554  char msg_from_parent[4096] = { 0 };
555  char const *msg_to_parent = "Message from child";
556  char const *msg_to_err = "Message from child err";
557 
558  if (read(exe.in_fd(), msg_from_parent, 4096) == 0)
559  throw(ERROR(errno,"Error reading input from parent"));
560  if (write(exe.out_fd(), msg_to_parent, strlen(msg_to_parent))
561  != (int)strlen(msg_to_parent))
562  throw(ERROR(errno,"Error writing output to parent"));
563  if (write(exe.err_fd(), msg_to_err, strlen(msg_to_err))
564  != (int)strlen(msg_to_err))
565  throw(ERROR(errno,"Error writing error to parent"));
566 
567  assert(static_cast<std::string>(msg_from_parent) == "Message from parent");
568 
569  exe.exit();
570  }
571 }
572 
573 void test12(void)
574 {
575  execute exe;
576  ofdstream fdout;
577  ifdstream fdin;
578 
579  exe.fork();
580  if (exe.is_parent()) {
581  char const *msg_to_child = "Message from parent";
582  char msg_from_child[4096] = { 0 };
583  char msg_from_err[4096] = { 0 };
584 
585  assert(exe.child_running());
586  assert(!exe.child_exited());
587  assert(!exe.child_exited_normally());
588  assert(!exe.child_signaled());
589  assert(exe.child_exit_code() == 0);
590  assert(exe.child_signal_no() == 0);
591 
592  fdout.attach(exe.in_fd());
593  // fdout << msg_to_child;
594  // fdout.flush();
595  if (write(exe.in_fd(), msg_to_child, strlen(msg_to_child))
596  != (int)strlen(msg_to_child))
597  throw(ERROR(errno,"Error writing to child's input pipe"));
598 
599  fdin.attach(exe.out_fd());
600  // fdin.get(msg_from_child,4096);
601  if (read(exe.out_fd(), msg_from_child, 4096) == 0)
602  throw(ERROR(errno,"Error reading from child's output pipe"));
603 
604  if (read(exe.err_fd(), msg_from_err, 4096) == 0)
605  throw(ERROR(errno,"Error reading from child's error pipe"));
606 
607  exe.wait();
608 
609  assert(static_cast<std::string>(msg_from_child) == "Message from child");
610  assert(static_cast<std::string>(msg_from_err) == "Message from child err");
611  assert(!exe.child_running());
612  assert(exe.child_exited());
613  assert(exe.child_exited_normally());
614  assert(!exe.child_signaled());
615  assert(exe.child_exit_code() == 0);
616  assert(exe.child_signal_no() == 0);
617  }
618  else {
619  char msg_from_parent[4096] = { 0 };
620  char const *msg_to_parent = "Message from child";
621  char const *msg_to_err = "Message from child err";
622 
623  if (read(exe.in_fd(), msg_from_parent, 4096) == 0)
624  throw(ERROR(errno,"Error reading input from parent"));
625  if (write(exe.out_fd(), msg_to_parent, strlen(msg_to_parent))
626  != (int)strlen(msg_to_parent))
627  throw(ERROR(errno,"Error writing output to parent"));
628  if (write(exe.err_fd(), msg_to_err, strlen(msg_to_err))
629  != (int)strlen(msg_to_err))
630  throw(ERROR(errno,"Error writing error to parent"));
631 
632  assert(static_cast<std::string>(msg_from_parent) == "Message from parent");
633 
634  exe.exit();
635  }
636 }
637 
638 void test13(void)
639 {
640  execute exe;
641 
642  exe.fork();
643  if (exe.is_parent()) {
644  char const * msg_to_child = "Message from parent";
645  char msg_from_child[4096] = { 0 };
646  char msg_from_err[4096] = { 0 };
647 
648  assert(exe.child_running());
649  assert(!exe.child_exited());
650  assert(!exe.child_exited_normally());
651  assert(!exe.child_signaled());
652  assert(exe.child_exit_code() == 0);
653  assert(exe.child_signal_no() == 0);
654 
655  assert(exe.in_ready());
656  assert(!exe.out_ready());
657  assert(!exe.err_ready());
658  assert(!exe.in_eof());
659  assert(!exe.out_eof());
660  assert(!exe.err_eof());
661 
662  if (exe.in_write(msg_to_child, strlen(msg_to_child))
663  != (int)strlen(msg_to_child))
664  throw(ERROR(errno,"Error writing to child's input pipe"));
665 
666  // Wait until input is ready from child
667  while (!(exe.out_ready() && exe.err_ready()));
668 
669  assert(exe.in_ready());
670  assert(exe.out_ready());
671  assert(exe.err_ready());
672  assert(!exe.in_eof());
673  assert(!exe.out_eof());
674  assert(!exe.err_eof());
675 
676  if (exe.out_read(msg_from_child, 4096) == 0)
677  throw(ERROR(errno,"Error reading from child's output pipe"));
678 
679  assert(exe.in_ready());
680 
681  assert(!exe.out_ready() || !exe.child_running());
682  assert(exe.err_ready());
683  assert(!exe.in_eof());
684  assert(!exe.out_eof());
685  assert(!exe.err_eof());
686 
687  if (exe.err_read(msg_from_err, 4096) == 0)
688  throw(ERROR(errno,"Error reading from child's error pipe"));
689 
690  while (!exe.out_ready() && !exe.err_ready());
691 
692  assert(exe.in_ready());
693  assert(exe.out_ready());
694  assert(exe.err_ready());
695  assert(!exe.in_eof());
696  assert(!exe.out_eof());
697  assert(!exe.err_eof());
698 
699  exe.wait();
700 
701  assert(exe.in_ready());
702  assert(exe.out_ready());
703  assert(exe.err_ready());
704  assert(!exe.in_eof());
705  assert(!exe.out_eof());
706  assert(!exe.err_eof());
707 
708  assert(static_cast<std::string>(msg_from_child) == "Message from child");
709  assert(static_cast<std::string>(msg_from_err) == "Message from child err");
710 
711  assert(exe.out_read(msg_from_child, 4096) == 0);
712  assert(exe.in_ready());
713  assert(exe.out_ready());
714  assert(exe.err_ready());
715  assert(!exe.in_eof());
716  assert(exe.out_eof());
717  assert(!exe.err_eof());
718 
719  assert(!exe.child_running());
720  assert(exe.child_exited());
721  assert(exe.child_exited_normally());
722  assert(!exe.child_signaled());
723  assert(exe.child_exit_code() == 0);
724  assert(exe.child_signal_no() == 0);
725  }
726  if (exe.is_child()) {
727  char msg_from_parent[4096] = { 0 };
728  char const * msg_to_parent = "Message from child";
729  char const * msg_to_err = "Message from child err";
730 
731  if (read(exe.in_fd(), msg_from_parent, 4096) == 0)
732  throw(ERROR(errno,"Error reading input from parent"));
733  if (write(exe.out_fd(), msg_to_parent, strlen(msg_to_parent))
734  != (int)strlen(msg_to_parent))
735  throw(ERROR(errno,"Error writing output to parent"));
736  if (write(exe.err_fd(), msg_to_err, strlen(msg_to_err))
737  != (int)strlen(msg_to_err))
738  throw(ERROR(errno,"Error writing error to parent"));
739 
740  assert(static_cast<std::string>(msg_from_parent) == "Message from parent");
741 
742  sleep(5);
743  exe.exit();
744  }
745 }
746 
747 int main(int argc, char const * argv[])
748 {
749  try {
750  test1();
751  test2();
752  test3();
753  test4();
754  test5();
755  test6();
756  test7();
757  test8();
758  test9();
759  test10();
760  test11();
761  test12();
762  test13();
763  }
764  catch(error e) {
765  std::cerr << e;
766  assert(0);
767  }
768  catch(...) {
769  std::cerr << err_unknown;
770  assert(0);
771  }
772  return(0);
773 }
774 
void test11(void)
Definition: test-exec.cc:513
int child_signal_no(void)
If the child was signaled, return the signal number.
Definition: exec.cc:284
void test4(void)
Definition: test-exec.cc:213
void test3(void)
Definition: test-exec.cc:111
void test9(void)
Definition: test-exec.cc:404
bool err_eof(void)
Check for err EOF.
Definition: exec.cc:533
bool out_eof(void)
Check for output EOF.
Definition: exec.cc:527
void fork(void)
Fork a child process.
Definition: exec.cc:72
void kill_child(void)
Send a KILL signal to the child.
Definition: exec.cc:188
void test5(void)
Definition: test-exec.cc:243
int err_read(char *buf, const int len)
Allow parent to read from err_fd()
Definition: exec.cc:607
void exit(int code=0)
Called by the child to exit with a particular code.
Definition: exec.cc:130
void signal_child(int signal_no)
Send a signal to the child.
Definition: exec.cc:176
void test7(void)
Definition: test-exec.cc:332
bool err_ready(void)
Check I/O for output.
Definition: exec.cc:508
bool out_ready(void)
Check I/O for output.
Definition: exec.cc:488
bool child_started(void) const
Returns true if the child has been started.
Definition: exec.cc:214
int in_write(const char *buf, const int len)
Allow parent to write output to in_fd()
Definition: exec.cc:556
int out_fd(void)
Return a file descriptor for I/O between parent a child.
Definition: exec.cc:327
void attach(int a_fd)
Definition: fdstream.cc:116
bool child_running(void)
Returns true if the child is running.
Definition: exec.cc:220
#define err_unknown
Definition: error.h:114
bool child_exited_success(void)
Returns true if the child returned exit code 0 and no caught signals.
Definition: exec.cc:263
void test1(void)
Definition: test-exec.cc:19
void test8(void)
Definition: test-exec.cc:362
void exec(const std::string command)
Execute a command, rerouting stdin, stdout, and stderr to parent.
Definition: exec.cc:390
int out_read(char *buf, const int len)
Allow parent to read out_fd()
Definition: exec.cc:573
bool child_signaled(void)
Returns true if the child was signaled.
Definition: exec.cc:252
An error class.
Definition: error.h:72
int child_exit_code(void)
Return the child's exit code.
Definition: exec.cc:273
bool child_exited_normally(void)
Returns true if the child has exited normally.
Definition: exec.cc:242
void test2(void)
Definition: test-exec.cc:53
Fork a child process or execute an external program.
Definition: exec.h:21
void test6(void)
Definition: test-exec.cc:285
bool in_ready(void)
Check I/O for input.
Definition: exec.cc:468
bool in_eof(void)
Check for input EOF.
Definition: exec.cc:521
void test10(void)
Definition: test-exec.cc:450
bool child_exited(void)
Returns true of the child has existed.
Definition: exec.cc:231
int err_fd(void)
Return a file descriptor for I/O between parent and child.
Definition: exec.cc:347
#define ERROR(e, s)
Definition: error.h:120
void test13(void)
Definition: test-exec.cc:638
void test12(void)
Definition: test-exec.cc:573
void wait(void)
Wait for the child to exit.
Definition: exec.cc:194
void attach(int a_fd)
Definition: fdstream.cc:51
bool is_child(void)
Returns true if called by the child.
Definition: exec.cc:101
int main(int argc, char const *argv[])
Definition: test-exec.cc:747
bool is_parent(void)
Returns true if called by the parent.
Definition: exec.cc:110
int in_fd(void)
Return a file descriptor for I/O between parent and child.
Definition: exec.cc:307