1*ee44dd6cSjmmv //
2*ee44dd6cSjmmv // Automated Testing Framework (atf)
3*ee44dd6cSjmmv //
4*ee44dd6cSjmmv // Copyright (c) 2007 The NetBSD Foundation, Inc.
5*ee44dd6cSjmmv // All rights reserved.
6*ee44dd6cSjmmv //
7*ee44dd6cSjmmv // Redistribution and use in source and binary forms, with or without
8*ee44dd6cSjmmv // modification, are permitted provided that the following conditions
9*ee44dd6cSjmmv // are met:
10*ee44dd6cSjmmv // 1. Redistributions of source code must retain the above copyright
11*ee44dd6cSjmmv //    notice, this list of conditions and the following disclaimer.
12*ee44dd6cSjmmv // 2. Redistributions in binary form must reproduce the above copyright
13*ee44dd6cSjmmv //    notice, this list of conditions and the following disclaimer in the
14*ee44dd6cSjmmv //    documentation and/or other materials provided with the distribution.
15*ee44dd6cSjmmv //
16*ee44dd6cSjmmv // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17*ee44dd6cSjmmv // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18*ee44dd6cSjmmv // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19*ee44dd6cSjmmv // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20*ee44dd6cSjmmv // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21*ee44dd6cSjmmv // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*ee44dd6cSjmmv // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23*ee44dd6cSjmmv // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*ee44dd6cSjmmv // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25*ee44dd6cSjmmv // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26*ee44dd6cSjmmv // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27*ee44dd6cSjmmv // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*ee44dd6cSjmmv //
29*ee44dd6cSjmmv 
30*ee44dd6cSjmmv #include <cstring>
31*ee44dd6cSjmmv #include <iostream>
32*ee44dd6cSjmmv 
33*ee44dd6cSjmmv #include <atf-c++.hpp>
34*ee44dd6cSjmmv 
35*ee44dd6cSjmmv #include "config.hpp"
36*ee44dd6cSjmmv #include "env.hpp"
37*ee44dd6cSjmmv #include "exceptions.hpp"
38*ee44dd6cSjmmv 
39*ee44dd6cSjmmv static const char *test_value = "env-value";
40*ee44dd6cSjmmv 
41*ee44dd6cSjmmv static struct varnames {
42*ee44dd6cSjmmv     const char *lc;
43*ee44dd6cSjmmv     const char *uc;
44*ee44dd6cSjmmv     bool can_be_empty;
45*ee44dd6cSjmmv } all_vars[] = {
46*ee44dd6cSjmmv     { "atf_arch",           "ATF_ARCH",           false },
47*ee44dd6cSjmmv     { "atf_build_cc",       "ATF_BUILD_CC",       false },
48*ee44dd6cSjmmv     { "atf_build_cflags",   "ATF_BUILD_CFLAGS",   true  },
49*ee44dd6cSjmmv     { "atf_build_cpp",      "ATF_BUILD_CPP",      false },
50*ee44dd6cSjmmv     { "atf_build_cppflags", "ATF_BUILD_CPPFLAGS", true  },
51*ee44dd6cSjmmv     { "atf_build_cxx",      "ATF_BUILD_CXX",      false },
52*ee44dd6cSjmmv     { "atf_build_cxxflags", "ATF_BUILD_CXXFLAGS", true  },
53*ee44dd6cSjmmv     { "atf_confdir",        "ATF_CONFDIR",        false },
54*ee44dd6cSjmmv     { "atf_includedir",     "ATF_INCLUDEDIR",     false },
55*ee44dd6cSjmmv     { "atf_libdir",         "ATF_LIBDIR",         false },
56*ee44dd6cSjmmv     { "atf_libexecdir",     "ATF_LIBEXECDIR",     false },
57*ee44dd6cSjmmv     { "atf_machine",        "ATF_MACHINE",        false },
58*ee44dd6cSjmmv     { "atf_pkgdatadir",     "ATF_PKGDATADIR",     false },
59*ee44dd6cSjmmv     { "atf_shell",          "ATF_SHELL",          false },
60*ee44dd6cSjmmv     { "atf_workdir",        "ATF_WORKDIR",        false },
61*ee44dd6cSjmmv     { NULL,                 NULL,                 false }
62*ee44dd6cSjmmv };
63*ee44dd6cSjmmv 
64*ee44dd6cSjmmv // ------------------------------------------------------------------------
65*ee44dd6cSjmmv // Auxiliary functions.
66*ee44dd6cSjmmv // ------------------------------------------------------------------------
67*ee44dd6cSjmmv 
68*ee44dd6cSjmmv namespace tools {
69*ee44dd6cSjmmv     namespace config {
70*ee44dd6cSjmmv         void __reinit(void);
71*ee44dd6cSjmmv     }
72*ee44dd6cSjmmv }
73*ee44dd6cSjmmv 
74*ee44dd6cSjmmv static
75*ee44dd6cSjmmv void
set_env_var(const char * name,const char * val)76*ee44dd6cSjmmv set_env_var(const char* name, const char* val)
77*ee44dd6cSjmmv {
78*ee44dd6cSjmmv     try {
79*ee44dd6cSjmmv         tools::env::set(name, val);
80*ee44dd6cSjmmv     } catch (const tools::system_error&) {
81*ee44dd6cSjmmv         ATF_FAIL(std::string("set_env_var(") + name + ", " + val +
82*ee44dd6cSjmmv                  ") failed");
83*ee44dd6cSjmmv     }
84*ee44dd6cSjmmv }
85*ee44dd6cSjmmv 
86*ee44dd6cSjmmv static
87*ee44dd6cSjmmv void
unset_env_var(const char * name)88*ee44dd6cSjmmv unset_env_var(const char* name)
89*ee44dd6cSjmmv {
90*ee44dd6cSjmmv     try {
91*ee44dd6cSjmmv         tools::env::unset(name);
92*ee44dd6cSjmmv     } catch (const tools::system_error&) {
93*ee44dd6cSjmmv         ATF_FAIL(std::string("unset_env_var(") + name + ") failed");
94*ee44dd6cSjmmv     }
95*ee44dd6cSjmmv }
96*ee44dd6cSjmmv 
97*ee44dd6cSjmmv static
98*ee44dd6cSjmmv size_t
all_vars_count(void)99*ee44dd6cSjmmv all_vars_count(void)
100*ee44dd6cSjmmv {
101*ee44dd6cSjmmv     size_t count = 0;
102*ee44dd6cSjmmv     for (const struct varnames* v = all_vars; v->lc != NULL; v++)
103*ee44dd6cSjmmv         count++;
104*ee44dd6cSjmmv     return count;
105*ee44dd6cSjmmv }
106*ee44dd6cSjmmv 
107*ee44dd6cSjmmv static
108*ee44dd6cSjmmv void
unset_all(void)109*ee44dd6cSjmmv unset_all(void)
110*ee44dd6cSjmmv {
111*ee44dd6cSjmmv     for (const struct varnames* v = all_vars; v->lc != NULL; v++)
112*ee44dd6cSjmmv         unset_env_var(v->uc);
113*ee44dd6cSjmmv }
114*ee44dd6cSjmmv 
115*ee44dd6cSjmmv static
116*ee44dd6cSjmmv void
compare_one(const char * var,const char * expvalue)117*ee44dd6cSjmmv compare_one(const char* var, const char* expvalue)
118*ee44dd6cSjmmv {
119*ee44dd6cSjmmv     std::cout << "Checking that " << var << " is set to " << expvalue << "\n";
120*ee44dd6cSjmmv 
121*ee44dd6cSjmmv     for (const struct varnames* v = all_vars; v->lc != NULL; v++) {
122*ee44dd6cSjmmv         if (std::strcmp(v->lc, var) == 0)
123*ee44dd6cSjmmv             ATF_REQUIRE_EQ(tools::config::get(v->lc), test_value);
124*ee44dd6cSjmmv         else
125*ee44dd6cSjmmv             ATF_REQUIRE(tools::config::get(v->lc) != test_value);
126*ee44dd6cSjmmv     }
127*ee44dd6cSjmmv }
128*ee44dd6cSjmmv 
129*ee44dd6cSjmmv // ------------------------------------------------------------------------
130*ee44dd6cSjmmv // Test cases for the free functions.
131*ee44dd6cSjmmv // ------------------------------------------------------------------------
132*ee44dd6cSjmmv 
133*ee44dd6cSjmmv ATF_TEST_CASE(get);
ATF_TEST_CASE_HEAD(get)134*ee44dd6cSjmmv ATF_TEST_CASE_HEAD(get)
135*ee44dd6cSjmmv {
136*ee44dd6cSjmmv     set_md_var("descr", "Tests the config::get function");
137*ee44dd6cSjmmv }
ATF_TEST_CASE_BODY(get)138*ee44dd6cSjmmv ATF_TEST_CASE_BODY(get)
139*ee44dd6cSjmmv {
140*ee44dd6cSjmmv     // Unset all known environment variables and make sure the built-in
141*ee44dd6cSjmmv     // values do not match the bogus value we will use for testing.
142*ee44dd6cSjmmv     unset_all();
143*ee44dd6cSjmmv     tools::config::__reinit();
144*ee44dd6cSjmmv     for (const struct varnames* v = all_vars; v->lc != NULL; v++)
145*ee44dd6cSjmmv         ATF_REQUIRE(tools::config::get(v->lc) != test_value);
146*ee44dd6cSjmmv 
147*ee44dd6cSjmmv     // Test the behavior of empty values.
148*ee44dd6cSjmmv     for (const struct varnames* v = all_vars; v->lc != NULL; v++) {
149*ee44dd6cSjmmv         unset_all();
150*ee44dd6cSjmmv         if (!tools::config::get(v->lc).empty()) {
151*ee44dd6cSjmmv             set_env_var(v->uc, "");
152*ee44dd6cSjmmv             tools::config::__reinit();
153*ee44dd6cSjmmv             if (v->can_be_empty)
154*ee44dd6cSjmmv                 ATF_REQUIRE(tools::config::get(v->lc).empty());
155*ee44dd6cSjmmv             else
156*ee44dd6cSjmmv                 ATF_REQUIRE(!tools::config::get(v->lc).empty());
157*ee44dd6cSjmmv         }
158*ee44dd6cSjmmv     }
159*ee44dd6cSjmmv 
160*ee44dd6cSjmmv     // Check if the ATF_ARCH variable is recognized.
161*ee44dd6cSjmmv     for (const struct varnames* v = all_vars; v->lc != NULL; v++) {
162*ee44dd6cSjmmv         unset_all();
163*ee44dd6cSjmmv         set_env_var(v->uc, test_value);
164*ee44dd6cSjmmv         tools::config::__reinit();
165*ee44dd6cSjmmv         compare_one(v->lc, test_value);
166*ee44dd6cSjmmv     }
167*ee44dd6cSjmmv }
168*ee44dd6cSjmmv 
169*ee44dd6cSjmmv ATF_TEST_CASE(get_all);
ATF_TEST_CASE_HEAD(get_all)170*ee44dd6cSjmmv ATF_TEST_CASE_HEAD(get_all)
171*ee44dd6cSjmmv {
172*ee44dd6cSjmmv     set_md_var("descr", "Tests the config::get_all function");
173*ee44dd6cSjmmv }
ATF_TEST_CASE_BODY(get_all)174*ee44dd6cSjmmv ATF_TEST_CASE_BODY(get_all)
175*ee44dd6cSjmmv {
176*ee44dd6cSjmmv     tools::config::__reinit();
177*ee44dd6cSjmmv 
178*ee44dd6cSjmmv     // Check that the valid variables, and only those, are returned.
179*ee44dd6cSjmmv     std::map< std::string, std::string > vars = tools::config::get_all();
180*ee44dd6cSjmmv     ATF_REQUIRE_EQ(vars.size(), all_vars_count());
181*ee44dd6cSjmmv     for (const struct varnames* v = all_vars; v->lc != NULL; v++)
182*ee44dd6cSjmmv         ATF_REQUIRE(vars.find(v->lc) != vars.end());
183*ee44dd6cSjmmv }
184*ee44dd6cSjmmv 
185*ee44dd6cSjmmv ATF_TEST_CASE(has);
ATF_TEST_CASE_HEAD(has)186*ee44dd6cSjmmv ATF_TEST_CASE_HEAD(has)
187*ee44dd6cSjmmv {
188*ee44dd6cSjmmv     set_md_var("descr", "Tests the config::has function");
189*ee44dd6cSjmmv }
ATF_TEST_CASE_BODY(has)190*ee44dd6cSjmmv ATF_TEST_CASE_BODY(has)
191*ee44dd6cSjmmv {
192*ee44dd6cSjmmv     tools::config::__reinit();
193*ee44dd6cSjmmv 
194*ee44dd6cSjmmv     // Check for all the variables that must exist.
195*ee44dd6cSjmmv     for (const struct varnames* v = all_vars; v->lc != NULL; v++)
196*ee44dd6cSjmmv         ATF_REQUIRE(tools::config::has(v->lc));
197*ee44dd6cSjmmv 
198*ee44dd6cSjmmv     // Same as above, but using uppercase (which is incorrect).
199*ee44dd6cSjmmv     for (const struct varnames* v = all_vars; v->lc != NULL; v++)
200*ee44dd6cSjmmv         ATF_REQUIRE(!tools::config::has(v->uc));
201*ee44dd6cSjmmv 
202*ee44dd6cSjmmv     // Check for some other variables that cannot exist.
203*ee44dd6cSjmmv     ATF_REQUIRE(!tools::config::has("foo"));
204*ee44dd6cSjmmv     ATF_REQUIRE(!tools::config::has("BAR"));
205*ee44dd6cSjmmv     ATF_REQUIRE(!tools::config::has("atf_foo"));
206*ee44dd6cSjmmv     ATF_REQUIRE(!tools::config::has("ATF_BAR"));
207*ee44dd6cSjmmv     ATF_REQUIRE(!tools::config::has("atf_shel"));
208*ee44dd6cSjmmv     ATF_REQUIRE(!tools::config::has("atf_shells"));
209*ee44dd6cSjmmv }
210*ee44dd6cSjmmv 
211*ee44dd6cSjmmv // ------------------------------------------------------------------------
212*ee44dd6cSjmmv // Main.
213*ee44dd6cSjmmv // ------------------------------------------------------------------------
214*ee44dd6cSjmmv 
ATF_INIT_TEST_CASES(tcs)215*ee44dd6cSjmmv ATF_INIT_TEST_CASES(tcs)
216*ee44dd6cSjmmv {
217*ee44dd6cSjmmv     // Add the test cases for the free functions.
218*ee44dd6cSjmmv     ATF_ADD_TEST_CASE(tcs, has);
219*ee44dd6cSjmmv     ATF_ADD_TEST_CASE(tcs, get);
220*ee44dd6cSjmmv     ATF_ADD_TEST_CASE(tcs, get_all);
221*ee44dd6cSjmmv }
222