freebsd-skq/tools/test_program_test.cpp
Julio Merino 8fee91db34 Import atf-0.19:
Experimental version released on February 7th, 2014.

This is the last release to bundle the code for the deprecated tools.
The next release will drop their code and will stop worrying about
backwards compatibility between the ATF libraries and what the old tools
may or may not support.

If you still require the old tools for some reason, grab a copy of the
'tools' directory now.  The code in this directory is standalone and
does not depend on any internal details of atf-c++ any longer.

* Various fixes and improvements to support running as part of the FreeBSD
  test suite.

* Project hosting moved from Google Code (as a subproject of Kyua) to
  GitHub (as a first-class project).  The main reason for the change is
  the suppression of binary downloads in Google Code on Jan 15th, 2014.
  See https://github.com/jmmv/atf/

* Removed builtin help from atf-sh(1) and atf-check(1) for simplicity
  reasons.  In other words, their -h option is gone.

* Moved the code of the deprecated tools into a 'tools' directory and
  completely decoupled their code from the internals of atf-c++.  The
  reason for this is to painlessly allow a third-party to maintain a
  copy of these tools after we delete them because upcoming changes to
  atf-c++ would break the stale tools.
2014-02-14 14:41:25 +00:00

1024 lines
29 KiB
C++

//
// Automated Testing Framework (atf)
//
// Copyright (c) 2010 The NetBSD Foundation, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#include <fstream>
#include <iostream>
#include <atf-c++.hpp>
#include "parser.hpp"
#include "test-program.hpp"
#include "test_helpers.hpp"
#include "text.hpp"
namespace impl = tools::test_program;
namespace detail = tools::test_program::detail;
// -------------------------------------------------------------------------
// Auxiliary functions.
// -------------------------------------------------------------------------
namespace {
typedef std::map< std::string, std::string > vars_map;
static
tools::fs::path
get_helper(const atf::tests::tc& tc, const char* name)
{
return tools::fs::path(tc.get_config_var("srcdir")) / name;
}
static
void
check_property(const vars_map& props, const char* name, const char* value)
{
const vars_map::const_iterator iter = props.find(name);
ATF_REQUIRE(iter != props.end());
ATF_REQUIRE_EQ(value, (*iter).second);
}
static void
check_result(const char* exp_state, const int exp_value, const char* exp_reason,
const impl::test_case_result& tcr)
{
ATF_REQUIRE_EQ(exp_state, tcr.state());
ATF_REQUIRE_EQ(exp_value, tcr.value());
ATF_REQUIRE_EQ(exp_reason, tcr.reason());
}
static
void
write_test_case_result(const char *results_path, const std::string& contents)
{
std::ofstream results_file(results_path);
ATF_REQUIRE(results_file);
results_file << contents;
}
static
void
print_indented(const std::string& str)
{
std::vector< std::string > ws = tools::text::split(str, "\n");
for (std::vector< std::string >::const_iterator iter = ws.begin();
iter != ws.end(); iter++)
std::cout << ">>" << *iter << "<<\n";
}
// XXX Should this string handling and verbosity level be part of the
// ATF_REQUIRE_EQ macro? It may be hard to predict sometimes that a
// string can have newlines in it, and so the error message generated
// at the moment will be bogus if there are some.
static
void
check_match(const atf::tests::tc& tc, const std::string& str,
const std::string& exp)
{
if (!tools::text::match(str, exp)) {
std::cout << "String match check failed.\n"
<< "Adding >> and << to delimit the string boundaries "
"below.\n";
std::cout << "GOT:\n";
print_indented(str);
std::cout << "EXPECTED:\n";
print_indented(exp);
tc.fail("Constructed string differs from the expected one");
}
}
} // anonymous namespace
// -------------------------------------------------------------------------
// Tests for the "tp" reader.
// -------------------------------------------------------------------------
class tp_reader : protected detail::atf_tp_reader {
void
got_tc(const std::string& ident,
const std::map< std::string, std::string >& md)
{
std::string call = "got_tc(" + ident + ", {";
for (std::map< std::string, std::string >::const_iterator iter =
md.begin(); iter != md.end(); iter++) {
if (iter != md.begin())
call += ", ";
call += (*iter).first + '=' + (*iter).second;
}
call += "})";
m_calls.push_back(call);
}
void
got_eof(void)
{
m_calls.push_back("got_eof()");
}
public:
tp_reader(std::istream& is) :
detail::atf_tp_reader(is)
{
}
void
read(void)
{
atf_tp_reader::read();
}
std::vector< std::string > m_calls;
};
ATF_TEST_CASE_WITHOUT_HEAD(tp_1);
ATF_TEST_CASE_BODY(tp_1)
{
const char* input =
"Content-Type: application/X-atf-tp; version=\"1\"\n"
"\n"
"ident: test_case_1\n"
"\n"
"ident: test_case_2\n"
"\n"
"ident: test_case_3\n"
;
const char* exp_calls[] = {
"got_tc(test_case_1, {ident=test_case_1})",
"got_tc(test_case_2, {ident=test_case_2})",
"got_tc(test_case_3, {ident=test_case_3})",
"got_eof()",
NULL
};
const char* exp_errors[] = {
NULL
};
do_parser_test< tp_reader >(input, exp_calls, exp_errors);
}
ATF_TEST_CASE_WITHOUT_HEAD(tp_2);
ATF_TEST_CASE_BODY(tp_2)
{
const char* input =
"Content-Type: application/X-atf-tp; version=\"1\"\n"
"\n"
"ident: test_case_1\n"
"descr: This is the description\n"
"timeout: 300\n"
"\n"
"ident: test_case_2\n"
"\n"
"ident: test_case_3\n"
"X-prop1: A custom property\n"
"descr: Third test case\n"
;
// NO_CHECK_STYLE_BEGIN
const char* exp_calls[] = {
"got_tc(test_case_1, {descr=This is the description, ident=test_case_1, timeout=300})",
"got_tc(test_case_2, {ident=test_case_2})",
"got_tc(test_case_3, {X-prop1=A custom property, descr=Third test case, ident=test_case_3})",
"got_eof()",
NULL
};
// NO_CHECK_STYLE_END
const char* exp_errors[] = {
NULL
};
do_parser_test< tp_reader >(input, exp_calls, exp_errors);
}
ATF_TEST_CASE_WITHOUT_HEAD(tp_3);
ATF_TEST_CASE_BODY(tp_3)
{
const char* input =
"Content-Type: application/X-atf-tp; version=\"1\"\n"
"\n"
"ident: single_test\n"
"descr: Some description\n"
"timeout: 300\n"
"require.arch: thearch\n"
"require.config: foo-bar\n"
"require.files: /a/1 /b/2\n"
"require.machine: themachine\n"
"require.progs: /bin/cp mv\n"
"require.user: root\n"
;
// NO_CHECK_STYLE_BEGIN
const char* exp_calls[] = {
"got_tc(single_test, {descr=Some description, ident=single_test, require.arch=thearch, require.config=foo-bar, require.files=/a/1 /b/2, require.machine=themachine, require.progs=/bin/cp mv, require.user=root, timeout=300})",
"got_eof()",
NULL
};
// NO_CHECK_STYLE_END
const char* exp_errors[] = {
NULL
};
do_parser_test< tp_reader >(input, exp_calls, exp_errors);
}
ATF_TEST_CASE_WITHOUT_HEAD(tp_4);
ATF_TEST_CASE_BODY(tp_4)
{
const char* input =
"Content-Type: application/X-atf-tp; version=\"1\"\n"
"\n"
"ident: single_test \n"
"descr: Some description \n"
;
const char* exp_calls[] = {
"got_tc(single_test, {descr=Some description, ident=single_test})",
"got_eof()",
NULL
};
const char* exp_errors[] = {
NULL
};
do_parser_test< tp_reader >(input, exp_calls, exp_errors);
}
ATF_TEST_CASE_WITHOUT_HEAD(tp_50);
ATF_TEST_CASE_BODY(tp_50)
{
const char* input =
"Content-Type: application/X-atf-tp; version=\"1\"\n"
"\n"
;
const char* exp_calls[] = {
NULL
};
const char* exp_errors[] = {
"3: Unexpected token `<<EOF>>'; expected property name",
NULL
};
do_parser_test< tp_reader >(input, exp_calls, exp_errors);
}
ATF_TEST_CASE_WITHOUT_HEAD(tp_51);
ATF_TEST_CASE_BODY(tp_51)
{
const char* input =
"Content-Type: application/X-atf-tp; version=\"1\"\n"
"\n"
"\n"
"\n"
"\n"
;
const char* exp_calls[] = {
NULL
};
const char* exp_errors[] = {
"3: Unexpected token `<<NEWLINE>>'; expected property name",
NULL
};
do_parser_test< tp_reader >(input, exp_calls, exp_errors);
}
ATF_TEST_CASE_WITHOUT_HEAD(tp_52);
ATF_TEST_CASE_BODY(tp_52)
{
const char* input =
"Content-Type: application/X-atf-tp; version=\"1\"\n"
"\n"
"ident: test1\n"
"ident: test2\n"
;
const char* exp_calls[] = {
"got_tc(test1, {ident=test1})",
"got_eof()",
NULL
};
const char* exp_errors[] = {
NULL
};
do_parser_test< tp_reader >(input, exp_calls, exp_errors);
}
ATF_TEST_CASE_WITHOUT_HEAD(tp_53);
ATF_TEST_CASE_BODY(tp_53)
{
const char* input =
"Content-Type: application/X-atf-tp; version=\"1\"\n"
"\n"
"descr: Out of order\n"
"ident: test1\n"
;
const char* exp_calls[] = {
NULL
};
const char* exp_errors[] = {
"3: First property of a test case must be 'ident'",
NULL
};
do_parser_test< tp_reader >(input, exp_calls, exp_errors);
}
ATF_TEST_CASE_WITHOUT_HEAD(tp_54);
ATF_TEST_CASE_BODY(tp_54)
{
const char* input =
"Content-Type: application/X-atf-tp; version=\"1\"\n"
"\n"
"ident:\n"
;
const char* exp_calls[] = {
NULL
};
const char* exp_errors[] = {
"3: The value for 'ident' cannot be empty",
NULL
};
do_parser_test< tp_reader >(input, exp_calls, exp_errors);
}
ATF_TEST_CASE_WITHOUT_HEAD(tp_55);
ATF_TEST_CASE_BODY(tp_55)
{
const char* input =
"Content-Type: application/X-atf-tp; version=\"1\"\n"
"\n"
"ident: +*,\n"
;
const char* exp_calls[] = {
NULL
};
const char* exp_errors[] = {
"3: The identifier must match ^[_A-Za-z0-9]+$; was '+*,'",
NULL
};
do_parser_test< tp_reader >(input, exp_calls, exp_errors);
}
ATF_TEST_CASE_WITHOUT_HEAD(tp_56);
ATF_TEST_CASE_BODY(tp_56)
{
const char* input =
"Content-Type: application/X-atf-tp; version=\"1\"\n"
"\n"
"ident: test\n"
"timeout: hello\n"
;
const char* exp_calls[] = {
NULL
};
const char* exp_errors[] = {
"4: The timeout property requires an integer value",
NULL
};
do_parser_test< tp_reader >(input, exp_calls, exp_errors);
}
ATF_TEST_CASE_WITHOUT_HEAD(tp_57);
ATF_TEST_CASE_BODY(tp_57)
{
const char* input =
"Content-Type: application/X-atf-tp; version=\"1\"\n"
"\n"
"ident: test\n"
"unknown: property\n"
;
const char* exp_calls[] = {
NULL
};
const char* exp_errors[] = {
"4: Unknown property 'unknown'",
NULL
};
do_parser_test< tp_reader >(input, exp_calls, exp_errors);
}
ATF_TEST_CASE_WITHOUT_HEAD(tp_58);
ATF_TEST_CASE_BODY(tp_58)
{
const char* input =
"Content-Type: application/X-atf-tp; version=\"1\"\n"
"\n"
"ident: test\n"
"X-foo:\n"
;
const char* exp_calls[] = {
NULL
};
const char* exp_errors[] = {
"4: The value for 'X-foo' cannot be empty",
NULL
};
do_parser_test< tp_reader >(input, exp_calls, exp_errors);
}
ATF_TEST_CASE_WITHOUT_HEAD(tp_59);
ATF_TEST_CASE_BODY(tp_59)
{
const char* input =
"Content-Type: application/X-atf-tp; version=\"1\"\n"
"\n"
"\n"
"ident: test\n"
"timeout: 300\n"
;
const char* exp_calls[] = {
NULL
};
const char* exp_errors[] = {
"3: Unexpected token `<<NEWLINE>>'; expected property name",
NULL
};
do_parser_test< tp_reader >(input, exp_calls, exp_errors);
}
ATF_TEST_CASE_WITHOUT_HEAD(tp_60);
ATF_TEST_CASE_BODY(tp_60)
{
const char* input =
"Content-Type: application/X-atf-tp; version=\"1\"\n"
"\n"
"ident: test\n"
"require.memory: 12345D\n"
;
const char* exp_calls[] = {
NULL
};
const char* exp_errors[] = {
"4: The require.memory property requires an integer value representing"
" an amount of bytes",
NULL
};
do_parser_test< tp_reader >(input, exp_calls, exp_errors);
}
// -------------------------------------------------------------------------
// Tests for the "tps" writer.
// -------------------------------------------------------------------------
ATF_TEST_CASE(atf_tps_writer);
ATF_TEST_CASE_HEAD(atf_tps_writer)
{
set_md_var("descr", "Verifies the application/X-atf-tps writer");
}
ATF_TEST_CASE_BODY(atf_tps_writer)
{
std::ostringstream expss;
std::ostringstream ss;
const char *ts_regex = "[0-9]+\\.[0-9]{1,6}, ";
#define RESET \
expss.str(""); \
ss.str("")
#define CHECK \
check_match(*this, ss.str(), expss.str())
{
RESET;
impl::atf_tps_writer w(ss);
expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n";
CHECK;
}
{
RESET;
impl::atf_tps_writer w(ss);
expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n";
CHECK;
w.info("foo", "bar");
expss << "info: foo, bar\n";
CHECK;
w.info("baz", "second info");
expss << "info: baz, second info\n";
CHECK;
}
{
RESET;
impl::atf_tps_writer w(ss);
expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n";
CHECK;
w.ntps(0);
expss << "tps-count: 0\n";
CHECK;
}
{
RESET;
impl::atf_tps_writer w(ss);
expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n";
CHECK;
w.ntps(123);
expss << "tps-count: 123\n";
CHECK;
}
{
RESET;
impl::atf_tps_writer w(ss);
expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n";
CHECK;
w.ntps(2);
expss << "tps-count: 2\n";
CHECK;
w.start_tp("foo", 0);
expss << "tp-start: " << ts_regex << "foo, 0\n";
CHECK;
w.end_tp("");
expss << "tp-end: " << ts_regex << "foo\n";
CHECK;
w.start_tp("bar", 0);
expss << "tp-start: " << ts_regex << "bar, 0\n";
CHECK;
w.end_tp("failed program");
expss << "tp-end: " << ts_regex << "bar, failed program\n";
CHECK;
}
{
RESET;
impl::atf_tps_writer w(ss);
expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n";
CHECK;
w.ntps(1);
expss << "tps-count: 1\n";
CHECK;
w.start_tp("foo", 1);
expss << "tp-start: " << ts_regex << "foo, 1\n";
CHECK;
w.start_tc("brokentc");
expss << "tc-start: " << ts_regex << "brokentc\n";
CHECK;
w.end_tp("aborted");
expss << "tp-end: " << ts_regex << "foo, aborted\n";
CHECK;
}
{
RESET;
impl::atf_tps_writer w(ss);
expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n";
CHECK;
w.ntps(1);
expss << "tps-count: 1\n";
CHECK;
w.start_tp("thetp", 3);
expss << "tp-start: " << ts_regex << "thetp, 3\n";
CHECK;
w.start_tc("passtc");
expss << "tc-start: " << ts_regex << "passtc\n";
CHECK;
w.end_tc("passed", "");
expss << "tc-end: " << ts_regex << "passtc, passed\n";
CHECK;
w.start_tc("failtc");
expss << "tc-start: " << ts_regex << "failtc\n";
CHECK;
w.end_tc("failed", "The reason");
expss << "tc-end: " << ts_regex << "failtc, failed, The reason\n";
CHECK;
w.start_tc("skiptc");
expss << "tc-start: " << ts_regex << "skiptc\n";
CHECK;
w.end_tc("skipped", "The reason");
expss << "tc-end: " << ts_regex << "skiptc, skipped, The reason\n";
CHECK;
w.end_tp("");
expss << "tp-end: " << ts_regex << "thetp\n";
CHECK;
}
{
RESET;
impl::atf_tps_writer w(ss);
expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n";
CHECK;
w.ntps(1);
expss << "tps-count: 1\n";
CHECK;
w.start_tp("thetp", 1);
expss << "tp-start: " << ts_regex << "thetp, 1\n";
CHECK;
w.start_tc("thetc");
expss << "tc-start: " << ts_regex << "thetc\n";
CHECK;
w.stdout_tc("a line");
expss << "tc-so:a line\n";
CHECK;
w.stdout_tc("another line");
expss << "tc-so:another line\n";
CHECK;
w.stderr_tc("an error message");
expss << "tc-se:an error message\n";
CHECK;
w.end_tc("passed", "");
expss << "tc-end: " << ts_regex << "thetc, passed\n";
CHECK;
w.end_tp("");
expss << "tp-end: " << ts_regex << "thetp\n";
CHECK;
}
{
RESET;
impl::atf_tps_writer w(ss);
expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n";
CHECK;
w.ntps(1);
expss << "tps-count: 1\n";
CHECK;
w.start_tp("thetp", 0);
expss << "tp-start: " << ts_regex << "thetp, 0\n";
CHECK;
w.end_tp("");
expss << "tp-end: " << ts_regex << "thetp\n";
CHECK;
w.info("foo", "bar");
expss << "info: foo, bar\n";
CHECK;
w.info("baz", "second value");
expss << "info: baz, second value\n";
CHECK;
}
#undef CHECK
#undef RESET
}
// -------------------------------------------------------------------------
// Tests for the free functions.
// -------------------------------------------------------------------------
ATF_TEST_CASE(get_metadata_bad);
ATF_TEST_CASE_HEAD(get_metadata_bad) {}
ATF_TEST_CASE_BODY(get_metadata_bad) {
const tools::fs::path executable = get_helper(*this, "bad_metadata_helper");
ATF_REQUIRE_THROW(tools::parser::parse_errors,
impl::get_metadata(executable, vars_map()));
}
ATF_TEST_CASE(get_metadata_zero_tcs);
ATF_TEST_CASE_HEAD(get_metadata_zero_tcs) {}
ATF_TEST_CASE_BODY(get_metadata_zero_tcs) {
const tools::fs::path executable = get_helper(*this, "zero_tcs_helper");
ATF_REQUIRE_THROW(tools::parser::parse_errors,
impl::get_metadata(executable, vars_map()));
}
ATF_TEST_CASE(get_metadata_several_tcs);
ATF_TEST_CASE_HEAD(get_metadata_several_tcs) {}
ATF_TEST_CASE_BODY(get_metadata_several_tcs) {
const tools::fs::path executable = get_helper(*this, "several_tcs_helper");
const impl::metadata md = impl::get_metadata(executable, vars_map());
ATF_REQUIRE_EQ(3, md.test_cases.size());
{
const impl::test_cases_map::const_iterator iter =
md.test_cases.find("first");
ATF_REQUIRE(iter != md.test_cases.end());
ATF_REQUIRE_EQ(4, (*iter).second.size());
check_property((*iter).second, "descr", "Description 1");
check_property((*iter).second, "has.cleanup", "false");
check_property((*iter).second, "ident", "first");
check_property((*iter).second, "timeout", "300");
}
{
const impl::test_cases_map::const_iterator iter =
md.test_cases.find("second");
ATF_REQUIRE(iter != md.test_cases.end());
ATF_REQUIRE_EQ(5, (*iter).second.size());
check_property((*iter).second, "descr", "Description 2");
check_property((*iter).second, "has.cleanup", "true");
check_property((*iter).second, "ident", "second");
check_property((*iter).second, "timeout", "500");
check_property((*iter).second, "X-property", "Custom property");
}
{
const impl::test_cases_map::const_iterator iter =
md.test_cases.find("third");
ATF_REQUIRE(iter != md.test_cases.end());
ATF_REQUIRE_EQ(3, (*iter).second.size());
check_property((*iter).second, "has.cleanup", "false");
check_property((*iter).second, "ident", "third");
check_property((*iter).second, "timeout", "300");
}
}
ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_expected_death);
ATF_TEST_CASE_BODY(parse_test_case_result_expected_death) {
check_result("expected_death", -1, "foo bar",
detail::parse_test_case_result("expected_death: foo bar"));
ATF_REQUIRE_THROW(std::runtime_error,
detail::parse_test_case_result("expected_death"));
ATF_REQUIRE_THROW(std::runtime_error,
detail::parse_test_case_result("expected_death(3): foo"));
}
ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_expected_exit);
ATF_TEST_CASE_BODY(parse_test_case_result_expected_exit) {
check_result("expected_exit", -1, "foo bar",
detail::parse_test_case_result("expected_exit: foo bar"));
check_result("expected_exit", -1, "foo bar",
detail::parse_test_case_result("expected_exit(): foo bar"));
check_result("expected_exit", 5, "foo bar",
detail::parse_test_case_result("expected_exit(5): foo bar"));
ATF_REQUIRE_THROW(std::runtime_error,
detail::parse_test_case_result("expected_exit"));
ATF_REQUIRE_THROW(std::runtime_error,
detail::parse_test_case_result("expected_exit("));
}
ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_expected_failure);
ATF_TEST_CASE_BODY(parse_test_case_result_expected_failure) {
check_result("expected_failure", -1, "foo bar",
detail::parse_test_case_result("expected_failure: foo bar"));
ATF_REQUIRE_THROW(std::runtime_error,
detail::parse_test_case_result("expected_failure"));
ATF_REQUIRE_THROW(std::runtime_error,
detail::parse_test_case_result("expected_failure(3): foo"));
}
ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_expected_signal);
ATF_TEST_CASE_BODY(parse_test_case_result_expected_signal) {
check_result("expected_signal", -1, "foo bar",
detail::parse_test_case_result("expected_signal: foo bar"));
check_result("expected_signal", -1, "foo bar",
detail::parse_test_case_result("expected_signal(): foo bar"));
check_result("expected_signal", 5, "foo bar",
detail::parse_test_case_result("expected_signal(5): foo bar"));
ATF_REQUIRE_THROW(std::runtime_error,
detail::parse_test_case_result("expected_signal"));
ATF_REQUIRE_THROW(std::runtime_error,
detail::parse_test_case_result("expected_signal("));
}
ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_expected_timeout);
ATF_TEST_CASE_BODY(parse_test_case_result_expected_timeout) {
check_result("expected_timeout", -1, "foo bar",
detail::parse_test_case_result("expected_timeout: foo bar"));
ATF_REQUIRE_THROW(std::runtime_error,
detail::parse_test_case_result("expected_timeout"));
ATF_REQUIRE_THROW(std::runtime_error,
detail::parse_test_case_result("expected_timeout(3): foo"));
}
ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_failed);
ATF_TEST_CASE_BODY(parse_test_case_result_failed) {
check_result("failed", -1, "foo bar",
detail::parse_test_case_result("failed: foo bar"));
ATF_REQUIRE_THROW(std::runtime_error,
detail::parse_test_case_result("failed"));
ATF_REQUIRE_THROW(std::runtime_error,
detail::parse_test_case_result("failed(3): foo"));
}
ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_passed);
ATF_TEST_CASE_BODY(parse_test_case_result_passed) {
check_result("passed", -1, "",
detail::parse_test_case_result("passed"));
ATF_REQUIRE_THROW(std::runtime_error,
detail::parse_test_case_result("passed: foo"));
ATF_REQUIRE_THROW(std::runtime_error,
detail::parse_test_case_result("passed(3): foo"));
}
ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_skipped);
ATF_TEST_CASE_BODY(parse_test_case_result_skipped) {
check_result("skipped", -1, "foo bar",
detail::parse_test_case_result("skipped: foo bar"));
ATF_REQUIRE_THROW(std::runtime_error,
detail::parse_test_case_result("skipped"));
ATF_REQUIRE_THROW(std::runtime_error,
detail::parse_test_case_result("skipped(3): foo"));
}
ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_unknown);
ATF_TEST_CASE_BODY(parse_test_case_result_unknown) {
ATF_REQUIRE_THROW(std::runtime_error,
detail::parse_test_case_result("foo"));
ATF_REQUIRE_THROW(std::runtime_error,
detail::parse_test_case_result("bar: foo"));
ATF_REQUIRE_THROW(std::runtime_error,
detail::parse_test_case_result("baz: foo"));
}
ATF_TEST_CASE_WITHOUT_HEAD(read_test_case_result_failed);
ATF_TEST_CASE_BODY(read_test_case_result_failed) {
write_test_case_result("resfile", "failed: foo bar\n");
const impl::test_case_result tcr = impl::read_test_case_result(
tools::fs::path("resfile"));
ATF_REQUIRE_EQ("failed", tcr.state());
ATF_REQUIRE_EQ("foo bar", tcr.reason());
}
ATF_TEST_CASE_WITHOUT_HEAD(read_test_case_result_skipped);
ATF_TEST_CASE_BODY(read_test_case_result_skipped) {
write_test_case_result("resfile", "skipped: baz bar\n");
const impl::test_case_result tcr = impl::read_test_case_result(
tools::fs::path("resfile"));
ATF_REQUIRE_EQ("skipped", tcr.state());
ATF_REQUIRE_EQ("baz bar", tcr.reason());
}
ATF_TEST_CASE(read_test_case_result_no_file);
ATF_TEST_CASE_HEAD(read_test_case_result_no_file) {}
ATF_TEST_CASE_BODY(read_test_case_result_no_file) {
ATF_REQUIRE_THROW(std::runtime_error,
impl::read_test_case_result(tools::fs::path("resfile")));
}
ATF_TEST_CASE_WITHOUT_HEAD(read_test_case_result_empty_file);
ATF_TEST_CASE_BODY(read_test_case_result_empty_file) {
write_test_case_result("resfile", "");
ATF_REQUIRE_THROW(std::runtime_error,
impl::read_test_case_result(tools::fs::path("resfile")));
}
ATF_TEST_CASE_WITHOUT_HEAD(read_test_case_result_invalid);
ATF_TEST_CASE_BODY(read_test_case_result_invalid) {
write_test_case_result("resfile", "passed: hello\n");
ATF_REQUIRE_THROW(std::runtime_error,
impl::read_test_case_result(tools::fs::path("resfile")));
}
ATF_TEST_CASE_WITHOUT_HEAD(read_test_case_result_multiline);
ATF_TEST_CASE_BODY(read_test_case_result_multiline) {
write_test_case_result("resfile", "skipped: foo\nbar\n");
const impl::test_case_result tcr = impl::read_test_case_result(
tools::fs::path("resfile"));
ATF_REQUIRE_EQ("skipped", tcr.state());
ATF_REQUIRE_EQ("foo<<NEWLINE UNEXPECTED>>bar", tcr.reason());
}
// -------------------------------------------------------------------------
// Main.
// -------------------------------------------------------------------------
ATF_INIT_TEST_CASES(tcs)
{
ATF_ADD_TEST_CASE(tcs, tp_1);
ATF_ADD_TEST_CASE(tcs, tp_2);
ATF_ADD_TEST_CASE(tcs, tp_3);
ATF_ADD_TEST_CASE(tcs, tp_4);
ATF_ADD_TEST_CASE(tcs, tp_50);
ATF_ADD_TEST_CASE(tcs, tp_51);
ATF_ADD_TEST_CASE(tcs, tp_52);
ATF_ADD_TEST_CASE(tcs, tp_53);
ATF_ADD_TEST_CASE(tcs, tp_54);
ATF_ADD_TEST_CASE(tcs, tp_55);
ATF_ADD_TEST_CASE(tcs, tp_56);
ATF_ADD_TEST_CASE(tcs, tp_57);
ATF_ADD_TEST_CASE(tcs, tp_58);
ATF_ADD_TEST_CASE(tcs, tp_59);
ATF_ADD_TEST_CASE(tcs, tp_60);
ATF_ADD_TEST_CASE(tcs, atf_tps_writer);
ATF_ADD_TEST_CASE(tcs, get_metadata_bad);
ATF_ADD_TEST_CASE(tcs, get_metadata_zero_tcs);
ATF_ADD_TEST_CASE(tcs, get_metadata_several_tcs);
ATF_ADD_TEST_CASE(tcs, parse_test_case_result_expected_death);
ATF_ADD_TEST_CASE(tcs, parse_test_case_result_expected_exit);
ATF_ADD_TEST_CASE(tcs, parse_test_case_result_expected_failure);
ATF_ADD_TEST_CASE(tcs, parse_test_case_result_expected_signal);
ATF_ADD_TEST_CASE(tcs, parse_test_case_result_expected_timeout);
ATF_ADD_TEST_CASE(tcs, parse_test_case_result_failed);
ATF_ADD_TEST_CASE(tcs, parse_test_case_result_passed);
ATF_ADD_TEST_CASE(tcs, parse_test_case_result_skipped);
ATF_ADD_TEST_CASE(tcs, parse_test_case_result_unknown);
ATF_ADD_TEST_CASE(tcs, read_test_case_result_failed);
ATF_ADD_TEST_CASE(tcs, read_test_case_result_skipped);
ATF_ADD_TEST_CASE(tcs, read_test_case_result_no_file);
ATF_ADD_TEST_CASE(tcs, read_test_case_result_empty_file);
ATF_ADD_TEST_CASE(tcs, read_test_case_result_multiline);
ATF_ADD_TEST_CASE(tcs, read_test_case_result_invalid);
// TODO: Add tests for run_test_case once all the missing functionality
// is implemented.
}