//
// 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
//
// 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 <fcntl.h>
#include <signal.h>
#include <unistd.h>
}
#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include "atf-c++/detail/parser.hpp"
#include "atf-c++/detail/process.hpp"
#include "atf-c++/detail/sanity.hpp"
#include "config.hpp"
#include "fs.hpp"
#include "io.hpp"
#include "requirements.hpp"
#include "signals.hpp"
#include "test-program.hpp"
#include "timer.hpp"
#include "user.hpp"
namespace {
static void
{
// If we receive a signal while writing to the stream, the bad bit gets set.
// Things seem to behave fine afterwards if we clear such error condition.
// However, I'm not sure if it's safe to query errno at this point.
else
}
}
namespace atf_tp {
public:
{
}
};
} // namespace atf_tp
{
" in test program"));
}
public:
{
}
const impl::test_cases_map&
get_tcs(void)
const
{
return m_tcs;
}
};
struct get_metadata_params {
{
}
};
struct test_case_params {
{
}
};
static
generate_timestamp(void)
{
return "0.0";
return "0.0";
else
return buf;
}
static
void
{
}
static
char**
{
}
return argv;
}
static
void
{
// This leaks memory in case of a failure, but it is OK. Exiting will
// do the necessary cleanup.
}
static
{
return args;
}
static
void
silence_stdin(void)
{
::close(STDIN_FILENO);
if (fd == -1)
}
static
void
{
}
static
void
{
static_cast< const get_metadata_params* >(raw_params);
}
void
{
static_cast< const test_case_params* >(raw_params);
// The input 'tp' parameter may be relative and become invalid once
// we change the current working directory.
// Prepare the test program's arguments. We use dynamic memory and
// do not care to release it. We are going to die anyway very soon,
// either due to exec(2) or to exit(3).
}
static void
{
out_arg = "";
out_reason = "";
out_arg = "";
"': unclosed optional argument");
} else
}
static impl::test_case_result
{
"be accompanied by a reason nor an expected value");
}
static impl::test_case_result
{
"be accompanied by a reason but not by an expected value");
}
static impl::test_case_result
{
"be accompanied by a reason");
int value;
value = -1;
} else {
try {
} catch (const std::runtime_error&) {
state + "' state must be an integer");
}
}
}
} // anonymous namespace
{
}
{
}
void
{
}
void
{
}
void
{
"empty");
if (name == "descr") {
// Any non-empty value is valid.
try {
} catch (const std::runtime_error&) {
" boolean value");
}
} else if (name == "ident") {
} else if (name == "require.arch") {
} else if (name == "require.config") {
} else if (name == "require.files") {
} else if (name == "require.machine") {
} else if (name == "require.memory") {
try {
} catch (const std::runtime_error&) {
"integer value representing an amount of bytes");
}
} else if (name == "require.progs") {
} else if (name == "require.user") {
} else if (name == "timeout") {
" value");
} else if (name == "use.fs") {
// Deprecated; ignore it.
// Any non-empty value is valid.
} else {
}
}
void
{
using namespace atf_tp;
"application/X-atf-tp", 1);
try {
if (t.text() != "ident")
"must be 'ident'");
do {
"line or eof");
"not define an 'ident' property");
if (t.text() != "ident")
"test case must be 'ident'");
}
}
ATF_PARSER_CALLBACK(p, got_eof());
} catch (const parse_error& pe) {
}
}
{
if (state == "expected_death")
else if (state == "failed")
else if (state == "passed")
else if (state == "skipped")
else
}
{
hm["Content-Type"] =
ct_attrs);
}
void
{
}
void
{
}
void
{
}
void
{
else
}
void
{
}
void
{
}
void
{
}
void
{
}
{
static_cast< void * >(¶ms));
"exit status for test case list");
}
{
if (!results_file)
if (!results_file.good())
}
namespace {
static volatile bool terminate_poll;
static void
{
terminate_poll = true;
}
void
{
switch (index) {
default: UNREACHABLE;
}
}
public:
{
}
};
} // anonymous namespace
{
// TODO: Capture termination signals and deliver them to the subprocess
// instead. Or maybe do something else; think about it.
static_cast< void * >(¶ms));
terminate_poll = false;
const unsigned int timeout =
// Get the input stream of stdout and stderr.
bool timed_out = false;
// Process the test case's output and multiplex it into our output
// stream as we read it.
try {
} catch (...) {
}
if (timed_out) {
// Don't assume the child process has been signaled due to the timeout
// expiration as older versions did. The child process may have exited
// but we may have timed out due to a subchild process getting stuck.
}
}