Import atf-0.20.
This is a MFC of r261897 and r262000 and should allow all of the atf tests to pass.
This commit is contained in:
parent
6c6bd8779d
commit
fe643776c1
@ -18,3 +18,4 @@ configure*
|
||||
doc/atf-formats.5
|
||||
doc/atf.7.in
|
||||
m4/
|
||||
tools/
|
||||
|
@ -6,13 +6,3 @@ include("atf-c/Kyuafile")
|
||||
include("atf-c++/Kyuafile")
|
||||
include("atf-sh/Kyuafile")
|
||||
include("test-programs/Kyuafile")
|
||||
|
||||
if fs.exists("atf-config/Kyuafile") then
|
||||
include("atf-config/Kyuafile")
|
||||
end
|
||||
if fs.exists("atf-report/Kyuafile") then
|
||||
include("atf-report/Kyuafile")
|
||||
end
|
||||
if fs.exists("atf-run/Kyuafile") then
|
||||
include("atf-run/Kyuafile")
|
||||
end
|
||||
|
@ -2,6 +2,51 @@ Major changes between releases Automated Testing Framework
|
||||
===========================================================================
|
||||
|
||||
|
||||
Changes in version 0.20
|
||||
***********************
|
||||
|
||||
Experimental version released on February 7th, 2014.
|
||||
|
||||
This is the first release without the code for the deprecated tools. If
|
||||
you require such code, please fetch a copy of the 0.19 release and extract
|
||||
the 'tools' directory for your own consumption.
|
||||
|
||||
* Removed the deprecated tools. This includes atf-config, atf-report,
|
||||
atf-run and atf-version.
|
||||
|
||||
|
||||
Changes in version 0.19
|
||||
***********************
|
||||
|
||||
Experimental version released on February 7th, 2014.
|
||||
|
||||
This is the last release to bundle the code for the deprecated tools.
|
||||
The next release will drop their code and will stop worrying about
|
||||
backwards compatibility between the ATF libraries and what the old tools
|
||||
may or may not support.
|
||||
|
||||
If you still require the old tools for some reason, grab a copy of the
|
||||
'tools' directory now. The code in this directory is standalone and
|
||||
does not depend on any internal details of atf-c++ any longer.
|
||||
|
||||
* Various fixes and improvements to support running as part of the FreeBSD
|
||||
test suite.
|
||||
|
||||
* Project hosting moved from Google Code (as a subproject of Kyua) to
|
||||
GitHub (as a first-class project). The main reason for the change is
|
||||
the suppression of binary downloads in Google Code on Jan 15th, 2014.
|
||||
See https://github.com/jmmv/atf/
|
||||
|
||||
* Removed builtin help from atf-sh(1) and atf-check(1) for simplicity
|
||||
reasons. In other words, their -h option is gone.
|
||||
|
||||
* Moved the code of the deprecated tools into a 'tools' directory and
|
||||
completely decoupled their code from the internals of atf-c++. The
|
||||
reason for this is to painlessly allow a third-party to maintain a
|
||||
copy of these tools after we delete them because upcoming changes to
|
||||
atf-c++ would break the stale tools.
|
||||
|
||||
|
||||
Changes in version 0.18
|
||||
***********************
|
||||
|
||||
|
@ -5,21 +5,18 @@ Introductory information Automated Testing Framework
|
||||
Introduction
|
||||
************
|
||||
|
||||
The Automated Testing Framework (ATF) is a collection of libraries and
|
||||
utilities designed to ease unattended application testing in the hands of
|
||||
developers and end users of a specific piece of software.
|
||||
The Automated Testing Framework (ATF) is a collection of libraries to
|
||||
implement test programs in a variety of languages. At the moment, ATF
|
||||
offers C, C++ and POSIX shell bindings with which to implement tests.
|
||||
These bindings all offer a similar set of functionality and any test
|
||||
program written with them exposes a consistent user interface.
|
||||
|
||||
As regards developers, ATF provides the necessary means to easily create
|
||||
test suites composed of multiple test programs, which in turn are a
|
||||
collection of test cases. It also attempts to simplify the debugging of
|
||||
problems when these test cases detect an error by providing as much
|
||||
information as possible about the failure.
|
||||
|
||||
As regards users, it simplifies the process of running the test suites and,
|
||||
in special, encourages end users to run them often: they do not need to
|
||||
have source trees around nor any other development tools installed to be
|
||||
able to certify that a given piece of software works on their machine as
|
||||
advertised.
|
||||
ATF-based test programs rely on a separate runtime engine to execute them.
|
||||
The runtime engine is in charge of isolating the test programs from the
|
||||
rest of the system to ensure that their results are deterministic and that
|
||||
they cannot affect the running system. The runtime engine is also
|
||||
responsible for gathering the results of all tests and composing reports.
|
||||
The current runtime of choice is Kyua.
|
||||
|
||||
|
||||
Other documents
|
||||
|
@ -39,8 +39,6 @@ extern "C" {
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <atf-c++/noncopyable.hpp>
|
||||
|
||||
namespace atf {
|
||||
|
||||
namespace process {
|
||||
@ -60,7 +58,11 @@ namespace check {
|
||||
//! of executing arbitrary command and manages files containing
|
||||
//! its output.
|
||||
//!
|
||||
class check_result : noncopyable {
|
||||
class check_result {
|
||||
// Non-copyable.
|
||||
check_result(const check_result&);
|
||||
check_result& operator=(const check_result&);
|
||||
|
||||
//!
|
||||
//! \brief Internal representation of a result.
|
||||
//!
|
||||
|
@ -52,18 +52,14 @@ init_variables(void)
|
||||
{
|
||||
PRE(m_variables.empty());
|
||||
|
||||
m_variables["atf_arch"] = atf_config_get("atf_arch");
|
||||
m_variables["atf_build_cc"] = atf_config_get("atf_build_cc");
|
||||
m_variables["atf_build_cflags"] = atf_config_get("atf_build_cflags");
|
||||
m_variables["atf_build_cpp"] = atf_config_get("atf_build_cpp");
|
||||
m_variables["atf_build_cppflags"] = atf_config_get("atf_build_cppflags");
|
||||
m_variables["atf_build_cxx"] = atf_config_get("atf_build_cxx");
|
||||
m_variables["atf_build_cxxflags"] = atf_config_get("atf_build_cxxflags");
|
||||
m_variables["atf_confdir"] = atf_config_get("atf_confdir");
|
||||
m_variables["atf_includedir"] = atf_config_get("atf_includedir");
|
||||
m_variables["atf_libdir"] = atf_config_get("atf_libdir");
|
||||
m_variables["atf_libexecdir"] = atf_config_get("atf_libexecdir");
|
||||
m_variables["atf_machine"] = atf_config_get("atf_machine");
|
||||
m_variables["atf_pkgdatadir"] = atf_config_get("atf_pkgdatadir");
|
||||
m_variables["atf_shell"] = atf_config_get("atf_shell");
|
||||
m_variables["atf_workdir"] = atf_config_get("atf_workdir");
|
||||
|
@ -44,18 +44,14 @@ static struct varnames {
|
||||
const char *uc;
|
||||
bool can_be_empty;
|
||||
} all_vars[] = {
|
||||
{ "atf_arch", "ATF_ARCH", false },
|
||||
{ "atf_build_cc", "ATF_BUILD_CC", false },
|
||||
{ "atf_build_cflags", "ATF_BUILD_CFLAGS", true },
|
||||
{ "atf_build_cpp", "ATF_BUILD_CPP", false },
|
||||
{ "atf_build_cppflags", "ATF_BUILD_CPPFLAGS", true },
|
||||
{ "atf_build_cxx", "ATF_BUILD_CXX", false },
|
||||
{ "atf_build_cxxflags", "ATF_BUILD_CXXFLAGS", true },
|
||||
{ "atf_confdir", "ATF_CONFDIR", false },
|
||||
{ "atf_includedir", "ATF_INCLUDEDIR", false },
|
||||
{ "atf_libdir", "ATF_LIBDIR", false },
|
||||
{ "atf_libexecdir", "ATF_LIBEXECDIR", false },
|
||||
{ "atf_machine", "ATF_MACHINE", false },
|
||||
{ "atf_pkgdatadir", "ATF_PKGDATADIR", false },
|
||||
{ "atf_shell", "ATF_SHELL", false },
|
||||
{ "atf_workdir", "ATF_WORKDIR", false },
|
||||
|
@ -6,9 +6,7 @@ atf_test_program{name="application_test"}
|
||||
atf_test_program{name="auto_array_test"}
|
||||
atf_test_program{name="env_test"}
|
||||
atf_test_program{name="exceptions_test"}
|
||||
atf_test_program{name="expand_test"}
|
||||
atf_test_program{name="fs_test"}
|
||||
atf_test_program{name="parser_test"}
|
||||
atf_test_program{name="process_test"}
|
||||
atf_test_program{name="sanity_test"}
|
||||
atf_test_program{name="text_test"}
|
||||
atf_test_program{name="ui_test"}
|
||||
|
@ -47,7 +47,6 @@ extern "C" {
|
||||
|
||||
#include "application.hpp"
|
||||
#include "sanity.hpp"
|
||||
#include "ui.hpp"
|
||||
|
||||
#if !defined(HAVE_VSNPRINTF_IN_STD)
|
||||
namespace std {
|
||||
@ -106,17 +105,12 @@ impl::option::operator<(const impl::option& o)
|
||||
}
|
||||
|
||||
impl::app::app(const std::string& description,
|
||||
const std::string& manpage,
|
||||
const std::string& global_manpage,
|
||||
const bool use_ui) :
|
||||
m_hflag(false),
|
||||
const std::string& manpage) :
|
||||
m_argc(-1),
|
||||
m_argv(NULL),
|
||||
m_prog_name(NULL),
|
||||
m_description(description),
|
||||
m_manpage(manpage),
|
||||
m_global_manpage(global_manpage),
|
||||
m_use_ui(use_ui)
|
||||
m_manpage(manpage)
|
||||
{
|
||||
}
|
||||
|
||||
@ -133,11 +127,7 @@ impl::app::inited(void)
|
||||
impl::app::options_set
|
||||
impl::app::options(void)
|
||||
{
|
||||
options_set opts = specific_options();
|
||||
if (m_use_ui) {
|
||||
opts.insert(option('h', "", "Shows this help message"));
|
||||
}
|
||||
return opts;
|
||||
return specific_options();
|
||||
}
|
||||
|
||||
std::string
|
||||
@ -187,11 +177,6 @@ impl::app::process_options(void)
|
||||
::opterr = 0;
|
||||
while ((ch = ::getopt(m_argc, m_argv, optstr.c_str())) != -1) {
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
INV(m_use_ui);
|
||||
m_hflag = true;
|
||||
break;
|
||||
|
||||
case ':':
|
||||
throw usage_error("Option -%c requires an argument.",
|
||||
::optopt);
|
||||
@ -214,51 +199,6 @@ impl::app::process_options(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
impl::app::usage(std::ostream& os)
|
||||
{
|
||||
PRE(inited());
|
||||
|
||||
std::string args = specific_args();
|
||||
if (!args.empty())
|
||||
args = " " + args;
|
||||
os << ui::format_text_with_tag(std::string(m_prog_name) + " [options]" +
|
||||
args, "Usage: ", false) << "\n\n"
|
||||
<< ui::format_text(m_description) << "\n\n";
|
||||
|
||||
options_set opts = options();
|
||||
INV(!opts.empty());
|
||||
os << "Available options:\n";
|
||||
size_t coldesc = 0;
|
||||
for (options_set::const_iterator iter = opts.begin();
|
||||
iter != opts.end(); iter++) {
|
||||
const option& opt = (*iter);
|
||||
|
||||
if (opt.m_argument.length() + 1 > coldesc)
|
||||
coldesc = opt.m_argument.length() + 1;
|
||||
}
|
||||
for (options_set::const_iterator iter = opts.begin();
|
||||
iter != opts.end(); iter++) {
|
||||
const option& opt = (*iter);
|
||||
|
||||
std::string tag = std::string(" -") + opt.m_character;
|
||||
if (opt.m_argument.empty())
|
||||
tag += " ";
|
||||
else
|
||||
tag += " " + opt.m_argument + " ";
|
||||
os << ui::format_text_with_tag(opt.m_description, tag, false,
|
||||
coldesc + 10) << "\n";
|
||||
}
|
||||
os << "\n";
|
||||
|
||||
std::string gmp;
|
||||
if (!m_global_manpage.empty())
|
||||
gmp = " and " + m_global_manpage;
|
||||
os << ui::format_text("For more details please see " + m_manpage +
|
||||
gmp + ".")
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
int
|
||||
impl::app::run(int argc, char* const* argv)
|
||||
{
|
||||
@ -290,55 +230,22 @@ impl::app::run(int argc, char* const* argv)
|
||||
|
||||
int errcode;
|
||||
try {
|
||||
int oldargc = m_argc;
|
||||
|
||||
process_options();
|
||||
|
||||
if (m_hflag) {
|
||||
INV(m_use_ui);
|
||||
if (oldargc != 2)
|
||||
throw usage_error("-h must be given alone.");
|
||||
|
||||
usage(std::cout);
|
||||
errcode = EXIT_SUCCESS;
|
||||
} else
|
||||
errcode = main();
|
||||
errcode = main();
|
||||
} catch (const usage_error& e) {
|
||||
if (m_use_ui) {
|
||||
std::cerr << ui::format_error(m_prog_name, e.what()) << "\n"
|
||||
<< ui::format_info(m_prog_name, std::string("Type `") +
|
||||
m_prog_name + " -h' for more details.")
|
||||
<< "\n";
|
||||
} else {
|
||||
std::cerr << m_prog_name << ": ERROR: " << e.what() << "\n";
|
||||
std::cerr << m_prog_name << ": See " << m_manpage << " for usage "
|
||||
"details.\n";
|
||||
}
|
||||
std::cerr << m_prog_name << ": ERROR: " << e.what() << "\n";
|
||||
std::cerr << m_prog_name << ": See " << m_manpage << " for usage "
|
||||
"details.\n";
|
||||
errcode = EXIT_FAILURE;
|
||||
} catch (const std::runtime_error& e) {
|
||||
if (m_use_ui) {
|
||||
std::cerr << ui::format_error(m_prog_name, std::string(e.what()))
|
||||
<< "\n";
|
||||
} else {
|
||||
std::cerr << m_prog_name << ": ERROR: " << e.what() << "\n";
|
||||
}
|
||||
std::cerr << m_prog_name << ": ERROR: " << e.what() << "\n";
|
||||
errcode = EXIT_FAILURE;
|
||||
} catch (const std::exception& e) {
|
||||
if (m_use_ui) {
|
||||
std::cerr << ui::format_error(m_prog_name, std::string("Caught "
|
||||
"unexpected error: ") + e.what() + "\n" + bug) << "\n";
|
||||
} else {
|
||||
std::cerr << m_prog_name << ": ERROR: Caught unexpected error: "
|
||||
<< e.what() << "\n";
|
||||
}
|
||||
std::cerr << m_prog_name << ": ERROR: Caught unexpected error: "
|
||||
<< e.what() << "\n";
|
||||
errcode = EXIT_FAILURE;
|
||||
} catch (...) {
|
||||
if (m_use_ui) {
|
||||
std::cerr << ui::format_error(m_prog_name, std::string("Caught "
|
||||
"unknown error\n") + bug) << "\n";
|
||||
} else {
|
||||
std::cerr << m_prog_name << ": ERROR: Caught unknown error\n";
|
||||
}
|
||||
std::cerr << m_prog_name << ": ERROR: Caught unknown error\n";
|
||||
errcode = EXIT_FAILURE;
|
||||
}
|
||||
return errcode;
|
||||
|
@ -74,8 +74,6 @@ class option {
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
class app {
|
||||
bool m_hflag;
|
||||
|
||||
void process_options(void);
|
||||
void usage(std::ostream&);
|
||||
|
||||
@ -90,8 +88,7 @@ class app {
|
||||
const char* m_argv0;
|
||||
const char* m_prog_name;
|
||||
std::string m_description;
|
||||
std::string m_manpage, m_global_manpage;
|
||||
const bool m_use_ui;
|
||||
std::string m_manpage;
|
||||
|
||||
options_set options(void);
|
||||
|
||||
@ -102,8 +99,7 @@ class app {
|
||||
virtual int main(void) = 0;
|
||||
|
||||
public:
|
||||
app(const std::string&, const std::string&, const std::string&,
|
||||
bool = true);
|
||||
app(const std::string&, const std::string&);
|
||||
virtual ~app(void);
|
||||
|
||||
int run(int, char* const*);
|
||||
|
@ -37,7 +37,7 @@ extern "C" {
|
||||
|
||||
class getopt_app : public atf::application::app {
|
||||
public:
|
||||
getopt_app(void) : app("description", "manpage", "other") {}
|
||||
getopt_app(void) : app("description", "manpage") {}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
@ -39,47 +39,6 @@ struct atf_error;
|
||||
|
||||
namespace atf {
|
||||
|
||||
template< class T >
|
||||
class not_found_error :
|
||||
public std::runtime_error
|
||||
{
|
||||
T m_value;
|
||||
|
||||
public:
|
||||
not_found_error(const std::string& message, const T& value) throw();
|
||||
|
||||
virtual ~not_found_error(void) throw();
|
||||
|
||||
const T& get_value(void) const throw();
|
||||
};
|
||||
|
||||
template< class T >
|
||||
inline
|
||||
not_found_error< T >::not_found_error(const std::string& message,
|
||||
const T& value)
|
||||
throw() :
|
||||
std::runtime_error(message),
|
||||
m_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
template< class T >
|
||||
inline
|
||||
not_found_error< T >::~not_found_error(void)
|
||||
throw()
|
||||
{
|
||||
}
|
||||
|
||||
template< class T >
|
||||
inline
|
||||
const T&
|
||||
not_found_error< T >::get_value(void)
|
||||
const
|
||||
throw()
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
class system_error : public std::runtime_error {
|
||||
int m_sys_err;
|
||||
mutable std::string m_message;
|
||||
|
@ -1,81 +0,0 @@
|
||||
//
|
||||
// Automated Testing Framework (atf)
|
||||
//
|
||||
// Copyright (c) 2007 The NetBSD Foundation, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
|
||||
// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "expand.hpp"
|
||||
#include "text.hpp"
|
||||
|
||||
namespace impl = atf::expand;
|
||||
#define IMPL_NAME "atf::expand"
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Auxiliary functions.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
|
||||
std::string
|
||||
glob_to_regex(const std::string& glob)
|
||||
{
|
||||
std::string regex;
|
||||
regex.reserve(glob.length() * 2);
|
||||
|
||||
regex += '^';
|
||||
for (std::string::const_iterator iter = glob.begin(); iter != glob.end();
|
||||
iter++) {
|
||||
switch (*iter) {
|
||||
case '*': regex += ".*"; break;
|
||||
case '?': regex += "."; break;
|
||||
default: regex += *iter;
|
||||
}
|
||||
}
|
||||
regex += '$';
|
||||
|
||||
return regex;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Free functions.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
impl::is_glob(const std::string& glob)
|
||||
{
|
||||
// NOTE: Keep this in sync with glob_to_regex!
|
||||
return glob.find_first_of("*?") != std::string::npos;
|
||||
}
|
||||
|
||||
bool
|
||||
impl::matches_glob(const std::string& glob, const std::string& candidate)
|
||||
{
|
||||
return atf::text::match(candidate, glob_to_regex(glob));
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
//
|
||||
// Automated Testing Framework (atf)
|
||||
//
|
||||
// Copyright (c) 2007 The NetBSD Foundation, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
|
||||
// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#if !defined(_ATF_CXX_EXPAND_HPP_)
|
||||
#define _ATF_CXX_EXPAND_HPP_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace atf {
|
||||
namespace expand {
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Free functions.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
//!
|
||||
//! \brief Checks if the given string is a glob pattern.
|
||||
//!
|
||||
//! Returns true if the given string is a glob pattern; i.e. if it contains
|
||||
//! any character that will be expanded by expand_glob.
|
||||
//!
|
||||
bool is_glob(const std::string&);
|
||||
|
||||
//!
|
||||
//! \brief Checks if a given string matches a glob pattern.
|
||||
//!
|
||||
//! Given a glob pattern and a string, checks whether the former matches
|
||||
//! the latter. Returns a boolean indicating this condition.
|
||||
//!
|
||||
bool matches_glob(const std::string&, const std::string&);
|
||||
|
||||
//!
|
||||
//! \brief Expands a glob pattern among multiple candidates.
|
||||
//!
|
||||
//! Given a glob pattern and a set of candidate strings, checks which of
|
||||
//! those strings match the glob pattern and returns them.
|
||||
//!
|
||||
template< class T >
|
||||
std::vector< std::string > expand_glob(const std::string& glob,
|
||||
const T& candidates)
|
||||
{
|
||||
std::vector< std::string > exps;
|
||||
|
||||
for (typename T::const_iterator iter = candidates.begin();
|
||||
iter != candidates.end(); iter++)
|
||||
if (matches_glob(glob, *iter))
|
||||
exps.push_back(*iter);
|
||||
|
||||
return exps;
|
||||
}
|
||||
|
||||
} // namespace expand
|
||||
} // namespace atf
|
||||
|
||||
#endif // !defined(_ATF_CXX_EXPAND_HPP_)
|
@ -1,272 +0,0 @@
|
||||
//
|
||||
// Automated Testing Framework (atf)
|
||||
//
|
||||
// Copyright (c) 2007 The NetBSD Foundation, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
|
||||
// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "../macros.hpp"
|
||||
|
||||
#include "expand.hpp"
|
||||
|
||||
// XXX Many of the tests here are duplicated in atf-c/t_expand. Should
|
||||
// find a way to easily share them, or maybe remove the ones here.
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Test cases for the free functions.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
ATF_TEST_CASE(is_glob);
|
||||
ATF_TEST_CASE_HEAD(is_glob)
|
||||
{
|
||||
set_md_var("descr", "Tests the is_glob function.");
|
||||
}
|
||||
ATF_TEST_CASE_BODY(is_glob)
|
||||
{
|
||||
using atf::expand::is_glob;
|
||||
|
||||
ATF_REQUIRE(!is_glob(""));
|
||||
ATF_REQUIRE(!is_glob("a"));
|
||||
ATF_REQUIRE(!is_glob("foo"));
|
||||
|
||||
ATF_REQUIRE( is_glob("*"));
|
||||
ATF_REQUIRE( is_glob("a*"));
|
||||
ATF_REQUIRE( is_glob("*a"));
|
||||
ATF_REQUIRE( is_glob("a*b"));
|
||||
|
||||
ATF_REQUIRE( is_glob("?"));
|
||||
ATF_REQUIRE( is_glob("a?"));
|
||||
ATF_REQUIRE( is_glob("?a"));
|
||||
ATF_REQUIRE( is_glob("a?b"));
|
||||
}
|
||||
|
||||
ATF_TEST_CASE(matches_glob_plain);
|
||||
ATF_TEST_CASE_HEAD(matches_glob_plain)
|
||||
{
|
||||
set_md_var("descr", "Tests the matches_glob function by using plain "
|
||||
"text strings as patterns only.");
|
||||
}
|
||||
ATF_TEST_CASE_BODY(matches_glob_plain)
|
||||
{
|
||||
using atf::expand::matches_glob;
|
||||
|
||||
ATF_REQUIRE( matches_glob("", ""));
|
||||
ATF_REQUIRE(!matches_glob("a", ""));
|
||||
ATF_REQUIRE(!matches_glob("", "a"));
|
||||
|
||||
ATF_REQUIRE( matches_glob("ab", "ab"));
|
||||
ATF_REQUIRE(!matches_glob("abc", "ab"));
|
||||
ATF_REQUIRE(!matches_glob("ab", "abc"));
|
||||
}
|
||||
|
||||
ATF_TEST_CASE(matches_glob_star);
|
||||
ATF_TEST_CASE_HEAD(matches_glob_star)
|
||||
{
|
||||
set_md_var("descr", "Tests the matches_glob function by using the '*' "
|
||||
"meta-character as part of the pattern.");
|
||||
}
|
||||
ATF_TEST_CASE_BODY(matches_glob_star)
|
||||
{
|
||||
using atf::expand::matches_glob;
|
||||
|
||||
ATF_REQUIRE( matches_glob("*", ""));
|
||||
ATF_REQUIRE( matches_glob("*", "a"));
|
||||
ATF_REQUIRE( matches_glob("*", "ab"));
|
||||
|
||||
ATF_REQUIRE(!matches_glob("a*", ""));
|
||||
ATF_REQUIRE( matches_glob("a*", "a"));
|
||||
ATF_REQUIRE( matches_glob("a*", "aa"));
|
||||
ATF_REQUIRE( matches_glob("a*", "ab"));
|
||||
ATF_REQUIRE( matches_glob("a*", "abc"));
|
||||
ATF_REQUIRE(!matches_glob("a*", "ba"));
|
||||
|
||||
ATF_REQUIRE( matches_glob("*a", "a"));
|
||||
ATF_REQUIRE( matches_glob("*a", "ba"));
|
||||
ATF_REQUIRE(!matches_glob("*a", "bc"));
|
||||
ATF_REQUIRE(!matches_glob("*a", "bac"));
|
||||
|
||||
ATF_REQUIRE( matches_glob("*ab", "ab"));
|
||||
ATF_REQUIRE( matches_glob("*ab", "aab"));
|
||||
ATF_REQUIRE( matches_glob("*ab", "aaab"));
|
||||
ATF_REQUIRE( matches_glob("*ab", "bab"));
|
||||
ATF_REQUIRE(!matches_glob("*ab", "bcb"));
|
||||
ATF_REQUIRE(!matches_glob("*ab", "bacb"));
|
||||
|
||||
ATF_REQUIRE( matches_glob("a*b", "ab"));
|
||||
ATF_REQUIRE( matches_glob("a*b", "acb"));
|
||||
ATF_REQUIRE( matches_glob("a*b", "acdeb"));
|
||||
ATF_REQUIRE(!matches_glob("a*b", "acdebz"));
|
||||
ATF_REQUIRE(!matches_glob("a*b", "zacdeb"));
|
||||
}
|
||||
|
||||
ATF_TEST_CASE(matches_glob_question);
|
||||
ATF_TEST_CASE_HEAD(matches_glob_question)
|
||||
{
|
||||
set_md_var("descr", "Tests the matches_glob function by using the '?' "
|
||||
"meta-character as part of the pattern.");
|
||||
}
|
||||
ATF_TEST_CASE_BODY(matches_glob_question)
|
||||
{
|
||||
using atf::expand::matches_glob;
|
||||
|
||||
ATF_REQUIRE(!matches_glob("?", ""));
|
||||
ATF_REQUIRE( matches_glob("?", "a"));
|
||||
ATF_REQUIRE(!matches_glob("?", "ab"));
|
||||
|
||||
ATF_REQUIRE( matches_glob("?", "b"));
|
||||
ATF_REQUIRE( matches_glob("?", "c"));
|
||||
|
||||
ATF_REQUIRE( matches_glob("a?", "ab"));
|
||||
ATF_REQUIRE( matches_glob("a?", "ac"));
|
||||
ATF_REQUIRE(!matches_glob("a?", "ca"));
|
||||
|
||||
ATF_REQUIRE( matches_glob("???", "abc"));
|
||||
ATF_REQUIRE( matches_glob("???", "def"));
|
||||
ATF_REQUIRE(!matches_glob("???", "a"));
|
||||
ATF_REQUIRE(!matches_glob("???", "ab"));
|
||||
ATF_REQUIRE(!matches_glob("???", "abcd"));
|
||||
}
|
||||
|
||||
ATF_TEST_CASE(expand_glob_base);
|
||||
ATF_TEST_CASE_HEAD(expand_glob_base)
|
||||
{
|
||||
set_md_var("descr", "Tests the expand_glob function with random "
|
||||
"patterns.");
|
||||
}
|
||||
ATF_TEST_CASE_BODY(expand_glob_base)
|
||||
{
|
||||
using atf::expand::expand_glob;
|
||||
|
||||
std::vector< std::string > candidates;
|
||||
candidates.push_back("foo");
|
||||
candidates.push_back("bar");
|
||||
candidates.push_back("baz");
|
||||
candidates.push_back("foobar");
|
||||
candidates.push_back("foobarbaz");
|
||||
candidates.push_back("foobarbazfoo");
|
||||
|
||||
std::vector< std::string > exps;
|
||||
|
||||
exps = expand_glob("foo", candidates);
|
||||
ATF_REQUIRE_EQ(exps.size(), 1);
|
||||
ATF_REQUIRE(exps[0] == "foo");
|
||||
|
||||
exps = expand_glob("bar", candidates);
|
||||
ATF_REQUIRE_EQ(exps.size(), 1);
|
||||
ATF_REQUIRE(exps[0] == "bar");
|
||||
|
||||
exps = expand_glob("foo*", candidates);
|
||||
ATF_REQUIRE_EQ(exps.size(), 4);
|
||||
ATF_REQUIRE(exps[0] == "foo");
|
||||
ATF_REQUIRE(exps[1] == "foobar");
|
||||
ATF_REQUIRE(exps[2] == "foobarbaz");
|
||||
ATF_REQUIRE(exps[3] == "foobarbazfoo");
|
||||
|
||||
exps = expand_glob("*foo", candidates);
|
||||
ATF_REQUIRE_EQ(exps.size(), 2);
|
||||
ATF_REQUIRE(exps[0] == "foo");
|
||||
ATF_REQUIRE(exps[1] == "foobarbazfoo");
|
||||
|
||||
exps = expand_glob("*foo*", candidates);
|
||||
ATF_REQUIRE_EQ(exps.size(), 4);
|
||||
ATF_REQUIRE(exps[0] == "foo");
|
||||
ATF_REQUIRE(exps[1] == "foobar");
|
||||
ATF_REQUIRE(exps[2] == "foobarbaz");
|
||||
ATF_REQUIRE(exps[3] == "foobarbazfoo");
|
||||
|
||||
exps = expand_glob("ba", candidates);
|
||||
ATF_REQUIRE_EQ(exps.size(), 0);
|
||||
|
||||
exps = expand_glob("ba*", candidates);
|
||||
ATF_REQUIRE_EQ(exps.size(), 2);
|
||||
ATF_REQUIRE(exps[0] == "bar");
|
||||
ATF_REQUIRE(exps[1] == "baz");
|
||||
|
||||
exps = expand_glob("*ba", candidates);
|
||||
ATF_REQUIRE_EQ(exps.size(), 0);
|
||||
|
||||
exps = expand_glob("*ba*", candidates);
|
||||
ATF_REQUIRE_EQ(exps.size(), 5);
|
||||
ATF_REQUIRE(exps[0] == "bar");
|
||||
ATF_REQUIRE(exps[1] == "baz");
|
||||
ATF_REQUIRE(exps[2] == "foobar");
|
||||
ATF_REQUIRE(exps[3] == "foobarbaz");
|
||||
ATF_REQUIRE(exps[4] == "foobarbazfoo");
|
||||
}
|
||||
|
||||
ATF_TEST_CASE(expand_glob_tps);
|
||||
ATF_TEST_CASE_HEAD(expand_glob_tps)
|
||||
{
|
||||
set_md_var("descr", "Tests the expand_glob function with patterns that "
|
||||
"match typical test program names. This is just a subcase "
|
||||
"of expand_base, but it is nice to make sure that it really "
|
||||
"works.");
|
||||
}
|
||||
ATF_TEST_CASE_BODY(expand_glob_tps)
|
||||
{
|
||||
using atf::expand::expand_glob;
|
||||
|
||||
std::vector< std::string > candidates;
|
||||
candidates.push_back("Atffile");
|
||||
candidates.push_back("h_foo");
|
||||
candidates.push_back("t_foo");
|
||||
candidates.push_back("t_bar");
|
||||
candidates.push_back("t_baz");
|
||||
candidates.push_back("foo_helper");
|
||||
candidates.push_back("foo_test");
|
||||
candidates.push_back("bar_test");
|
||||
candidates.push_back("baz_test");
|
||||
|
||||
std::vector< std::string > exps;
|
||||
|
||||
exps = expand_glob("t_*", candidates);
|
||||
ATF_REQUIRE_EQ(exps.size(), 3);
|
||||
ATF_REQUIRE(exps[0] == "t_foo");
|
||||
ATF_REQUIRE(exps[1] == "t_bar");
|
||||
ATF_REQUIRE(exps[2] == "t_baz");
|
||||
|
||||
exps = expand_glob("*_test", candidates);
|
||||
ATF_REQUIRE_EQ(exps.size(), 3);
|
||||
ATF_REQUIRE(exps[0] == "foo_test");
|
||||
ATF_REQUIRE(exps[1] == "bar_test");
|
||||
ATF_REQUIRE(exps[2] == "baz_test");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Main.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
ATF_INIT_TEST_CASES(tcs)
|
||||
{
|
||||
// Add the tests for the free functions.
|
||||
ATF_ADD_TEST_CASE(tcs, is_glob);
|
||||
ATF_ADD_TEST_CASE(tcs, matches_glob_plain);
|
||||
ATF_ADD_TEST_CASE(tcs, matches_glob_star);
|
||||
ATF_ADD_TEST_CASE(tcs, matches_glob_question);
|
||||
ATF_ADD_TEST_CASE(tcs, expand_glob_base);
|
||||
ATF_ADD_TEST_CASE(tcs, expand_glob_tps);
|
||||
}
|
@ -1,384 +0,0 @@
|
||||
//
|
||||
// Automated Testing Framework (atf)
|
||||
//
|
||||
// Copyright (c) 2007 The NetBSD Foundation, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
|
||||
// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "parser.hpp"
|
||||
#include "sanity.hpp"
|
||||
#include "text.hpp"
|
||||
|
||||
namespace impl = atf::parser;
|
||||
#define IMPL_NAME "atf::parser"
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// The "parse_error" class.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
impl::parse_error::parse_error(size_t line, std::string msg) :
|
||||
std::runtime_error(msg),
|
||||
std::pair< size_t, std::string >(line, msg)
|
||||
{
|
||||
}
|
||||
|
||||
impl::parse_error::~parse_error(void)
|
||||
throw()
|
||||
{
|
||||
}
|
||||
|
||||
const char*
|
||||
impl::parse_error::what(void)
|
||||
const throw()
|
||||
{
|
||||
try {
|
||||
std::ostringstream oss;
|
||||
oss << "LONELY PARSE ERROR: " << first << ": " << second;
|
||||
m_msg = oss.str();
|
||||
return m_msg.c_str();
|
||||
} catch (...) {
|
||||
return "Could not format message for parsing error.";
|
||||
}
|
||||
}
|
||||
|
||||
impl::parse_error::operator std::string(void)
|
||||
const
|
||||
{
|
||||
return atf::text::to_string(first) + ": " + second;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// The "parse_errors" class.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
impl::parse_errors::parse_errors(void) :
|
||||
std::runtime_error("No parsing errors yet")
|
||||
{
|
||||
m_msg.clear();
|
||||
}
|
||||
|
||||
impl::parse_errors::~parse_errors(void)
|
||||
throw()
|
||||
{
|
||||
}
|
||||
|
||||
const char*
|
||||
impl::parse_errors::what(void)
|
||||
const throw()
|
||||
{
|
||||
try {
|
||||
m_msg = atf::text::join(*this, "\n");
|
||||
return m_msg.c_str();
|
||||
} catch (...) {
|
||||
return "Could not format messages for parsing errors.";
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// The "format_error" class.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
impl::format_error::format_error(const std::string& w) :
|
||||
std::runtime_error(w.c_str())
|
||||
{
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// The "token" class.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
impl::token::token(void) :
|
||||
m_inited(false)
|
||||
{
|
||||
}
|
||||
|
||||
impl::token::token(size_t p_line,
|
||||
const token_type& p_type,
|
||||
const std::string& p_text) :
|
||||
m_inited(true),
|
||||
m_line(p_line),
|
||||
m_type(p_type),
|
||||
m_text(p_text)
|
||||
{
|
||||
}
|
||||
|
||||
size_t
|
||||
impl::token::lineno(void)
|
||||
const
|
||||
{
|
||||
return m_line;
|
||||
}
|
||||
|
||||
const impl::token_type&
|
||||
impl::token::type(void)
|
||||
const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
const std::string&
|
||||
impl::token::text(void)
|
||||
const
|
||||
{
|
||||
return m_text;
|
||||
}
|
||||
|
||||
impl::token::operator bool(void)
|
||||
const
|
||||
{
|
||||
return m_inited;
|
||||
}
|
||||
|
||||
bool
|
||||
impl::token::operator!(void)
|
||||
const
|
||||
{
|
||||
return !m_inited;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// The "header_entry" class.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
impl::header_entry::header_entry(void)
|
||||
{
|
||||
}
|
||||
|
||||
impl::header_entry::header_entry(const std::string& n, const std::string& v,
|
||||
attrs_map as) :
|
||||
m_name(n),
|
||||
m_value(v),
|
||||
m_attrs(as)
|
||||
{
|
||||
}
|
||||
|
||||
const std::string&
|
||||
impl::header_entry::name(void) const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
const std::string&
|
||||
impl::header_entry::value(void) const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
const impl::attrs_map&
|
||||
impl::header_entry::attrs(void) const
|
||||
{
|
||||
return m_attrs;
|
||||
}
|
||||
|
||||
bool
|
||||
impl::header_entry::has_attr(const std::string& n) const
|
||||
{
|
||||
return m_attrs.find(n) != m_attrs.end();
|
||||
}
|
||||
|
||||
const std::string&
|
||||
impl::header_entry::get_attr(const std::string& n) const
|
||||
{
|
||||
attrs_map::const_iterator iter = m_attrs.find(n);
|
||||
PRE(iter != m_attrs.end());
|
||||
return (*iter).second;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// The header tokenizer.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
namespace header {
|
||||
|
||||
static const impl::token_type eof_type = 0;
|
||||
static const impl::token_type nl_type = 1;
|
||||
static const impl::token_type text_type = 2;
|
||||
static const impl::token_type colon_type = 3;
|
||||
static const impl::token_type semicolon_type = 4;
|
||||
static const impl::token_type dblquote_type = 5;
|
||||
static const impl::token_type equal_type = 6;
|
||||
|
||||
class tokenizer : public impl::tokenizer< std::istream > {
|
||||
public:
|
||||
tokenizer(std::istream& is, size_t curline) :
|
||||
impl::tokenizer< std::istream >
|
||||
(is, true, eof_type, nl_type, text_type, curline)
|
||||
{
|
||||
add_delim(';', semicolon_type);
|
||||
add_delim(':', colon_type);
|
||||
add_delim('=', equal_type);
|
||||
add_quote('"', dblquote_type);
|
||||
}
|
||||
};
|
||||
|
||||
static
|
||||
impl::parser< header::tokenizer >&
|
||||
read(impl::parser< header::tokenizer >& p, impl::header_entry& he)
|
||||
{
|
||||
using namespace header;
|
||||
|
||||
impl::token t = p.expect(text_type, nl_type, "a header name");
|
||||
if (t.type() == nl_type) {
|
||||
he = impl::header_entry();
|
||||
return p;
|
||||
}
|
||||
std::string hdr_name = t.text();
|
||||
|
||||
t = p.expect(colon_type, "`:'");
|
||||
|
||||
t = p.expect(text_type, "a textual value");
|
||||
std::string hdr_value = t.text();
|
||||
|
||||
impl::attrs_map attrs;
|
||||
|
||||
for (;;) {
|
||||
t = p.expect(eof_type, semicolon_type, nl_type,
|
||||
"eof, `;' or new line");
|
||||
if (t.type() == eof_type || t.type() == nl_type)
|
||||
break;
|
||||
|
||||
t = p.expect(text_type, "an attribute name");
|
||||
std::string attr_name = t.text();
|
||||
|
||||
t = p.expect(equal_type, "`='");
|
||||
|
||||
t = p.expect(text_type, "word or quoted string");
|
||||
std::string attr_value = t.text();
|
||||
attrs[attr_name] = attr_value;
|
||||
}
|
||||
|
||||
he = impl::header_entry(hdr_name, hdr_value, attrs);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static
|
||||
std::ostream&
|
||||
write(std::ostream& os, const impl::header_entry& he)
|
||||
{
|
||||
std::string line = he.name() + ": " + he.value();
|
||||
impl::attrs_map as = he.attrs();
|
||||
for (impl::attrs_map::const_iterator iter = as.begin(); iter != as.end();
|
||||
iter++) {
|
||||
PRE((*iter).second.find('\"') == std::string::npos);
|
||||
line += "; " + (*iter).first + "=\"" + (*iter).second + "\"";
|
||||
}
|
||||
|
||||
os << line << "\n";
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace header
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Free functions.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
std::pair< size_t, impl::headers_map >
|
||||
impl::read_headers(std::istream& is, size_t curline)
|
||||
{
|
||||
using impl::format_error;
|
||||
|
||||
headers_map hm;
|
||||
|
||||
//
|
||||
// Grammar
|
||||
//
|
||||
// header = entry+ nl
|
||||
// entry = line nl
|
||||
// line = text colon text
|
||||
// (semicolon (text equal (text | dblquote string dblquote)))*
|
||||
// string = quoted_string
|
||||
//
|
||||
|
||||
header::tokenizer tkz(is, curline);
|
||||
impl::parser< header::tokenizer > p(tkz);
|
||||
|
||||
bool first = true;
|
||||
for (;;) {
|
||||
try {
|
||||
header_entry he;
|
||||
if (!header::read(p, he).good() || he.name().empty())
|
||||
break;
|
||||
|
||||
if (first && he.name() != "Content-Type")
|
||||
throw format_error("Could not determine content type");
|
||||
else
|
||||
first = false;
|
||||
|
||||
hm[he.name()] = he;
|
||||
} catch (const impl::parse_error& pe) {
|
||||
p.add_error(pe);
|
||||
p.reset(header::nl_type);
|
||||
}
|
||||
}
|
||||
|
||||
if (!is.good())
|
||||
throw format_error("Unexpected end of stream");
|
||||
|
||||
return std::pair< size_t, headers_map >(tkz.lineno(), hm);
|
||||
}
|
||||
|
||||
void
|
||||
impl::write_headers(const impl::headers_map& hm, std::ostream& os)
|
||||
{
|
||||
PRE(!hm.empty());
|
||||
headers_map::const_iterator ct = hm.find("Content-Type");
|
||||
PRE(ct != hm.end());
|
||||
header::write(os, (*ct).second);
|
||||
for (headers_map::const_iterator iter = hm.begin(); iter != hm.end();
|
||||
iter++) {
|
||||
if ((*iter).first != "Content-Type")
|
||||
header::write(os, (*iter).second);
|
||||
}
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
void
|
||||
impl::validate_content_type(const impl::headers_map& hm, const std::string& fmt,
|
||||
int version)
|
||||
{
|
||||
using impl::format_error;
|
||||
|
||||
headers_map::const_iterator iter = hm.find("Content-Type");
|
||||
if (iter == hm.end())
|
||||
throw format_error("Could not determine content type");
|
||||
|
||||
const header_entry& he = (*iter).second;
|
||||
if (he.value() != fmt)
|
||||
throw format_error("Mismatched content type: expected `" + fmt +
|
||||
"' but got `" + he.value() + "'");
|
||||
|
||||
if (!he.has_attr("version"))
|
||||
throw format_error("Could not determine version");
|
||||
const std::string& vstr = atf::text::to_string(version);
|
||||
if (he.get_attr("version") != vstr)
|
||||
throw format_error("Mismatched version: expected `" +
|
||||
vstr + "' but got `" +
|
||||
he.get_attr("version") + "'");
|
||||
}
|
@ -1,607 +0,0 @@
|
||||
//
|
||||
// Automated Testing Framework (atf)
|
||||
//
|
||||
// Copyright (c) 2007 The NetBSD Foundation, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
|
||||
// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#if !defined(_ATF_CXX_PARSER_HPP_)
|
||||
#define _ATF_CXX_PARSER_HPP_
|
||||
|
||||
#include <istream>
|
||||
#include <map>
|
||||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace atf {
|
||||
namespace parser {
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// The "parse_error" class.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
class parse_error : public std::runtime_error,
|
||||
public std::pair< size_t, std::string > {
|
||||
mutable std::string m_msg;
|
||||
|
||||
public:
|
||||
parse_error(size_t, std::string);
|
||||
~parse_error(void) throw();
|
||||
|
||||
const char* what(void) const throw();
|
||||
|
||||
operator std::string(void) const;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// The "parse_errors" class.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
class parse_errors : public std::runtime_error,
|
||||
public std::vector< parse_error > {
|
||||
std::vector< parse_error > m_errors;
|
||||
mutable std::string m_msg;
|
||||
|
||||
public:
|
||||
parse_errors(void);
|
||||
~parse_errors(void) throw();
|
||||
|
||||
const char* what(void) const throw();
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// The "format_error" class.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
class format_error : public std::runtime_error {
|
||||
public:
|
||||
format_error(const std::string&);
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// The "token" class.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
typedef int token_type;
|
||||
|
||||
//!
|
||||
//! \brief Representation of a read token.
|
||||
//!
|
||||
//! A pair that contains the information of a token read from a stream.
|
||||
//! It contains the token's type and its associated data, if any.
|
||||
//!
|
||||
struct token {
|
||||
bool m_inited;
|
||||
size_t m_line;
|
||||
token_type m_type;
|
||||
std::string m_text;
|
||||
|
||||
public:
|
||||
token(void);
|
||||
token(size_t, const token_type&, const std::string& = "");
|
||||
|
||||
size_t lineno(void) const;
|
||||
const token_type& type(void) const;
|
||||
const std::string& text(void) const;
|
||||
|
||||
operator bool(void) const;
|
||||
bool operator!(void) const;
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// The "tokenizer" class.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
//!
|
||||
//! \brief A stream tokenizer.
|
||||
//!
|
||||
//! This template implements an extremely simple, line-oriented stream
|
||||
//! tokenizer. It is only able to recognize one character-long delimiters,
|
||||
//! random-length keywords, skip whitespace and, anything that does not
|
||||
//! match these rules is supposed to be a word.
|
||||
//!
|
||||
//! Parameter IS: The input stream's type.
|
||||
//!
|
||||
template< class IS >
|
||||
class tokenizer {
|
||||
IS& m_is;
|
||||
size_t m_lineno;
|
||||
token m_la;
|
||||
|
||||
bool m_skipws;
|
||||
token_type m_eof_type, m_nl_type, m_text_type;
|
||||
|
||||
std::map< char, token_type > m_delims_map;
|
||||
std::string m_delims_str;
|
||||
|
||||
char m_quotech;
|
||||
token_type m_quotetype;
|
||||
|
||||
std::map< std::string, token_type > m_keywords_map;
|
||||
|
||||
token_type alloc_type(void);
|
||||
|
||||
template< class TKZ >
|
||||
friend
|
||||
class parser;
|
||||
|
||||
public:
|
||||
tokenizer(IS&, bool, const token_type&, const token_type&,
|
||||
const token_type&, size_t = 1);
|
||||
|
||||
size_t lineno(void) const;
|
||||
|
||||
void add_delim(char, const token_type&);
|
||||
void add_keyword(const std::string&, const token_type&);
|
||||
void add_quote(char, const token_type&);
|
||||
|
||||
token next(void);
|
||||
std::string rest_of_line(void);
|
||||
};
|
||||
|
||||
template< class IS >
|
||||
tokenizer< IS >::tokenizer(IS& p_is,
|
||||
bool p_skipws,
|
||||
const token_type& p_eof_type,
|
||||
const token_type& p_nl_type,
|
||||
const token_type& p_text_type,
|
||||
size_t p_lineno) :
|
||||
m_is(p_is),
|
||||
m_lineno(p_lineno),
|
||||
m_skipws(p_skipws),
|
||||
m_eof_type(p_eof_type),
|
||||
m_nl_type(p_nl_type),
|
||||
m_text_type(p_text_type),
|
||||
m_quotech(-1)
|
||||
{
|
||||
}
|
||||
|
||||
template< class IS >
|
||||
size_t
|
||||
tokenizer< IS >::lineno(void)
|
||||
const
|
||||
{
|
||||
return m_lineno;
|
||||
}
|
||||
|
||||
template< class IS >
|
||||
void
|
||||
tokenizer< IS >::add_delim(char delim, const token_type& type)
|
||||
{
|
||||
m_delims_map[delim] = type;
|
||||
m_delims_str += delim;
|
||||
}
|
||||
|
||||
template< class IS >
|
||||
void
|
||||
tokenizer< IS >::add_keyword(const std::string& keyword,
|
||||
const token_type& type)
|
||||
{
|
||||
m_keywords_map[keyword] = type;
|
||||
}
|
||||
|
||||
template< class IS >
|
||||
void
|
||||
tokenizer< IS >::add_quote(char ch, const token_type& type)
|
||||
{
|
||||
m_quotech = ch;
|
||||
m_quotetype = type;
|
||||
}
|
||||
|
||||
template< class IS >
|
||||
token
|
||||
tokenizer< IS >::next(void)
|
||||
{
|
||||
if (m_la) {
|
||||
token t = m_la;
|
||||
m_la = token();
|
||||
if (t.type() == m_nl_type)
|
||||
m_lineno++;
|
||||
return t;
|
||||
}
|
||||
|
||||
char ch;
|
||||
std::string text;
|
||||
|
||||
bool done = false, quoted = false;
|
||||
token t(m_lineno, m_eof_type, "<<EOF>>");
|
||||
while (!done && m_is.get(ch).good()) {
|
||||
if (ch == m_quotech) {
|
||||
if (text.empty()) {
|
||||
bool escaped = false;
|
||||
while (!done && m_is.get(ch).good()) {
|
||||
if (!escaped) {
|
||||
if (ch == '\\')
|
||||
escaped = true;
|
||||
else if (ch == '\n') {
|
||||
m_la = token(m_lineno, m_nl_type, "<<NEWLINE>>");
|
||||
throw parse_error(t.lineno(),
|
||||
"Missing double quotes before "
|
||||
"end of line");
|
||||
} else if (ch == m_quotech)
|
||||
done = true;
|
||||
else
|
||||
text += ch;
|
||||
} else {
|
||||
text += ch;
|
||||
escaped = false;
|
||||
}
|
||||
}
|
||||
if (!m_is.good())
|
||||
throw parse_error(t.lineno(),
|
||||
"Missing double quotes before "
|
||||
"end of file");
|
||||
t = token(m_lineno, m_text_type, text);
|
||||
quoted = true;
|
||||
} else {
|
||||
m_is.putback(ch);
|
||||
done = true;
|
||||
}
|
||||
} else {
|
||||
typename std::map< char, token_type >::const_iterator idelim;
|
||||
idelim = m_delims_map.find(ch);
|
||||
if (idelim != m_delims_map.end()) {
|
||||
done = true;
|
||||
if (text.empty())
|
||||
t = token(m_lineno, (*idelim).second,
|
||||
std::string("") + ch);
|
||||
else
|
||||
m_is.putback(ch);
|
||||
} else if (ch == '\n') {
|
||||
done = true;
|
||||
if (text.empty())
|
||||
t = token(m_lineno, m_nl_type, "<<NEWLINE>>");
|
||||
else
|
||||
m_is.putback(ch);
|
||||
} else if (m_skipws && (ch == ' ' || ch == '\t')) {
|
||||
if (!text.empty())
|
||||
done = true;
|
||||
} else
|
||||
text += ch;
|
||||
}
|
||||
}
|
||||
|
||||
if (!quoted && !text.empty()) {
|
||||
typename std::map< std::string, token_type >::const_iterator ikw;
|
||||
ikw = m_keywords_map.find(text);
|
||||
if (ikw != m_keywords_map.end())
|
||||
t = token(m_lineno, (*ikw).second, text);
|
||||
else
|
||||
t = token(m_lineno, m_text_type, text);
|
||||
}
|
||||
|
||||
if (t.type() == m_nl_type)
|
||||
m_lineno++;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
template< class IS >
|
||||
std::string
|
||||
tokenizer< IS >::rest_of_line(void)
|
||||
{
|
||||
std::string str;
|
||||
while (m_is.good() && m_is.peek() != '\n')
|
||||
str += m_is.get();
|
||||
return str;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// The "parser" class.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
template< class TKZ >
|
||||
class parser {
|
||||
TKZ& m_tkz;
|
||||
token m_last;
|
||||
parse_errors m_errors;
|
||||
bool m_thrown;
|
||||
|
||||
public:
|
||||
parser(TKZ& tkz);
|
||||
~parser(void);
|
||||
|
||||
bool good(void) const;
|
||||
void add_error(const parse_error&);
|
||||
bool has_errors(void) const;
|
||||
|
||||
token next(void);
|
||||
std::string rest_of_line(void);
|
||||
token reset(const token_type&);
|
||||
|
||||
token
|
||||
expect(const token_type&,
|
||||
const std::string&);
|
||||
|
||||
token
|
||||
expect(const token_type&,
|
||||
const token_type&,
|
||||
const std::string&);
|
||||
|
||||
token
|
||||
expect(const token_type&,
|
||||
const token_type&,
|
||||
const token_type&,
|
||||
const std::string&);
|
||||
|
||||
token
|
||||
expect(const token_type&,
|
||||
const token_type&,
|
||||
const token_type&,
|
||||
const token_type&,
|
||||
const std::string&);
|
||||
|
||||
token
|
||||
expect(const token_type&,
|
||||
const token_type&,
|
||||
const token_type&,
|
||||
const token_type&,
|
||||
const token_type&,
|
||||
const token_type&,
|
||||
const token_type&,
|
||||
const std::string&);
|
||||
|
||||
token
|
||||
expect(const token_type&,
|
||||
const token_type&,
|
||||
const token_type&,
|
||||
const token_type&,
|
||||
const token_type&,
|
||||
const token_type&,
|
||||
const token_type&,
|
||||
const token_type&,
|
||||
const std::string&);
|
||||
};
|
||||
|
||||
template< class TKZ >
|
||||
parser< TKZ >::parser(TKZ& tkz) :
|
||||
m_tkz(tkz),
|
||||
m_thrown(false)
|
||||
{
|
||||
}
|
||||
|
||||
template< class TKZ >
|
||||
parser< TKZ >::~parser(void)
|
||||
{
|
||||
if (!m_errors.empty() && !m_thrown)
|
||||
throw m_errors;
|
||||
}
|
||||
|
||||
template< class TKZ >
|
||||
bool
|
||||
parser< TKZ >::good(void)
|
||||
const
|
||||
{
|
||||
return m_tkz.m_is.good();
|
||||
}
|
||||
|
||||
template< class TKZ >
|
||||
void
|
||||
parser< TKZ >::add_error(const parse_error& pe)
|
||||
{
|
||||
m_errors.push_back(pe);
|
||||
}
|
||||
|
||||
template< class TKZ >
|
||||
bool
|
||||
parser< TKZ >::has_errors(void)
|
||||
const
|
||||
{
|
||||
return !m_errors.empty();
|
||||
}
|
||||
|
||||
template< class TKZ >
|
||||
token
|
||||
parser< TKZ >::next(void)
|
||||
{
|
||||
token t = m_tkz.next();
|
||||
|
||||
m_last = t;
|
||||
|
||||
if (t.type() == m_tkz.m_eof_type) {
|
||||
if (!m_errors.empty()) {
|
||||
m_thrown = true;
|
||||
throw m_errors;
|
||||
}
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
template< class TKZ >
|
||||
std::string
|
||||
parser< TKZ >::rest_of_line(void)
|
||||
{
|
||||
return m_tkz.rest_of_line();
|
||||
}
|
||||
|
||||
template< class TKZ >
|
||||
token
|
||||
parser< TKZ >::reset(const token_type& stop)
|
||||
{
|
||||
token t = m_last;
|
||||
|
||||
while (t.type() != m_tkz.m_eof_type && t.type() != stop)
|
||||
t = next();
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
template< class TKZ >
|
||||
token
|
||||
parser< TKZ >::expect(const token_type& t1,
|
||||
const std::string& textual)
|
||||
{
|
||||
token t = next();
|
||||
|
||||
if (t.type() != t1)
|
||||
throw parse_error(t.lineno(),
|
||||
"Unexpected token `" + t.text() +
|
||||
"'; expected " + textual);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
template< class TKZ >
|
||||
token
|
||||
parser< TKZ >::expect(const token_type& t1,
|
||||
const token_type& t2,
|
||||
const std::string& textual)
|
||||
{
|
||||
token t = next();
|
||||
|
||||
if (t.type() != t1 && t.type() != t2)
|
||||
throw parse_error(t.lineno(),
|
||||
"Unexpected token `" + t.text() +
|
||||
"'; expected " + textual);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
template< class TKZ >
|
||||
token
|
||||
parser< TKZ >::expect(const token_type& t1,
|
||||
const token_type& t2,
|
||||
const token_type& t3,
|
||||
const std::string& textual)
|
||||
{
|
||||
token t = next();
|
||||
|
||||
if (t.type() != t1 && t.type() != t2 && t.type() != t3)
|
||||
throw parse_error(t.lineno(),
|
||||
"Unexpected token `" + t.text() +
|
||||
"'; expected " + textual);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
template< class TKZ >
|
||||
token
|
||||
parser< TKZ >::expect(const token_type& t1,
|
||||
const token_type& t2,
|
||||
const token_type& t3,
|
||||
const token_type& t4,
|
||||
const std::string& textual)
|
||||
{
|
||||
token t = next();
|
||||
|
||||
if (t.type() != t1 && t.type() != t2 && t.type() != t3 &&
|
||||
t.type() != t4)
|
||||
throw parse_error(t.lineno(),
|
||||
"Unexpected token `" + t.text() +
|
||||
"'; expected " + textual);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
template< class TKZ >
|
||||
token
|
||||
parser< TKZ >::expect(const token_type& t1,
|
||||
const token_type& t2,
|
||||
const token_type& t3,
|
||||
const token_type& t4,
|
||||
const token_type& t5,
|
||||
const token_type& t6,
|
||||
const token_type& t7,
|
||||
const std::string& textual)
|
||||
{
|
||||
token t = next();
|
||||
|
||||
if (t.type() != t1 && t.type() != t2 && t.type() != t3 &&
|
||||
t.type() != t4 && t.type() != t5 && t.type() != t6 &&
|
||||
t.type() != t7)
|
||||
throw parse_error(t.lineno(),
|
||||
"Unexpected token `" + t.text() +
|
||||
"'; expected " + textual);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
template< class TKZ >
|
||||
token
|
||||
parser< TKZ >::expect(const token_type& t1,
|
||||
const token_type& t2,
|
||||
const token_type& t3,
|
||||
const token_type& t4,
|
||||
const token_type& t5,
|
||||
const token_type& t6,
|
||||
const token_type& t7,
|
||||
const token_type& t8,
|
||||
const std::string& textual)
|
||||
{
|
||||
token t = next();
|
||||
|
||||
if (t.type() != t1 && t.type() != t2 && t.type() != t3 &&
|
||||
t.type() != t4 && t.type() != t5 && t.type() != t6 &&
|
||||
t.type() != t7 && t.type() != t8)
|
||||
throw parse_error(t.lineno(),
|
||||
"Unexpected token `" + t.text() +
|
||||
"'; expected " + textual);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
#define ATF_PARSER_CALLBACK(parser, func) \
|
||||
do { \
|
||||
if (!(parser).has_errors()) \
|
||||
func; \
|
||||
} while (false)
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Header parsing.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
typedef std::map< std::string, std::string > attrs_map;
|
||||
|
||||
class header_entry {
|
||||
std::string m_name;
|
||||
std::string m_value;
|
||||
attrs_map m_attrs;
|
||||
|
||||
public:
|
||||
header_entry(void);
|
||||
header_entry(const std::string&, const std::string&,
|
||||
attrs_map = attrs_map());
|
||||
|
||||
const std::string& name(void) const;
|
||||
const std::string& value(void) const;
|
||||
const attrs_map& attrs(void) const;
|
||||
bool has_attr(const std::string&) const;
|
||||
const std::string& get_attr(const std::string&) const;
|
||||
};
|
||||
|
||||
typedef std::map< std::string, header_entry > headers_map;
|
||||
|
||||
std::pair< size_t, headers_map > read_headers(std::istream&, size_t);
|
||||
void write_headers(const headers_map&, std::ostream&);
|
||||
void validate_content_type(const headers_map&, const std::string&, int);
|
||||
|
||||
} // namespace parser
|
||||
} // namespace atf
|
||||
|
||||
#endif // !defined(_ATF_CXX_PARSER_HPP_)
|
File diff suppressed because it is too large
Load Diff
@ -52,28 +52,24 @@ static const char* atf_c_tests_base = NULL;
|
||||
#endif
|
||||
#undef ATF_C_TESTS_BASE
|
||||
|
||||
void
|
||||
build_check_cxx_o_aux(const atf::fs::path& sfile, const char* failmsg,
|
||||
const bool expect_pass)
|
||||
bool
|
||||
build_check_cxx_o(const char* sfile)
|
||||
{
|
||||
std::vector< std::string > optargs;
|
||||
optargs.push_back("-I" + atf::config::get("atf_includedir"));
|
||||
optargs.push_back("-Wall");
|
||||
optargs.push_back("-Werror");
|
||||
|
||||
const bool result = atf::check::build_cxx_o(
|
||||
sfile.str(), "test.o", atf::process::argv_array(optargs));
|
||||
if ((expect_pass && !result) || (!expect_pass && result))
|
||||
ATF_FAIL(failmsg);
|
||||
return atf::check::build_cxx_o(sfile, "test.o",
|
||||
atf::process::argv_array(optargs));
|
||||
}
|
||||
|
||||
void
|
||||
build_check_cxx_o(const atf::tests::tc& tc, const char* sfile,
|
||||
const char* failmsg, const bool expect_pass)
|
||||
bool
|
||||
build_check_cxx_o_srcdir(const atf::tests::tc& tc, const char* sfile)
|
||||
{
|
||||
const atf::fs::path sfilepath =
|
||||
atf::fs::path(tc.get_config_var("srcdir")) / sfile;
|
||||
build_check_cxx_o_aux(sfilepath, failmsg, expect_pass);
|
||||
return build_check_cxx_o(sfilepath.c_str());
|
||||
}
|
||||
|
||||
void
|
||||
@ -86,7 +82,8 @@ header_check(const char *hdrname)
|
||||
|
||||
const std::string failmsg = std::string("Header check failed; ") +
|
||||
hdrname + " is not self-contained";
|
||||
build_check_cxx_o_aux(atf::fs::path("test.cpp"), failmsg.c_str(), true);
|
||||
if (!build_check_cxx_o("test.cpp"))
|
||||
ATF_FAIL(failmsg);
|
||||
}
|
||||
|
||||
atf::fs::path
|
||||
@ -104,37 +101,3 @@ get_process_helpers_path(const atf::tests::tc& tc, bool is_detail)
|
||||
return atf::fs::path(atf_c_tests_base) / helper;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_helpers_detail::check_equal(const char* expected[],
|
||||
const string_vector& actual)
|
||||
{
|
||||
const char** expected_iter = expected;
|
||||
string_vector::const_iterator actual_iter = actual.begin();
|
||||
|
||||
bool equals = true;
|
||||
while (equals && *expected_iter != NULL && actual_iter != actual.end()) {
|
||||
if (*expected_iter != *actual_iter) {
|
||||
equals = false;
|
||||
} else {
|
||||
expected_iter++;
|
||||
actual_iter++;
|
||||
}
|
||||
}
|
||||
if (equals && ((*expected_iter == NULL && actual_iter != actual.end()) ||
|
||||
(*expected_iter != NULL && actual_iter == actual.end())))
|
||||
equals = false;
|
||||
|
||||
if (!equals) {
|
||||
std::cerr << "EXPECTED:\n";
|
||||
for (expected_iter = expected; *expected_iter != NULL; expected_iter++)
|
||||
std::cerr << *expected_iter << "\n";
|
||||
|
||||
std::cerr << "ACTUAL:\n";
|
||||
for (actual_iter = actual.begin(); actual_iter != actual.end();
|
||||
actual_iter++)
|
||||
std::cerr << *actual_iter << "\n";
|
||||
|
||||
ATF_FAIL("Expected results differ to actual values");
|
||||
}
|
||||
}
|
||||
|
@ -40,9 +40,7 @@
|
||||
|
||||
#include "../macros.hpp"
|
||||
#include "../tests.hpp"
|
||||
#include "parser.hpp"
|
||||
#include "process.hpp"
|
||||
#include "text.hpp"
|
||||
|
||||
#define HEADER_TC(name, hdrname) \
|
||||
ATF_TEST_CASE(name); \
|
||||
@ -64,18 +62,8 @@
|
||||
} \
|
||||
ATF_TEST_CASE_BODY(name) \
|
||||
{ \
|
||||
build_check_cxx_o(*this, sfile, failmsg, true); \
|
||||
}
|
||||
|
||||
#define BUILD_TC_FAIL(name, sfile, descr, failmsg) \
|
||||
ATF_TEST_CASE(name); \
|
||||
ATF_TEST_CASE_HEAD(name) \
|
||||
{ \
|
||||
set_md_var("descr", descr); \
|
||||
} \
|
||||
ATF_TEST_CASE_BODY(name) \
|
||||
{ \
|
||||
build_check_cxx_o(*this, sfile, failmsg, false); \
|
||||
if (!build_check_cxx_o_srcdir(*this, sfile)) \
|
||||
ATF_FAIL(failmsg); \
|
||||
}
|
||||
|
||||
namespace atf {
|
||||
@ -85,7 +73,8 @@ class tc;
|
||||
}
|
||||
|
||||
void header_check(const char*);
|
||||
void build_check_cxx_o(const atf::tests::tc&, const char*, const char*, bool);
|
||||
bool build_check_cxx_o(const char*);
|
||||
bool build_check_cxx_o_srcdir(const atf::tests::tc&, const char*);
|
||||
atf::fs::path get_process_helpers_path(const atf::tests::tc&, bool);
|
||||
|
||||
struct run_h_tc_data {
|
||||
@ -120,45 +109,3 @@ run_h_tc(atf::tests::vars_map config = atf::tests::vars_map())
|
||||
const atf::process::status s = c.wait();
|
||||
ATF_REQUIRE(s.exited());
|
||||
}
|
||||
|
||||
namespace test_helpers_detail {
|
||||
|
||||
typedef std::vector< std::string > string_vector;
|
||||
|
||||
template< class Reader >
|
||||
std::pair< string_vector, string_vector >
|
||||
do_read(const char* input)
|
||||
{
|
||||
string_vector errors;
|
||||
|
||||
std::istringstream is(input);
|
||||
Reader reader(is);
|
||||
try {
|
||||
reader.read();
|
||||
} catch (const atf::parser::parse_errors& pes) {
|
||||
for (std::vector< atf::parser::parse_error >::const_iterator iter =
|
||||
pes.begin(); iter != pes.end(); iter++)
|
||||
errors.push_back(*iter);
|
||||
} catch (const atf::parser::parse_error& pe) {
|
||||
ATF_FAIL("Raised a lonely parse error: " +
|
||||
atf::text::to_string(pe.first) + ": " + pe.second);
|
||||
}
|
||||
|
||||
return std::make_pair(reader.m_calls, errors);
|
||||
}
|
||||
|
||||
void check_equal(const char*[], const string_vector&);
|
||||
|
||||
} // namespace test_helpers_detail
|
||||
|
||||
template< class Reader >
|
||||
void
|
||||
do_parser_test(const char* input, const char* exp_calls[],
|
||||
const char* exp_errors[])
|
||||
{
|
||||
const std::pair< test_helpers_detail::string_vector,
|
||||
test_helpers_detail::string_vector >
|
||||
actual = test_helpers_detail::do_read< Reader >(input);
|
||||
test_helpers_detail::check_equal(exp_calls, actual.first);
|
||||
test_helpers_detail::check_equal(exp_errors, actual.second);
|
||||
}
|
||||
|
@ -1,173 +0,0 @@
|
||||
//
|
||||
// Automated Testing Framework (atf)
|
||||
//
|
||||
// Copyright (c) 2007 The NetBSD Foundation, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
|
||||
// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
extern "C" {
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
}
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "env.hpp"
|
||||
#include "text.hpp"
|
||||
#include "sanity.hpp"
|
||||
#include "text.hpp"
|
||||
#include "ui.hpp"
|
||||
|
||||
namespace impl = atf::ui;
|
||||
#define IMPL_NAME "atf::ui"
|
||||
|
||||
static
|
||||
size_t
|
||||
terminal_width(void)
|
||||
{
|
||||
static bool done = false;
|
||||
static size_t width = 0;
|
||||
|
||||
if (!done) {
|
||||
if (atf::env::has("COLUMNS")) {
|
||||
const std::string cols = atf::env::get("COLUMNS");
|
||||
if (cols.length() > 0) {
|
||||
width = atf::text::to_type< size_t >(cols);
|
||||
}
|
||||
} else {
|
||||
struct winsize ws;
|
||||
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1)
|
||||
width = ws.ws_col;
|
||||
}
|
||||
|
||||
if (width >= 80)
|
||||
width -= 5;
|
||||
|
||||
done = true;
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
static
|
||||
std::string
|
||||
format_paragraph(const std::string& text,
|
||||
const std::string& tag,
|
||||
const bool first,
|
||||
const bool repeat,
|
||||
const size_t col)
|
||||
{
|
||||
PRE(text.find('\n') == std::string::npos);
|
||||
|
||||
const std::string pad(col - tag.length(), ' ');
|
||||
const std::string fullpad(col, ' ');
|
||||
|
||||
std::string formatted;
|
||||
if (first || repeat)
|
||||
formatted = tag + pad;
|
||||
else
|
||||
formatted = fullpad;
|
||||
INV(formatted.length() == col);
|
||||
size_t curcol = col;
|
||||
|
||||
const size_t maxcol = terminal_width();
|
||||
|
||||
std::vector< std::string > words = atf::text::split(text, " ");
|
||||
for (std::vector< std::string >::const_iterator iter = words.begin();
|
||||
iter != words.end(); iter++) {
|
||||
const std::string& word = *iter;
|
||||
|
||||
if (iter != words.begin() && maxcol > 0 &&
|
||||
curcol + word.length() + 1 > maxcol) {
|
||||
if (repeat)
|
||||
formatted += '\n' + tag + pad;
|
||||
else
|
||||
formatted += '\n' + fullpad;
|
||||
curcol = col;
|
||||
} else if (iter != words.begin()) {
|
||||
formatted += ' ';
|
||||
curcol++;
|
||||
}
|
||||
|
||||
formatted += word;
|
||||
curcol += word.length();
|
||||
}
|
||||
|
||||
return formatted;
|
||||
}
|
||||
|
||||
std::string
|
||||
impl::format_error(const std::string& prog_name, const std::string& error)
|
||||
{
|
||||
return format_text_with_tag("ERROR: " + error, prog_name + ": ", true);
|
||||
}
|
||||
|
||||
std::string
|
||||
impl::format_info(const std::string& prog_name, const std::string& msg)
|
||||
{
|
||||
return format_text_with_tag(msg, prog_name + ": ", true);
|
||||
}
|
||||
|
||||
std::string
|
||||
impl::format_text(const std::string& text)
|
||||
{
|
||||
return format_text_with_tag(text, "", false, 0);
|
||||
}
|
||||
|
||||
std::string
|
||||
impl::format_text_with_tag(const std::string& text, const std::string& tag,
|
||||
bool repeat, size_t col)
|
||||
{
|
||||
PRE(col == 0 || col >= tag.length());
|
||||
if (col == 0)
|
||||
col = tag.length();
|
||||
|
||||
std::string formatted;
|
||||
|
||||
std::vector< std::string > lines = atf::text::split(text, "\n");
|
||||
for (std::vector< std::string >::const_iterator iter = lines.begin();
|
||||
iter != lines.end(); iter++) {
|
||||
const std::string& line = *iter;
|
||||
|
||||
formatted += format_paragraph(line, tag, iter == lines.begin(),
|
||||
repeat, col);
|
||||
if (iter + 1 != lines.end()) {
|
||||
if (repeat)
|
||||
formatted += "\n" + tag + "\n";
|
||||
else
|
||||
formatted += "\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
return formatted;
|
||||
}
|
||||
|
||||
std::string
|
||||
impl::format_warning(const std::string& prog_name, const std::string& error)
|
||||
{
|
||||
return format_text_with_tag("WARNING: " + error, prog_name + ": ", true);
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
//
|
||||
// Automated Testing Framework (atf)
|
||||
//
|
||||
// Copyright (c) 2007 The NetBSD Foundation, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
|
||||
// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#if !defined(_ATF_CXX_UI_HPP_)
|
||||
#define _ATF_CXX_UI_HPP_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace atf {
|
||||
namespace ui {
|
||||
|
||||
//!
|
||||
//! \brief Formats an error message to fit on screen.
|
||||
//!
|
||||
//! Given the program's name and an error message, properly formats it to
|
||||
//! fit on screen.
|
||||
//!
|
||||
//! The program's name is not stored globally to prevent the usage of this
|
||||
//! function from inside the library. Making it a explicit parameter
|
||||
//! restricts its usage to the frontend.
|
||||
//!
|
||||
std::string format_error(const std::string&, const std::string&);
|
||||
|
||||
//!
|
||||
//! \brief Formats an informational message to fit on screen.
|
||||
//!
|
||||
//! Given the program's name and an informational message, properly formats
|
||||
//! it to fit on screen.
|
||||
//!
|
||||
//! The program's name is not stored globally to prevent the usage of this
|
||||
//! function from inside the library. Making it a explicit parameter
|
||||
//! restricts its usage to the frontend.
|
||||
//!
|
||||
std::string format_info(const std::string&, const std::string&);
|
||||
|
||||
//!
|
||||
//! \brief Formats a block of text to fit nicely on screen.
|
||||
//!
|
||||
//! Given a text, which is composed of multiple paragraphs separated by
|
||||
//! a single '\n' character, reformats it to fill on the current screen's
|
||||
//! width with proper line wrapping.
|
||||
//!
|
||||
//! This is just a special case of format_text_with_tag, provided for
|
||||
//! simplicity.
|
||||
//!
|
||||
std::string format_text(const std::string&);
|
||||
|
||||
//!
|
||||
//! \brief Formats a block of text to fit nicely on screen, prepending a
|
||||
//! tag to it.
|
||||
//!
|
||||
//! Given a text, which is composed of multiple paragraphs separated by
|
||||
//! a single '\n' character, reformats it to fill on the current screen's
|
||||
//! width with proper line wrapping. The text is prepended with a tag;
|
||||
//! i.e. a word that is printed at the beginning of the first paragraph and
|
||||
//! optionally repeated at the beginning of each word. The last parameter
|
||||
//! specifies the column on which the text should start, and that position
|
||||
//! must be greater than the tag's length or 0, in which case it
|
||||
//! automatically takes the correct value.
|
||||
//!
|
||||
std::string format_text_with_tag(const std::string&, const std::string&,
|
||||
bool, size_t = 0);
|
||||
|
||||
//!
|
||||
//! \brief Formats a warning message to fit on screen.
|
||||
//!
|
||||
//! Given the program's name and a warning message, properly formats it to
|
||||
//! fit on screen.
|
||||
//!
|
||||
//! The program's name is not stored globally to prevent the usage of this
|
||||
//! function from inside the library. Making it a explicit parameter
|
||||
//! restricts its usage to the frontend.
|
||||
//!
|
||||
std::string format_warning(const std::string&, const std::string&);
|
||||
|
||||
} // namespace ui
|
||||
} // namespace atf
|
||||
|
||||
#endif // !defined(_ATF_CXX_UI_HPP_)
|
@ -1,462 +0,0 @@
|
||||
//
|
||||
// Automated Testing Framework (atf)
|
||||
//
|
||||
// Copyright (c) 2009 The NetBSD Foundation, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
|
||||
// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
#include "../macros.hpp"
|
||||
|
||||
#include "env.hpp"
|
||||
#include "ui.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Test cases for the free functions.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
struct test {
|
||||
const char *tc;
|
||||
const char *tag;
|
||||
bool repeat;
|
||||
size_t col;
|
||||
const char *fmt;
|
||||
const char *result;
|
||||
} tests[] = {
|
||||
//
|
||||
// wo_tag
|
||||
//
|
||||
|
||||
{
|
||||
"wo_tag",
|
||||
"",
|
||||
false,
|
||||
0,
|
||||
"12345",
|
||||
"12345",
|
||||
},
|
||||
|
||||
{
|
||||
"wo_tag",
|
||||
"",
|
||||
false,
|
||||
0,
|
||||
"12345 ",
|
||||
"12345",
|
||||
},
|
||||
|
||||
{
|
||||
"wo_tag",
|
||||
"",
|
||||
false,
|
||||
0,
|
||||
"12345 7890",
|
||||
"12345 7890",
|
||||
},
|
||||
|
||||
{
|
||||
"wo_tag",
|
||||
"",
|
||||
false,
|
||||
0,
|
||||
"12345 789012 45",
|
||||
"12345 789012 45",
|
||||
},
|
||||
|
||||
{
|
||||
"wo_tag",
|
||||
"",
|
||||
false,
|
||||
0,
|
||||
"12345 789012 456",
|
||||
"12345 789012\n456",
|
||||
},
|
||||
|
||||
{
|
||||
"wo_tag",
|
||||
"",
|
||||
false,
|
||||
0,
|
||||
"1234567890123456",
|
||||
"1234567890123456",
|
||||
},
|
||||
|
||||
// TODO(jmmv): Fix the code to pass this test...
|
||||
// {
|
||||
// "wo_tag",
|
||||
// "",
|
||||
// false,
|
||||
// 0,
|
||||
// " 2345678901234567",
|
||||
// "\n2345678901234567",
|
||||
// },
|
||||
|
||||
{
|
||||
"wo_tag",
|
||||
"",
|
||||
false,
|
||||
0,
|
||||
"12345 789012345 78",
|
||||
"12345 789012345\n78",
|
||||
},
|
||||
|
||||
//
|
||||
// wo_tag_col
|
||||
//
|
||||
|
||||
{
|
||||
"wo_tag_col",
|
||||
"",
|
||||
false,
|
||||
10,
|
||||
"12345",
|
||||
" 12345",
|
||||
},
|
||||
|
||||
{
|
||||
"wo_tag_col",
|
||||
"",
|
||||
false,
|
||||
10,
|
||||
"12345 7890",
|
||||
" 12345\n"
|
||||
" 7890",
|
||||
},
|
||||
|
||||
{
|
||||
"wo_tag_col",
|
||||
"",
|
||||
false,
|
||||
10,
|
||||
"1 3 5 7 9",
|
||||
" 1 3 5\n"
|
||||
" 7 9",
|
||||
},
|
||||
|
||||
//
|
||||
// w_tag_no_repeat
|
||||
//
|
||||
|
||||
{
|
||||
"w_tag_no_repeat",
|
||||
"1234: ",
|
||||
false,
|
||||
0,
|
||||
"789012345",
|
||||
"1234: 789012345",
|
||||
},
|
||||
|
||||
{
|
||||
"w_tag_no_repeat",
|
||||
"1234: ",
|
||||
false,
|
||||
0,
|
||||
"789 1234 56789",
|
||||
"1234: 789 1234\n"
|
||||
" 56789",
|
||||
},
|
||||
|
||||
{
|
||||
"w_tag_no_repeat",
|
||||
"1234: ",
|
||||
false,
|
||||
0,
|
||||
"789012345",
|
||||
"1234: 789012345",
|
||||
},
|
||||
|
||||
{
|
||||
"w_tag_no_repeat",
|
||||
"1234: ",
|
||||
false,
|
||||
0,
|
||||
"789012345 7890",
|
||||
"1234: 789012345\n"
|
||||
" 7890",
|
||||
},
|
||||
|
||||
//
|
||||
// w_tag_repeat
|
||||
//
|
||||
|
||||
{
|
||||
"w_tag_repeat",
|
||||
"1234: ",
|
||||
true,
|
||||
0,
|
||||
"789012345",
|
||||
"1234: 789012345",
|
||||
},
|
||||
|
||||
{
|
||||
"w_tag_repeat",
|
||||
"1234: ",
|
||||
true,
|
||||
0,
|
||||
"789 1234 56789",
|
||||
"1234: 789 1234\n"
|
||||
"1234: 56789",
|
||||
},
|
||||
|
||||
{
|
||||
"w_tag_repeat",
|
||||
"1234: ",
|
||||
true,
|
||||
0,
|
||||
"789012345",
|
||||
"1234: 789012345",
|
||||
},
|
||||
|
||||
{
|
||||
"w_tag_no_repeat",
|
||||
"1234: ",
|
||||
true,
|
||||
0,
|
||||
"789012345 7890",
|
||||
"1234: 789012345\n"
|
||||
"1234: 7890",
|
||||
},
|
||||
|
||||
//
|
||||
// w_tag_col
|
||||
//
|
||||
|
||||
{
|
||||
"w_tag_col",
|
||||
"1234:",
|
||||
false,
|
||||
10,
|
||||
"1 3 5",
|
||||
"1234: 1 3 5",
|
||||
},
|
||||
|
||||
{
|
||||
"w_tag_col",
|
||||
"1234:",
|
||||
false,
|
||||
10,
|
||||
"1 3 5 7 9",
|
||||
"1234: 1 3 5\n"
|
||||
" 7 9",
|
||||
},
|
||||
|
||||
{
|
||||
"w_tag_col",
|
||||
"1234:",
|
||||
true,
|
||||
10,
|
||||
"1 3 5 7 9",
|
||||
"1234: 1 3 5\n"
|
||||
"1234: 7 9",
|
||||
},
|
||||
|
||||
//
|
||||
// paragraphs
|
||||
//
|
||||
|
||||
{
|
||||
"paragraphs",
|
||||
"",
|
||||
false,
|
||||
0,
|
||||
"1 3 5\n\n",
|
||||
"1 3 5"
|
||||
},
|
||||
|
||||
{
|
||||
"paragraphs",
|
||||
"",
|
||||
false,
|
||||
0,
|
||||
"1 3 5\n2 4 6",
|
||||
"1 3 5\n\n2 4 6"
|
||||
},
|
||||
|
||||
{
|
||||
"paragraphs",
|
||||
"",
|
||||
false,
|
||||
0,
|
||||
"1234 6789 123456\n2 4 6",
|
||||
"1234 6789\n123456\n\n2 4 6"
|
||||
},
|
||||
|
||||
{
|
||||
"paragraphs",
|
||||
"12: ",
|
||||
false,
|
||||
0,
|
||||
"56789 123456\n2 4 6",
|
||||
"12: 56789\n 123456\n\n 2 4 6"
|
||||
},
|
||||
|
||||
{
|
||||
"paragraphs",
|
||||
"12: ",
|
||||
true,
|
||||
0,
|
||||
"56789 123456\n2 4 6",
|
||||
"12: 56789\n12: 123456\n12: \n12: 2 4 6"
|
||||
},
|
||||
|
||||
{
|
||||
"paragraphs",
|
||||
"12:",
|
||||
false,
|
||||
4,
|
||||
"56789 123456\n2 4 6",
|
||||
"12: 56789\n 123456\n\n 2 4 6"
|
||||
},
|
||||
|
||||
{
|
||||
"paragraphs",
|
||||
"12:",
|
||||
true,
|
||||
4,
|
||||
"56789 123456\n2 4 6",
|
||||
"12: 56789\n12: 123456\n12:\n12: 2 4 6"
|
||||
},
|
||||
|
||||
//
|
||||
// end
|
||||
//
|
||||
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
false,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
},
|
||||
};
|
||||
|
||||
static
|
||||
void
|
||||
run_tests(const char *tc)
|
||||
{
|
||||
struct test *t;
|
||||
|
||||
std::cout << "Running tests for " << tc << "\n";
|
||||
|
||||
atf::env::set("COLUMNS", "15");
|
||||
|
||||
for (t = &tests[0]; t->tc != NULL; t++) {
|
||||
if (std::strcmp(t->tc, tc) == 0) {
|
||||
std::cout << "\n";
|
||||
std::cout << "Testing with tag '" << t->tag << "', '"
|
||||
<< (t->repeat ? "repeat" : "no repeat") << "', col "
|
||||
<< t->col << "\n";
|
||||
std::cout << "Input: >>>" << t->fmt << "<<<\n";
|
||||
std::cout << "Expected output: >>>" << t->result << "<<<\n";
|
||||
|
||||
std::string result = atf::ui::format_text_with_tag(t->fmt, t->tag,
|
||||
t->repeat, t->col);
|
||||
std::cout << "Output : >>>" << result << "<<<\n";
|
||||
ATF_REQUIRE_EQ(t->result, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ATF_TEST_CASE(wo_tag);
|
||||
ATF_TEST_CASE_HEAD(wo_tag)
|
||||
{
|
||||
set_md_var("descr", "Checks formatting without tags");
|
||||
}
|
||||
ATF_TEST_CASE_BODY(wo_tag)
|
||||
{
|
||||
run_tests("wo_tag");
|
||||
}
|
||||
|
||||
ATF_TEST_CASE(wo_tag_col);
|
||||
ATF_TEST_CASE_HEAD(wo_tag_col)
|
||||
{
|
||||
set_md_var("descr", "Checks formatting without tags and with a non-zero "
|
||||
"starting column");
|
||||
}
|
||||
ATF_TEST_CASE_BODY(wo_tag_col)
|
||||
{
|
||||
run_tests("wo_tag_col");
|
||||
}
|
||||
|
||||
ATF_TEST_CASE(w_tag_no_repeat);
|
||||
ATF_TEST_CASE_HEAD(w_tag_no_repeat)
|
||||
{
|
||||
set_md_var("descr", "Checks formatting with a tag");
|
||||
}
|
||||
ATF_TEST_CASE_BODY(w_tag_no_repeat)
|
||||
{
|
||||
run_tests("w_tag_no_repeat");
|
||||
}
|
||||
|
||||
ATF_TEST_CASE(w_tag_repeat);
|
||||
ATF_TEST_CASE_HEAD(w_tag_repeat)
|
||||
{
|
||||
set_md_var("descr", "Checks formatting with a tag and repeating it on "
|
||||
"each line");
|
||||
}
|
||||
ATF_TEST_CASE_BODY(w_tag_repeat)
|
||||
{
|
||||
run_tests("w_tag_repeat");
|
||||
}
|
||||
|
||||
ATF_TEST_CASE(w_tag_col);
|
||||
ATF_TEST_CASE_HEAD(w_tag_col)
|
||||
{
|
||||
set_md_var("descr", "Checks formatting with a tag and starting at a "
|
||||
"column greater than its length");
|
||||
}
|
||||
ATF_TEST_CASE_BODY(w_tag_col)
|
||||
{
|
||||
run_tests("w_tag_col");
|
||||
}
|
||||
|
||||
ATF_TEST_CASE(paragraphs);
|
||||
ATF_TEST_CASE_HEAD(paragraphs)
|
||||
{
|
||||
set_md_var("descr", "Checks formatting a string that contains multiple "
|
||||
"paragraphs");
|
||||
}
|
||||
ATF_TEST_CASE_BODY(paragraphs)
|
||||
{
|
||||
run_tests("paragraphs");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Main.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
ATF_INIT_TEST_CASES(tcs)
|
||||
{
|
||||
// Add the test cases for the free functions.
|
||||
ATF_ADD_TEST_CASE(tcs, wo_tag);
|
||||
ATF_ADD_TEST_CASE(tcs, wo_tag_col);
|
||||
ATF_ADD_TEST_CASE(tcs, w_tag_no_repeat);
|
||||
ATF_ADD_TEST_CASE(tcs, w_tag_repeat);
|
||||
ATF_ADD_TEST_CASE(tcs, w_tag_col);
|
||||
ATF_ADD_TEST_CASE(tcs, paragraphs);
|
||||
}
|
41
contrib/atf/atf-c++/detail/version_helper.cpp
Normal file
41
contrib/atf/atf-c++/detail/version_helper.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright 2014 Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "bconfig.h"
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
std::cout << PACKAGE_VERSION << "\n";
|
||||
return EXIT_SUCCESS;
|
||||
}
|
@ -763,11 +763,30 @@ BUILD_TC(use, "macros_hpp_test.cpp",
|
||||
"do not cause syntax errors when used",
|
||||
"Build of macros_hpp_test.cpp failed; some macros in "
|
||||
"atf-c++/macros.hpp are broken");
|
||||
BUILD_TC_FAIL(detect_unused_tests, "unused_test.cpp",
|
||||
"Tests that defining an unused test case raises a warning (and thus "
|
||||
"an error)",
|
||||
"Build of unused_test.cpp passed; unused test cases are not properly "
|
||||
"detected");
|
||||
|
||||
ATF_TEST_CASE(detect_unused_tests);
|
||||
ATF_TEST_CASE_HEAD(detect_unused_tests)
|
||||
{
|
||||
set_md_var("descr",
|
||||
"Tests that defining an unused test case raises a warning (and "
|
||||
"thus an error)");
|
||||
}
|
||||
ATF_TEST_CASE_BODY(detect_unused_tests)
|
||||
{
|
||||
const char* validate_compiler =
|
||||
"class test_class { public: int dummy; };\n"
|
||||
"#define define_unused static test_class unused\n"
|
||||
"define_unused;\n";
|
||||
|
||||
atf::utils::create_file("compiler_test.cpp", validate_compiler);
|
||||
if (build_check_cxx_o("compiler_test.cpp"))
|
||||
expect_fail("Compiler does not raise a warning on an unused "
|
||||
"static global variable declared by a macro");
|
||||
|
||||
if (build_check_cxx_o_srcdir(*this, "unused_test.cpp"))
|
||||
ATF_FAIL("Build of unused_test.cpp passed; unused test cases are "
|
||||
"not properly detected");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Main.
|
||||
|
@ -1,56 +0,0 @@
|
||||
//
|
||||
// Automated Testing Framework (atf)
|
||||
//
|
||||
// Copyright (c) 2007 The NetBSD Foundation, Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
|
||||
// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#if !defined(_ATF_CXX_NONCOPYABLE_HPP_)
|
||||
#define _ATF_CXX_NONCOPYABLE_HPP_
|
||||
|
||||
namespace atf {
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// The "noncopyable" class.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
class noncopyable {
|
||||
// The class cannot be empty; otherwise we get ABI-stability warnings
|
||||
// during the build, which will break it due to strict checking.
|
||||
int m_noncopyable_dummy;
|
||||
|
||||
noncopyable(const noncopyable& nc);
|
||||
noncopyable& operator=(const noncopyable& nc);
|
||||
|
||||
protected:
|
||||
// Explicitly needed to provide some non-private functions. Otherwise
|
||||
// we also get some warnings during the build.
|
||||
noncopyable(void) {}
|
||||
~noncopyable(void) {}
|
||||
};
|
||||
|
||||
} // namespace atf
|
||||
|
||||
#endif // !defined(_ATF_CXX_NONCOPYABLE_HPP_)
|
@ -43,10 +43,8 @@ require_pc()
|
||||
|
||||
check_version()
|
||||
{
|
||||
atf_check -s eq:0 -o save:stdout -e empty -x \
|
||||
"atf-version | head -n 1 | cut -d ' ' -f 4"
|
||||
ver1=$(cat stdout)
|
||||
echo "Version reported by atf-version: ${ver1}"
|
||||
ver1=$($(atf_get_srcdir)/detail/version_helper)
|
||||
echo "Version reported by builtin PACKAGE_VERSION: ${ver1}"
|
||||
|
||||
atf_check -s eq:0 -o save:stdout -e empty pkg-config --modversion "${1}"
|
||||
ver2=$(cat stdout)
|
||||
@ -59,7 +57,7 @@ atf_test_case version
|
||||
version_head()
|
||||
{
|
||||
atf_set "descr" "Checks that the version in atf-c++ is correct"
|
||||
atf_set "require.progs" "atf-version pkg-config"
|
||||
atf_set "require.progs" "pkg-config"
|
||||
}
|
||||
version_body()
|
||||
{
|
||||
|
@ -55,7 +55,6 @@ extern "C" {
|
||||
#include "atf-c/utils.h"
|
||||
}
|
||||
|
||||
#include "noncopyable.hpp"
|
||||
#include "tests.hpp"
|
||||
|
||||
#include "detail/application.hpp"
|
||||
@ -63,7 +62,6 @@ extern "C" {
|
||||
#include "detail/env.hpp"
|
||||
#include "detail/exceptions.hpp"
|
||||
#include "detail/fs.hpp"
|
||||
#include "detail/parser.hpp"
|
||||
#include "detail/sanity.hpp"
|
||||
#include "detail/text.hpp"
|
||||
|
||||
@ -79,12 +77,7 @@ detail::atf_tp_writer::atf_tp_writer(std::ostream& os) :
|
||||
m_os(os),
|
||||
m_is_first(true)
|
||||
{
|
||||
atf::parser::headers_map hm;
|
||||
atf::parser::attrs_map ct_attrs;
|
||||
ct_attrs["version"] = "1";
|
||||
hm["Content-Type"] = atf::parser::header_entry("Content-Type",
|
||||
"application/X-atf-tp", ct_attrs);
|
||||
atf::parser::write_headers(hm, m_os);
|
||||
m_os << "Content-Type: application/X-atf-tp; version=\"1\"\n\n";
|
||||
}
|
||||
|
||||
void
|
||||
@ -129,7 +122,13 @@ detail::match(const std::string& regexp, const std::string& str)
|
||||
static std::map< atf_tc_t*, impl::tc* > wraps;
|
||||
static std::map< const atf_tc_t*, const impl::tc* > cwraps;
|
||||
|
||||
struct impl::tc_impl : atf::noncopyable {
|
||||
struct impl::tc_impl {
|
||||
private:
|
||||
// Non-copyable.
|
||||
tc_impl(const tc_impl&);
|
||||
tc_impl& operator=(const tc_impl&);
|
||||
|
||||
public:
|
||||
std::string m_ident;
|
||||
atf_tc_t m_tc;
|
||||
bool m_has_cleanup;
|
||||
@ -435,7 +434,7 @@ const char* tp::m_description =
|
||||
"This is an independent atf test program.";
|
||||
|
||||
tp::tp(void (*add_tcs)(tc_vector&)) :
|
||||
app(m_description, "atf-test-program(1)", "atf(7)", false),
|
||||
app(m_description, "atf-test-program(1)"),
|
||||
m_lflag(false),
|
||||
m_resfile("/dev/stdout"),
|
||||
m_srcdir("."),
|
||||
|
@ -38,8 +38,6 @@ extern "C" {
|
||||
#include <atf-c/defs.h>
|
||||
}
|
||||
|
||||
#include <atf-c++/noncopyable.hpp>
|
||||
|
||||
namespace atf {
|
||||
namespace tests {
|
||||
|
||||
@ -74,7 +72,11 @@ typedef std::map< std::string, std::string > vars_map;
|
||||
|
||||
struct tc_impl;
|
||||
|
||||
class tc : noncopyable {
|
||||
class tc {
|
||||
// Non-copyable.
|
||||
tc(const tc&);
|
||||
tc& operator=(const tc&);
|
||||
|
||||
std::auto_ptr< tc_impl > pimpl;
|
||||
|
||||
protected:
|
||||
|
@ -40,8 +40,8 @@ extern "C" {
|
||||
|
||||
#include "macros.hpp"
|
||||
|
||||
#include "detail/parser.hpp"
|
||||
#include "detail/test_helpers.hpp"
|
||||
#include "detail/text.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Tests for the "atf_tp_writer" class.
|
||||
|
@ -45,18 +45,14 @@ static struct var {
|
||||
const char *value;
|
||||
bool can_be_empty;
|
||||
} vars[] = {
|
||||
{ "atf_arch", ATF_ARCH, NULL, false, },
|
||||
{ "atf_build_cc", ATF_BUILD_CC, NULL, false, },
|
||||
{ "atf_build_cflags", ATF_BUILD_CFLAGS, NULL, true, },
|
||||
{ "atf_build_cpp", ATF_BUILD_CPP, NULL, false, },
|
||||
{ "atf_build_cppflags", ATF_BUILD_CPPFLAGS, NULL, true, },
|
||||
{ "atf_build_cxx", ATF_BUILD_CXX, NULL, false, },
|
||||
{ "atf_build_cxxflags", ATF_BUILD_CXXFLAGS, NULL, true, },
|
||||
{ "atf_confdir", ATF_CONFDIR, NULL, false, },
|
||||
{ "atf_includedir", ATF_INCLUDEDIR, NULL, false, },
|
||||
{ "atf_libdir", ATF_LIBDIR, NULL, false, },
|
||||
{ "atf_libexecdir", ATF_LIBEXECDIR, NULL, false, },
|
||||
{ "atf_machine", ATF_MACHINE, NULL, false, },
|
||||
{ "atf_pkgdatadir", ATF_PKGDATADIR, NULL, false, },
|
||||
{ "atf_shell", ATF_SHELL, NULL, false, },
|
||||
{ "atf_workdir", ATF_WORKDIR, NULL, false, },
|
||||
|
@ -44,18 +44,14 @@ static struct varnames {
|
||||
const char *uc;
|
||||
bool can_be_empty;
|
||||
} all_vars[] = {
|
||||
{ "atf_arch", "ATF_ARCH", false },
|
||||
{ "atf_build_cc", "ATF_BUILD_CC", false },
|
||||
{ "atf_build_cflags", "ATF_BUILD_CFLAGS", true },
|
||||
{ "atf_build_cpp", "ATF_BUILD_CPP", false },
|
||||
{ "atf_build_cppflags", "ATF_BUILD_CPPFLAGS", true },
|
||||
{ "atf_build_cxx", "ATF_BUILD_CXX", false },
|
||||
{ "atf_build_cxxflags", "ATF_BUILD_CXXFLAGS", true },
|
||||
{ "atf_confdir", "ATF_CONFDIR", false },
|
||||
{ "atf_includedir", "ATF_INCLUDEDIR", false },
|
||||
{ "atf_libdir", "ATF_LIBDIR", false },
|
||||
{ "atf_libexecdir", "ATF_LIBEXECDIR", false },
|
||||
{ "atf_machine", "ATF_MACHINE", false },
|
||||
{ "atf_pkgdatadir", "ATF_PKGDATADIR", false },
|
||||
{ "atf_shell", "ATF_SHELL", false },
|
||||
{ "atf_workdir", "ATF_WORKDIR", false },
|
||||
|
@ -43,10 +43,8 @@
|
||||
#include "process.h"
|
||||
#include "test_helpers.h"
|
||||
|
||||
static
|
||||
void
|
||||
build_check_c_o_aux(const char *path, const char *failmsg,
|
||||
const bool expect_pass)
|
||||
bool
|
||||
build_check_c_o(const char *path)
|
||||
{
|
||||
bool success;
|
||||
atf_dynstr_t iflag;
|
||||
@ -63,20 +61,19 @@ build_check_c_o_aux(const char *path, const char *failmsg,
|
||||
|
||||
atf_dynstr_fini(&iflag);
|
||||
|
||||
if ((expect_pass && !success) || (!expect_pass && success))
|
||||
atf_tc_fail("%s", failmsg);
|
||||
return success;
|
||||
}
|
||||
|
||||
void
|
||||
build_check_c_o(const atf_tc_t *tc, const char *sfile, const char *failmsg,
|
||||
const bool expect_pass)
|
||||
bool
|
||||
build_check_c_o_srcdir(const atf_tc_t *tc, const char *sfile)
|
||||
{
|
||||
atf_fs_path_t path;
|
||||
|
||||
RE(atf_fs_path_init_fmt(&path, "%s/%s",
|
||||
atf_tc_get_config_var(tc, "srcdir"), sfile));
|
||||
build_check_c_o_aux(atf_fs_path_cstring(&path), failmsg, expect_pass);
|
||||
const bool result = build_check_c_o(atf_fs_path_cstring(&path));
|
||||
atf_fs_path_fini(&path);
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
@ -93,7 +90,8 @@ header_check(const char *hdrname)
|
||||
snprintf(failmsg, sizeof(failmsg),
|
||||
"Header check failed; %s is not self-contained", hdrname);
|
||||
|
||||
build_check_c_o_aux("test.c", failmsg, true);
|
||||
if (!build_check_c_o("test.c"))
|
||||
atf_tc_fail("%s", failmsg);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -63,21 +63,12 @@ struct atf_fs_path;
|
||||
} \
|
||||
ATF_TC_BODY(name, tc) \
|
||||
{ \
|
||||
build_check_c_o(tc, sfile, failmsg, true); \
|
||||
if (!build_check_c_o_srcdir(tc, sfile)) \
|
||||
atf_tc_fail("%s", failmsg); \
|
||||
}
|
||||
|
||||
#define BUILD_TC_FAIL(name, sfile, descr, failmsg) \
|
||||
ATF_TC(name); \
|
||||
ATF_TC_HEAD(name, tc) \
|
||||
{ \
|
||||
atf_tc_set_md_var(tc, "descr", descr); \
|
||||
} \
|
||||
ATF_TC_BODY(name, tc) \
|
||||
{ \
|
||||
build_check_c_o(tc, sfile, failmsg, false); \
|
||||
}
|
||||
|
||||
void build_check_c_o(const atf_tc_t *, const char *, const char *, const bool);
|
||||
bool build_check_c_o(const char *);
|
||||
bool build_check_c_o_srcdir(const atf_tc_t *, const char *);
|
||||
void header_check(const char *);
|
||||
void get_process_helpers_path(const atf_tc_t *, const bool,
|
||||
struct atf_fs_path *);
|
||||
|
43
contrib/atf/atf-c/detail/version_helper.c
Normal file
43
contrib/atf/atf-c/detail/version_helper.c
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "bconfig.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
printf("%s\n", PACKAGE_VERSION);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
@ -843,11 +843,30 @@ BUILD_TC(use, "macros_h_test.c",
|
||||
"do not cause syntax errors when used",
|
||||
"Build of macros_h_test.c failed; some macros in atf-c/macros.h "
|
||||
"are broken");
|
||||
BUILD_TC_FAIL(detect_unused_tests, "unused_test.c",
|
||||
"Tests that defining an unused test case raises a warning (and thus "
|
||||
"an error)",
|
||||
"Build of unused_test.c passed; unused test cases are not properly "
|
||||
"detected");
|
||||
|
||||
ATF_TC(detect_unused_tests);
|
||||
ATF_TC_HEAD(detect_unused_tests, tc)
|
||||
{
|
||||
atf_tc_set_md_var(tc, "descr",
|
||||
"Tests that defining an unused test case raises a "
|
||||
"warning (and thus an error)");
|
||||
}
|
||||
ATF_TC_BODY(detect_unused_tests, tc)
|
||||
{
|
||||
const char* validate_compiler =
|
||||
"struct test_struct { int dummy; };\n"
|
||||
"#define define_unused static struct test_struct unused\n"
|
||||
"define_unused;\n";
|
||||
|
||||
atf_utils_create_file("compiler_test.c", "%s", validate_compiler);
|
||||
if (build_check_c_o("compiler_test.c"))
|
||||
atf_tc_expect_fail("Compiler does not raise a warning on an unused "
|
||||
"static global variable declared by a macro");
|
||||
|
||||
if (build_check_c_o_srcdir(tc, "unused_test.c"))
|
||||
atf_tc_fail("Build of unused_test.c passed; unused test cases are "
|
||||
"not properly detected");
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Main.
|
||||
|
@ -43,10 +43,8 @@ require_pc()
|
||||
|
||||
check_version()
|
||||
{
|
||||
atf_check -s eq:0 -o save:stdout -e empty -x \
|
||||
"atf-version | head -n 1 | cut -d ' ' -f 4"
|
||||
ver1=$(cat stdout)
|
||||
echo "Version reported by atf-version: ${ver1}"
|
||||
ver1=$($(atf_get_srcdir)/detail/version_helper)
|
||||
echo "Version reported by builtin PACKAGE_VERSION: ${ver1}"
|
||||
|
||||
atf_check -s eq:0 -o save:stdout -e empty pkg-config --modversion "${1}"
|
||||
ver2=$(cat stdout)
|
||||
@ -59,7 +57,7 @@ atf_test_case version
|
||||
version_head()
|
||||
{
|
||||
atf_set "descr" "Checks that the version in atf-c is correct"
|
||||
atf_set "require.progs" "atf-version pkg-config"
|
||||
atf_set "require.progs" "pkg-config"
|
||||
}
|
||||
version_body()
|
||||
{
|
||||
|
@ -724,7 +724,7 @@ const char* atf_check::m_description =
|
||||
"atf-check executes given command and analyzes its results.";
|
||||
|
||||
atf_check::atf_check(void) :
|
||||
app(m_description, "atf-check(1)", "atf(7)"),
|
||||
app(m_description, "atf-check(1)"),
|
||||
m_xflag(false)
|
||||
{
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ const char* atf_sh::m_description =
|
||||
"system sh(1) with the atf-sh library.";
|
||||
|
||||
atf_sh::atf_sh(void) :
|
||||
app(m_description, "atf-sh(1)", "atf(7)")
|
||||
app(m_description, "atf-sh(1)")
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ atf_test_case expout_mismatch
|
||||
expout_mismatch_head()
|
||||
{
|
||||
atf_set "descr" "Verifies that atf_check prints a diff of the" \
|
||||
"stdout and the expected stdout of the two do not" \
|
||||
"stdout and the expected stdout if the two do not" \
|
||||
"match"
|
||||
}
|
||||
expout_mismatch_body()
|
||||
@ -79,7 +79,7 @@ atf_test_case experr_mismatch
|
||||
experr_mismatch_head()
|
||||
{
|
||||
atf_set "descr" "Verifies that atf_check prints a diff of the" \
|
||||
"stderr and the expected stderr of the two do not" \
|
||||
"stderr and the expected stderr if the two do not" \
|
||||
"match"
|
||||
}
|
||||
experr_mismatch_body()
|
||||
|
@ -38,7 +38,7 @@ no_args_body()
|
||||
{
|
||||
cat >experr <<EOF
|
||||
atf-sh: ERROR: No test program provided
|
||||
atf-sh: Type \`atf-sh -h' for more details.
|
||||
atf-sh: See atf-sh(1) for usage details.
|
||||
EOF
|
||||
atf_check -s eq:1 -o ignore -e file:experr atf-sh
|
||||
}
|
||||
|
@ -28,18 +28,9 @@
|
||||
/* Define to 1 if you have the `putenv' function. */
|
||||
#define HAVE_PUTENV 1
|
||||
|
||||
/* Define to 1 if putenv is in std */
|
||||
/* #undef HAVE_PUTENV_IN_STD */
|
||||
|
||||
/* Define to 1 if you have the `setenv' function. */
|
||||
#define HAVE_SETENV 1
|
||||
|
||||
/* Define to 1 if setenv is in std */
|
||||
/* #undef HAVE_SETENV_IN_STD */
|
||||
|
||||
/* Define to 1 if snprintf is in std */
|
||||
/* #undef HAVE_SNPRINTF_IN_STD */
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
@ -61,21 +52,12 @@
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if you have the `unmount' function. */
|
||||
#define HAVE_UNMOUNT 1
|
||||
|
||||
/* Define to 1 if you have the `unsetenv' function. */
|
||||
#define HAVE_UNSETENV 1
|
||||
|
||||
/* Define to 1 if unsetenv is in std */
|
||||
/* #undef HAVE_UNSETENV_IN_STD */
|
||||
|
||||
/* Define to 1 if vsnprintf is in std */
|
||||
/* #undef HAVE_VSNPRINTF_IN_STD */
|
||||
|
||||
/* Define to the last valid signal number */
|
||||
#define LAST_SIGNO 128
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#define LT_OBJDIR ".libs/"
|
||||
@ -93,19 +75,19 @@
|
||||
#define PACKAGE_NAME "Automated Testing Framework"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "Automated Testing Framework 0.18"
|
||||
#define PACKAGE_STRING "Automated Testing Framework 0.20"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "atf"
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL "http://code.google.com/p/kyua/wiki/ATF"
|
||||
#define PACKAGE_URL "https://github.com/jmmv/atf/"
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "0.18"
|
||||
#define PACKAGE_VERSION "0.20"
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "0.18"
|
||||
#define VERSION "0.20"
|
||||
|
@ -123,8 +123,9 @@ The usefulness of the
|
||||
.Sq expected_*
|
||||
results comes when writing test cases that verify known failures caused,
|
||||
in general, due to programming errors (aka bugs).
|
||||
Whenever the faulty condition that the expectation is trying to convery is
|
||||
fixed, then the test case will be reported as
|
||||
Whenever the faulty condition that the
|
||||
.Sq expected_*
|
||||
result is trying to cover is fixed, then the test case will be reported as
|
||||
.Sq failed
|
||||
and the developer will have to adjust it to match its new condition.
|
||||
.Pp
|
||||
|
@ -28,7 +28,7 @@
|
||||
.include <bsd.init.mk>
|
||||
|
||||
LIB= atf-c++
|
||||
SHLIB_MAJOR= 1
|
||||
SHLIB_MAJOR= 2
|
||||
|
||||
# libatf-c++ depends on the C version of the ATF library to build.
|
||||
DPADD= ${LIBATFC}
|
||||
@ -53,20 +53,16 @@ SRCS= application.cpp \
|
||||
config.cpp \
|
||||
env.cpp \
|
||||
exceptions.cpp \
|
||||
expand.cpp \
|
||||
fs.cpp \
|
||||
parser.cpp \
|
||||
process.cpp \
|
||||
tests.cpp \
|
||||
text.cpp \
|
||||
ui.cpp \
|
||||
utils.cpp
|
||||
|
||||
INCS= build.hpp \
|
||||
check.hpp \
|
||||
config.hpp \
|
||||
macros.hpp \
|
||||
noncopyable.hpp \
|
||||
tests.hpp \
|
||||
utils.hpp
|
||||
INCSDIR= ${INCLUDEDIR}/atf-c++
|
||||
|
@ -12,15 +12,21 @@ CFLAGS+= -I${ATF}
|
||||
.for _T in application_test \
|
||||
env_test \
|
||||
exceptions_test \
|
||||
expand_test \
|
||||
fs_test \
|
||||
parser_test \
|
||||
process_test \
|
||||
sanity_test \
|
||||
text_test \
|
||||
ui_test
|
||||
text_test
|
||||
ATF_TESTS_CXX+= ${_T}
|
||||
SRCS.${_T}= ${_T}.cpp test_helpers.cpp
|
||||
.endfor
|
||||
|
||||
.for p in version_helper
|
||||
PROGS_CXX+= ${p}
|
||||
SRCS.${p}= ${p}.cpp
|
||||
MAN.${p}= # defined
|
||||
BINDIR.${p}= ${TESTSDIR}
|
||||
.endfor
|
||||
version_helper.o: atf-version
|
||||
|
||||
.include "../../../common.mk"
|
||||
.include <atf.test.mk>
|
||||
|
@ -22,9 +22,13 @@ ATF_TESTS_C+= ${_T}
|
||||
SRCS.${_T}= ${_T}.c test_helpers.c
|
||||
.endfor
|
||||
|
||||
PROGS+= process_helpers
|
||||
SRCS.process_helpers= process_helpers.c
|
||||
MAN.process_helpers= # defined
|
||||
BINDIR.process_helpers= ${TESTSDIR}
|
||||
.for p in process_helpers version_helper
|
||||
PROGS+= ${p}
|
||||
SRCS.${p}= ${p}.c
|
||||
MAN.${p}= # defined
|
||||
BINDIR.${p}= ${TESTSDIR}
|
||||
.endfor
|
||||
version_helper.o: atf-version
|
||||
|
||||
.include "../../../common.mk"
|
||||
.include <atf.test.mk>
|
||||
|
@ -4100,9 +4100,13 @@ OLD_FILES+=usr/share/man/man8/telnetd.8.gz
|
||||
.endif
|
||||
|
||||
.if ${MK_TESTS} == yes
|
||||
OLD_LIBS+=usr/lib/libatf-c++.so.1
|
||||
OLD_FILES+=usr/tests/lib/atf/libatf-c/test_helpers_test
|
||||
OLD_FILES+=usr/tests/lib/atf/test-programs/fork_test
|
||||
OLD_FILES+=usr/tests/lib/atf/libatf-c++/application_test
|
||||
OLD_FILES+=usr/tests/lib/atf/libatf-c++/detail/expand_test
|
||||
OLD_FILES+=usr/tests/lib/atf/libatf-c++/detail/parser_test
|
||||
OLD_FILES+=usr/tests/lib/atf/libatf-c++/detail/ui_test
|
||||
OLD_FILES+=usr/tests/lib/atf/libatf-c++/env_test
|
||||
OLD_FILES+=usr/tests/lib/atf/libatf-c++/exceptions_test
|
||||
OLD_FILES+=usr/tests/lib/atf/libatf-c++/expand_test
|
||||
|
Loading…
Reference in New Issue
Block a user