Drop files removed (most of them were renamed) in atf-0.5.

This commit is contained in:
jmmv 2008-05-01 15:26:16 +00:00
parent ffe8204c6b
commit f768eb7c67
83 changed files with 0 additions and 15311 deletions

View File

@ -1,99 +0,0 @@
#! /bin/sh
#
# 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.
# 3. All advertising materials mentioning features or use of this
# software must display the following acknowledgement:
# This product includes software developed by the NetBSD
# Foundation, Inc. and its contributors.
# 4. Neither the name of The NetBSD Foundation 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 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.
#
#
# A utility to ensure that README lists the correct versions of the
# tools used to generate the distfile.
#
Prog_Name=${0##*/}
#
# err message
#
err() {
echo "${Prog_Name}: ${@}" 1>&2
exit 1
}
#
# warn message
#
warn() {
echo "${Prog_Name}: ${@}" 1>&2
}
#
# check_tool readme_file prog_name verbose_name
#
# Executes 'prog_name' to determine its version and checks if the
# given 'readme_file' contains 'verbose_name <version>' in it.
#
check_tool() {
readme=${1}
prog=${2}
name=${3}
ver=$(${prog} --version | head -n 1 | cut -d ' ' -f 4-)
if grep "^\\* ${name} ${ver}$" ${readme} >/dev/null; then
true
else
warn "Incorrect version of ${name}"
false
fi
}
#
# main readme_file
#
# Entry point.
#
main() {
readme=${1}
ret=0
check_tool ${readme} autoconf "GNU autoconf" || ret=1
check_tool ${readme} automake "GNU automake" || ret=1
check_tool ${readme} libtool "GNU libtool" || ret=1
return ${ret}
}
main "${@}"
# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4

42
dist/atf/atf.hpp vendored
View File

@ -1,42 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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_HPP_)
#define _ATF_HPP_
#include <atf/macros.hpp>
#endif // !defined(_ATF_HPP_)

View File

@ -1,307 +0,0 @@
//
// Automated Testing Framework (atf)
//
// Copyright (c) 2007, 2008 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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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(HAVE_CONFIG_H)
#include "config.h"
#endif
extern "C" {
#include <unistd.h>
}
#include <cstdarg>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include "atf/application.hpp"
#include "atf/sanity.hpp"
#include "atf/ui.hpp"
#if !defined(HAVE_VSNPRINTF_IN_STD)
namespace std {
using ::vsnprintf;
}
#endif // !defined(HAVE_VSNPRINTF_IN_STD)
namespace impl = atf::application;
#define IMPL_NAME "atf::application"
// ------------------------------------------------------------------------
// The "usage_error" class.
// ------------------------------------------------------------------------
impl::usage_error::usage_error(const char *fmt, ...)
throw() :
std::runtime_error("usage_error; message unformatted")
{
va_list ap;
va_start(ap, fmt);
std::vsnprintf(m_text, sizeof(m_text), fmt, ap);
va_end(ap);
}
impl::usage_error::~usage_error(void)
throw()
{
}
const char*
impl::usage_error::what(void)
const throw()
{
return m_text;
}
// ------------------------------------------------------------------------
// The "application" class.
// ------------------------------------------------------------------------
impl::option::option(char ch,
const std::string& a,
const std::string& desc) :
m_character(ch),
m_argument(a),
m_description(desc)
{
}
bool
impl::option::operator<(const impl::option& o)
const
{
return m_character < o.m_character;
}
impl::app::app(const std::string& description,
const std::string& manpage,
const std::string& global_manpage) :
m_argc(-1),
m_argv(NULL),
m_prog_name(NULL),
m_description(description),
m_manpage(manpage),
m_global_manpage(global_manpage)
{
}
impl::app::~app(void)
{
}
bool
impl::app::inited(void)
{
return m_argc != -1;
}
impl::app::options_set
impl::app::options(void)
{
options_set opts = specific_options();
opts.insert(option('h', "", "Shows this help message"));
return opts;
}
std::string
impl::app::specific_args(void)
const
{
return "";
}
impl::app::options_set
impl::app::specific_options(void)
const
{
return options_set();
}
void
impl::app::process_option(int ch, const char* arg)
{
}
void
impl::app::process_options(void)
{
PRE(inited());
std::string optstr;
#if defined(HAVE_GNU_GETOPT)
optstr += '+'; // Turn on POSIX behavior.
#endif
optstr += ':';
{
options_set opts = options();
for (options_set::const_iterator iter = opts.begin();
iter != opts.end(); iter++) {
const option& opt = (*iter);
optstr += opt.m_character;
if (!opt.m_argument.empty())
optstr += ':';
}
}
int ch;
::opterr = 0;
while ((ch = ::getopt(m_argc, m_argv, optstr.c_str())) != -1) {
switch (ch) {
case 'h':
usage(std::cout);
::exit(EXIT_SUCCESS);
case ':':
throw usage_error("Option -%c requires an argument.",
::optopt);
case '?':
throw usage_error("Unknown option -%c.", ::optopt);
default:
process_option(ch, ::optarg);
}
}
m_argc -= ::optind;
m_argv += ::optind;
}
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) << std::endl
<< std::endl
<< ui::format_text(m_description) << std::endl
<< std::endl;
options_set opts = options();
INV(!opts.empty());
os << "Available options:" << std::endl;
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)
<< std::endl;
}
os << std::endl;
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 + ".")
<< std::endl;
}
int
impl::app::run(int argc, char* const* argv)
{
PRE(argc > 0);
PRE(argv != NULL);
m_argc = argc;
m_argv = argv;
m_prog_name = std::strrchr(m_argv[0], '/');
if (m_prog_name == NULL)
m_prog_name = m_argv[0];
else
m_prog_name++;
const std::string bug =
std::string("This is probably a bug in ") + m_prog_name +
" or one of the libraries it uses. Please report this problem to "
PACKAGE_BUGREPORT " and provide as many details as possible "
"describing how you got to this condition.";
int errcode;
try {
process_options();
errcode = main();
} catch (const usage_error& e) {
std::cerr << ui::format_error(m_prog_name, e.what())
<< std::endl
<< ui::format_info(m_prog_name, std::string("Type `") +
m_prog_name + " -h' for more details.")
<< std::endl;
errcode = EXIT_FAILURE;
} catch (const std::runtime_error& e) {
std::cerr << ui::format_error(m_prog_name, std::string(e.what()))
<< std::endl;
errcode = EXIT_FAILURE;
} catch (const atf::sanity::sanity_error& e) {
std::cerr << ui::format_error(m_prog_name,
std::string(e.what()) + "\n" + bug)
<< std::endl;
errcode = EXIT_FAILURE;
} catch (const std::exception& e) {
std::cerr << ui::format_error(m_prog_name,
std::string("Caught unexpected error: ")
+ e.what() + "\n" + bug)
<< std::endl;
errcode = EXIT_FAILURE;
} catch (...) {
std::cerr << ui::format_error(m_prog_name,
std::string("Caught unknown error\n") +
bug)
<< std::endl;
errcode = EXIT_FAILURE;
}
return errcode;
}

View File

@ -1,117 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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_APPLICATION_HPP_)
#define _ATF_APPLICATION_HPP_
#include <ostream>
#include <set>
#include <stdexcept>
#include <string>
namespace atf {
namespace application {
// ------------------------------------------------------------------------
// The "usage_error" class.
// ------------------------------------------------------------------------
class usage_error : public std::runtime_error {
char m_text[4096];
public:
usage_error(const char*, ...) throw();
~usage_error(void) throw();
const char* what(void) const throw();
};
// ------------------------------------------------------------------------
// The "option" class.
// ------------------------------------------------------------------------
class option {
char m_character;
std::string m_argument;
std::string m_description;
friend class app;
public:
option(char, const std::string&, const std::string&);
bool operator<(const option&) const;
};
// ------------------------------------------------------------------------
// The "app" class.
// ------------------------------------------------------------------------
class app {
void process_options(void);
void usage(std::ostream&);
bool inited(void);
protected:
typedef std::set< option > options_set;
int m_argc;
char* const* m_argv;
const char* m_prog_name;
std::string m_description;
std::string m_manpage, m_global_manpage;
options_set options(void);
// To be redefined.
virtual std::string specific_args(void) const;
virtual options_set specific_options(void) const;
virtual void process_option(int, const char*);
virtual int main(void) = 0;
public:
app(const std::string&, const std::string&, const std::string&);
virtual ~app(void);
int run(int, char* const* argv);
};
} // namespace application
} // namespace atf
#endif // !defined(_ATF_APPLICATION_HPP_)

View File

@ -1,297 +0,0 @@
.\"
.\" Automated Testing Framework (atf)
.\"
.\" Copyright (c) 2008 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.
.\" 3. All advertising materials mentioning features or use of this
.\" software must display the following acknowledgement:
.\" This product includes software developed by the NetBSD
.\" Foundation, Inc. and its contributors.
.\" 4. Neither the name of The NetBSD Foundation 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 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.
.\"
.Dd January 5, 2008
.Dt ATF-C++-API 3
.Os
.Sh NAME
.Nm ATF_ADD_TEST_CASE ,
.Nm ATF_CHECK ,
.Nm ATF_CHECK_EQUAL ,
.Nm ATF_CHECK_THROW ,
.Nm ATF_FAIL ,
.Nm ATF_INIT_TEST_CASES ,
.Nm ATF_PASS ,
.Nm ATF_SKIP ,
.Nm ATF_TEST_CASE ,
.Nm ATF_TEST_CASE_BODY ,
.Nm ATF_TEST_CASE_CLEANUP ,
.Nm ATF_TEST_CASE_HEAD ,
.Nm ATF_TEST_CASE_WITH_CLEANUP
.Nd C++ API to write ATF-based test programs
.Sh SYNOPSIS
.In atf.hpp
.Fn ATF_ADD_TEST_CASE "tcs" "name"
.Fn ATF_CHECK "expression"
.Fn ATF_CHECK_EQUAL "expression_1" "expression_2"
.Fn ATF_CHECK_THROW "statement_1" "expected_exception"
.Fn ATF_FAIL "reason"
.Fn ATF_INIT_TEST_CASES "tcs"
.Fn ATF_PASS
.Fn ATF_SKIP "reason"
.Fn ATF_TEST_CASE "name"
.Fn ATF_TEST_CASE_BODY "name"
.Fn ATF_TEST_CASE_CLEANUP "name"
.Fn ATF_TEST_CASE_HEAD "name"
.Fn ATF_TEST_CASE_WITH_CLEANUP "name"
.Sh DESCRIPTION
ATF provides a mostly-macro-based programming interface to implement test
programs in C or C++.
This interface is backed by a C++ implementation, but this fact is
hidden from the developer as much as possible through the use of
macros to simplify programming.
However, the use of C++ is not hidden everywhere and while you can
implement test cases without knowing anything at all about the object model
underneath the provided calls, you might need some minimum notions of the
language in very specific circumstances.
.Pp
C++-based test programs always follow this template:
.Bd -literal -offset indent
extern "C" {
.Ns ... C-specific includes go here ...
}
.Ns ... C++-specific includes go here ...
#include <atf.hpp>
ATF_TEST_CASE(tc1);
ATF_TEST_CASE_HEAD(tc1)
{
... first test case's header ...
}
ATF_TEST_CASE_BODY(tc1)
{
... first test case's body ...
}
ATF_TEST_CASE_WITH_CLEANUP(tc2);
ATF_TEST_CASE_HEAD(tc2)
{
... second test case's header ...
}
ATF_TEST_CASE_BODY(tc2)
{
... second test case's body ...
}
ATF_TEST_CASE_CLEANUP(tc2)
{
... second test case's cleanup ...
}
.Ns ... additional test cases ...
ATF_INIT_TEST_CASES(tcs)
{
ATF_ADD_TEST_CASE(tcs, tc1)
ATF_ADD_TEST_CASE(tcs, tc2)
... add additional test cases ...
}
.Ed
.Ss Definition of test cases
Test cases have an identifier and are composed of three different parts:
the header, the body and an optional cleanup routine, all of which are
described in
.Xr atf-test-case 8 .
To define test cases, one can use the
.Fn ATF_TEST_CASE
or the
.Fn ATF_TEST_CASE_WITH_CLEANUP
macros, which take a single parameter specifiying the test case's
name.
The former does not allow the specification of a cleanup routine for the
test case while the latter does.
It is important to note that these
.Em do not
set the test case up for execution when the program is run.
In order to do so, a later registration is needed through the
.Fn ATF_ADD_TEST_CASE
macro detailed in
.Sx Program initialization .
.Pp
Later on, one must define the three parts of the body by means of three
functions.
Their headers are given by the
.Fn ATF_TEST_CASE_HEAD ,
.Fn ATF_TEST_CASE_BODY
and
.Fn ATF_TEST_CASE_CLEANUP
macros, all of which take the test case's name.
Following each of these, a block of code is expected, surrounded by the
opening and closing brackets.
.Ss Program initialization
The library provides a way to easily define the test program's
.Fn main
function.
You should never define one on your own, but rely on the
library to do it for you.
This is done by using the
.Fn ATF_INIT_TEST_CASES
macro, which is passed the name of the list that will hold the test cases.
This name can be whatever you want as long as it is a valid variable value.
.Pp
After the macro, you are supposed to provide the body of a function, which
should only use the
.Fn ATF_ADD_TEST_CASE
macro to register the test cases the test program will execute.
The first parameter of this macro matches the name you provided in the
former call.
.Ss Header definitions
The test case's header can define the meta-data by using the
.Fn set
method, which takes two parameters: the first one specifies the
meta-data variable to be set and the second one specifies its value.
Both of them are strings.
.Ss Configuration variables
The test case has read-only access to the current configuration variables
by means of the
.Ft vars_map
.Fn config
method, which can be called in any of the three parts of a test case.
.Pp
The
.Ft vars_map
type extends a string-to-string standard C++ map and adds some convenience
functions to it.
The
.Fn has
method takes the name of a configuration variable and returns a boolean
indicating whether the map contains it or not.
If the variable is present, there are several getters to retrieve its
value.
.Pp
The first version of the
.Fn get
method takes the name of a variable and returns its value as a textual
string.
It assumes that the variable is present in the map and will crash your
program if it is not.
The second is an overloaded version of
.Fn get
that takes two parameters: the name of a variable and the default value for
it.
It returns the variable's value if it is defined, or the default value
if not.
.Pp
Similarly, there are a couple of
.Fn get_bool
methods that mimic the previous ones but interpret the variable's textual
value and return a boolean instead.
.Ss Access to the source directory
It is possible to get the path to the test case's source directory from any
of its three components by using the
.Fn get_srcdir
method.
.Ss Requiring programs
Aside from the
.Va require.progs
meta-data variable available in the header only, one can also check for
additional programs in the test case's body by using the
.Fn require_prog
function, which takes the base name or full path of a single binary.
Relative paths are forbidden.
If it is not found, the test case will be automatically skipped.
.Ss Test case finalization
The test case finalizes either when the body reaches its end, at which
point the test is assumed to have
.Em passed ,
or at any explicit call to
.Fn ATF_PASS ,
.Fn ATF_FAIL
or
.Fn ATF_SKIP .
These three macros terminate the execution of the test case immediately.
The cleanup routine will be processed afterwards in a completely automated
way, regardless of the test case's termination reason.
.Pp
.Fn ATF_PASS
does not take any parameters.
.Fn ATF_FAIL
and
.Fn ATF_SKIP
take a single string that describes why the test case failed or
was skipped, respectively.
It is very important to provide a clear error message in both cases so that
the user can quickly know why the test did not pass.
.Ss Helper macros for common checks
The library provides several macros that are very handy in multiple
situations.
These basically check some condition after executing a given statement or
processing a given expression and, if the condition is not met, they
automatically call
.Fn ATF_FAIL
with an appropriate error message.
.Pp
.Fn ATF_CHECK
takes an expression and raises a failure if it evaluates to false.
.Pp
.Fn ATF_CHECK_EQUAL
takes two expressions and raises a failure if the two do not evaluate to
the same exact value.
.Pp
.Fn ATF_CHECK_THROW
takes a statement and the name of an exception and raises a failure if
the statement did not throw the specified exception.
.Sh EXAMPLES
The following shows a complete test program with a single test case that
validates the addition operator:
.Bd -literal -offset indent
#include <atf.hpp>
ATF_TEST_CASE(addition);
ATF_TEST_CASE_HEAD(addition)
{
set("descr", "Sample tests for the addition operator");
}
ATF_TEST_CASE_BODY(addition)
{
ATF_CHECK_EQUAL(0 + 0, 0);
ATF_CHECK_EQUAL(0 + 1, 1);
ATF_CHECK_EQUAL(1 + 0, 1);
ATF_CHECK_EQUAL(1 + 1, 2);
ATF_CHECK_EQUAL(100 + 200, 300);
}
ATF_INIT_TEST_CASES(tcs)
{
ATF_ADD_TEST_CASE(tcs, addition);
}
.Ed
.Sh SEE ALSO
.Xr atf-test-program 1 ,
.Xr atf 7 ,
.Xr atf-test-case 8

View File

@ -1,176 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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 <fstream>
#include "atf/atffile.hpp"
#include "atf/exceptions.hpp"
#include "atf/expand.hpp"
#include "atf/formats.hpp"
// ------------------------------------------------------------------------
// The "reader" helper class.
// ------------------------------------------------------------------------
class reader : public atf::formats::atf_atffile_reader {
const atf::fs::directory& m_dir;
atf::tests::vars_map m_conf, m_props;
std::vector< std::string > m_tps;
void
got_tp(const std::string& name, bool isglob)
{
if (isglob) {
std::set< std::string > ms =
atf::expand::expand_glob(name, m_dir.names());
// Cannot use m_tps.insert(iterator, begin, end) here because it
// does not work under Solaris.
for (std::set< std::string >::const_iterator iter = ms.begin();
iter != ms.end(); iter++)
m_tps.push_back(*iter);
} else {
if (m_dir.find(name) == m_dir.end())
throw atf::not_found_error< atf::fs::path >
("Cannot locate the " + name + " file",
atf::fs::path(name));
m_tps.push_back(name);
}
}
void
got_prop(const std::string& name, const std::string& val)
{
m_props[name] = val;
}
void
got_conf(const std::string& var, const std::string& val)
{
m_conf[var] = val;
}
public:
reader(std::istream& is, const atf::fs::directory& dir) :
atf::formats::atf_atffile_reader(is),
m_dir(dir)
{
}
const atf::tests::vars_map&
conf(void)
const
{
return m_conf;
}
const atf::tests::vars_map&
props(void)
const
{
return m_props;
}
const std::vector< std::string >&
tps(void)
const
{
return m_tps;
}
};
// ------------------------------------------------------------------------
// The "atffile" class.
// ------------------------------------------------------------------------
atf::atffile::atffile(const atf::fs::path& filename)
{
// Scan the directory where the atffile lives in to gather a list of
// all possible test programs in it.
fs::directory dir(filename.branch_path());
dir.erase(filename.leaf_name());
fs::directory::iterator iter = dir.begin();
while (iter != dir.end()) {
const std::string& name = (*iter).first;
const fs::file_info& fi = (*iter).second;
// Discard hidden files and non-executable ones so that they are
// not candidates for glob matching.
if (name[0] == '.' || (!fi.is_owner_executable() &&
!fi.is_group_executable()))
dir.erase(iter++);
else
iter++;
}
// Parse the atffile.
std::ifstream is(filename.c_str());
if (!is)
throw atf::not_found_error< fs::path >
("Cannot open Atffile", filename);
reader r(is, dir);
r.read();
is.close();
// Update the atffile with the data accumulated in the reader.
m_conf = r.conf();
m_props = r.props();
m_tps = r.tps();
// Sanity checks.
if (m_props.find("test-suite") == m_props.end())
throw std::runtime_error("Undefined property `test-suite'");
}
const std::vector< std::string >&
atf::atffile::tps(void)
const
{
return m_tps;
}
const atf::tests::vars_map&
atf::atffile::conf(void)
const
{
return m_conf;
}
const atf::tests::vars_map&
atf::atffile::props(void)
const
{
return m_props;
}

View File

@ -1,63 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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_ATFFILE_HPP_)
#define _ATF_ATFFILE_HPP_
#include <string>
#include <vector>
#include <atf/fs.hpp>
#include <atf/tests.hpp>
namespace atf {
class atffile {
atf::tests::vars_map m_conf;
std::vector< std::string > m_tps;
atf::tests::vars_map m_props;
public:
atffile(const fs::path&);
const atf::tests::vars_map& conf(void) const;
const std::vector< std::string >& tps(void) const;
const atf::tests::vars_map& props(void) const;
};
} // namespace atf
#endif // !defined(_ATF_ATFFILE_HPP_)

View File

@ -1,167 +0,0 @@
//
// Automated Testing Framework (atf)
//
// Copyright (c) 2007, 2008 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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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 <map>
#include "atf/config.hpp"
#include "atf/env.hpp"
#include "atf/sanity.hpp"
static std::map< std::string, std::string > m_variables;
//
// Adds all predefined standard build-time variables to the m_variables
// map, considering the values a user may have provided in the environment.
//
// Can only be called once during the program's lifetime.
//
static
void
init_variables(void)
{
PRE(m_variables.empty());
if (atf::env::has("ATF_ARCH")) {
const std::string& val = atf::env::get("ATF_ARCH");
if (!val.empty())
m_variables["atf_arch"] = val;
else
m_variables["atf_arch"] = ATF_ARCH;
} else
m_variables["atf_arch"] = ATF_ARCH;
if (atf::env::has("ATF_CONFDIR")) {
const std::string& val = atf::env::get("ATF_CONFDIR");
if (!val.empty())
m_variables["atf_confdir"] = val;
else
m_variables["atf_confdir"] = ATF_CONFDIR;
} else
m_variables["atf_confdir"] = ATF_CONFDIR;
if (atf::env::has("ATF_LIBEXECDIR")) {
const std::string& val = atf::env::get("ATF_LIBEXECDIR");
if (!val.empty())
m_variables["atf_libexecdir"] = val;
else
m_variables["atf_libexecdir"] = ATF_LIBEXECDIR;
} else
m_variables["atf_libexecdir"] = ATF_LIBEXECDIR;
if (atf::env::has("ATF_MACHINE")) {
const std::string& val = atf::env::get("ATF_MACHINE");
if (!val.empty())
m_variables["atf_machine"] = val;
else
m_variables["atf_machine"] = ATF_MACHINE;
} else
m_variables["atf_machine"] = ATF_MACHINE;
if (atf::env::has("ATF_PKGDATADIR")) {
const std::string& val = atf::env::get("ATF_PKGDATADIR");
if (!val.empty())
m_variables["atf_pkgdatadir"] = val;
else
m_variables["atf_pkgdatadir"] = ATF_PKGDATADIR;
} else
m_variables["atf_pkgdatadir"] = ATF_PKGDATADIR;
if (atf::env::has("ATF_SHELL")) {
const std::string& val = atf::env::get("ATF_SHELL");
if (!val.empty())
m_variables["atf_shell"] = val;
else
m_variables["atf_shell"] = ATF_SHELL;
} else
m_variables["atf_shell"] = ATF_SHELL;
if (atf::env::has("ATF_WORKDIR")) {
const std::string& val = atf::env::get("ATF_WORKDIR");
if (!val.empty())
m_variables["atf_workdir"] = val;
else
m_variables["atf_workdir"] = ATF_WORKDIR;
} else
m_variables["atf_workdir"] = ATF_WORKDIR;
POST(!m_variables.empty());
}
const std::string&
atf::config::get(const std::string& varname)
{
if (m_variables.empty())
init_variables();
PRE(has(varname));
return m_variables[varname];
}
const std::map< std::string, std::string >&
atf::config::get_all(void)
{
if (m_variables.empty())
init_variables();
return m_variables;
}
bool
atf::config::has(const std::string& varname)
{
if (m_variables.empty())
init_variables();
return m_variables.find(varname) != m_variables.end();
}
namespace atf {
namespace config {
//
// Auxiliary function for the t_config test program so that it can
// revert the configuration's global status to an empty state and
// do new tests from there on.
//
// Ideally this shouldn't be part of the production library... but
// this is so small that it does not matter.
//
void
__reinit(void)
{
m_variables.clear();
}
} // namespace config
} // namespace atf

View File

@ -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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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_CONFIG_HPP_)
#define _ATF_CONFIG_HPP_
#include <map>
#include <string>
namespace atf {
namespace config {
//!
//! \brief Gets a build-time configuration variable's value.
//!
//! Given the name of a build-time configuration variable, returns its
//! textual value. The user is free to override these by setting their
//! corresponding environment variables. Therefore always use this
//! interface to get the value of these variables.
//!
//! \pre The variable must exist.
//!
const std::string& get(const std::string&);
//!
//! \brief Returns all the build-time configuration variables.
//!
//! Returns a name to value map containing all build-time configuration
//! variables.
//!
const std::map< std::string, std::string >& get_all(void);
//!
//! \brief Checks whether a build-time configuration variable exists.
//!
//! Given the name of a build-time configuration variable, checks
//! whether it is defined and returns a boolean indicating this
//! condition. The program only has to use this function to sanity-check
//! a variable name provided by the user. Otherwise it can assume that
//! the variables are defined.
//!
bool has(const std::string&);
} // namespace config
} // namespace atf
#endif // !defined(_ATF_CONFIG_HPP_)

109
dist/atf/atf/env.cpp vendored
View File

@ -1,109 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <cerrno>
#include <cstdlib>
#include "atf/env.hpp"
#include "atf/exceptions.hpp"
#include "atf/sanity.hpp"
namespace std {
#if !defined(HAVE_PUTENV_IN_STD)
using ::putenv;
#endif
#if !defined(HAVE_SETENV_IN_STD)
using ::setenv;
#endif
#if !defined(HAVE_UNSETENV_IN_STD)
using ::unsetenv;
#endif
}
namespace impl = atf::env;
#define IMPL_NAME "atf::env"
// ------------------------------------------------------------------------
// Free functions.
// ------------------------------------------------------------------------
std::string
impl::get(const std::string& name)
{
const char* val = std::getenv(name.c_str());
PRE(val != NULL);
return val;
}
bool
impl::has(const std::string& name)
{
return std::getenv(name.c_str()) != NULL;
}
void
impl::set(const std::string& name, const std::string& val)
{
#if defined(HAVE_SETENV)
if (std::setenv(name.c_str(), val.c_str(), 1) == -1)
throw atf::system_error(IMPL_NAME "::set(" + name + ", " +
val + ")", "setenv(3) failed", errno);
#elif defined(HAVE_PUTENV)
if (std::putenv((name + "=" + val).c_str()) == -1)
throw atf::system_error(IMPL_NAME "::set(" + name + ", " +
val + ")", "putenv(3) failed", errno);
#else
# error "Don't know how to set an environment variable."
#endif
}
void
impl::unset(const std::string& name)
{
#if defined(HAVE_UNSETENV)
std::unsetenv(name.c_str());
#elif defined(HAVE_PUTENV)
if (std::putenv((name + "=").c_str()) == -1)
throw atf::system_error(IMPL_NAME "::unset(" + name + ")",
"putenv(3) failed", errno);
#else
# error "Don't know how to unset an environment variable."
#endif
}

91
dist/atf/atf/env.hpp vendored
View File

@ -1,91 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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_ENV_HPP_)
#define _ATF_ENV_HPP_
#include <string>
namespace atf {
namespace env {
// ------------------------------------------------------------------------
// Free functions.
// ------------------------------------------------------------------------
//!
//! \brief Returns the value of an environment variable.
//!
//! Returns the value of the specified environment variable. The variable
//! must be defined.
//!
std::string get(const std::string&);
//!
//! \brief Checks if the environment has a variable.
//!
//! Checks if the environment has a given variable.
//!
bool has(const std::string&);
//!
//! \brief Sets an environment variable to a given value.
//!
//! Sets the specified environment variable to the given value. Note that
//! variables set to the empty string are different to undefined ones.
//!
//! Be aware that this alters the program's global status, which in general
//! is a bad thing to do due to the side-effects it may have. There are
//! some legitimate usages for this function, though.
//!
void set(const std::string&, const std::string&);
//!
//! \brief Unsets an environment variable.
//!
//! Unsets the specified environment variable Note that undefined
//! variables are different to those defined but set to an empty value.
//!
//! Be aware that this alters the program's global status, which in general
//! is a bad thing to do due to the side-effects it may have. There are
//! some legitimate usages for this function, though.
//!
void unset(const std::string&);
} // namespace env
} // namespace atf
#endif // !defined(_ATF_ENV_HPP_)

View File

@ -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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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 "config.h"
#include <cstdarg>
#include <cstdio>
#include <cstring>
#include "atf/exceptions.hpp"
atf::system_error::system_error(const std::string& who,
const std::string& message,
int sys_err) :
std::runtime_error(who + ": " + message),
m_sys_err(sys_err)
{
}
atf::system_error::~system_error(void)
throw()
{
}
int
atf::system_error::code(void)
const
throw()
{
return m_sys_err;
}
const char*
atf::system_error::what(void)
const
throw()
{
try {
if (m_message.length() == 0) {
m_message = std::string(std::runtime_error::what()) + ": ";
m_message += ::strerror(m_sys_err);
}
return m_message.c_str();
} catch (...) {
return "Unable to format system_error message";
}
}

View File

@ -1,99 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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_EXCEPTIONS_HPP_)
#define _ATF_EXCEPTIONS_HPP_
#include <stdexcept>
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;
public:
system_error(const std::string&, const std::string&, int);
~system_error(void) throw();
int code(void) const throw();
const char* what(void) const throw();
};
} // namespace atf
#endif // !defined(_ATF_EXCEPTIONS_HPP_)

View File

@ -1,187 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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 <regex.h>
// REG_BASIC is just a synonym for 0, provided as a counterpart to
// REG_EXTENDED to improve readability. It is not provided by all systems.
#if !defined(REG_BASIC)
#define REG_BASIC 0
#endif // !defined(REG_BASIC)
}
#include "atf/exceptions.hpp"
#include "atf/expand.hpp"
#include "atf/sanity.hpp"
namespace impl = atf::expand;
#define IMPL_NAME "atf::expand"
// ------------------------------------------------------------------------
// Auxiliary functions.
// ------------------------------------------------------------------------
//
// Auxiliary function that converts a glob pattern into a regular
// expression ready to be processed by ::regcomp. It is currently very
// limited and does not handle errors; those are handled when compiling
// the regular expression.
//
static
std::string
glob_to_regex(const std::string& glob)
{
std::string regex;
regex = "^";
for (std::string::const_iterator iter = glob.begin();
iter != glob.end(); iter++) {
// NOTE: Keep this in sync with is_glob!
if (*iter == '*')
regex += ".*";
else if (*iter == '?')
regex += ".";
else
regex += *iter;
}
regex += "$";
return regex;
}
//
// Auxiliary function that constructs and throws a pattern_error object
// based on the error code returned by one of ::regcomp or ::regexec and
// their corresponding ::regex_t object.
//
static inline
void
throw_pattern_error(int errcode, const regex_t* preg)
{
// Calculate the length of the error message by using ::regerror with
// a very small buffer.
char lenbuf[1];
size_t len = ::regerror(errcode, preg, lenbuf, 1);
INV(len > 1);
// Allocate a big-enough buffer to hold the complete error message and
// throw an exception containing it.
atf::utils::auto_array< char > buf(new char[len]);
size_t len2 = ::regerror(errcode, preg, buf.get(), len);
INV(len == len2);
throw impl::pattern_error(buf);
}
// ------------------------------------------------------------------------
// The "pattern_error" class.
// ------------------------------------------------------------------------
impl::pattern_error::pattern_error(atf::utils::auto_array< char >& w) :
std::runtime_error(w.get())
{
m_sd = new shared_data();
m_sd->m_refs = 1;
m_sd->m_what = w.release();
}
impl::pattern_error::pattern_error(const pattern_error& pe) :
std::runtime_error(pe.m_sd->m_what),
m_sd(pe.m_sd)
{
m_sd->m_refs++;
}
impl::pattern_error::~pattern_error(void)
throw()
{
if (m_sd->m_refs > 0)
m_sd->m_refs--;
else {
delete [] m_sd->m_what;
m_sd->m_what = NULL;
delete m_sd;
}
}
// ------------------------------------------------------------------------
// Free functions.
// ------------------------------------------------------------------------
std::set< std::string >
impl::expand_glob(const std::string& glob,
const std::set< std::string >& candidates)
{
std::set< std::string > exps;
for (std::set< std::string >::const_iterator iter = candidates.begin();
iter != candidates.end(); iter++)
if (matches_glob(glob, *iter))
exps.insert(*iter);
return exps;
}
bool
impl::is_glob(const std::string& glob)
{
// NOTE: Keep this in sync with glob_to_regex!
return (glob.find('*') != std::string::npos) ||
(glob.find('?') != std::string::npos);
}
bool
impl::matches_glob(const std::string& glob, const std::string& candidate)
{
int res;
::regex_t preg;
// Special case: regcomp does not like empty patterns.
if (glob.empty())
return candidate.empty();
// Convert the glob pattern into a regular expression and compile it.
std::string regex = glob_to_regex(glob);
res = ::regcomp(&preg, regex.c_str(), REG_BASIC);
if (res != 0)
throw_pattern_error(res, &preg);
// Check if the regular expression matches the candidate.
res = ::regexec(&preg, candidate.c_str(), 0, NULL, 0);
if (res != 0 && res != REG_NOMATCH)
throw_pattern_error(res, &preg);
return res == 0;
}

View File

@ -1,143 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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_EXPAND_HPP_)
#define _ATF_EXPAND_HPP_
#include <set>
#include <stdexcept>
#include <string>
#include <atf/utils.hpp>
namespace atf {
namespace expand {
// ------------------------------------------------------------------------
// The "pattern_error" class.
// ------------------------------------------------------------------------
//!
//! \brief An error class to hold information about bad patterns.
//!
//! The pattern_error class is used to represent an error when parsing
//! or comparing a pattern against a string.
//!
class pattern_error : public std::runtime_error {
struct shared_data {
//!
//! \brief Number of live references to this shared_data.
//!
size_t m_refs;
//!
//! \brief A pointer to the error message.
//!
//! This variable holds a pointer to the error message describing
//! why the pattern failed. This is a pointer to dynamic memory
//! allocated by the code that constructed this class.
//!
char *m_what;
};
mutable shared_data* m_sd;
//!
//! \brief Assignment operator for pattern_error.
//!
//! This assignment operator is made private to prevent its usage.
//! We cannot modify the parent's message once constructed, so we
//! cannot safely implement this method.
//!
pattern_error& operator=(const pattern_error&);
public:
//!
//! \brief Constructs a new pattern_error.
//!
//! Constructs a new pattern error, to be thrown as an exception,
//! with the given error message. The error message must be a
//! pointer to dynamically allocated memory, obtained by using the
//! 'new char[...]' construction.
//!
pattern_error(atf::utils::auto_array< char >&);
//!
//! \brief Copy-constructor for pattern_error.
//!
pattern_error(const pattern_error&);
//!
//! \brief Destroys the pattern_error.
//!
//! Destroys the object and releases the memory that was held by the
//! error message given during construction.
//!
~pattern_error(void) throw();
};
// ------------------------------------------------------------------------
// Free functions.
// ------------------------------------------------------------------------
//!
//! \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.
//!
std::set< std::string > expand_glob(const std::string&,
const std::set< std::string >&);
//!
//! \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&);
} // namespace expand
} // namespace atf
#endif // !defined(_ATF_EXPAND_HPP_)

1269
dist/atf/atf/formats.cpp vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,206 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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_FORMATS_HPP_)
#define _ATF_FORMATS_HPP_
#include <istream>
#include <ostream>
#include <stdexcept>
#include <string>
#include <atf/io.hpp>
#include <atf/tests.hpp>
namespace atf {
namespace formats {
// ------------------------------------------------------------------------
// The "format_error" class.
// ------------------------------------------------------------------------
//!
//! \brief A class to signal format errors in external data formats.
//!
//! This error class is used to signal format errors while parsing some
//! externalized representation of a data structure.
//!
class format_error : public std::runtime_error {
public:
format_error(const std::string&);
};
// ------------------------------------------------------------------------
// The "atf_atffile_reader" class.
// ------------------------------------------------------------------------
class atf_atffile_reader {
std::istream& m_is;
protected:
virtual void got_conf(const std::string&, const std::string &);
virtual void got_prop(const std::string&, const std::string &);
virtual void got_tp(const std::string&, bool);
virtual void got_eof(void);
public:
atf_atffile_reader(std::istream&);
virtual ~atf_atffile_reader(void);
void read(void);
};
// ------------------------------------------------------------------------
// The "atf_config_reader" class.
// ------------------------------------------------------------------------
class atf_config_reader {
std::istream& m_is;
protected:
virtual void got_var(const std::string&, const std::string &);
virtual void got_eof(void);
public:
atf_config_reader(std::istream&);
virtual ~atf_config_reader(void);
void read(void);
};
// ------------------------------------------------------------------------
// The "atf_tcs_reader" class.
// ------------------------------------------------------------------------
class atf_tcs_reader {
std::istream& m_is;
void read_out_err(void*,
atf::io::unbuffered_istream&,
atf::io::unbuffered_istream&);
protected:
virtual void got_ntcs(size_t);
virtual void got_tc_start(const std::string&);
virtual void got_tc_end(const atf::tests::tcr&);
virtual void got_stdout_line(const std::string&);
virtual void got_stderr_line(const std::string&);
virtual void got_eof(void);
public:
atf_tcs_reader(std::istream&);
virtual ~atf_tcs_reader(void);
void read(atf::io::unbuffered_istream&, atf::io::unbuffered_istream&);
};
// ------------------------------------------------------------------------
// The "atf_tcs_writer" class.
// ------------------------------------------------------------------------
class atf_tcs_writer {
std::ostream& m_os;
std::ostream& m_cout;
std::ostream& m_cerr;
size_t m_ntcs, m_curtc;
std::string m_tcname;
public:
atf_tcs_writer(std::ostream&, std::ostream&, std::ostream&, size_t);
void start_tc(const std::string&);
void end_tc(const atf::tests::tcr&);
};
// ------------------------------------------------------------------------
// The "atf_tps_reader" class.
// ------------------------------------------------------------------------
class atf_tps_reader {
std::istream& m_is;
void read_info(void*);
void read_tp(void*);
void read_tc(void*);
protected:
virtual void got_info(const std::string&, const std::string&);
virtual void got_ntps(size_t);
virtual void got_tp_start(const std::string&, size_t);
virtual void got_tp_end(const std::string&);
virtual void got_tc_start(const std::string&);
virtual void got_tc_stdout_line(const std::string&);
virtual void got_tc_stderr_line(const std::string&);
virtual void got_tc_end(const atf::tests::tcr&);
virtual void got_eof(void);
public:
atf_tps_reader(std::istream&);
virtual ~atf_tps_reader(void);
void read(void);
};
// ------------------------------------------------------------------------
// The "atf_tps_writer" class.
// ------------------------------------------------------------------------
class atf_tps_writer {
std::ostream& m_os;
std::string m_tpname, m_tcname;
public:
atf_tps_writer(std::ostream&);
void info(const std::string&, const std::string&);
void ntps(size_t);
void start_tp(const std::string&, size_t);
void end_tp(const std::string&);
void start_tc(const std::string&);
void stdout_tc(const std::string&);
void stderr_tc(const std::string&);
void end_tc(const atf::tests::tcr&);
};
} // namespace formats
} // namespace atf
#endif // !defined(_ATF_FORMATS_HPP_)

679
dist/atf/atf/fs.cpp vendored
View File

@ -1,679 +0,0 @@
//
// Automated Testing Framework (atf)
//
// Copyright (c) 2007, 2008 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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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 "config.h"
extern "C" {
#include <sys/param.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <dirent.h>
#include <libgen.h>
#include <unistd.h>
}
#include <cerrno>
#include <cstdlib>
#include "atf/exceptions.hpp"
#include "atf/env.hpp"
#include "atf/fs.hpp"
#include "atf/sanity.hpp"
#include "atf/text.hpp"
#include "atf/user.hpp"
#include "atf/utils.hpp"
namespace impl = atf::fs;
#define IMPL_NAME "atf::fs"
// ------------------------------------------------------------------------
// Auxiliary functions.
// ------------------------------------------------------------------------
//!
//! \brief A version of access(2) using the effective user.
//!
//! An implementation of access(2) but using the effective user value
//! instead of the real one. Also avoids false positives for root when
//! asking for execute permissions, which appear in SunOS.
//!
static
int
effective_access(const impl::path& p, int mode)
{
struct stat st;
if (::lstat(p.c_str(), &st) == -1)
return -1;
// Early return if we are only checking for existence and the file
// exists (stat call returned).
if (F_OK == 0 && mode == 0)
return 0;
else if (mode & F_OK)
return 0;
bool ok = false;
if (atf::user::is_root()) {
if (!ok && !(mode & X_OK)) {
// Allow root to read/write any file.
ok = true;
}
if (!ok && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
// Allow root to execute the file if any of its execution bits
// are set.
ok = true;
}
} else {
if (!ok && (atf::user::euid() == st.st_uid)) {
ok = ((mode & R_OK) && (st.st_mode & S_IRUSR)) ||
((mode & W_OK) && (st.st_mode & S_IWUSR)) ||
((mode & X_OK) && (st.st_mode & S_IXUSR));
}
if (!ok && (atf::user::is_member_of_group(st.st_gid))) {
ok = ((mode & R_OK) && (st.st_mode & S_IRGRP)) ||
((mode & W_OK) && (st.st_mode & S_IWGRP)) ||
((mode & X_OK) && (st.st_mode & S_IXGRP));
}
if (!ok) {
ok = ((mode & R_OK) && (st.st_mode & S_IROTH)) ||
((mode & W_OK) && (st.st_mode & S_IWOTH)) ||
((mode & X_OK) && (st.st_mode & S_IXOTH));
}
}
if (!ok)
errno = EACCES;
return ok ? 0 : -1;
}
//!
//! \brief A controlled version of access(2).
//!
//! This function reimplements the standard access(2) system call to
//! safely control its exit status and raise an exception in case of
//! failure.
//!
static
bool
safe_access(const impl::path& p, int mode, int experr)
{
bool ok;
int res = effective_access(p, mode);
if (res == 0)
ok = true;
else if (res == -1 && errno == experr)
ok = false;
else
throw atf::system_error("effective_access(" + p.str() + ")",
"access(2) failed", errno);
return ok;
}
//!
//! \brief Normalizes a path.
//!
//! Normalizes a path string by removing any consecutive separators.
//! The returned string should be used to construct a path object
//! immediately.
//!
static
std::string
normalize(const std::string& s)
{
PRE(!s.empty());
std::vector< std::string > cs = atf::text::split(s, "/");
std::string data = (s[0] == '/') ? "/" : "";
for (std::vector< std::string >::size_type i = 0; i < cs.size(); i++) {
data += cs[i];
if (i != cs.size() - 1)
data += '/';
}
return data;
}
// ------------------------------------------------------------------------
// The "path" class.
// ------------------------------------------------------------------------
impl::path::path(const std::string& s) :
m_data(s.empty() ? "" : normalize(s))
{
}
const char*
impl::path::c_str(void)
const
{
return m_data.c_str();
}
const std::string&
impl::path::str(void)
const
{
return m_data;
}
bool
impl::path::is_absolute(void)
const
{
return !empty() && m_data[0] == '/';
}
bool
impl::path::is_root(void)
const
{
return m_data == "/";
}
impl::path
impl::path::branch_path(void)
const
{
std::string branch;
std::string::size_type endpos = m_data.rfind('/');
if (endpos == std::string::npos)
branch = ".";
else if (endpos == 0)
branch = "/";
else
branch = m_data.substr(0, endpos);
#if defined(HAVE_CONST_DIRNAME)
INV(branch == ::dirname(m_data.c_str()));
#endif // defined(HAVE_CONST_DIRNAME)
return path(branch);
}
bool
impl::path::empty(void)
const
{
return m_data.empty();
}
std::string
impl::path::leaf_name(void)
const
{
std::string::size_type begpos = m_data.rfind('/');
if (begpos == std::string::npos)
begpos = 0;
else
begpos++;
std::string leaf = m_data.substr(begpos);
#if defined(HAVE_CONST_BASENAME)
INV(leaf == ::basename(m_data.c_str()));
#endif // defined(HAVE_CONST_BASENAME)
return leaf;
}
impl::path
impl::path::to_absolute(void)
const
{
PRE(!is_absolute());
path curdir = get_current_dir();
return curdir / (*this);
}
bool
impl::path::operator==(const path& p)
const
{
return m_data == p.m_data;
}
bool
impl::path::operator!=(const path& p)
const
{
return m_data != p.m_data;
}
impl::path
impl::path::operator/(const std::string& p)
const
{
return path(m_data + "/" + normalize(p));
}
impl::path
impl::path::operator/(const path& p)
const
{
return path(m_data + "/" + p.m_data);
}
bool
impl::path::operator<(const path& p)
const
{
return m_data < p.m_data;
}
// ------------------------------------------------------------------------
// The "file_info" class.
// ------------------------------------------------------------------------
impl::file_info::file_info(const path& p) :
m_path(p)
{
struct stat sb;
if (::lstat(p.c_str(), &sb) == -1)
throw atf::system_error(IMPL_NAME "::file_info(" + p.str() + ")",
"lstat(2) failed", errno);
switch (sb.st_mode & S_IFMT) {
case S_IFBLK: m_type = blk_type; break;
case S_IFCHR: m_type = chr_type; break;
case S_IFDIR: m_type = dir_type; break;
case S_IFIFO: m_type = fifo_type; break;
case S_IFLNK: m_type = lnk_type; break;
case S_IFREG: m_type = reg_type; break;
case S_IFSOCK: m_type = sock_type; break;
#if defined(S_IFWHT)
case S_IFWHT: m_type = wht_type; break;
#endif
default:
throw std::runtime_error(IMPL_NAME "::file_info(" + p.str() + "): "
"lstat(2) returned an unknown file type");
}
m_device = sb.st_dev;
m_inode = sb.st_ino;
m_mode = sb.st_mode & ~S_IFMT;
}
dev_t
impl::file_info::get_device(void)
const
{
return m_device;
}
ino_t
impl::file_info::get_inode(void)
const
{
return m_inode;
}
const impl::path&
impl::file_info::get_path(void)
const
{
return m_path;
}
impl::file_info::type
impl::file_info::get_type(void)
const
{
return m_type;
}
bool
impl::file_info::is_owner_readable(void)
const
{
return m_mode & S_IRUSR;
}
bool
impl::file_info::is_owner_writable(void)
const
{
return m_mode & S_IWUSR;
}
bool
impl::file_info::is_owner_executable(void)
const
{
return m_mode & S_IXUSR;
}
bool
impl::file_info::is_group_readable(void)
const
{
return m_mode & S_IRGRP;
}
bool
impl::file_info::is_group_writable(void)
const
{
return m_mode & S_IWGRP;
}
bool
impl::file_info::is_group_executable(void)
const
{
return m_mode & S_IXGRP;
}
bool
impl::file_info::is_other_readable(void)
const
{
return m_mode & S_IROTH;
}
bool
impl::file_info::is_other_writable(void)
const
{
return m_mode & S_IWOTH;
}
bool
impl::file_info::is_other_executable(void)
const
{
return m_mode & S_IXOTH;
}
// ------------------------------------------------------------------------
// The "directory" class.
// ------------------------------------------------------------------------
impl::directory::directory(const path& p)
{
DIR* dp = ::opendir(p.c_str());
if (dp == NULL)
throw system_error(IMPL_NAME "::directory::directory(" +
p.str() + ")", "opendir(3) failed", errno);
struct dirent* dep;
while ((dep = ::readdir(dp)) != NULL) {
path entryp = p / dep->d_name;
insert(value_type(dep->d_name, file_info(entryp)));
}
if (::closedir(dp) == -1)
throw system_error(IMPL_NAME "::directory::directory(" +
p.str() + ")", "closedir(3) failed", errno);
}
std::set< std::string >
impl::directory::names(void)
const
{
std::set< std::string > ns;
for (const_iterator iter = begin(); iter != end(); iter++)
ns.insert((*iter).first);
return ns;
}
// ------------------------------------------------------------------------
// The "temp_dir" class.
// ------------------------------------------------------------------------
impl::temp_dir::temp_dir(const path& p)
{
PRE(!p.empty());
atf::utils::auto_array< char > buf(new char[p.str().length() + 1]);
std::strcpy(buf.get(), p.c_str());
if (::mkdtemp(buf.get()) == NULL)
throw system_error(IMPL_NAME "::temp_dir::temp_dir(" +
p.str() + ")", "mkdtemp(3) failed",
errno);
m_path = path(buf.get());
}
impl::temp_dir::~temp_dir(void)
{
cleanup(m_path);
}
const impl::path&
impl::temp_dir::get_path(void)
const
{
return m_path;
}
// ------------------------------------------------------------------------
// Free functions.
// ------------------------------------------------------------------------
impl::path
impl::change_directory(const path& dir)
{
path olddir = get_current_dir();
if (olddir != dir) {
if (::chdir(dir.c_str()) == -1)
throw system_error(IMPL_NAME "::chdir(" + dir.str() + ")",
"chdir(2) failed", errno);
}
return olddir;
}
bool
impl::exists(const path& p)
{
return safe_access(p, F_OK, ENOENT);
}
impl::path
impl::find_prog_in_path(const std::string& prog)
{
PRE(prog.find('/') == std::string::npos);
// Do not bother to provide a default value for PATH. If it is not
// there something is broken in the user's environment.
if (!atf::env::has("PATH"))
throw std::runtime_error("PATH not defined in the environment");
std::vector< std::string > dirs = \
atf::text::split(atf::env::get("PATH"), ":");
path p;
for (std::vector< std::string >::const_iterator iter = dirs.begin();
p.empty() && iter != dirs.end(); iter++) {
const path& dir = path(*iter);
if (is_executable(dir / prog))
p = dir / prog;
}
return p;
}
impl::path
impl::get_current_dir(void)
{
#if defined(MAXPATHLEN)
char buf[MAXPATHLEN];
if (::getcwd(buf, sizeof(buf)) == NULL)
throw system_error(IMPL_NAME "::get_current_dir",
"getcwd(3) failed", errno);
return path(buf);
#else // !defined(MAXPATHLEN)
# error "Not implemented."
#endif // defined(MAXPATHLEN)
}
bool
impl::is_executable(const path& p)
{
if (!exists(p))
return false;
return safe_access(p, X_OK, EACCES);
}
void
impl::remove(const path& p)
{
if (file_info(p).get_type() == file_info::dir_type)
throw atf::system_error(IMPL_NAME "::remove(" + p.str() + ")",
"Is a directory",
EPERM);
if (::unlink(p.c_str()) == -1)
throw atf::system_error(IMPL_NAME "::remove(" + p.str() + ")",
"unlink(" + p.str() + ") failed",
errno);
}
static
void
rm_rf_aux(const impl::path& p, const impl::path& root,
const impl::file_info& rootinfo)
{
impl::file_info pinfo(p);
if (pinfo.get_device() != rootinfo.get_device())
throw std::runtime_error("Cannot cross mount-point " +
p.str() + " while removing " +
root.str());
if (pinfo.get_type() != impl::file_info::dir_type)
remove(p);
else {
impl::directory dir(p);
dir.erase(".");
dir.erase("..");
for (impl::directory::iterator iter = dir.begin(); iter != dir.end();
iter++) {
const impl::file_info& entry = (*iter).second;
rm_rf_aux(entry.get_path(), root, rootinfo);
}
if (::rmdir(p.c_str()) == -1)
throw atf::system_error(IMPL_NAME "::rm_rf(" + p.str() + ")",
"rmdir(" + p.str() + ") failed", errno);
}
}
//!
//! \brief Recursively removes a directory tree.
//!
//! Recursively removes a directory tree, which can contain both files and
//! subdirectories. This will raise an error if asked to remove the root
//! directory.
//!
//! Mount points are not crossed; if one is found, an error is raised.
//!
static
void
rm_rf(const impl::path& p)
{
if (p.is_root())
throw std::runtime_error("Cannot delete root directory for "
"safety reasons");
rm_rf_aux(p, p, impl::file_info(p));
}
static
std::vector< impl::path >
find_mount_points(const impl::path& p, const impl::file_info& parentinfo)
{
impl::file_info pinfo(p);
std::vector< impl::path > mntpts;
if (pinfo.get_type() == impl::file_info::dir_type) {
impl::directory dir(p);
dir.erase(".");
dir.erase("..");
for (impl::directory::iterator iter = dir.begin(); iter != dir.end();
iter++) {
const impl::file_info& entry = (*iter).second;
std::vector< impl::path > aux =
find_mount_points(entry.get_path(), pinfo);
mntpts.insert(mntpts.end(), aux.begin(), aux.end());
}
}
if (pinfo.get_device() != parentinfo.get_device())
mntpts.push_back(p);
return mntpts;
}
void
impl::cleanup(const path& p)
{
std::vector< path > mntpts = find_mount_points(p, file_info(p));
for (std::vector< path >::const_iterator iter = mntpts.begin();
iter != mntpts.end(); iter++) {
// At least, FreeBSD's unmount(2) requires the path to be absolute.
// Let's make it absolute in all cases just to be safe that this does
// not affect other systems.
path p2 = (*iter).is_absolute() ? (*iter) : (*iter).to_absolute();
#if defined(HAVE_UNMOUNT)
if (::unmount(p2.c_str(), 0) == -1)
throw system_error(IMPL_NAME "::cleanup(" + p.str() + ")",
"unmount(" + p2.str() + ") failed", errno);
#else
// We could use umount(2) instead if it was available... but
// trying to do so under, e.g. Linux, is a nightmare because we
// also have to update /etc/mtab to match what we did. It is
// simpler to just leave the system-specific umount(8) tool deal
// with it, at least for now.
int res = std::system(("umount '" + p2.str() + "'").c_str());
if (res == -1 || !WIFEXITED(res) || WEXITSTATUS(res) != EXIT_SUCCESS)
throw std::runtime_error("Failed to execute umount '" +
p2.str() + "'");
#endif
}
rm_rf(p);
}

446
dist/atf/atf/fs.hpp vendored
View File

@ -1,446 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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_FS_HPP_)
#define _ATF_FS_HPP_
extern "C" {
#include <sys/types.h>
}
#include <map>
#include <set>
#include <stdexcept>
#include <string>
namespace atf {
namespace fs {
// ------------------------------------------------------------------------
// The "path" class.
// ------------------------------------------------------------------------
//!
//! \brief A class to represent a path to a file.
//!
//! The path class represents the route to a file or directory in the
//! file system. All file manipulation operations use this class to
//! represent their arguments as it takes care of normalizing user-provided
//! strings and ensures they are valid.
//!
//! It is important to note that the file pointed to by a path need not
//! exist.
//!
class path {
//!
//! \brief Internal representation of a path.
//!
std::string m_data;
public:
//! \brief Constructs a new path from a user-provided string.
//!
//! This constructor takes a string, either provided by the program's
//! code or by the user and constructs a new path object. The string
//! is normalized to not contain multiple delimiters together and to
//! remove any trailing one.
//!
//! The input string may be empty, in which case the path is left
//! uninitialized.
//!
explicit path(const std::string& = "");
//!
//! \brief Returns a pointer to a C-style string representing this path.
//!
const char* c_str(void) const;
//!
//! \brief Returns a string representing this path.
//!
const std::string& str(void) const;
//!
//! \brief Returns the branch path of this path.
//!
//! Calculates and returns the branch path of this path. In other
//! words, it returns what the standard ::dirname function would return.
//!
path branch_path(void) const;
//!
//! \brief Checks whether the path is empty or not.
//!
bool empty(void) const;
//!
//! \brief Returns the leaf name of this path.
//!
//! Calculates and returns the leaf name of this path. In other words,
//! it returns what the standard ::basename function would return.
//!
std::string leaf_name(void) const;
//!
//! \brief Checks whether this path is absolute or not.
//!
//! Returns a boolean indicating if this is an absolute path or not;
//! i.e. if it starts with a slash.
//!
bool is_absolute(void) const;
//!
//! \brief Checks whether this path points to the root directory or not.
//!
//! Returns a boolean indicating if this is path points to the root
//! directory or not. The checks made by this are extremely simple (so
//! the results cannot always be trusted) but they are enough for our
//! modest sanity-checking needs. I.e. "/../" could return false.
//!
bool is_root(void) const;
//!
//! \brief Converts the path to be absolute.
//!
//! \pre The path was not absolute.
//!
path to_absolute(void) const;
//!
//! \brief Checks if two paths are equal.
//!
bool operator==(const path&) const;
//!
//! \brief Checks if two paths are different.
//!
bool operator!=(const path&) const;
//!
//! \brief Concatenates a path with a string.
//!
//! Constructs a new path object that is the concatenation of the
//! left-hand path with the right-hand string. The string is normalized
//! before the concatenation, and a path delimiter is introduced between
//! the two components if needed.
//!
path operator/(const std::string&) const;
//!
//! \brief Concatenates a path with another path.
//!
//! Constructs a new path object that is the concatenation of the
//! left-hand path with the right-hand one. A path delimiter is
//! introduced between the two components if needed.
//!
path operator/(const path&) const;
//!
//! \brief Checks if a path has to be sorted before another one
//! lexicographically.
//!
bool operator<(const path&) const;
};
// ------------------------------------------------------------------------
// The "file_info" class.
// ------------------------------------------------------------------------
class directory;
//!
//! \brief A class that contains information about a file.
//!
//! The file_info class holds information about an specific file that
//! exists in the file system.
//!
class file_info {
public:
//!
//! \brief The file's type.
//!
enum type {
blk_type,
chr_type,
dir_type,
fifo_type,
lnk_type,
reg_type,
sock_type,
wht_type
};
//!
//! \brief Constructs a new file_info based on a given file.
//!
//! This constructor creates a new file_info object and fills it with
//! the data returned by ::stat when run on the given file, which must
//! exist.
//!
explicit file_info(const path&);
//!
//! \brief Returns the device containing the file.
//!
dev_t get_device(void) const;
//!
//! \brief Returns the file's inode.
//!
ino_t get_inode(void) const;
//!
//! \brief Returns the file's name.
//!
const path& get_path(void) const;
//!
//! \brief Returns the file's type.
//!
type get_type(void) const;
//!
//! \brief Returns whether the file is readable by its owner or not.
//!
bool is_owner_readable(void) const;
//!
//! \brief Returns whether the file is writable by its owner or not.
//!
bool is_owner_writable(void) const;
//!
//! \brief Returns whether the file is executable by its owner or not.
//!
bool is_owner_executable(void) const;
//!
//! \brief Returns whether the file is readable by the users belonging
//! to its group or not.
//!
bool is_group_readable(void) const;
//!
//! \brief Returns whether the file is writable the users belonging to
//! its group or not.
//!
bool is_group_writable(void) const;
//!
//! \brief Returns whether the file is executable by the users
//! belonging to its group or not.
//!
bool is_group_executable(void) const;
//!
//! \brief Returns whether the file is readable by people different
//! than the owner and those belonging to the group or not.
//!
bool is_other_readable(void) const;
//!
//! \brief Returns whether the file is write by people different
//! than the owner and those belonging to the group or not.
//!
bool is_other_writable(void) const;
//!
//! \brief Returns whether the file is executable by people different
//! than the owner and those belonging to the group or not.
//!
bool is_other_executable(void) const;
private:
//!
//! \brief The file's full path.
//!
path m_path;
//!
//! \brief The file's type.
//!
type m_type;
//!
//! \brief The device on which the file lives.
//!
dev_t m_device;
//!
//! \brief The file's inode.
//!
ino_t m_inode;
//!
//! \brief The file's mode.
//!
mode_t m_mode;
};
// ------------------------------------------------------------------------
// The "directory" class.
// ------------------------------------------------------------------------
//!
//! \brief A class representing a file system directory.
//!
//! The directory class represents a group of files in the file system and
//! corresponds to exactly one directory.
//!
class directory : public std::map< std::string, file_info > {
public:
//!
//! \brief Constructs a new directory.
//!
//! Constructs a new directory object representing the given path.
//! The directory must exist at creation time as the contents of the
//! class are gathered from it.
//!
directory(const path&);
//!
//! \brief Returns the file names of the files in the directory.
//!
//! Returns the leaf names of all files contained in the directory.
//! I.e. the keys of the directory map.
//!
std::set< std::string > names(void) const;
};
// ------------------------------------------------------------------------
// The "temp_dir" class.
// ------------------------------------------------------------------------
//!
//! \brief A RAII model for temporary directories.
//!
//! The temp_dir class provides a RAII model for temporary directories.
//! During construction, a safe temporary directory is created and during
//! destruction it is carefully removed by making use of the cleanup
//! function.
//!
class temp_dir {
//!
//! \brief The path to this temporary directory.
//!
path m_path;
public:
//!
//! \brief Creates a new temporary directory.
//!
//! Creates a new temporary directory based on the provided name
//! template. The template must end with six X characters preceded
//! by a dot. These characters are replaced with a unique name on
//! the file system as described in mkdtemp(3).
//!
temp_dir(const path&);
//!
//! \brief Destroys the temporary directory.
//!
//! Destroys this temporary directory object as well as its file
//! system representation.
//!
~temp_dir(void);
//!
//! \brief Returns the path to this temporary directory.
//!
const path& get_path(void) const;
};
// ------------------------------------------------------------------------
// Free functions.
// ------------------------------------------------------------------------
//!
//! \brief Changes the current working directory.
//!
//! Changes the current working directory to the given path. Returns the
//! path to the directory just left.
//!
//! \throw system_error If ::chdir failed.
//!
path change_directory(const path&);
//!
//! \brief Checks if the given path exists.
//!
bool exists(const path&);
//!
//! \brief Looks for the given program in the PATH.
//!
//! Given a program name (without slashes) looks for it in the path and
//! returns its full path name if found, otherwise an empty path.
//!
path find_prog_in_path(const std::string&);
//!
//! \brief Returns the path to the current working directory.
//!
//! Calculates and returns the path to the current working directory, which
//! is guessed using the ::getcwd function.
//!
//! \throw system_error If ::getcwd failed.
//!
path get_current_dir(void);
//!
//! \brief Checks if the given path exists, is accessible and is executable.
//!
bool is_executable(const path&);
//!
//! \brief Removes a given file.
//!
void remove(const path&);
//!
//! \brief Recursively cleans up a directory.
//!
//! This function cleans up a directory hierarchy. First of all, it looks
//! for any file system that may be mounted under the given path and, if
//! any is found, an attempt is made to unmount it. Later on, the
//! directory is removed alongside all of its contents.
//!
void cleanup(const path&);
} // namespace fs
} // namespace atf
#endif // !defined(_ATF_FS_HPP_)

357
dist/atf/atf/io.cpp vendored
View File

@ -1,357 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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 <unistd.h>
}
#include <cerrno>
#include "atf/exceptions.hpp"
#include "atf/io.hpp"
#include "atf/sanity.hpp"
namespace impl = atf::io;
#define IMPL_NAME "atf::io"
// ------------------------------------------------------------------------
// The "file_handle" class.
// ------------------------------------------------------------------------
impl::file_handle::file_handle(void) :
m_handle(invalid_value())
{
}
impl::file_handle::file_handle(handle_type h) :
m_handle(h)
{
PRE(m_handle != invalid_value());
}
impl::file_handle::file_handle(const file_handle& fh) :
m_handle(fh.m_handle)
{
fh.m_handle = invalid_value();
}
impl::file_handle::~file_handle(void)
{
if (is_valid())
close();
}
impl::file_handle&
impl::file_handle::operator=(const file_handle& fh)
{
m_handle = fh.m_handle;
fh.m_handle = invalid_value();
return *this;
}
bool
impl::file_handle::is_valid(void)
const
{
return m_handle != invalid_value();
}
void
impl::file_handle::close(void)
{
PRE(is_valid());
::close(m_handle);
m_handle = invalid_value();
}
impl::file_handle::handle_type
impl::file_handle::disown(void)
{
PRE(is_valid());
handle_type h = m_handle;
m_handle = invalid_value();
return h;
}
impl::file_handle::handle_type
impl::file_handle::get(void)
const
{
PRE(is_valid());
return m_handle;
}
void
impl::file_handle::posix_remap(handle_type h)
{
PRE(is_valid());
if (m_handle == h)
return;
if (::dup2(m_handle, h) == -1)
throw system_error(IMPL_NAME "::file_handle::posix_remap",
"dup2(2) failed", errno);
if (::close(m_handle) == -1) {
::close(h);
throw system_error(IMPL_NAME "::file_handle::posix_remap",
"close(2) failed", errno);
}
m_handle = h;
}
const impl::file_handle::handle_type
impl::file_handle::invalid_value(void)
{
return -1;
}
// ------------------------------------------------------------------------
// The "systembuf" class.
// ------------------------------------------------------------------------
impl::systembuf::systembuf(handle_type h, std::size_t bufsize) :
m_handle(h),
m_bufsize(bufsize),
m_read_buf(NULL),
m_write_buf(NULL)
{
PRE(m_handle >= 0);
PRE(m_bufsize > 0);
try {
m_read_buf = new char[bufsize];
m_write_buf = new char[bufsize];
} catch (...) {
if (m_read_buf != NULL)
delete [] m_read_buf;
if (m_write_buf != NULL)
delete [] m_write_buf;
throw;
}
setp(m_write_buf, m_write_buf + m_bufsize);
}
impl::systembuf::~systembuf(void)
{
sync(); // XXX Unsure if this is correct. But seems to be needed.
delete [] m_read_buf;
delete [] m_write_buf;
}
impl::systembuf::int_type
impl::systembuf::underflow(void)
{
PRE(gptr() >= egptr());
bool ok;
ssize_t cnt = ::read(m_handle, m_read_buf, m_bufsize);
ok = (cnt != -1 && cnt != 0);
if (!ok)
return traits_type::eof();
else {
setg(m_read_buf, m_read_buf, m_read_buf + cnt);
return traits_type::to_int_type(*gptr());
}
}
impl::systembuf::int_type
impl::systembuf::overflow(int c)
{
PRE(pptr() >= epptr());
if (sync() == -1)
return traits_type::eof();
if (!traits_type::eq_int_type(c, traits_type::eof())) {
traits_type::assign(*pptr(), c);
pbump(1);
}
return traits_type::not_eof(c);
}
int
impl::systembuf::sync(void)
{
ssize_t cnt = pptr() - pbase();
bool ok;
ok = ::write(m_handle, pbase(), cnt) == cnt;
if (ok)
pbump(-cnt);
return ok ? 0 : -1;
}
// ------------------------------------------------------------------------
// The "pipe" class.
// ------------------------------------------------------------------------
impl::pipe::pipe(void)
{
file_handle::handle_type hs[2];
if (::pipe(hs) == -1)
throw system_error(IMPL_NAME "::pipe::pipe",
"pipe(2) failed", errno);
m_read_end = file_handle(hs[0]);
m_write_end = file_handle(hs[1]);
}
impl::file_handle&
impl::pipe::rend(void)
{
return m_read_end;
}
impl::file_handle&
impl::pipe::wend(void)
{
return m_write_end;
}
// ------------------------------------------------------------------------
// The "pistream" class.
// ------------------------------------------------------------------------
impl::pistream::pistream(impl::file_handle& fh) :
std::istream(NULL),
m_handle(fh),
m_systembuf(m_handle.get())
{
rdbuf(&m_systembuf);
}
void
impl::pistream::close(void)
{
m_handle.close();
}
impl::file_handle&
impl::pistream::handle(void)
{
return m_handle;
}
// ------------------------------------------------------------------------
// The "postream" class.
// ------------------------------------------------------------------------
impl::postream::postream(impl::file_handle& fh) :
std::ostream(NULL),
m_handle(fh),
m_systembuf(m_handle.get())
{
rdbuf(&m_systembuf);
}
void
impl::postream::close(void)
{
m_handle.close();
}
impl::file_handle&
impl::postream::handle(void)
{
return m_handle;
}
// ------------------------------------------------------------------------
// The "pollable_istream" class.
// ------------------------------------------------------------------------
impl::unbuffered_istream::unbuffered_istream(impl::file_handle& fh) :
m_fh(fh),
m_is_good(true)
{
}
impl::file_handle&
impl::unbuffered_istream::get_fh(void)
{
return m_fh;
}
bool
impl::unbuffered_istream::good(void)
const
{
return m_is_good;
}
size_t
impl::unbuffered_istream::read(void* buf, size_t buflen)
{
if (!m_is_good)
return 0;
ssize_t res = ::read(m_fh.get(), buf, buflen);
m_is_good = res > 0;
return res > 0 ? res : 0;
}
void
impl::unbuffered_istream::close(void)
{
m_is_good = false;
m_fh.close();
}
// ------------------------------------------------------------------------
// Free functions.
// ------------------------------------------------------------------------
impl::unbuffered_istream&
impl::getline(unbuffered_istream& uis, std::string& str)
{
str.clear();
char ch;
while (uis.read(&ch, sizeof(ch)) == sizeof(ch) && ch != '\n') {
if (ch != '\r')
str += ch;
}
return uis;
}

644
dist/atf/atf/io.hpp vendored
View File

@ -1,644 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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_IO_HPP_)
#define _ATF_IO_HPP_
#include <istream>
#include <ostream>
#include <streambuf>
#include <atf/utils.hpp>
namespace atf {
namespace io {
// ------------------------------------------------------------------------
// The "file_handle" class.
// ------------------------------------------------------------------------
//!
//! \brief Simple RAII model for system file handles.
//!
//! The \a file_handle class is a simple RAII model for native system file
//! handles. This class wraps one of such handles grabbing its ownership,
//! and automaticaly closes it upon destruction. It is basically used
//! inside the library to avoid leaking open file handles, shall an
//! unexpected execution trace occur.
//!
//! A \a file_handle object can be copied but doing so invalidates the
//! source object. There can only be a single valid \a file_handle object
//! for a given system file handle. This is similar to std::auto_ptr\<\>'s
//! semantics.
//!
//! This class also provides some convenience methods to issue special file
//! operations under their respective platforms.
//!
class file_handle
{
public:
//!
//! \brief Opaque name for the native handle type.
//!
//! Each operating system identifies file handles using a specific type.
//! The \a handle_type type is used to transparently refer to file
//! handles regarless of the operating system in which this class is
//! used.
//!
//! If this class is used in a POSIX system, \a NativeSystemHandle is
//! an integer type while it is a \a HANDLE in a Win32 system.
//!
typedef int handle_type;
//!
//! \brief Constructs an invalid file handle.
//!
//! This constructor creates a new \a file_handle object that represents
//! an invalid file handle. An invalid file handle can be copied but
//! cannot be manipulated in any way (except checking for its validity).
//!
//! \see is_valid()
//!
file_handle(void);
//!
//! \brief Constructs a new file handle from a native file handle.
//!
//! This constructor creates a new \a file_handle object that takes
//! ownership of the given \a h native file handle. The user must not
//! close \a h on his own during the lifetime of the new object.
//! Ownership can be reclaimed using disown().
//!
//! \pre The native file handle must be valid; a close operation must
//! succeed on it.
//!
//! \see disown()
//!
file_handle(handle_type h);
//!
//! \brief Copy constructor; invalidates the source handle.
//!
//! This copy constructor creates a new file handle from a given one.
//! Ownership of the native file handle is transferred to the new
//! object, effectively invalidating the source file handle. This
//! avoids having two live \a file_handle objects referring to the
//! same native file handle. The source file handle need not be
//! valid in the name of simplicity.
//!
//! \post The source file handle is invalid.
//! \post The new file handle owns the source's native file handle.
//!
file_handle(const file_handle& fh);
//!
//! \brief Releases resources if the handle is valid.
//!
//! If the file handle is valid, the destructor closes it.
//!
//! \see is_valid()
//!
~file_handle(void);
//!
//! \brief Assignment operator; invalidates the source handle.
//!
//! This assignment operator transfers ownership of the RHS file
//! handle to the LHS one, effectively invalidating the source file
//! handle. This avoids having two live \a file_handle objects
//! referring to the same native file handle. The source file
//! handle need not be valid in the name of simplicity.
//!
//! \post The RHS file handle is invalid.
//! \post The LHS file handle owns RHS' native file handle.
//! \return A reference to the LHS file handle.
//!
file_handle& operator=(const file_handle& fh);
//!
//! \brief Checks whether the file handle is valid or not.
//!
//! Returns a boolean indicating whether the file handle is valid or
//! not. If the file handle is invalid, no other applications can be
//! executed other than the destructor.
//!
//! \return True if the file handle is valid; false otherwise.
//!
bool is_valid(void) const;
//!
//! \brief Closes the file handle.
//!
//! Explicitly closes the file handle, which must be valid. Upon
//! exit, the handle is not valid any more.
//!
//! \pre The file handle is valid.
//! \post The file handle is invalid.
//! \post The native file handle is closed.
//!
void close(void);
//!
//! \brief Reclaims ownership of the native file handle.
//!
//! Explicitly reclaims ownership of the native file handle contained
//! in the \a file_handle object, returning the native file handle.
//! The caller is responsible of closing it later on.
//!
//! \pre The file handle is valid.
//! \post The file handle is invalid.
//! \return The native file handle.
//!
handle_type disown(void);
//!
//! \brief Gets the native file handle.
//!
//! Returns the native file handle for the \a file_handle object.
//! The caller can issue any operation on it except closing it.
//! If closing is required, disown() shall be used.
//!
//! \pre The file handle is valid.
//! \return The native file handle.
//!
handle_type get(void) const;
//!
//! \brief Changes the native file handle to the given one.
//!
//! Given a new native file handle \a h, this operation assigns this
//! handle to the current object, closing its old native file handle.
//! In other words, it first calls dup2() to remap the old handle to
//! the new one and then closes the old handle.
//!
//! If \a h matches the current value of the handle, this is a no-op.
//! This is done for simplicity, to avoid the caller having to check
//! this condition on its own.
//!
//! If \a h is open, it is automatically closed by dup2().
//!
//! This operation is only available in POSIX systems.
//!
//! \pre The file handle is valid.
//! \pre The native file handle \a h is valid; i.e., it must be
//! closeable.
//! \post The file handle's native file handle is \a h.
//! \throw system_error If the internal remapping operation fails.
//!
void posix_remap(handle_type h);
private:
//!
//! \brief Internal handle value.
//!
//! This variable holds the native handle value for the file handle
//! hold by this object. It is interesting to note that this needs
//! to be mutable because the copy constructor and the assignment
//! operator invalidate the source object.
//!
mutable handle_type m_handle;
//!
//! \brief Constant function representing an invalid handle value.
//!
//! Returns the platform-specific handle value that represents an
//! invalid handle. This is a constant function rather than a regular
//! constant because, in the latter case, we cannot define it under
//! Win32 due to the value being of a complex type.
//!
static const handle_type invalid_value(void);
};
// ------------------------------------------------------------------------
// The "systembuf" class.
// ------------------------------------------------------------------------
//!
//! \brief std::streambuf implementation for system file handles.
//!
//! systembuf provides a std::streambuf implementation for system file
//! handles. Contrarywise to file_handle, this class does \b not take
//! ownership of the native file handle; this should be taken care of
//! somewhere else.
//!
//! This class follows the expected semantics of a std::streambuf object.
//! However, it is not copyable to avoid introducing inconsistences with
//! the on-disk file and the in-memory buffers.
//!
class systembuf :
public std::streambuf, utils::noncopyable
{
public:
typedef int handle_type;
//!
//! \brief Constructs a new systembuf for the given file handle.
//!
//! This constructor creates a new systembuf object that reads or
//! writes data from/to the \a h native file handle. This handle
//! is \b not owned by the created systembuf object; the code
//! should take care of it externally.
//!
//! This class buffers input and output; the buffer size may be
//! tuned through the \a bufsize parameter, which defaults to 8192
//! bytes.
//!
//! \see pistream and postream.
//!
explicit systembuf(handle_type h, std::size_t bufsize = 8192);
~systembuf(void);
private:
//!
//! \brief Native file handle used by the systembuf object.
//!
handle_type m_handle;
//!
//! \brief Internal buffer size used during read and write operations.
//!
std::size_t m_bufsize;
//!
//! \brief Internal buffer used during read operations.
//!
char* m_read_buf;
//!
//! \brief Internal buffer used during write operations.
//!
char* m_write_buf;
protected:
//!
//! \brief Reads new data from the native file handle.
//!
//! This operation is called by input methods when there are no more
//! data in the input buffer. The function fills the buffer with new
//! data, if available.
//!
//! \pre All input positions are exhausted (gptr() >= egptr()).
//! \post The input buffer has new data, if available.
//! \returns traits_type::eof() if a read error occurrs or there are
//! no more data to be read. Otherwise returns
//! traits_type::to_int_type(*gptr()).
//!
virtual int_type underflow(void);
//!
//! \brief Makes room in the write buffer for additional data.
//!
//! This operation is called by output methods when there is no more
//! space in the output buffer to hold a new element. The function
//! first flushes the buffer's contents to disk and then clears it to
//! leave room for more characters. The given \a c character is
//! stored at the beginning of the new space.
//!
//! \pre All output positions are exhausted (pptr() >= epptr()).
//! \post The output buffer has more space if no errors occurred
//! during the write to disk.
//! \post *(pptr() - 1) is \a c.
//! \returns traits_type::eof() if a write error occurrs. Otherwise
//! returns traits_type::not_eof(c).
//!
virtual int_type overflow(int c);
//!
//! \brief Flushes the output buffer to disk.
//!
//! Synchronizes the systembuf buffers with the contents of the file
//! associated to this object through the native file handle. The
//! output buffer is flushed to disk and cleared to leave new room
//! for more data.
//!
//! \returns 0 on success, -1 if an error occurred.
//!
virtual int sync(void);
};
// ------------------------------------------------------------------------
// The "pipe" class.
// ------------------------------------------------------------------------
//!
//! \brief Simple RAII model for anonymous pipes.
//!
//! The pipe class is a simple RAII model for anonymous pipes. It
//! provides a portable constructor that allocates a new %pipe and creates
//! a pipe object that owns the two file handles associated to it: the
//! read end and the write end.
//!
//! These handles can be retrieved for modification according to
//! file_handle semantics. Optionally, their ownership can be transferred
//! to external \a file_handle objects which comes handy when the two
//! ends need to be used in different places (i.e. after a POSIX fork()
//! system call).
//!
//! Pipes can be copied following the same semantics as file handles.
//! In other words, copying a %pipe object invalidates the source one.
//!
//! \see file_handle
//!
class pipe
{
//!
//! \brief The %pipe's read end file handle.
//!
file_handle m_read_end;
//!
//! \brief The %pipe's write end file handle.
//!
file_handle m_write_end;
public:
//!
//! \brief Creates a new %pipe.
//!
//! The default pipe constructor allocates a new anonymous %pipe
//! and assigns its ownership to the created pipe object.
//!
//! \throw system_error If the anonymous %pipe creation fails.
//!
pipe(void);
//!
//! \brief Returns the %pipe's read end file handle.
//!
//! Obtains a reference to the %pipe's read end file handle. Care
//! should be taken to not duplicate the returned object if ownership
//! shall remain to the %pipe.
//!
//! Duplicating the returned object invalidates its corresponding file
//! handle in the %pipe.
//!
//! \return A reference to the %pipe's read end file handle.
//!
file_handle& rend(void);
//!
//! \brief Returns the %pipe's write end file handle.
//!
//! Obtains a reference to the %pipe's write end file handle. Care
//! should be taken to not duplicate the returned object if ownership
//! shall remain to the %pipe.
//!
//! Duplicating the returned object invalidates its corresponding file
//! handle in the %pipe.
//!
//! \return A reference to the %pipe's write end file handle.
//!
file_handle& wend(void);
};
// ------------------------------------------------------------------------
// The "pistream" class.
// ------------------------------------------------------------------------
//!
//! \brief Child process' output stream.
//!
//! The pistream class represents an output communication channel with the
//! child process. The child process writes data to this stream and the
//! parent process can read it through the pistream object. In other
//! words, from the child's point of view, the communication channel is an
//! output one, but from the parent's point of view it is an input one;
//! hence the confusing pistream name.
//!
//! pistream objects cannot be copied because they own the file handle
//! they use to communicate with the child and because they buffer data
//! that flows through the communication channel.
//!
//! A pistream object behaves as a std::istream stream in all senses.
//! The class is only provided because it must provide a method to let
//! the caller explicitly close the communication channel.
//!
//! \remark <b>Blocking remarks</b>: Functions that read data from this
//! stream can block if the associated file handle blocks during the read.
//! As this class is used to communicate with child processes through
//! anonymous pipes, the most typical blocking condition happens when the
//! child has no more data to send to the pipe's system buffer. When
//! this happens, the buffer eventually empties and the system blocks
//! until the writer generates some data.
//!
class pistream :
public std::istream, utils::noncopyable
{
//!
//! \brief The file handle managed by this stream.
//!
file_handle m_handle;
//!
//! \brief The systembuf object used to manage this stream's data.
//!
systembuf m_systembuf;
public:
//!
//! \brief Creates a new process' output stream.
//!
//! Given a file handle, this constructor creates a new pistream
//! object that owns the given file handle \a fh. Ownership of
//! \a fh is transferred to the created pistream object.
//!
//! \pre \a fh is valid.
//! \post \a fh is invalid.
//! \post The new pistream object owns \a fh.
//!
explicit pistream(file_handle& fh);
//!
//! \brief Closes the file handle managed by this stream.
//!
//! Explicitly closes the file handle managed by this stream. This
//! function can be used by the user to tell the child process it's
//! not willing to receive more data.
//!
void close(void);
//!
//! \brief Returns the file descriptor attached to this stream.
//!
file_handle& handle(void);
};
// ------------------------------------------------------------------------
// The "postream" class.
// ------------------------------------------------------------------------
//!
//! \brief Child process' input stream.
//!
//! The postream class represents an input communication channel with the
//! child process. The child process reads data from this stream and the
//! parent process can write to it through the postream object. In other
//! words, from the child's point of view, the communication channel is an
//! input one, but from the parent's point of view it is an output one;
//! hence the confusing postream name.
//!
//! postream objects cannot be copied because they own the file handle
//! they use to communicate with the child and because they buffer data
//! that flows through the communication channel.
//!
//! A postream object behaves as a std::ostream stream in all senses.
//! The class is only provided because it must provide a method to let
//! the caller explicitly close the communication channel.
//!
//! \remark <b>Blocking remarks</b>: Functions that write data to this
//! stream can block if the associated file handle blocks during the write.
//! As this class is used to communicate with child processes through
//! anonymous pipes, the most typical blocking condition happens when the
//! child is not processing the data in the pipe's system buffer. When
//! this happens, the buffer eventually fills up and the system blocks
//! until the reader consumes some data, leaving some new room.
//!
class postream :
public std::ostream, utils::noncopyable
{
//!
//! \brief The file handle managed by this stream.
//!
file_handle m_handle;
//!
//! \brief The systembuf object used to manage this stream's data.
//!
systembuf m_systembuf;
public:
//!
//! \brief Creates a new process' input stream.
//!
//! Given a file handle, this constructor creates a new postream
//! object that owns the given file handle \a fh. Ownership of
//! \a fh is transferred to the created postream object.
//!
//! \pre \a fh is valid.
//! \post \a fh is invalid.
//! \post The new postream object owns \a fh.
//!
explicit postream(file_handle& fh);
//!
//! \brief Closes the file handle managed by this stream.
//!
//! Explicitly closes the file handle managed by this stream. This
//! function can be used by the user to tell the child process there
//! is no more data to send.
//!
void close(void);
//!
//! \brief Returns the file descriptor attached to this stream.
//!
file_handle& handle(void);
};
// ------------------------------------------------------------------------
// The "unbuffered_istream" class.
// ------------------------------------------------------------------------
//!
//! \brief An unbuffered input stream.
//!
//! The unbuffered_istream class somewhat mimics the interface of
//! std::istream, but it provides unbuffered access to its attached
//! file descriptor. This is required in those situations where poll(2)
//! is needed, because buffering data will mangle the events reported by
//! this system call and break algorithms mysteriously on some platforms.
//!
class unbuffered_istream {
//!
//! \brief The file descriptor attached to this stream.
//!
file_handle m_fh;
//!
//! \brief Whether the stream is good or not.
//!
bool m_is_good;
public:
//!
//! \brief Constructs a new unbuffered input stream.
//!
//! Given a file handle, constructs a new unbuffered input stream to
//! handle it and takes ownership of that handle.
//!
unbuffered_istream(file_handle& fh);
//!
//! \brief Returns a reference to this stream's file handle.
//!
file_handle& get_fh(void);
//!
//! \brief Checks whether the stream is good or not for reading.
//!
bool good(void) const;
//!
//! \brief Reads unformatted data.
//!
//! Reads data from this stream onto the buffer specified and returns
//! the amount of data read. To detect errors, check for the stream's
//! status using the good method after a call to this function.
//!
size_t read(void*, size_t);
//!
//! \brief Closes the stream.
//!
void close(void);
};
// ------------------------------------------------------------------------
// Free functions.
// ------------------------------------------------------------------------
//!
//! \brief Unbuffered getline implementation.
//!
//! Reads a text line from the given stream without buffering any data.
//! This is inefficient but is the only way to safely use poll(2)...
//!
unbuffered_istream& getline(unbuffered_istream&, std::string&);
} // namespace io
} // namespace atf
#endif // !defined(_ATF_IO_HPP_)

View File

@ -1,152 +0,0 @@
//
// Automated Testing Framework (atf)
//
// Copyright (c) 2007, 2008 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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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_MACROS_HPP_)
#define _ATF_MACROS_HPP_
#include <sstream>
#include <stdexcept>
#include <vector>
#include <atf/tests.hpp>
#define ATF_TEST_CASE(name) \
class atf_tc_ ## name : public atf::tests::tc { \
void head(void); \
void body(void) const; \
public: \
atf_tc_ ## name(void) : atf::tests::tc(#name) {} \
}; \
static atf_tc_ ## name atf_tc_ ## name;
#define ATF_TEST_CASE_WITH_CLEANUP(name) \
class atf_tc_ ## name : public atf::tests::tc { \
void head(void); \
void body(void) const; \
void cleanup(void) const; \
public: \
atf_tc_ ## name(void) : atf::tests::tc(#name) {} \
}; \
static atf_tc_ ## name atf_tc_ ## name;
#define ATF_TEST_CASE_HEAD(name) \
void \
atf_tc_ ## name::head(void)
#define ATF_TEST_CASE_BODY(name) \
void \
atf_tc_ ## name::body(void) \
const
#define ATF_TEST_CASE_CLEANUP(name) \
void \
atf_tc_ ## name::cleanup(void) \
const
#define ATF_FAIL(reason) \
throw atf::tests::tcr::failed(reason)
#define ATF_SKIP(reason) \
throw atf::tests::tcr::skipped(reason)
#define ATF_PASS() \
throw atf::tests::tcr::passed()
#define ATF_CHECK(x) \
do { \
if (!(x)) { \
std::ostringstream __atf_ss; \
__atf_ss << "Line " << __LINE__ << ": " << #x << " not met"; \
throw atf::tests::tcr::failed(__atf_ss.str()); \
} \
} while (false)
#define ATF_CHECK_EQUAL(x, y) \
do { \
if ((x) != (y)) { \
std::ostringstream __atf_ss; \
__atf_ss << "Line " << __LINE__ << ": " << #x << " != " << #y \
<< " (" << (x) << " != " << (y) << ")"; \
throw atf::tests::tcr::failed(__atf_ss.str()); \
} \
} while (false)
#define ATF_CHECK_THROW(x, e) \
try { \
x; \
std::ostringstream __atf_ss; \
__atf_ss << "Line " << __LINE__ << ": " #x " did not throw " \
#e " as expected"; \
throw atf::tests::tcr::failed(__atf_ss.str()); \
} catch (const e& __atf_eo) { \
} catch (const atf::tests::tcr&) { \
throw; \
} catch (const std::exception& __atf_e) { \
std::ostringstream __atf_ss; \
__atf_ss << "Line " << __LINE__ << ": " #x " threw an " \
"unexpected error (not " #e "): " << __atf_e.what(); \
throw atf::tests::tcr::failed(__atf_ss.str()); \
} catch (...) { \
std::ostringstream __atf_ss; \
__atf_ss << "Line " << __LINE__ << ": " #x " threw an " \
"unexpected error (not " #e ")"; \
throw atf::tests::tcr::failed(__atf_ss.str()); \
}
#define ATF_INIT_TEST_CASES(tcs) \
namespace atf { \
namespace tests { \
int run_tp(int, char* const*, \
const std::vector< atf::tests::tc * >&); \
} \
} \
\
int \
main(int argc, char* const* argv) \
{ \
void __atf_init_tcs(std::vector< atf::tests::tc * >&); \
std::vector< atf::tests::tc * > tcs; \
__atf_init_tcs(tcs); \
return atf::tests::run_tp(argc, argv, tcs); \
} \
\
void \
__atf_init_tcs(std::vector< atf::tests::tc * >& tcs)
#define ATF_ADD_TEST_CASE(tcs, tc) \
(tcs).push_back(&(atf_tc_ ## tc));
#endif // !defined(_ATF_MACROS_HPP_)

View File

@ -1,156 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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 "atf/parser.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.";
}
}
// ------------------------------------------------------------------------
// 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 {
std::ostringstream oss;
for (const_iterator iter = begin(); iter != end(); iter++) {
oss << (*iter).first << ": " << (*iter).second
<< std::endl;
}
m_msg = oss.str();
return m_msg.c_str();
} catch (...) {
return "Could not format messages for parsing errors.";
}
}
// ------------------------------------------------------------------------
// 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;
}

View File

@ -1,537 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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_PARSER_HPP_)
#define _ATF_PARSER_HPP_
#include <map>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
namespace atf {
namespace serial {
class internalizer;
}
}
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();
};
// ------------------------------------------------------------------------
// 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 "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.unget();
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.unget();
} else if (ch == '\n') {
done = true;
if (text.empty())
t = token(m_lineno, m_nl_type, "<<NEWLINE>>");
else
m_is.unget();
} 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&);
};
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;
}
} // namespace parser
} // namespace atf
#endif // !defined(_ATF_PARSER_HPP_)

View File

@ -1,162 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <cstdio>
#include "atf/sanity.hpp"
namespace std {
#if !defined(HAVE_SNPRINTF_IN_STD)
using ::snprintf;
#endif
}
namespace impl = atf::sanity;
#define IMPL_NAME "atf::sanity"
// ------------------------------------------------------------------------
// The "sanity_error" class.
// ------------------------------------------------------------------------
impl::sanity_error::sanity_error(const char* p_file,
size_t p_line,
const char* p_msg)
throw() :
std::logic_error(p_msg),
m_file(p_file),
m_line(p_line),
m_msg(p_msg)
{
m_buffer[0] = '\0';
}
impl::sanity_error::~sanity_error(void)
throw()
{
}
const char*
impl::sanity_error::file(void)
const
throw()
{
return m_file;
}
size_t
impl::sanity_error::line(void)
const
throw()
{
return m_line;
}
const char*
impl::sanity_error::format_message(const char* type)
const
throw()
{
if (m_buffer[0] == '\0') {
std::snprintf(m_buffer, sizeof(m_buffer),
"%s check failed at %s:%zu: %s",
type, m_file, m_line, m_msg);
}
return m_buffer;
}
// ------------------------------------------------------------------------
// The "precondition_error" class.
// ------------------------------------------------------------------------
impl::precondition_error::precondition_error(const char* p_file,
size_t p_line,
const char* p_msg)
throw() :
sanity_error(p_file, p_line, p_msg)
{
}
const char*
impl::precondition_error::what(void)
const
throw()
{
return format_message("Precondition");
}
// ------------------------------------------------------------------------
// The "postcondition_error" class.
// ------------------------------------------------------------------------
impl::postcondition_error::postcondition_error(const char* p_file,
size_t p_line,
const char* p_msg)
throw() :
sanity_error(p_file, p_line, p_msg)
{
}
const char*
impl::postcondition_error::what(void)
const
throw()
{
return format_message("Postcondition");
}
// ------------------------------------------------------------------------
// The "invariant_error" class.
// ------------------------------------------------------------------------
impl::invariant_error::invariant_error(const char* p_file,
size_t p_line,
const char* p_msg)
throw() :
sanity_error(p_file, p_line, p_msg)
{
}
const char*
impl::invariant_error::what(void)
const
throw()
{
return format_message("Invariant");
}

View File

@ -1,132 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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_SANITY_HPP_)
#define _ATF_SANITY_HPP_
#include <stdexcept>
namespace atf {
namespace sanity {
// ------------------------------------------------------------------------
// The "sanity_error" class.
// ------------------------------------------------------------------------
class sanity_error : public std::logic_error {
const char* m_file;
size_t m_line;
const char* m_msg;
mutable char m_buffer[1024];
protected:
const char* format_message(const char*) const throw();
public:
sanity_error(const char*, size_t, const char*) throw();
virtual ~sanity_error(void) throw();
const char* file(void) const throw();
size_t line(void) const throw();
virtual const char* what(void) const throw() = 0;
};
// ------------------------------------------------------------------------
// The "precondition_error" class.
// ------------------------------------------------------------------------
class precondition_error : public sanity_error {
public:
precondition_error(const char*, size_t, const char*) throw();
const char* what(void) const throw();
};
// ------------------------------------------------------------------------
// The "postcondition_error" class.
// ------------------------------------------------------------------------
class postcondition_error : public sanity_error {
public:
postcondition_error(const char*, size_t, const char*) throw();
const char* what(void) const throw();
};
// ------------------------------------------------------------------------
// The "invariant_error" class.
// ------------------------------------------------------------------------
class invariant_error : public sanity_error {
public:
invariant_error(const char*, size_t, const char*) throw();
const char* what(void) const throw();
};
// ------------------------------------------------------------------------
// Auxiliary macros.
// ------------------------------------------------------------------------
#define PRE(cond) \
do { \
if (!(cond)) \
throw atf::sanity::precondition_error(__FILE__, __LINE__, \
#cond); \
} while (false)
#define POST(cond) \
do { \
if (!(cond)) \
throw atf::sanity::postcondition_error(__FILE__, __LINE__, \
#cond); \
} while (false)
#define INV(cond) \
do { \
if (!(cond)) \
throw atf::sanity::invariant_error(__FILE__, __LINE__, \
#cond); \
} while (false)
#define UNREACHABLE INV(false)
} // namespace sanity
} // namespace atf
#endif // !defined(_ATF_SANITY_HPP_)

View File

@ -1,132 +0,0 @@
//
// Automated Testing Framework (atf)
//
// Copyright (c) 2007, 2008 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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
}
#include <cerrno>
#include "atf/exceptions.hpp"
#include "atf/sanity.hpp"
#include "atf/signals.hpp"
namespace impl = atf::signals;
#define IMPL_NAME "atf::signals"
// ------------------------------------------------------------------------
// The "signal_holder" class.
// ------------------------------------------------------------------------
std::map< int, impl::signal_holder* > impl::signal_holder::m_holders;
void
impl::signal_holder::handler(int s)
{
m_holders[s]->m_happened = true;
}
void
impl::signal_holder::program(void)
{
if (::sigaction(m_signal, &m_sanew, &m_saold) == -1)
throw atf::system_error(IMPL_NAME "::signal_holder::signal_holder",
"sigaction(2) failed", errno);
}
impl::signal_holder::signal_holder(int s) :
m_signal(s),
m_happened(false)
{
m_sanew.sa_handler = handler;
sigemptyset(&m_sanew.sa_mask);
m_sanew.sa_flags = 0;
program();
PRE(m_holders.find(m_signal) == m_holders.end());
m_holders[m_signal] = this;
}
impl::signal_holder::~signal_holder(void)
{
int res = ::sigaction(m_signal, &m_saold, NULL);
INV(res == 0);
if (m_happened)
::kill(::getpid(), m_signal);
}
void
impl::signal_holder::process(void)
{
if (m_happened) {
int res = ::sigaction(m_signal, &m_saold, NULL);
if (res == -1)
throw atf::system_error(IMPL_NAME "::signal_holder::signal_holder",
"sigaction(2) failed", errno);
m_happened = false;
::kill(::getpid(), m_signal);
program();
}
}
// ------------------------------------------------------------------------
// The "signal_programmer" class.
// ------------------------------------------------------------------------
impl::signal_programmer::signal_programmer(int s, void (*handler)(int)) :
m_signal(s)
{
struct sigaction sa;
sa.sa_handler = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (::sigaction(m_signal, &sa, &m_saold) == -1)
throw atf::system_error(IMPL_NAME
"::signal_programmer::signal_programmer",
"sigaction(2) failed", errno);
}
impl::signal_programmer::~signal_programmer(void)
{
int res = ::sigaction(m_signal, &m_saold, NULL);
INV(res == 0);
}

View File

@ -1,119 +0,0 @@
//
// Automated Testing Framework (atf)
//
// Copyright (c) 2007, 2008 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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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_SIGNALS_HPP_)
#define _ATF_SIGNALS_HPP_
extern "C" {
#include <signal.h>
}
#include <map>
namespace atf {
namespace signals {
//
// Define last_signo to the last signal number valid for the system.
// This is tricky. For example, NetBSD defines SIGPWR as the last valid
// number, whereas Mac OS X defines it as SIGTHR. Both share the same
// signal number (32). If none of these are available, we assume that
// the highest signal is SIGUSR2.
//
// TODO: Make this a configure check that uses ::kill and finds the first
// number that returns EINVAL. The result is probably usable in the
// shell interface too.
//
#if defined(SIGTHR) && defined(SIGPWR)
# if SIGTHR > SIGPWR
static const int last_signo = SIGTHR;
# elif SIGPWR < SIGTHR
static const int last_signo = SIGPWR;
# else
static const int last_signo = SIGPWR;
# endif
#elif defined(SIGTHR)
static const int last_signo = SIGTHR;
#elif defined(SIGPWR)
static const int last_signo = SIGPWR;
#else
static const int last_signo = SIGUSR2;
#endif
// ------------------------------------------------------------------------
// The "signal_holder" class.
// ------------------------------------------------------------------------
//
// A RAII model to hold a signal while the object is alive.
//
class signal_holder {
int m_signal;
bool m_happened;
struct sigaction m_sanew, m_saold;
static std::map< int, signal_holder* > m_holders;
static void handler(int);
void program(void);
public:
signal_holder(int);
~signal_holder(void);
void process(void);
};
// ------------------------------------------------------------------------
// The "signal_programmer" class.
// ------------------------------------------------------------------------
//
// A RAII model to program a signal while the object is alive.
//
class signal_programmer {
int m_signal;
struct sigaction m_saold;
public:
signal_programmer(int s, void (*handler)(int));
~signal_programmer(void);
};
} // namespace signals
} // namespace atf
#endif // !defined(_ATF_SIGNALS_HPP_)

989
dist/atf/atf/tests.cpp vendored
View File

@ -1,989 +0,0 @@
//
// Automated Testing Framework (atf)
//
// Copyright (c) 2007, 2008 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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
}
#include <algorithm>
#include <cctype>
#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <map>
#include <memory>
#include <sstream>
#include <stdexcept>
#include <vector>
#include "atf/application.hpp"
#include "atf/config.hpp"
#include "atf/env.hpp"
#include "atf/exceptions.hpp"
#include "atf/expand.hpp"
#include "atf/formats.hpp"
#include "atf/fs.hpp"
#include "atf/io.hpp"
#include "atf/sanity.hpp"
#include "atf/signals.hpp"
#include "atf/tests.hpp"
#include "atf/text.hpp"
#include "atf/ui.hpp"
#include "atf/user.hpp"
namespace impl = atf::tests;
#define IMPL_NAME "atf::tests"
// ------------------------------------------------------------------------
// Auxiliary stuff for the timeout implementation.
// ------------------------------------------------------------------------
namespace timeout {
static pid_t current_body = 0;
static bool killed = false;
void
sigalrm_handler(int signo)
{
PRE(signo == SIGALRM);
if (current_body != 0) {
::killpg(current_body, SIGTERM);
killed = true;
}
}
} // namespace timeout
// ------------------------------------------------------------------------
// The "vars_map" class.
// ------------------------------------------------------------------------
impl::vars_map::vars_map(void)
{
}
const std::string&
impl::vars_map::get(const std::string& key)
const
{
const_iterator iter = find(key);
if (iter == end())
throw std::runtime_error("Could not find variable `" + key +
"' in map");
return (*iter).second;
}
const std::string&
impl::vars_map::get(const std::string& key, const std::string& def)
const
{
const_iterator iter = find(key);
return (iter == end()) ? def : (*iter).second;
}
bool
impl::vars_map::get_bool(const std::string& key)
const
{
bool val;
std::string str = text::to_lower(get(key));
if (str == "yes" || str == "true")
val = true;
else if (str == "no" || str == "false")
val = false;
else
throw std::runtime_error("Invalid value for boolean variable `" +
key + "'");
return val;
}
bool
impl::vars_map::get_bool(const std::string& key, bool def)
const
{
bool val;
const_iterator iter = find(key);
if (iter == end())
val = def;
else {
std::string str = text::to_lower((*iter).second);
if (str == "yes" || str == "true")
val = true;
else if (str == "no" || str == "false")
val = false;
else
throw std::runtime_error("Invalid value for boolean "
"variable `" + key + "'");
}
return val;
}
bool
impl::vars_map::has(const std::string& key)
const
{
return find(key) != end();
}
impl::vars_map::value_type
impl::vars_map::parse(const std::string& str)
{
if (str.empty())
throw std::runtime_error("-v requires a non-empty argument");
std::vector< std::string > ws = atf::text::split(str, "=");
if (ws.size() == 1 && str[str.length() - 1] == '=') {
return impl::vars_map::value_type(ws[0], "");
} else {
if (ws.size() != 2)
throw std::runtime_error("-v requires an argument of the form "
"var=value");
return impl::vars_map::value_type(ws[0], ws[1]);
}
}
// ------------------------------------------------------------------------
// The "tcr" class.
// ------------------------------------------------------------------------
impl::tcr::tcr(void) :
m_status(status_failed),
m_reason("Uninitialized test case result")
{
}
impl::tcr::tcr(impl::tcr::status s, const std::string& r) :
m_status(s)
{
if (r.find('\n') == std::string::npos)
m_reason = r;
else {
m_reason = "BOGUS REASON (THE ORIGINAL HAD NEWLINES): ";
for (std::string::size_type i = 0; i < r.length(); i++) {
if (r[i] == '\n')
m_reason += "<<NEWLINE>>";
else if (r[i] != '\r')
m_reason += r[i];
}
}
}
impl::tcr
impl::tcr::passed(void)
{
return tcr(status_passed, "");
}
impl::tcr
impl::tcr::skipped(const std::string& reason)
{
return tcr(status_skipped, reason);
}
impl::tcr
impl::tcr::failed(const std::string& reason)
{
return tcr(status_failed, reason);
}
impl::tcr::status
impl::tcr::get_status(void)
const
{
return m_status;
}
const std::string&
impl::tcr::get_reason(void)
const
{
return m_reason;
}
// ------------------------------------------------------------------------
// The "tc" class.
// ------------------------------------------------------------------------
impl::tc::tc(const std::string& ident) :
m_ident(ident)
{
}
impl::tc::~tc(void)
{
}
void
impl::tc::ensure_boolean(const std::string& name)
{
ensure_not_empty(name);
std::string val = text::to_lower(get(name));
if (val == "yes" || val == "true")
set(name, "true");
else if (val == "no" || val == "false")
set(name, "false");
else
throw std::runtime_error("Invalid value for boolean variable `" +
name + "'");
}
void
impl::tc::ensure_integral(const std::string& name)
{
ensure_not_empty(name);
const std::string& val = get(name);
for (std::string::const_iterator iter = val.begin(); iter != val.end();
iter++) {
if (!std::isdigit(*iter))
throw std::runtime_error("Invalid value for integral "
"variable `" + name + "'");
}
}
void
impl::tc::ensure_not_empty(const std::string& name)
{
if (m_meta_data.find(name) == m_meta_data.end())
throw atf::not_found_error< std::string >
("Undefined or empty variable", name);
vars_map::const_iterator iter = m_meta_data.find(name);
INV(iter != m_meta_data.end());
const std::string& val = (*iter).second;
if (val.empty())
throw atf::not_found_error< std::string > // XXX Incorrect error
("Undefined or empty variable", name);
}
void
impl::tc::set(const std::string& var, const std::string& val)
{
m_meta_data[var] = val;
}
const std::string&
impl::tc::get(const std::string& var)
const
{
vars_map::const_iterator iter = m_meta_data.find(var);
PRE(iter != m_meta_data.end());
return (*iter).second;
}
bool
impl::tc::get_bool(const std::string& var)
const
{
std::string val = get(var);
if (val == "true")
return true;
else if (val == "false")
return false;
else
UNREACHABLE;
}
bool
impl::tc::has(const std::string& var)
const
{
vars_map::const_iterator iter = m_meta_data.find(var);
return (iter != m_meta_data.end());
}
const impl::vars_map&
impl::tc::config(void)
const
{
return m_config;
}
const std::string&
impl::tc::get_srcdir(void)
const
{
return m_srcdir;
}
void
impl::tc::init(const vars_map& c, const std::string& srcdir)
{
PRE(m_meta_data.empty());
m_config = c; // XXX Uh, deep copy. Should be a reference...
m_srcdir = srcdir;
m_meta_data["ident"] = m_ident;
m_meta_data["timeout"] = "300";
head();
ensure_not_empty("descr");
ensure_not_empty("ident");
ensure_integral("timeout");
INV(m_meta_data["ident"] == m_ident);
}
impl::tcr
impl::tc::safe_run(void)
const
{
atf::fs::temp_dir workdir
(atf::fs::path(m_config.get("workdir")) / "atf.XXXXXX");
impl::tcr tcr = fork_body(workdir.get_path().str());
fork_cleanup(workdir.get_path().str());
return tcr;
}
static void
sanitize_process(const atf::fs::path& workdir)
{
// Reset all signal handlers to their default behavior.
struct sigaction sadfl;
sadfl.sa_handler = SIG_DFL;
sigemptyset(&sadfl.sa_mask);
sadfl.sa_flags = 0;
for (int i = 0; i < atf::signals::last_signo; i++)
::sigaction(i, &sadfl, NULL);
// Reset critical environment variables to known values.
atf::env::set("HOME", workdir.str());
atf::env::unset("LANG");
atf::env::unset("LC_ALL");
atf::env::unset("LC_COLLATE");
atf::env::unset("LC_CTYPE");
atf::env::unset("LC_MESSAGES");
atf::env::unset("LC_MONETARY");
atf::env::unset("LC_NUMERIC");
atf::env::unset("LC_TIME");
atf::env::unset("TZ");
// Reset the umask.
::umask(S_IWGRP | S_IWOTH);
// Set the work directory.
atf::fs::change_directory(workdir);
}
void
impl::tc::check_requirements(void)
const
{
if (has("require.arch")) {
const std::string& a = get("require.arch");
std::vector< std::string > arches = text::split(a, " ");
bool found = false;
for (std::vector< std::string >::const_iterator iter = arches.begin();
iter != arches.end() && !found; iter++) {
if ((*iter) == atf::config::get("atf_arch"))
found = true;
}
if (!a.empty() && !found)
throw tcr::skipped("Requires one of the '" + a +
"' architectures");
}
if (has("require.machine")) {
const std::string& m = get("require.machine");
std::vector< std::string > machines = text::split(m, " ");
bool found = false;
for (std::vector< std::string >::const_iterator iter =
machines.begin(); iter != machines.end() && !found; iter++) {
if ((*iter) == atf::config::get("atf_machine"))
found = true;
}
if (!m.empty() && !found)
throw tcr::skipped("Requires one of the '" + m +
"' machine types");
}
if (has("require.config")) {
const std::string& c = get("require.config");
std::vector< std::string > vars = text::split(c, " ");
for (std::vector< std::string >::const_iterator iter = vars.begin();
iter != vars.end(); iter++) {
if (!m_config.has(*iter))
throw tcr::skipped("Required configuration variable " +
*iter + " not defined");
}
}
if (has("require.user")) {
const std::string& u = get("require.user");
if (u == "root") {
if (!user::is_root())
throw tcr::skipped("Requires root privileges");
} else if (u == "unprivileged") {
if (!user::is_unprivileged())
throw tcr::skipped("Requires an unprivileged user");
} else
throw tcr::skipped("Invalid value in the require.user "
"property");
}
if (has("require.progs")) {
std::vector< std::string > progs =
text::split(get("require.progs"), " ");
for (std::vector< std::string >::const_iterator iter =
progs.begin(); iter != progs.end(); iter++)
require_prog(*iter);
}
}
static
void
program_timeout(pid_t pid, const std::string& tostr)
{
PRE(pid != 0);
INV(!tostr.empty());
int timeout = atf::text::to_type< int >(tostr);
if (timeout != 0) {
struct itimerval itv;
timerclear(&itv.it_interval);
timerclear(&itv.it_value);
itv.it_value.tv_sec = timeout;
timeout::current_body = pid;
::setitimer(ITIMER_REAL, &itv, NULL);
}
}
impl::tcr
impl::tc::fork_body(const std::string& workdir)
const
{
tcr tcr;
fs::path result(fs::path(workdir) / "tc-result");
pid_t pid = ::fork();
if (pid == -1) {
tcr = tcr::failed("Coult not fork to run test case");
} else if (pid == 0) {
int errcode;
::setpgid(::getpid(), 0);
// Unexpected errors detected in the child process are mentioned
// in stderr to give the user a chance to see what happened.
// This is specially useful in those cases where these errors
// cannot be directed to the parent process.
try {
sanitize_process(atf::fs::path(workdir));
check_requirements();
body();
throw impl::tcr::passed();
} catch (const impl::tcr& tcre) {
std::ofstream os(result.c_str());
if (!os) {
std::cerr << "Could not open the temporary file " +
result.str() + " to leave the results in it"
<< std::endl;
errcode = EXIT_FAILURE;
} else {
if (tcre.get_status() == impl::tcr::status_passed)
os << "passed\n";
else if (tcre.get_status() == impl::tcr::status_failed)
os << "failed\n" << tcre.get_reason() << '\n';
else if (tcre.get_status() == impl::tcr::status_skipped)
os << "skipped\n" << tcre.get_reason() << '\n';
os.close();
errcode = EXIT_SUCCESS;
}
} catch (const std::runtime_error& e) {
std::cerr << "Caught unexpected error: " << e.what() << std::endl;
errcode = EXIT_FAILURE;
} catch (...) {
std::cerr << "Caught unexpected error" << std::endl;
errcode = EXIT_FAILURE;
}
std::exit(errcode);
} else {
// Program the timeout handler.
timeout::current_body = 0;
timeout::killed = false;
atf::signals::signal_programmer sigalrm(SIGALRM,
timeout::sigalrm_handler);
program_timeout(pid, get("timeout"));
// Wait for the child and deal with its termination status.
int status;
if (::waitpid(pid, &status, 0) != pid) {
if (errno == EINTR && timeout::killed)
tcr = tcr::failed("Test case timed out after " +
get("timeout") + " seconds");
else
tcr = tcr::failed("Error while waiting for process " +
atf::text::to_string(pid) + ": " +
::strerror(errno));
} else {
if (WIFEXITED(status)) {
if (WEXITSTATUS(status) == EXIT_SUCCESS) {
std::ifstream is(result.c_str());
if (!is) {
tcr = tcr::failed("Could not open results file for "
"reading");
} else {
std::string line;
std::getline(is, line);
if (line == "passed") {
tcr = tcr::passed();
} else if (line == "failed") {
std::getline(is, line);
tcr = tcr::failed(line);
} else if (line == "skipped") {
std::getline(is, line);
tcr = tcr::skipped(line);
} else {
tcr = tcr::failed("Test case failed to report its "
"status");
}
is.close();
}
} else
tcr = tcr::failed("Test case returned non-OK status; "
"see its stderr output for more "
"details");
} else if (WIFSIGNALED(status)) {
tcr = tcr::failed("Test case received signal " +
atf::text::to_string(WTERMSIG(status)));
} else
UNREACHABLE;
}
}
return tcr;
}
void
impl::tc::fork_cleanup(const std::string& workdir)
const
{
pid_t pid = ::fork();
if (pid == -1) {
std::cerr << "WARNING: Could not fork to run test case's cleanup "
"routine for " << workdir << std::endl;
} else if (pid == 0) {
int errcode = EXIT_FAILURE;
try {
sanitize_process(atf::fs::path(workdir));
cleanup();
errcode = EXIT_SUCCESS;
} catch (const std::exception& e) {
std::cerr << "WARNING: Caught unexpected exception while "
"running the test case's cleanup routine: "
<< e.what() << std::endl;
} catch (...) {
std::cerr << "WARNING: Caught unknown exception while "
"running the test case's cleanup routine"
<< std::endl;
}
std::exit(errcode);
} else {
int status;
if (::waitpid(pid, &status, 0) == -1)
std::cerr << "WARNING: Error while waiting for cleanup process "
<< atf::text::to_string(pid) << ": "
<< ::strerror(errno) << std::endl;
if (!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_SUCCESS)
std::cerr << "WARNING: Cleanup process ended unexpectedly"
<< std::endl;
}
}
impl::tcr
impl::tc::run(void)
const
{
PRE(!m_meta_data.empty());
tcr tcr;
try {
tcr = safe_run();
} catch (const std::exception& e) {
tcr = tcr::failed(std::string("Unhandled exception: ") +
e.what());
} catch (...) {
tcr = tcr::failed("Unknown unhandled exception");
}
return tcr;
}
void
impl::tc::cleanup(void)
const
{
}
void
impl::tc::require_prog(const std::string& prog)
const
{
PRE(!prog.empty());
fs::path p(prog);
if (p.is_absolute()) {
if (!fs::is_executable(p))
throw impl::tcr::skipped("The required program " + prog +
" could not be found");
} else {
INV(p.branch_path() == fs::path("."));
if (fs::find_prog_in_path(prog).empty())
throw impl::tcr::skipped("The required program " + prog +
" could not be found in the PATH");
}
}
// ------------------------------------------------------------------------
// The "tp" class.
// ------------------------------------------------------------------------
class tp : public atf::application::app {
public:
typedef std::vector< impl::tc * > tc_vector;
private:
static const char* m_description;
bool m_lflag;
int m_results_fd;
std::auto_ptr< std::ostream > m_results_os;
atf::fs::path m_srcdir;
std::set< std::string > m_tcnames;
atf::tests::vars_map m_vars;
std::string specific_args(void) const;
options_set specific_options(void) const;
void process_option(int, const char*);
tc_vector m_tcs;
tc_vector init_tcs(void);
static tc_vector filter_tcs(tc_vector, const std::set< std::string >&);
std::ostream& results_stream(void);
int list_tcs(void);
int run_tcs(void);
public:
tp(const tc_vector&);
int main(void);
};
const char* tp::m_description =
"This is an independent atf test program.";
tp::tp(const tc_vector& tcs) :
app(m_description, "atf-test-program(1)", "atf(7)"),
m_lflag(false),
m_results_fd(STDOUT_FILENO),
m_srcdir(atf::fs::get_current_dir()),
m_tcs(tcs)
{
m_vars["workdir"] = atf::config::get("atf_workdir");
}
std::string
tp::specific_args(void)
const
{
return "[test_case1 [.. test_caseN]]";
}
tp::options_set
tp::specific_options(void)
const
{
using atf::application::option;
options_set opts;
opts.insert(option('l', "", "List test cases and their purpose"));
opts.insert(option('r', "fd", "The file descriptor to which the test "
"program will send the results of the "
"test cases"));
opts.insert(option('s', "srcdir", "Directory where the test's data "
"files are located"));
opts.insert(option('v', "var=value", "Sets the configuration variable "
"`var' to `value'"));
return opts;
}
void
tp::process_option(int ch, const char* arg)
{
switch (ch) {
case 'l':
m_lflag = true;
break;
case 'r':
{
std::istringstream ss(arg);
ss >> m_results_fd;
}
break;
case 's':
m_srcdir = atf::fs::path(arg);
break;
case 'v':
{
atf::tests::vars_map::value_type v =
atf::tests::vars_map::parse(arg);
m_vars[v.first] = v.second;
}
break;
default:
UNREACHABLE;
}
}
tp::tc_vector
tp::init_tcs(void)
{
tc_vector tcs = m_tcs;
for (tc_vector::iterator iter = tcs.begin();
iter != tcs.end(); iter++) {
impl::tc* tc = *iter;
tc->init(m_vars, m_srcdir.str());
}
return tcs;
}
//
// An auxiliary unary predicate that compares the given test case's
// identifier to the identifier stored in it.
//
class tc_equal_to_ident {
const std::string& m_ident;
public:
tc_equal_to_ident(const std::string& i) :
m_ident(i)
{
}
bool operator()(const impl::tc* tc)
{
return tc->get("ident") == m_ident;
}
};
tp::tc_vector
tp::filter_tcs(tc_vector tcs, const std::set< std::string >& tcnames)
{
tc_vector tcso;
if (tcnames.empty()) {
// Special case: added for efficiency because this is the most
// typical situation.
tcso = tcs;
} else {
// Collect all the test cases' identifiers.
std::set< std::string > ids;
for (tc_vector::iterator iter = tcs.begin();
iter != tcs.end(); iter++) {
impl::tc* tc = *iter;
ids.insert(tc->get("ident"));
}
// Iterate over all names provided by the user and, for each one,
// expand it as if it were a glob pattern. Collect all expansions.
std::set< std::string > exps;
for (std::set< std::string >::const_iterator iter = tcnames.begin();
iter != tcnames.end(); iter++) {
const std::string& glob = *iter;
std::set< std::string > ms = atf::expand::expand_glob(glob, ids);
if (ms.empty())
throw std::runtime_error("Unknown test case `" + glob + "'");
exps.insert(ms.begin(), ms.end());
}
// For each expansion, locate its corresponding test case and add
// it to the output set.
for (std::set< std::string >::const_iterator iter = exps.begin();
iter != exps.end(); iter++) {
const std::string& name = *iter;
tc_vector::iterator tciter =
std::find_if(tcs.begin(), tcs.end(), tc_equal_to_ident(name));
INV(tciter != tcs.end());
tcso.push_back(*tciter);
}
}
return tcso;
}
int
tp::list_tcs(void)
{
tc_vector tcs = filter_tcs(init_tcs(), m_tcnames);
std::string::size_type maxlen = 0;
for (tc_vector::const_iterator iter = tcs.begin();
iter != tcs.end(); iter++) {
const impl::tc* tc = *iter;
if (maxlen < tc->get("ident").length())
maxlen = tc->get("ident").length();
}
for (tc_vector::const_iterator iter = tcs.begin();
iter != tcs.end(); iter++) {
const impl::tc* tc = *iter;
std::cout << atf::ui::format_text_with_tag(tc->get("descr"),
tc->get("ident"),
false, maxlen + 4)
<< std::endl;
}
return EXIT_SUCCESS;
}
std::ostream&
tp::results_stream(void)
{
if (m_results_fd == STDOUT_FILENO)
return std::cout;
else if (m_results_fd == STDERR_FILENO)
return std::cerr;
else
return *m_results_os;
}
int
tp::run_tcs(void)
{
tc_vector tcs = filter_tcs(init_tcs(), m_tcnames);
if (!atf::fs::exists(atf::fs::path(m_vars.get("workdir"))))
throw std::runtime_error("Cannot find the work directory `" +
m_vars.get("workdir") + "'");
int errcode = EXIT_SUCCESS;
atf::signals::signal_holder sighup(SIGHUP);
atf::signals::signal_holder sigint(SIGINT);
atf::signals::signal_holder sigterm(SIGTERM);
atf::formats::atf_tcs_writer w(results_stream(), std::cout, std::cerr,
tcs.size());
for (tc_vector::iterator iter = tcs.begin();
iter != tcs.end(); iter++) {
impl::tc* tc = *iter;
w.start_tc(tc->get("ident"));
impl::tcr tcr = tc->run();
w.end_tc(tcr);
sighup.process();
sigint.process();
sigterm.process();
if (tcr.get_status() == impl::tcr::status_failed)
errcode = EXIT_FAILURE;
}
return errcode;
}
int
tp::main(void)
{
int errcode;
if (!atf::fs::exists(m_srcdir / m_prog_name))
throw std::runtime_error("Cannot find the test program in the "
"source directory `" + m_srcdir.str() + "'");
for (int i = 0; i < m_argc; i++)
m_tcnames.insert(m_argv[i]);
if (m_lflag)
errcode = list_tcs();
else {
if (m_results_fd != STDOUT_FILENO && m_results_fd != STDERR_FILENO) {
atf::io::file_handle fh(m_results_fd);
m_results_os =
std::auto_ptr< std::ostream >(new atf::io::postream(fh));
}
errcode = run_tcs();
}
return errcode;
}
namespace atf {
namespace tests {
int run_tp(int, char* const*, const tp::tc_vector&);
}
}
int
impl::run_tp(int argc, char* const* argv, const tp::tc_vector& tcs)
{
return tp(tcs).run(argc, argv);
}

148
dist/atf/atf/tests.hpp vendored
View File

@ -1,148 +0,0 @@
//
// Automated Testing Framework (atf)
//
// Copyright (c) 2007, 2008 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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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_TESTS_HPP_)
#define _ATF_TESTS_HPP_
#include <map>
#include <string>
namespace atf {
namespace tests {
// ------------------------------------------------------------------------
// The "vars_map" class.
// ------------------------------------------------------------------------
class vars_map : public std::map< std::string, std::string >
{
public:
vars_map(void);
const std::string& get(const std::string&) const;
const std::string& get(const std::string&, const std::string&) const;
bool get_bool(const std::string&) const;
bool get_bool(const std::string&, bool) const;
bool has(const std::string&) const;
static value_type parse(const std::string&);
};
// ------------------------------------------------------------------------
// The "tcr" class.
// ------------------------------------------------------------------------
//!
//! \brief Holds the results of a test case's execution.
//!
//! The tcr class holds the information that describes the results of a
//! test case's execution. This is composed of an exit code and a reason
//! for that exit code.
//!
//! TODO: Complete documentation for this class. Not done yet because it
//! is worth to investigate if this class could be rewritten as several
//! different classes, one for each status.
//!
class tcr {
public:
enum status { status_passed, status_skipped, status_failed };
tcr(void);
static tcr passed(void);
static tcr skipped(const std::string&);
static tcr failed(const std::string&);
status get_status(void) const;
const std::string& get_reason(void) const;
private:
status m_status;
std::string m_reason;
tcr(status, const std::string&);
};
// ------------------------------------------------------------------------
// The "tc" class.
// ------------------------------------------------------------------------
class tc {
std::string m_ident;
vars_map m_meta_data;
vars_map m_config;
std::string m_srcdir;
void ensure_boolean(const std::string&);
void ensure_integral(const std::string&);
void ensure_not_empty(const std::string&);
tcr safe_run(void) const;
tcr fork_body(const std::string&) const;
void fork_cleanup(const std::string&) const;
void check_requirements(void) const;
protected:
virtual void head(void) = 0;
virtual void body(void) const = 0;
virtual void cleanup(void) const;
void require_prog(const std::string&) const;
public:
tc(const std::string&);
virtual ~tc(void);
const std::string& get(const std::string&) const;
bool get_bool(const std::string&) const;
bool has(const std::string&) const;
void set(const std::string&, const std::string&);
const vars_map& config(void) const;
const std::string& get_srcdir(void) const;
void init(const vars_map&, const std::string&);
tcr run(void) const;
};
} // namespace tests
} // namespace atf
#endif // !defined(_ATF_TESTS_HPP_)

84
dist/atf/atf/text.cpp vendored
View File

@ -1,84 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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 <cctype>
#include "atf/text.hpp"
namespace impl = atf::text;
#define IMPL_NAME "atf::text"
std::string
impl::to_lower(const std::string& str)
{
std::string lc;
for (std::string::const_iterator iter = str.begin(); iter != str.end();
iter++)
lc += std::tolower(*iter);
return lc;
}
std::vector< std::string >
impl::split(const std::string& str, const std::string& delim)
{
std::vector< std::string > words;
std::string::size_type pos = 0, newpos = 0;
while (pos < str.length() && newpos != std::string::npos) {
newpos = str.find(delim, pos);
if (newpos != pos)
words.push_back(str.substr(pos, newpos - pos));
pos = newpos + delim.length();
}
return words;
}
std::string
impl::trim(const std::string& str)
{
std::string::size_type pos1 = str.find_first_not_of(" \t");
std::string::size_type pos2 = str.find_last_not_of(" \t");
if (pos1 == std::string::npos && pos2 == std::string::npos)
return "";
else if (pos1 == std::string::npos)
return str.substr(0, str.length() - pos2);
else if (pos2 == std::string::npos)
return str.substr(pos1);
else
return str.substr(pos1, pos2 - pos1 + 1);
}

133
dist/atf/atf/text.hpp vendored
View File

@ -1,133 +0,0 @@
//
// Automated Testing Framework (atf)
//
// Copyright (c) 2007, 2008 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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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_TEXT_HPP_)
#define _ATF_TEXT_HPP_
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
namespace atf {
namespace text {
//!
//! \brief Joins multiple words into a string.
//!
//! Joins a list of words into a string, separating them using the provided
//! separator. Empty words are not omitted.
//!
template< class T >
std::string
join(const T& words, const std::string& separator)
{
std::string str;
typename T::const_iterator iter = words.begin();
bool done = iter == words.end();
while (!done) {
str += *iter;
iter++;
if (iter != words.end())
str += separator;
else
done = true;
}
return str;
}
//!
//! \brief Splits a string into words.
//!
//! Splits the given string into multiple words, all separated by the
//! given delimiter. Multiple occurrences of the same delimiter are
//! not condensed so that rejoining the words later on using the same
//! delimiter results in the original string.
//!
std::vector< std::string > split(const std::string&, const std::string&);
//!
//! \brief Removes whitespace from the beginning and end of a string.
//!
std::string trim(const std::string&);
//!
//! \brief Changes the case of a string to lowercase.
//!
//! Returns a new string that is a lowercased version of the original
//! one.
//!
std::string to_lower(const std::string&);
//!
//! \brief Converts the given object to a string.
//!
//! Returns a string with the representation of the given object. There
//! must exist an operator<< method for that object.
//!
template< class T >
std::string
to_string(const T& ob)
{
std::ostringstream ss;
ss << ob;
return ss.str();
}
//!
//! \brief Converts the given string to another type.
//!
//! Attempts to convert the given string to the requested type. Throws
//! an exception if the conversion failed.
//!
template< class T >
T
to_type(const std::string& str)
{
std::istringstream ss(str);
T value;
ss >> value;
if (!ss.eof() || (!ss.eof() && !ss.good()))
throw std::runtime_error("Cannot convert string to requested type");
return value;
}
} // namespace text
} // namespace atf
#endif // !defined(_ATF_TEXT_HPP_)

179
dist/atf/atf/ui.cpp vendored
View File

@ -1,179 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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 "atf/env.hpp"
#include "atf/text.hpp"
#include "atf/sanity.hpp"
#include "atf/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.empty()) {
std::istringstream str(cols);
str >> width;
}
} 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);
}

112
dist/atf/atf/ui.hpp vendored
View File

@ -1,112 +0,0 @@
//
// Automated Testing Framework (atf)
//
// Copyright (c) 2007, 2008 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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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_UI_HPP_)
#define _ATF_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_UI_HPP_)

85
dist/atf/atf/user.cpp vendored
View File

@ -1,85 +0,0 @@
//
// Automated Testing Framework (atf)
//
// Copyright (c) 2007, 2008 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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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 "config.h"
extern "C" {
#include <sys/param.h>
#include <sys/types.h>
#include <unistd.h>
}
#include "atf/sanity.hpp"
#include "atf/user.hpp"
namespace impl = atf::user;
#define IMPL_NAME "atf::user"
uid_t
impl::euid(void)
{
return ::geteuid();
}
bool
impl::is_member_of_group(gid_t gid)
{
static gid_t groups[NGROUPS_MAX];
static int ngroups = -1;
if (ngroups == -1) {
ngroups = ::getgroups(NGROUPS_MAX, groups);
INV(ngroups >= 0);
}
bool found = false;
for (int i = 0; !found && i < ngroups; i++)
if (groups[i] == gid)
found = true;
return found;
}
bool
impl::is_root(void)
{
return ::geteuid() == 0;
}
bool
impl::is_unprivileged(void)
{
return ::geteuid() != 0;
}

55
dist/atf/atf/user.hpp vendored
View File

@ -1,55 +0,0 @@
//
// Automated Testing Framework (atf)
//
// Copyright (c) 2007, 2008 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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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_USER_HPP_)
#define _ATF_USER_HPP_
extern "C" {
#include <sys/types.h>
}
namespace atf {
namespace user {
uid_t euid(void);
bool is_member_of_group(gid_t);
bool is_root(void);
bool is_unprivileged(void);
} // namespace user
} // namespace atf
#endif // !defined(_ATF_USER_HPP_)

155
dist/atf/atf/utils.hpp vendored
View File

@ -1,155 +0,0 @@
//
// Automated Testing Framework (atf)
//
// Copyright (c) 2007, 2008 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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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_UTILS_HPP_)
#define _ATF_UTILS_HPP_
#include <cstddef>
namespace atf {
namespace utils {
// ------------------------------------------------------------------------
// The "auto_array" class.
// ------------------------------------------------------------------------
template< class T >
class auto_array {
T* m_ptr;
public:
auto_array(T* = NULL) throw();
auto_array(auto_array< T >&) throw();
~auto_array(void) throw();
T* get(void) throw();
T* release(void) throw();
void reset(T* = NULL) throw();
auto_array< T >& operator=(auto_array< T >&) throw();
T& operator[](int) throw();
};
template< class T >
auto_array< T >::auto_array(T* ptr)
throw() :
m_ptr(ptr)
{
}
template< class T >
auto_array< T >::auto_array(auto_array< T >& ptr)
throw() :
m_ptr(ptr.release())
{
}
template< class T >
auto_array< T >::~auto_array(void)
throw()
{
if (m_ptr != NULL)
delete [] m_ptr;
}
template< class T >
T*
auto_array< T >::get(void)
throw()
{
return m_ptr;
}
template< class T >
T*
auto_array< T >::release(void)
throw()
{
T* ptr = m_ptr;
m_ptr = NULL;
return ptr;
}
template< class T >
void
auto_array< T >::reset(T* ptr)
throw()
{
if (m_ptr != NULL)
delete [] m_ptr;
m_ptr = ptr;
}
template< class T >
auto_array< T >&
auto_array< T >::operator=(auto_array< T >& ptr)
throw()
{
reset(ptr.release());
return *this;
}
template< class T >
T&
auto_array< T >::operator[](int pos)
throw()
{
return m_ptr[pos];
}
// ------------------------------------------------------------------------
// 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 utils
} // namespace atf
#endif // !defined(_ATF_UTILS_HPP_)

94
dist/atf/config.h.in vendored
View File

@ -1,94 +0,0 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if basename takes a constant pointer */
#undef HAVE_CONST_BASENAME
/* Define to 1 if dirname takes a constant pointer */
#undef HAVE_CONST_DIRNAME
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if getopt allows a + sign for POSIX behavior */
#undef HAVE_GNU_GETOPT
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `putenv' function. */
#undef HAVE_PUTENV
/* Define to 1 if putenv is in std */
#undef HAVE_PUTENV_IN_STD
/* Define to 1 if you have the `setenv' function. */
#undef HAVE_SETENV
/* 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. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `unmount' function. */
#undef HAVE_UNMOUNT
/* Define to 1 if you have the `unsetenv' function. */
#undef HAVE_UNSETENV
/* 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
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the copyright string applicable to this package. */
#undef PACKAGE_COPYRIGHT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#undef VERSION

View File

@ -1,11 +0,0 @@
# ATF pkg-config file
cxx=__CXX__
includedir=__INCLUDEDIR__
libdir=__LIBDIR__
Name: atf
Description: Automated Testing Framework
Version: __ATF_VERSION__
Cflags: -I${includedir}
Libs: -L${libdir} -latf

View File

@ -1,314 +0,0 @@
.\"
.\" Automated Testing Framework (atf)
.\"
.\" Copyright (c) 2008 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.
.\" 3. All advertising materials mentioning features or use of this
.\" software must display the following acknowledgement:
.\" This product includes software developed by the NetBSD
.\" Foundation, Inc. and its contributors.
.\" 4. Neither the name of The NetBSD Foundation 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 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.
.\"
.Dd February 26, 2008
.Dt ATF-SH-API 3
.Os
.Sh NAME
.Nm atf_add_test_case ,
.Nm atf_check ,
.Nm atf_check_equal ,
.Nm atf_config_get ,
.Nm atf_config_has ,
.Nm atf_fail ,
.Nm atf_get ,
.Nm atf_get_srcdir ,
.Nm atf_pass ,
.Nm atf_require_prog ,
.Nm atf_set ,
.Nm atf_skip
.Nd POSIX shell API to write ATF-based test programs
.Sh SYNOPSIS
.Fn atf_add_test_case "name"
.Fn atf_check "command"
.Fn atf_check_equal "expr1" "expr2"
.Fn atf_config_get "var_name"
.Fn atf_config_has "var_name"
.Fn atf_fail "reason"
.Fn atf_get "var_name"
.Fn atf_get_srcdir
.Fn atf_pass
.Fn atf_require_prog "prog_name"
.Fn atf_set "var_name" "value"
.Fn atf_skip "reason"
.Sh DESCRIPTION
ATF
provides a simple but powerful interface to easily write test programs in
the POSIX shell language.
These are extremely helpful given that they are trivial to write due to the
language simplicity and the great deal of available external tools, so they
are often ideal to test other applications at the user level.
.Pp
Test programs written using this library must be preprocessed by the
.Xr atf-compile 1
tool, which includes some boilerplate code and generates the final
(installable) test program.
.Pp
Shell-based test programs always follow this template:
.Bd -literal -offset indent
atf_test_case tc1
tc1_head() {
... first test case's header ...
}
tc1_body() {
... first test case's body ...
}
atf_test_case tc2
tc2_head() {
... second test case's header ...
}
tc2_body() {
... second test case's body ...
}
tc2_cleanup() {
... second test case's cleanup ...
}
.Ns ... additional test cases ...
atf_init_test_cases() {
atf_add_test_case tc1
atf_add_test_case tc2
... add additional test cases ...
}
.Ed
.Ss Definition of test cases
Test cases have an identifier and are composed of three different parts:
the header, the body and an optional cleanup routine, all of which are
described in
.Xr atf-test-case 8 .
To define test cases, one can use the
.Fn atf_test_case
function, which takes a single parameter specifiying the test case's
name and instructs the library to set things up to accept it as a valid
test case.
It is important to note that it
.Em does not
set the test case up for execution when the program is run.
In order to do so, a later registration is needed through the
.Fn atf_add_test_case
function detailed in
.Sx Program initialization .
.Pp
Later on, one must define the three parts of the body by providing two
or three functions (remember that the cleanup routine is optional).
These functions are named after the test case's identifier, and are
.Fn <id>_head ,
.Fn <id>_body
and
.Fn <id>_cleanup.
None of these take parameters when executed.
.Ss Program initialization
The test program must define an
.Fn atf_init_test_cases
function, which is in charge of registering the test cases that will be
executed at run time by using the
.Fn atf_add_test_case
function, which takes the name of a test case as its single parameter.
This main function should not do anything else, except maybe sourcing
auxiliary source files that define extra variables and functions.
.Ss Configuration variables
The test case has read-only access to the current configuration variables
through the
.Fn atf_config_has
and
.Fn atf_config_get
methods.
The former takes a single parameter specifying a variable name and returns
a boolean indicating whether the variable is defined or not.
The latter can take one or two parameters.
If it takes only one, it specifies the variable from which to get the
value, and this variable must be defined.
If it takes two, the second one specifies a default value to be returned
if the variable is not available.
.Ss Access to the source directory
It is possible to get the path to the test case's source directory from
anywhere in the test program by using the
.Fn atf_get_srcdir
function.
It is interesting to note that this can be used inside
.Fn atf_init_test_cases
to silently include additional helper files from the source directory.
.Ss Requiring programs
Aside from the
.Va require.progs
meta-data variable available in the header only, one can also check for
additional programs in the test case's body by using the
.Fn atf_require_prog
function, which takes the base name or full path of a single binary.
Relative paths are forbidden.
If it is not found, the test case will be automatically skipped.
.Ss Test case finalization
The test case finalizes either when the body reaches its end, at which
point the test is assumed to have
.Em passed ,
or at any explicit call to
.Fn atf_pass ,
.Fn atf_fail
or
.Fn atf_skip .
These three functions terminate the execution of the test case immediately.
The cleanup routine will be processed afterwards in a completely automated
way, regardless of the test case's termination reason.
.Pp
.Fn atf_pass
does not take any parameters.
.Fn atf_fail
and
.Fn atf_skip
take a single string parameter that describes why the test case failed or
was skipped, respectively.
It is very important to provide a clear error message in both cases so that
the user can quickly know why the test did not pass.
.Ss Helper functions for common checks
.Fn atf_check cmd expcode expout experr
.Pp
This function takes four parameters: the command to execute, the expected
numerical exit code, the expected behavior of
.Dv stdout
and the expected
behavior of
.Dv stderr .
.Fa expout
can be one of the following:
.Bl -tag -width expout
.It Li expout
What the command writes to the
.Dv stdout
channel must match exactly what is
found in the
.Pa expout
file.
.It Li ignore
The test does not check what the command writes to the
.Dv stdout
channel.
.It Li null
The command must not write anything to the
.Dv stdout
channel.
.It Li stdout
What the command writes to the
.Dv stdout
channel is written to a
.Pa stdout
file, available for further inspection.
.El
.Pp
Similarly,
.Fa experr
can be one of
.Sq Li experr ,
.Sq Li ignore ,
.Sq Li null ,
or
.Sq Li stderr ,
all of which follow the same semantics of their corresponding counterparts
for the
.Fa expout
case.
.Pp
It is important to note that when a failure is detected, this function will
print as much information as possible to be able to identify the cause of
the failure.
For example, if the
.Dv stdout
does not match with the expected contents, a
diff will be printed.
.Pp
.Fn atf_check_equal expr1 expr2
.Pp
This function takes two expressions, evaluates them and, if their
results differ, aborts the test case with an appropriate failure message.
.Sh EXAMPLES
The following shows a complete test program with a single test case that
validates the addition operator:
.Bd -literal -offset indent
atf_test_case addition
addition_head() {
atf_set "descr" "Sample tests for the addition operator"
}
addition_body() {
atf_check_equal $((0 + 0)) 0
atf_check_equal $((0 + 1)) 1
atf_check_equal $((1 + 0)) 0
atf_check_equal $((1 + 1)) 2
atf_check_equal $((100 + 200)) 300
}
atf_init_test_cases() {
atf_add_test_case addition
}
.Ed
.Pp
This other example shows how to include a file with extra helper functions
in the test program:
.Bd -literal -offset indent
.Ns ... definition of test cases ...
atf_init_test_cases() {
. $(atf_get_srcdir)/helper_functions.sh
atf_add_test_case foo1
atf_add_test_case foo2
}
.Ed
.Pp
This example demonstrates the use of the very useful
.Fn atf_check
function:
.Bd -literal -offset indent
# Check for silent output
atf_check 'true' 0 null null
# Check for silent output and failure
atf_check 'false' 1 null null
# Check for known stdout and silent stderr
echo foo >expout
atf_check 'echo foo' 0 expout null
# Generate a file for later inspection
atf_check 'ls' 0 stdout null
grep foo ls || atf_fail "foo file not found in listing"
.Ed
.Sh SEE ALSO
.Xr atf-compile 1 ,
.Xr atf-test-program 1 ,
.Xr atf 7 ,
.Xr atf-test-case 8

File diff suppressed because it is too large Load Diff

View File

@ -1,84 +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.
# 3. All advertising materials mentioning features or use of this
# software must display the following acknowledgement:
# This product includes software developed by the NetBSD
# Foundation, Inc. and its contributors.
# 4. Neither the name of The NetBSD Foundation 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 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.
#
#
# File: atf.header.subr
#
# This file provides default contents for the hooks that must be
# redefined by test programs and other stuff that has to be defined
# before the test program's code is parsed.
#
# ------------------------------------------------------------------------
# GLOBAL VARIABLES
# ------------------------------------------------------------------------
# The list of all test cases defined by the test program.
Defined_Test_Cases=
# ------------------------------------------------------------------------
# PUBLIC INTERFACE
# ------------------------------------------------------------------------
#
# atf_init_test_cases
#
# The function in charge of registering the test cases that have to
# be made available to the user. Must be redefined.
#
atf_init_test_cases()
{
_atf_error 128 "No test cases defined"
}
#
# atf_test_case tc-name
#
# Defines a new test case named tc-name. The name provided here must be
# accompanied by two functions named after it: <tc-name>_head and
# <tc-name>_body, and may also be accompanied by a <tc-name>_cleanup
# function.
#
atf_test_case()
{
Defined_Test_Cases="${Defined_Test_Cases} ${1}"
eval "${1}_head() { _atf_error 128 '${1}_head not defined'; }"
eval "${1}_body() { :; }"
eval "${1}_cleanup() { :; }"
}
# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4

View File

@ -1,86 +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.
# 3. All advertising materials mentioning features or use of this
# software must display the following acknowledgement:
# This product includes software developed by the NetBSD
# Foundation, Inc. and its contributors.
# 4. Neither the name of The NetBSD Foundation 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 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.
#
#
# File: atf.init.subr
#
# Initialization for a test program. A verbatim copy of this file is
# stuck at the very beginning of each test program, so it has to be
# kept as simple as possible to minimize the possible need of rebuilding
# a huge amount of test programs, which could happen after modifying
# this file.
#
Prog_Name=${0##*/}
#
# _atf_find_in_path program
#
# Looks for a program in the path and prints the full path to it or
# nothing if it could not be found. It also returns true in case of
# success.
#
_atf_find_in_path()
{
_prog="${1}"
_oldifs=${IFS}
IFS=:
for _dir in ${PATH}
do
if [ -x ${_dir}/${_prog} ]; then
IFS=${_oldifs}
echo ${_dir}/${_prog}
return 0
fi
done
IFS=${_oldifs}
return 1
}
#
# Look for atf-config to deduce where the atf.*.subr files are stored
# in the system.
#
Atf_Config=`_atf_find_in_path atf-config`
if [ -z "${Atf_Config}" ]; then
echo "${Prog_Name}: ERROR: Cannot locate atf-config in PATH" 1>&2
exit 128
fi
Atf_Pkgdatadir=`${Atf_Config} -t atf_pkgdatadir`
# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4

View File

@ -1,9 +0,0 @@
Content-Type: application/X-atf-atffile; version="1"
prop: test-suite = atf
tp: t_tc
tp: t_tp
tp: t_normalize
tp: t_config
tp: t_atf_check

View File

@ -1,267 +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.
# 3. All advertising materials mentioning features or use of this
# software must display the following acknowledgement:
# This product includes software developed by the NetBSD
# Foundation, Inc. and its contributors.
# 4. Neither the name of The NetBSD Foundation 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 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.
#
# -------------------------------------------------------------------------
# Helper tests for "t_atf_check".
# -------------------------------------------------------------------------
atf_test_case atf_check_info_ok
atf_check_info_ok_head()
{
atf_set "descr" "Helper test case for the t_atf_check test program"
}
atf_check_info_ok_body()
{
atf_check 'true' 0 null null
}
atf_test_case atf_check_info_fail
atf_check_info_fail_head()
{
atf_set "descr" "Helper test case for the t_atf_check test program"
}
atf_check_info_fail_body()
{
atf_check 'false' 1 null null
}
atf_test_case atf_check_expout_mismatch
atf_check_expout_mismatch_head()
{
atf_set "descr" "Helper test case for the t_atf_check test program"
}
atf_check_expout_mismatch_body()
{
cat >expout <<SECONDEOF
foo
SECONDEOF
atf_check 'echo bar' 0 expout null
}
atf_test_case atf_check_experr_mismatch
atf_check_experr_mismatch_head()
{
atf_set "descr" "Helper test case for the t_atf_check test program"
}
atf_check_experr_mismatch_body()
{
cat >experr <<SECONDEOF
foo
SECONDEOF
atf_check 'echo bar 1>&2' 0 null experr
}
atf_test_case atf_check_null_stdout
atf_check_null_stdout_head()
{
atf_set "descr" "Helper test case for the t_atf_check test program"
}
atf_check_null_stdout_body()
{
atf_check 'echo "These are the contents"' 0 null null
}
atf_test_case atf_check_null_stderr
atf_check_null_stderr_head()
{
atf_set "descr" "Helper test case for the t_atf_check test program"
}
atf_check_null_stderr_body()
{
atf_check 'echo "These are the contents" 1>&2' 0 null null
}
atf_test_case atf_check_change_cwd
atf_check_change_cwd_head()
{
atf_set "descr" "Helper test case for the t_atf_check test program"
}
atf_check_change_cwd_body()
{
mkdir foo
chmod 555 foo
cd foo
atf_check 'echo Hello' 0 stdout null
cd -
test -f stdout || atf_fail "Used incorrect work directory"
echo Hello >bar
cmp -s stdout bar || atf_fail "Used incorrect work directory"
}
atf_test_case atf_check_equal_ok
atf_check_equal_ok_head()
{
atf_set "descr" "Helper test case for the t_atf_check test program"
}
atf_check_equal_ok_body()
{
atf_check_equal a a
}
atf_test_case atf_check_equal_fail
atf_check_equal_fail_head()
{
atf_set "descr" "Helper test case for the t_atf_check test program"
}
atf_check_equal_fail_body()
{
atf_check_equal a b
}
atf_test_case atf_check_equal_eval_ok
atf_check_equal_eval_ok_head()
{
atf_set "descr" "Helper test case for the t_atf_check test program"
}
atf_check_equal_eval_ok_body()
{
x=a
y=a
atf_check_equal '${x}' '${y}'
}
atf_test_case atf_check_equal_eval_fail
atf_check_equal_eval_fail_head()
{
atf_set "descr" "Helper test case for the t_atf_check test program"
}
atf_check_equal_eval_fail_body()
{
x=a
y=b
atf_check_equal '${x}' '${y}'
}
# -------------------------------------------------------------------------
# Helper tests for "t_normalize".
# -------------------------------------------------------------------------
atf_test_case normalize
normalize_head()
{
atf_set "descr" "Helper test case for the t_normalize test program"
atf_set "a.b" "test value 1"
atf_set "c-d" "test value 2"
}
normalize_body()
{
echo "a.b: $(atf_get a.b)"
echo "c-d: $(atf_get c-d)"
}
# -------------------------------------------------------------------------
# Helper tests for "t_tc".
# -------------------------------------------------------------------------
atf_test_case tc_pass_true
tc_pass_true_head()
{
atf_set "descr" "Helper test case for the t_tc test program"
}
tc_pass_true_body()
{
true
}
atf_test_case tc_pass_false
tc_pass_false_head()
{
atf_set "descr" "Helper test case for the t_tc test program"
}
tc_pass_false_body()
{
false
}
atf_test_case tc_fail
tc_fail_head()
{
atf_set "descr" "Helper test case for the t_tc test program"
}
tc_fail_body()
{
echo "An error" 1>&2
exit 1
}
# -------------------------------------------------------------------------
# Helper tests for "t_tp".
# -------------------------------------------------------------------------
atf_test_case tp_srcdir
tp_srcdir_head()
{
atf_set "descr" "Helper test case for the t_tp test program"
}
tp_srcdir_body()
{
echo "Calling helper"
helper_subr || atf_fail "Could not call helper subroutine"
}
# -------------------------------------------------------------------------
# Main.
# -------------------------------------------------------------------------
atf_init_test_cases()
{
# Add helper tests for t_atf_check.
atf_add_test_case atf_check_info_ok
atf_add_test_case atf_check_info_fail
atf_add_test_case atf_check_expout_mismatch
atf_add_test_case atf_check_experr_mismatch
atf_add_test_case atf_check_null_stdout
atf_add_test_case atf_check_null_stderr
atf_add_test_case atf_check_change_cwd
atf_add_test_case atf_check_equal_ok
atf_add_test_case atf_check_equal_fail
atf_add_test_case atf_check_equal_eval_ok
atf_add_test_case atf_check_equal_eval_fail
# Add helper tests for t_normalize.
atf_add_test_case normalize
# Add helper tests for t_tc.
atf_add_test_case tc_pass_true
atf_add_test_case tc_pass_false
atf_add_test_case tc_fail
# Add helper tests for t_tp.
[ -f $(atf_get_srcdir)/subrs ] && . $(atf_get_srcdir)/subrs
atf_add_test_case tp_srcdir
}
# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4

View File

@ -1,193 +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.
# 3. All advertising materials mentioning features or use of this
# software must display the following acknowledgement:
# This product includes software developed by the NetBSD
# Foundation, Inc. and its contributors.
# 4. Neither the name of The NetBSD Foundation 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 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.
#
# TODO: Bring in the checks in the bootstrap testsuite for atf_check.
atf_test_case info_ok
info_ok_head()
{
atf_set "descr" "Verifies that atf_check prints an informative" \
"message even when the command is successful"
}
info_ok_body()
{
h="$(atf_get_srcdir)/h_misc -s $(atf_get_srcdir)"
atf_check "${h} -r3 atf_check_info_ok 3>resout" 0 stdout stderr
grep 'Checking command.*true' stdout >/dev/null || \
atf_fail "atf_check does not print an informative message"
atf_check "${h} -r3 atf_check_info_fail 3>resout" 0 stdout stderr
grep 'Checking command.*false' stdout >/dev/null || \
atf_fail "atf_check does not print an informative message"
}
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 if the two do no" \
"match"
}
expout_mismatch_body()
{
h="$(atf_get_srcdir)/h_misc -s $(atf_get_srcdir)"
atf_check "${h} -r3 atf_check_expout_mismatch 3>resout" 1 stdout stderr
grep 'Checking command.*echo bar' stdout >/dev/null || \
atf_fail "atf_check does not print an informative message"
grep 'stdout:' stdout >/dev/null || \
atf_fail "atf_check does not print the stdout header"
grep 'stderr:' stdout >/dev/null && \
atf_fail "atf_check prints the stdout header"
grep '^-foo' stdout >/dev/null || \
atf_fail "atf_check does not print the stdout's diff"
grep '^+bar' stdout >/dev/null || \
atf_fail "atf_check does not print the stdout's diff"
}
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 if the two do no" \
"match"
}
experr_mismatch_body()
{
h="$(atf_get_srcdir)/h_misc -s $(atf_get_srcdir)"
atf_check "${h} -r3 atf_check_experr_mismatch 3>resout" 1 stdout stderr
grep 'Checking command.*echo bar' stdout >/dev/null || \
atf_fail "atf_check does not print an informative message"
grep 'stdout:' stdout >/dev/null && \
atf_fail "atf_check prints the stdout header"
grep 'stderr:' stdout >/dev/null || \
atf_fail "atf_check does not print the stderr header"
grep '^-foo' stdout >/dev/null || \
atf_fail "atf_check does not print the stderr's diff"
grep '^+bar' stdout >/dev/null || \
atf_fail "atf_check does not print the stderr's diff"
}
atf_test_case null_stdout
null_stdout_head()
{
atf_set "descr" "Verifies that atf_check prints a the stdout it got" \
"when it was supposed to be null"
}
null_stdout_body()
{
h="$(atf_get_srcdir)/h_misc -s $(atf_get_srcdir)"
atf_check "${h} -r3 atf_check_null_stdout 3>resout" 1 stdout stderr
grep 'Checking command.*echo.*These.*contents' stdout >/dev/null || \
atf_fail "atf_check does not print an informative message"
grep 'stdout:' stdout >/dev/null || \
atf_fail "atf_check does not print the stdout header"
grep 'stderr:' stdout >/dev/null && \
atf_fail "atf_check prints the stderr header"
grep 'These are the contents' stdout >/dev/null || \
atf_fail "atf_check does not print stdout's contents"
}
atf_test_case null_stderr
null_stderr_head()
{
atf_set "descr" "Verifies that atf_check prints a the stderr it got" \
"when it was supposed to be null"
}
null_stderr_body()
{
h="$(atf_get_srcdir)/h_misc -s $(atf_get_srcdir)"
atf_check "${h} -r3 atf_check_null_stderr 3>resout" 1 stdout stderr
grep 'Checking command.*echo.*These.*contents' stdout >/dev/null || \
atf_fail "atf_check does not print an informative message"
grep 'stdout:' stdout >/dev/null && \
atf_fail "atf_check prints the stdout header"
grep 'stderr:' stdout >/dev/null || \
atf_fail "atf_check does not print the stderr header"
grep 'These are the contents' stdout >/dev/null || \
atf_fail "atf_check does not print stderr's contents"
}
atf_test_case change_cwd
change_cwd_head()
{
atf_set "descr" "Verifies that atf_check uses the correct work" \
"directory even if changing the current one"
}
change_cwd_body()
{
h="$(atf_get_srcdir)/h_misc -s $(atf_get_srcdir)"
atf_check "${h} -r3 atf_check_change_cwd 3>resout" 0 stdout stderr
atf_check 'grep -i passed resout' 0 ignore null
}
atf_test_case equal
equal_head()
{
atf_set "descr" "Verifies that atf_check_equal works"
}
equal_body()
{
h="$(atf_get_srcdir)/h_misc -s $(atf_get_srcdir)"
atf_check "${h} -r3 atf_check_equal_ok 3>resout" 0 ignore ignore
atf_check "${h} -r3 atf_check_equal_fail 3>resout" 1 ignore ignore
atf_check 'grep "a != b (a != b)" resout' 0 ignore null
atf_check "${h} -r3 atf_check_equal_eval_ok 3>resout" 0 ignore ignore
atf_check "${h} -r3 atf_check_equal_eval_fail 3>resout" 1 ignore ignore
atf_check 'grep "\${x} != \${y} (a != b)" resout' 0 ignore null
}
atf_init_test_cases()
{
atf_add_test_case info_ok
atf_add_test_case expout_mismatch
atf_add_test_case experr_mismatch
atf_add_test_case null_stdout
atf_add_test_case null_stderr
atf_add_test_case change_cwd
atf_add_test_case equal
}
# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4

View File

@ -1,84 +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.
# 3. All advertising materials mentioning features or use of this
# software must display the following acknowledgement:
# This product includes software developed by the NetBSD
# Foundation, Inc. and its contributors.
# 4. Neither the name of The NetBSD Foundation 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 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.
#
atf_test_case has
has_head()
{
atf_set "descr" "Verifies that atf_config_has works"
}
has_body()
{
atf_config_has "workdir" || atf_fail "Missing expected variable"
atf_config_has "undefined" && atf_fail "Found unexpected variable"
}
atf_test_case get
get_head()
{
atf_set "descr" "Verifies that atf_config_get works"
}
get_body()
{
echo "Querying an undefined variable"
( atf_config_get "undefined" ) >out 2>err && \
atf_fail "Getting an undefined variable succeeded"
grep 'not find' err || \
atf_fail "Getting an undefined variable did not report an error"
echo "Querying an undefined variable using a default value"
v=$(atf_config_get "undefined" "the default value")
[ "${v}" = "the default value" ] || \
atf_fail "Default value does not work"
echo "Querying an known defined variable"
v=$(atf_config_get "workdir")
case "${v}" in
/*)
;;
*)
atf_fail "Getting a known variable did not work"
;;
esac
}
atf_init_test_cases()
{
atf_add_test_case has
atf_add_test_case get
}
# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4

View File

@ -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.
# 3. All advertising materials mentioning features or use of this
# software must display the following acknowledgement:
# This product includes software developed by the NetBSD
# Foundation, Inc. and its contributors.
# 4. Neither the name of The NetBSD Foundation 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 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.
#
atf_test_case main
main_head()
{
atf_set "descr" "Verifies that variable names with symbols not" \
"allowed as part of shell variable names work"
}
main_body()
{
h="$(atf_get_srcdir)/h_misc -s $(atf_get_srcdir)"
atf_check "${h} normalize" 0 stdout ignore
atf_check 'grep "a.b: test value 1" stdout' 0 ignore null
atf_check 'grep "c-d: test value 2" stdout' 0 ignore null
}
atf_init_test_cases()
{
atf_add_test_case main
}
# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4

View File

@ -1,57 +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.
# 3. All advertising materials mentioning features or use of this
# software must display the following acknowledgement:
# This product includes software developed by the NetBSD
# Foundation, Inc. and its contributors.
# 4. Neither the name of The NetBSD Foundation 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 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.
#
atf_test_case default_status
default_status_head()
{
atf_set "descr" "Verifies that test cases get the correct default" \
"status if they did not provide any"
}
default_status_body()
{
h="$(atf_get_srcdir)/h_misc -s $(atf_get_srcdir)"
atf_check "${h} -r3 tc_pass_true 3>resout" 0 ignore ignore
atf_check "${h} -r3 tc_pass_false 3>resout" 0 ignore ignore
atf_check "${h} -r3 tc_fail 3>resout" 1 ignore stderr
atf_check 'grep "An error" stderr' 0 ignore null
}
atf_init_test_cases()
{
atf_add_test_case default_status
}
# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4

View File

@ -1,63 +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.
# 3. All advertising materials mentioning features or use of this
# software must display the following acknowledgement:
# This product includes software developed by the NetBSD
# Foundation, Inc. and its contributors.
# 4. Neither the name of The NetBSD Foundation 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 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.
#
atf_test_case srcdir
srcdir_head()
{
atf_set "descr" "Verifies that the source directory can be queried" \
"from the initialization function"
}
srcdir_body()
{
mkdir work
atf_check "cp $(atf_get_srcdir)/h_misc work" 0 null null
cat >work/subrs <<EOF
helper_subr() {
echo "This is a helper subroutine"
}
EOF
atf_check "./work/h_misc -s $(pwd)/work tp_srcdir" 0 stdout null
atf_check "grep 'Calling helper' stdout" 0 ignore null
atf_check "grep 'This is a helper subroutine' stdout" 0 ignore null
}
atf_init_test_cases()
{
atf_add_test_case srcdir
}
# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4

View File

@ -1,16 +0,0 @@
Content-Type: application/X-atf-atffile; version="1"
prop: test-suite = atf
tp: t_sanity
tp: t_env
tp: t_config
tp: t_text
tp: t_fs
tp: t_io
tp: t_expand
tp: t_user
tp: t_parser
tp: t_signals
tp: t_tests
tp: t_utils

View File

@ -1,294 +0,0 @@
//
// Automated Testing Framework (atf)
//
// Copyright (c) 2007, 2008 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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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 "atf/config.hpp"
#include "atf/env.hpp"
#include "atf/exceptions.hpp"
#include "atf/macros.hpp"
namespace atf {
namespace config {
void __reinit(void);
}
}
static
void
set_env_var(const char* name, const char* val)
{
try {
atf::env::set(name, val);
} catch (const atf::system_error& e) {
ATF_FAIL(std::string("set_env_var(") + name + ", " + val +
") failed");
}
}
static
void
unset_env_var(const char* name)
{
try {
atf::env::unset(name);
} catch (const atf::system_error& e) {
ATF_FAIL(std::string("unset_env_var(") + name + ") failed");
}
}
ATF_TEST_CASE(get);
ATF_TEST_CASE_HEAD(get)
{
set("descr", "Tests the config::get function");
}
ATF_TEST_CASE_BODY(get)
{
// Unset all known environment variables and make sure the built-in
// values do not match the bogus value we will use for testing.
unset_env_var("ATF_ARCH");
unset_env_var("ATF_CONFDIR");
unset_env_var("ATF_LIBEXECDIR");
unset_env_var("ATF_MACHINE");
unset_env_var("ATF_PKGDATADIR");
unset_env_var("ATF_SHELL");
unset_env_var("ATF_WORKDIR");
atf::config::__reinit();
ATF_CHECK(atf::config::get("atf_arch") != "env-value");
ATF_CHECK(atf::config::get("atf_confdir") != "env-value");
ATF_CHECK(atf::config::get("atf_libexecdir") != "env-value");
ATF_CHECK(atf::config::get("atf_machine") != "env-value");
ATF_CHECK(atf::config::get("atf_pkgdatadir") != "env-value");
ATF_CHECK(atf::config::get("atf_shell") != "env-value");
ATF_CHECK(atf::config::get("atf_workdir") != "env-value");
// Make sure empty values in the environment are not considered.
set_env_var("ATF_ARCH", "");
set_env_var("ATF_CONFDIR", "");
set_env_var("ATF_LIBEXECDIR", "");
set_env_var("ATF_MACHINE", "");
set_env_var("ATF_PKGDATADIR", "");
set_env_var("ATF_SHELL", "");
set_env_var("ATF_WORKDIR", "");
atf::config::__reinit();
ATF_CHECK(!atf::config::get("atf_arch").empty());
ATF_CHECK(!atf::config::get("atf_confdir").empty());
ATF_CHECK(!atf::config::get("atf_libexecdir").empty());
ATF_CHECK(!atf::config::get("atf_machine").empty());
ATF_CHECK(!atf::config::get("atf_pkgdatadir").empty());
ATF_CHECK(!atf::config::get("atf_shell").empty());
ATF_CHECK(!atf::config::get("atf_workdir").empty());
// Check if the ATF_ARCH variable is recognized.
set_env_var ("ATF_ARCH", "env-value");
unset_env_var("ATF_LIBEXECDIR");
unset_env_var("ATF_MACHINE");
unset_env_var("ATF_PKGDATADIR");
unset_env_var("ATF_SHELL");
unset_env_var("ATF_WORKDIR");
atf::config::__reinit();
ATF_CHECK_EQUAL(atf::config::get("atf_arch"), "env-value");
ATF_CHECK(atf::config::get("atf_confdir") != "env-value");
ATF_CHECK(atf::config::get("atf_libexecdir") != "env-value");
ATF_CHECK(atf::config::get("atf_machine") != "env-value");
ATF_CHECK(atf::config::get("atf_pkgdatadir") != "env-value");
ATF_CHECK(atf::config::get("atf_shell") != "env-value");
ATF_CHECK(atf::config::get("atf_workdir") != "env-value");
// Check if the ATF_CONFDIR variable is recognized.
unset_env_var("ATF_ARCH");
set_env_var ("ATF_CONFDIR", "env-value");
unset_env_var("ATF_LIBEXECDIR");
unset_env_var("ATF_MACHINE");
unset_env_var("ATF_PKGDATADIR");
unset_env_var("ATF_SHELL");
unset_env_var("ATF_WORKDIR");
atf::config::__reinit();
ATF_CHECK(atf::config::get("atf_arch") != "env-value");
ATF_CHECK_EQUAL(atf::config::get("atf_confdir"), "env-value");
ATF_CHECK(atf::config::get("atf_libexecdir") != "env-value");
ATF_CHECK(atf::config::get("atf_machine") != "env-value");
ATF_CHECK(atf::config::get("atf_pkgdatadir") != "env-value");
ATF_CHECK(atf::config::get("atf_shell") != "env-value");
ATF_CHECK(atf::config::get("atf_workdir") != "env-value");
// Check if the ATF_LIBEXECDIR variable is recognized.
unset_env_var("ATF_ARCH");
unset_env_var("ATF_CONFDIR");
set_env_var ("ATF_LIBEXECDIR", "env-value");
unset_env_var("ATF_MACHINE");
unset_env_var("ATF_PKGDATADIR");
unset_env_var("ATF_SHELL");
unset_env_var("ATF_WORKDIR");
atf::config::__reinit();
ATF_CHECK(atf::config::get("atf_arch") != "env-value");
ATF_CHECK(atf::config::get("atf_confdir") != "env-value");
ATF_CHECK_EQUAL(atf::config::get("atf_libexecdir"), "env-value");
ATF_CHECK(atf::config::get("atf_machine") != "env-value");
ATF_CHECK(atf::config::get("atf_pkgdatadir") != "env-value");
ATF_CHECK(atf::config::get("atf_shell") != "env-value");
ATF_CHECK(atf::config::get("atf_workdir") != "env-value");
// Check if the ATF_MACHINE variable is recognized.
unset_env_var("ATF_ARCH");
unset_env_var("ATF_CONFDIR");
unset_env_var("ATF_LIBEXECDIR");
set_env_var ("ATF_MACHINE", "env-value");
unset_env_var("ATF_PKGDATADIR");
unset_env_var("ATF_SHELL");
unset_env_var("ATF_WORKDIR");
atf::config::__reinit();
ATF_CHECK(atf::config::get("atf_arch") != "env-value");
ATF_CHECK(atf::config::get("atf_confdir") != "env-value");
ATF_CHECK(atf::config::get("atf_libexecdir") != "env-value");
ATF_CHECK_EQUAL(atf::config::get("atf_machine"), "env-value");
ATF_CHECK(atf::config::get("atf_pkgdatadir") != "env-value");
ATF_CHECK(atf::config::get("atf_shell") != "env-value");
ATF_CHECK(atf::config::get("atf_workdir") != "env-value");
// Check if the ATF_PKGDATADIR variable is recognized.
unset_env_var("ATF_ARCH");
unset_env_var("ATF_CONFDIR");
unset_env_var("ATF_LIBEXECDIR");
unset_env_var("ATF_MACHINE");
set_env_var ("ATF_PKGDATADIR", "env-value");
unset_env_var("ATF_SHELL");
unset_env_var("ATF_WORKDIR");
atf::config::__reinit();
ATF_CHECK(atf::config::get("atf_arch") != "env-value");
ATF_CHECK(atf::config::get("atf_confdir") != "env-value");
ATF_CHECK(atf::config::get("atf_libexecdir") != "env-value");
ATF_CHECK(atf::config::get("atf_machine") != "env-value");
ATF_CHECK_EQUAL(atf::config::get("atf_pkgdatadir"), "env-value");
ATF_CHECK(atf::config::get("atf_shell") != "env-value");
ATF_CHECK(atf::config::get("atf_workdir") != "env-value");
// Check if the ATF_SHELL variable is recognized.
unset_env_var("ATF_ARCH");
unset_env_var("ATF_CONFDIR");
unset_env_var("ATF_LIBEXECDIR");
unset_env_var("ATF_MACHINE");
unset_env_var("ATF_PKGDATADIR");
set_env_var ("ATF_SHELL", "env-value");
unset_env_var("ATF_WORKDIR");
atf::config::__reinit();
ATF_CHECK(atf::config::get("atf_arch") != "env-value");
ATF_CHECK(atf::config::get("atf_confdir") != "env-value");
ATF_CHECK(atf::config::get("atf_libexecdir") != "env-value");
ATF_CHECK(atf::config::get("atf_machine") != "env-value");
ATF_CHECK(atf::config::get("atf_pkgdatadir") != "env-value");
ATF_CHECK_EQUAL(atf::config::get("atf_shell"), "env-value");
ATF_CHECK(atf::config::get("atf_workdir") != "env-value");
// Check if the ATF_WORKDIR variable is recognized.
unset_env_var("ATF_ARCH");
unset_env_var("ATF_CONFDIR");
unset_env_var("ATF_LIBEXECDIR");
unset_env_var("ATF_MACHINE");
unset_env_var("ATF_PKGDATADIR");
unset_env_var("ATF_SHELL");
set_env_var ("ATF_WORKDIR", "env-value");
atf::config::__reinit();
ATF_CHECK(atf::config::get("atf_arch") != "env-value");
ATF_CHECK(atf::config::get("atf_confdir") != "env-value");
ATF_CHECK(atf::config::get("atf_libexecdir") != "env-value");
ATF_CHECK(atf::config::get("atf_machine") != "env-value");
ATF_CHECK(atf::config::get("atf_pkgdatadir") != "env-value");
ATF_CHECK(atf::config::get("atf_shell") != "env-value");
ATF_CHECK_EQUAL(atf::config::get("atf_workdir"), "env-value");
}
ATF_TEST_CASE(get_all);
ATF_TEST_CASE_HEAD(get_all)
{
set("descr", "Tests the config::get_all function");
}
ATF_TEST_CASE_BODY(get_all)
{
atf::config::__reinit();
// Check that the valid variables, and only those, are returned.
std::map< std::string, std::string > vars = atf::config::get_all();
ATF_CHECK_EQUAL(vars.size(), 7);
ATF_CHECK(vars.find("atf_arch") != vars.end());
ATF_CHECK(vars.find("atf_confdir") != vars.end());
ATF_CHECK(vars.find("atf_libexecdir") != vars.end());
ATF_CHECK(vars.find("atf_machine") != vars.end());
ATF_CHECK(vars.find("atf_pkgdatadir") != vars.end());
ATF_CHECK(vars.find("atf_shell") != vars.end());
ATF_CHECK(vars.find("atf_workdir") != vars.end());
}
ATF_TEST_CASE(has);
ATF_TEST_CASE_HEAD(has)
{
set("descr", "Tests the config::has function");
}
ATF_TEST_CASE_BODY(has)
{
atf::config::__reinit();
// Check for all the variables that must exist.
ATF_CHECK(atf::config::has("atf_arch"));
ATF_CHECK(atf::config::has("atf_confdir"));
ATF_CHECK(atf::config::has("atf_libexecdir"));
ATF_CHECK(atf::config::has("atf_machine"));
ATF_CHECK(atf::config::has("atf_pkgdatadir"));
ATF_CHECK(atf::config::has("atf_shell"));
ATF_CHECK(atf::config::has("atf_workdir"));
// Same as above, but using uppercase (which is incorrect).
ATF_CHECK(!atf::config::has("ATF_ARCH"));
ATF_CHECK(!atf::config::has("ATF_CONFDIR"));
ATF_CHECK(!atf::config::has("ATF_LIBEXECDIR"));
ATF_CHECK(!atf::config::has("ATF_MACHINE"));
ATF_CHECK(!atf::config::has("ATF_PKGDATADIR"));
ATF_CHECK(!atf::config::has("ATF_SHELL"));
ATF_CHECK(!atf::config::has("ATF_WORKDIR"));
// Check for some other variables that cannot exist.
ATF_CHECK(!atf::config::has("foo"));
ATF_CHECK(!atf::config::has("BAR"));
ATF_CHECK(!atf::config::has("atf_foo"));
ATF_CHECK(!atf::config::has("ATF_BAR"));
ATF_CHECK(!atf::config::has("atf_shel"));
ATF_CHECK(!atf::config::has("atf_shells"));
}
ATF_INIT_TEST_CASES(tcs)
{
ATF_ADD_TEST_CASE(tcs, has);
ATF_ADD_TEST_CASE(tcs, get);
ATF_ADD_TEST_CASE(tcs, get_all);
}

View File

@ -1,88 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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 "atf/env.hpp"
#include "atf/macros.hpp"
ATF_TEST_CASE(has_get);
ATF_TEST_CASE_HEAD(has_get)
{
set("descr", "Tests the has and get functions");
}
ATF_TEST_CASE_BODY(has_get)
{
ATF_CHECK(atf::env::has("PATH"));
ATF_CHECK(!atf::env::get("PATH").empty());
ATF_CHECK(!atf::env::has("_UNDEFINED_VARIABLE_"));
}
ATF_TEST_CASE(set);
ATF_TEST_CASE_HEAD(set)
{
set("descr", "Tests the set function");
}
ATF_TEST_CASE_BODY(set)
{
ATF_CHECK(atf::env::has("PATH"));
const std::string& oldval = atf::env::get("PATH");
atf::env::set("PATH", "foo-bar");
ATF_CHECK(atf::env::get("PATH") != oldval);
ATF_CHECK_EQUAL(atf::env::get("PATH"), "foo-bar");
ATF_CHECK(!atf::env::has("_UNDEFINED_VARIABLE_"));
atf::env::set("_UNDEFINED_VARIABLE_", "foo2-bar2");
ATF_CHECK_EQUAL(atf::env::get("_UNDEFINED_VARIABLE_"), "foo2-bar2");
}
ATF_TEST_CASE(unset);
ATF_TEST_CASE_HEAD(unset)
{
set("descr", "Tests the unset function");
}
ATF_TEST_CASE_BODY(unset)
{
ATF_CHECK(atf::env::has("PATH"));
atf::env::unset("PATH");
ATF_CHECK(!atf::env::has("PATH"));
}
ATF_INIT_TEST_CASES(tcs)
{
ATF_ADD_TEST_CASE(tcs, has_get);
ATF_ADD_TEST_CASE(tcs, set);
ATF_ADD_TEST_CASE(tcs, unset);
}

View File

@ -1,297 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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 "atf/expand.hpp"
#include "atf/macros.hpp"
// ------------------------------------------------------------------------
// Test cases for the "pattern_error" class.
// ------------------------------------------------------------------------
ATF_TEST_CASE(pattern_error);
ATF_TEST_CASE_HEAD(pattern_error)
{
set("descr", "Tests the pattern_error class.");
}
ATF_TEST_CASE_BODY(pattern_error)
{
using atf::expand::pattern_error;
atf::utils::auto_array< char > buf(new char[80]);
std::strcpy(buf.get(), "Test string.");
pattern_error pe1(buf);
{
pattern_error pe2(pe1);
ATF_CHECK(std::strcmp(pe1.what(), pe2.what()) == 0);
}
ATF_CHECK(std::strcmp(pe1.what(), "Test string.") == 0);
}
// ------------------------------------------------------------------------
// Test cases for the free functions.
// ------------------------------------------------------------------------
ATF_TEST_CASE(is_glob);
ATF_TEST_CASE_HEAD(is_glob)
{
set("descr", "Tests the is_glob function.");
}
ATF_TEST_CASE_BODY(is_glob)
{
using atf::expand::is_glob;
ATF_CHECK(!is_glob(""));
ATF_CHECK(!is_glob("a"));
ATF_CHECK(!is_glob("foo"));
ATF_CHECK( is_glob("*"));
ATF_CHECK( is_glob("a*"));
ATF_CHECK( is_glob("*a"));
ATF_CHECK( is_glob("a*b"));
ATF_CHECK( is_glob("?"));
ATF_CHECK( is_glob("a?"));
ATF_CHECK( is_glob("?a"));
ATF_CHECK( is_glob("a?b"));
}
ATF_TEST_CASE(matches_glob_plain);
ATF_TEST_CASE_HEAD(matches_glob_plain)
{
set("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_CHECK( matches_glob("", ""));
ATF_CHECK(!matches_glob("a", ""));
ATF_CHECK(!matches_glob("", "a"));
ATF_CHECK( matches_glob("ab", "ab"));
ATF_CHECK(!matches_glob("abc", "ab"));
ATF_CHECK(!matches_glob("ab", "abc"));
}
ATF_TEST_CASE(matches_glob_star);
ATF_TEST_CASE_HEAD(matches_glob_star)
{
set("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_CHECK( matches_glob("*", ""));
ATF_CHECK( matches_glob("*", "a"));
ATF_CHECK( matches_glob("*", "ab"));
ATF_CHECK(!matches_glob("a*", ""));
ATF_CHECK( matches_glob("a*", "a"));
ATF_CHECK( matches_glob("a*", "aa"));
ATF_CHECK( matches_glob("a*", "ab"));
ATF_CHECK( matches_glob("a*", "abc"));
ATF_CHECK(!matches_glob("a*", "ba"));
ATF_CHECK( matches_glob("*a", "a"));
ATF_CHECK( matches_glob("*a", "ba"));
ATF_CHECK(!matches_glob("*a", "bc"));
ATF_CHECK(!matches_glob("*a", "bac"));
ATF_CHECK( matches_glob("*ab", "ab"));
ATF_CHECK( matches_glob("*ab", "aab"));
ATF_CHECK( matches_glob("*ab", "aaab"));
ATF_CHECK( matches_glob("*ab", "bab"));
ATF_CHECK(!matches_glob("*ab", "bcb"));
ATF_CHECK(!matches_glob("*ab", "bacb"));
ATF_CHECK( matches_glob("a*b", "ab"));
ATF_CHECK( matches_glob("a*b", "acb"));
ATF_CHECK( matches_glob("a*b", "acdeb"));
ATF_CHECK(!matches_glob("a*b", "acdebz"));
ATF_CHECK(!matches_glob("a*b", "zacdeb"));
}
ATF_TEST_CASE(matches_glob_question);
ATF_TEST_CASE_HEAD(matches_glob_question)
{
set("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_CHECK(!matches_glob("?", ""));
ATF_CHECK( matches_glob("?", "a"));
ATF_CHECK(!matches_glob("?", "ab"));
ATF_CHECK( matches_glob("?", "b"));
ATF_CHECK( matches_glob("?", "c"));
ATF_CHECK( matches_glob("a?", "ab"));
ATF_CHECK( matches_glob("a?", "ac"));
ATF_CHECK(!matches_glob("a?", "ca"));
ATF_CHECK( matches_glob("???", "abc"));
ATF_CHECK( matches_glob("???", "def"));
ATF_CHECK(!matches_glob("???", "a"));
ATF_CHECK(!matches_glob("???", "ab"));
ATF_CHECK(!matches_glob("???", "abcd"));
}
ATF_TEST_CASE(expand_glob_base);
ATF_TEST_CASE_HEAD(expand_glob_base)
{
set("descr", "Tests the expand_glob function with random patterns.");
}
ATF_TEST_CASE_BODY(expand_glob_base)
{
using atf::expand::expand_glob;
std::set< std::string > candidates;
candidates.insert("foo");
candidates.insert("bar");
candidates.insert("baz");
candidates.insert("foobar");
candidates.insert("foobarbaz");
candidates.insert("foobarbazfoo");
std::set< std::string > exps;
exps = expand_glob("foo", candidates);
ATF_CHECK_EQUAL(exps.size(), 1);
ATF_CHECK(exps.find("foo") != exps.end());
exps = expand_glob("bar", candidates);
ATF_CHECK_EQUAL(exps.size(), 1);
ATF_CHECK(exps.find("bar") != exps.end());
exps = expand_glob("foo*", candidates);
ATF_CHECK_EQUAL(exps.size(), 4);
ATF_CHECK(exps.find("foo") != exps.end());
ATF_CHECK(exps.find("foobar") != exps.end());
ATF_CHECK(exps.find("foobarbaz") != exps.end());
ATF_CHECK(exps.find("foobarbazfoo") != exps.end());
exps = expand_glob("*foo", candidates);
ATF_CHECK_EQUAL(exps.size(), 2);
ATF_CHECK(exps.find("foo") != exps.end());
ATF_CHECK(exps.find("foobarbazfoo") != exps.end());
exps = expand_glob("*foo*", candidates);
ATF_CHECK_EQUAL(exps.size(), 4);
ATF_CHECK(exps.find("foo") != exps.end());
ATF_CHECK(exps.find("foobar") != exps.end());
ATF_CHECK(exps.find("foobarbaz") != exps.end());
ATF_CHECK(exps.find("foobarbazfoo") != exps.end());
exps = expand_glob("ba", candidates);
ATF_CHECK_EQUAL(exps.size(), 0);
exps = expand_glob("ba*", candidates);
ATF_CHECK_EQUAL(exps.size(), 2);
ATF_CHECK(exps.find("bar") != exps.end());
ATF_CHECK(exps.find("baz") != exps.end());
exps = expand_glob("*ba", candidates);
ATF_CHECK_EQUAL(exps.size(), 0);
exps = expand_glob("*ba*", candidates);
ATF_CHECK_EQUAL(exps.size(), 5);
ATF_CHECK(exps.find("bar") != exps.end());
ATF_CHECK(exps.find("baz") != exps.end());
ATF_CHECK(exps.find("foobar") != exps.end());
ATF_CHECK(exps.find("foobarbaz") != exps.end());
ATF_CHECK(exps.find("foobarbazfoo") != exps.end());
}
ATF_TEST_CASE(expand_glob_tps);
ATF_TEST_CASE_HEAD(expand_glob_tps)
{
set("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::set< std::string > candidates;
candidates.insert("Atffile");
candidates.insert("h_foo");
candidates.insert("t_foo");
candidates.insert("t_bar");
candidates.insert("t_baz");
candidates.insert("foo_helper");
candidates.insert("foo_test");
candidates.insert("bar_test");
candidates.insert("baz_test");
std::set< std::string > exps;
exps = expand_glob("t_*", candidates);
ATF_CHECK_EQUAL(exps.size(), 3);
ATF_CHECK(exps.find("t_foo") != exps.end());
ATF_CHECK(exps.find("t_bar") != exps.end());
ATF_CHECK(exps.find("t_baz") != exps.end());
exps = expand_glob("*_test", candidates);
ATF_CHECK_EQUAL(exps.size(), 3);
ATF_CHECK(exps.find("foo_test") != exps.end());
ATF_CHECK(exps.find("bar_test") != exps.end());
ATF_CHECK(exps.find("baz_test") != exps.end());
}
ATF_INIT_TEST_CASES(tcs)
{
// Add the tests for the "pattern_error" class.
ATF_ADD_TEST_CASE(tcs, pattern_error);
// 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);
}

View File

@ -1,707 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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/types.h>
#include <sys/stat.h>
}
#include <fstream>
#include "atf/exceptions.hpp"
#include "atf/fs.hpp"
#include "atf/macros.hpp"
static
void
create_files(void)
{
::mkdir("files", 0755);
::mkdir("files/dir", 0755);
std::ofstream os("files/reg");
os.close();
// TODO: Should create all other file types (blk, chr, fifo, lnk, sock)
// and test for them... but the underlying file system may not support
// most of these. Specially as we are working on /tmp, which can be
// mounted with flags such as "nodev". See how to deal with this
// situation.
}
// ------------------------------------------------------------------------
// Test cases for the "path" class.
// ------------------------------------------------------------------------
ATF_TEST_CASE(path_empty);
ATF_TEST_CASE_HEAD(path_empty)
{
set("descr", "Tests the path's empty method");
}
ATF_TEST_CASE_BODY(path_empty)
{
using atf::fs::path;
ATF_CHECK( path().empty());
ATF_CHECK(!path("foo").empty());
path p1;
ATF_CHECK( p1.empty());
p1 = p1 / "foo";
ATF_CHECK(!p1.empty());
}
ATF_TEST_CASE(path_normalize);
ATF_TEST_CASE_HEAD(path_normalize)
{
set("descr", "Tests the path's normalization");
}
ATF_TEST_CASE_BODY(path_normalize)
{
using atf::fs::path;
ATF_CHECK_EQUAL(path(".").str(), ".");
ATF_CHECK_EQUAL(path("..").str(), "..");
ATF_CHECK_EQUAL(path("foo").str(), "foo");
ATF_CHECK_EQUAL(path("foo/bar").str(), "foo/bar");
ATF_CHECK_EQUAL(path("foo/bar/").str(), "foo/bar");
ATF_CHECK_EQUAL(path("/foo").str(), "/foo");
ATF_CHECK_EQUAL(path("/foo/bar").str(), "/foo/bar");
ATF_CHECK_EQUAL(path("/foo/bar/").str(), "/foo/bar");
ATF_CHECK_EQUAL(path("///foo").str(), "/foo");
ATF_CHECK_EQUAL(path("///foo///bar").str(), "/foo/bar");
ATF_CHECK_EQUAL(path("///foo///bar///").str(), "/foo/bar");
}
ATF_TEST_CASE(path_is_absolute);
ATF_TEST_CASE_HEAD(path_is_absolute)
{
set("descr", "Tests the path::is_absolute function");
}
ATF_TEST_CASE_BODY(path_is_absolute)
{
using atf::fs::path;
ATF_CHECK( path("/").is_absolute());
ATF_CHECK( path("////").is_absolute());
ATF_CHECK( path("////a").is_absolute());
ATF_CHECK( path("//a//").is_absolute());
ATF_CHECK(!path("a////").is_absolute());
ATF_CHECK(!path("../foo").is_absolute());
}
ATF_TEST_CASE(path_is_root);
ATF_TEST_CASE_HEAD(path_is_root)
{
set("descr", "Tests the path::is_root function");
}
ATF_TEST_CASE_BODY(path_is_root)
{
using atf::fs::path;
ATF_CHECK( path("/").is_root());
ATF_CHECK( path("////").is_root());
ATF_CHECK(!path("////a").is_root());
ATF_CHECK(!path("//a//").is_root());
ATF_CHECK(!path("a////").is_root());
ATF_CHECK(!path("../foo").is_root());
}
ATF_TEST_CASE(path_branch_path);
ATF_TEST_CASE_HEAD(path_branch_path)
{
set("descr", "Tests the path::branch_path function");
}
ATF_TEST_CASE_BODY(path_branch_path)
{
using atf::fs::path;
ATF_CHECK_EQUAL(path(".").branch_path().str(), ".");
ATF_CHECK_EQUAL(path("foo").branch_path().str(), ".");
ATF_CHECK_EQUAL(path("foo/bar").branch_path().str(), "foo");
ATF_CHECK_EQUAL(path("/foo").branch_path().str(), "/");
ATF_CHECK_EQUAL(path("/foo/bar").branch_path().str(), "/foo");
}
ATF_TEST_CASE(path_leaf_name);
ATF_TEST_CASE_HEAD(path_leaf_name)
{
set("descr", "Tests the path::leaf_name function");
}
ATF_TEST_CASE_BODY(path_leaf_name)
{
using atf::fs::path;
ATF_CHECK_EQUAL(path(".").leaf_name(), ".");
ATF_CHECK_EQUAL(path("foo").leaf_name(), "foo");
ATF_CHECK_EQUAL(path("foo/bar").leaf_name(), "bar");
ATF_CHECK_EQUAL(path("/foo").leaf_name(), "foo");
ATF_CHECK_EQUAL(path("/foo/bar").leaf_name(), "bar");
}
ATF_TEST_CASE(path_compare_equal);
ATF_TEST_CASE_HEAD(path_compare_equal)
{
set("descr", "Tests the comparison for equality between paths");
}
ATF_TEST_CASE_BODY(path_compare_equal)
{
using atf::fs::path;
ATF_CHECK(path("/") == path("///"));
ATF_CHECK(path("/a") == path("///a"));
ATF_CHECK(path("/a") == path("///a///"));
ATF_CHECK(path("a/b/c") == path("a//b//c"));
ATF_CHECK(path("a/b/c") == path("a//b//c///"));
}
ATF_TEST_CASE(path_compare_different);
ATF_TEST_CASE_HEAD(path_compare_different)
{
set("descr", "Tests the comparison for difference between paths");
}
ATF_TEST_CASE_BODY(path_compare_different)
{
using atf::fs::path;
ATF_CHECK(path("/") != path("//a/"));
ATF_CHECK(path("/a") != path("a///"));
ATF_CHECK(path("a/b/c") != path("a/b"));
ATF_CHECK(path("a/b/c") != path("a//b"));
ATF_CHECK(path("a/b/c") != path("/a/b/c"));
ATF_CHECK(path("a/b/c") != path("/a//b//c"));
}
ATF_TEST_CASE(path_concat);
ATF_TEST_CASE_HEAD(path_concat)
{
set("descr", "Tests the concatenation of multiple paths");
}
ATF_TEST_CASE_BODY(path_concat)
{
using atf::fs::path;
ATF_CHECK_EQUAL((path("foo") / "bar").str(), "foo/bar");
ATF_CHECK_EQUAL((path("foo/") / "/bar").str(), "foo/bar");
ATF_CHECK_EQUAL((path("foo/") / "/bar/baz").str(), "foo/bar/baz");
ATF_CHECK_EQUAL((path("foo/") / "///bar///baz").str(), "foo/bar/baz");
}
ATF_TEST_CASE(path_to_absolute);
ATF_TEST_CASE_HEAD(path_to_absolute)
{
set("descr", "Tests the conversion of a relative path to an absolute "
"one");
}
ATF_TEST_CASE_BODY(path_to_absolute)
{
using atf::fs::file_info;
using atf::fs::path;
create_files();
{
const path p(".");
path pa = p.to_absolute();
ATF_CHECK(pa.is_absolute());
file_info fi(p);
file_info fia(pa);
ATF_CHECK_EQUAL(fi.get_device(), fia.get_device());
ATF_CHECK_EQUAL(fi.get_inode(), fia.get_inode());
}
{
const path p("files/reg");
path pa = p.to_absolute();
ATF_CHECK(pa.is_absolute());
file_info fi(p);
file_info fia(pa);
ATF_CHECK_EQUAL(fi.get_device(), fia.get_device());
ATF_CHECK_EQUAL(fi.get_inode(), fia.get_inode());
}
}
ATF_TEST_CASE(path_op_less);
ATF_TEST_CASE_HEAD(path_op_less)
{
set("descr", "Tests that the path's less-than operator works");
}
ATF_TEST_CASE_BODY(path_op_less)
{
using atf::fs::path;
create_files();
ATF_CHECK(!(path("aaa") < path("aaa")));
ATF_CHECK( path("aab") < path("abc"));
ATF_CHECK(!(path("abc") < path("aab")));
}
// ------------------------------------------------------------------------
// Test cases for the "directory" class.
// ------------------------------------------------------------------------
ATF_TEST_CASE(directory_read);
ATF_TEST_CASE_HEAD(directory_read)
{
set("descr", "Tests the directory class creation, which reads the "
"contents of a directory");
}
ATF_TEST_CASE_BODY(directory_read)
{
using atf::fs::directory;
using atf::fs::path;
create_files();
directory d(path("files"));
ATF_CHECK_EQUAL(d.size(), 4);
ATF_CHECK(d.find(".") != d.end());
ATF_CHECK(d.find("..") != d.end());
ATF_CHECK(d.find("dir") != d.end());
ATF_CHECK(d.find("reg") != d.end());
}
ATF_TEST_CASE(directory_file_info);
ATF_TEST_CASE_HEAD(directory_file_info)
{
set("descr", "Tests that the file_info objects attached to the "
"directory are valid");
}
ATF_TEST_CASE_BODY(directory_file_info)
{
using atf::fs::directory;
using atf::fs::file_info;
using atf::fs::path;
create_files();
directory d(path("files"));
{
directory::const_iterator iter = d.find("dir");
ATF_CHECK(iter != d.end());
const file_info& fi = (*iter).second;
ATF_CHECK(fi.get_path() == path("files/dir"));
ATF_CHECK(fi.get_type() == file_info::dir_type);
}
{
directory::const_iterator iter = d.find("reg");
ATF_CHECK(iter != d.end());
const file_info& fi = (*iter).second;
ATF_CHECK(fi.get_path() == path("files/reg"));
ATF_CHECK(fi.get_type() == file_info::reg_type);
}
}
ATF_TEST_CASE(directory_names);
ATF_TEST_CASE_HEAD(directory_names)
{
set("descr", "Tests the directory's names method");
}
ATF_TEST_CASE_BODY(directory_names)
{
using atf::fs::directory;
using atf::fs::path;
create_files();
directory d(path("files"));
std::set< std::string > ns = d.names();
ATF_CHECK_EQUAL(ns.size(), 4);
ATF_CHECK(ns.find(".") != ns.end());
ATF_CHECK(ns.find("..") != ns.end());
ATF_CHECK(ns.find("dir") != ns.end());
ATF_CHECK(ns.find("reg") != ns.end());
}
// ------------------------------------------------------------------------
// Test cases for the "file_info" class.
// ------------------------------------------------------------------------
ATF_TEST_CASE(file_info_stat);
ATF_TEST_CASE_HEAD(file_info_stat)
{
set("descr", "Tests the file_info creation and its basic contents");
}
ATF_TEST_CASE_BODY(file_info_stat)
{
using atf::fs::file_info;
using atf::fs::path;
create_files();
{
path p("files/dir");
file_info fi(p);
ATF_CHECK(fi.get_path() == p);
ATF_CHECK(fi.get_type() == file_info::dir_type);
}
{
path p("files/reg");
file_info fi(p);
ATF_CHECK(fi.get_path() == p);
ATF_CHECK(fi.get_type() == file_info::reg_type);
}
}
ATF_TEST_CASE(file_info_perms);
ATF_TEST_CASE_HEAD(file_info_perms)
{
set("descr", "Tests the file_info methods to get the file's "
"permissions");
}
ATF_TEST_CASE_BODY(file_info_perms)
{
using atf::fs::file_info;
using atf::fs::path;
path p("file");
std::ofstream os(p.c_str());
os.close();
#define perms(ur, uw, ux, gr, gw, gx, othr, othw, othx) \
{ \
file_info fi(p); \
ATF_CHECK(fi.is_owner_readable() == ur); \
ATF_CHECK(fi.is_owner_writable() == uw); \
ATF_CHECK(fi.is_owner_executable() == ux); \
ATF_CHECK(fi.is_group_readable() == gr); \
ATF_CHECK(fi.is_group_writable() == gw); \
ATF_CHECK(fi.is_group_executable() == gx); \
ATF_CHECK(fi.is_other_readable() == othr); \
ATF_CHECK(fi.is_other_writable() == othw); \
ATF_CHECK(fi.is_other_executable() == othx); \
}
::chmod(p.c_str(), 0000);
perms(false, false, false, false, false, false, false, false, false);
::chmod(p.c_str(), 0001);
perms(false, false, false, false, false, false, false, false, true);
::chmod(p.c_str(), 0010);
perms(false, false, false, false, false, true, false, false, false);
::chmod(p.c_str(), 0100);
perms(false, false, true, false, false, false, false, false, false);
::chmod(p.c_str(), 0002);
perms(false, false, false, false, false, false, false, true, false);
::chmod(p.c_str(), 0020);
perms(false, false, false, false, true, false, false, false, false);
::chmod(p.c_str(), 0200);
perms(false, true, false, false, false, false, false, false, false);
::chmod(p.c_str(), 0004);
perms(false, false, false, false, false, false, true, false, false);
::chmod(p.c_str(), 0040);
perms(false, false, false, true, false, false, false, false, false);
::chmod(p.c_str(), 0400);
perms(true, false, false, false, false, false, false, false, false);
::chmod(p.c_str(), 0644);
perms(true, true, false, true, false, false, true, false, false);
::chmod(p.c_str(), 0755);
perms(true, true, true, true, false, true, true, false, true);
::chmod(p.c_str(), 0777);
perms(true, true, true, true, true, true, true, true, true);
#undef perms
}
// ------------------------------------------------------------------------
// Test cases for the "temp_dir" class.
// ------------------------------------------------------------------------
ATF_TEST_CASE(temp_dir_raii);
ATF_TEST_CASE_HEAD(temp_dir_raii)
{
set("descr", "Tests the RAII behavior of the temp_dir class");
}
ATF_TEST_CASE_BODY(temp_dir_raii)
{
using atf::fs::exists;
using atf::fs::file_info;
using atf::fs::path;
using atf::fs::temp_dir;
path t1;
path t2;
{
path tmpl("testdir.XXXXXX");
temp_dir td1(tmpl);
temp_dir td2(tmpl);
t1 = td1.get_path();
t2 = td2.get_path();
ATF_CHECK(t1.str().find("XXXXXX") == std::string::npos);
ATF_CHECK(t2.str().find("XXXXXX") == std::string::npos);
ATF_CHECK(t1 != t2);
ATF_CHECK(!exists(tmpl));
ATF_CHECK( exists(t1));
ATF_CHECK( exists(t2));
file_info fi1(t1);
ATF_CHECK( fi1.is_owner_readable());
ATF_CHECK( fi1.is_owner_writable());
ATF_CHECK( fi1.is_owner_executable());
ATF_CHECK(!fi1.is_group_readable());
ATF_CHECK(!fi1.is_group_writable());
ATF_CHECK(!fi1.is_group_executable());
ATF_CHECK(!fi1.is_other_readable());
ATF_CHECK(!fi1.is_other_writable());
ATF_CHECK(!fi1.is_other_executable());
file_info fi2(t2);
ATF_CHECK( fi2.is_owner_readable());
ATF_CHECK( fi2.is_owner_writable());
ATF_CHECK( fi2.is_owner_executable());
ATF_CHECK(!fi2.is_group_readable());
ATF_CHECK(!fi2.is_group_writable());
ATF_CHECK(!fi2.is_group_executable());
ATF_CHECK(!fi2.is_other_readable());
ATF_CHECK(!fi2.is_other_writable());
ATF_CHECK(!fi2.is_other_executable());
}
ATF_CHECK(!exists(t1));
ATF_CHECK(!exists(t2));
}
// ------------------------------------------------------------------------
// Test cases for the free functions.
// ------------------------------------------------------------------------
ATF_TEST_CASE(change_directory);
ATF_TEST_CASE_HEAD(change_directory)
{
set("descr", "Tests the change_directory function");
}
ATF_TEST_CASE_BODY(change_directory)
{
using atf::fs::change_directory;
using atf::fs::get_current_dir;
using atf::fs::path;
create_files();
const path old = get_current_dir();
ATF_CHECK_THROW(change_directory(path("files/reg")), atf::system_error);
ATF_CHECK(get_current_dir() == old);
path old2 = change_directory(path("files"));
ATF_CHECK(old2 == old);
path old3 = change_directory(path("dir"));
ATF_CHECK(old3 == old2 / "files");
path old4 = change_directory(path("../.."));
ATF_CHECK(old4 == old3 / "dir");
ATF_CHECK(get_current_dir() == old);
}
ATF_TEST_CASE(exists);
ATF_TEST_CASE_HEAD(exists)
{
set("descr", "Tests the exists function");
}
ATF_TEST_CASE_BODY(exists)
{
using atf::fs::exists;
using atf::fs::path;
create_files();
ATF_CHECK( exists(path("files")));
ATF_CHECK(!exists(path("file")));
ATF_CHECK(!exists(path("files2")));
ATF_CHECK( exists(path("files/.")));
ATF_CHECK( exists(path("files/..")));
ATF_CHECK( exists(path("files/dir")));
ATF_CHECK( exists(path("files/reg")));
ATF_CHECK(!exists(path("files/foo")));
}
ATF_TEST_CASE(get_current_dir);
ATF_TEST_CASE_HEAD(get_current_dir)
{
set("descr", "Tests the get_current_dir function");
}
ATF_TEST_CASE_BODY(get_current_dir)
{
using atf::fs::change_directory;
using atf::fs::get_current_dir;
using atf::fs::path;
create_files();
path curdir = get_current_dir();
change_directory(path("."));
ATF_CHECK(get_current_dir() == curdir);
change_directory(path("files"));
ATF_CHECK(get_current_dir() == curdir / "files");
change_directory(path("dir"));
ATF_CHECK(get_current_dir() == curdir / "files/dir");
change_directory(path(".."));
ATF_CHECK(get_current_dir() == curdir / "files");
change_directory(path(".."));
ATF_CHECK(get_current_dir() == curdir);
}
ATF_TEST_CASE(is_executable);
ATF_TEST_CASE_HEAD(is_executable)
{
set("descr", "Tests the is_executable function");
}
ATF_TEST_CASE_BODY(is_executable)
{
using atf::fs::is_executable;
using atf::fs::path;
create_files();
ATF_CHECK( is_executable(path("files")));
ATF_CHECK( is_executable(path("files/.")));
ATF_CHECK( is_executable(path("files/..")));
ATF_CHECK( is_executable(path("files/dir")));
ATF_CHECK(!is_executable(path("non-existent")));
ATF_CHECK(!is_executable(path("files/reg")));
ATF_CHECK(::chmod("files/reg", 0755) != -1);
ATF_CHECK( is_executable(path("files/reg")));
}
ATF_TEST_CASE(cleanup);
ATF_TEST_CASE_HEAD(cleanup)
{
set("descr", "Tests the cleanup function");
}
ATF_TEST_CASE_BODY(cleanup)
{
using atf::fs::cleanup;
using atf::fs::get_current_dir;
using atf::fs::exists;
using atf::fs::path;
create_files();
path p("files");
ATF_CHECK( exists(p));
ATF_CHECK( exists(p / "dir"));
ATF_CHECK( exists(p / "reg"));
cleanup(p);
ATF_CHECK(!exists(p));
}
ATF_TEST_CASE(remove);
ATF_TEST_CASE_HEAD(remove)
{
set("descr", "Tests the remove function");
}
ATF_TEST_CASE_BODY(remove)
{
using atf::fs::exists;
using atf::fs::path;
using atf::fs::remove;
create_files();
ATF_CHECK( exists(path("files/reg")));
remove(path("files/reg"));
ATF_CHECK(!exists(path("files/reg")));
ATF_CHECK( exists(path("files/dir")));
ATF_CHECK_THROW(remove(path("files/dir")), atf::system_error);
ATF_CHECK( exists(path("files/dir")));
}
// ------------------------------------------------------------------------
// Main.
// ------------------------------------------------------------------------
ATF_INIT_TEST_CASES(tcs)
{
// Add the tests for the "path" class.
ATF_ADD_TEST_CASE(tcs, path_empty);
ATF_ADD_TEST_CASE(tcs, path_normalize);
ATF_ADD_TEST_CASE(tcs, path_is_absolute);
ATF_ADD_TEST_CASE(tcs, path_is_root);
ATF_ADD_TEST_CASE(tcs, path_branch_path);
ATF_ADD_TEST_CASE(tcs, path_leaf_name);
ATF_ADD_TEST_CASE(tcs, path_compare_equal);
ATF_ADD_TEST_CASE(tcs, path_compare_different);
ATF_ADD_TEST_CASE(tcs, path_concat);
ATF_ADD_TEST_CASE(tcs, path_to_absolute);
ATF_ADD_TEST_CASE(tcs, path_op_less);
// Add the tests for the "file_info" class.
ATF_ADD_TEST_CASE(tcs, file_info_stat);
ATF_ADD_TEST_CASE(tcs, file_info_perms);
// Add the tests for the "directory" class.
ATF_ADD_TEST_CASE(tcs, directory_read);
ATF_ADD_TEST_CASE(tcs, directory_names);
ATF_ADD_TEST_CASE(tcs, directory_file_info);
// Add the tests for the "temp_dir" class.
ATF_ADD_TEST_CASE(tcs, temp_dir_raii);
// Add the tests for the free functions.
ATF_ADD_TEST_CASE(tcs, get_current_dir);
ATF_ADD_TEST_CASE(tcs, exists);
ATF_ADD_TEST_CASE(tcs, is_executable);
ATF_ADD_TEST_CASE(tcs, change_directory);
ATF_ADD_TEST_CASE(tcs, cleanup);
ATF_ADD_TEST_CASE(tcs, remove);
}

View File

@ -1,459 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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/stat.h>
#include <fcntl.h>
#include <unistd.h>
}
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <istream>
#include <ostream>
#include "atf/io.hpp"
#include "atf/macros.hpp"
// ------------------------------------------------------------------------
// Auxiliary functions.
// ------------------------------------------------------------------------
static
void
systembuf_check_data(std::istream& is, std::size_t length)
{
char ch = 'A', chr;
std::size_t cnt = 0;
while (is >> chr) {
ATF_CHECK_EQUAL(ch, chr);
if (ch == 'Z')
ch = 'A';
else
ch++;
cnt++;
}
ATF_CHECK_EQUAL(cnt, length);
}
static
void
systembuf_write_data(std::ostream& os, std::size_t length)
{
char ch = 'A';
for (std::size_t i = 0; i < length; i++) {
os << ch;
if (ch == 'Z')
ch = 'A';
else
ch++;
}
os.flush();
}
static
void
systembuf_test_read(std::size_t length, std::size_t bufsize)
{
using atf::io::systembuf;
std::ofstream f("test_read.txt");
systembuf_write_data(f, length);
f.close();
int fd = ::open("test_read.txt", O_RDONLY);
ATF_CHECK(fd != -1);
systembuf sb(fd, bufsize);
std::istream is(&sb);
systembuf_check_data(is, length);
::close(fd);
::unlink("test_read.txt");
}
static
void
systembuf_test_write(std::size_t length, std::size_t bufsize)
{
using atf::io::systembuf;
int fd = ::open("test_write.txt", O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
ATF_CHECK(fd != -1);
systembuf sb(fd, bufsize);
std::ostream os(&sb);
systembuf_write_data(os, length);
::close(fd);
std::ifstream is("test_write.txt");
systembuf_check_data(is, length);
is.close();
::unlink("test_write.txt");
}
// ------------------------------------------------------------------------
// Test cases for the "file_handle" class.
// ------------------------------------------------------------------------
ATF_TEST_CASE(file_handle_ctor);
ATF_TEST_CASE_HEAD(file_handle_ctor)
{
set("descr", "Tests file_handle's constructors");
}
ATF_TEST_CASE_BODY(file_handle_ctor)
{
using atf::io::file_handle;
file_handle fh1;
ATF_CHECK(!fh1.is_valid());
file_handle fh2(STDOUT_FILENO);
ATF_CHECK(fh2.is_valid());
fh2.disown();
}
ATF_TEST_CASE(file_handle_copy);
ATF_TEST_CASE_HEAD(file_handle_copy)
{
set("descr", "Tests file_handle's copy constructor");
}
ATF_TEST_CASE_BODY(file_handle_copy)
{
using atf::io::file_handle;
file_handle fh1;
file_handle fh2(STDOUT_FILENO);
file_handle fh3(fh2);
ATF_CHECK(!fh2.is_valid());
ATF_CHECK(fh3.is_valid());
fh1 = fh3;
ATF_CHECK(!fh3.is_valid());
ATF_CHECK(fh1.is_valid());
fh1.disown();
}
ATF_TEST_CASE(file_handle_get);
ATF_TEST_CASE_HEAD(file_handle_get)
{
set("descr", "Tests the file_handle::get method");
}
ATF_TEST_CASE_BODY(file_handle_get)
{
using atf::io::file_handle;
file_handle fh1(STDOUT_FILENO);
ATF_CHECK_EQUAL(fh1.get(), STDOUT_FILENO);
}
ATF_TEST_CASE(file_handle_posix_remap);
ATF_TEST_CASE_HEAD(file_handle_posix_remap)
{
set("descr", "Tests the file_handle::posix_remap method");
}
ATF_TEST_CASE_BODY(file_handle_posix_remap)
{
using atf::io::file_handle;
int pfd[2];
ATF_CHECK(::pipe(pfd) != -1);
file_handle rend(pfd[0]);
file_handle wend(pfd[1]);
ATF_CHECK(rend.get() != 10);
ATF_CHECK(wend.get() != 10);
wend.posix_remap(10);
ATF_CHECK_EQUAL(wend.get(), 10);
ATF_CHECK(::write(wend.get(), "test-posix-remap", 16) != -1);
{
char buf[17];
ATF_CHECK_EQUAL(::read(rend.get(), buf, sizeof(buf)), 16);
buf[16] = '\0';
ATF_CHECK(std::strcmp(buf, "test-posix-remap") == 0);
}
// Redo previous to ensure that remapping over the same descriptor
// has no side-effects.
ATF_CHECK_EQUAL(wend.get(), 10);
wend.posix_remap(10);
ATF_CHECK_EQUAL(wend.get(), 10);
ATF_CHECK(::write(wend.get(), "test-posix-remap", 16) != -1);
{
char buf[17];
ATF_CHECK_EQUAL(::read(rend.get(), buf, sizeof(buf)), 16);
buf[16] = '\0';
ATF_CHECK(std::strcmp(buf, "test-posix-remap") == 0);
}
}
// ------------------------------------------------------------------------
// Test cases for the "systembuf" class.
// ------------------------------------------------------------------------
ATF_TEST_CASE(systembuf_short_read);
ATF_TEST_CASE_HEAD(systembuf_short_read)
{
set("descr", "Tests that a short read (one that fits in the "
"internal buffer) works when using systembuf");
}
ATF_TEST_CASE_BODY(systembuf_short_read)
{
systembuf_test_read(64, 1024);
}
ATF_TEST_CASE(systembuf_long_read);
ATF_TEST_CASE_HEAD(systembuf_long_read)
{
set("descr", "Tests that a long read (one that does not fit in the "
"internal buffer) works when using systembuf");
}
ATF_TEST_CASE_BODY(systembuf_long_read)
{
systembuf_test_read(64 * 1024, 1024);
}
ATF_TEST_CASE(systembuf_short_write);
ATF_TEST_CASE_HEAD(systembuf_short_write)
{
set("descr", "Tests that a short write (one that fits in the "
"internal buffer) works when using systembuf");
}
ATF_TEST_CASE_BODY(systembuf_short_write)
{
systembuf_test_write(64, 1024);
}
ATF_TEST_CASE(systembuf_long_write);
ATF_TEST_CASE_HEAD(systembuf_long_write)
{
set("descr", "Tests that a long write (one that does not fit in the "
"internal buffer) works when using systembuf");
}
ATF_TEST_CASE_BODY(systembuf_long_write)
{
systembuf_test_write(64 * 1024, 1024);
}
// ------------------------------------------------------------------------
// Test cases for the "pipe" class.
// ------------------------------------------------------------------------
ATF_TEST_CASE(pipe_read_and_write);
ATF_TEST_CASE_HEAD(pipe_read_and_write)
{
set("descr", "Tests reading from and writing to a pipe");
}
ATF_TEST_CASE_BODY(pipe_read_and_write)
{
using atf::io::pipe;
using atf::io::systembuf;
pipe p;
systembuf rbuf(p.rend().get());
systembuf wbuf(p.wend().get());
std::istream rend(&rbuf);
std::ostream wend(&wbuf);
// XXX This assumes that the pipe's buffer is big enough to accept
// the data written without blocking!
wend << "1Test 1message" << std::endl;
std::string tmp;
rend >> tmp;
ATF_CHECK_EQUAL(tmp, "1Test");
rend >> tmp;
ATF_CHECK_EQUAL(tmp, "1message");
}
ATF_TEST_CASE(pipe_remap_read);
ATF_TEST_CASE_HEAD(pipe_remap_read)
{
set("descr", "Tests the pipe::remap_read method");
}
ATF_TEST_CASE_BODY(pipe_remap_read)
{
using atf::io::pipe;
using atf::io::systembuf;
pipe p;
systembuf wbuf(p.wend().get());
std::ostream wend(&wbuf);
p.rend().posix_remap(STDIN_FILENO);
// XXX This assumes that the pipe's buffer is big enough to accept
// the data written without blocking!
wend << "2Test 2message" << std::endl;
std::string tmp;
std::cin >> tmp;
ATF_CHECK_EQUAL(tmp, "2Test");
std::cin >> tmp;
ATF_CHECK_EQUAL(tmp, "2message");
}
ATF_TEST_CASE(pipe_remap_write);
ATF_TEST_CASE_HEAD(pipe_remap_write)
{
set("descr", "Tests the pipe::remap_write method");
}
ATF_TEST_CASE_BODY(pipe_remap_write)
{
using atf::io::pipe;
using atf::io::systembuf;
pipe p;
if (p.rend().get() == STDOUT_FILENO) {
if (p.rend().get() > p.wend().get())
p.rend().posix_remap(p.rend().get() + 1);
else
p.rend().posix_remap(p.wend().get() + 1);
}
systembuf rbuf(p.rend().get());
std::istream rend(&rbuf);
p.wend().posix_remap(STDOUT_FILENO);
// XXX This assumes that the pipe's buffer is big enough to accept
// the data written without blocking!
std::cout << "3Test 3message" << std::endl;
std::string tmp;
rend >> tmp;
ATF_CHECK_EQUAL(tmp, "3Test");
rend >> tmp;
ATF_CHECK_EQUAL(tmp, "3message");
}
// ------------------------------------------------------------------------
// Test cases for the "pistream" class.
// ------------------------------------------------------------------------
ATF_TEST_CASE(pistream);
ATF_TEST_CASE_HEAD(pistream)
{
set("descr", "Tests the pistream class");
}
ATF_TEST_CASE_BODY(pistream)
{
using atf::io::pipe;
using atf::io::pistream;
using atf::io::systembuf;
pipe p;
int fh = p.rend().get();
pistream rend(p.rend());
ATF_CHECK_EQUAL(fh, rend.handle().get());
systembuf wbuf(p.wend().get());
std::ostream wend(&wbuf);
// XXX This assumes that the pipe's buffer is big enough to accept
// the data written without blocking!
wend << "1Test 1message" << std::endl;
std::string tmp;
rend >> tmp;
ATF_CHECK_EQUAL(tmp, "1Test");
rend >> tmp;
ATF_CHECK_EQUAL(tmp, "1message");
}
// ------------------------------------------------------------------------
// Test cases for the "postream" class.
// ------------------------------------------------------------------------
ATF_TEST_CASE(postream);
ATF_TEST_CASE_HEAD(postream)
{
set("descr", "Tests the postream class");
}
ATF_TEST_CASE_BODY(postream)
{
using atf::io::pipe;
using atf::io::postream;
using atf::io::systembuf;
pipe p;
int fh = p.wend().get();
postream wend(p.wend());
ATF_CHECK_EQUAL(fh, wend.handle().get());
// The following block is to ensure that the read end is closed
// before the write one. Otherwise we get a SIGPIPE, at least
// under FreeBSD 6.2.
{
systembuf rbuf(p.rend().get());
std::istream rend(&rbuf);
// XXX This assumes that the pipe's buffer is big enough to accept
// the data written without blocking!
wend << "1Test 1message" << std::endl;
std::string tmp;
rend >> tmp;
ATF_CHECK_EQUAL(tmp, "1Test");
rend >> tmp;
ATF_CHECK_EQUAL(tmp, "1message");
}
}
// ------------------------------------------------------------------------
// Main.
// ------------------------------------------------------------------------
ATF_INIT_TEST_CASES(tcs)
{
// Add the tests for the "file_handle" class.
ATF_ADD_TEST_CASE(tcs, file_handle_ctor);
ATF_ADD_TEST_CASE(tcs, file_handle_copy);
ATF_ADD_TEST_CASE(tcs, file_handle_get);
ATF_ADD_TEST_CASE(tcs, file_handle_posix_remap);
// Add the tests for the "systembuf" class.
ATF_ADD_TEST_CASE(tcs, systembuf_short_read);
ATF_ADD_TEST_CASE(tcs, systembuf_long_read);
ATF_ADD_TEST_CASE(tcs, systembuf_short_write);
ATF_ADD_TEST_CASE(tcs, systembuf_long_write);
// Add the tests for the "pipe" class.
ATF_ADD_TEST_CASE(tcs, pipe_read_and_write);
ATF_ADD_TEST_CASE(tcs, pipe_remap_read);
ATF_ADD_TEST_CASE(tcs, pipe_remap_write);
// Add the tests for the "pistream" class.
ATF_ADD_TEST_CASE(tcs, pistream);
// Add the tests for the "postream" class.
ATF_ADD_TEST_CASE(tcs, postream);
}

View File

@ -1,711 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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 "atf/macros.hpp"
#include "atf/parser.hpp"
// ------------------------------------------------------------------------
// Tests for the "token" class.
// ------------------------------------------------------------------------
ATF_TEST_CASE(token_getters);
ATF_TEST_CASE_HEAD(token_getters)
{
set("descr", "Tests the token getters");
}
ATF_TEST_CASE_BODY(token_getters)
{
using atf::parser::token;
{
token t(10, 0);
ATF_CHECK_EQUAL(t.lineno(), 10);
ATF_CHECK_EQUAL(t.type(), 0);
ATF_CHECK(t.text().empty());
}
{
token t(10, 0, "foo");
ATF_CHECK_EQUAL(t.lineno(), 10);
ATF_CHECK_EQUAL(t.type(), 0);
ATF_CHECK_EQUAL(t.text(), "foo");
}
{
token t(20, 1);
ATF_CHECK_EQUAL(t.lineno(), 20);
ATF_CHECK_EQUAL(t.type(), 1);
ATF_CHECK(t.text().empty());
}
{
token t(20, 1, "bar");
ATF_CHECK_EQUAL(t.lineno(), 20);
ATF_CHECK_EQUAL(t.type(), 1);
ATF_CHECK_EQUAL(t.text(), "bar");
}
}
// ------------------------------------------------------------------------
// Tests for the "tokenizer" class.
// ------------------------------------------------------------------------
#define EXPECT(tkz, ttype, ttext) \
do { \
atf::parser::token t = tkz.next(); \
ATF_CHECK(t.type() == ttype); \
ATF_CHECK_EQUAL(t.text(), ttext); \
} while (false);
namespace minimal {
static const atf::parser::token_type& eof_type = 0;
static const atf::parser::token_type& nl_type = 1;
static const atf::parser::token_type& word_type = 2;
class tokenizer : public atf::parser::tokenizer< std::istream > {
public:
tokenizer(std::istream& is, bool skipws) :
atf::parser::tokenizer< std::istream >
(is, skipws, eof_type, nl_type, word_type)
{
}
};
}
namespace delims {
static const atf::parser::token_type& eof_type = 0;
static const atf::parser::token_type& nl_type = 1;
static const atf::parser::token_type& word_type = 2;
static const atf::parser::token_type& plus_type = 3;
static const atf::parser::token_type& minus_type = 4;
static const atf::parser::token_type& equal_type = 5;
class tokenizer : public atf::parser::tokenizer< std::istream > {
public:
tokenizer(std::istream& is, bool skipws) :
atf::parser::tokenizer< std::istream >
(is, skipws, eof_type, nl_type, word_type)
{
add_delim('+', plus_type);
add_delim('-', minus_type);
add_delim('=', equal_type);
}
};
}
namespace keywords {
static const atf::parser::token_type& eof_type = 0;
static const atf::parser::token_type& nl_type = 1;
static const atf::parser::token_type& word_type = 2;
static const atf::parser::token_type& var_type = 3;
static const atf::parser::token_type& loop_type = 4;
static const atf::parser::token_type& endloop_type = 5;
class tokenizer : public atf::parser::tokenizer< std::istream > {
public:
tokenizer(std::istream& is, bool skipws) :
atf::parser::tokenizer< std::istream >
(is, skipws, eof_type, nl_type, word_type)
{
add_keyword("var", var_type);
add_keyword("loop", loop_type);
add_keyword("endloop", endloop_type);
}
};
}
namespace quotes {
static const atf::parser::token_type& eof_type = 0;
static const atf::parser::token_type& nl_type = 1;
static const atf::parser::token_type& word_type = 2;
static const atf::parser::token_type& dblquote_type = 3;
class tokenizer : public atf::parser::tokenizer< std::istream > {
public:
tokenizer(std::istream& is, bool skipws) :
atf::parser::tokenizer< std::istream >
(is, skipws, eof_type, nl_type, word_type)
{
add_quote('"', dblquote_type);
}
};
}
ATF_TEST_CASE(tokenizer_minimal_nows);
ATF_TEST_CASE_HEAD(tokenizer_minimal_nows)
{
set("descr", "Tests the tokenizer class using a minimal parser and "
"not skipping whitespace");
}
ATF_TEST_CASE_BODY(tokenizer_minimal_nows)
{
using namespace minimal;
{
std::istringstream iss("");
tokenizer mt(iss, false);
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("\n");
tokenizer mt(iss, false);
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("\n\n\n");
tokenizer mt(iss, false);
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("line 1");
tokenizer mt(iss, false);
EXPECT(mt, word_type, "line 1");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("line 1\n");
tokenizer mt(iss, false);
EXPECT(mt, word_type, "line 1");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("line 1\nline 2");
tokenizer mt(iss, false);
EXPECT(mt, word_type, "line 1");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, word_type, "line 2");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("line 1\nline 2\nline 3\n");
tokenizer mt(iss, false);
EXPECT(mt, word_type, "line 1");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, word_type, "line 2");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, word_type, "line 3");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
}
ATF_TEST_CASE(tokenizer_minimal_ws);
ATF_TEST_CASE_HEAD(tokenizer_minimal_ws)
{
set("descr", "Tests the tokenizer class using a minimal parser and "
"skipping whitespace");
}
ATF_TEST_CASE_BODY(tokenizer_minimal_ws)
{
using namespace minimal;
{
std::istringstream iss("");
minimal::tokenizer mt(iss, true);
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss(" \t ");
tokenizer mt(iss, true);
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("\n");
tokenizer mt(iss, true);
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss(" \t \n \t ");
tokenizer mt(iss, true);
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("\n\n\n");
tokenizer mt(iss, true);
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("line 1");
tokenizer mt(iss, true);
EXPECT(mt, word_type, "line");
EXPECT(mt, word_type, "1");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss(" \tline\t 1\t");
tokenizer mt(iss, true);
EXPECT(mt, word_type, "line");
EXPECT(mt, word_type, "1");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("line 1\n");
tokenizer mt(iss, true);
EXPECT(mt, word_type, "line");
EXPECT(mt, word_type, "1");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("line 1\nline 2");
tokenizer mt(iss, true);
EXPECT(mt, word_type, "line");
EXPECT(mt, word_type, "1");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, word_type, "line");
EXPECT(mt, word_type, "2");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("line 1\nline 2\nline 3\n");
tokenizer mt(iss, true);
EXPECT(mt, word_type, "line");
EXPECT(mt, word_type, "1");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, word_type, "line");
EXPECT(mt, word_type, "2");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, word_type, "line");
EXPECT(mt, word_type, "3");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss(" \t line \t 1\n\tline\t2\n line 3 \n");
tokenizer mt(iss, true);
EXPECT(mt, word_type, "line");
EXPECT(mt, word_type, "1");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, word_type, "line");
EXPECT(mt, word_type, "2");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, word_type, "line");
EXPECT(mt, word_type, "3");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
}
ATF_TEST_CASE(tokenizer_delims_nows);
ATF_TEST_CASE_HEAD(tokenizer_delims_nows)
{
set("descr", "Tests the tokenizer class using a parser with some "
"additional delimiters and not skipping whitespace");
}
ATF_TEST_CASE_BODY(tokenizer_delims_nows)
{
using namespace delims;
{
std::istringstream iss("+-=");
tokenizer mt(iss, false);
EXPECT(mt, plus_type, "+");
EXPECT(mt, minus_type, "-");
EXPECT(mt, equal_type, "=");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("+++");
tokenizer mt(iss, false);
EXPECT(mt, plus_type, "+");
EXPECT(mt, plus_type, "+");
EXPECT(mt, plus_type, "+");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("\n+\n++\n");
tokenizer mt(iss, false);
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, plus_type, "+");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, plus_type, "+");
EXPECT(mt, plus_type, "+");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("foo+bar=baz");
tokenizer mt(iss, false);
EXPECT(mt, word_type, "foo");
EXPECT(mt, plus_type, "+");
EXPECT(mt, word_type, "bar");
EXPECT(mt, equal_type, "=");
EXPECT(mt, word_type, "baz");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss(" foo\t+\tbar = baz ");
tokenizer mt(iss, false);
EXPECT(mt, word_type, " foo\t");
EXPECT(mt, plus_type, "+");
EXPECT(mt, word_type, "\tbar ");
EXPECT(mt, equal_type, "=");
EXPECT(mt, word_type, " baz ");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
}
ATF_TEST_CASE(tokenizer_delims_ws);
ATF_TEST_CASE_HEAD(tokenizer_delims_ws)
{
set("descr", "Tests the tokenizer class using a parser with some "
"additional delimiters and skipping whitespace");
}
ATF_TEST_CASE_BODY(tokenizer_delims_ws)
{
using namespace delims;
{
std::istringstream iss(" foo\t+\tbar = baz ");
tokenizer mt(iss, true);
EXPECT(mt, word_type, "foo");
EXPECT(mt, plus_type, "+");
EXPECT(mt, word_type, "bar");
EXPECT(mt, equal_type, "=");
EXPECT(mt, word_type, "baz");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
}
ATF_TEST_CASE(tokenizer_keywords_nows);
ATF_TEST_CASE_HEAD(tokenizer_keywords_nows)
{
set("descr", "Tests the tokenizer class using a parser with some "
"additional keywords and not skipping whitespace");
}
ATF_TEST_CASE_BODY(tokenizer_keywords_nows)
{
using namespace keywords;
{
std::istringstream iss("var");
tokenizer mt(iss, false);
EXPECT(mt, var_type, "var");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("va");
tokenizer mt(iss, false);
EXPECT(mt, word_type, "va");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("vara");
tokenizer mt(iss, false);
EXPECT(mt, word_type, "vara");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("var ");
tokenizer mt(iss, false);
EXPECT(mt, word_type, "var ");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("var\nloop\nendloop");
tokenizer mt(iss, false);
EXPECT(mt, var_type, "var");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, loop_type, "loop");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, endloop_type, "endloop");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
}
ATF_TEST_CASE(tokenizer_keywords_ws);
ATF_TEST_CASE_HEAD(tokenizer_keywords_ws)
{
set("descr", "Tests the tokenizer class using a parser with some "
"additional keywords and not skipping whitespace");
}
ATF_TEST_CASE_BODY(tokenizer_keywords_ws)
{
using namespace keywords;
{
std::istringstream iss("var ");
tokenizer mt(iss, true);
EXPECT(mt, var_type, "var");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss(" var \n\tloop\t\n \tendloop \t");
tokenizer mt(iss, true);
EXPECT(mt, var_type, "var");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, loop_type, "loop");
EXPECT(mt, nl_type, "<<NEWLINE>>");
EXPECT(mt, endloop_type, "endloop");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("var loop endloop");
tokenizer mt(iss, true);
EXPECT(mt, var_type, "var");
EXPECT(mt, loop_type, "loop");
EXPECT(mt, endloop_type, "endloop");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
}
ATF_TEST_CASE(tokenizer_quotes_nows);
ATF_TEST_CASE_HEAD(tokenizer_quotes_nows)
{
set("descr", "Tests the tokenizer class using a parser with "
"quoted strings and not skipping whitespace");
}
ATF_TEST_CASE_BODY(tokenizer_quotes_nows)
{
using namespace quotes;
{
std::istringstream iss("var");
tokenizer mt(iss, false);
EXPECT(mt, word_type, "var");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("\"var\"");
tokenizer mt(iss, false);
EXPECT(mt, word_type, "var");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("var1\"var2\"");
tokenizer mt(iss, false);
EXPECT(mt, word_type, "var1");
EXPECT(mt, word_type, "var2");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss("var1\" var2 \"");
tokenizer mt(iss, false);
EXPECT(mt, word_type, "var1");
EXPECT(mt, word_type, " var2 ");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
}
ATF_TEST_CASE(tokenizer_quotes_ws);
ATF_TEST_CASE_HEAD(tokenizer_quotes_ws)
{
set("descr", "Tests the tokenizer class using a parser with "
"quoted strings and skipping whitespace");
}
ATF_TEST_CASE_BODY(tokenizer_quotes_ws)
{
using namespace quotes;
{
std::istringstream iss(" var ");
tokenizer mt(iss, true);
EXPECT(mt, word_type, "var");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss(" \"var\" ");
tokenizer mt(iss, true);
EXPECT(mt, word_type, "var");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss(" var1 \"var2\" ");
tokenizer mt(iss, true);
EXPECT(mt, word_type, "var1");
EXPECT(mt, word_type, "var2");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
{
std::istringstream iss(" var1 \" var2 \" ");
tokenizer mt(iss, true);
EXPECT(mt, word_type, "var1");
EXPECT(mt, word_type, " var2 ");
EXPECT(mt, eof_type, "<<EOF>>");
EXPECT(mt, eof_type, "<<EOF>>");
}
}
// ------------------------------------------------------------------------
// Main.
// ------------------------------------------------------------------------
ATF_INIT_TEST_CASES(tcs)
{
// Add test cases for the "token" class.
ATF_ADD_TEST_CASE(tcs, token_getters);
// Add test cases for the "tokenizer" class.
ATF_ADD_TEST_CASE(tcs, tokenizer_minimal_nows);
ATF_ADD_TEST_CASE(tcs, tokenizer_minimal_ws);
ATF_ADD_TEST_CASE(tcs, tokenizer_delims_nows);
ATF_ADD_TEST_CASE(tcs, tokenizer_delims_ws);
ATF_ADD_TEST_CASE(tcs, tokenizer_keywords_nows);
ATF_ADD_TEST_CASE(tcs, tokenizer_keywords_ws);
ATF_ADD_TEST_CASE(tcs, tokenizer_quotes_nows);
ATF_ADD_TEST_CASE(tcs, tokenizer_quotes_ws);
}

View File

@ -1,145 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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 "atf/macros.hpp"
#include "atf/sanity.hpp"
template< class E >
void
test_getters(void)
{
E error("a-file.c", 123, "Test message");
ATF_CHECK(std::strcmp(error.file(), "a-file.c") == 0);
ATF_CHECK_EQUAL(error.line(), 123);
}
// ------------------------------------------------------------------------
// Tests for the "precondition_error" class.
// ------------------------------------------------------------------------
ATF_TEST_CASE(precondition_error_getters);
ATF_TEST_CASE_HEAD(precondition_error_getters)
{
set("descr", "Tests the precondition_error's getters");
}
ATF_TEST_CASE_BODY(precondition_error_getters)
{
test_getters< atf::sanity::precondition_error >();
}
ATF_TEST_CASE(precondition_error_macro);
ATF_TEST_CASE_HEAD(precondition_error_macro)
{
set("descr", "Tests the precondition_error's PRE macro");
}
ATF_TEST_CASE_BODY(precondition_error_macro)
{
PRE(true);
ATF_CHECK_THROW(PRE(false), atf::sanity::precondition_error);
}
// ------------------------------------------------------------------------
// Tests for the "postcondition_error" class.
// ------------------------------------------------------------------------
ATF_TEST_CASE(postcondition_error_getters);
ATF_TEST_CASE_HEAD(postcondition_error_getters)
{
set("descr", "Tests the postcondition_error's getters");
}
ATF_TEST_CASE_BODY(postcondition_error_getters)
{
test_getters< atf::sanity::postcondition_error >();
}
ATF_TEST_CASE(postcondition_error_macro);
ATF_TEST_CASE_HEAD(postcondition_error_macro)
{
set("descr", "Tests the postcondition_error's POST macro");
}
ATF_TEST_CASE_BODY(postcondition_error_macro)
{
POST(true);
ATF_CHECK_THROW(POST(false), atf::sanity::postcondition_error);
}
// ------------------------------------------------------------------------
// Tests for the "invariant_error" class.
// ------------------------------------------------------------------------
ATF_TEST_CASE(invariant_error_getters);
ATF_TEST_CASE_HEAD(invariant_error_getters)
{
set("descr", "Tests the invariant_error's getters");
}
ATF_TEST_CASE_BODY(invariant_error_getters)
{
test_getters< atf::sanity::invariant_error >();
}
ATF_TEST_CASE(invariant_error_macro);
ATF_TEST_CASE_HEAD(invariant_error_macro)
{
set("descr", "Tests the invariant_error's INV macro");
}
ATF_TEST_CASE_BODY(invariant_error_macro)
{
INV(true);
ATF_CHECK_THROW(INV(false), atf::sanity::invariant_error);
}
// ------------------------------------------------------------------------
// Main.
// ------------------------------------------------------------------------
ATF_INIT_TEST_CASES(tcs)
{
// We do not check the sanity_error class directly because it is just
// provided as a base class. It is indirectly tested through all of
// its children.
// Add the tests for the "precondition_error" class.
ATF_ADD_TEST_CASE(tcs, precondition_error_getters);
// Add the tests for the "postcondition_error" class.
ATF_ADD_TEST_CASE(tcs, postcondition_error_getters);
// Add the tests for the "invariant_error" class.
ATF_ADD_TEST_CASE(tcs, invariant_error_getters);
ATF_ADD_TEST_CASE(tcs, invariant_error_macro);
}

View File

@ -1,232 +0,0 @@
//
// Automated Testing Framework (atf)
//
// Copyright (c) 2008 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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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/types.h>
#include <signal.h>
#include <unistd.h>
}
#include <cerrno>
#include "atf/exceptions.hpp"
#include "atf/macros.hpp"
#include "atf/signals.hpp"
namespace sigusr1 {
static bool happened = false;
static
void
handler(int signo)
{
happened = true;
}
static
void
program(void)
{
struct sigaction sa;
sa.sa_handler = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (::sigaction(SIGUSR1, &sa, NULL) == -1)
throw atf::system_error("sigusr1::program",
"sigaction(2) failed", errno);
}
} // namespace sigusr1
namespace sigusr1_2 {
static bool happened = false;
static
void
handler(int signo)
{
happened = true;
}
} // namespace sigusr1_2
// ------------------------------------------------------------------------
// Tests for the "signal_holder" class.
// ------------------------------------------------------------------------
ATF_TEST_CASE(signal_holder_preserve);
ATF_TEST_CASE_HEAD(signal_holder_preserve)
{
set("descr", "Tests that signal_holder preserves the original signal "
"handler and restores it upon destruction");
}
ATF_TEST_CASE_BODY(signal_holder_preserve)
{
using atf::signals::signal_holder;
sigusr1::program();
sigusr1::happened = false;
::kill(::getpid(), SIGUSR1);
ATF_CHECK(sigusr1::happened);
{
signal_holder hld(SIGUSR1);
::kill(::getpid(), SIGUSR1);
}
sigusr1::happened = false;
::kill(::getpid(), SIGUSR1);
ATF_CHECK(sigusr1::happened);
}
ATF_TEST_CASE(signal_holder_destructor);
ATF_TEST_CASE_HEAD(signal_holder_destructor)
{
set("descr", "Tests that signal_holder processes a pending signal "
"upon destruction");
}
ATF_TEST_CASE_BODY(signal_holder_destructor)
{
using atf::signals::signal_holder;
sigusr1::program();
sigusr1::happened = false;
::kill(::getpid(), SIGUSR1);
ATF_CHECK(sigusr1::happened);
{
signal_holder hld(SIGUSR1);
sigusr1::happened = false;
::kill(::getpid(), SIGUSR1);
ATF_CHECK(!sigusr1::happened);
}
ATF_CHECK(sigusr1::happened);
}
ATF_TEST_CASE(signal_holder_process);
ATF_TEST_CASE_HEAD(signal_holder_process)
{
set("descr", "Tests that signal_holder's process method works to "
"process a delayed signal explicitly");
}
ATF_TEST_CASE_BODY(signal_holder_process)
{
using atf::signals::signal_holder;
sigusr1::program();
sigusr1::happened = false;
::kill(::getpid(), SIGUSR1);
ATF_CHECK(sigusr1::happened);
{
signal_holder hld(SIGUSR1);
sigusr1::happened = false;
::kill(::getpid(), SIGUSR1);
ATF_CHECK(!sigusr1::happened);
hld.process();
ATF_CHECK(sigusr1::happened);
sigusr1::happened = false;
}
ATF_CHECK(!sigusr1::happened);
}
// ------------------------------------------------------------------------
// Tests for the "signal_programmer" class.
// ------------------------------------------------------------------------
ATF_TEST_CASE(signal_programmer_program);
ATF_TEST_CASE_HEAD(signal_programmer_program)
{
set("descr", "Tests that signal_programmer correctly installs a "
"handler");
}
ATF_TEST_CASE_BODY(signal_programmer_program)
{
using atf::signals::signal_programmer;
signal_programmer sp(SIGUSR1, sigusr1_2::handler);
sigusr1_2::happened = false;
::kill(::getpid(), SIGUSR1);
ATF_CHECK(sigusr1_2::happened);
}
ATF_TEST_CASE(signal_programmer_preserve);
ATF_TEST_CASE_HEAD(signal_programmer_preserve)
{
set("descr", "Tests that signal_programmer uninstalls the handler "
"during destruction");
}
ATF_TEST_CASE_BODY(signal_programmer_preserve)
{
using atf::signals::signal_programmer;
sigusr1::program();
sigusr1::happened = false;
{
signal_programmer sp(SIGUSR1, sigusr1_2::handler);
sigusr1_2::happened = false;
::kill(::getpid(), SIGUSR1);
ATF_CHECK(sigusr1_2::happened);
}
ATF_CHECK(!sigusr1::happened);
::kill(::getpid(), SIGUSR1);
ATF_CHECK(sigusr1::happened);
}
// ------------------------------------------------------------------------
// Main.
// ------------------------------------------------------------------------
ATF_INIT_TEST_CASES(tcs)
{
// Add the tests for the "signal_holder" class.
ATF_ADD_TEST_CASE(tcs, signal_holder_preserve);
ATF_ADD_TEST_CASE(tcs, signal_holder_destructor);
ATF_ADD_TEST_CASE(tcs, signal_holder_process);
// Add the tests for the "signal_programmer" class.
ATF_ADD_TEST_CASE(tcs, signal_programmer_program);
ATF_ADD_TEST_CASE(tcs, signal_programmer_preserve);
}

View File

@ -1,127 +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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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 <atf.hpp>
// ------------------------------------------------------------------------
// Tests for the "tcr" class.
// ------------------------------------------------------------------------
ATF_TEST_CASE(tcr_default_ctor);
ATF_TEST_CASE_HEAD(tcr_default_ctor)
{
set("descr", "Tests that the default constructor creates a failed "
"result.");
}
ATF_TEST_CASE_BODY(tcr_default_ctor)
{
using atf::tests::tcr;
tcr tcr;
ATF_CHECK(tcr.get_status() == tcr::status_failed);
}
ATF_TEST_CASE(tcr_passed_ctor);
ATF_TEST_CASE_HEAD(tcr_passed_ctor)
{
set("descr", "Tests that the passed pseudo-constructor works.");
}
ATF_TEST_CASE_BODY(tcr_passed_ctor)
{
using atf::tests::tcr;
tcr tcr = tcr::passed();
ATF_CHECK(tcr.get_status() == tcr::status_passed);
}
ATF_TEST_CASE(tcr_skipped_ctor);
ATF_TEST_CASE_HEAD(tcr_skipped_ctor)
{
set("descr", "Tests that the skipped pseudo-constructor works.");
}
ATF_TEST_CASE_BODY(tcr_skipped_ctor)
{
using atf::tests::tcr;
{
tcr tcr = tcr::skipped("Reason 1");
ATF_CHECK(tcr.get_status() == tcr::status_skipped);
ATF_CHECK_EQUAL(tcr.get_reason(), "Reason 1");
}
{
tcr tcr = tcr::skipped("Reason 2");
ATF_CHECK(tcr.get_status() == tcr::status_skipped);
ATF_CHECK_EQUAL(tcr.get_reason(), "Reason 2");
}
}
ATF_TEST_CASE(tcr_failed_ctor);
ATF_TEST_CASE_HEAD(tcr_failed_ctor)
{
set("descr", "Tests that the failed pseudo-constructor works.");
}
ATF_TEST_CASE_BODY(tcr_failed_ctor)
{
using atf::tests::tcr;
{
tcr tcr = tcr::failed("Reason 1");
ATF_CHECK(tcr.get_status() == tcr::status_failed);
ATF_CHECK_EQUAL(tcr.get_reason(), "Reason 1");
}
{
tcr tcr = tcr::failed("Reason 2");
ATF_CHECK(tcr.get_status() == tcr::status_failed);
ATF_CHECK_EQUAL(tcr.get_reason(), "Reason 2");
}
}
// ------------------------------------------------------------------------
// Main.
// ------------------------------------------------------------------------
ATF_INIT_TEST_CASES(tcs)
{
// Add tests for the "tcr" class.
ATF_ADD_TEST_CASE(tcs, tcr_default_ctor);
ATF_ADD_TEST_CASE(tcs, tcr_passed_ctor);
ATF_ADD_TEST_CASE(tcs, tcr_skipped_ctor);
ATF_ADD_TEST_CASE(tcs, tcr_failed_ctor);
}

View File

@ -1,286 +0,0 @@
//
// Automated Testing Framework (atf)
//
// Copyright (c) 2007, 2008 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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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 <set>
#include <vector>
#include "atf/macros.hpp"
#include "atf/text.hpp"
ATF_TEST_CASE(join);
ATF_TEST_CASE_HEAD(join)
{
set("descr", "Tests the join function");
}
ATF_TEST_CASE_BODY(join)
{
using atf::text::join;
// First set of tests using a non-sorted collection, std::vector.
{
std::vector< std::string > words;
std::string str;
words.clear();
str = join(words, ",");
ATF_CHECK_EQUAL(str, "");
words.clear();
words.push_back("");
str = join(words, ",");
ATF_CHECK_EQUAL(str, "");
words.clear();
words.push_back("");
words.push_back("");
str = join(words, ",");
ATF_CHECK_EQUAL(str, ",");
words.clear();
words.push_back("foo");
words.push_back("");
words.push_back("baz");
str = join(words, ",");
ATF_CHECK_EQUAL(str, "foo,,baz");
words.clear();
words.push_back("foo");
words.push_back("bar");
words.push_back("baz");
str = join(words, ",");
ATF_CHECK_EQUAL(str, "foo,bar,baz");
}
// Second set of tests using a sorted collection, std::set.
{
std::set< std::string > words;
std::string str;
words.clear();
str = join(words, ",");
ATF_CHECK_EQUAL(str, "");
words.clear();
words.insert("");
str = join(words, ",");
ATF_CHECK_EQUAL(str, "");
words.clear();
words.insert("foo");
words.insert("");
words.insert("baz");
str = join(words, ",");
ATF_CHECK_EQUAL(str, ",baz,foo");
words.clear();
words.insert("foo");
words.insert("bar");
words.insert("baz");
str = join(words, ",");
ATF_CHECK_EQUAL(str, "bar,baz,foo");
}
}
ATF_TEST_CASE(split);
ATF_TEST_CASE_HEAD(split)
{
set("descr", "Tests the split function");
}
ATF_TEST_CASE_BODY(split)
{
using atf::text::split;
std::vector< std::string > words;
words = split("", " ");
ATF_CHECK_EQUAL(words.size(), 0);
words = split(" ", " ");
ATF_CHECK_EQUAL(words.size(), 0);
words = split(" ", " ");
ATF_CHECK_EQUAL(words.size(), 0);
words = split("a b", " ");
ATF_CHECK_EQUAL(words.size(), 2);
ATF_CHECK_EQUAL(words[0], "a");
ATF_CHECK_EQUAL(words[1], "b");
words = split("a b c d", " ");
ATF_CHECK_EQUAL(words.size(), 4);
ATF_CHECK_EQUAL(words[0], "a");
ATF_CHECK_EQUAL(words[1], "b");
ATF_CHECK_EQUAL(words[2], "c");
ATF_CHECK_EQUAL(words[3], "d");
words = split("foo bar", " ");
ATF_CHECK_EQUAL(words.size(), 2);
ATF_CHECK_EQUAL(words[0], "foo");
ATF_CHECK_EQUAL(words[1], "bar");
words = split("foo bar baz foobar", " ");
ATF_CHECK_EQUAL(words.size(), 4);
ATF_CHECK_EQUAL(words[0], "foo");
ATF_CHECK_EQUAL(words[1], "bar");
ATF_CHECK_EQUAL(words[2], "baz");
ATF_CHECK_EQUAL(words[3], "foobar");
words = split(" foo bar", " ");
ATF_CHECK_EQUAL(words.size(), 2);
ATF_CHECK_EQUAL(words[0], "foo");
ATF_CHECK_EQUAL(words[1], "bar");
words = split("foo bar", " ");
ATF_CHECK_EQUAL(words.size(), 2);
ATF_CHECK_EQUAL(words[0], "foo");
ATF_CHECK_EQUAL(words[1], "bar");
words = split("foo bar ", " ");
ATF_CHECK_EQUAL(words.size(), 2);
ATF_CHECK_EQUAL(words[0], "foo");
ATF_CHECK_EQUAL(words[1], "bar");
words = split(" foo bar ", " ");
ATF_CHECK_EQUAL(words.size(), 2);
ATF_CHECK_EQUAL(words[0], "foo");
ATF_CHECK_EQUAL(words[1], "bar");
}
ATF_TEST_CASE(split_delims);
ATF_TEST_CASE_HEAD(split_delims)
{
set("descr", "Tests the split function using different delimiters");
}
ATF_TEST_CASE_BODY(split_delims)
{
using atf::text::split;
std::vector< std::string > words;
words = split("", "/");
ATF_CHECK_EQUAL(words.size(), 0);
words = split(" ", "/");
ATF_CHECK_EQUAL(words.size(), 1);
ATF_CHECK_EQUAL(words[0], " ");
words = split(" ", "/");
ATF_CHECK_EQUAL(words.size(), 1);
ATF_CHECK_EQUAL(words[0], " ");
words = split("a/b", "/");
ATF_CHECK_EQUAL(words.size(), 2);
ATF_CHECK_EQUAL(words[0], "a");
ATF_CHECK_EQUAL(words[1], "b");
words = split("aLONGDELIMbcdLONGDELIMef", "LONGDELIM");
ATF_CHECK_EQUAL(words.size(), 3);
ATF_CHECK_EQUAL(words[0], "a");
ATF_CHECK_EQUAL(words[1], "bcd");
ATF_CHECK_EQUAL(words[2], "ef");
}
ATF_TEST_CASE(trim);
ATF_TEST_CASE_HEAD(trim)
{
set("descr", "Tests the trim function");
}
ATF_TEST_CASE_BODY(trim)
{
using atf::text::trim;
ATF_CHECK_EQUAL(trim(""), "");
ATF_CHECK_EQUAL(trim(" "), "");
ATF_CHECK_EQUAL(trim("\t"), "");
ATF_CHECK_EQUAL(trim(" foo"), "foo");
ATF_CHECK_EQUAL(trim("\t foo"), "foo");
ATF_CHECK_EQUAL(trim(" \tfoo"), "foo");
ATF_CHECK_EQUAL(trim("foo\t "), "foo");
ATF_CHECK_EQUAL(trim("foo \t"), "foo");
ATF_CHECK_EQUAL(trim("foo bar"), "foo bar");
ATF_CHECK_EQUAL(trim("\t foo bar"), "foo bar");
ATF_CHECK_EQUAL(trim(" \tfoo bar"), "foo bar");
ATF_CHECK_EQUAL(trim("foo bar\t "), "foo bar");
ATF_CHECK_EQUAL(trim("foo bar \t"), "foo bar");
}
ATF_TEST_CASE(to_string);
ATF_TEST_CASE_HEAD(to_string)
{
set("descr", "Tests the to_string function");
}
ATF_TEST_CASE_BODY(to_string)
{
using atf::text::to_string;
ATF_CHECK_EQUAL(to_string('a'), "a");
ATF_CHECK_EQUAL(to_string("a"), "a");
ATF_CHECK_EQUAL(to_string(5), "5");
}
#include <iostream>
ATF_TEST_CASE(to_type);
ATF_TEST_CASE_HEAD(to_type)
{
set("descr", "Tests the to_type function");
}
ATF_TEST_CASE_BODY(to_type)
{
using atf::text::to_type;
ATF_CHECK_EQUAL(to_type< int >("0"), 0);
ATF_CHECK_EQUAL(to_type< int >("1234"), 1234);
ATF_CHECK_THROW(to_type< int >("0 a"), std::runtime_error);
ATF_CHECK_THROW(to_type< int >("a"), std::runtime_error);
ATF_CHECK_EQUAL(to_type< float >("0.5"), 0.5);
ATF_CHECK_EQUAL(to_type< float >("1234.5"), 1234.5);
ATF_CHECK_THROW(to_type< float >("0.5 a"), std::runtime_error);
ATF_CHECK_THROW(to_type< float >("a"), std::runtime_error);
ATF_CHECK_EQUAL(to_type< std::string >("a"), "a");
}
ATF_INIT_TEST_CASES(tcs)
{
ATF_ADD_TEST_CASE(tcs, join);
ATF_ADD_TEST_CASE(tcs, split);
ATF_ADD_TEST_CASE(tcs, split_delims);
ATF_ADD_TEST_CASE(tcs, trim);
ATF_ADD_TEST_CASE(tcs, to_string);
ATF_ADD_TEST_CASE(tcs, to_type);
}

View File

@ -1,147 +0,0 @@
//
// Automated Testing Framework (atf)
//
// Copyright (c) 2007, 2008 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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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/param.h>
#include <sys/types.h>
#include <unistd.h>
}
#include <iostream>
#include <set>
#include "atf/exceptions.hpp"
#include "atf/macros.hpp"
#include "atf/user.hpp"
// ------------------------------------------------------------------------
// Test cases for the free functions.
// ------------------------------------------------------------------------
ATF_TEST_CASE(euid);
ATF_TEST_CASE_HEAD(euid)
{
set("descr", "Tests the euid function");
}
ATF_TEST_CASE_BODY(euid)
{
using atf::user::euid;
ATF_CHECK_EQUAL(euid(), ::geteuid());
}
ATF_TEST_CASE(is_member_of_group);
ATF_TEST_CASE_HEAD(is_member_of_group)
{
set("descr", "Tests the is_member_of_group function");
}
ATF_TEST_CASE_BODY(is_member_of_group)
{
using atf::user::is_member_of_group;
std::set< gid_t > groups;
gid_t maxgid = 0;
{
gid_t gids[NGROUPS_MAX];
int ngids = ::getgroups(NGROUPS_MAX, gids);
if (ngids == -1)
ATF_FAIL("Call to ::getgroups failed");
for (int i = 0; i < ngids; i++) {
groups.insert(gids[i]);
if (gids[i] > maxgid)
maxgid = gids[i];
}
std::cout << "User belongs to " << ngids << " groups" << std::endl;
std::cout << "Last GID is " << maxgid << std::endl;
}
for (gid_t g = 0; g <= maxgid; g++) {
if (groups.find(g) == groups.end()) {
std::cout << "Checking if user does not belong to group "
<< g << std::endl;
ATF_CHECK(!is_member_of_group(g));
} else {
std::cout << "Checking if user belongs to group "
<< g << std::endl;
ATF_CHECK(is_member_of_group(g));
}
}
}
ATF_TEST_CASE(is_root);
ATF_TEST_CASE_HEAD(is_root)
{
set("descr", "Tests the is_root function");
}
ATF_TEST_CASE_BODY(is_root)
{
using atf::user::is_root;
if (::geteuid() == 0) {
ATF_CHECK(is_root());
} else {
ATF_CHECK(!is_root());
}
}
ATF_TEST_CASE(is_unprivileged);
ATF_TEST_CASE_HEAD(is_unprivileged)
{
set("descr", "Tests the is_unprivileged function");
}
ATF_TEST_CASE_BODY(is_unprivileged)
{
using atf::user::is_unprivileged;
if (::geteuid() != 0) {
ATF_CHECK(is_unprivileged());
} else {
ATF_CHECK(!is_unprivileged());
}
}
// ------------------------------------------------------------------------
// Main.
// ------------------------------------------------------------------------
ATF_INIT_TEST_CASES(tcs)
{
// Add the tests for the free functions.
ATF_ADD_TEST_CASE(tcs, euid);
ATF_ADD_TEST_CASE(tcs, is_member_of_group);
ATF_ADD_TEST_CASE(tcs, is_root);
ATF_ADD_TEST_CASE(tcs, is_unprivileged);
}

View File

@ -1,244 +0,0 @@
//
// Automated Testing Framework (atf)
//
// Copyright (c) 2007, 2008 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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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 <iostream>
#include "atf/macros.hpp"
#include "atf/utils.hpp"
// ------------------------------------------------------------------------
// Tests for the "auto_array" class.
// ------------------------------------------------------------------------
class test_array {
public:
int m_value;
static ssize_t m_nblocks;
void* operator new(size_t size)
{
ATF_FAIL("New called but should have been new[]");
}
void* operator new[](size_t size)
{
m_nblocks++;
void* mem = ::operator new(size);
std::cout << "Allocated 'test_array' object " << mem << std::endl;
return mem;
}
void operator delete(void* mem)
{
ATF_FAIL("Delete called but should have been delete[]");
}
void operator delete[](void* mem)
{
std::cout << "Releasing 'test_array' object " << mem << std::endl;
if (m_nblocks == 0)
ATF_FAIL("Unbalanced delete[]");
m_nblocks--;
::operator delete(mem);
}
};
ssize_t test_array::m_nblocks = 0;
ATF_TEST_CASE(auto_array_scope);
ATF_TEST_CASE_HEAD(auto_array_scope)
{
set("descr", "Tests the automatic scope handling in the auto_array "
"smart pointer class");
}
ATF_TEST_CASE_BODY(auto_array_scope)
{
using atf::utils::auto_array;
ATF_CHECK_EQUAL(test_array::m_nblocks, 0);
{
auto_array< test_array > t(new test_array[10]);
ATF_CHECK_EQUAL(test_array::m_nblocks, 1);
}
ATF_CHECK_EQUAL(test_array::m_nblocks, 0);
}
ATF_TEST_CASE(auto_array_copy);
ATF_TEST_CASE_HEAD(auto_array_copy)
{
set("descr", "Tests the auto_array smart pointer class' copy "
"constructor");
}
ATF_TEST_CASE_BODY(auto_array_copy)
{
using atf::utils::auto_array;
ATF_CHECK_EQUAL(test_array::m_nblocks, 0);
{
auto_array< test_array > t1(new test_array[10]);
ATF_CHECK_EQUAL(test_array::m_nblocks, 1);
{
auto_array< test_array > t2(t1);
ATF_CHECK_EQUAL(test_array::m_nblocks, 1);
}
ATF_CHECK_EQUAL(test_array::m_nblocks, 0);
}
ATF_CHECK_EQUAL(test_array::m_nblocks, 0);
}
ATF_TEST_CASE(auto_array_get);
ATF_TEST_CASE_HEAD(auto_array_get)
{
set("descr", "Tests the auto_array smart pointer class' get "
"method");
}
ATF_TEST_CASE_BODY(auto_array_get)
{
using atf::utils::auto_array;
test_array* ta = new test_array[10];
auto_array< test_array > t(ta);
ATF_CHECK_EQUAL(t.get(), ta);
}
ATF_TEST_CASE(auto_array_release);
ATF_TEST_CASE_HEAD(auto_array_release)
{
set("descr", "Tests the auto_array smart pointer class' release "
"method");
}
ATF_TEST_CASE_BODY(auto_array_release)
{
using atf::utils::auto_array;
test_array* ta1 = new test_array[10];
{
auto_array< test_array > t(ta1);
ATF_CHECK_EQUAL(test_array::m_nblocks, 1);
test_array* ta2 = t.release();
ATF_CHECK_EQUAL(ta2, ta1);
ATF_CHECK_EQUAL(test_array::m_nblocks, 1);
}
ATF_CHECK_EQUAL(test_array::m_nblocks, 1);
delete [] ta1;
}
ATF_TEST_CASE(auto_array_reset);
ATF_TEST_CASE_HEAD(auto_array_reset)
{
set("descr", "Tests the auto_array smart pointer class' reset "
"method");
}
ATF_TEST_CASE_BODY(auto_array_reset)
{
using atf::utils::auto_array;
test_array* ta1 = new test_array[10];
test_array* ta2 = new test_array[10];
ATF_CHECK_EQUAL(test_array::m_nblocks, 2);
{
auto_array< test_array > t(ta1);
ATF_CHECK_EQUAL(test_array::m_nblocks, 2);
t.reset(ta2);
ATF_CHECK_EQUAL(test_array::m_nblocks, 1);
t.reset();
ATF_CHECK_EQUAL(test_array::m_nblocks, 0);
}
ATF_CHECK_EQUAL(test_array::m_nblocks, 0);
}
ATF_TEST_CASE(auto_array_assign);
ATF_TEST_CASE_HEAD(auto_array_assign)
{
set("descr", "Tests the auto_array smart pointer class' assignment "
"operator");
}
ATF_TEST_CASE_BODY(auto_array_assign)
{
using atf::utils::auto_array;
ATF_CHECK_EQUAL(test_array::m_nblocks, 0);
{
auto_array< test_array > t1(new test_array[10]);
ATF_CHECK_EQUAL(test_array::m_nblocks, 1);
{
auto_array< test_array > t2;
t2 = t1;
ATF_CHECK_EQUAL(test_array::m_nblocks, 1);
}
ATF_CHECK_EQUAL(test_array::m_nblocks, 0);
}
ATF_CHECK_EQUAL(test_array::m_nblocks, 0);
}
ATF_TEST_CASE(auto_array_access);
ATF_TEST_CASE_HEAD(auto_array_access)
{
set("descr", "Tests the auto_array smart pointer class' access "
"operator");
}
ATF_TEST_CASE_BODY(auto_array_access)
{
using atf::utils::auto_array;
auto_array< test_array > t(new test_array[10]);
for (int i = 0; i < 10; i++)
t[i].m_value = i * 2;
for (int i = 0; i < 10; i++)
ATF_CHECK_EQUAL(t[i].m_value, i * 2);
}
// ------------------------------------------------------------------------
// Main.
// ------------------------------------------------------------------------
ATF_INIT_TEST_CASES(tcs)
{
// Add the test for the "auto_array" class.
ATF_ADD_TEST_CASE(tcs, auto_array_scope);
ATF_ADD_TEST_CASE(tcs, auto_array_copy);
ATF_ADD_TEST_CASE(tcs, auto_array_get);
ATF_ADD_TEST_CASE(tcs, auto_array_release);
ATF_ADD_TEST_CASE(tcs, auto_array_reset);
ATF_ADD_TEST_CASE(tcs, auto_array_assign);
ATF_ADD_TEST_CASE(tcs, auto_array_access);
}

View File

@ -1 +0,0 @@
#include <atf/application.hpp>

View File

@ -1 +0,0 @@
#include <atf.hpp>

View File

@ -1 +0,0 @@
#include <atf/atffile.hpp>

View File

@ -1 +0,0 @@
#include <atf/config.hpp>

View File

@ -1 +0,0 @@
#include <atf/env.hpp>

View File

@ -1 +0,0 @@
#include <atf/exceptions.hpp>

View File

@ -1 +0,0 @@
#include <atf/expand.hpp>

View File

@ -1 +0,0 @@
#include <atf/formats.hpp>

View File

@ -1 +0,0 @@
#include <atf/fs.hpp>

View File

@ -1 +0,0 @@
#include <atf/io.hpp>

View File

@ -1 +0,0 @@
#include <atf/macros.hpp>

View File

@ -1 +0,0 @@
#include <atf/parser.hpp>

View File

@ -1 +0,0 @@
#include <atf/sanity.hpp>

View File

@ -1 +0,0 @@
#include <atf/signals.hpp>

View File

@ -1 +0,0 @@
#include <atf/tests.hpp>

View File

@ -1 +0,0 @@
#include <atf/text.hpp>

View File

@ -1 +0,0 @@
#include <atf/ui.hpp>

View File

@ -1 +0,0 @@
#include <atf/user.hpp>

View File

@ -1 +0,0 @@
#include <atf/utils.hpp>

View File

@ -1,75 +0,0 @@
//
// Automated Testing Framework (atf)
//
// Copyright (c) 2008 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.
// 3. All advertising materials mentioning features or use of this
// software must display the following acknowledgement:
// This product includes software developed by the NetBSD
// Foundation, Inc. and its contributors.
// 4. Neither the name of The NetBSD Foundation 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 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 <atf/macros.hpp>
void
atf_check_inside_if(void)
{
// Make sure that ATF_CHECK can be used inside an if statement that
// does not have braces. Earlier versions of it generated an error
// if there was an else clause because they confused the compiler
// by defining an unprotected nested if.
if (true)
ATF_CHECK(true);
else
ATF_CHECK(true);
}
void
atf_check_equal_inside_if(void)
{
// Make sure that ATF_CHECK_EQUAL can be used inside an if statement
// that does not have braces. Earlier versions of it generated an
// error if there was an else clause because they confused the
// compiler by defining an unprotected nested if.
if (true)
ATF_CHECK_EQUAL(true, true);
else
ATF_CHECK_EQUAL(true, true);
}
void
atf_check_throw_runtime_error(void)
{
// Check that we can pass std::runtime_error to ATF_CHECK_THROW.
// Earlier versions generated a warning because the macro's code also
// attempted to capture this exception, and thus we had a duplicate
// catch clause.
ATF_CHECK_THROW((void)0, std::runtime_error);
}