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