Merge autoconf transition and jaunty build updates.
[third_party/subunit] / c / tests / test_child.c
1 /**
2  *
3  *  subunit C bindings.
4  *  Copyright (C) 2006  Robert Collins <robertc@robertcollins.net>
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 2 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, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  **/
20
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <string.h>
24 #include <check.h>
25
26 #include "subunit/child.h"
27
28 /**
29  * Helper function to capture stdout, run some call, and check what
30  * was written.
31  * @expected the expected stdout content
32  * @function the function to call.
33  **/
34 static void
35 test_stdout_function(char const * expected,
36                      void (*function)(void))
37 {
38     /* test that the start function emits a correct test: line. */
39     int bytecount;
40     int old_stdout;
41     int new_stdout[2];
42     char buffer[100];
43     /* we need a socketpair to capture stdout in */
44     fail_if(pipe(new_stdout), "Failed to create a socketpair.");
45     /* backup stdout so we can replace it */
46     old_stdout = dup(1);
47     if (old_stdout == -1) {
48       close(new_stdout[0]);
49       close(new_stdout[1]);
50       fail("Failed to backup stdout before replacing.");
51     }
52     /* redirect stdout so we can analyse it */
53     if (dup2(new_stdout[1], 1) != 1) {
54       close(old_stdout);
55       close(new_stdout[0]);
56       close(new_stdout[1]);
57       fail("Failed to redirect stdout");
58     }
59     /* yes this can block. Its a test case with < 100 bytes of output.
60      * DEAL.
61      */
62     function();
63     /* restore stdout now */
64     if (dup2(old_stdout, 1) != 1) {
65       close(old_stdout);
66       close(new_stdout[0]);
67       close(new_stdout[1]);
68       fail("Failed to restore stdout");
69     }
70     /* and we dont need the write side any more */
71     if (close(new_stdout[1])) {
72       close(new_stdout[0]);
73       fail("Failed to close write side of socketpair.");
74     }
75     /* get the output */
76     bytecount = read(new_stdout[0], buffer, 100);
77     if (0 > bytecount) {
78       close(new_stdout[0]);
79       fail("Failed to read captured output.");
80     }
81     buffer[bytecount]='\0';
82     /* and we dont need the read side any more */
83     fail_if(close(new_stdout[0]), "Failed to close write side of socketpair.");
84     /* compare with expected outcome */
85     fail_if(strcmp(expected, buffer), "Did not get expected output [%s], got [%s]", expected, buffer);
86 }
87
88
89 static void
90 call_test_start(void)
91 {
92     subunit_test_start("test case");
93 }
94
95
96 START_TEST (test_start)
97 {
98     test_stdout_function("test: test case\n", call_test_start);
99 }
100 END_TEST
101
102
103 static void
104 call_test_pass(void)
105 {
106     subunit_test_pass("test case");
107 }
108
109
110 START_TEST (test_pass)
111 {
112     test_stdout_function("success: test case\n", call_test_pass);
113 }
114 END_TEST
115
116
117 static void
118 call_test_fail(void)
119 {
120     subunit_test_fail("test case", "Multiple lines\n of error\n");
121 }
122
123
124 START_TEST (test_fail)
125 {
126     test_stdout_function("failure: test case [\n"
127                          "Multiple lines\n"
128                          " of error\n"
129                          "]\n",
130                          call_test_fail);
131 }
132 END_TEST
133
134
135 static void
136 call_test_error(void)
137 {
138     subunit_test_error("test case", "Multiple lines\n of output\n");
139 }
140
141
142 START_TEST (test_error)
143 {
144     test_stdout_function("error: test case [\n"
145                          "Multiple lines\n"
146                          " of output\n"
147                          "]\n",
148                          call_test_error);
149 }
150 END_TEST
151
152 static Suite *
153 child_suite(void)
154 {
155     Suite *s = suite_create("subunit_child");
156     TCase *tc_core = tcase_create("Core");
157     suite_add_tcase (s, tc_core);
158     tcase_add_test (tc_core, test_start);
159     tcase_add_test (tc_core, test_pass);
160     tcase_add_test (tc_core, test_fail);
161     tcase_add_test (tc_core, test_error);
162     return s;
163 }
164
165
166 int
167 main(void)
168 {
169   int nf;
170   Suite *s = child_suite();
171   SRunner *sr = srunner_create(s);
172   srunner_run_all(sr, CK_NORMAL);
173   nf = srunner_ntests_failed(sr);
174   srunner_free(sr);
175   return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
176 }