a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt// Copyright (c) 2008 The NetBSD Foundation, Inc.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// All rights reserved.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt//
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// Redistribution and use in source and binary forms, with or without
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// modification, are permitted provided that the following conditions
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// are met:
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// 1. Redistributions of source code must retain the above copyright
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// notice, this list of conditions and the following disclaimer.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// 2. Redistributions in binary form must reproduce the above copyright
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// notice, this list of conditions and the following disclaimer in the
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// documentation and/or other materials provided with the distribution.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt//
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntextern "C" {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <sys/types.h>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <sys/wait.h>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <limits.h>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <signal.h>
ef2aea274a14bd33e722336ed8a15bab0289b1f3Mark Andrews#include <unistd.h>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <cerrno>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <cstdlib>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <cstring>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <fstream>
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt#include <ios>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <iostream>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <iterator>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <list>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <memory>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include <utility>
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include "atf-c++/check.hpp"
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include "atf-c++/detail/application.hpp"
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt#include "atf-c++/detail/auto_array.hpp"
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews#include "atf-c++/detail/env.hpp"
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include "atf-c++/detail/exceptions.hpp"
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include "atf-c++/detail/fs.hpp"
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include "atf-c++/detail/process.hpp"
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include "atf-c++/detail/sanity.hpp"
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt#include "atf-c++/detail/text.hpp"
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// ------------------------------------------------------------------------
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// Auxiliary functions.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// ------------------------------------------------------------------------
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntnamespace {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntenum status_check_t {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt sc_exit,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt sc_ignore,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt sc_signal,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt};
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstruct status_check {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt status_check_t type;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt bool negated;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt int value;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt status_check(const status_check_t& p_type, const bool p_negated,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const int p_value) :
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt type(p_type),
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt negated(p_negated),
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt value(p_value)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt};
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntenum output_check_t {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt oc_ignore,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt oc_inline,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt oc_file,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt oc_empty,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt oc_match,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt oc_save
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt};
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstruct output_check {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt output_check_t type;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt bool negated;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::string value;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt output_check(const output_check_t& p_type, const bool p_negated,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const std::string& p_value) :
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt type(p_type),
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt negated(p_negated),
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt value(p_value)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt};
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntclass temp_file : public std::ostream {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::auto_ptr< atf::fs::path > m_path;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt int m_fd;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntpublic:
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews temp_file(const char* pattern) :
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::ostream(NULL),
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt m_fd(-1)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt {
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews const atf::fs::path file = atf::fs::path(
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews atf::env::get("TMPDIR", "/tmp")) / pattern;
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews atf::auto_array< char > buf(new char[file.str().length() + 1]);
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews std::strcpy(buf.get(), file.c_str());
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt m_fd = ::mkstemp(buf.get());
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (m_fd == -1)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt throw atf::system_error("atf_check::temp_file::temp_file(" +
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews file.str() + ")", "mkstemp(3) failed",
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt errno);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt m_path.reset(new atf::fs::path(buf.get()));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ~temp_file(void)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt close();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt try {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt remove(*m_path);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } catch (const atf::system_error&) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt // Ignore deletion errors.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const atf::fs::path&
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt get_path(void) const
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return *m_path;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt void
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt write(const std::string& text)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (::write(m_fd, text.c_str(), text.size()) == -1)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt throw atf::system_error("atf_check", "write(2) failed", errno);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt void
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt close(void)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (m_fd != -1) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt flush();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ::close(m_fd);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt m_fd = -1;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt};
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt} // anonymous namespace
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic int
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntparse_exit_code(const std::string& str)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt try {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const int value = atf::text::to_type< int >(str);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (value < 0 || value > 255)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt throw std::runtime_error("Unused reason");
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return value;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } catch (const std::runtime_error&) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt throw atf::application::usage_error("Invalid exit code for -s option; "
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt "must be an integer in range 0-255");
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic struct name_number {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const char *name;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt int signo;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt} signal_names_to_numbers[] = {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt { "hup", SIGHUP },
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt { "int", SIGINT },
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt { "quit", SIGQUIT },
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt { "trap", SIGTRAP },
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt { "abrt", SIGABRT },
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt { "kill", SIGKILL },
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt { "segv", SIGSEGV },
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt { "pipe", SIGPIPE },
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt { "alrm", SIGALRM },
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt { "term", SIGTERM },
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt { "usr1", SIGUSR1 },
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt { "usr2", SIGUSR2 },
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt { NULL, INT_MIN },
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt};
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic int
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntsignal_name_to_number(const std::string& str)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt struct name_number* iter = signal_names_to_numbers;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt int signo = INT_MIN;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt while (signo == INT_MIN && iter->name != NULL) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (str == iter->name || str == std::string("sig") + iter->name)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt signo = iter->signo;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt iter++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return signo;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic int
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntparse_signal(const std::string& str)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const int signo = signal_name_to_number(str);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (signo == INT_MIN) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt try {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return atf::text::to_type< int >(str);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } catch (std::runtime_error) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt throw atf::application::usage_error("Invalid signal name or number "
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt "in -s option");
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt INV(signo != INT_MIN);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return signo;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic status_check
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntparse_status_check_arg(const std::string& arg)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const std::string::size_type delimiter = arg.find(':');
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt bool negated = (arg.compare(0, 4, "not-") == 0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const std::string action_str = arg.substr(0, delimiter);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const std::string action = negated ? action_str.substr(4) : action_str;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const std::string value_str = (
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt delimiter == std::string::npos ? "" : arg.substr(delimiter + 1));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt int value;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt status_check_t type;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (action == "eq") {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt // Deprecated; use exit instead. TODO: Remove after 0.10.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt type = sc_exit;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (negated)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt throw atf::application::usage_error("Cannot negate eq checker");
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt negated = false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt value = parse_exit_code(value_str);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (action == "exit") {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt type = sc_exit;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (value_str.empty())
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt value = INT_MIN;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt value = parse_exit_code(value_str);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (action == "ignore") {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (negated)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt throw atf::application::usage_error("Cannot negate ignore checker");
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt type = sc_ignore;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt value = INT_MIN;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (action == "ne") {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt // Deprecated; use not-exit instead. TODO: Remove after 0.10.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt type = sc_exit;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (negated)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt throw atf::application::usage_error("Cannot negate ne checker");
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt negated = true;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt value = parse_exit_code(value_str);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (action == "signal") {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt type = sc_signal;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (value_str.empty())
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt value = INT_MIN;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt value = parse_signal(value_str);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt throw atf::application::usage_error("Invalid status checker");
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return status_check(type, negated, value);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntoutput_check
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntparse_output_check_arg(const std::string& arg)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const std::string::size_type delimiter = arg.find(':');
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const bool negated = (arg.compare(0, 4, "not-") == 0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const std::string action_str = arg.substr(0, delimiter);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const std::string action = negated ? action_str.substr(4) : action_str;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt output_check_t type;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (action == "empty")
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt type = oc_empty;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else if (action == "file")
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt type = oc_file;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else if (action == "ignore") {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (negated)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt throw atf::application::usage_error("Cannot negate ignore checker");
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt type = oc_ignore;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (action == "inline")
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt type = oc_inline;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else if (action == "match")
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt type = oc_match;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else if (action == "save") {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (negated)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt throw atf::application::usage_error("Cannot negate save checker");
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt type = oc_save;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt throw atf::application::usage_error("Invalid output checker");
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return output_check(type, negated, arg.substr(delimiter + 1));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstd::string
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntflatten_argv(char* const* argv)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::string cmdline;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt char* const* arg = &argv[0];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt while (*arg != NULL) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (arg != &argv[0])
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt cmdline += ' ';
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt cmdline += *arg;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt arg++;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return cmdline;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstd::auto_ptr< atf::check::check_result >
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntexecute(const char* const* argv)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews // TODO: This should go to stderr... but fixing it now may be hard as test
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews // cases out there might be relying on stderr being silent.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cout << "Executing command [ ";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt for (int i = 0; argv[i] != NULL; ++i)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cout << argv[i] << " ";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cout << "]\n";
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews std::cout.flush();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf::process::argv_array argva(argv);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return atf::check::exec(argva);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstd::auto_ptr< atf::check::check_result >
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntexecute_with_shell(char* const* argv)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const std::string cmd = flatten_argv(argv);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const char* sh_argv[4];
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews sh_argv[0] = atf::env::get("ATF_SHELL", ATF_SHELL).c_str();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt sh_argv[1] = "-c";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt sh_argv[2] = cmd.c_str();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt sh_argv[3] = NULL;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return execute(sh_argv);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntvoid
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntcat_file(const atf::fs::path& path)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::ifstream stream(path.c_str());
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (!stream)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt throw std::runtime_error("Failed to open " + path.str());
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt stream >> std::noskipws;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::istream_iterator< char > begin(stream), end;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::ostream_iterator< char > out(std::cerr);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::copy(begin, end, out);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt stream.close();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntbool
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntgrep_file(const atf::fs::path& path, const std::string& regexp)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::ifstream stream(path.c_str());
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (!stream)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt throw std::runtime_error("Failed to open " + path.str());
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt bool found = false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::string line;
a747113422afaa29ce72d2c5ba7f0b7ea9ec2054Evan Hunt while (!found && !std::getline(stream, line).fail()) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (atf::text::match(line, regexp))
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt found = true;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt stream.close();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return found;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntbool
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntfile_empty(const atf::fs::path& p)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf::fs::file_info f(p);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return (f.get_size() == 0);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic bool
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntcompare_files(const atf::fs::path& p1, const atf::fs::path& p2)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt bool equal = false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::ifstream f1(p1.c_str());
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (!f1)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt throw std::runtime_error("Failed to open " + p1.str());
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::ifstream f2(p2.c_str());
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (!f2)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt throw std::runtime_error("Failed to open " + p1.str());
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt for (;;) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt char buf1[512], buf2[512];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt f1.read(buf1, sizeof(buf1));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (f1.bad())
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt throw std::runtime_error("Failed to read from " + p1.str());
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt f2.read(buf2, sizeof(buf2));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (f2.bad())
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt throw std::runtime_error("Failed to read from " + p1.str());
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if ((f1.gcount() == 0) && (f2.gcount() == 0)) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt equal = true;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if ((f1.gcount() != f2.gcount()) ||
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt (std::memcmp(buf1, buf2, f1.gcount()) != 0)) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return equal;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntvoid
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntprint_diff(const atf::fs::path& p1, const atf::fs::path& p2)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const atf::process::status s =
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf::process::exec(atf::fs::path("diff"),
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf::process::argv_array("diff", "-u", p1.c_str(),
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt p2.c_str(), NULL),
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf::process::stream_connect(STDOUT_FILENO,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt STDERR_FILENO),
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf::process::stream_inherit());
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (!s.exited())
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cerr << "Failed to run diff(3)\n";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (s.exitstatus() != 1)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cerr << "Error while running diff(3)\n";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstd::string
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntdecode(const std::string& s)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt size_t i;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::string res;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt res.reserve(s.length());
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt i = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt while (i < s.length()) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt char c = s[i++];
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (c == '\\') {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt switch (s[i++]) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt case 'a': c = '\a'; break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt case 'b': c = '\b'; break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt case 'c': break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt case 'e': c = 033; break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt case 'f': c = '\f'; break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt case 'n': c = '\n'; break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt case 'r': c = '\r'; break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt case 't': c = '\t'; break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt case 'v': c = '\v'; break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt case '\\': break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt case '0':
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt int count = 3;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt c = 0;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt while (--count >= 0 && (unsigned)(s[i] - '0') < 8)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt c = (c << 3) + (s[i++] - '0');
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt default:
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt --i;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt res.push_back(c);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return res;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntbool
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntrun_status_check(const status_check& sc, const atf::check::check_result& cr)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt bool result;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (sc.type == sc_exit) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (cr.exited() && sc.value != INT_MIN) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const int status = cr.exitcode();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (!sc.negated && sc.value != status) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cerr << "Fail: incorrect exit status: "
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt << status << ", expected: "
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt << sc.value << "\n";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (sc.negated && sc.value == status) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cerr << "Fail: incorrect exit status: "
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt << status << ", expected: "
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt << "anything else\n";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = true;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (cr.exited() && sc.value == INT_MIN) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = true;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cerr << "Fail: program did not exit cleanly\n";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (sc.type == sc_ignore) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = true;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (sc.type == sc_signal) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (cr.signaled() && sc.value != INT_MIN) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const int status = cr.termsig();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (!sc.negated && sc.value != status) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cerr << "Fail: incorrect signal received: "
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt << status << ", expected: " << sc.value << "\n";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (sc.negated && sc.value == status) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cerr << "Fail: incorrect signal received: "
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt << status << ", expected: "
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt << "anything else\n";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = true;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (cr.signaled() && sc.value == INT_MIN) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = true;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cerr << "Fail: program did not receive a signal\n";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt UNREACHABLE;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (result == false) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cerr << "stdout:\n";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt cat_file(atf::fs::path(cr.stdout_path()));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cerr << "\n";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cerr << "stderr:\n";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt cat_file(atf::fs::path(cr.stderr_path()));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cerr << "\n";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return result;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntbool
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntrun_status_checks(const std::vector< status_check >& checks,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const atf::check::check_result& result)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt bool ok = false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt for (std::vector< status_check >::const_iterator iter = checks.begin();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt !ok && iter != checks.end(); iter++) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ok |= run_status_check(*iter, result);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return ok;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntbool
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntrun_output_check(const output_check oc, const atf::fs::path& path,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const std::string& stdxxx)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt bool result;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (oc.type == oc_empty) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const bool is_empty = file_empty(path);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (!oc.negated && !is_empty) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cerr << "Fail: " << stdxxx << " not empty\n";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt print_diff(atf::fs::path("/dev/null"), path);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (oc.negated && is_empty) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cerr << "Fail: " << stdxxx << " is empty\n";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = true;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (oc.type == oc_file) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const bool equals = compare_files(path, atf::fs::path(oc.value));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (!oc.negated && !equals) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cerr << "Fail: " << stdxxx << " does not match golden "
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt "output\n";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt print_diff(atf::fs::path(oc.value), path);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (oc.negated && equals) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cerr << "Fail: " << stdxxx << " matches golden output\n";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt cat_file(atf::fs::path(oc.value));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = true;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (oc.type == oc_ignore) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = true;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (oc.type == oc_inline) {
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews temp_file temp("atf-check.XXXXXX");
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt temp.write(decode(oc.value));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt temp.close();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const bool equals = compare_files(path, temp.get_path());
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (!oc.negated && !equals) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cerr << "Fail: " << stdxxx << " does not match expected "
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt "value\n";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt print_diff(temp.get_path(), path);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (oc.negated && equals) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cerr << "Fail: " << stdxxx << " matches expected value\n";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt cat_file(temp.get_path());
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = true;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (oc.type == oc_match) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const bool matches = grep_file(path, oc.value);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (!oc.negated && !matches) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cerr << "Fail: regexp " + oc.value + " not in " << stdxxx
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt << "\n";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt cat_file(path);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (oc.negated && matches) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::cerr << "Fail: regexp " + oc.value + " is in " << stdxxx
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt << "\n";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt cat_file(path);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = true;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (oc.type == oc_save) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt INV(!oc.negated);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::ifstream ifs(path.c_str(), std::fstream::binary);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ifs >> std::noskipws;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::istream_iterator< char > begin(ifs), end;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::ofstream ofs(oc.value.c_str(), std::fstream::binary
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt | std::fstream::trunc);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::ostream_iterator <char> obegin(ofs);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::copy(begin, end, obegin);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = true;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt UNREACHABLE;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt result = false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return result;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstatic
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntbool
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntrun_output_checks(const std::vector< output_check >& checks,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const atf::fs::path& path, const std::string& stdxxx)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt bool ok = true;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt for (std::vector< output_check >::const_iterator iter = checks.begin();
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt iter != checks.end(); iter++) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt ok &= run_output_check(*iter, path, stdxxx);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return ok;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// ------------------------------------------------------------------------
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// The "atf_check" application.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt// ------------------------------------------------------------------------
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntnamespace {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntclass atf_check : public atf::application::app {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt bool m_xflag;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::vector< status_check > m_status_checks;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::vector< output_check > m_stdout_checks;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::vector< output_check > m_stderr_checks;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt static const char* m_description;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt bool run_output_checks(const atf::check::check_result&,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const std::string&) const;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::string specific_args(void) const;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt options_set specific_options(void) const;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt void process_option(int, const char*);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt void process_option_s(const std::string&);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntpublic:
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf_check(void);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt int main(void);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt};
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt} // anonymous namespace
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntconst char* atf_check::m_description =
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt "atf-check executes given command and analyzes its results.";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_check::atf_check(void) :
4a53e3c2b83c476a93148eaee0272649beb221caMark Andrews app(m_description, "atf-check(1)"),
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt m_xflag(false)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntbool
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_check::run_output_checks(const atf::check::check_result& r,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const std::string& stdxxx)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (stdxxx == "stdout") {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return ::run_output_checks(m_stdout_checks,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf::fs::path(r.stdout_path()), "stdout");
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else if (stdxxx == "stderr") {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return ::run_output_checks(m_stderr_checks,
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt atf::fs::path(r.stderr_path()), "stderr");
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt } else {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt UNREACHABLE;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return false;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntstd::string
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_check::specific_args(void)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return "<command>";
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_check::options_set
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_check::specific_options(void)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt const
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt using atf::application::option;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt options_set opts;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt opts.insert(option('s', "qual:value", "Handle status. Qualifier "
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt "must be one of: ignore exit:<num> signal:<name|num>"));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt opts.insert(option('o', "action:arg", "Handle stdout. Action must be "
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt "one of: empty ignore file:<path> inline:<val> match:regexp "
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt "save:<path>"));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt opts.insert(option('e', "action:arg", "Handle stderr. Action must be "
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt "one of: empty ignore file:<path> inline:<val> match:regexp "
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt "save:<path>"));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt opts.insert(option('x', "", "Execute command as a shell command"));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return opts;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntvoid
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_check::process_option(int ch, const char* arg)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt switch (ch) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt case 's':
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt m_status_checks.push_back(parse_status_check_arg(arg));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt case 'o':
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt m_stdout_checks.push_back(parse_output_check_arg(arg));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt case 'e':
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt m_stderr_checks.push_back(parse_output_check_arg(arg));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt case 'x':
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt m_xflag = true;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt break;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt default:
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt UNREACHABLE;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntint
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntatf_check::main(void)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (m_argc < 1)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt throw atf::application::usage_error("No command specified");
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt int status = EXIT_FAILURE;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt std::auto_ptr< atf::check::check_result > r =
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt m_xflag ? execute_with_shell(m_argv) : execute(m_argv);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (m_status_checks.empty())
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt m_status_checks.push_back(status_check(sc_exit, false, EXIT_SUCCESS));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else if (m_status_checks.size() > 1) {
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt // TODO: Remove this restriction.
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt throw atf::application::usage_error("Cannot specify -s more than once");
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt }
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (m_stdout_checks.empty())
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt m_stdout_checks.push_back(output_check(oc_empty, false, ""));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if (m_stderr_checks.empty())
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt m_stderr_checks.push_back(output_check(oc_empty, false, ""));
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt if ((run_status_checks(m_status_checks, *r) == false) ||
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt (run_output_checks(*r, "stderr") == false) ||
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt (run_output_checks(*r, "stdout") == false))
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt status = EXIT_FAILURE;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt else
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt status = EXIT_SUCCESS;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return status;
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntint
ef421f66f47224a42073deaf087378c5d0c9952eEvan Huntmain(int argc, char* const* argv)
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt{
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt return atf_check().run(argc, argv);
ef421f66f47224a42073deaf087378c5d0c9952eEvan Hunt}