1318322ab20dfb121511245f7031596757b1a2e4
[amitay/samba.git] / lib / subunit / c / tests / test_child.c
1 /**
2  *
3  *  subunit C bindings.
4  *  Copyright (C) 2006  Robert Collins <robertc@robertcollins.net>
5  *
6  *  Licensed under either the Apache License, Version 2.0 or the BSD 3-clause
7  *  license at the users choice. A copy of both licenses are available in the
8  *  project source as Apache-2.0 and BSD. You may not use this file except in
9  *  compliance with one of these two licences.
10  *  
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under these licenses is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the license you chose for the specific language governing permissions
15  *  and limitations under that license.
16  **/
17
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <unistd.h>
21 #include <string.h>
22 #include <check.h>
23
24 #include "subunit/child.h"
25
26 /**
27  * Helper function to capture stdout, run some call, and check what
28  * was written.
29  * @expected the expected stdout content
30  * @function the function to call.
31  **/
32 static void
33 test_stdout_function(char const * expected,
34                      void (*function)(void))
35 {
36     /* test that the start function emits a correct test: line. */
37     int bytecount;
38     int old_stdout;
39     int new_stdout[2];
40     char buffer[100];
41     /* we need a socketpair to capture stdout in */
42     fail_if(pipe(new_stdout), "Failed to create a socketpair.");
43     /* backup stdout so we can replace it */
44     old_stdout = dup(1);
45     if (old_stdout == -1) {
46       close(new_stdout[0]);
47       close(new_stdout[1]);
48       fail("Failed to backup stdout before replacing.");
49     }
50     /* redirect stdout so we can analyse it */
51     if (dup2(new_stdout[1], 1) != 1) {
52       close(old_stdout);
53       close(new_stdout[0]);
54       close(new_stdout[1]);
55       fail("Failed to redirect stdout");
56     }
57     /* yes this can block. Its a test case with < 100 bytes of output.
58      * DEAL.
59      */
60     function();
61     /* flush writes on FILE object to file descriptor */
62     fflush(stdout);
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
153 static void
154 call_test_skip(void)
155 {
156     subunit_test_skip("test case", "Multiple lines\n of output\n");
157 }
158
159
160 START_TEST (test_skip)
161 {
162     test_stdout_function("skip: test case [\n"
163                          "Multiple lines\n"
164                          " of output\n"
165                          "]\n",
166                          call_test_skip);
167 }
168 END_TEST
169
170
171 static void
172 call_test_progress_pop(void)
173 {
174         subunit_progress(SUBUNIT_PROGRESS_POP, 0);
175 }
176
177 static void
178 call_test_progress_set(void)
179 {
180         subunit_progress(SUBUNIT_PROGRESS_SET, 5);
181 }
182
183 static void
184 call_test_progress_push(void)
185 {
186         subunit_progress(SUBUNIT_PROGRESS_PUSH, 0);
187 }
188
189 static void
190 call_test_progress_cur(void)
191 {
192         subunit_progress(SUBUNIT_PROGRESS_CUR, -6);
193 }
194
195 START_TEST (test_progress)
196 {
197         test_stdout_function("progress: pop\n",
198                          call_test_progress_pop);
199         test_stdout_function("progress: push\n",
200                          call_test_progress_push);
201         test_stdout_function("progress: 5\n",
202                          call_test_progress_set);
203         test_stdout_function("progress: -6\n",
204                          call_test_progress_cur);
205 }
206 END_TEST
207
208 static Suite *
209 child_suite(void)
210 {
211     Suite *s = suite_create("subunit_child");
212     TCase *tc_core = tcase_create("Core");
213     suite_add_tcase (s, tc_core);
214     tcase_add_test (tc_core, test_start);
215     tcase_add_test (tc_core, test_pass);
216     tcase_add_test (tc_core, test_fail);
217     tcase_add_test (tc_core, test_error);
218     tcase_add_test (tc_core, test_skip);
219     tcase_add_test (tc_core, test_progress);
220     return s;
221 }
222
223
224 int
225 main(void)
226 {
227   int nf;
228   Suite *s = child_suite();
229   SRunner *sr = srunner_create(s);
230   srunner_run_all(sr, CK_NORMAL);
231   nf = srunner_ntests_failed(sr);
232   srunner_free(sr);
233   return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
234 }