Drop files removed (most of them were renamed) in atf-0.5.
This commit is contained in:
parent
ffe8204c6b
commit
f768eb7c67
|
@ -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
|
|
@ -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_)
|
|
@ -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;
|
||||
}
|
|
@ -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_)
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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_)
|
|
@ -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
|
|
@ -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_)
|
|
@ -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
|
||||
}
|
|
@ -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_)
|
|
@ -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";
|
||||
}
|
||||
}
|
|
@ -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_)
|
|
@ -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;
|
||||
}
|
|
@ -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_)
|
File diff suppressed because it is too large
Load Diff
|
@ -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_)
|
|
@ -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);
|
||||
}
|
|
@ -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_)
|
|
@ -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;
|
||||
}
|
|
@ -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_)
|
|
@ -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_)
|
|
@ -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;
|
||||
}
|
|
@ -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_)
|
|
@ -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");
|
||||
}
|
|
@ -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_)
|
|
@ -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);
|
||||
}
|
|
@ -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_)
|
|
@ -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);
|
||||
}
|
|
@ -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_)
|
|
@ -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);
|
||||
}
|
|
@ -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_)
|
|
@ -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);
|
||||
}
|
|
@ -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_)
|
|
@ -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;
|
||||
}
|
|
@ -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_)
|
|
@ -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_)
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
#include <atf/application.hpp>
|
|
@ -1 +0,0 @@
|
|||
#include <atf.hpp>
|
|
@ -1 +0,0 @@
|
|||
#include <atf/atffile.hpp>
|
|
@ -1 +0,0 @@
|
|||
#include <atf/config.hpp>
|
|
@ -1 +0,0 @@
|
|||
#include <atf/env.hpp>
|
|
@ -1 +0,0 @@
|
|||
#include <atf/exceptions.hpp>
|
|
@ -1 +0,0 @@
|
|||
#include <atf/expand.hpp>
|
|
@ -1 +0,0 @@
|
|||
#include <atf/formats.hpp>
|
|
@ -1 +0,0 @@
|
|||
#include <atf/fs.hpp>
|
|
@ -1 +0,0 @@
|
|||
#include <atf/io.hpp>
|
|
@ -1 +0,0 @@
|
|||
#include <atf/macros.hpp>
|
|
@ -1 +0,0 @@
|
|||
#include <atf/parser.hpp>
|
|
@ -1 +0,0 @@
|
|||
#include <atf/sanity.hpp>
|
|
@ -1 +0,0 @@
|
|||
#include <atf/signals.hpp>
|
|
@ -1 +0,0 @@
|
|||
#include <atf/tests.hpp>
|
|
@ -1 +0,0 @@
|
|||
#include <atf/text.hpp>
|
|
@ -1 +0,0 @@
|
|||
#include <atf/ui.hpp>
|
|
@ -1 +0,0 @@
|
|||
#include <atf/user.hpp>
|
|
@ -1 +0,0 @@
|
|||
#include <atf/utils.hpp>
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue