1*00b67f09SDavid van Moolenbroek //
2*00b67f09SDavid van Moolenbroek // Automated Testing Framework (atf)
3*00b67f09SDavid van Moolenbroek //
4*00b67f09SDavid van Moolenbroek // Copyright (c) 2007 The NetBSD Foundation, Inc.
5*00b67f09SDavid van Moolenbroek // All rights reserved.
6*00b67f09SDavid van Moolenbroek //
7*00b67f09SDavid van Moolenbroek // Redistribution and use in source and binary forms, with or without
8*00b67f09SDavid van Moolenbroek // modification, are permitted provided that the following conditions
9*00b67f09SDavid van Moolenbroek // are met:
10*00b67f09SDavid van Moolenbroek // 1. Redistributions of source code must retain the above copyright
11*00b67f09SDavid van Moolenbroek // notice, this list of conditions and the following disclaimer.
12*00b67f09SDavid van Moolenbroek // 2. Redistributions in binary form must reproduce the above copyright
13*00b67f09SDavid van Moolenbroek // notice, this list of conditions and the following disclaimer in the
14*00b67f09SDavid van Moolenbroek // documentation and/or other materials provided with the distribution.
15*00b67f09SDavid van Moolenbroek //
16*00b67f09SDavid van Moolenbroek // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17*00b67f09SDavid van Moolenbroek // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18*00b67f09SDavid van Moolenbroek // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19*00b67f09SDavid van Moolenbroek // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20*00b67f09SDavid van Moolenbroek // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21*00b67f09SDavid van Moolenbroek // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*00b67f09SDavid van Moolenbroek // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23*00b67f09SDavid van Moolenbroek // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*00b67f09SDavid van Moolenbroek // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25*00b67f09SDavid van Moolenbroek // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26*00b67f09SDavid van Moolenbroek // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27*00b67f09SDavid van Moolenbroek // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*00b67f09SDavid van Moolenbroek //
29*00b67f09SDavid van Moolenbroek
30*00b67f09SDavid van Moolenbroek extern "C" {
31*00b67f09SDavid van Moolenbroek #include <sys/types.h>
32*00b67f09SDavid van Moolenbroek #include <sys/stat.h>
33*00b67f09SDavid van Moolenbroek #include <sys/time.h>
34*00b67f09SDavid van Moolenbroek #include <sys/wait.h>
35*00b67f09SDavid van Moolenbroek #include <signal.h>
36*00b67f09SDavid van Moolenbroek #include <unistd.h>
37*00b67f09SDavid van Moolenbroek }
38*00b67f09SDavid van Moolenbroek
39*00b67f09SDavid van Moolenbroek #include <algorithm>
40*00b67f09SDavid van Moolenbroek #include <cctype>
41*00b67f09SDavid van Moolenbroek #include <cerrno>
42*00b67f09SDavid van Moolenbroek #include <cstdlib>
43*00b67f09SDavid van Moolenbroek #include <cstring>
44*00b67f09SDavid van Moolenbroek #include <fstream>
45*00b67f09SDavid van Moolenbroek #include <iostream>
46*00b67f09SDavid van Moolenbroek #include <map>
47*00b67f09SDavid van Moolenbroek #include <memory>
48*00b67f09SDavid van Moolenbroek #include <sstream>
49*00b67f09SDavid van Moolenbroek #include <stdexcept>
50*00b67f09SDavid van Moolenbroek #include <vector>
51*00b67f09SDavid van Moolenbroek
52*00b67f09SDavid van Moolenbroek extern "C" {
53*00b67f09SDavid van Moolenbroek #include "atf-c/error.h"
54*00b67f09SDavid van Moolenbroek #include "atf-c/tc.h"
55*00b67f09SDavid van Moolenbroek #include "atf-c/utils.h"
56*00b67f09SDavid van Moolenbroek }
57*00b67f09SDavid van Moolenbroek
58*00b67f09SDavid van Moolenbroek #include "noncopyable.hpp"
59*00b67f09SDavid van Moolenbroek #include "tests.hpp"
60*00b67f09SDavid van Moolenbroek
61*00b67f09SDavid van Moolenbroek #include "detail/application.hpp"
62*00b67f09SDavid van Moolenbroek #include "detail/auto_array.hpp"
63*00b67f09SDavid van Moolenbroek #include "detail/env.hpp"
64*00b67f09SDavid van Moolenbroek #include "detail/exceptions.hpp"
65*00b67f09SDavid van Moolenbroek #include "detail/fs.hpp"
66*00b67f09SDavid van Moolenbroek #include "detail/parser.hpp"
67*00b67f09SDavid van Moolenbroek #include "detail/sanity.hpp"
68*00b67f09SDavid van Moolenbroek #include "detail/text.hpp"
69*00b67f09SDavid van Moolenbroek
70*00b67f09SDavid van Moolenbroek namespace impl = atf::tests;
71*00b67f09SDavid van Moolenbroek namespace detail = atf::tests::detail;
72*00b67f09SDavid van Moolenbroek #define IMPL_NAME "atf::tests"
73*00b67f09SDavid van Moolenbroek
74*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
75*00b67f09SDavid van Moolenbroek // The "atf_tp_writer" class.
76*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
77*00b67f09SDavid van Moolenbroek
atf_tp_writer(std::ostream & os)78*00b67f09SDavid van Moolenbroek detail::atf_tp_writer::atf_tp_writer(std::ostream& os) :
79*00b67f09SDavid van Moolenbroek m_os(os),
80*00b67f09SDavid van Moolenbroek m_is_first(true)
81*00b67f09SDavid van Moolenbroek {
82*00b67f09SDavid van Moolenbroek atf::parser::headers_map hm;
83*00b67f09SDavid van Moolenbroek atf::parser::attrs_map ct_attrs;
84*00b67f09SDavid van Moolenbroek ct_attrs["version"] = "1";
85*00b67f09SDavid van Moolenbroek hm["Content-Type"] = atf::parser::header_entry("Content-Type",
86*00b67f09SDavid van Moolenbroek "application/X-atf-tp", ct_attrs);
87*00b67f09SDavid van Moolenbroek atf::parser::write_headers(hm, m_os);
88*00b67f09SDavid van Moolenbroek }
89*00b67f09SDavid van Moolenbroek
90*00b67f09SDavid van Moolenbroek void
start_tc(const std::string & ident)91*00b67f09SDavid van Moolenbroek detail::atf_tp_writer::start_tc(const std::string& ident)
92*00b67f09SDavid van Moolenbroek {
93*00b67f09SDavid van Moolenbroek if (!m_is_first)
94*00b67f09SDavid van Moolenbroek m_os << "\n";
95*00b67f09SDavid van Moolenbroek m_os << "ident: " << ident << "\n";
96*00b67f09SDavid van Moolenbroek m_os.flush();
97*00b67f09SDavid van Moolenbroek }
98*00b67f09SDavid van Moolenbroek
99*00b67f09SDavid van Moolenbroek void
end_tc(void)100*00b67f09SDavid van Moolenbroek detail::atf_tp_writer::end_tc(void)
101*00b67f09SDavid van Moolenbroek {
102*00b67f09SDavid van Moolenbroek if (m_is_first)
103*00b67f09SDavid van Moolenbroek m_is_first = false;
104*00b67f09SDavid van Moolenbroek }
105*00b67f09SDavid van Moolenbroek
106*00b67f09SDavid van Moolenbroek void
tc_meta_data(const std::string & name,const std::string & value)107*00b67f09SDavid van Moolenbroek detail::atf_tp_writer::tc_meta_data(const std::string& name,
108*00b67f09SDavid van Moolenbroek const std::string& value)
109*00b67f09SDavid van Moolenbroek {
110*00b67f09SDavid van Moolenbroek PRE(name != "ident");
111*00b67f09SDavid van Moolenbroek m_os << name << ": " << value << "\n";
112*00b67f09SDavid van Moolenbroek m_os.flush();
113*00b67f09SDavid van Moolenbroek }
114*00b67f09SDavid van Moolenbroek
115*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
116*00b67f09SDavid van Moolenbroek // Free helper functions.
117*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
118*00b67f09SDavid van Moolenbroek
119*00b67f09SDavid van Moolenbroek bool
match(const std::string & regexp,const std::string & str)120*00b67f09SDavid van Moolenbroek detail::match(const std::string& regexp, const std::string& str)
121*00b67f09SDavid van Moolenbroek {
122*00b67f09SDavid van Moolenbroek return atf::text::match(str, regexp);
123*00b67f09SDavid van Moolenbroek }
124*00b67f09SDavid van Moolenbroek
125*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
126*00b67f09SDavid van Moolenbroek // The "tc" class.
127*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
128*00b67f09SDavid van Moolenbroek
129*00b67f09SDavid van Moolenbroek static std::map< atf_tc_t*, impl::tc* > wraps;
130*00b67f09SDavid van Moolenbroek static std::map< const atf_tc_t*, const impl::tc* > cwraps;
131*00b67f09SDavid van Moolenbroek
132*00b67f09SDavid van Moolenbroek struct impl::tc_impl : atf::noncopyable {
133*00b67f09SDavid van Moolenbroek std::string m_ident;
134*00b67f09SDavid van Moolenbroek atf_tc_t m_tc;
135*00b67f09SDavid van Moolenbroek bool m_has_cleanup;
136*00b67f09SDavid van Moolenbroek
tc_implimpl::tc_impl137*00b67f09SDavid van Moolenbroek tc_impl(const std::string& ident, const bool has_cleanup) :
138*00b67f09SDavid van Moolenbroek m_ident(ident),
139*00b67f09SDavid van Moolenbroek m_has_cleanup(has_cleanup)
140*00b67f09SDavid van Moolenbroek {
141*00b67f09SDavid van Moolenbroek }
142*00b67f09SDavid van Moolenbroek
143*00b67f09SDavid van Moolenbroek static void
wrap_headimpl::tc_impl144*00b67f09SDavid van Moolenbroek wrap_head(atf_tc_t *tc)
145*00b67f09SDavid van Moolenbroek {
146*00b67f09SDavid van Moolenbroek std::map< atf_tc_t*, impl::tc* >::iterator iter = wraps.find(tc);
147*00b67f09SDavid van Moolenbroek INV(iter != wraps.end());
148*00b67f09SDavid van Moolenbroek (*iter).second->head();
149*00b67f09SDavid van Moolenbroek }
150*00b67f09SDavid van Moolenbroek
151*00b67f09SDavid van Moolenbroek static void
wrap_bodyimpl::tc_impl152*00b67f09SDavid van Moolenbroek wrap_body(const atf_tc_t *tc)
153*00b67f09SDavid van Moolenbroek {
154*00b67f09SDavid van Moolenbroek std::map< const atf_tc_t*, const impl::tc* >::const_iterator iter =
155*00b67f09SDavid van Moolenbroek cwraps.find(tc);
156*00b67f09SDavid van Moolenbroek INV(iter != cwraps.end());
157*00b67f09SDavid van Moolenbroek try {
158*00b67f09SDavid van Moolenbroek (*iter).second->body();
159*00b67f09SDavid van Moolenbroek } catch (const std::exception& e) {
160*00b67f09SDavid van Moolenbroek (*iter).second->fail("Caught unhandled exception: " + std::string(
161*00b67f09SDavid van Moolenbroek e.what()));
162*00b67f09SDavid van Moolenbroek } catch (...) {
163*00b67f09SDavid van Moolenbroek (*iter).second->fail("Caught unknown exception");
164*00b67f09SDavid van Moolenbroek }
165*00b67f09SDavid van Moolenbroek }
166*00b67f09SDavid van Moolenbroek
167*00b67f09SDavid van Moolenbroek static void
wrap_cleanupimpl::tc_impl168*00b67f09SDavid van Moolenbroek wrap_cleanup(const atf_tc_t *tc)
169*00b67f09SDavid van Moolenbroek {
170*00b67f09SDavid van Moolenbroek std::map< const atf_tc_t*, const impl::tc* >::const_iterator iter =
171*00b67f09SDavid van Moolenbroek cwraps.find(tc);
172*00b67f09SDavid van Moolenbroek INV(iter != cwraps.end());
173*00b67f09SDavid van Moolenbroek (*iter).second->cleanup();
174*00b67f09SDavid van Moolenbroek }
175*00b67f09SDavid van Moolenbroek };
176*00b67f09SDavid van Moolenbroek
tc(const std::string & ident,const bool has_cleanup)177*00b67f09SDavid van Moolenbroek impl::tc::tc(const std::string& ident, const bool has_cleanup) :
178*00b67f09SDavid van Moolenbroek pimpl(new tc_impl(ident, has_cleanup))
179*00b67f09SDavid van Moolenbroek {
180*00b67f09SDavid van Moolenbroek }
181*00b67f09SDavid van Moolenbroek
~tc(void)182*00b67f09SDavid van Moolenbroek impl::tc::~tc(void)
183*00b67f09SDavid van Moolenbroek {
184*00b67f09SDavid van Moolenbroek cwraps.erase(&pimpl->m_tc);
185*00b67f09SDavid van Moolenbroek wraps.erase(&pimpl->m_tc);
186*00b67f09SDavid van Moolenbroek
187*00b67f09SDavid van Moolenbroek atf_tc_fini(&pimpl->m_tc);
188*00b67f09SDavid van Moolenbroek }
189*00b67f09SDavid van Moolenbroek
190*00b67f09SDavid van Moolenbroek void
init(const vars_map & config)191*00b67f09SDavid van Moolenbroek impl::tc::init(const vars_map& config)
192*00b67f09SDavid van Moolenbroek {
193*00b67f09SDavid van Moolenbroek atf_error_t err;
194*00b67f09SDavid van Moolenbroek
195*00b67f09SDavid van Moolenbroek auto_array< const char * > array(new const char*[(config.size() * 2) + 1]);
196*00b67f09SDavid van Moolenbroek const char **ptr = array.get();
197*00b67f09SDavid van Moolenbroek for (vars_map::const_iterator iter = config.begin();
198*00b67f09SDavid van Moolenbroek iter != config.end(); iter++) {
199*00b67f09SDavid van Moolenbroek *ptr = (*iter).first.c_str();
200*00b67f09SDavid van Moolenbroek *(ptr + 1) = (*iter).second.c_str();
201*00b67f09SDavid van Moolenbroek ptr += 2;
202*00b67f09SDavid van Moolenbroek }
203*00b67f09SDavid van Moolenbroek *ptr = NULL;
204*00b67f09SDavid van Moolenbroek
205*00b67f09SDavid van Moolenbroek wraps[&pimpl->m_tc] = this;
206*00b67f09SDavid van Moolenbroek cwraps[&pimpl->m_tc] = this;
207*00b67f09SDavid van Moolenbroek
208*00b67f09SDavid van Moolenbroek err = atf_tc_init(&pimpl->m_tc, pimpl->m_ident.c_str(), pimpl->wrap_head,
209*00b67f09SDavid van Moolenbroek pimpl->wrap_body, pimpl->m_has_cleanup ? pimpl->wrap_cleanup : NULL,
210*00b67f09SDavid van Moolenbroek array.get());
211*00b67f09SDavid van Moolenbroek if (atf_is_error(err))
212*00b67f09SDavid van Moolenbroek throw_atf_error(err);
213*00b67f09SDavid van Moolenbroek }
214*00b67f09SDavid van Moolenbroek
215*00b67f09SDavid van Moolenbroek bool
has_config_var(const std::string & var) const216*00b67f09SDavid van Moolenbroek impl::tc::has_config_var(const std::string& var)
217*00b67f09SDavid van Moolenbroek const
218*00b67f09SDavid van Moolenbroek {
219*00b67f09SDavid van Moolenbroek return atf_tc_has_config_var(&pimpl->m_tc, var.c_str());
220*00b67f09SDavid van Moolenbroek }
221*00b67f09SDavid van Moolenbroek
222*00b67f09SDavid van Moolenbroek bool
has_md_var(const std::string & var) const223*00b67f09SDavid van Moolenbroek impl::tc::has_md_var(const std::string& var)
224*00b67f09SDavid van Moolenbroek const
225*00b67f09SDavid van Moolenbroek {
226*00b67f09SDavid van Moolenbroek return atf_tc_has_md_var(&pimpl->m_tc, var.c_str());
227*00b67f09SDavid van Moolenbroek }
228*00b67f09SDavid van Moolenbroek
229*00b67f09SDavid van Moolenbroek const std::string
get_config_var(const std::string & var) const230*00b67f09SDavid van Moolenbroek impl::tc::get_config_var(const std::string& var)
231*00b67f09SDavid van Moolenbroek const
232*00b67f09SDavid van Moolenbroek {
233*00b67f09SDavid van Moolenbroek return atf_tc_get_config_var(&pimpl->m_tc, var.c_str());
234*00b67f09SDavid van Moolenbroek }
235*00b67f09SDavid van Moolenbroek
236*00b67f09SDavid van Moolenbroek const std::string
get_config_var(const std::string & var,const std::string & defval) const237*00b67f09SDavid van Moolenbroek impl::tc::get_config_var(const std::string& var, const std::string& defval)
238*00b67f09SDavid van Moolenbroek const
239*00b67f09SDavid van Moolenbroek {
240*00b67f09SDavid van Moolenbroek return atf_tc_get_config_var_wd(&pimpl->m_tc, var.c_str(), defval.c_str());
241*00b67f09SDavid van Moolenbroek }
242*00b67f09SDavid van Moolenbroek
243*00b67f09SDavid van Moolenbroek const std::string
get_md_var(const std::string & var) const244*00b67f09SDavid van Moolenbroek impl::tc::get_md_var(const std::string& var)
245*00b67f09SDavid van Moolenbroek const
246*00b67f09SDavid van Moolenbroek {
247*00b67f09SDavid van Moolenbroek return atf_tc_get_md_var(&pimpl->m_tc, var.c_str());
248*00b67f09SDavid van Moolenbroek }
249*00b67f09SDavid van Moolenbroek
250*00b67f09SDavid van Moolenbroek const impl::vars_map
get_md_vars(void) const251*00b67f09SDavid van Moolenbroek impl::tc::get_md_vars(void)
252*00b67f09SDavid van Moolenbroek const
253*00b67f09SDavid van Moolenbroek {
254*00b67f09SDavid van Moolenbroek vars_map vars;
255*00b67f09SDavid van Moolenbroek
256*00b67f09SDavid van Moolenbroek char **array = atf_tc_get_md_vars(&pimpl->m_tc);
257*00b67f09SDavid van Moolenbroek try {
258*00b67f09SDavid van Moolenbroek char **ptr;
259*00b67f09SDavid van Moolenbroek for (ptr = array; *ptr != NULL; ptr += 2)
260*00b67f09SDavid van Moolenbroek vars[*ptr] = *(ptr + 1);
261*00b67f09SDavid van Moolenbroek } catch (...) {
262*00b67f09SDavid van Moolenbroek atf_utils_free_charpp(array);
263*00b67f09SDavid van Moolenbroek throw;
264*00b67f09SDavid van Moolenbroek }
265*00b67f09SDavid van Moolenbroek
266*00b67f09SDavid van Moolenbroek return vars;
267*00b67f09SDavid van Moolenbroek }
268*00b67f09SDavid van Moolenbroek
269*00b67f09SDavid van Moolenbroek void
set_md_var(const std::string & var,const std::string & val)270*00b67f09SDavid van Moolenbroek impl::tc::set_md_var(const std::string& var, const std::string& val)
271*00b67f09SDavid van Moolenbroek {
272*00b67f09SDavid van Moolenbroek atf_error_t err = atf_tc_set_md_var(&pimpl->m_tc, var.c_str(), val.c_str());
273*00b67f09SDavid van Moolenbroek if (atf_is_error(err))
274*00b67f09SDavid van Moolenbroek throw_atf_error(err);
275*00b67f09SDavid van Moolenbroek }
276*00b67f09SDavid van Moolenbroek
277*00b67f09SDavid van Moolenbroek void
run(const std::string & resfile) const278*00b67f09SDavid van Moolenbroek impl::tc::run(const std::string& resfile)
279*00b67f09SDavid van Moolenbroek const
280*00b67f09SDavid van Moolenbroek {
281*00b67f09SDavid van Moolenbroek atf_error_t err = atf_tc_run(&pimpl->m_tc, resfile.c_str());
282*00b67f09SDavid van Moolenbroek if (atf_is_error(err))
283*00b67f09SDavid van Moolenbroek throw_atf_error(err);
284*00b67f09SDavid van Moolenbroek }
285*00b67f09SDavid van Moolenbroek
286*00b67f09SDavid van Moolenbroek void
run_cleanup(void) const287*00b67f09SDavid van Moolenbroek impl::tc::run_cleanup(void)
288*00b67f09SDavid van Moolenbroek const
289*00b67f09SDavid van Moolenbroek {
290*00b67f09SDavid van Moolenbroek atf_error_t err = atf_tc_cleanup(&pimpl->m_tc);
291*00b67f09SDavid van Moolenbroek if (atf_is_error(err))
292*00b67f09SDavid van Moolenbroek throw_atf_error(err);
293*00b67f09SDavid van Moolenbroek }
294*00b67f09SDavid van Moolenbroek
295*00b67f09SDavid van Moolenbroek void
head(void)296*00b67f09SDavid van Moolenbroek impl::tc::head(void)
297*00b67f09SDavid van Moolenbroek {
298*00b67f09SDavid van Moolenbroek }
299*00b67f09SDavid van Moolenbroek
300*00b67f09SDavid van Moolenbroek void
cleanup(void) const301*00b67f09SDavid van Moolenbroek impl::tc::cleanup(void)
302*00b67f09SDavid van Moolenbroek const
303*00b67f09SDavid van Moolenbroek {
304*00b67f09SDavid van Moolenbroek }
305*00b67f09SDavid van Moolenbroek
306*00b67f09SDavid van Moolenbroek void
require_prog(const std::string & prog) const307*00b67f09SDavid van Moolenbroek impl::tc::require_prog(const std::string& prog)
308*00b67f09SDavid van Moolenbroek const
309*00b67f09SDavid van Moolenbroek {
310*00b67f09SDavid van Moolenbroek atf_tc_require_prog(prog.c_str());
311*00b67f09SDavid van Moolenbroek }
312*00b67f09SDavid van Moolenbroek
313*00b67f09SDavid van Moolenbroek void
pass(void)314*00b67f09SDavid van Moolenbroek impl::tc::pass(void)
315*00b67f09SDavid van Moolenbroek {
316*00b67f09SDavid van Moolenbroek atf_tc_pass();
317*00b67f09SDavid van Moolenbroek }
318*00b67f09SDavid van Moolenbroek
319*00b67f09SDavid van Moolenbroek void
fail(const std::string & reason)320*00b67f09SDavid van Moolenbroek impl::tc::fail(const std::string& reason)
321*00b67f09SDavid van Moolenbroek {
322*00b67f09SDavid van Moolenbroek atf_tc_fail("%s", reason.c_str());
323*00b67f09SDavid van Moolenbroek }
324*00b67f09SDavid van Moolenbroek
325*00b67f09SDavid van Moolenbroek void
fail_nonfatal(const std::string & reason)326*00b67f09SDavid van Moolenbroek impl::tc::fail_nonfatal(const std::string& reason)
327*00b67f09SDavid van Moolenbroek {
328*00b67f09SDavid van Moolenbroek atf_tc_fail_nonfatal("%s", reason.c_str());
329*00b67f09SDavid van Moolenbroek }
330*00b67f09SDavid van Moolenbroek
331*00b67f09SDavid van Moolenbroek void
skip(const std::string & reason)332*00b67f09SDavid van Moolenbroek impl::tc::skip(const std::string& reason)
333*00b67f09SDavid van Moolenbroek {
334*00b67f09SDavid van Moolenbroek atf_tc_skip("%s", reason.c_str());
335*00b67f09SDavid van Moolenbroek }
336*00b67f09SDavid van Moolenbroek
337*00b67f09SDavid van Moolenbroek void
check_errno(const char * file,const int line,const int exp_errno,const char * expr_str,const bool result)338*00b67f09SDavid van Moolenbroek impl::tc::check_errno(const char* file, const int line, const int exp_errno,
339*00b67f09SDavid van Moolenbroek const char* expr_str, const bool result)
340*00b67f09SDavid van Moolenbroek {
341*00b67f09SDavid van Moolenbroek atf_tc_check_errno(file, line, exp_errno, expr_str, result);
342*00b67f09SDavid van Moolenbroek }
343*00b67f09SDavid van Moolenbroek
344*00b67f09SDavid van Moolenbroek void
require_errno(const char * file,const int line,const int exp_errno,const char * expr_str,const bool result)345*00b67f09SDavid van Moolenbroek impl::tc::require_errno(const char* file, const int line, const int exp_errno,
346*00b67f09SDavid van Moolenbroek const char* expr_str, const bool result)
347*00b67f09SDavid van Moolenbroek {
348*00b67f09SDavid van Moolenbroek atf_tc_require_errno(file, line, exp_errno, expr_str, result);
349*00b67f09SDavid van Moolenbroek }
350*00b67f09SDavid van Moolenbroek
351*00b67f09SDavid van Moolenbroek void
expect_pass(void)352*00b67f09SDavid van Moolenbroek impl::tc::expect_pass(void)
353*00b67f09SDavid van Moolenbroek {
354*00b67f09SDavid van Moolenbroek atf_tc_expect_pass();
355*00b67f09SDavid van Moolenbroek }
356*00b67f09SDavid van Moolenbroek
357*00b67f09SDavid van Moolenbroek void
expect_fail(const std::string & reason)358*00b67f09SDavid van Moolenbroek impl::tc::expect_fail(const std::string& reason)
359*00b67f09SDavid van Moolenbroek {
360*00b67f09SDavid van Moolenbroek atf_tc_expect_fail("%s", reason.c_str());
361*00b67f09SDavid van Moolenbroek }
362*00b67f09SDavid van Moolenbroek
363*00b67f09SDavid van Moolenbroek void
expect_exit(const int exitcode,const std::string & reason)364*00b67f09SDavid van Moolenbroek impl::tc::expect_exit(const int exitcode, const std::string& reason)
365*00b67f09SDavid van Moolenbroek {
366*00b67f09SDavid van Moolenbroek atf_tc_expect_exit(exitcode, "%s", reason.c_str());
367*00b67f09SDavid van Moolenbroek }
368*00b67f09SDavid van Moolenbroek
369*00b67f09SDavid van Moolenbroek void
expect_signal(const int signo,const std::string & reason)370*00b67f09SDavid van Moolenbroek impl::tc::expect_signal(const int signo, const std::string& reason)
371*00b67f09SDavid van Moolenbroek {
372*00b67f09SDavid van Moolenbroek atf_tc_expect_signal(signo, "%s", reason.c_str());
373*00b67f09SDavid van Moolenbroek }
374*00b67f09SDavid van Moolenbroek
375*00b67f09SDavid van Moolenbroek void
expect_death(const std::string & reason)376*00b67f09SDavid van Moolenbroek impl::tc::expect_death(const std::string& reason)
377*00b67f09SDavid van Moolenbroek {
378*00b67f09SDavid van Moolenbroek atf_tc_expect_death("%s", reason.c_str());
379*00b67f09SDavid van Moolenbroek }
380*00b67f09SDavid van Moolenbroek
381*00b67f09SDavid van Moolenbroek void
expect_timeout(const std::string & reason)382*00b67f09SDavid van Moolenbroek impl::tc::expect_timeout(const std::string& reason)
383*00b67f09SDavid van Moolenbroek {
384*00b67f09SDavid van Moolenbroek atf_tc_expect_timeout("%s", reason.c_str());
385*00b67f09SDavid van Moolenbroek }
386*00b67f09SDavid van Moolenbroek
387*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
388*00b67f09SDavid van Moolenbroek // The "tp" class.
389*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------
390*00b67f09SDavid van Moolenbroek
391*00b67f09SDavid van Moolenbroek class tp : public atf::application::app {
392*00b67f09SDavid van Moolenbroek public:
393*00b67f09SDavid van Moolenbroek typedef std::vector< impl::tc * > tc_vector;
394*00b67f09SDavid van Moolenbroek
395*00b67f09SDavid van Moolenbroek private:
396*00b67f09SDavid van Moolenbroek static const char* m_description;
397*00b67f09SDavid van Moolenbroek
398*00b67f09SDavid van Moolenbroek bool m_lflag;
399*00b67f09SDavid van Moolenbroek atf::fs::path m_resfile;
400*00b67f09SDavid van Moolenbroek std::string m_srcdir_arg;
401*00b67f09SDavid van Moolenbroek atf::fs::path m_srcdir;
402*00b67f09SDavid van Moolenbroek
403*00b67f09SDavid van Moolenbroek atf::tests::vars_map m_vars;
404*00b67f09SDavid van Moolenbroek
405*00b67f09SDavid van Moolenbroek std::string specific_args(void) const;
406*00b67f09SDavid van Moolenbroek options_set specific_options(void) const;
407*00b67f09SDavid van Moolenbroek void process_option(int, const char*);
408*00b67f09SDavid van Moolenbroek
409*00b67f09SDavid van Moolenbroek void (*m_add_tcs)(tc_vector&);
410*00b67f09SDavid van Moolenbroek tc_vector m_tcs;
411*00b67f09SDavid van Moolenbroek
412*00b67f09SDavid van Moolenbroek void parse_vflag(const std::string&);
413*00b67f09SDavid van Moolenbroek void handle_srcdir(void);
414*00b67f09SDavid van Moolenbroek
415*00b67f09SDavid van Moolenbroek tc_vector init_tcs(void);
416*00b67f09SDavid van Moolenbroek
417*00b67f09SDavid van Moolenbroek enum tc_part {
418*00b67f09SDavid van Moolenbroek BODY,
419*00b67f09SDavid van Moolenbroek CLEANUP,
420*00b67f09SDavid van Moolenbroek };
421*00b67f09SDavid van Moolenbroek
422*00b67f09SDavid van Moolenbroek void list_tcs(void);
423*00b67f09SDavid van Moolenbroek impl::tc* find_tc(tc_vector, const std::string&);
424*00b67f09SDavid van Moolenbroek static std::pair< std::string, tc_part > process_tcarg(const std::string&);
425*00b67f09SDavid van Moolenbroek int run_tc(const std::string&);
426*00b67f09SDavid van Moolenbroek
427*00b67f09SDavid van Moolenbroek public:
428*00b67f09SDavid van Moolenbroek tp(void (*)(tc_vector&));
429*00b67f09SDavid van Moolenbroek ~tp(void);
430*00b67f09SDavid van Moolenbroek
431*00b67f09SDavid van Moolenbroek int main(void);
432*00b67f09SDavid van Moolenbroek };
433*00b67f09SDavid van Moolenbroek
434*00b67f09SDavid van Moolenbroek const char* tp::m_description =
435*00b67f09SDavid van Moolenbroek "This is an independent atf test program.";
436*00b67f09SDavid van Moolenbroek
tp(void (* add_tcs)(tc_vector &))437*00b67f09SDavid van Moolenbroek tp::tp(void (*add_tcs)(tc_vector&)) :
438*00b67f09SDavid van Moolenbroek app(m_description, "atf-test-program(1)", "atf(7)", false),
439*00b67f09SDavid van Moolenbroek m_lflag(false),
440*00b67f09SDavid van Moolenbroek m_resfile("/dev/stdout"),
441*00b67f09SDavid van Moolenbroek m_srcdir("."),
442*00b67f09SDavid van Moolenbroek m_add_tcs(add_tcs)
443*00b67f09SDavid van Moolenbroek {
444*00b67f09SDavid van Moolenbroek }
445*00b67f09SDavid van Moolenbroek
~tp(void)446*00b67f09SDavid van Moolenbroek tp::~tp(void)
447*00b67f09SDavid van Moolenbroek {
448*00b67f09SDavid van Moolenbroek for (tc_vector::iterator iter = m_tcs.begin();
449*00b67f09SDavid van Moolenbroek iter != m_tcs.end(); iter++) {
450*00b67f09SDavid van Moolenbroek impl::tc* tc = *iter;
451*00b67f09SDavid van Moolenbroek
452*00b67f09SDavid van Moolenbroek delete tc;
453*00b67f09SDavid van Moolenbroek }
454*00b67f09SDavid van Moolenbroek }
455*00b67f09SDavid van Moolenbroek
456*00b67f09SDavid van Moolenbroek std::string
specific_args(void) const457*00b67f09SDavid van Moolenbroek tp::specific_args(void)
458*00b67f09SDavid van Moolenbroek const
459*00b67f09SDavid van Moolenbroek {
460*00b67f09SDavid van Moolenbroek return "test_case";
461*00b67f09SDavid van Moolenbroek }
462*00b67f09SDavid van Moolenbroek
463*00b67f09SDavid van Moolenbroek tp::options_set
specific_options(void) const464*00b67f09SDavid van Moolenbroek tp::specific_options(void)
465*00b67f09SDavid van Moolenbroek const
466*00b67f09SDavid van Moolenbroek {
467*00b67f09SDavid van Moolenbroek using atf::application::option;
468*00b67f09SDavid van Moolenbroek options_set opts;
469*00b67f09SDavid van Moolenbroek opts.insert(option('l', "", "List test cases and their purpose"));
470*00b67f09SDavid van Moolenbroek opts.insert(option('r', "resfile", "The file to which the test program "
471*00b67f09SDavid van Moolenbroek "will write the results of the "
472*00b67f09SDavid van Moolenbroek "executed test case"));
473*00b67f09SDavid van Moolenbroek opts.insert(option('s', "srcdir", "Directory where the test's data "
474*00b67f09SDavid van Moolenbroek "files are located"));
475*00b67f09SDavid van Moolenbroek opts.insert(option('v', "var=value", "Sets the configuration variable "
476*00b67f09SDavid van Moolenbroek "`var' to `value'"));
477*00b67f09SDavid van Moolenbroek return opts;
478*00b67f09SDavid van Moolenbroek }
479*00b67f09SDavid van Moolenbroek
480*00b67f09SDavid van Moolenbroek void
process_option(int ch,const char * arg)481*00b67f09SDavid van Moolenbroek tp::process_option(int ch, const char* arg)
482*00b67f09SDavid van Moolenbroek {
483*00b67f09SDavid van Moolenbroek switch (ch) {
484*00b67f09SDavid van Moolenbroek case 'l':
485*00b67f09SDavid van Moolenbroek m_lflag = true;
486*00b67f09SDavid van Moolenbroek break;
487*00b67f09SDavid van Moolenbroek
488*00b67f09SDavid van Moolenbroek case 'r':
489*00b67f09SDavid van Moolenbroek m_resfile = atf::fs::path(arg);
490*00b67f09SDavid van Moolenbroek break;
491*00b67f09SDavid van Moolenbroek
492*00b67f09SDavid van Moolenbroek case 's':
493*00b67f09SDavid van Moolenbroek m_srcdir_arg = arg;
494*00b67f09SDavid van Moolenbroek break;
495*00b67f09SDavid van Moolenbroek
496*00b67f09SDavid van Moolenbroek case 'v':
497*00b67f09SDavid van Moolenbroek parse_vflag(arg);
498*00b67f09SDavid van Moolenbroek break;
499*00b67f09SDavid van Moolenbroek
500*00b67f09SDavid van Moolenbroek default:
501*00b67f09SDavid van Moolenbroek UNREACHABLE;
502*00b67f09SDavid van Moolenbroek }
503*00b67f09SDavid van Moolenbroek }
504*00b67f09SDavid van Moolenbroek
505*00b67f09SDavid van Moolenbroek void
parse_vflag(const std::string & str)506*00b67f09SDavid van Moolenbroek tp::parse_vflag(const std::string& str)
507*00b67f09SDavid van Moolenbroek {
508*00b67f09SDavid van Moolenbroek if (str.empty())
509*00b67f09SDavid van Moolenbroek throw std::runtime_error("-v requires a non-empty argument");
510*00b67f09SDavid van Moolenbroek
511*00b67f09SDavid van Moolenbroek std::vector< std::string > ws = atf::text::split(str, "=");
512*00b67f09SDavid van Moolenbroek if (ws.size() == 1 && str[str.length() - 1] == '=') {
513*00b67f09SDavid van Moolenbroek m_vars[ws[0]] = "";
514*00b67f09SDavid van Moolenbroek } else {
515*00b67f09SDavid van Moolenbroek if (ws.size() != 2)
516*00b67f09SDavid van Moolenbroek throw std::runtime_error("-v requires an argument of the form "
517*00b67f09SDavid van Moolenbroek "var=value");
518*00b67f09SDavid van Moolenbroek
519*00b67f09SDavid van Moolenbroek m_vars[ws[0]] = ws[1];
520*00b67f09SDavid van Moolenbroek }
521*00b67f09SDavid van Moolenbroek }
522*00b67f09SDavid van Moolenbroek
523*00b67f09SDavid van Moolenbroek void
handle_srcdir(void)524*00b67f09SDavid van Moolenbroek tp::handle_srcdir(void)
525*00b67f09SDavid van Moolenbroek {
526*00b67f09SDavid van Moolenbroek if (m_srcdir_arg.empty()) {
527*00b67f09SDavid van Moolenbroek m_srcdir = atf::fs::path(m_argv0).branch_path();
528*00b67f09SDavid van Moolenbroek if (m_srcdir.leaf_name() == ".libs")
529*00b67f09SDavid van Moolenbroek m_srcdir = m_srcdir.branch_path();
530*00b67f09SDavid van Moolenbroek } else
531*00b67f09SDavid van Moolenbroek m_srcdir = atf::fs::path(m_srcdir_arg);
532*00b67f09SDavid van Moolenbroek
533*00b67f09SDavid van Moolenbroek if (!atf::fs::exists(m_srcdir / m_prog_name))
534*00b67f09SDavid van Moolenbroek throw std::runtime_error("Cannot find the test program in the "
535*00b67f09SDavid van Moolenbroek "source directory `" + m_srcdir.str() + "'");
536*00b67f09SDavid van Moolenbroek
537*00b67f09SDavid van Moolenbroek if (!m_srcdir.is_absolute())
538*00b67f09SDavid van Moolenbroek m_srcdir = m_srcdir.to_absolute();
539*00b67f09SDavid van Moolenbroek
540*00b67f09SDavid van Moolenbroek m_vars["srcdir"] = m_srcdir.str();
541*00b67f09SDavid van Moolenbroek }
542*00b67f09SDavid van Moolenbroek
543*00b67f09SDavid van Moolenbroek tp::tc_vector
init_tcs(void)544*00b67f09SDavid van Moolenbroek tp::init_tcs(void)
545*00b67f09SDavid van Moolenbroek {
546*00b67f09SDavid van Moolenbroek m_add_tcs(m_tcs);
547*00b67f09SDavid van Moolenbroek for (tc_vector::iterator iter = m_tcs.begin();
548*00b67f09SDavid van Moolenbroek iter != m_tcs.end(); iter++) {
549*00b67f09SDavid van Moolenbroek impl::tc* tc = *iter;
550*00b67f09SDavid van Moolenbroek
551*00b67f09SDavid van Moolenbroek tc->init(m_vars);
552*00b67f09SDavid van Moolenbroek }
553*00b67f09SDavid van Moolenbroek return m_tcs;
554*00b67f09SDavid van Moolenbroek }
555*00b67f09SDavid van Moolenbroek
556*00b67f09SDavid van Moolenbroek //
557*00b67f09SDavid van Moolenbroek // An auxiliary unary predicate that compares the given test case's
558*00b67f09SDavid van Moolenbroek // identifier to the identifier stored in it.
559*00b67f09SDavid van Moolenbroek //
560*00b67f09SDavid van Moolenbroek class tc_equal_to_ident {
561*00b67f09SDavid van Moolenbroek const std::string& m_ident;
562*00b67f09SDavid van Moolenbroek
563*00b67f09SDavid van Moolenbroek public:
tc_equal_to_ident(const std::string & i)564*00b67f09SDavid van Moolenbroek tc_equal_to_ident(const std::string& i) :
565*00b67f09SDavid van Moolenbroek m_ident(i)
566*00b67f09SDavid van Moolenbroek {
567*00b67f09SDavid van Moolenbroek }
568*00b67f09SDavid van Moolenbroek
operator ()(const impl::tc * tc)569*00b67f09SDavid van Moolenbroek bool operator()(const impl::tc* tc)
570*00b67f09SDavid van Moolenbroek {
571*00b67f09SDavid van Moolenbroek return tc->get_md_var("ident") == m_ident;
572*00b67f09SDavid van Moolenbroek }
573*00b67f09SDavid van Moolenbroek };
574*00b67f09SDavid van Moolenbroek
575*00b67f09SDavid van Moolenbroek void
list_tcs(void)576*00b67f09SDavid van Moolenbroek tp::list_tcs(void)
577*00b67f09SDavid van Moolenbroek {
578*00b67f09SDavid van Moolenbroek tc_vector tcs = init_tcs();
579*00b67f09SDavid van Moolenbroek detail::atf_tp_writer writer(std::cout);
580*00b67f09SDavid van Moolenbroek
581*00b67f09SDavid van Moolenbroek for (tc_vector::const_iterator iter = tcs.begin();
582*00b67f09SDavid van Moolenbroek iter != tcs.end(); iter++) {
583*00b67f09SDavid van Moolenbroek const impl::vars_map vars = (*iter)->get_md_vars();
584*00b67f09SDavid van Moolenbroek
585*00b67f09SDavid van Moolenbroek {
586*00b67f09SDavid van Moolenbroek impl::vars_map::const_iterator iter2 = vars.find("ident");
587*00b67f09SDavid van Moolenbroek INV(iter2 != vars.end());
588*00b67f09SDavid van Moolenbroek writer.start_tc((*iter2).second);
589*00b67f09SDavid van Moolenbroek }
590*00b67f09SDavid van Moolenbroek
591*00b67f09SDavid van Moolenbroek for (impl::vars_map::const_iterator iter2 = vars.begin();
592*00b67f09SDavid van Moolenbroek iter2 != vars.end(); iter2++) {
593*00b67f09SDavid van Moolenbroek const std::string& key = (*iter2).first;
594*00b67f09SDavid van Moolenbroek if (key != "ident")
595*00b67f09SDavid van Moolenbroek writer.tc_meta_data(key, (*iter2).second);
596*00b67f09SDavid van Moolenbroek }
597*00b67f09SDavid van Moolenbroek
598*00b67f09SDavid van Moolenbroek writer.end_tc();
599*00b67f09SDavid van Moolenbroek }
600*00b67f09SDavid van Moolenbroek }
601*00b67f09SDavid van Moolenbroek
602*00b67f09SDavid van Moolenbroek impl::tc*
find_tc(tc_vector tcs,const std::string & name)603*00b67f09SDavid van Moolenbroek tp::find_tc(tc_vector tcs, const std::string& name)
604*00b67f09SDavid van Moolenbroek {
605*00b67f09SDavid van Moolenbroek std::vector< std::string > ids;
606*00b67f09SDavid van Moolenbroek for (tc_vector::iterator iter = tcs.begin();
607*00b67f09SDavid van Moolenbroek iter != tcs.end(); iter++) {
608*00b67f09SDavid van Moolenbroek impl::tc* tc = *iter;
609*00b67f09SDavid van Moolenbroek
610*00b67f09SDavid van Moolenbroek if (tc->get_md_var("ident") == name)
611*00b67f09SDavid van Moolenbroek return tc;
612*00b67f09SDavid van Moolenbroek }
613*00b67f09SDavid van Moolenbroek throw atf::application::usage_error("Unknown test case `%s'",
614*00b67f09SDavid van Moolenbroek name.c_str());
615*00b67f09SDavid van Moolenbroek }
616*00b67f09SDavid van Moolenbroek
617*00b67f09SDavid van Moolenbroek std::pair< std::string, tp::tc_part >
process_tcarg(const std::string & tcarg)618*00b67f09SDavid van Moolenbroek tp::process_tcarg(const std::string& tcarg)
619*00b67f09SDavid van Moolenbroek {
620*00b67f09SDavid van Moolenbroek const std::string::size_type pos = tcarg.find(':');
621*00b67f09SDavid van Moolenbroek if (pos == std::string::npos) {
622*00b67f09SDavid van Moolenbroek return std::make_pair(tcarg, BODY);
623*00b67f09SDavid van Moolenbroek } else {
624*00b67f09SDavid van Moolenbroek const std::string tcname = tcarg.substr(0, pos);
625*00b67f09SDavid van Moolenbroek
626*00b67f09SDavid van Moolenbroek const std::string partname = tcarg.substr(pos + 1);
627*00b67f09SDavid van Moolenbroek if (partname == "body")
628*00b67f09SDavid van Moolenbroek return std::make_pair(tcname, BODY);
629*00b67f09SDavid van Moolenbroek else if (partname == "cleanup")
630*00b67f09SDavid van Moolenbroek return std::make_pair(tcname, CLEANUP);
631*00b67f09SDavid van Moolenbroek else {
632*00b67f09SDavid van Moolenbroek using atf::application::usage_error;
633*00b67f09SDavid van Moolenbroek throw usage_error("Invalid test case part `%s'", partname.c_str());
634*00b67f09SDavid van Moolenbroek }
635*00b67f09SDavid van Moolenbroek }
636*00b67f09SDavid van Moolenbroek }
637*00b67f09SDavid van Moolenbroek
638*00b67f09SDavid van Moolenbroek int
run_tc(const std::string & tcarg)639*00b67f09SDavid van Moolenbroek tp::run_tc(const std::string& tcarg)
640*00b67f09SDavid van Moolenbroek {
641*00b67f09SDavid van Moolenbroek const std::pair< std::string, tc_part > fields = process_tcarg(tcarg);
642*00b67f09SDavid van Moolenbroek
643*00b67f09SDavid van Moolenbroek impl::tc* tc = find_tc(init_tcs(), fields.first);
644*00b67f09SDavid van Moolenbroek
645*00b67f09SDavid van Moolenbroek if (!atf::env::has("__RUNNING_INSIDE_ATF_RUN") || atf::env::get(
646*00b67f09SDavid van Moolenbroek "__RUNNING_INSIDE_ATF_RUN") != "internal-yes-value")
647*00b67f09SDavid van Moolenbroek {
648*00b67f09SDavid van Moolenbroek std::cerr << m_prog_name << ": WARNING: Running test cases without "
649*00b67f09SDavid van Moolenbroek "atf-run(1) is unsupported\n";
650*00b67f09SDavid van Moolenbroek std::cerr << m_prog_name << ": WARNING: No isolation nor timeout "
651*00b67f09SDavid van Moolenbroek "control is being applied; you may get unexpected failures; see "
652*00b67f09SDavid van Moolenbroek "atf-test-case(4)\n";
653*00b67f09SDavid van Moolenbroek }
654*00b67f09SDavid van Moolenbroek
655*00b67f09SDavid van Moolenbroek try {
656*00b67f09SDavid van Moolenbroek switch (fields.second) {
657*00b67f09SDavid van Moolenbroek case BODY:
658*00b67f09SDavid van Moolenbroek tc->run(m_resfile.str());
659*00b67f09SDavid van Moolenbroek break;
660*00b67f09SDavid van Moolenbroek case CLEANUP:
661*00b67f09SDavid van Moolenbroek tc->run_cleanup();
662*00b67f09SDavid van Moolenbroek break;
663*00b67f09SDavid van Moolenbroek default:
664*00b67f09SDavid van Moolenbroek UNREACHABLE;
665*00b67f09SDavid van Moolenbroek }
666*00b67f09SDavid van Moolenbroek return EXIT_SUCCESS;
667*00b67f09SDavid van Moolenbroek } catch (const std::runtime_error& e) {
668*00b67f09SDavid van Moolenbroek std::cerr << "ERROR: " << e.what() << "\n";
669*00b67f09SDavid van Moolenbroek return EXIT_FAILURE;
670*00b67f09SDavid van Moolenbroek }
671*00b67f09SDavid van Moolenbroek }
672*00b67f09SDavid van Moolenbroek
673*00b67f09SDavid van Moolenbroek int
main(void)674*00b67f09SDavid van Moolenbroek tp::main(void)
675*00b67f09SDavid van Moolenbroek {
676*00b67f09SDavid van Moolenbroek using atf::application::usage_error;
677*00b67f09SDavid van Moolenbroek
678*00b67f09SDavid van Moolenbroek int errcode;
679*00b67f09SDavid van Moolenbroek
680*00b67f09SDavid van Moolenbroek handle_srcdir();
681*00b67f09SDavid van Moolenbroek
682*00b67f09SDavid van Moolenbroek if (m_lflag) {
683*00b67f09SDavid van Moolenbroek if (m_argc > 0)
684*00b67f09SDavid van Moolenbroek throw usage_error("Cannot provide test case names with -l");
685*00b67f09SDavid van Moolenbroek
686*00b67f09SDavid van Moolenbroek list_tcs();
687*00b67f09SDavid van Moolenbroek errcode = EXIT_SUCCESS;
688*00b67f09SDavid van Moolenbroek } else {
689*00b67f09SDavid van Moolenbroek if (m_argc == 0)
690*00b67f09SDavid van Moolenbroek throw usage_error("Must provide a test case name");
691*00b67f09SDavid van Moolenbroek else if (m_argc > 1)
692*00b67f09SDavid van Moolenbroek throw usage_error("Cannot provide more than one test case name");
693*00b67f09SDavid van Moolenbroek INV(m_argc == 1);
694*00b67f09SDavid van Moolenbroek
695*00b67f09SDavid van Moolenbroek errcode = run_tc(m_argv[0]);
696*00b67f09SDavid van Moolenbroek }
697*00b67f09SDavid van Moolenbroek
698*00b67f09SDavid van Moolenbroek return errcode;
699*00b67f09SDavid van Moolenbroek }
700*00b67f09SDavid van Moolenbroek
701*00b67f09SDavid van Moolenbroek namespace atf {
702*00b67f09SDavid van Moolenbroek namespace tests {
703*00b67f09SDavid van Moolenbroek int run_tp(int, char* const*, void (*)(tp::tc_vector&));
704*00b67f09SDavid van Moolenbroek }
705*00b67f09SDavid van Moolenbroek }
706*00b67f09SDavid van Moolenbroek
707*00b67f09SDavid van Moolenbroek int
run_tp(int argc,char * const * argv,void (* add_tcs)(tp::tc_vector &))708*00b67f09SDavid van Moolenbroek impl::run_tp(int argc, char* const* argv, void (*add_tcs)(tp::tc_vector&))
709*00b67f09SDavid van Moolenbroek {
710*00b67f09SDavid van Moolenbroek return tp(add_tcs).run(argc, argv);
711*00b67f09SDavid van Moolenbroek }
712