1 /* Copyright (c) 2009 The NetBSD Foundation, Inc.
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
14  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
15  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */
25 
26 #include "atf-c/build.h"
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #include <atf-c.h>
33 
34 #include "atf-c/detail/env.h"
35 #include "atf-c/detail/test_helpers.h"
36 #include "atf-c/h_build.h"
37 #include "atf-c/utils.h"
38 
39 /* ---------------------------------------------------------------------
40  * Auxiliary functions.
41  * --------------------------------------------------------------------- */
42 
43 static
44 bool
equal_arrays(const char * const * exp_array,char ** actual_array)45 equal_arrays(const char *const *exp_array, char **actual_array)
46 {
47     bool equal;
48 
49     if (*exp_array == NULL && *actual_array == NULL)
50         equal = true;
51     else if (*exp_array == NULL || *actual_array == NULL)
52         equal = false;
53     else {
54         equal = true;
55         while (*actual_array != NULL) {
56             if (*exp_array == NULL || strcmp(*exp_array, *actual_array) != 0) {
57                 equal = false;
58                 break;
59             }
60             exp_array++;
61             actual_array++;
62         }
63     }
64 
65     return equal;
66 }
67 
68 static
69 void
check_equal_array(const char * const * exp_array,char ** actual_array)70 check_equal_array(const char *const *exp_array, char **actual_array)
71 {
72     {
73         const char *const *exp_ptr;
74         printf("Expected arguments:");
75         for (exp_ptr = exp_array; *exp_ptr != NULL; exp_ptr++)
76             printf(" '%s'", *exp_ptr);
77         printf("\n");
78     }
79 
80     {
81         char **actual_ptr;
82         printf("Returned arguments:");
83         for (actual_ptr = actual_array; *actual_ptr != NULL; actual_ptr++)
84             printf(" '%s'", *actual_ptr);
85         printf("\n");
86     }
87 
88     if (!equal_arrays(exp_array, actual_array))
89         atf_tc_fail_nonfatal("The constructed argv differs from the "
90                              "expected values");
91 }
92 
93 static
94 void
verbose_set_env(const char * var,const char * val)95 verbose_set_env(const char *var, const char *val)
96 {
97     printf("Setting %s to '%s'\n", var, val);
98     RE(atf_env_set(var, val));
99 }
100 
101 /* ---------------------------------------------------------------------
102  * Internal test cases.
103  * --------------------------------------------------------------------- */
104 
105 ATF_TC(equal_arrays);
ATF_TC_HEAD(equal_arrays,tc)106 ATF_TC_HEAD(equal_arrays, tc)
107 {
108     atf_tc_set_md_var(tc, "descr", "Tests the test case internal "
109                       "equal_arrays function");
110 }
ATF_TC_BODY(equal_arrays,tc)111 ATF_TC_BODY(equal_arrays, tc)
112 {
113     {
114         const char *const exp[] = { NULL };
115         char *actual[] = { NULL };
116 
117         ATF_CHECK(equal_arrays(exp, actual));
118     }
119 
120     {
121         const char *const exp[] = { NULL };
122         char *actual[2] = { strdup("foo"), NULL };
123 
124         ATF_CHECK(!equal_arrays(exp, actual));
125         free(actual[0]);
126     }
127 
128     {
129         const char *const exp[] = { "foo", NULL };
130         char *actual[] = { NULL };
131 
132         ATF_CHECK(!equal_arrays(exp, actual));
133     }
134 
135     {
136         const char *const exp[] = { "foo", NULL };
137         char *actual[2] = { strdup("foo"), NULL };
138 
139         ATF_CHECK(equal_arrays(exp, actual));
140         free(actual[0]);
141     }
142 }
143 
144 /* ---------------------------------------------------------------------
145  * Test cases for the free functions.
146  * --------------------------------------------------------------------- */
147 
148 ATF_TC(c_o);
ATF_TC_HEAD(c_o,tc)149 ATF_TC_HEAD(c_o, tc)
150 {
151     atf_tc_set_md_var(tc, "descr", "Tests the atf_build_c_o function");
152 }
ATF_TC_BODY(c_o,tc)153 ATF_TC_BODY(c_o, tc)
154 {
155     struct c_o_test *test;
156 
157     for (test = c_o_tests; test->expargv[0] != NULL; test++) {
158         printf("> Test: %s\n", test->msg);
159 
160         verbose_set_env("ATF_BUILD_CC", test->cc);
161         verbose_set_env("ATF_BUILD_CFLAGS", test->cflags);
162         verbose_set_env("ATF_BUILD_CPPFLAGS", test->cppflags);
163 
164         {
165             char **argv;
166             if (test->hasoptargs)
167                 RE(atf_build_c_o(test->sfile, test->ofile, test->optargs,
168                                  &argv));
169             else
170                 RE(atf_build_c_o(test->sfile, test->ofile, NULL, &argv));
171             check_equal_array(test->expargv, argv);
172             atf_utils_free_charpp(argv);
173         }
174     }
175 }
176 
177 ATF_TC(cpp);
ATF_TC_HEAD(cpp,tc)178 ATF_TC_HEAD(cpp, tc)
179 {
180     atf_tc_set_md_var(tc, "descr", "Tests the atf_build_cpp function");
181 }
ATF_TC_BODY(cpp,tc)182 ATF_TC_BODY(cpp, tc)
183 {
184     struct cpp_test *test;
185 
186     for (test = cpp_tests; test->expargv[0] != NULL; test++) {
187         printf("> Test: %s\n", test->msg);
188 
189         verbose_set_env("ATF_BUILD_CPP", test->cpp);
190         verbose_set_env("ATF_BUILD_CPPFLAGS", test->cppflags);
191 
192         {
193             char **argv;
194             if (test->hasoptargs)
195                 RE(atf_build_cpp(test->sfile, test->ofile, test->optargs,
196                                  &argv));
197             else
198                 RE(atf_build_cpp(test->sfile, test->ofile, NULL, &argv));
199             check_equal_array(test->expargv, argv);
200             atf_utils_free_charpp(argv);
201         }
202     }
203 }
204 
205 ATF_TC(cxx_o);
ATF_TC_HEAD(cxx_o,tc)206 ATF_TC_HEAD(cxx_o, tc)
207 {
208     atf_tc_set_md_var(tc, "descr", "Tests the atf_build_cxx_o function");
209 }
ATF_TC_BODY(cxx_o,tc)210 ATF_TC_BODY(cxx_o, tc)
211 {
212     struct cxx_o_test *test;
213 
214     for (test = cxx_o_tests; test->expargv[0] != NULL; test++) {
215         printf("> Test: %s\n", test->msg);
216 
217         verbose_set_env("ATF_BUILD_CXX", test->cxx);
218         verbose_set_env("ATF_BUILD_CXXFLAGS", test->cxxflags);
219         verbose_set_env("ATF_BUILD_CPPFLAGS", test->cppflags);
220 
221         {
222             char **argv;
223             if (test->hasoptargs)
224                 RE(atf_build_cxx_o(test->sfile, test->ofile, test->optargs,
225                                    &argv));
226             else
227                 RE(atf_build_cxx_o(test->sfile, test->ofile, NULL, &argv));
228             check_equal_array(test->expargv, argv);
229             atf_utils_free_charpp(argv);
230         }
231     }
232 }
233 
234 /* ---------------------------------------------------------------------
235  * Main.
236  * --------------------------------------------------------------------- */
237 
ATF_TP_ADD_TCS(tp)238 ATF_TP_ADD_TCS(tp)
239 {
240     /* Add the internal test cases. */
241     ATF_TP_ADD_TC(tp, equal_arrays);
242 
243     /* Add the test cases for the free functions. */
244     ATF_TP_ADD_TC(tp, c_o);
245     ATF_TP_ADD_TC(tp, cpp);
246     ATF_TP_ADD_TC(tp, cxx_o);
247 
248     return atf_no_error();
249 }
250