1//
2// Automated Testing Framework (atf)
3//
4// Copyright (c) 2007, 2008, 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 "config.hpp"
34#include "macros.hpp"
35
36#include "detail/env.hpp"
37#include "detail/exceptions.hpp"
38#include "detail/test_helpers.hpp"
39
40static const char *test_value = "env-value";
41
42static struct varnames {
43    const char *lc;
44    const char *uc;
45    bool can_be_empty;
46} all_vars[] = {
47    { "atf_arch",           "ATF_ARCH",           false },
48    { "atf_build_cc",       "ATF_BUILD_CC",       false },
49    { "atf_build_cflags",   "ATF_BUILD_CFLAGS",   true  },
50    { "atf_build_cpp",      "ATF_BUILD_CPP",      false },
51    { "atf_build_cppflags", "ATF_BUILD_CPPFLAGS", true  },
52    { "atf_build_cxx",      "ATF_BUILD_CXX",      false },
53    { "atf_build_cxxflags", "ATF_BUILD_CXXFLAGS", true  },
54    { "atf_confdir",        "ATF_CONFDIR",        false },
55    { "atf_includedir",     "ATF_INCLUDEDIR",     false },
56    { "atf_libdir",         "ATF_LIBDIR",         false },
57    { "atf_libexecdir",     "ATF_LIBEXECDIR",     false },
58    { "atf_machine",        "ATF_MACHINE",        false },
59    { "atf_pkgdatadir",     "ATF_PKGDATADIR",     false },
60    { "atf_shell",          "ATF_SHELL",          false },
61    { "atf_workdir",        "ATF_WORKDIR",        false },
62    { NULL,                 NULL,                 false }
63};
64
65// ------------------------------------------------------------------------
66// Auxiliary functions.
67// ------------------------------------------------------------------------
68
69namespace atf {
70    namespace config {
71        void __reinit(void);
72    }
73}
74
75static
76void
77set_env_var(const char* name, const char* val)
78{
79    try {
80        atf::env::set(name, val);
81    } catch (const atf::system_error&) {
82        ATF_FAIL(std::string("set_env_var(") + name + ", " + val +
83                 ") failed");
84    }
85}
86
87static
88void
89unset_env_var(const char* name)
90{
91    try {
92        atf::env::unset(name);
93    } catch (const atf::system_error&) {
94        ATF_FAIL(std::string("unset_env_var(") + name + ") failed");
95    }
96}
97
98static
99size_t
100all_vars_count(void)
101{
102    size_t count = 0;
103    for (const struct varnames* v = all_vars; v->lc != NULL; v++)
104        count++;
105    return count;
106}
107
108static
109void
110unset_all(void)
111{
112    for (const struct varnames* v = all_vars; v->lc != NULL; v++)
113        unset_env_var(v->uc);
114}
115
116static
117void
118compare_one(const char* var, const char* expvalue)
119{
120    std::cout << "Checking that " << var << " is set to " << expvalue << "\n";
121
122    for (const struct varnames* v = all_vars; v->lc != NULL; v++) {
123        if (std::strcmp(v->lc, var) == 0)
124            ATF_REQUIRE_EQ(atf::config::get(v->lc), test_value);
125        else
126            ATF_REQUIRE(atf::config::get(v->lc) != test_value);
127    }
128}
129
130// ------------------------------------------------------------------------
131// Test cases for the free functions.
132// ------------------------------------------------------------------------
133
134ATF_TEST_CASE(get);
135ATF_TEST_CASE_HEAD(get)
136{
137    set_md_var("descr", "Tests the config::get function");
138}
139ATF_TEST_CASE_BODY(get)
140{
141    // Unset all known environment variables and make sure the built-in
142    // values do not match the bogus value we will use for testing.
143    unset_all();
144    atf::config::__reinit();
145    for (const struct varnames* v = all_vars; v->lc != NULL; v++)
146        ATF_REQUIRE(atf::config::get(v->lc) != test_value);
147
148    // Test the behavior of empty values.
149    for (const struct varnames* v = all_vars; v->lc != NULL; v++) {
150        unset_all();
151        if (!atf::config::get(v->lc).empty()) {
152            set_env_var(v->uc, "");
153            atf::config::__reinit();
154            if (v->can_be_empty)
155                ATF_REQUIRE(atf::config::get(v->lc).empty());
156            else
157                ATF_REQUIRE(!atf::config::get(v->lc).empty());
158        }
159    }
160
161    // Check if the ATF_ARCH variable is recognized.
162    for (const struct varnames* v = all_vars; v->lc != NULL; v++) {
163        unset_all();
164        set_env_var(v->uc, test_value);
165        atf::config::__reinit();
166        compare_one(v->lc, test_value);
167    }
168}
169
170ATF_TEST_CASE(get_all);
171ATF_TEST_CASE_HEAD(get_all)
172{
173    set_md_var("descr", "Tests the config::get_all function");
174}
175ATF_TEST_CASE_BODY(get_all)
176{
177    atf::config::__reinit();
178
179    // Check that the valid variables, and only those, are returned.
180    std::map< std::string, std::string > vars = atf::config::get_all();
181    ATF_REQUIRE_EQ(vars.size(), all_vars_count());
182    for (const struct varnames* v = all_vars; v->lc != NULL; v++)
183        ATF_REQUIRE(vars.find(v->lc) != vars.end());
184}
185
186ATF_TEST_CASE(has);
187ATF_TEST_CASE_HEAD(has)
188{
189    set_md_var("descr", "Tests the config::has function");
190}
191ATF_TEST_CASE_BODY(has)
192{
193    atf::config::__reinit();
194
195    // Check for all the variables that must exist.
196    for (const struct varnames* v = all_vars; v->lc != NULL; v++)
197        ATF_REQUIRE(atf::config::has(v->lc));
198
199    // Same as above, but using uppercase (which is incorrect).
200    for (const struct varnames* v = all_vars; v->lc != NULL; v++)
201        ATF_REQUIRE(!atf::config::has(v->uc));
202
203    // Check for some other variables that cannot exist.
204    ATF_REQUIRE(!atf::config::has("foo"));
205    ATF_REQUIRE(!atf::config::has("BAR"));
206    ATF_REQUIRE(!atf::config::has("atf_foo"));
207    ATF_REQUIRE(!atf::config::has("ATF_BAR"));
208    ATF_REQUIRE(!atf::config::has("atf_shel"));
209    ATF_REQUIRE(!atf::config::has("atf_shells"));
210}
211
212// ------------------------------------------------------------------------
213// Tests cases for the header file.
214// ------------------------------------------------------------------------
215
216HEADER_TC(include, "atf-c++/config.hpp");
217
218// ------------------------------------------------------------------------
219// Main.
220// ------------------------------------------------------------------------
221
222ATF_INIT_TEST_CASES(tcs)
223{
224    // Add the test cases for the free functions.
225    ATF_ADD_TEST_CASE(tcs, has);
226    ATF_ADD_TEST_CASE(tcs, get);
227    ATF_ADD_TEST_CASE(tcs, get_all);
228
229    // Add the test cases for the header file.
230    ATF_ADD_TEST_CASE(tcs, include);
231}
232