diff options
author | jmmv <jmmv@FreeBSD.org> | 2014-02-14 14:44:03 +0000 |
---|---|---|
committer | jmmv <jmmv@FreeBSD.org> | 2014-02-14 14:44:03 +0000 |
commit | 14f39fed9fe557bdd640e02d9abbe2e695400d9e (patch) | |
tree | 907c960968fce28b8ca3cb9367140ed92c404150 /tools | |
parent | a817576754c6af0869b83f2f3efc4659963962a1 (diff) | |
download | FreeBSD-src-14f39fed9fe557bdd640e02d9abbe2e695400d9e.zip FreeBSD-src-14f39fed9fe557bdd640e02d9abbe2e695400d9e.tar.gz |
Import atf-0.20:
Experimental version released on February 7th, 2014.
This is the first release without the code for the deprecated tools. If
you require such code, please fetch a copy of the 0.19 release and extract
the 'tools' directory for your own consumption.
* Removed the deprecated tools. This includes atf-config, atf-report,
atf-run and atf-version.
Diffstat (limited to 'tools')
90 files changed, 0 insertions, 24140 deletions
diff --git a/tools/Atffile b/tools/Atffile deleted file mode 100644 index 8896078..0000000 --- a/tools/Atffile +++ /dev/null @@ -1,25 +0,0 @@ -Content-Type: application/X-atf-atffile; version="1" - -prop: test-suite = atf - -tp: atf-config_test -tp: atf-report_test -tp: atf-run_test -tp: application_test -tp: atffile_test -tp: auto_array_test -tp: config_test -tp: config_file_test -tp: env_test -tp: expand_test -tp: fs_test -tp: io_test -tp: parser_test -tp: process_test -tp: reader_test -tp: requirements_test -tp: signals_test -tp: test_program_test -tp: text_test -tp: ui_test -tp: user_test diff --git a/tools/Kyuafile b/tools/Kyuafile deleted file mode 100644 index 09c5145..0000000 --- a/tools/Kyuafile +++ /dev/null @@ -1,24 +0,0 @@ -syntax("kyuafile", 1) - -test_suite("atf") - -atf_test_program{name="atf-config_test"} -atf_test_program{name="atf-report_test"} -atf_test_program{name="atf-run_test"} -atf_test_program{name="application_test"} -atf_test_program{name="atffile_test"} -atf_test_program{name="auto_array_test"} -atf_test_program{name="config_test"} -atf_test_program{name="config_file_test"} -atf_test_program{name="env_test"} -atf_test_program{name="expand_test"} -atf_test_program{name="fs_test"} -atf_test_program{name="io_test"} -atf_test_program{name="parser_test"} -atf_test_program{name="process_test"} -atf_test_program{name="reader_test"} -atf_test_program{name="requirements_test"} -atf_test_program{name="signals_test"} -atf_test_program{name="test_program_test"} -atf_test_program{name="text_test"} -atf_test_program{name="ui_test"} diff --git a/tools/Makefile.am.inc b/tools/Makefile.am.inc deleted file mode 100644 index 26668ba..0000000 --- a/tools/Makefile.am.inc +++ /dev/null @@ -1,332 +0,0 @@ -# -# Automated Testing Framework (atf) -# -# Copyright (c) 2007 The NetBSD Foundation, Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 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. -# - -TOOLS_CPPFLAGS = -I$(top_srcdir)/tools -I$(top_builddir)/tools -TOOLS_LDADD = tools/libtools.a - -noinst_LIBRARIES = tools/libtools.a -tools_libtools_a_SOURCES = tools/application.cpp \ - tools/application.hpp \ - tools/atffile.cpp \ - tools/atffile.hpp \ - tools/auto_array.hpp \ - tools/config.cpp \ - tools/config.hpp \ - tools/config_file.cpp \ - tools/config_file.hpp \ - tools/env.cpp \ - tools/env.hpp \ - tools/exceptions.cpp \ - tools/exceptions.hpp \ - tools/expand.cpp \ - tools/expand.hpp \ - tools/fs.cpp \ - tools/fs.hpp \ - tools/io.cpp \ - tools/io.hpp \ - tools/parser.cpp \ - tools/parser.hpp \ - tools/process.cpp \ - tools/process.hpp \ - tools/reader.cpp \ - tools/reader.hpp \ - tools/requirements.cpp \ - tools/requirements.hpp \ - tools/signals.cpp \ - tools/signals.hpp \ - tools/test-program.cpp \ - tools/test-program.hpp \ - tools/test_helpers.hpp \ - tools/text.cpp \ - tools/text.hpp \ - tools/timers.cpp \ - tools/timers.hpp \ - tools/ui.cpp \ - tools/ui.hpp \ - tools/user.cpp \ - tools/user.hpp -nodist_tools_libtools_a_SOURCES = tools/defs.hpp -tools_libtools_a_CPPFLAGS = "-DATF_ARCH=\"$(atf_arch)\"" \ - "-DATF_BUILD_CC=\"$(ATF_BUILD_CC)\"" \ - "-DATF_BUILD_CFLAGS=\"$(ATF_BUILD_CFLAGS)\"" \ - "-DATF_BUILD_CPP=\"$(ATF_BUILD_CPP)\"" \ - "-DATF_BUILD_CPPFLAGS=\"$(ATF_BUILD_CPPFLAGS)\"" \ - "-DATF_BUILD_CXX=\"$(ATF_BUILD_CXX)\"" \ - "-DATF_BUILD_CXXFLAGS=\"$(ATF_BUILD_CXXFLAGS)\"" \ - "-DATF_CONFDIR=\"$(atf_confdir)\"" \ - "-DATF_INCLUDEDIR=\"$(includedir)\"" \ - "-DATF_LIBDIR=\"$(libdir)\"" \ - "-DATF_LIBEXECDIR=\"$(libexecdir)\"" \ - "-DATF_MACHINE=\"$(atf_machine)\"" \ - "-DATF_PKGDATADIR=\"$(pkgdatadir)\"" \ - "-DATF_SHELL=\"$(ATF_SHELL)\"" \ - "-DATF_WORKDIR=\"$(ATF_WORKDIR)\"" \ - $(TOOLS_CPPFLAGS) - -# XXX For some reason, the nodist line above does not work as expected. -# Work this problem around. -DIST_HOOKS += kill-defs-hpp -kill-defs-hpp: - rm -f $(distdir)/tools/defs.hpp - - - -bin_PROGRAMS += tools/atf-config -tools_atf_config_SOURCES = tools/atf-config.cpp -tools_atf_config_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_atf_config_LDADD = $(TOOLS_LDADD) -dist_man_MANS += tools/atf-config.1 - -bin_PROGRAMS += tools/atf-report -tools_atf_report_SOURCES = tools/atf-report.cpp -tools_atf_report_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_atf_report_LDADD = $(TOOLS_LDADD) -dist_man_MANS += tools/atf-report.1 - -bin_PROGRAMS += tools/atf-run -tools_atf_run_CPPFLAGS = $(TOOLS_CPPFLAGS) "-DGDB=\"$(GDB)\"" -tools_atf_run_SOURCES = tools/atf-run.cpp -tools_atf_run_LDADD = $(TOOLS_LDADD) -dist_man_MANS += tools/atf-run.1 - -bin_PROGRAMS += tools/atf-version -tools_atf_version_SOURCES = tools/atf-version.cpp -nodist_tools_atf_version_SOURCES = tools/revision.h -tools_atf_version_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_atf_version_LDADD = $(TOOLS_LDADD) -dist_man_MANS += tools/atf-version.1 - -EXTRA_DIST += tools/generate-revision.sh - -BUILT_SOURCES += tools/revision.h -CLEANFILES += tools/revision.h -tools/revision.h: tools/revision.h.stamp - @test -d tools || mkdir -p tools - @cmp -s tools/revision.h tools/revision.h.stamp || \ - cp -p tools/revision.h.stamp tools/revision.h - -CLEANFILES += tools/revision.h.stamp -PHONY_TARGETS += tools/revision.h.stamp -tools/revision.h.stamp: - @test -d tools || mkdir -p tools - @$(top_srcdir)/tools/generate-revision.sh \ - -g "$(GIT)" -r $(top_srcdir) -o tools/revision.h.stamp \ - -v $(PACKAGE_VERSION) - - - -man_MANS += tools/atf.7 -CLEANFILES += tools/atf.7 -EXTRA_DIST += tools/atf.7.in - -dist_man_MANS += tools/atf-formats.5 - -tools/atf.7: $(srcdir)/tools/atf.7.in - test -d tools || mkdir -p tools - sed -e 's#__DOCDIR__#$(docdir)#g' \ - -e 's#__TESTSDIR__#$(testsdir)#g' \ - <$(srcdir)/tools/atf.7.in >tools/atf.7.tmp - mv tools/atf.7.tmp tools/atf.7 - - - -cssdir = $(atf_cssdir) -css_DATA = tools/tests-results.css -EXTRA_DIST += $(css_DATA) - -dtddir = $(atf_dtddir) -dtd_DATA = tools/tests-results.dtd -EXTRA_DIST += $(dtd_DATA) - -egdir = $(atf_egdir) -eg_DATA = tools/sample/atf-run.hooks -eg_DATA += tools/sample/common.conf -EXTRA_DIST += $(eg_DATA) - -hooksdir = $(pkgdatadir) -hooks_DATA = tools/share/atf-run.hooks -EXTRA_DIST += $(hooks_DATA) - -xsldir = $(atf_xsldir) -xsl_DATA = tools/tests-results.xsl -EXTRA_DIST += $(xsl_DATA) - - - -tests_tools_DATA = tools/Atffile tools/Kyuafile -tests_toolsdir = $(pkgtestsdir)/tools -EXTRA_DIST += $(tests_tools_DATA) - -tests_tools_SCRIPTS = tools/atf-config_test -CLEANFILES += tools/atf-config_test -EXTRA_DIST += tools/atf-config_test.sh -tools/atf-config_test: $(srcdir)/tools/atf-config_test.sh - @test -d tools || mkdir -p tools - @src="$(srcdir)/tools/atf-config_test.sh"; \ - dst="tools/atf-config_test"; $(BUILD_SH_TP) - -tests_tools_SCRIPTS += tools/atf-report_test -CLEANFILES += tools/atf-report_test -EXTRA_DIST += tools/atf-report_test.sh -tools/atf-report_test: $(srcdir)/tools/atf-report_test.sh - @test -d tools || mkdir -p tools - @src="$(srcdir)/tools/atf-report_test.sh"; \ - dst="tools/atf-report_test"; $(BUILD_SH_TP) - -tests_tools_SCRIPTS += tools/atf-run_test -CLEANFILES += tools/atf-run_test -EXTRA_DIST += tools/atf-run_test.sh -tools/atf-run_test: $(srcdir)/tools/atf-run_test.sh - @test -d tools || mkdir -p tools - @src="$(srcdir)/tools/atf-run_test.sh"; \ - dst="tools/atf-run_test"; $(BUILD_SH_TP) - -tests_tools_PROGRAMS = tools/application_test -tools_application_test_SOURCES = tools/application_test.cpp -tools_application_test_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_application_test_LDADD = $(TOOLS_LDADD) $(ATF_CXX_LIBS) - -tests_tools_PROGRAMS += tools/atffile_test -tools_atffile_test_SOURCES = tools/atffile_test.cpp -tools_atffile_test_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_atffile_test_LDADD = $(TOOLS_LDADD) $(ATF_CXX_LIBS) - -tests_tools_PROGRAMS += tools/auto_array_test -tools_auto_array_test_SOURCES = tools/auto_array_test.cpp -tools_auto_array_test_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_auto_array_test_LDADD = $(TOOLS_LDADD) $(ATF_CXX_LIBS) - -tests_tools_PROGRAMS += tools/bad_metadata_helper -tools_bad_metadata_helper_SOURCES = tools/bad_metadata_helper.c -tools_bad_metadata_helper_LDADD = libatf-c.la - -tests_tools_PROGRAMS += tools/config_test -tools_config_test_SOURCES = tools/config_test.cpp -tools_config_test_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_config_test_LDADD = $(TOOLS_LDADD) $(ATF_CXX_LIBS) - -tests_tools_PROGRAMS += tools/config_file_test -tools_config_file_test_SOURCES = tools/config_file_test.cpp -tools_config_file_test_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_config_file_test_LDADD = $(TOOLS_LDADD) $(ATF_CXX_LIBS) - -tests_tools_PROGRAMS += tools/env_test -tools_env_test_SOURCES = tools/env_test.cpp -tools_env_test_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_env_test_LDADD = $(TOOLS_LDADD) $(ATF_CXX_LIBS) - -tests_tools_PROGRAMS += tools/expand_test -tools_expand_test_SOURCES = tools/expand_test.cpp -tools_expand_test_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_expand_test_LDADD = $(TOOLS_LDADD) $(ATF_CXX_LIBS) - -tests_tools_PROGRAMS += tools/expect_helpers -tools_expect_helpers_SOURCES = tools/expect_helpers.c -tools_expect_helpers_LDADD = libatf-c.la - -tests_tools_PROGRAMS += tools/fail_helper -tools_fail_helper_SOURCES = tools/fail_helper.cpp -tools_fail_helper_LDADD = $(ATF_CXX_LIBS) - -tests_tools_PROGRAMS += tools/fs_test -tools_fs_test_SOURCES = tools/fs_test.cpp -tools_fs_test_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_fs_test_LDADD = $(TOOLS_LDADD) $(ATF_CXX_LIBS) - -tests_tools_PROGRAMS += tools/io_test -tools_io_test_SOURCES = tools/io_test.cpp -tools_io_test_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_io_test_LDADD = $(TOOLS_LDADD) $(ATF_CXX_LIBS) - -tests_tools_PROGRAMS += tools/misc_helpers -tools_misc_helpers_SOURCES = tools/misc_helpers.cpp -tools_misc_helpers_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_misc_helpers_LDADD = $(TOOLS_LDADD) $(ATF_CXX_LIBS) - -tests_tools_PROGRAMS += tools/parser_test -tools_parser_test_SOURCES = tools/parser_test.cpp -tools_parser_test_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_parser_test_LDADD = $(TOOLS_LDADD) $(ATF_CXX_LIBS) - -tests_tools_PROGRAMS += tools/process_test -tools_process_test_SOURCES = tools/process_test.cpp -tools_process_test_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_process_test_LDADD = $(TOOLS_LDADD) $(ATF_CXX_LIBS) - -tests_tools_PROGRAMS += tools/pass_helper -tools_pass_helper_SOURCES = tools/pass_helper.cpp -tools_pass_helper_LDADD = $(ATF_CXX_LIBS) - -tests_tools_PROGRAMS += tools/process_helpers -tools_process_helpers_SOURCES = tools/process_helpers.c - -tests_tools_PROGRAMS += tools/reader_test -tools_reader_test_SOURCES = tools/reader_test.cpp -tools_reader_test_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_reader_test_LDADD = $(TOOLS_LDADD) $(ATF_CXX_LIBS) - -tests_tools_PROGRAMS += tools/requirements_test -tools_requirements_test_SOURCES = tools/requirements_test.cpp -tools_requirements_test_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_requirements_test_LDADD = $(TOOLS_LDADD) $(ATF_CXX_LIBS) - -tests_tools_PROGRAMS += tools/several_tcs_helper -tools_several_tcs_helper_SOURCES = tools/several_tcs_helper.c -tools_several_tcs_helper_LDADD = libatf-c.la - -tests_tools_PROGRAMS += tools/signals_test -tools_signals_test_SOURCES = tools/signals_test.cpp tools/signals.cpp -tools_signals_test_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_signals_test_LDADD = $(TOOLS_LDADD) $(ATF_CXX_LIBS) - -tests_tools_PROGRAMS += tools/test_program_test -tools_test_program_test_SOURCES = tools/test_program_test.cpp -tools_test_program_test_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_test_program_test_LDADD = $(TOOLS_LDADD) $(ATF_CXX_LIBS) - -tests_tools_PROGRAMS += tools/text_test -tools_text_test_SOURCES = tools/text_test.cpp tools/text.cpp -tools_text_test_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_text_test_LDADD = $(TOOLS_LDADD) $(ATF_CXX_LIBS) - -tests_tools_PROGRAMS += tools/ui_test -tools_ui_test_SOURCES = tools/ui_test.cpp tools/ui.cpp -tools_ui_test_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_ui_test_LDADD = $(TOOLS_LDADD) $(ATF_CXX_LIBS) - -tests_tools_PROGRAMS += tools/user_test -tools_user_test_SOURCES = tools/user_test.cpp tools/user.cpp -tools_user_test_CPPFLAGS = $(TOOLS_CPPFLAGS) -tools_user_test_LDADD = $(TOOLS_LDADD) $(ATF_CXX_LIBS) - -tests_tools_PROGRAMS += tools/zero_tcs_helper -tools_zero_tcs_helper_SOURCES = tools/zero_tcs_helper.c -tools_zero_tcs_helper_LDADD = libatf-c.la - -# vim: syntax=make:noexpandtab:shiftwidth=8:softtabstop=8 diff --git a/tools/application.cpp b/tools/application.cpp deleted file mode 100644 index 723e9f1..0000000 --- a/tools/application.cpp +++ /dev/null @@ -1,317 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if defined(HAVE_CONFIG_H) -#include "bconfig.h" -#endif - -extern "C" { -#include <unistd.h> -} - -#include <cassert> -#include <cstdarg> -#include <cstdio> -#include <cstdlib> -#include <cstring> -#include <iostream> - -#include "application.hpp" -#include "defs.hpp" -#include "ui.hpp" - -#if !defined(HAVE_VSNPRINTF_IN_STD) -namespace std { -using ::vsnprintf; -} -#endif // !defined(HAVE_VSNPRINTF_IN_STD) - -namespace impl = tools::application; -#define IMPL_NAME "tools::application" - -// ------------------------------------------------------------------------ -// The "usage_error" class. -// ------------------------------------------------------------------------ - -impl::usage_error::usage_error(const char *fmt, ...) - throw() : - std::runtime_error("usage_error; message unformatted") -{ - va_list ap; - - va_start(ap, fmt); - std::vsnprintf(m_text, sizeof(m_text), fmt, ap); - va_end(ap); -} - -impl::usage_error::~usage_error(void) - throw() -{ -} - -const char* -impl::usage_error::what(void) - const throw() -{ - return m_text; -} - -// ------------------------------------------------------------------------ -// The "application" class. -// ------------------------------------------------------------------------ - -impl::option::option(char ch, - const std::string& a, - const std::string& desc) : - m_character(ch), - m_argument(a), - m_description(desc) -{ -} - -bool -impl::option::operator<(const impl::option& o) - const -{ - return m_character < o.m_character; -} - -impl::app::app(const std::string& description, - const std::string& manpage, - const std::string& global_manpage) : - m_hflag(false), - m_argc(-1), - m_argv(NULL), - m_prog_name(NULL), - m_description(description), - m_manpage(manpage), - m_global_manpage(global_manpage) -{ -} - -impl::app::~app(void) -{ -} - -bool -impl::app::inited(void) -{ - return m_argc != -1; -} - -impl::app::options_set -impl::app::options(void) -{ - options_set opts = specific_options(); - opts.insert(option('h', "", "Shows this help message")); - return opts; -} - -std::string -impl::app::specific_args(void) - const -{ - return ""; -} - -impl::app::options_set -impl::app::specific_options(void) - const -{ - return options_set(); -} - -void -impl::app::process_option(int ch ATF_DEFS_ATTRIBUTE_UNUSED, - const char* arg ATF_DEFS_ATTRIBUTE_UNUSED) -{ -} - -void -impl::app::process_options(void) -{ - assert(inited()); - - std::string optstr; -#if defined(HAVE_GNU_GETOPT) - optstr += '+'; // Turn on POSIX behavior. -#endif - optstr += ':'; - { - options_set opts = options(); - for (options_set::const_iterator iter = opts.begin(); - iter != opts.end(); iter++) { - const option& opt = (*iter); - - optstr += opt.m_character; - if (!opt.m_argument.empty()) - optstr += ':'; - } - } - - int ch; - const int old_opterr = ::opterr; - ::opterr = 0; - while ((ch = ::getopt(m_argc, m_argv, optstr.c_str())) != -1) { - switch (ch) { - case 'h': - m_hflag = true; - break; - - case ':': - throw usage_error("Option -%c requires an argument.", - ::optopt); - - case '?': - throw usage_error("Unknown option -%c.", ::optopt); - - default: - process_option(ch, ::optarg); - } - } - m_argc -= ::optind; - m_argv += ::optind; - - // Clear getopt state just in case the test wants to use it. - opterr = old_opterr; - optind = 1; -#if defined(HAVE_OPTRESET) - optreset = 1; -#endif -} - -void -impl::app::usage(std::ostream& os) -{ - assert(inited()); - - std::string args = specific_args(); - if (!args.empty()) - args = " " + args; - os << ui::format_text_with_tag(std::string(m_prog_name) + " [options]" + - args, "Usage: ", false) << "\n\n" - << ui::format_text(m_description) << "\n\n"; - - options_set opts = options(); - assert(!opts.empty()); - os << "Available options:\n"; - size_t coldesc = 0; - for (options_set::const_iterator iter = opts.begin(); - iter != opts.end(); iter++) { - const option& opt = (*iter); - - if (opt.m_argument.length() + 1 > coldesc) - coldesc = opt.m_argument.length() + 1; - } - for (options_set::const_iterator iter = opts.begin(); - iter != opts.end(); iter++) { - const option& opt = (*iter); - - std::string tag = std::string(" -") + opt.m_character; - if (opt.m_argument.empty()) - tag += " "; - else - tag += " " + opt.m_argument + " "; - os << ui::format_text_with_tag(opt.m_description, tag, false, - coldesc + 10) << "\n"; - } - os << "\n"; - - std::string gmp; - if (!m_global_manpage.empty()) - gmp = " and " + m_global_manpage; - os << ui::format_text("For more details please see " + m_manpage + - gmp + ".") - << "\n"; -} - -int -impl::app::run(int argc, char* const* argv) -{ - assert(argc > 0); - assert(argv != NULL); - - m_argc = argc; - m_argv = argv; - - m_argv0 = m_argv[0]; - - m_prog_name = std::strrchr(m_argv[0], '/'); - if (m_prog_name == NULL) - m_prog_name = m_argv[0]; - else - m_prog_name++; - - // Libtool workaround: if running from within the source tree (binaries - // that are not installed yet), skip the "lt-" prefix added to files in - // the ".libs" directory to show the real (not temporary) name. - if (std::strncmp(m_prog_name, "lt-", 3) == 0) - m_prog_name += 3; - - const std::string bug = - std::string("This is probably a bug in ") + m_prog_name + - " or one of the libraries it uses. Please report this problem to " - PACKAGE_BUGREPORT " and provide as many details as possible " - "describing how you got to this condition."; - - int errcode; - try { - int oldargc = m_argc; - - process_options(); - - if (m_hflag) { - if (oldargc != 2) - throw usage_error("-h must be given alone."); - - usage(std::cout); - errcode = EXIT_SUCCESS; - } else - errcode = main(); - } catch (const usage_error& e) { - std::cerr << ui::format_error(m_prog_name, e.what()) << "\n" - << ui::format_info(m_prog_name, std::string("Type `") + - m_prog_name + " -h' for more details.") - << "\n"; - errcode = EXIT_FAILURE; - } catch (const std::runtime_error& e) { - std::cerr << ui::format_error(m_prog_name, std::string(e.what())) - << "\n"; - errcode = EXIT_FAILURE; - } catch (const std::exception& e) { - std::cerr << ui::format_error(m_prog_name, std::string("Caught " - "unexpected error: ") + e.what() + "\n" + bug) << "\n"; - errcode = EXIT_FAILURE; - } catch (...) { - std::cerr << ui::format_error(m_prog_name, std::string("Caught " - "unknown error\n") + bug) << "\n"; - errcode = EXIT_FAILURE; - } - return errcode; -} diff --git a/tools/application.hpp b/tools/application.hpp deleted file mode 100644 index 5a8d57c..0000000 --- a/tools/application.hpp +++ /dev/null @@ -1,113 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if !defined(TOOLS_APPLICATION_HPP) -#define TOOLS_APPLICATION_HPP - -#include <ostream> -#include <set> -#include <stdexcept> -#include <string> - -namespace tools { -namespace application { - -// ------------------------------------------------------------------------ -// The "usage_error" class. -// ------------------------------------------------------------------------ - -class usage_error : public std::runtime_error { - char m_text[4096]; - -public: - usage_error(const char*, ...) throw(); - ~usage_error(void) throw(); - - const char* what(void) const throw(); -}; - -// ------------------------------------------------------------------------ -// The "option" class. -// ------------------------------------------------------------------------ - -class option { - char m_character; - std::string m_argument; - std::string m_description; - - friend class app; - -public: - option(char, const std::string&, const std::string&); - - bool operator<(const option&) const; -}; - -// ------------------------------------------------------------------------ -// The "app" class. -// ------------------------------------------------------------------------ - -class app { - bool m_hflag; - - void process_options(void); - void usage(std::ostream&); - - bool inited(void); - -protected: - typedef std::set< option > options_set; - - int m_argc; - char* const* m_argv; - - const char* m_argv0; - const char* m_prog_name; - std::string m_description; - std::string m_manpage, m_global_manpage; - - options_set options(void); - - // To be redefined. - virtual std::string specific_args(void) const; - virtual options_set specific_options(void) const; - virtual void process_option(int, const char*); - virtual int main(void) = 0; - -public: - app(const std::string&, const std::string&, const std::string&); - virtual ~app(void); - - int run(int, char* const*); -}; - -} // namespace application -} // namespace tools - -#endif // !defined(TOOLS_APPLICATION_HPP) diff --git a/tools/application_test.cpp b/tools/application_test.cpp deleted file mode 100644 index a9013cd..0000000 --- a/tools/application_test.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2009 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. -// - -extern "C" { -#include <unistd.h> -} - -#include <atf-c++.hpp> - -#include "application.hpp" - -class getopt_app : public tools::application::app { -public: - getopt_app(void) : app("description", "manpage", "other") {} - - int main(void) - { - // Provide an option that is unknown to the application driver and - // one that is, together with an argument that would be swallowed by - // the test program option if it were recognized. - int argc = 4; - char arg1[] = "progname"; - char arg2[] = "-Z"; - char arg3[] = "-s"; - char arg4[] = "foo"; - char *const argv[] = { arg1, arg2, arg3, arg4, NULL }; - - int ch; - bool zflag; - - // Given that this obviously is an application, and that we used the - // same driver to start, we can test getopt(3) right here without doing - // any fancy stuff. - zflag = false; - while ((ch = ::getopt(argc, argv, ":Z")) != -1) { - switch (ch) { - case 'Z': - zflag = true; - break; - - case '?': - default: - if (optopt != 's') - ATF_FAIL("Unexpected unknown option found"); - } - } - - ATF_REQUIRE(zflag); - ATF_REQUIRE_EQ(1, argc - optind); - ATF_REQUIRE_EQ(std::string("foo"), argv[optind]); - - return 0; - } -}; - -ATF_TEST_CASE_WITHOUT_HEAD(getopt); -ATF_TEST_CASE_BODY(getopt) -{ - int argc = 1; - char arg1[] = "progname"; - char *const argv[] = { arg1, NULL }; - ATF_REQUIRE_EQ(0, getopt_app().run(argc, argv)); -} - -ATF_INIT_TEST_CASES(tcs) -{ - ATF_ADD_TEST_CASE(tcs, getopt); -} diff --git a/tools/atf-config.1 b/tools/atf-config.1 deleted file mode 100644 index deae6f6..0000000 --- a/tools/atf-config.1 +++ /dev/null @@ -1,184 +0,0 @@ -.\" -.\" Automated Testing Framework (atf) -.\" -.\" Copyright (c) 2007 The NetBSD Foundation, Inc. -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.Dd March 14, 2009 -.Dt ATF-CONFIG 1 -.Os -.Sh NAME -.Nm atf-config -.Nd queries static configuration information of ATF -.Sh SYNOPSIS -.Nm -.Op Fl t -.Op Ar var1 Op Ar .. varN -.Nm -.Fl h -.Sh DESCRIPTION -.Nm -is a utility that queries static configuration information of ATF. -Static configuration refers to all those values for settings that -were built into the ATF binaries at build time. -.Pp -In the first synopsis form, -.Nm -will print variable-value pairs for all built-in static variables if -no variable names are provided as arguments. -If any is provided, it will only print the variable-value pairs for -those variables. -The output of the utility does not use the -.Sq = -symbol to separate the variable name from its corresponding value in -an attempt to avoid sourcing the output in shell scripts or Makefiles. -If you need to do that, the -.Fl t -flag allows you to query the value of individual variables without any -surrounding text. -.Pp -In the second synopsis form, -.Nm -will print information about all supported options and their purpose. -.Pp -The following options are available: -.Bl -tag -width flag -.It Fl h -Shows a short summary of all available options and their purpose. -.It Fl t -Changes the output of the utility to show the variable values, one -per line, without the variable names. -.El -.Ss Static configuration variables -The following list describes all the variables that are part of ATF's -static configuration: -.Bl -tag -width atfXbuildXcppflagsXX -.It Va atf_arch -The architecture name detected by ATF. -This is derived from -.Va atf_machine -because it is a subset of it. -Given that this name might be misdetected, it is provided to the user -as a configuration variable so that he can fix its value temporarily -until a real fix is incorporated into mainstream sources. -.It Va atf_build_cc -The C compiler used by the ATF checks that provide build-time tests. -.It Va atf_build_cflags -The C compiler flags used by the ATF checks that provide build-time tests. -.It Va atf_build_cpp -The C/C++ preprocessor used by the ATF checks that provide build-time tests. -.It Va atf_build_cppflags -The C/C++ preprocessor flags used by the ATF checks that provide build-time -tests. -.It Va atf_build_cxx -The C++ compiler used by the ATF checks that provide build-time tests. -.It Va atf_build_cxxflags -The C++ compiler flags used by the ATF checks that provide build-time tests. -.It Va atf_confdir -The path to the directory that contains the system-wide configuration -files for ATF. -.It Va atf_includedir -The path to the directory that contains the ATF header files. -.It Va atf_libdir -The path to the directory that contains the ATF libraries. -.It Va atf_libexecdir -The path to the directory that contains the auxiliary utilities of ATF, -used internally by the public tools. -.It Va atf_machine -The machine type name detected by ATF. -This should not be tunable but is provided for symmetry with -.Va atf_arch . -.It Va atf_pkgdatadir -The path to the directory that contains the files that form the ATF's -shell-scripting library. -.It Va atf_shell -The path to the shell interpreter that will be used by ATF. -.It Va atf_workdir -The path to the temporary directory that the utilities and the test -programs will use to store temporary files in. -.El -.Sh ENVIRONMENT -Every variable that is part of the static configuration can be -overridden at run-time by defining an environment variable. -This environment variable has the exact same name as the one shown by -.Nm -except that the name is all composed of uppercase letters. -.Pp -In general, empty values in the environment will be ignored unless -otherwise noted below. -.Pp -The recognized environment variables are: -.Bl -tag -width ATFXBUILDXCPPFLAGSXX -.It Ev ATF_ARCH -Overrides the built-in value of -.Va atf_arch . -.It Ev ATF_BUILD_CC -Overrides the built-in value of -.Va atf_build_cc . -.It Ev ATF_BUILD_CFLAGS -Overrides the built-in value of -.Va atf_build_cflags . -Empty values are allowed. -.It Ev ATF_BUILD_CPP -Overrides the built-in value of -.Va atf_build_cpp . -.It Ev ATF_BUILD_CPPFLAGS -Overrides the built-in value of -.Va atf_build_cppflags . -Empty values are allowed. -.It Ev ATF_BUILD_CXX -Overrides the built-in value of -.Va atf_build_cxx . -.It Ev ATF_BUILD_CXXFLAGS -Overrides the built-in value of -.Va atf_build_cxxflags . -Empty values are allowed. -.It Ev ATF_CONFDIR -Overrides the built-in value of -.Va atf_confdir . -.It Ev ATF_INCLUDEDIR -Overrides the built-in value of -.Va atf_includedir . -.It Ev ATF_LIBDIR -Overrides the built-in value of -.Va atf_libdir . -.It Ev ATF_LIBEXECDIR -Overrides the built-in value of -.Va atf_libexecdir . -.It Ev ATF_MACHINE -Overrides the built-in value of -.Va atf_machine . -.It Ev ATF_PKGDATADIR -Overrides the built-in value of -.Va atf_pkgdatadir . -.It Ev ATF_SHELL -Overrides the built-in value of -.Va atf_shell . -.It Ev ATF_WORKDIR -Overrides the built-in value of -.Va atf_workdir . -.El -.Sh SEE ALSO -.Xr atf 7 diff --git a/tools/atf-config.cpp b/tools/atf-config.cpp deleted file mode 100644 index 4d82d55..0000000 --- a/tools/atf-config.cpp +++ /dev/null @@ -1,140 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 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 <cstdlib> -#include <iostream> -#include <map> -#include <string> - -#include "application.hpp" -#include "config.hpp" -#include "defs.hpp" - -class atf_config : public tools::application::app { - static const char* m_description; - - bool m_tflag; - - void process_option(int, const char*); - std::string specific_args(void) const; - options_set specific_options(void) const; - - std::string format_var(const std::string&, const std::string&); - -public: - atf_config(void); - - int main(void); -}; - -const char* atf_config::m_description = - "atf-config is a tool that queries the value of several " - "installation-specific configuration values of the atf. " - "It can be used by external tools to discover where specific " - "internal atf files are installed."; - -atf_config::atf_config(void) : - app(m_description, "atf-config(1)", "atf(7)"), - m_tflag(false) -{ -} - -void -atf_config::process_option(int ch, const char* arg ATF_DEFS_ATTRIBUTE_UNUSED) -{ - switch (ch) { - case 't': - m_tflag = true; - break; - - default: - std::abort(); - } -} - -std::string -atf_config::specific_args(void) - const -{ - return "[var1 [.. varN]]"; -} - -atf_config::options_set -atf_config::specific_options(void) - const -{ - using tools::application::option; - options_set opts; - opts.insert(option('t', "", "Terse output: show values only")); - return opts; -} - -std::string -atf_config::format_var(const std::string& name, const std::string& val) -{ - std::string str; - - if (m_tflag) - str = val; - else - str = name + " : " + val; - - return str; -} - -int -atf_config::main(void) -{ - if (m_argc < 1) { - std::map< std::string, std::string > cv = tools::config::get_all(); - - for (std::map< std::string, std::string >::const_iterator iter = - cv.begin(); iter != cv.end(); iter++) - std::cout << format_var((*iter).first, (*iter).second) << "\n"; - } else { - for (int i = 0; i < m_argc; i++) { - if (!tools::config::has(m_argv[i])) - throw std::runtime_error(std::string("Unknown variable `") + - m_argv[i] + "'"); - } - - for (int i = 0; i < m_argc; i++) { - std::cout << format_var(m_argv[i], tools::config::get(m_argv[i])) - << "\n"; - } - } - - return EXIT_SUCCESS; -} - -int -main(int argc, char* const* argv) -{ - return atf_config().run(argc, argv); -} diff --git a/tools/atf-config_test.sh b/tools/atf-config_test.sh deleted file mode 100755 index 5d6505a..0000000 --- a/tools/atf-config_test.sh +++ /dev/null @@ -1,180 +0,0 @@ -# -# Automated Testing Framework (atf) -# -# Copyright (c) 2007 The NetBSD Foundation, Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 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. -# - -all_vars="atf_arch \ - atf_build_cc \ - atf_build_cflags \ - atf_build_cpp \ - atf_build_cppflags \ - atf_build_cxx \ - atf_build_cxxflags \ - atf_confdir \ - atf_includedir \ - atf_libdir \ - atf_libexecdir \ - atf_machine \ - atf_pkgdatadir \ - atf_shell \ - atf_workdir" -all_vars_no=15 - -atf_test_case list_all -list_all_head() -{ - atf_set "descr" "Tests that at atf-config prints all expected" \ - "variables, and not more" -} -list_all_body() -{ - atf_check -s eq:0 -o save:stdout -e empty atf-config - atf_check -s eq:0 -o empty -e empty \ - test "$(wc -l stdout | awk '{ print $1 }')" = "${all_vars_no}" - for v in ${all_vars}; do - atf_check -s eq:0 -o ignore -e empty grep "${v}" stdout - done -} - -atf_test_case query_one -query_one_head() -{ - atf_set "descr" "Tests that querying a single variable works" -} -query_one_body() -{ - for v in ${all_vars}; do - atf_check -s eq:0 -o save:stdout -o match:"${v}" -e empty \ - atf-config "${v}" - atf_check -s eq:0 -o empty -e empty \ - test "$(wc -l stdout | awk '{ print $1 }')" = 1 - done -} - -atf_test_case query_one_terse -query_one_terse_head() -{ - atf_set "descr" "Tests that querying a single variable in terse mode" \ - "works" -} -query_one_terse_body() -{ - for v in ${all_vars}; do - atf_check -s eq:0 -o save:stdout -o match:"${v}" -e empty \ - atf-config "${v}" - atf_check -s eq:0 -o empty -e empty \ - test "$(wc -l stdout | awk '{ print $1 }')" = 1 - atf_check -s eq:0 -o save:stdout -e empty cut -d ' ' -f 3- stdout - atf_check -s eq:0 -o empty -e empty mv stdout expout - atf_check -s eq:0 -o file:expout -e empty atf-config -t "${v}" - done -} - -atf_test_case query_multiple -query_multiple_head() -{ - atf_set "descr" "Tests that querying multiple variables works" -} -query_multiple_body() -{ - atf_check -s eq:0 -o save:stdout -o match:'atf_libexecdir' \ - -o match:'atf_shell' -e empty atf-config atf_libexecdir atf_shell - atf_check -s eq:0 -o empty -e empty \ - test "$(wc -l stdout | awk '{ print $1 }')" = 2 -} - -atf_test_case query_unknown -query_unknown_head() -{ - atf_set "descr" "Tests that querying an unknown variable delivers" \ - "the correct error" -} -query_unknown_body() -{ - atf_check -s eq:1 -o empty -e match:'Unknown variable.*non_existent' \ - atf-config non_existent -} - -atf_test_case query_mixture -query_mixture_head() -{ - atf_set "descr" "Tests that querying a known and an unknown variable" \ - "delivers the correct error" -} -query_mixture_body() -{ - for v in ${all_vars}; do - atf_check -s eq:1 -o empty -e match:'Unknown variable.*non_existent' \ - atf-config "${v}" non_existent - atf_check -s eq:1 -o empty -e match:'Unknown variable.*non_existent' \ - atf-config non_existent "${v}" - done -} - -atf_test_case override_env -override_env_head() -{ - atf_set "descr" "Tests that build-time variables can be overriden" \ - "through their corresponding environment variables" -} -override_env_body() -{ - for v in ${all_vars}; do - V=$(echo ${v} | tr '[a-z]' '[A-Z]') - atf_check -s eq:0 -o save:stdout -e empty -x "${V}=testval atf-config" - atf_check -s eq:0 -o empty -e empty mv stdout all - - atf_check -s eq:0 -o save:stdout -e empty grep "^${v} : " all - atf_check -s eq:0 -o empty -e empty mv stdout affected - atf_check -s eq:0 -o save:stdout -e empty grep -v "^${v} : " all - atf_check -s eq:0 -o empty -e empty mv stdout unaffected - - atf_check -s eq:0 -o empty -e empty \ - test "$(wc -l affected | awk '{ print $1 }')" = 1 - atf_check -s eq:0 -o empty -e empty \ - test "$(wc -l unaffected | awk '{ print $1 }')" = \ - "$((${all_vars_no} -1))" - - atf_check -s eq:0 -o ignore -e empty grep "^${v} : testval$" affected - atf_check -s eq:1 -o empty -e empty grep ' : testval$' unaffected - done -} - -atf_init_test_cases() -{ - atf_add_test_case list_all - - atf_add_test_case query_one - atf_add_test_case query_one_terse - atf_add_test_case query_multiple - atf_add_test_case query_unknown - atf_add_test_case query_mixture - - atf_add_test_case override_env -} - -# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/tools/atf-formats.5 b/tools/atf-formats.5 deleted file mode 100644 index bb919f4..0000000 --- a/tools/atf-formats.5 +++ /dev/null @@ -1,231 +0,0 @@ -.\" -.\" Automated Testing Framework (atf) -.\" -.\" Copyright (c) 2007 The NetBSD Foundation, Inc. -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.Dd December 20, 2011 -.Dt ATF-FORMATS 5 -.Os -.Sh NAME -.Nm atf-formats -.Nd machine-parseable data formats used by ATF -.Sh DESCRIPTION -This manual page describes the multiple data formats used in ATF. -These formats affect configuration files, control files and any data that -is externalized or internalized by the tools. -.Pp -Data files are always organized as follows: -.Bd -literal -offset indent -Header1: Value1 \\ - ... | head -HeaderN: ValueN / - mandatory blank line -Free-form text contents \\ - ... | body - ... / -.Ed -.Pp -A file must always contain a -.Sq Content-Type -header and must always separate that header from the body with a blank -line, even if the body is empty. -.Pp -The -.Sq Content-Type -is always of the form: -.Bd -literal -offset indent -Content-Type: application/X-atf-<subtype>; version="<version>" -.Ed -.Pp -where -.Sq subtype -indicates the specific file format and -.Sq version -its format version. -This header must be the first one of the file. -.Pp -The main purpose of the -.Sq Content-Type -header, aside from determining the format used in the file, is to allow -future changes to a given format. -Whenever an incompatible change is made, the version is bumped by one. -By keeping the header in the first line, future versions may even remove -the need for such a header -- e.g. if some format was replaced by XML -files, which have their own mandatory header. -.Pp -The rest of this document details the different format types. -.Ss Format: application/X-atf-atffile, version: 1 -Atffiles are logically divided into three sections: -.Bl -bullet -.It -Test programs: the list of test programs that define the test suite -described by the Atffile. -.It -Meta-data properties: these define some constant values applicable to -all the test programs defined in the file. -In some sense they define the properties that describe the test suite. -.It -Configuration variables: defaults for configuration variables that -can be overridden through configuration files or the command line. -.El -.Pp -The grammar for Atffiles is the following: -.Bd -literal -offset indent -DATA ::= ( ( CONF | PROP | TP )? COMMENT? NEWLINE )* EOF -CONF ::= 'conf:' WORD EQUAL STRING -PROP ::= 'prop:' WORD EQUAL STRING -TP ::= TPFILE | TPGLOB -TPFILE ::= 'tp: ' STRING -TPGLOB ::= 'tp-glob: ' STRING -STRING ::= WORD | '"' WORD* '"' -.Ed -.Pp -The meaning of the constructions above is: -.Bl -tag -width TPGLOBXX -.It CONF -Definition of a configuration variable. -.It PROP -Definition of a meta-data property. -.It TPFILE -Addition of a test program into the test suite. -The string is taken literally as the program's name, and this program -must exist. -.It TPGLOB -Addition of multiple test programs into the test suite. -The string is taken as a glob pattern, which may have or not have any -matches in the current directory. -.El -.Pp -An example: -.Bd -literal -offset indent -prop: test-suite = utilities - -conf: unprivileged-user = nobody - -tp: t_cp -tp: t_mv -tp: t_df -tp-glob: t_dir_* -.Ed -.Ss Format: application/X-atf-config, version: 1 -Configuration files are very simple: they only contain a list of variable -name/variable value pairs. -Their grammar is: -.Bd -literal -offset indent -DATA ::= ( VAR? COMMENT? NEWLINE )* EOF -VAR ::= WORD EQUAL STRING -COMMENT ::= HASH WORD* -STRING ::= WORD | '"' WORD* '"' -.Ed -.Pp -An example: -.Bd -literal -offset indent -# This is the system-wide configuration file for ATF. -# The above and this line are comments placed on their own line. - -var1 = this is a variable value -var2 = this is another one # Optional comment at the end. -.Ed -.Ss Format: application/X-atf-tps, version: 3 -The -.Sq application/X-atf-tps -format multiplexes the standard output, standard error and results output -streams from multiple test programs into a single data file. -This format is used by -.Xr atf-run 1 -to report the execution of several test programs and is later parsed by -.Xr atf-report 1 -to inform the user of this process. -It has the following grammar: -.Bd -literal -offset indent -DATA ::= INFO* TPS-COUNT TP-STANZA* INFO* EOF -INFO ::= 'info' COLON STRING COMMA STRING NEWLINE -TPS-COUNT ::= 'tps-count' COLON POSITIVE-NUMBER NEWLINE -TP-STANZA ::= TP-START TC-STANZA* TC-END -TP-START ::= 'tp-start' COLON TIMESTAMP COMMA STRING COMMA - POSITIVE-NUMBER NEWLINE -TP-END ::= 'tc-end' COLON TIMESTAMP COMMA STRING (COMMA STRING)? -TC-STANZA ::= TC-START (TC-SO | TC-SE)* TC-END -TC-START ::= 'tc-start' COLON TIMESTAMP COMMA STRING NEWLINE -TC-SO ::= 'tc-so' COLON STRING NEWLINE -TC-SE ::= 'tc-se' COLON STRING NEWLINE -TC-END ::= 'tc-end' COLON TIMESTAMP COMMA STRING COMMA TCR NEWLINE -TCR ::= 'passed' | ('failed' | 'skipped') COMMA STRING -TIMESTAMP ::= [0-9]+.[0-9]+ -.Ed -.Pp -The meaning of the constructions above is: -.Bl -tag -width TPSXCOUNTXX -.It TPS-COUNT -Indicates the number of test programs that will be executed. -There will be this exact amount of -.Sq TP-STANZA -constructions following it. -.It TP-START -Indicates the beginning of a test program. -This includes the program's name and the amount of test cases that -will follow. -.It TP-END -Indicates the completion of a test program. -This is followed by the program's name and, if the program ended -prematurely, an error message indicating the reason of its failure. -A successful execution of a test program (regardless of the status of its -test cases) must not be accompanied by any reason. -.It TC-START -Indicates the beginning of a test case. -This is accompanied by the test case's name. -.It TC-SO -Contains a text line sent to the standard output stream during the -execution of the test case. -Leading and trailing space is preserved. -.It TC-SE -Contains a text line sent to the standard error stream during the -execution of the test case. -Leading and trailing space is preserved. -.It TC-END -Indicates the completion of a test case. -This is accompanied by the test case's name, its result and the reason -associated with this result (if applicable). -.El -.Pp -An example: -.Bd -literal -offset indent -tps-count: 2 -tp-start: calculator, 1324318951.838923, 2 -tc-start: add, 1324318951.839101 -tc-end: add, 1324318951.839500, passed -tc-start: subtract, 1324318951.840001 -tc-so: 3-2 expected to return 1 but got 0 -tc-end: subtract, 1324318952.000123, failed, Calculated an unexpected value -tp-end: calculator, 1324318952.002301 -tp-start: files, 1, 1324318952.502348 -tc-start: copy, 1324318952.508291 -tc-se: could not find the cp(1) utility -tc-end: copy, 1324318953.203145, skipped -tp-end: files, 1324318953.203800 -.Ed -.Sh SEE ALSO -.Xr atf 7 diff --git a/tools/atf-report.1 b/tools/atf-report.1 deleted file mode 100644 index df03af0..0000000 --- a/tools/atf-report.1 +++ /dev/null @@ -1,168 +0,0 @@ -.\" -.\" Automated Testing Framework (atf) -.\" -.\" Copyright (c) 2007 The NetBSD Foundation, Inc. -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.Dd December 16, 2011 -.Dt ATF-REPORT 1 -.Os -.Sh NAME -.Nm atf-report -.Nd transforms the output of atf-run to different formats -.Sh SYNOPSIS -.Nm -.Op Fl o Ar fmt1:path1 Op .. Fl o Ar fmtN:pathN -.Nm -.Fl h -.Sh DESCRIPTION -.Nm -reads the output of -.Nm atf-run -and transforms it to different formats. -Some of these are user-friendly and others are machine-parseable, which -opens a wide range of possibilities to analyze the results of a test -suite's execution. -See -.Sx Output formats -below for more details on which these formats are. -.Pp -In the first synopsis form, -.Nm -reads the output of -.Nm atf-run -through its standard input and, if no -.Fl o -options are given, prints a user-friendly report on its standard -output using the -.Sq ticker -format. -If -.Fl o -options are provided (more than one are allowed), they specify the complete -list of reports to generate. -They are all generated simultaneously, and for obvious reasons, two reports -cannot be written to the same file. -Note that the default output is suppressed when -.Fl o -is provided. -.Pp -In the second synopsis form, -.Nm -will print information about all supported options and their purpose. -.Pp -The following options are available: -.Bl -tag -width XoXfmtXpathXX -.It Fl h -Shows a short summary of all available options and their purpose. -.It Fl o Ar fmt:path -Adds a new output format. -.Ar fmt -is one of the formats described later on in -.Sx Output formats . -.Ar path -specifies where the report will be written to. -Depending on the chosen format, this may refer to a single file or to -a directory. -For those formats that write to a single file, specifying a -.Sq - -as the path will redirect the report to the standard output. -.El -.Ss Output formats -The following output formats are allowed: -.Bl -tag -width tickerXX -.It csv -A machine-parseable Comma-Separated Values (CSV) file. -This file contains the results for all test cases and test programs. -Test cases are logged using the following syntax: -.Bd -literal -offset indent -tc, duration, test-program, test-case, result[, reason] -.Ed -.Pp -The -.Sq result -field for test cases is always one of -.Sq passed , -.Sq skipped -or -.Sq failed . -The last two are always followed by a reason. -.Pp -Test programs are logged with the following syntax: -.Bd -literal -offset indent -tp, duration, test-program, result[, reason] -.Ed -.Pp -In this case, the -.Sq result -can be one of: -.Sq passed , -which denotes test programs that ran without any failure; -.Sq failed , -which refers to test programs in which one or more test cases failed; -or -.Sq bogus , -which mentions those test programs that failed to execute by some reason. -The reason field is only available in the last case. -.Pp -The time required to execute each test case and test program is -also provided. -You should not rely on the order of the entries in the resulting output. -.It ticker -A user-friendly report that shows the progress of the test suite's -execution as it operates. -This type of report should always be redirected to a virtual terminal, -not a file, as it may use control sequences that will make the output -unreadable in regular files. -.It xml -A report contained in a single XML file. -Ideal for later processing with -.Xr xsltproc 1 -to generate nice HTML reports. -.El -.Sh EXAMPLES -The most simple way of running a test suite is to pipe the output of -.Nm atf-run -through -.Nm -without any additional flags. -This will use the default output format, which is suitable to most users: -.Bd -literal -offset indent -atf-run | atf-report -.Ed -.Pp -In some situations, it may be interesting to get a machine-parseable file -aside from the standard report. -This can be done as follows: -.Bd -literal -offset indent -atf-run | atf-report -o csv:testsuite.csv -o ticker:- -.Ed -.Pp -Or if the standard report is not desired, thus achieving completely silent -operation: -atf-run | atf-report -o csv:testsuite.csv -.Sh SEE ALSO -.Xr atf-run 1 , -.Xr atf 7 diff --git a/tools/atf-report.cpp b/tools/atf-report.cpp deleted file mode 100644 index cb065f9..0000000 --- a/tools/atf-report.cpp +++ /dev/null @@ -1,710 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -extern "C" { -#include <sys/time.h> -} - -#include <cctype> -#include <cstdlib> -#include <fstream> -#include <iomanip> -#include <iostream> -#include <memory> -#include <sstream> -#include <utility> -#include <vector> - -#include "application.hpp" -#include "defs.hpp" -#include "fs.hpp" -#include "reader.hpp" -#include "text.hpp" -#include "ui.hpp" - -typedef std::auto_ptr< std::ostream > ostream_ptr; - -static ostream_ptr -open_outfile(const tools::fs::path& path) -{ - ostream_ptr osp; - if (path.str() == "-") - osp = ostream_ptr(new std::ofstream("/dev/stdout")); - else - osp = ostream_ptr(new std::ofstream(path.c_str())); - if (!(*osp)) - throw std::runtime_error("Could not create file " + path.str()); - return osp; -} - -static std::string -format_tv(struct timeval* tv) -{ - std::ostringstream output; - output << static_cast< long >(tv->tv_sec) << '.' - << std::setfill('0') << std::setw(6) - << static_cast< long >(tv->tv_usec); - return output.str(); -} - -// ------------------------------------------------------------------------ -// The "writer" interface. -// ------------------------------------------------------------------------ - -//! -//! \brief A base class that defines an output format. -//! -//! The writer base class defines a generic interface to output formats. -//! This is meant to be subclassed, and each subclass can redefine any -//! method to format the information as it wishes. -//! -//! This class is not tied to a output stream nor a file because, depending -//! on the output format, we will want to write to a single file or to -//! multiple ones. -//! -class writer { -public: - writer(void) {} - virtual ~writer(void) {} - - virtual void write_info(const std::string&, const std::string&) {} - virtual void write_ntps(size_t) {} - virtual void write_tp_start(const std::string&, size_t) {} - virtual void write_tp_end(struct timeval*, const std::string&) {} - virtual void write_tc_start(const std::string&) {} - virtual void write_tc_stdout_line(const std::string&) {} - virtual void write_tc_stderr_line(const std::string&) {} - virtual void write_tc_end(const std::string&, struct timeval*, - const std::string&) {} - virtual void write_eof(void) {} -}; - -// ------------------------------------------------------------------------ -// The "csv_writer" class. -// ------------------------------------------------------------------------ - -//! -//! \brief A very simple plain-text output format. -//! -//! The csv_writer class implements a very simple plain-text output -//! format that summarizes the results of each executed test case. The -//! results are meant to be easily parseable by third-party tools, hence -//! they are formatted as a CSV file. -//! -class csv_writer : public writer { - ostream_ptr m_os; - bool m_failed; - - std::string m_tpname; - std::string m_tcname; - -public: - csv_writer(const tools::fs::path& p) : - m_os(open_outfile(p)) - { - } - - virtual - void - write_tp_start(const std::string& name, - size_t ntcs ATF_DEFS_ATTRIBUTE_UNUSED) - { - m_tpname = name; - m_failed = false; - } - - virtual - void - write_tp_end(struct timeval* tv, const std::string& reason) - { - const std::string timestamp = format_tv(tv); - - if (!reason.empty()) - (*m_os) << "tp, " << timestamp << ", " << m_tpname << ", bogus, " - << reason << "\n"; - else if (m_failed) - (*m_os) << "tp, " << timestamp << ", "<< m_tpname << ", failed\n"; - else - (*m_os) << "tp, " << timestamp << ", "<< m_tpname << ", passed\n"; - } - - virtual - void - write_tc_start(const std::string& name) - { - m_tcname = name; - } - - virtual - void - write_tc_end(const std::string& state, struct timeval* tv, - const std::string& reason) - { - std::string str = m_tpname + ", " + m_tcname + ", " + state; - if (!reason.empty()) - str += ", " + reason; - (*m_os) << "tc, " << format_tv(tv) << ", " << str << "\n"; - - if (state == "failed") - m_failed = true; - } -}; - -// ------------------------------------------------------------------------ -// The "ticker_writer" class. -// ------------------------------------------------------------------------ - -//! -//! \brief A console-friendly output format. -//! -//! The ticker_writer class implements a formatter that is user-friendly -//! in the sense that it shows the execution of test cases in an easy to -//! read format. It is not meant to be parseable and its format can -//! freely change across releases. -//! -class ticker_writer : public writer { - ostream_ptr m_os; - - size_t m_curtp, m_ntps; - size_t m_tcs_passed, m_tcs_failed, m_tcs_skipped, m_tcs_expected_failures; - std::string m_tcname, m_tpname; - std::vector< std::string > m_failed_tcs; - std::map< std::string, std::string > m_expected_failures_tcs; - std::vector< std::string > m_failed_tps; - - void - write_info(const std::string& what, const std::string& val) - { - if (what == "tests.root") { - (*m_os) << "Tests root: " << val << "\n\n"; - } - } - - void - write_ntps(size_t ntps) - { - m_curtp = 1; - m_tcs_passed = 0; - m_tcs_failed = 0; - m_tcs_skipped = 0; - m_tcs_expected_failures = 0; - m_ntps = ntps; - } - - void - write_tp_start(const std::string& tp, size_t ntcs) - { - using tools::text::to_string; - using tools::ui::format_text; - - m_tpname = tp; - - (*m_os) << format_text(tp + " (" + to_string(m_curtp) + - "/" + to_string(m_ntps) + "): " + - to_string(ntcs) + " test cases") - << "\n"; - (*m_os).flush(); - } - - void - write_tp_end(struct timeval* tv, const std::string& reason) - { - using tools::ui::format_text_with_tag; - - m_curtp++; - - if (!reason.empty()) { - (*m_os) << format_text_with_tag("BOGUS TEST PROGRAM: Cannot " - "trust its results because " - "of `" + reason + "'", - m_tpname + ": ", false) - << "\n"; - m_failed_tps.push_back(m_tpname); - } - (*m_os) << "[" << format_tv(tv) << "s]\n\n"; - (*m_os).flush(); - - m_tpname.clear(); - } - - void - write_tc_start(const std::string& tcname) - { - m_tcname = tcname; - - (*m_os) << " " + tcname + ": "; - (*m_os).flush(); - } - - void - write_tc_end(const std::string& state, struct timeval* tv, - const std::string& reason) - { - std::string str; - - (*m_os) << "[" << format_tv(tv) << "s] "; - - if (state == "expected_death" || state == "expected_exit" || - state == "expected_failure" || state == "expected_signal" || - state == "expected_timeout") { - str = "Expected failure: " + reason; - m_tcs_expected_failures++; - m_expected_failures_tcs[m_tpname + ":" + m_tcname] = reason; - } else if (state == "failed") { - str = "Failed: " + reason; - m_tcs_failed++; - m_failed_tcs.push_back(m_tpname + ":" + m_tcname); - } else if (state == "passed") { - str = "Passed."; - m_tcs_passed++; - } else if (state == "skipped") { - str = "Skipped: " + reason; - m_tcs_skipped++; - } else - std::abort(); - - // XXX Wrap text. format_text_with_tag does not currently allow - // to specify the current column, which is needed because we have - // already printed the tc's name. - (*m_os) << str << '\n'; - - m_tcname = ""; - } - - static void - write_expected_failures(const std::map< std::string, std::string >& xfails, - std::ostream& os) - { - using tools::ui::format_text; - using tools::ui::format_text_with_tag; - - os << format_text("Test cases for known bugs:") << "\n"; - - for (std::map< std::string, std::string >::const_iterator iter = - xfails.begin(); iter != xfails.end(); iter++) { - const std::string& name = (*iter).first; - const std::string& reason = (*iter).second; - - os << format_text_with_tag(reason, " " + name + ": ", false) - << "\n"; - } - } - - void - write_eof(void) - { - using tools::text::join; - using tools::text::to_string; - using tools::ui::format_text; - using tools::ui::format_text_with_tag; - - if (!m_failed_tps.empty()) { - (*m_os) << format_text("Failed (bogus) test programs:") - << "\n"; - (*m_os) << format_text_with_tag(join(m_failed_tps, ", "), - " ", false) << "\n\n"; - } - - if (!m_expected_failures_tcs.empty()) { - write_expected_failures(m_expected_failures_tcs, *m_os); - (*m_os) << "\n"; - } - - if (!m_failed_tcs.empty()) { - (*m_os) << format_text("Failed test cases:") << "\n"; - (*m_os) << format_text_with_tag(join(m_failed_tcs, ", "), - " ", false) << "\n\n"; - } - - (*m_os) << format_text("Summary for " + to_string(m_ntps) + - " test programs:") << "\n"; - (*m_os) << format_text_with_tag(to_string(m_tcs_passed) + - " passed test cases.", - " ", false) << "\n"; - (*m_os) << format_text_with_tag(to_string(m_tcs_failed) + - " failed test cases.", - " ", false) << "\n"; - (*m_os) << format_text_with_tag(to_string(m_tcs_expected_failures) + - " expected failed test cases.", - " ", false) << "\n"; - (*m_os) << format_text_with_tag(to_string(m_tcs_skipped) + - " skipped test cases.", - " ", false) << "\n"; - } - -public: - ticker_writer(const tools::fs::path& p) : - m_os(open_outfile(p)) - { - } -}; - -// ------------------------------------------------------------------------ -// The "xml" class. -// ------------------------------------------------------------------------ - -//! -//! \brief A single-file XML output format. -//! -//! The xml_writer class implements a formatter that prints the results -//! of test cases in an XML format easily parseable later on by other -//! utilities. -//! -class xml_writer : public writer { - ostream_ptr m_os; - - std::string m_tcname, m_tpname; - - static - std::string - attrval(const std::string& str) - { - return str; - } - - static - std::string - elemval(const std::string& str) - { - std::ostringstream buf; - for (std::string::const_iterator iter = str.begin(); - iter != str.end(); iter++) { - const int character = static_cast< unsigned char >(*iter); - if (character == '&') { - buf << "&"; - } else if (character == '<') { - buf << "<"; - } else if (character == '>') { - buf << ">"; - } else if (std::isalnum(character) || std::ispunct(character) || - std::isspace(character)) { - buf << static_cast< char >(character); - } else { - buf << "&#" << character << ";"; - } - } - return buf.str(); - } - - void - write_info(const std::string& what, const std::string& val) - { - (*m_os) << "<info class=\"" << what << "\">" << val << "</info>\n"; - } - - void - write_tp_start(const std::string& tp, - size_t ntcs ATF_DEFS_ATTRIBUTE_UNUSED) - { - (*m_os) << "<tp id=\"" << attrval(tp) << "\">\n"; - } - - void - write_tp_end(struct timeval* tv, const std::string& reason) - { - if (!reason.empty()) - (*m_os) << "<failed>" << elemval(reason) << "</failed>\n"; - (*m_os) << "<tp-time>" << format_tv(tv) << "</tp-time>"; - (*m_os) << "</tp>\n"; - } - - void - write_tc_start(const std::string& tcname) - { - (*m_os) << "<tc id=\"" << attrval(tcname) << "\">\n"; - } - - void - write_tc_stdout_line(const std::string& line) - { - (*m_os) << "<so>" << elemval(line) << "</so>\n"; - } - - void - write_tc_stderr_line(const std::string& line) - { - (*m_os) << "<se>" << elemval(line) << "</se>\n"; - } - - void - write_tc_end(const std::string& state, struct timeval* tv, - const std::string& reason) - { - std::string str; - - if (state == "expected_death" || state == "expected_exit" || - state == "expected_failure" || state == "expected_signal" || - state == "expected_timeout") { - (*m_os) << "<" << state << ">" << elemval(reason) - << "</" << state << ">\n"; - } else if (state == "passed") { - (*m_os) << "<passed />\n"; - } else if (state == "failed") { - (*m_os) << "<failed>" << elemval(reason) << "</failed>\n"; - } else if (state == "skipped") { - (*m_os) << "<skipped>" << elemval(reason) << "</skipped>\n"; - } else - std::abort(); - (*m_os) << "<tc-time>" << format_tv(tv) << "</tc-time>"; - (*m_os) << "</tc>\n"; - } - - void - write_eof(void) - { - (*m_os) << "</tests-results>\n"; - } - -public: - xml_writer(const tools::fs::path& p) : - m_os(open_outfile(p)) - { - (*m_os) << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" - << "<!DOCTYPE tests-results PUBLIC " - "\"-//NetBSD//DTD ATF Tests Results 0.1//EN\" " - "\"http://www.NetBSD.org/XML/atf/tests-results.dtd\">\n\n" - "<tests-results>\n"; - } -}; - -// ------------------------------------------------------------------------ -// The "converter" class. -// ------------------------------------------------------------------------ - -//! -//! \brief A reader that redirects events to multiple writers. -//! -//! The converter class implements an atf_tps_reader that, for each event -//! raised by the parser, redirects it to multiple writers so that they -//! can reformat it according to their output rules. -//! -class converter : public tools::atf_report::atf_tps_reader { - typedef std::vector< writer* > outs_vector; - outs_vector m_outs; - - void - got_info(const std::string& what, const std::string& val) - { - for (outs_vector::iterator iter = m_outs.begin(); - iter != m_outs.end(); iter++) - (*iter)->write_info(what, val); - } - - void - got_ntps(size_t ntps) - { - for (outs_vector::iterator iter = m_outs.begin(); - iter != m_outs.end(); iter++) - (*iter)->write_ntps(ntps); - } - - void - got_tp_start(const std::string& tp, size_t ntcs) - { - for (outs_vector::iterator iter = m_outs.begin(); - iter != m_outs.end(); iter++) - (*iter)->write_tp_start(tp, ntcs); - } - - void - got_tp_end(struct timeval* tv, const std::string& reason) - { - for (outs_vector::iterator iter = m_outs.begin(); - iter != m_outs.end(); iter++) - (*iter)->write_tp_end(tv, reason); - } - - void - got_tc_start(const std::string& tcname) - { - for (outs_vector::iterator iter = m_outs.begin(); - iter != m_outs.end(); iter++) - (*iter)->write_tc_start(tcname); - } - - void - got_tc_stdout_line(const std::string& line) - { - for (outs_vector::iterator iter = m_outs.begin(); - iter != m_outs.end(); iter++) - (*iter)->write_tc_stdout_line(line); - } - - void - got_tc_stderr_line(const std::string& line) - { - for (outs_vector::iterator iter = m_outs.begin(); - iter != m_outs.end(); iter++) - (*iter)->write_tc_stderr_line(line); - } - - void - got_tc_end(const std::string& state, struct timeval* tv, - const std::string& reason) - { - for (outs_vector::iterator iter = m_outs.begin(); - iter != m_outs.end(); iter++) - (*iter)->write_tc_end(state, tv, reason); - } - - void - got_eof(void) - { - for (outs_vector::iterator iter = m_outs.begin(); - iter != m_outs.end(); iter++) - (*iter)->write_eof(); - } - -public: - converter(std::istream& is) : - tools::atf_report::atf_tps_reader(is) - { - } - - ~converter(void) - { - for (outs_vector::iterator iter = m_outs.begin(); - iter != m_outs.end(); iter++) - delete *iter; - } - - void - add_output(const std::string& fmt, const tools::fs::path& p) - { - if (fmt == "csv") { - m_outs.push_back(new csv_writer(p)); - } else if (fmt == "ticker") { - m_outs.push_back(new ticker_writer(p)); - } else if (fmt == "xml") { - m_outs.push_back(new xml_writer(p)); - } else - throw std::runtime_error("Unknown format `" + fmt + "'"); - } -}; - -// ------------------------------------------------------------------------ -// The "atf_report" class. -// ------------------------------------------------------------------------ - -class atf_report : public tools::application::app { - static const char* m_description; - - typedef std::pair< std::string, tools::fs::path > fmt_path_pair; - std::vector< fmt_path_pair > m_oflags; - - void process_option(int, const char*); - options_set specific_options(void) const; - -public: - atf_report(void); - - int main(void); -}; - -const char* atf_report::m_description = - "atf-report is a tool that parses the output of atf-run and " - "generates user-friendly reports in multiple different formats."; - -atf_report::atf_report(void) : - app(m_description, "atf-report(1)", "atf(7)") -{ -} - -void -atf_report::process_option(int ch, const char* arg) -{ - switch (ch) { - case 'o': - { - std::string str(arg); - std::string::size_type pos = str.find(':'); - if (pos == std::string::npos) - throw std::runtime_error("Syntax error in -o option"); - else { - std::string fmt = str.substr(0, pos); - tools::fs::path path = tools::fs::path(str.substr(pos + 1)); - m_oflags.push_back(fmt_path_pair(fmt, path)); - } - } - break; - - default: - std::abort(); - } -} - -atf_report::options_set -atf_report::specific_options(void) - const -{ - using tools::application::option; - options_set opts; - opts.insert(option('o', "fmt:path", "Adds a new output file; multiple " - "ones can be specified, and a - " - "path means stdout")); - return opts; -} - -int -atf_report::main(void) -{ - if (m_argc > 0) - throw std::runtime_error("No arguments allowed"); - - if (m_oflags.empty()) - m_oflags.push_back(fmt_path_pair("ticker", tools::fs::path("-"))); - - // Look for path duplicates. - std::set< tools::fs::path > paths; - for (std::vector< fmt_path_pair >::const_iterator iter = m_oflags.begin(); - iter != m_oflags.end(); iter++) { - tools::fs::path p = (*iter).second; - if (p == tools::fs::path("/dev/stdout")) - p = tools::fs::path("-"); - if (paths.find(p) != paths.end()) - throw std::runtime_error("The file `" + p.str() + "' was " - "specified more than once"); - paths.insert((*iter).second); - } - - // Generate the output files. - converter cnv(std::cin); - for (std::vector< fmt_path_pair >::const_iterator iter = m_oflags.begin(); - iter != m_oflags.end(); iter++) - cnv.add_output((*iter).first, (*iter).second); - cnv.read(); - - return EXIT_SUCCESS; -} - -int -main(int argc, char* const* argv) -{ - return atf_report().run(argc, argv); -} diff --git a/tools/atf-report_test.sh b/tools/atf-report_test.sh deleted file mode 100755 index 9f0f47f..0000000 --- a/tools/atf-report_test.sh +++ /dev/null @@ -1,449 +0,0 @@ -# -# Automated Testing Framework (atf) -# -# Copyright (c) 2007 The NetBSD Foundation, Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 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. -# - -create_helpers() -{ - mkdir dir1 - cp $(atf_get_srcdir)/pass_helper dir1/tp1 - cp $(atf_get_srcdir)/fail_helper dir1/tp2 - cp $(atf_get_srcdir)/pass_helper tp3 - cp $(atf_get_srcdir)/fail_helper tp4 - - cat >tp5 <<EOF -#! $(atf-config -t atf_shell) -echo foo -EOF - chmod +x tp5 - - cat >Atffile <<EOF -Content-Type: application/X-atf-atffile; version="1" - -prop: test-suite = atf - -tp: dir1 -tp: tp3 -tp: tp4 -tp: tp5 -EOF - - cat >dir1/Atffile <<EOF -Content-Type: application/X-atf-atffile; version="1" - -prop: test-suite = atf - -tp: tp1 -tp: tp2 -EOF -} - -run_helpers() -{ - mkdir etc - cat >etc/atf-run.hooks <<EOF -#! $(atf-config -t atf_shell) - -info_start_hook() -{ - atf_tps_writer_info "startinfo" "A value" -} - -info_end_hook() -{ - atf_tps_writer_info "endinfo" "Another value" -} -EOF - echo "Using atf-run to run helpers" - ATF_CONFDIR=$(pwd)/etc atf-run >tps.out 2>/dev/null - rm -rf etc -} - -atf_test_case default -default_head() -{ - atf_set "descr" "Checks that the default output uses the ticker" \ - "format" -} -default_body() -{ - create_helpers - run_helpers - - # Check that the default output uses the ticker format. - atf_check -s eq:0 -o match:'test cases' -o match:'Failed test cases' \ - -o match:'Summary for' -e empty -x 'atf-report <tps.out' -} - -# XXX The test for all expect_ values should be intermixed with the other -# tests. However, to do that, we need to migrate to using C helpers for -# simplicity in raising signals... -atf_test_case expect -expect_body() -{ - ln -s "$(atf_get_srcdir)/expect_helpers" . - cat >Atffile <<EOF -Content-Type: application/X-atf-atffile; version="1" - -prop: test-suite = atf - -tp: expect_helpers -EOF - run_helpers - -# NO_CHECK_STYLE_BEGIN - cat >expout <<EOF -tc, #.#, expect_helpers, death_and_exit, expected_death, Exit case -tc, #.#, expect_helpers, death_and_signal, expected_death, Signal case -tc, #.#, expect_helpers, death_but_pass, failed, Test case was expected to terminate abruptly but it continued execution -tc, #.#, expect_helpers, exit_any_and_exit, expected_exit, Call will exit -tc, #.#, expect_helpers, exit_but_pass, failed, Test case was expected to exit cleanly but it continued execution -tc, #.#, expect_helpers, exit_code_and_exit, expected_exit, Call will exit -tc, #.#, expect_helpers, fail_and_fail_check, expected_failure, And fail again: 2 checks failed as expected; see output for more details -tc, #.#, expect_helpers, fail_and_fail_requirement, expected_failure, Fail reason: The failure -tc, #.#, expect_helpers, fail_but_pass, failed, Test case was expecting a failure but none were raised -tc, #.#, expect_helpers, pass_and_pass, passed -tc, #.#, expect_helpers, pass_but_fail_check, failed, 1 checks failed; see output for more details -tc, #.#, expect_helpers, pass_but_fail_requirement, failed, Some reason -tc, #.#, expect_helpers, signal_any_and_signal, expected_signal, Call will signal -tc, #.#, expect_helpers, signal_but_pass, failed, Test case was expected to receive a termination signal but it continued execution -tc, #.#, expect_helpers, signal_no_and_signal, expected_signal, Call will signal -tc, #.#, expect_helpers, timeout_and_hang, expected_timeout, Will overrun -tc, #.#, expect_helpers, timeout_but_pass, failed, Test case was expected to hang but it continued execution -tp, #.#, expect_helpers, failed -EOF -# NO_CHECK_STYLE_END - atf_check -s eq:0 -o file:expout -e empty -x \ - "atf-report -o csv:- <tps.out | " \ - "sed -E -e 's/[0-9]+.[0-9]{6}, /#.#, /'" - -# NO_CHECK_STYLE_BEGIN - cat >expout <<EOF -expect_helpers (1/1): 17 test cases - death_and_exit: [#.#s] Expected failure: Exit case - death_and_signal: [#.#s] Expected failure: Signal case - death_but_pass: [#.#s] Failed: Test case was expected to terminate abruptly but it continued execution - exit_any_and_exit: [#.#s] Expected failure: Call will exit - exit_but_pass: [#.#s] Failed: Test case was expected to exit cleanly but it continued execution - exit_code_and_exit: [#.#s] Expected failure: Call will exit - fail_and_fail_check: [#.#s] Expected failure: And fail again: 2 checks failed as expected; see output for more details - fail_and_fail_requirement: [#.#s] Expected failure: Fail reason: The failure - fail_but_pass: [#.#s] Failed: Test case was expecting a failure but none were raised - pass_and_pass: [#.#s] Passed. - pass_but_fail_check: [#.#s] Failed: 1 checks failed; see output for more details - pass_but_fail_requirement: [#.#s] Failed: Some reason - signal_any_and_signal: [#.#s] Expected failure: Call will signal - signal_but_pass: [#.#s] Failed: Test case was expected to receive a termination signal but it continued execution - signal_no_and_signal: [#.#s] Expected failure: Call will signal - timeout_and_hang: [#.#s] Expected failure: Will overrun - timeout_but_pass: [#.#s] Failed: Test case was expected to hang but it continued execution -[#.#s] - -Test cases for known bugs: - expect_helpers:death_and_exit: Exit case - expect_helpers:death_and_signal: Signal case - expect_helpers:exit_any_and_exit: Call will exit - expect_helpers:exit_code_and_exit: Call will exit - expect_helpers:fail_and_fail_check: And fail again: 2 checks failed as expected; see output for more details - expect_helpers:fail_and_fail_requirement: Fail reason: The failure - expect_helpers:signal_any_and_signal: Call will signal - expect_helpers:signal_no_and_signal: Call will signal - expect_helpers:timeout_and_hang: Will overrun - -Failed test cases: - expect_helpers:death_but_pass, expect_helpers:exit_but_pass, expect_helpers:fail_but_pass, expect_helpers:pass_but_fail_check, expect_helpers:pass_but_fail_requirement, expect_helpers:signal_but_pass, expect_helpers:timeout_but_pass - -Summary for 1 test programs: - 1 passed test cases. - 7 failed test cases. - 9 expected failed test cases. - 0 skipped test cases. -EOF -# NO_CHECK_STYLE_END - atf_check -s eq:0 -o file:expout -e empty -x \ - "atf-report -o ticker:- <tps.out | " \ - "sed -E -e 's/[0-9]+.[0-9]{6}/#.#/'" - - # Just ensure that this does not crash for now... - atf_check -s eq:0 -o ignore -e empty -x "atf-report -o xml:- <tps.out" -} - -atf_test_case oflag -oflag_head() -{ - atf_set "descr" "Checks that the -o flag works" -} -oflag_body() -{ - create_helpers - run_helpers - - # Get the default output. - atf_check -s eq:0 -o save:stdout -e empty -x 'atf-report <tps.out' - mv stdout defout - - # Check that changing the stdout output works. - atf_check -s eq:0 -o save:stdout -e empty -x 'atf-report -o csv:- <tps.out' - atf_check -s eq:1 -o empty -e empty cmp -s defout stdout - cp stdout expcsv - - # Check that sending the output to a file does not write to stdout. - atf_check -s eq:0 -o empty -e empty -x 'atf-report -o csv:fmt.out <tps.out' - atf_check -s eq:0 -o empty -e empty cmp -s expcsv fmt.out - rm -f fmt.out - - # Check that defining two outputs using the same format works. - atf_check -s eq:0 -o empty -e empty -x \ - 'atf-report -o csv:fmt.out -o csv:fmt2.out <tps.out' - atf_check -s eq:0 -o empty -e empty cmp -s expcsv fmt.out - atf_check -s eq:0 -o empty -e empty cmp -s fmt.out fmt2.out - rm -f fmt.out fmt2.out - - # Check that defining two outputs using different formats works. - atf_check -s eq:0 -o empty -e empty -x \ - 'atf-report -o csv:fmt.out -o ticker:fmt2.out <tps.out' - atf_check -s eq:0 -o empty -e empty cmp -s expcsv fmt.out - atf_check -s eq:1 -o empty -e empty cmp -s fmt.out fmt2.out - atf_check -s eq:0 -o ignore -e empty grep "test cases" fmt2.out - atf_check -s eq:0 -o ignore -e empty grep "Failed test cases" fmt2.out - atf_check -s eq:0 -o ignore -e empty grep "Summary for" fmt2.out - rm -f fmt.out fmt2.out - - # Check that defining two outputs over the same file does not work. - atf_check -s eq:1 -o empty -e match:'more than once' -x \ - 'atf-report -o csv:fmt.out -o ticker:fmt.out <tps.out' - rm -f fmt.out - - # Check that defining two outputs over stdout (but using different - # paths) does not work. - atf_check -s eq:1 -o empty -e match:'more than once' -x \ - 'atf-report -o csv:- -o ticker:/dev/stdout <tps.out' - rm -f fmt.out -} - -atf_test_case output_csv -output_csv_head() -{ - atf_set "descr" "Checks the CSV output format" -} -output_csv_body() -{ - create_helpers - run_helpers - -# NO_CHECK_STYLE_BEGIN - cat >expout <<EOF -tc, #.#, dir1/tp1, main, passed -tp, #.#, dir1/tp1, passed -tc, #.#, dir1/tp2, main, failed, This always fails -tp, #.#, dir1/tp2, failed -tc, #.#, tp3, main, passed -tp, #.#, tp3, passed -tc, #.#, tp4, main, failed, This always fails -tp, #.#, tp4, failed -tp, #.#, tp5, bogus, Invalid format for test case list: 1: Unexpected token \`<<NEWLINE>>'; expected \`:' -EOF -# NO_CHECK_STYLE_END - - atf_check -s eq:0 -o file:expout -e empty -x \ - "atf-report -o csv:- <tps.out | sed -E -e 's/[0-9]+.[0-9]{6}, /#.#, /'" -} - -atf_test_case output_ticker -output_ticker_head() -{ - atf_set "descr" "Checks the ticker output format" -} -output_ticker_body() -{ - create_helpers - run_helpers - -# NO_CHECK_STYLE_BEGIN - cat >expout <<EOF -dir1/tp1 (1/5): 1 test cases - main: [#.#s] Passed. -[#.#s] - -dir1/tp2 (2/5): 1 test cases - main: [#.#s] Failed: This always fails -[#.#s] - -tp3 (3/5): 1 test cases - main: [#.#s] Passed. -[#.#s] - -tp4 (4/5): 1 test cases - main: [#.#s] Failed: This always fails -[#.#s] - -tp5 (5/5): 0 test cases -tp5: BOGUS TEST PROGRAM: Cannot trust its results because of \`Invalid format for test case list: 1: Unexpected token \`<<NEWLINE>>'; expected \`:'' -[#.#s] - -Failed (bogus) test programs: - tp5 - -Failed test cases: - dir1/tp2:main, tp4:main - -Summary for 5 test programs: - 2 passed test cases. - 2 failed test cases. - 0 expected failed test cases. - 0 skipped test cases. -EOF - - atf_check -s eq:0 -o file:expout -e empty -x \ - "atf-report -o ticker:- <tps.out | sed -E -e 's/[0-9]+.[0-9]{6}/#.#/'" -} -# NO_CHECK_STYLE_END - -atf_test_case output_xml -output_xml_head() -{ - atf_set "descr" "Checks the XML output format" -} -output_xml_body() -{ - create_helpers - run_helpers - -# NO_CHECK_STYLE_BEGIN - cat >expout <<EOF -<?xml version="1.0" encoding="ISO-8859-1"?> -<!DOCTYPE tests-results PUBLIC "-//NetBSD//DTD ATF Tests Results 0.1//EN" "http://www.NetBSD.org/XML/atf/tests-results.dtd"> - -<tests-results> -<info class="startinfo">A value</info> -<tp id="dir1/tp1"> -<tc id="main"> -<passed /> -<tc-time>#.#</tc-time></tc> -<tp-time>#.#</tp-time></tp> -<tp id="dir1/tp2"> -<tc id="main"> -<failed>This always fails</failed> -<tc-time>#.#</tc-time></tc> -<tp-time>#.#</tp-time></tp> -<tp id="tp3"> -<tc id="main"> -<passed /> -<tc-time>#.#</tc-time></tc> -<tp-time>#.#</tp-time></tp> -<tp id="tp4"> -<tc id="main"> -<failed>This always fails</failed> -<tc-time>#.#</tc-time></tc> -<tp-time>#.#</tp-time></tp> -<tp id="tp5"> -<failed>Invalid format for test case list: 1: Unexpected token \`<<NEWLINE>>'; expected \`:'</failed> -<tp-time>#.#</tp-time></tp> -<info class="endinfo">Another value</info> -</tests-results> -EOF -# NO_CHECK_STYLE_END - - atf_check -s eq:0 -o file:expout -e empty -x \ - "atf-report -o xml:- < tps.out | sed -E -e 's/>[0-9]+.[0-9]{6}</>#.#</'" -} - -atf_test_case output_xml_space -output_xml_space_head() -{ - atf_set "descr" "Checks that the XML output format properly preserves" \ - "leading and trailing whitespace in stdout and stderr" \ - "lines" -} -output_xml_space_body() -{ - export TESTCASE=diff - cp $(atf_get_srcdir)/misc_helpers . - cat >Atffile <<EOF -Content-Type: application/X-atf-atffile; version="1" - -prop: test-suite = atf - -tp: misc_helpers -EOF - -# NO_CHECK_STYLE_BEGIN - cat >expout <<EOF -<?xml version="1.0" encoding="ISO-8859-1"?> -<!DOCTYPE tests-results PUBLIC "-//NetBSD//DTD ATF Tests Results 0.1//EN" "http://www.NetBSD.org/XML/atf/tests-results.dtd"> - -<tests-results> -<info class="startinfo">A value</info> -<tp id="misc_helpers"> -<tc id="diff"> -<so>--- a 2007-11-04 14:00:41.000000000 +0100</so> -<so>+++ b 2007-11-04 14:00:48.000000000 +0100</so> -<so>@@ -1,7 +1,7 @@</so> -<so> This test is meant to simulate a diff.</so> -<so> Blank space at beginning of context lines must be preserved.</so> -<so> </so> -<so>-First original line.</so> -<so>-Second original line.</so> -<so>+First modified line.</so> -<so>+Second modified line.</so> -<so> </so> -<so> EOF</so> -<passed /> -<tc-time>#.#</tc-time></tc> -<tp-time>#.#</tp-time></tp> -<info class="endinfo">Another value</info> -</tests-results> -EOF -# NO_CHECK_STYLE_END - - run_helpers - atf_check -s eq:0 -o file:expout -e empty -x \ - "atf-report -o xml:- <tps.out | sed -E -e 's/>[0-9]+.[0-9]{6}</>#.#</'" -} - -atf_test_case too_many_args -too_many_args_body() -{ - cat >experr <<EOF -atf-report: ERROR: No arguments allowed -EOF - atf_check -s eq:1 -o empty -e file:experr atf-report foo -} - -atf_init_test_cases() -{ - atf_add_test_case default - atf_add_test_case expect - atf_add_test_case oflag - atf_add_test_case output_csv - atf_add_test_case output_ticker - atf_add_test_case output_xml - atf_add_test_case output_xml_space - atf_add_test_case too_many_args -} - -# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/tools/atf-run.1 b/tools/atf-run.1 deleted file mode 100644 index d593f47..0000000 --- a/tools/atf-run.1 +++ /dev/null @@ -1,202 +0,0 @@ -.\" -.\" Automated Testing Framework (atf) -.\" -.\" Copyright (c) 2007 The NetBSD Foundation, Inc. -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.Dd November 1, 2010 -.Dt ATF-RUN 1 -.Os -.Sh NAME -.Nm atf-run -.Nd executes a collection of test programs -.Sh SYNOPSIS -.Nm -.Op Fl v Ar var1=value1 Op .. Fl v Ar varN=valueN -.Op Ar test_program1 Op Ar .. test_programN -.Nm -.Fl h -.Sh DESCRIPTION -.Nm -executes a collection of test programs or, in other words, a complete -test suite. -The results of each test program are collected by the tool, and are then -multiplexed into a single machine-parseable report; see -.Xr atf-formats 5 -for more details. -This report can later be transformed into many different and saner formats -using the -.Nm atf-report -tool. -.Pp -The list of test programs to execute is read from an -.Pa Atffile -present in the current directory. -This file describes the test suite stored in the directory it lives in, -which aside from the list of test programs also includes meta-data and -configuration variables. -.Pp -.Nm -is also in charge of reading the configuration files that tune the behavior -of each test program and passing down the necessary variables to them. -More details on how this is done are given in the -.Sx Configuration -section. -.Pp -In the first synopsis form, -.Nm -parses the -.Pa Atffile -in the current directory and runs all the test programs specified in it. -If any test program names are given as part of the command line, those are -the ones executed instead of the complete list. -.Pp -In the second synopsis form, -.Nm -will print information about all supported options and their purpose. -.Pp -The following options are available: -.Bl -tag -width XvXvarXvalueXX -.It Fl h -Shows a short summary of all available options and their purpose. -.It Fl v Ar var=value -Sets the configuration variable -.Ar var -to the given value -.Ar value . -.El -.Ss Configuration -.Nm -reads configuration data from multiple places. -After all of these places have been analyzed, a list of variable-value -pairs are passed to the test programs to be run. -.Pp -The following locations are scanned for configuration data, in order. -Items down the list override values defined above them: -.Bl -enum -.It -Configuration variables defined in the -.Pa Atffile . -.It -Configuration variables defined in the system-wide configuration file -shared among all test suites. -This lives in -.Pa ${ATF_CONFDIR}/common.conf . -.It -Configuration variables defined in the system-wide test-suite-specific -configuration file. -This lives in -.Pa ${ATF_CONFDIR}/<test-suite>.conf . -.It -Configuration variables defined in the user-specific configuration file -shared among all test suites. -This lives in -.Pa ${HOME}/.atf/common.conf . -.It -Configuration variables defined in the user-specific test-suite-specific -configuration file. -This lives in -.Pa ${HOME}/.atf/<test-suite>.conf . -.It -Configuration variables provided as part of the command line through the -.Fl v -option. -.El -.Pp -The value of -.Va ATF_CONFDIR -in the above list determined as detailed in -.Xr atf-config 1 . -.Pp -The following configuration variables are globally recognized: -.Bl -tag -width XunprivilegedXuserXX -.It Va unprivileged-user -The name of the system user that atf-run will drop root privileges into -for test cases defining -.Sq require.user=unprivileged . -Note that this is -.Em not provided for security purposes ; -this feature is only for the convenience of the user. -.El -.Ss Hooks -.Nm Ns 's -internal behavior can be customized by the system administrator and the -user by means of hooks. -These hooks are written in the shell script language for simplicity and -are stored in the following files, which are read in the order provided -below: -.Bl -enum -.It -${ATF_CONFDIR}/atf-run.hooks -.It -${HOME}/.atf/atf-run.hooks -.El -.Pp -The following hooks are supported: -.Bl -tag -width infoXstartXhookXX -.It info_start_hook -Called before -.Nm -executes any test program. -The purpose of this hook is to write additional -.Sq info -stanzas to the top of the output report; these are defined by the -.Sq application/X-atf-tps format -described in -.Xr atf-formats 5 . -Always use the -.Sq atf_tps_writer_info -function to print these. -.Pp -This takes no parameters. -.It info_end_hook -Similar to -.Sq info_start_hook -but executed after all test programs have been run so that additional -.Sq info -stanzas can be added to the bottom of the output report. -.Pp -This takes no parameters. -.El -.Pp -All hooks are accompanied by a function named -.Sq default_<hook_name> -that can be executed by them to invoke the default behavior built into -.Nm . -For example, in order to extend the default -.Sq info_start_hook -hook, we could write the following function: -.Bd -literal -offset indent -info_start_hook() -{ - default_info_start_hook "${@}" - - atf_tps_writer_info "uptime" "$(uptime)" -} -.Ed -.Sh SEE ALSO -.Xr atf-report 1 , -.Xr atf-test-program 1 , -.Xr atf 7 diff --git a/tools/atf-run.cpp b/tools/atf-run.cpp deleted file mode 100644 index 3bc6f63..0000000 --- a/tools/atf-run.cpp +++ /dev/null @@ -1,567 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if defined(HAVE_CONFIG_H) -#include "bconfig.h" -#endif - -extern "C" { -#include <sys/types.h> -#include <sys/param.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <unistd.h> -} - -#include <algorithm> -#include <cassert> -#include <cerrno> -#include <cstdlib> -#include <cstring> -#include <fstream> -#include <iostream> -#include <map> -#include <string> - -#include "application.hpp" -#include "atffile.hpp" -#include "config.hpp" -#include "config_file.hpp" -#include "env.hpp" -#include "exceptions.hpp" -#include "fs.hpp" -#include "parser.hpp" -#include "process.hpp" -#include "requirements.hpp" -#include "test-program.hpp" -#include "text.hpp" - -namespace { - -typedef std::map< std::string, std::string > vars_map; - -} // anonymous namespace - -#if defined(MAXCOMLEN) -static const std::string::size_type max_core_name_length = MAXCOMLEN; -#else -static const std::string::size_type max_core_name_length = std::string::npos; -#endif - -class atf_run : public tools::application::app { - static const char* m_description; - - vars_map m_cmdline_vars; - - static vars_map::value_type parse_var(const std::string&); - - void process_option(int, const char*); - std::string specific_args(void) const; - options_set specific_options(void) const; - - void parse_vflag(const std::string&); - - std::vector< std::string > conf_args(void) const; - - size_t count_tps(std::vector< std::string >) const; - - int run_test(const tools::fs::path&, tools::test_program::atf_tps_writer&, - const vars_map&); - int run_test_directory(const tools::fs::path&, - tools::test_program::atf_tps_writer&); - int run_test_program(const tools::fs::path&, - tools::test_program::atf_tps_writer&, - const vars_map&); - - tools::test_program::test_case_result get_test_case_result( - const std::string&, const tools::process::status&, - const tools::fs::path&) const; - -public: - atf_run(void); - - int main(void); -}; - -static void -sanitize_gdb_env(void) -{ - try { - tools::env::unset("TERM"); - } catch (...) { - // Just swallow exceptions here; they cannot propagate into C, which - // is where this function is called from, and even if these exceptions - // appear they are benign. - } -} - -static void -dump_stacktrace(const tools::fs::path& tp, const tools::process::status& s, - const tools::fs::path& workdir, - tools::test_program::atf_tps_writer& w) -{ - assert(s.signaled() && s.coredump()); - - w.stderr_tc("Test program crashed; attempting to get stack trace"); - - const tools::fs::path corename = workdir / - (tp.leaf_name().substr(0, max_core_name_length) + ".core"); - if (!tools::fs::exists(corename)) { - w.stderr_tc("Expected file " + corename.str() + " not found"); - return; - } - - const tools::fs::path gdb(GDB); - const tools::fs::path gdbout = workdir / "gdb.out"; - const tools::process::argv_array args(gdb.leaf_name().c_str(), "-batch", - "-q", "-ex", "bt", tp.c_str(), - corename.c_str(), NULL); - tools::process::status status = tools::process::exec( - gdb, args, - tools::process::stream_redirect_path(gdbout), - tools::process::stream_redirect_path(tools::fs::path("/dev/null")), - sanitize_gdb_env); - if (!status.exited() || status.exitstatus() != EXIT_SUCCESS) { - w.stderr_tc("Execution of " GDB " failed"); - return; - } - - std::ifstream input(gdbout.c_str()); - if (input) { - std::string line; - while (std::getline(input, line).good()) - w.stderr_tc(line); - input.close(); - } - - w.stderr_tc("Stack trace complete"); -} - -const char* atf_run::m_description = - "atf-run is a tool that runs tests programs and collects their " - "results."; - -atf_run::atf_run(void) : - app(m_description, "atf-run(1)", "atf(7)") -{ -} - -void -atf_run::process_option(int ch, const char* arg) -{ - switch (ch) { - case 'v': - parse_vflag(arg); - break; - - default: - std::abort(); - } -} - -std::string -atf_run::specific_args(void) - const -{ - return "[test-program1 .. test-programN]"; -} - -atf_run::options_set -atf_run::specific_options(void) - const -{ - using tools::application::option; - options_set opts; - opts.insert(option('v', "var=value", "Sets the configuration variable " - "`var' to `value'; overrides " - "values in configuration files")); - return opts; -} - -void -atf_run::parse_vflag(const std::string& str) -{ - if (str.empty()) - throw std::runtime_error("-v requires a non-empty argument"); - - std::vector< std::string > ws = tools::text::split(str, "="); - if (ws.size() == 1 && str[str.length() - 1] == '=') { - m_cmdline_vars[ws[0]] = ""; - } else { - if (ws.size() != 2) - throw std::runtime_error("-v requires an argument of the form " - "var=value"); - - m_cmdline_vars[ws[0]] = ws[1]; - } -} - -int -atf_run::run_test(const tools::fs::path& tp, - tools::test_program::atf_tps_writer& w, - const vars_map& config) -{ - tools::fs::file_info fi(tp); - - int errcode; - if (fi.get_type() == tools::fs::file_info::dir_type) - errcode = run_test_directory(tp, w); - else { - const vars_map effective_config = - tools::config_file::merge_configs(config, m_cmdline_vars); - - errcode = run_test_program(tp, w, effective_config); - } - return errcode; -} - -int -atf_run::run_test_directory(const tools::fs::path& tp, - tools::test_program::atf_tps_writer& w) -{ - tools::atffile af = tools::read_atffile(tp / "Atffile"); - - vars_map test_suite_vars; - { - vars_map::const_iterator iter = af.props().find("test-suite"); - assert(iter != af.props().end()); - test_suite_vars = tools::config_file::read_config_files((*iter).second); - } - - bool ok = true; - for (std::vector< std::string >::const_iterator iter = af.tps().begin(); - iter != af.tps().end(); iter++) { - const bool result = run_test(tp / *iter, w, - tools::config_file::merge_configs(af.conf(), test_suite_vars)); - ok &= (result == EXIT_SUCCESS); - } - - return ok ? EXIT_SUCCESS : EXIT_FAILURE; -} - -tools::test_program::test_case_result -atf_run::get_test_case_result(const std::string& broken_reason, - const tools::process::status& s, - const tools::fs::path& resfile) - const -{ - using tools::text::to_string; - using tools::test_program::read_test_case_result; - using tools::test_program::test_case_result; - - if (!broken_reason.empty()) { - test_case_result tcr; - - try { - tcr = read_test_case_result(resfile); - - if (tcr.state() == "expected_timeout") { - return tcr; - } else { - return test_case_result("failed", -1, broken_reason); - } - } catch (const std::runtime_error&) { - return test_case_result("failed", -1, broken_reason); - } - } - - if (s.exited()) { - test_case_result tcr; - - try { - tcr = read_test_case_result(resfile); - } catch (const std::runtime_error& e) { - return test_case_result("failed", -1, "Test case exited " - "normally but failed to create the results file: " + - std::string(e.what())); - } - - if (tcr.state() == "expected_death") { - return tcr; - } else if (tcr.state() == "expected_exit") { - if (tcr.value() == -1 || s.exitstatus() == tcr.value()) - return tcr; - else - return test_case_result("failed", -1, "Test case was " - "expected to exit with a " + to_string(tcr.value()) + - " error code but returned " + to_string(s.exitstatus())); - } else if (tcr.state() == "expected_failure") { - if (s.exitstatus() == EXIT_SUCCESS) - return tcr; - else - return test_case_result("failed", -1, "Test case returned an " - "error in expected_failure mode but it should not have"); - } else if (tcr.state() == "expected_signal") { - return test_case_result("failed", -1, "Test case exited cleanly " - "but was expected to receive a signal"); - } else if (tcr.state() == "failed") { - if (s.exitstatus() == EXIT_SUCCESS) - return test_case_result("failed", -1, "Test case " - "exited successfully but reported failure"); - else - return tcr; - } else if (tcr.state() == "passed") { - if (s.exitstatus() == EXIT_SUCCESS) - return tcr; - else - return test_case_result("failed", -1, "Test case exited as " - "passed but reported an error"); - } else if (tcr.state() == "skipped") { - if (s.exitstatus() == EXIT_SUCCESS) - return tcr; - else - return test_case_result("failed", -1, "Test case exited as " - "skipped but reported an error"); - } - } else if (s.signaled()) { - test_case_result tcr; - - try { - tcr = read_test_case_result(resfile); - } catch (const std::runtime_error&) { - return test_case_result("failed", -1, "Test program received " - "signal " + tools::text::to_string(s.termsig()) + - (s.coredump() ? " (core dumped)" : "")); - } - - if (tcr.state() == "expected_death") { - return tcr; - } else if (tcr.state() == "expected_signal") { - if (tcr.value() == -1 || s.termsig() == tcr.value()) - return tcr; - else - return test_case_result("failed", -1, "Test case was " - "expected to exit due to a " + to_string(tcr.value()) + - " signal but got " + to_string(s.termsig())); - } else { - return test_case_result("failed", -1, "Test program received " - "signal " + tools::text::to_string(s.termsig()) + - (s.coredump() ? " (core dumped)" : "") + " and created a " - "bogus results file"); - } - } - std::abort(); - return test_case_result(); -} - -int -atf_run::run_test_program(const tools::fs::path& tp, - tools::test_program::atf_tps_writer& w, - const vars_map& config) -{ - int errcode = EXIT_SUCCESS; - - tools::test_program::metadata md; - try { - md = tools::test_program::get_metadata(tp, config); - } catch (const tools::parser::format_error& e) { - w.start_tp(tp.str(), 0); - w.end_tp("Invalid format for test case list: " + std::string(e.what())); - return EXIT_FAILURE; - } catch (const tools::parser::parse_errors& e) { - const std::string reason = tools::text::join(e, "; "); - w.start_tp(tp.str(), 0); - w.end_tp("Invalid format for test case list: " + reason); - return EXIT_FAILURE; - } - - tools::fs::temp_dir resdir( - tools::fs::path(tools::config::get("atf_workdir")) / "atf-run.XXXXXX"); - - w.start_tp(tp.str(), md.test_cases.size()); - if (md.test_cases.empty()) { - w.end_tp("Bogus test program: reported 0 test cases"); - errcode = EXIT_FAILURE; - } else { - for (std::map< std::string, vars_map >::const_iterator iter - = md.test_cases.begin(); iter != md.test_cases.end(); iter++) { - const std::string& tcname = (*iter).first; - const vars_map& tcmd = (*iter).second; - - w.start_tc(tcname); - - try { - const std::string& reqfail = tools::check_requirements( - tcmd, config); - if (!reqfail.empty()) { - w.end_tc("skipped", reqfail); - continue; - } - } catch (const std::runtime_error& e) { - w.end_tc("failed", e.what()); - errcode = EXIT_FAILURE; - continue; - } - - const std::pair< int, int > user = tools::get_required_user( - tcmd, config); - - tools::fs::path resfile = resdir.get_path() / "tcr"; - assert(!tools::fs::exists(resfile)); - try { - const bool has_cleanup = tools::text::to_bool( - (*tcmd.find("has.cleanup")).second); - - tools::fs::temp_dir workdir(tools::fs::path(tools::config::get( - "atf_workdir")) / "atf-run.XXXXXX"); - if (user.first != -1 && user.second != -1) { - if (::chown(workdir.get_path().c_str(), user.first, - user.second) == -1) { - throw tools::system_error("chown(" + - workdir.get_path().str() + ")", "chown(2) failed", - errno); - } - resfile = workdir.get_path() / "tcr"; - } - - std::pair< std::string, const tools::process::status > s = - tools::test_program::run_test_case( - tp, tcname, "body", tcmd, config, - resfile, workdir.get_path(), w); - if (s.second.signaled() && s.second.coredump()) - dump_stacktrace(tp, s.second, workdir.get_path(), w); - if (has_cleanup) - (void)tools::test_program::run_test_case( - tp, tcname, "cleanup", tcmd, - config, resfile, workdir.get_path(), w); - - // TODO: Force deletion of workdir. - - tools::test_program::test_case_result tcr = - get_test_case_result(s.first, s.second, resfile); - - w.end_tc(tcr.state(), tcr.reason()); - if (tcr.state() == "failed") - errcode = EXIT_FAILURE; - } catch (...) { - if (tools::fs::exists(resfile)) - tools::fs::remove(resfile); - throw; - } - if (tools::fs::exists(resfile)) - tools::fs::remove(resfile); - - } - w.end_tp(""); - } - - return errcode; -} - -size_t -atf_run::count_tps(std::vector< std::string > tps) - const -{ - size_t ntps = 0; - - for (std::vector< std::string >::const_iterator iter = tps.begin(); - iter != tps.end(); iter++) { - tools::fs::path tp(*iter); - tools::fs::file_info fi(tp); - - if (fi.get_type() == tools::fs::file_info::dir_type) { - tools::atffile af = tools::read_atffile(tp / "Atffile"); - std::vector< std::string > aux = af.tps(); - for (std::vector< std::string >::iterator i2 = aux.begin(); - i2 != aux.end(); i2++) - *i2 = (tp / *i2).str(); - ntps += count_tps(aux); - } else - ntps++; - } - - return ntps; -} - -static -void -call_hook(const std::string& tool, const std::string& hook) -{ - const tools::fs::path sh(tools::config::get("atf_shell")); - const tools::fs::path hooks = - tools::fs::path(tools::config::get("atf_pkgdatadir")) / (tool + ".hooks"); - - const tools::process::status s = - tools::process::exec(sh, - tools::process::argv_array(sh.c_str(), hooks.c_str(), - hook.c_str(), NULL), - tools::process::stream_inherit(), - tools::process::stream_inherit()); - - - if (!s.exited() || s.exitstatus() != EXIT_SUCCESS) - throw std::runtime_error("Failed to run the '" + hook + "' hook " - "for '" + tool + "'"); -} - -int -atf_run::main(void) -{ - tools::atffile af = tools::read_atffile(tools::fs::path("Atffile")); - - std::vector< std::string > tps; - tps = af.tps(); - if (m_argc >= 1) { - // TODO: Ensure that the given test names are listed in the - // Atffile. Take into account that the file can be using globs. - tps.clear(); - for (int i = 0; i < m_argc; i++) - tps.push_back(m_argv[i]); - } - - // Read configuration data for this test suite. - vars_map test_suite_vars; - { - vars_map::const_iterator iter = af.props().find("test-suite"); - assert(iter != af.props().end()); - test_suite_vars = tools::config_file::read_config_files((*iter).second); - } - - tools::test_program::atf_tps_writer w(std::cout); - call_hook("atf-run", "info_start_hook"); - w.ntps(count_tps(tps)); - - bool ok = true; - for (std::vector< std::string >::const_iterator iter = tps.begin(); - iter != tps.end(); iter++) { - const bool result = run_test(tools::fs::path(*iter), w, - tools::config_file::merge_configs(af.conf(), test_suite_vars)); - ok &= (result == EXIT_SUCCESS); - } - - call_hook("atf-run", "info_end_hook"); - - return ok ? EXIT_SUCCESS : EXIT_FAILURE; -} - -int -main(int argc, char* const* argv) -{ - return atf_run().run(argc, argv); -} diff --git a/tools/atf-run_test.sh b/tools/atf-run_test.sh deleted file mode 100755 index afd013e..0000000 --- a/tools/atf-run_test.sh +++ /dev/null @@ -1,1134 +0,0 @@ -# -# Automated Testing Framework (atf) -# -# Copyright (c) 2007 The NetBSD Foundation, Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 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. -# - -create_atffile() -{ - ATF_CONFDIR="$(pwd)"; export ATF_CONFDIR - - cat >Atffile <<EOF -Content-Type: application/X-atf-atffile; version="1" - -prop: test-suite = atf - -EOF - for f in "${@}"; do - echo "tp: ${f}" >>Atffile - done -} - -create_helper() -{ - cp $(atf_get_srcdir)/misc_helpers helper - create_atffile helper - TESTCASE=${1}; export TESTCASE -} - -create_helper_stdin() -{ - # TODO: This really, really, really must use real test programs. - cat >${1} <<EOF -#! $(atf-config -t atf_shell) -while [ \${#} -gt 0 ]; do - case \${1} in - -l) - echo 'Content-Type: application/X-atf-tp; version="1"' - echo -EOF - cnt=1 - while [ ${cnt} -le ${2} ]; do - echo "echo 'ident: tc${cnt}'" >>${1} - [ ${cnt} -lt ${2} ] && echo "echo" >>${1} - cnt=$((${cnt} + 1)) - done -cat >>${1} <<EOF - exit 0 - ;; - -r*) - resfile=\$(echo \${1} | cut -d r -f 2-) - ;; - esac - testcase=\$(echo \${1} | cut -d : -f 1) - shift -done -EOF - cat >>${1} -} - -create_mount_helper() -{ - cat >${1} <<EOF -#! /usr/bin/env atf-sh - -do_mount() { - platform=\$(uname) - case \${platform} in - Linux|NetBSD) - mount -t tmpfs tmpfs \${1} || atf_fail "Mount failed" - ;; - FreeBSD) - mdmfs -s 16m md \${1} || atf_fail "Mount failed" - ;; - SunOS) - mount -F tmpfs tmpfs \$(pwd)/\${1} || atf_fail "Mount failed" - ;; - *) - atf_fail "create_mount_helper called for an unsupported platform." - ;; - esac -} - -atf_test_case main -main_head() { - atf_set "require.user" "root" -} -main_body() { -EOF - cat >>${1} - cat >>${1} <<EOF -} - -atf_init_test_cases() -{ - atf_add_test_case main -} -EOF -} - -atf_test_case no_warnings -no_warnings_head() -{ - atf_set "descr" "Tests that atf-run suppresses warnings about not running" \ - "within atf-run" -} -no_warnings_body() -{ - create_helper pass - atf_check -s eq:0 -o ignore -e not-match:'WARNING.*atf-run' atf-run helper -} - -atf_test_case config -config_head() -{ - atf_set "descr" "Tests that the config files are read in the correct" \ - "order" -} -config_body() -{ - create_helper config - - mkdir etc - mkdir .atf - - echo "First: read system-wide common.conf." - cat >etc/common.conf <<EOF -Content-Type: application/X-atf-config; version="1" - -1st = "sw common" -2nd = "sw common" -3rd = "sw common" -4th = "sw common" -EOF - atf_check -s eq:0 \ - -o match:'1st: sw common' \ - -o match:'2nd: sw common' \ - -o match:'3rd: sw common' \ - -o match:'4th: sw common' \ - -e ignore -x \ - "ATF_CONFDIR=$(pwd)/etc HOME=$(pwd) atf-run helper" - - echo "Second: read system-wide <test-suite>.conf." - cat >etc/atf.conf <<EOF -Content-Type: application/X-atf-config; version="1" - -1st = "sw atf" -EOF - atf_check -s eq:0 \ - -o match:'1st: sw atf' \ - -o match:'2nd: sw common' \ - -o match:'3rd: sw common' \ - -o match:'4th: sw common' \ - -e ignore -x \ - "ATF_CONFDIR=$(pwd)/etc HOME=$(pwd) atf-run helper" - - echo "Third: read user-specific common.conf." - cat >.atf/common.conf <<EOF -Content-Type: application/X-atf-config; version="1" - -2nd = "us common" -EOF - atf_check -s eq:0 \ - -o match:'1st: sw atf' \ - -o match:'2nd: us common' \ - -o match:'3rd: sw common' \ - -o match:'4th: sw common' \ - -e ignore -x \ - "ATF_CONFDIR=$(pwd)/etc HOME=$(pwd) atf-run helper" - - echo "Fourth: read user-specific <test-suite>.conf." - cat >.atf/atf.conf <<EOF -Content-Type: application/X-atf-config; version="1" - -3rd = "us atf" -EOF - atf_check -s eq:0 \ - -o match:'1st: sw atf' \ - -o match:'2nd: us common' \ - -o match:'3rd: us atf' \ - -o match:'4th: sw common' \ - -e ignore -x \ - "ATF_CONFDIR=$(pwd)/etc HOME=$(pwd) atf-run helper" -} - -atf_test_case vflag -vflag_head() -{ - atf_set "descr" "Tests that the -v flag works and that it properly" \ - "overrides the values in configuration files" -} -vflag_body() -{ - create_helper testvar - - echo "Checking that 'testvar' is not defined." - atf_check -s eq:1 -o ignore -e ignore -x \ - "ATF_CONFDIR=$(pwd)/etc atf-run helper" - - echo "Checking that defining 'testvar' trough '-v' works." - atf_check -s eq:0 -o match:'testvar: a value' -e ignore -x \ - "ATF_CONFDIR=$(pwd)/etc atf-run -v testvar='a value' helper" - - echo "Checking that defining 'testvar' trough the configuration" \ - "file works." - mkdir etc - cat >etc/common.conf <<EOF -Content-Type: application/X-atf-config; version="1" - -testvar = "value in conf file" -EOF - atf_check -s eq:0 -o match:'testvar: value in conf file' -e ignore -x \ - "ATF_CONFDIR=$(pwd)/etc atf-run helper" - - echo "Checking that defining 'testvar' trough -v overrides the" \ - "configuration file." - atf_check -s eq:0 -o match:'testvar: a value' -e ignore -x \ - "ATF_CONFDIR=$(pwd)/etc atf-run -v testvar='a value' helper" -} - -atf_test_case atffile -atffile_head() -{ - atf_set "descr" "Tests that the variables defined by the Atffile" \ - "are recognized and that they take the lowest priority" -} -atffile_body() -{ - create_helper testvar - - echo "Checking that 'testvar' is not defined." - atf_check -s eq:1 -o ignore -e ignore -x \ - "ATF_CONFDIR=$(pwd)/etc atf-run helper" - - echo "Checking that defining 'testvar' trough the Atffile works." - echo 'conf: testvar = "a value"' >>Atffile - atf_check -s eq:0 -o match:'testvar: a value' -e ignore -x \ - "ATF_CONFDIR=$(pwd)/etc atf-run helper" - - echo "Checking that defining 'testvar' trough the configuration" \ - "file overrides the one in the Atffile." - mkdir etc - cat >etc/common.conf <<EOF -Content-Type: application/X-atf-config; version="1" - -testvar = "value in conf file" -EOF - atf_check -s eq:0 -o match:'testvar: value in conf file' -e ignore -x \ - "ATF_CONFDIR=$(pwd)/etc atf-run helper" - rm -rf etc - - echo "Checking that defining 'testvar' trough -v overrides the" \ - "one in the Atffile." - atf_check -s eq:0 -o match:'testvar: new value' -e ignore -x \ - "ATF_CONFDIR=$(pwd)/etc atf-run -v testvar='new value' helper" -} - -atf_test_case atffile_recursive -atffile_recursive_head() -{ - atf_set "descr" "Tests that variables defined by an Atffile are not" \ - "inherited by other Atffiles." -} -atffile_recursive_body() -{ - create_helper testvar - - mkdir dir - mv Atffile helper dir - - echo "Checking that 'testvar' is not inherited." - create_atffile dir - echo 'conf: testvar = "a value"' >> Atffile - atf_check -s eq:1 -o ignore -e ignore -x "ATF_CONFDIR=$(pwd)/etc atf-run" - - echo "Checking that defining 'testvar' in the correct Atffile works." - echo 'conf: testvar = "a value"' >>dir/Atffile - atf_check -s eq:0 -o match:'testvar: a value' -e ignore -x \ - "ATF_CONFDIR=$(pwd)/etc atf-run" -} - -atf_test_case fds -fds_head() -{ - atf_set "descr" "Tests that all streams are properly captured" -} -fds_body() -{ - create_helper fds - - atf_check -s eq:0 \ - -o match:'^tc-so:msg1 to stdout$' \ - -o match:'^tc-so:msg2 to stdout$' \ - -o match:'^tc-se:msg1 to stderr$' \ - -o match:'^tc-se:msg2 to stderr$' \ - -e empty atf-run -} - -atf_test_case mux_streams -mux_streams_head() -{ - atf_set "descr" "Tests for a race condition in stream multiplexing" -} -mux_streams_body() -{ - create_helper mux_streams - - for i in 1 2 3 4 5; do - echo "Attempt ${i}" - atf_check -s eq:0 -o match:'stdout 9999' -o match:'stderr 9999' atf-run - done -} - -atf_test_case expect -expect_head() -{ - atf_set "descr" "Tests the processing of test case results and the" \ - "expect features" -} -expect_body() -{ - ln -s "$(atf_get_srcdir)/expect_helpers" . - create_atffile expect_helpers - - atf_check -s eq:1 \ - -o match:'death_and_exit, expected_death' \ - -o match:'death_and_signal, expected_death' \ - -o match:'death_but_pass, failed' \ - -o match:'exit_any_and_exit, expected_exit' \ - -o match:'exit_but_pass, failed' \ - -o match:'exit_code_and_exit, expected_exit' \ - -o match:'fail_and_fail_check, expected_failure' \ - -o match:'fail_and_fail_requirement, expected_failure' \ - -o match:'fail_but_pass, failed' \ - -o match:'pass_and_pass, passed' \ - -o match:'pass_but_fail_check, failed' \ - -o match:'pass_but_fail_requirement, failed' \ - -o match:'signal_any_and_signal, expected_signal' \ - -o match:'signal_but_pass, failed' \ - -o match:'signal_no_and_signal, expected_signal' \ - -o match:'timeout_and_hang, expected_timeout' \ - -o match:'timeout_but_pass, failed' \ - -e empty atf-run -} - -atf_test_case missing_results -missing_results_head() -{ - atf_set "descr" "Ensures that atf-run correctly handles test cases that " \ - "do not create the results file" -} -missing_results_body() -{ - create_helper_stdin helper 1 <<EOF -test -f \${resfile} && echo "resfile found" -exit 0 -EOF - chmod +x helper - - create_atffile helper - - re='^tc-end: [0-9][0-9]*\.[0-9]*, tc1,' - atf_check -s eq:1 \ - -o match:"${re} failed,.*failed to create" \ - -o not-match:'resfile found' \ - -e empty atf-run -} - -atf_test_case broken_results -broken_results_head() -{ - atf_set "descr" "Ensures that atf-run reports test programs that" \ - "provide a bogus results output as broken programs" -} -broken_results_body() -{ - # We produce two errors from the header to ensure that the parse - # errors are printed on a single line on the output file. Printing - # them on separate lines would be incorrect. - create_helper_stdin helper 1 <<EOF -echo 'line 1' >\${resfile} -echo 'line 2' >>\${resfile} -exit 0 -EOF - chmod +x helper - - create_atffile helper - - re='^tc-end: [0-9][0-9]*\.[0-9]*, tc1,' - atf_check -s eq:1 -o match:"${re} .*line 1.*line 2" -e empty atf-run -} - -atf_test_case broken_tp_list -broken_tp_list_head() -{ - atf_set "descr" "Ensures that atf-run reports test programs that" \ - "provide a bogus test case list" -} -broken_tp_list_body() -{ - cat >helper <<EOF -#! $(atf-config -t atf_shell) -while [ \${#} -gt 0 ]; do - if [ \${1} = -l ]; then - echo 'Content-Type: application/X-atf-tp; version="1"' - echo - echo 'foo: bar' - exit 0 - else - shift - fi -done -exit 0 -EOF - chmod +x helper - - create_atffile helper - - re='^tp-end: [0-9][0-9]*\.[0-9]*, helper,' - re="${re} Invalid format for test case list:.*First property.*ident" - atf_check -s eq:1 -o match:"${re}" -e empty atf-run -} - -atf_test_case zero_tcs -zero_tcs_head() -{ - atf_set "descr" "Ensures that atf-run reports test programs without" \ - "test cases as errors" -} -zero_tcs_body() -{ - create_helper_stdin helper 0 <<EOF -echo 'Content-Type: application/X-atf-tp; version="1"' -echo -exit 1 -EOF - chmod +x helper - - create_atffile helper - - re='^tp-end: [0-9][0-9]*\.[0-9]*, helper,' - atf_check -s eq:1 \ - -o match:"${re} .*Invalid format for test case list" \ - -e empty atf-run -} - -atf_test_case exit_codes -exit_codes_head() -{ - atf_set "descr" "Ensures that atf-run reports bogus exit codes for" \ - "programs correctly" -} -exit_codes_body() -{ - create_helper_stdin helper 1 <<EOF -echo "failed: Yes, it failed" >\${resfile} -exit 0 -EOF - chmod +x helper - - create_atffile helper - - re='^tc-end: [0-9][0-9]*\.[0-9]*, tc1,' - atf_check -s eq:1 \ - -o match:"${re} .*exited successfully.*reported failure" \ - -e empty atf-run -} - -atf_test_case signaled -signaled_head() -{ - atf_set "descr" "Ensures that atf-run reports test program's crashes" \ - "correctly regardless of their actual results" -} -signaled_body() -{ - create_helper_stdin helper 2 <<EOF -echo "passed" >\${resfile} -case \${testcase} in - tc1) ;; - tc2) echo "Killing myself!" ; kill -9 \$\$ ;; -esac -EOF - chmod +x helper - - create_atffile helper - - re='^tc-end: [0-9][0-9]*\.[0-9]*, tc2,' - atf_check -s eq:1 -o match:"${re} .*received signal 9" \ - -e empty atf-run -} - -atf_test_case hooks -hooks_head() -{ - atf_set "descr" "Checks that the default hooks work and that they" \ - "can be overriden by the user" -} -hooks_body() -{ - cp $(atf_get_srcdir)/pass_helper helper - create_atffile helper - - mkdir atf - mkdir .atf - - echo "Checking default hooks" - atf_check -s eq:0 -o match:'^info: time.start, ' \ - -o match:'^info: time.end, ' -e empty -x \ - "ATF_CONFDIR=$(pwd)/atf atf-run" - - echo "Checking the system-wide info_start hook" - cat >atf/atf-run.hooks <<EOF -info_start_hook() -{ - atf_tps_writer_info "test" "sw value" -} -EOF - atf_check -s eq:0 \ - -o match:'^info: test, sw value' \ - -o not-match:'^info: time.start, ' \ - -o match:'^info: time.end, ' \ - -e empty -x \ - "ATF_CONFDIR=$(pwd)/atf atf-run" - - echo "Checking the user-specific info_start hook" - cat >.atf/atf-run.hooks <<EOF -info_start_hook() -{ - atf_tps_writer_info "test" "user value" -} -EOF - atf_check -s eq:0 \ - -o match:'^info: test, user value' \ - -o not-match:'^info: time.start, ' \ - -o match:'^info: time.end, ' \ - -e empty -x \ - "ATF_CONFDIR=$(pwd)/atf atf-run" - - rm atf/atf-run.hooks - rm .atf/atf-run.hooks - - echo "Checking the system-wide info_end hook" - cat >atf/atf-run.hooks <<EOF -info_end_hook() -{ - atf_tps_writer_info "test" "sw value" -} -EOF - atf_check -s eq:0 \ - -o match:'^info: time.start, ' \ - -o not-match:'^info: time.end, ' \ - -o match:'^info: test, sw value' \ - -e empty -x \ - "ATF_CONFDIR=$(pwd)/atf atf-run" - - echo "Checking the user-specific info_end hook" - cat >.atf/atf-run.hooks <<EOF -info_end_hook() -{ - atf_tps_writer_info "test" "user value" -} -EOF - atf_check -s eq:0 \ - -o match:'^info: time.start, ' \ - -o not-match:'^info: time.end, ' \ - -o match:'^info: test, user value' \ - -e empty -x \ - "ATF_CONFDIR=$(pwd)/atf atf-run" -} - -atf_test_case isolation_env -isolation_env_head() -{ - atf_set "descr" "Tests that atf-run sets a set of environment variables" \ - "to known sane values" -} -isolation_env_body() -{ - undef_vars="LANG LC_ALL LC_COLLATE LC_CTYPE LC_MESSAGES LC_MONETARY \ - LC_NUMERIC LC_TIME" - def_vars="HOME TZ" - - mangleenv="env" - for v in ${undef_vars} ${def_vars}; do - mangleenv="${mangleenv} ${v}=bogus-value" - done - - create_helper env_list - create_atffile helper - - # We must ignore stderr in this call (instead of specifying -e empty) - # because, when atf-run invokes the shell to run the hooks, we may get - # error messages about an invalid locale. This happens, at least, when - # the shell is bash 4.x. - atf_check -s eq:0 -o save:stdout -e ignore ${mangleenv} atf-run helper - - for v in ${undef_vars}; do - atf_check -s eq:1 -o empty -e empty grep "^tc-so:${v}=" stdout - done - - for v in ${def_vars}; do - atf_check -s eq:0 -o ignore -e empty grep "^tc-so:${v}=" stdout - done - - atf_check -s eq:0 -o ignore -e empty grep "^tc-so:TZ=UTC" stdout -} - -atf_test_case isolation_home -isolation_home_head() -{ - atf_set "descr" "Tests that atf-run sets HOME to a sane and valid value" -} -isolation_home_body() -{ - create_helper env_home - create_atffile helper - atf_check -s eq:0 -o ignore -e ignore env HOME=foo atf-run helper -} - -atf_test_case isolation_stdin -isolation_stdin_head() -{ - atf_set "descr" "Tests that atf-run nullifies the stdin of test cases" -} -isolation_stdin_body() -{ - create_helper read_stdin - create_atffile helper - atf_check -s eq:0 -o ignore -e ignore -x 'echo hello world | atf-run helper' -} - -atf_test_case isolation_umask -isolation_umask_head() -{ - atf_set "descr" "Tests that atf-run sets the umask to a known value" -} -isolation_umask_body() -{ - create_helper umask - create_atffile helper - - atf_check -s eq:0 -o match:'umask: 0022' -e ignore -x \ - "umask 0000 && atf-run helper" -} - -atf_test_case cleanup_pass -cleanup_pass_head() -{ - atf_set "descr" "Tests that atf-run calls the cleanup routine of the test" \ - "case when the test case result is passed" -} -cleanup_pass_body() -{ - create_helper cleanup_states - create_atffile helper - - atf_check -s eq:0 -o match:'cleanup_states, passed' -e ignore atf-run \ - -v state=pass -v statedir=$(pwd) helper - test -f to-stay || atf_fail "Test case body did not run correctly" - if [ -f to-delete ]; then - atf_fail "Test case cleanup did not run correctly" - fi -} - -atf_test_case cleanup_fail -cleanup_fail_head() -{ - atf_set "descr" "Tests that atf-run calls the cleanup routine of the test" \ - "case when the test case result is failed" -} -cleanup_fail_body() -{ - create_helper cleanup_states - create_atffile helper - - atf_check -s eq:1 -o match:'cleanup_states, failed' -e ignore atf-run \ - -v state=fail -v statedir=$(pwd) helper - test -f to-stay || atf_fail "Test case body did not run correctly" - if [ -f to-delete ]; then - atf_fail "Test case cleanup did not run correctly" - fi -} - -atf_test_case cleanup_skip -cleanup_skip_head() -{ - atf_set "descr" "Tests that atf-run calls the cleanup routine of the test" \ - "case when the test case result is skipped" -} -cleanup_skip_body() -{ - create_helper cleanup_states - create_atffile helper - - atf_check -s eq:0 -o match:'cleanup_states, skipped' -e ignore atf-run \ - -v state=skip -v statedir=$(pwd) helper - test -f to-stay || atf_fail "Test case body did not run correctly" - if [ -f to-delete ]; then - atf_fail "Test case cleanup did not run correctly" - fi -} - -atf_test_case cleanup_curdir -cleanup_curdir_head() -{ - atf_set "descr" "Tests that atf-run calls the cleanup routine in the same" \ - "work directory as the body so that they can share data" -} -cleanup_curdir_body() -{ - create_helper cleanup_curdir - create_atffile helper - - atf_check -s eq:0 -o match:'cleanup_curdir, passed' \ - -o match:'Old value: 1234' -e ignore atf-run helper -} - -atf_test_case cleanup_signal -cleanup_signal_head() -{ - atf_set "descr" "Tests that atf-run calls the cleanup routine if it gets" \ - "a termination signal while running the body" -} -cleanup_signal_body() -{ - : # TODO: Write this. -} - -atf_test_case cleanup_mount -cleanup_mount_head() -{ - atf_set "descr" "Tests that the removal algorithm does not cross" \ - "mount points" - atf_set "require.user" "root" -} -cleanup_mount_body() -{ - ROOT="$(pwd)/root"; export ROOT - - create_mount_helper helper <<EOF -echo \$(pwd) >\${ROOT} -mkdir foo -mkdir foo/bar -mkdir foo/bar/mnt -do_mount foo/bar/mnt -mkdir foo/baz -do_mount foo/baz -mkdir foo/baz/foo -mkdir foo/baz/foo/bar -do_mount foo/baz/foo/bar -EOF - create_atffile helper - chmod +x helper - - platform=$(uname) - case ${platform} in - Linux|FreeBSD|NetBSD|SunOS) - ;; - *) - # XXX Possibly specify in meta-data too. - atf_skip "Test unimplemented in this platform (${platform})" - ;; - esac - - atf_check -s eq:0 -o match:"main, passed" -e ignore atf-run helper - mount | grep $(cat root) && atf_fail "Some file systems remain mounted" - atf_check -s eq:1 -o empty -e empty test -d $(cat root)/foo -} - -atf_test_case cleanup_symlink -cleanup_symlink_head() -{ - atf_set "descr" "Tests that the removal algorithm does not follow" \ - "symlinks, which may live in another device and thus" \ - "be treated as mount points" - atf_set "require.user" "root" -} -cleanup_symlink_body() -{ - ROOT="$(pwd)/root"; export ROOT - - create_mount_helper helper <<EOF -echo \$(pwd) >\${ROOT} -atf_check -s eq:0 -o empty -e empty mkdir foo -atf_check -s eq:0 -o empty -e empty mkdir foo/bar -do_mount foo/bar -atf_check -s eq:0 -o empty -e empty touch a -atf_check -s eq:0 -o empty -e empty ln -s "\$(pwd)/a" foo/bar -EOF - create_atffile helper - chmod +x helper - - platform=$(uname) - case ${platform} in - Linux|FreeBSD|NetBSD|SunOS) - ;; - *) - # XXX Possibly specify in meta-data too. - atf_skip "Test unimplemented in this platform (${platform})" - ;; - esac - - atf_check -s eq:0 -o match:"main, passed" -e ignore atf-run helper - mount | grep $(cat root) && atf_fail "Some file systems remain mounted" - atf_check -s eq:1 -o empty -e empty test -d $(cat root)/foo -} - -atf_test_case require_arch -require_arch_head() -{ - atf_set "descr" "Tests that atf-run validates the require.arch property" -} -require_arch_body() -{ - create_helper require_arch - create_atffile helper - - echo "Checking for the real architecture" - arch=$(atf-config -t atf_arch) - atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ - -v arch="${arch}" helper - atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ - -v arch="foo ${arch}" helper - atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ - -v arch="${arch} foo" helper - - echo "Checking for a fictitious architecture" - arch=fictitious - export ATF_ARCH=fictitious - atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ - -v arch="${arch}" helper - atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ - -v arch="foo ${arch}" helper - atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ - -v arch="${arch} foo" helper - - echo "Triggering some failures" - atf_check -s eq:0 -o match:"${TESTCASE}, skipped, .*foo.*architecture" \ - -e ignore atf-run -v arch="foo" helper - atf_check -s eq:0 \ - -o match:"${TESTCASE}, skipped, .*foo bar.*architectures" -e ignore \ - atf-run -v arch="foo bar" helper - atf_check -s eq:0 \ - -o match:"${TESTCASE}, skipped, .*fictitiousxxx.*architecture" \ - -e ignore atf-run -v arch="${arch}xxx" helper -} - -atf_test_case require_config -require_config_head() -{ - atf_set "descr" "Tests that atf-run validates the require.config property" -} -require_config_body() -{ - create_helper require_config - create_atffile helper - - atf_check -s eq:0 -o match:"${TESTCASE}, skipped, .*var1.*not defined" \ - -e ignore atf-run helper - atf_check -s eq:0 -o match:"${TESTCASE}, skipped, .*var2.*not defined" \ - -e ignore atf-run -v var1=foo helper - atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ - -v var1=a -v var2=' ' helper -} - -atf_test_case require_files -require_files_head() -{ - atf_set "descr" "Tests that atf-run validates the require.files property" -} -require_files_body() -{ - create_helper require_files - create_atffile helper - - touch i-exist - - echo "Checking absolute paths" - atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ - -v files='/bin/cp' helper - atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ - -v files="$(pwd)/i-exist" helper - atf_check -s eq:0 \ - -o match:"${TESTCASE}, skipped, .*/dont-exist" \ - -e ignore atf-run -v files="$(pwd)/i-exist $(pwd)/dont-exist" helper - - echo "Checking that relative paths are not allowed" - atf_check -s eq:1 \ - -o match:"${TESTCASE}, failed, Relative paths.*not allowed.*hello" \ - -e ignore atf-run -v files='hello' helper - atf_check -s eq:1 \ - -o match:"${TESTCASE}, failed, Relative paths.*not allowed.*a/b" \ - -e ignore atf-run -v files='a/b' helper -} - -atf_test_case require_machine -require_machine_head() -{ - atf_set "descr" "Tests that atf-run validates the require.machine property" -} -require_machine_body() -{ - create_helper require_machine - create_atffile helper - - echo "Checking for the real machine type" - machine=$(atf-config -t atf_machine) - atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ - -v machine="${machine}" helper - atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ - -v machine="foo ${machine}" helper - atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ - -v machine="${machine} foo" helper - - echo "Checking for a fictitious machine type" - machine=fictitious - export ATF_MACHINE=fictitious - atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ - -v machine="${machine}" helper - atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ - -v machine="foo ${machine}" helper - atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ - -v machine="${machine} foo" helper - - echo "Triggering some failures" - atf_check -s eq:0 -o match:"${TESTCASE}, skipped, .*foo.*machine type" \ - -e ignore atf-run -v machine="foo" helper - atf_check -s eq:0 \ - -o match:"${TESTCASE}, skipped, .*foo bar.*machine types" -e ignore \ - atf-run -v machine="foo bar" helper - atf_check -s eq:0 \ - -o match:"${TESTCASE}, skipped, .*fictitiousxxx.*machine type" \ - -e ignore atf-run -v machine="${machine}xxx" helper -} - -atf_test_case require_progs -require_progs_head() -{ - atf_set "descr" "Tests that atf-run validates the require.progs property" -} -require_progs_body() -{ - create_helper require_progs - create_atffile helper - - echo "Checking absolute paths" - atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ - -v progs='/bin/cp' helper - atf_check -s eq:0 \ - -o match:"${TESTCASE}, skipped, .*/bin/__non-existent__.*PATH" \ - -e ignore atf-run -v progs='/bin/__non-existent__' helper - - echo "Checking that relative paths are not allowed" - atf_check -s eq:1 \ - -o match:"${TESTCASE}, failed, Relative paths.*not allowed.*bin/cp" \ - -e ignore atf-run -v progs='bin/cp' helper - - echo "Check plain file names, searching them in the PATH." - atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ - -v progs='cp' helper - atf_check -s eq:0 \ - -o match:"${TESTCASE}, skipped, .*__non-existent__.*PATH" -e ignore \ - atf-run -v progs='__non-existent__' helper -} - -atf_test_case require_user_root -require_user_root_head() -{ - atf_set "descr" "Tests that atf-run validates the require.user property" \ - "when it is set to 'root'" -} -require_user_root_body() -{ - create_helper require_user - create_atffile helper - - if [ $(id -u) -eq 0 ]; then - exp=passed - else - exp=skipped - fi - atf_check -s eq:0 -o match:"${TESTCASE}, ${exp}" -e ignore atf-run \ - -v user=root helper -} - -atf_test_case require_user_unprivileged -require_user_unprivileged_head() -{ - atf_set "descr" "Tests that atf-run validates the require.user property" \ - "when it is set to 'root'" -} -require_user_unprivileged_body() -{ - create_helper require_user - create_atffile helper - - if [ $(id -u) -eq 0 ]; then - exp=skipped - else - exp=passed - fi - atf_check -s eq:0 -o match:"${TESTCASE}, ${exp}" -e ignore atf-run \ - -v user=unprivileged helper -} - -atf_test_case require_user_bad -require_user_bad_head() -{ - atf_set "descr" "Tests that atf-run validates the require.user property" \ - "when it is set to 'root'" -} -require_user_bad_body() -{ - create_helper require_user - create_atffile helper - - atf_check -s eq:1 -o match:"${TESTCASE}, failed, Invalid value.*foobar" \ - -e ignore atf-run -v user=foobar helper -} - -atf_test_case timeout -timeout_head() -{ - atf_set "descr" "Tests that atf-run kills a test case that times out" -} -timeout_body() -{ - create_helper timeout - create_atffile helper - - atf_check -s eq:1 \ - -o match:"${TESTCASE}, failed, .*timed out after 1 second" -e ignore \ - atf-run -v statedir=$(pwd) helper - if [ -f finished ]; then - atf_fail "Test case was not killed after time out" - fi -} - -atf_test_case timeout_forkexit -timeout_forkexit_head() -{ - atf_set "descr" "Tests that atf-run deals gracefully with a test program" \ - "that forks, exits, but the child process hangs" -} -timeout_forkexit_body() -{ - create_helper timeout_forkexit - create_atffile helper - - atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ - -v statedir=$(pwd) helper - test -f parent-finished || atf_fail "Parent did not exit as expected" - test -f child-finished && atf_fail "Subprocess exited but it should have" \ - "been forcibly terminated" || true -} - -atf_test_case ignore_deprecated_use_fs -ignore_deprecated_use_fs_head() -{ - atf_set "descr" "Tests that atf-run ignores the deprecated use.fs property" -} -ignore_deprecated_use_fs_body() -{ - create_helper use_fs - create_atffile helper - - atf_check -s eq:0 -o ignore -e ignore atf-run helper -} - -atf_init_test_cases() -{ - atf_add_test_case no_warnings - atf_add_test_case config - atf_add_test_case vflag - atf_add_test_case atffile - atf_add_test_case atffile_recursive - atf_add_test_case expect - atf_add_test_case fds - atf_add_test_case mux_streams - atf_add_test_case missing_results - atf_add_test_case broken_results - atf_add_test_case broken_tp_list - atf_add_test_case zero_tcs - atf_add_test_case exit_codes - atf_add_test_case signaled - atf_add_test_case hooks - atf_add_test_case isolation_env - atf_add_test_case isolation_home - atf_add_test_case isolation_stdin - atf_add_test_case isolation_umask - atf_add_test_case cleanup_pass - atf_add_test_case cleanup_fail - atf_add_test_case cleanup_skip - atf_add_test_case cleanup_curdir - atf_add_test_case cleanup_signal - atf_add_test_case cleanup_mount - atf_add_test_case cleanup_symlink - atf_add_test_case require_arch - atf_add_test_case require_config - atf_add_test_case require_files - atf_add_test_case require_machine - atf_add_test_case require_progs - atf_add_test_case require_user_root - atf_add_test_case require_user_unprivileged - atf_add_test_case require_user_bad - atf_add_test_case timeout - atf_add_test_case timeout_forkexit - atf_add_test_case ignore_deprecated_use_fs -} - -# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/tools/atf-version.1 b/tools/atf-version.1 deleted file mode 100644 index 136f13c..0000000 --- a/tools/atf-version.1 +++ /dev/null @@ -1,56 +0,0 @@ -.\" -.\" Automated Testing Framework (atf) -.\" -.\" Copyright (c) 2007 The NetBSD Foundation, Inc. -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.Dd September 16, 2007 -.Dt ATF-VERSION 1 -.Os -.Sh NAME -.Nm atf-version -.Nd shows information about the installed ATF version -.Sh SYNOPSIS -.Nm -.Nm -.Fl h -.Sh DESCRIPTION -.Nm -is a utility that prints information about the version of ATF currently -installed in the system. -.Pp -In the first synopsis form, -.Nm -shows the release version of the ATF package installed in the system (the -installation that corresponds to the instance of -.Nm -being executed) and also shows information related to the repository -revision used to build that package. -.Pp -In the second synopsis form, -.Nm -will print information about all supported options and their purpose. -.Sh SEE ALSO -.Xr atf 7 diff --git a/tools/atf-version.cpp b/tools/atf-version.cpp deleted file mode 100644 index 0a13e7e..0000000 --- a/tools/atf-version.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if defined(HAVE_CONFIG_H) -#include "bconfig.h" -#endif - -#include <cstdlib> -#include <iostream> - -#include "application.hpp" -#include "revision.h" -#include "ui.hpp" - -class atf_version : public tools::application::app { - static const char* m_description; - -public: - atf_version(void); - - int main(void); -}; - -const char* atf_version::m_description = - "atf-version is a tool that shows information about the currently " - "installed version of ATF."; - -atf_version::atf_version(void) : - app(m_description, "atf-version(1)", "atf(7)") -{ -} - -int -atf_version::main(void) -{ - using tools::ui::format_text; - using tools::ui::format_text_with_tag; - - std::cout << PACKAGE_STRING " (" PACKAGE_TARNAME "-" PACKAGE_VERSION - ")\n" PACKAGE_COPYRIGHT "\n\n"; - -#if defined(PACKAGE_REVISION_TYPE_DIST) - std::cout << format_text("Built from a distribution file; no revision " - "information available.") << "\n"; -#elif defined(PACKAGE_REVISION_TYPE_GIT) - std::cout << format_text_with_tag(PACKAGE_REVISION_BRANCH, "Branch: ", - false) << "\n"; - std::cout << format_text_with_tag(PACKAGE_REVISION_BASE -# if PACKAGE_REVISION_MODIFIED - " (locally modified)" -# endif - " " PACKAGE_REVISION_DATE, - "Base revision: ", false) << "\n"; -#else -# error "Unknown PACKAGE_REVISION_TYPE value" -#endif - - return EXIT_SUCCESS; -} - -int -main(int argc, char* const* argv) -{ - return atf_version().run(argc, argv); -} diff --git a/tools/atf.7.in b/tools/atf.7.in deleted file mode 100644 index b11054c..0000000 --- a/tools/atf.7.in +++ /dev/null @@ -1,192 +0,0 @@ -.\" -.\" Automated Testing Framework (atf) -.\" -.\" Copyright (c) 2007 The NetBSD Foundation, Inc. -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.Dd August 28, 2010 -.Dt ATF 7 -.Os -.Sh NAME -.Nm ATF -.Nd introduction to the Automated Testing Framework -.Sh DESCRIPTION -.Em IMPORTANT: If you are here because you want to know how to run the tests in -.Pa __TESTSDIR__ , -.Em you most likely want to read the -.Xr tests 7 -.Em manual page instead. -.Pp -The Automated Testing Framework -.Pf ( Nm ) -is a collection of libraries and utilities designed to ease unattended -application testing in the hands of developers and end users of a specific -piece of software. -.Pp -As regards developers, -.Nm -provides the necessary means to easily create -test suites composed of multiple test programs, which in turn are a -collection of test cases. -It also attempts to simplify the debugging of problems when these test -cases detect an error by providing as much information as possible -about the failure. -.Pp -As regards users, it simplifies the process of running the test suites and, -in special, encourages end users to run them often: they do not need to -have source trees around nor any other development tools installed to be -able to certify that a given piece of software works on their machine as -advertised. -.Pp -If your operating systems distributes -.Nm , -it is possible that it provides an introductory -.Xr tests 7 -manual page. -You are encouraged to read it now. -.Ss License -.Nm -is distributed under the terms of the TNF License, a 2-clause BSD license. -For more details please see: -.Bd -literal -offset indent -.Pa __DOCDIR__/COPYING -.Ed -.Ss Components -.Nm -is a highly modular piece of software. -It provides a couple of libraries to ease the implementation of test -programs: one for the C and C++ languages and another one for shell -scripts. -It also includes multiple small utilities that follow the principle of -doing a single thing but doing it right. -This section outlines which these components are. -.Pp -Public utilities: -.Bl -tag -width atfXtestXprogramXXXXX -.It Xr atf-check 1 -Executes a command and checks that its exit code, its standard output -and its standard error output match pre-specified expected values. -.It Xr atf-config 1 -Queries static configuration information. -.It Xr atf-report 1 -Converts the output of -.Nm atf-run -to user-friendly and/or machine-parseable reports. -.It Xr atf-run 1 -Automates the execution of a series of test programs and collects their -results in a unified report. -.It Xr atf-sh 1 -Shell interpreter for shell-based test programs. -.El -.Pp -Programming interfaces: -.Bl -tag -width atfXtestXprogramXXXXX -.It Xr atf-c-api 3 -C programming interface for test programs. -.It Xr atf-c++-api 3 -C++ programming interface for test programs. -.It Xr atf-sh-api 3 -POSIX shell programming interface for test programs. -.El -.Pp -Other: -.Bl -tag -width atfXtestXprogramXXXXX -.It Xr atf-formats 5 -Description of the machine-parseable data formats used by the tools. -.It Xr atf-test-case 4 -Generic description of test cases, independent of the language they are -implemented in. -.It Xr atf-test-program 1 -Common interface provided by the test programs written using the -.Nm -libraries. -.El -.Ss Recommended reading order -For end users wishing to run tests: -.Bl -enum -compact -.It -.Xr tests 7 -(only if provided by your operating system). -.It -.Xr atf-test-program 1 -.It -.Xr atf-run 1 -.It -.Xr atf-report 1 -.It -.Xr atf-config 1 -.El -.Pp -For developers wanting to write their own tests: -.Bl -enum -compact -.It -Everything recommended to users. -.It -.Xr atf-test-case 4 -.It -.Xr atf-c-api 3 -.It -.Xr atf-c++-api 3 -.It -.Xr atf-sh-api 3 -.It -.Xr atf-sh 1 -.It -.Xr atf-check 1 -.El -.Pp -For those interested in -.Nm -internals: -.Bl -enum -compact -.It -Everything recommended to users. -.It -Everything recommended to developers. -.It -.Xr atf-formats 5 -.El -.Sh SEE ALSO -.Xr tests 7 -.Sh HISTORY -.Nm -started as a Google Summer of Code 2007 project mentored by The NetBSD -Foundation. -Its original goal was to provide a testing framework for The NetBSD -Operating System, but it grew as an independent project because the -framework itself did not need to be tied to a specific operating system. -.Pp -For more details on this subject, please see: -.Bd -literal -offset indent -.Pa __DOCDIR__/NEWS -.Pa __DOCDIR__/ROADMAP -.Ed -.Sh AUTHORS -For more details on the people that made -.Nm -possible, please see: -.Bd -literal -offset indent -.Pa __DOCDIR__/AUTHORS -.Ed diff --git a/tools/atffile.cpp b/tools/atffile.cpp deleted file mode 100644 index b04c59e..0000000 --- a/tools/atffile.cpp +++ /dev/null @@ -1,348 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 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 <cassert> -#include <cstdlib> -#include <fstream> - -#include "atffile.hpp" -#include "defs.hpp" -#include "exceptions.hpp" -#include "expand.hpp" -#include "parser.hpp" - -namespace impl = tools; -namespace detail = tools::detail; - -namespace { - -typedef std::map< std::string, std::string > vars_map; - -} // anonymous namespace - -// ------------------------------------------------------------------------ -// The "atf_atffile" auxiliary parser. -// ------------------------------------------------------------------------ - -namespace atf_atffile { - -static const tools::parser::token_type eof_type = 0; -static const tools::parser::token_type nl_type = 1; -static const tools::parser::token_type text_type = 2; -static const tools::parser::token_type colon_type = 3; -static const tools::parser::token_type conf_type = 4; -static const tools::parser::token_type dblquote_type = 5; -static const tools::parser::token_type equal_type = 6; -static const tools::parser::token_type hash_type = 7; -static const tools::parser::token_type prop_type = 8; -static const tools::parser::token_type tp_type = 9; -static const tools::parser::token_type tp_glob_type = 10; - -class tokenizer : public tools::parser::tokenizer< std::istream > { -public: - tokenizer(std::istream& is, size_t curline) : - tools::parser::tokenizer< std::istream > - (is, true, eof_type, nl_type, text_type, curline) - { - add_delim(':', colon_type); - add_delim('=', equal_type); - add_delim('#', hash_type); - add_quote('"', dblquote_type); - add_keyword("conf", conf_type); - add_keyword("prop", prop_type); - add_keyword("tp", tp_type); - add_keyword("tp-glob", tp_glob_type); - } -}; - -} // namespace atf_atffile - -// ------------------------------------------------------------------------ -// The "atf_atffile_reader" class. -// ------------------------------------------------------------------------ - -detail::atf_atffile_reader::atf_atffile_reader(std::istream& is) : - m_is(is) -{ -} - -detail::atf_atffile_reader::~atf_atffile_reader(void) -{ -} - -void -detail::atf_atffile_reader::got_conf( - const std::string& name ATF_DEFS_ATTRIBUTE_UNUSED, - const std::string& val ATF_DEFS_ATTRIBUTE_UNUSED) -{ -} - -void -detail::atf_atffile_reader::got_prop( - const std::string& name ATF_DEFS_ATTRIBUTE_UNUSED, - const std::string& val ATF_DEFS_ATTRIBUTE_UNUSED) -{ -} - -void -detail::atf_atffile_reader::got_tp( - const std::string& name ATF_DEFS_ATTRIBUTE_UNUSED, - bool isglob ATF_DEFS_ATTRIBUTE_UNUSED) -{ -} - -void -detail::atf_atffile_reader::got_eof(void) -{ -} - -void -detail::atf_atffile_reader::read(void) -{ - using tools::parser::parse_error; - using namespace atf_atffile; - - std::pair< size_t, tools::parser::headers_map > hml = - tools::parser::read_headers(m_is, 1); - tools::parser::validate_content_type(hml.second, - "application/X-atf-atffile", 1); - - tokenizer tkz(m_is, hml.first); - tools::parser::parser< tokenizer > p(tkz); - - for (;;) { - try { - tools::parser::token t = - p.expect(conf_type, hash_type, prop_type, tp_type, - tp_glob_type, nl_type, eof_type, - "conf, #, prop, tp, tp-glob, a new line or eof"); - if (t.type() == eof_type) - break; - - if (t.type() == conf_type) { - t = p.expect(colon_type, "`:'"); - - t = p.expect(text_type, "variable name"); - std::string var = t.text(); - - t = p.expect(equal_type, "equal sign"); - - t = p.expect(text_type, "word or quoted string"); - ATF_PARSER_CALLBACK(p, got_conf(var, t.text())); - } else if (t.type() == hash_type) { - (void)p.rest_of_line(); - } else if (t.type() == prop_type) { - t = p.expect(colon_type, "`:'"); - - t = p.expect(text_type, "property name"); - std::string name = t.text(); - - t = p.expect(equal_type, "equale sign"); - - t = p.expect(text_type, "word or quoted string"); - ATF_PARSER_CALLBACK(p, got_prop(name, t.text())); - } else if (t.type() == tp_type) { - t = p.expect(colon_type, "`:'"); - - t = p.expect(text_type, "word or quoted string"); - ATF_PARSER_CALLBACK(p, got_tp(t.text(), false)); - } else if (t.type() == tp_glob_type) { - t = p.expect(colon_type, "`:'"); - - t = p.expect(text_type, "word or quoted string"); - ATF_PARSER_CALLBACK(p, got_tp(t.text(), true)); - } else if (t.type() == nl_type) { - continue; - } else - std::abort(); - - t = p.expect(nl_type, hash_type, eof_type, - "new line or comment"); - if (t.type() == hash_type) { - (void)p.rest_of_line(); - t = p.next(); - } else if (t.type() == eof_type) - break; - } catch (const parse_error& pe) { - p.add_error(pe); - p.reset(nl_type); - } - } - - ATF_PARSER_CALLBACK(p, got_eof()); -} - -// ------------------------------------------------------------------------ -// The "reader" helper class. -// ------------------------------------------------------------------------ - -class reader : public detail::atf_atffile_reader { - const tools::fs::directory& m_dir; - vars_map m_conf, m_props; - std::vector< std::string > m_tps; - - void - got_tp(const std::string& name, bool isglob) - { - if (isglob) { - std::vector< std::string > ms = - tools::expand::expand_glob(name, m_dir.names()); - // Cannot use m_tps.insert(iterator, begin, end) here because it - // does not work under Solaris. - for (std::vector< std::string >::const_iterator iter = ms.begin(); - iter != ms.end(); iter++) - m_tps.push_back(*iter); - } else { - if (m_dir.find(name) == m_dir.end()) - throw tools::not_found_error< tools::fs::path > - ("Cannot locate the " + name + " file", - tools::fs::path(name)); - m_tps.push_back(name); - } - } - - void - got_prop(const std::string& name, const std::string& val) - { - m_props[name] = val; - } - - void - got_conf(const std::string& var, const std::string& val) - { - m_conf[var] = val; - } - -public: - reader(std::istream& is, const tools::fs::directory& dir) : - detail::atf_atffile_reader(is), - m_dir(dir) - { - } - - const vars_map& - conf(void) - const - { - return m_conf; - } - - const vars_map& - props(void) - const - { - return m_props; - } - - const std::vector< std::string >& - tps(void) - const - { - return m_tps; - } -}; - -// ------------------------------------------------------------------------ -// The "atffile" class. -// ------------------------------------------------------------------------ - -impl::atffile::atffile(const vars_map& config_vars, - const std::vector< std::string >& test_program_names, - const vars_map& properties) : - m_conf(config_vars), - m_tps(test_program_names), - m_props(properties) -{ - assert(properties.find("test-suite") != properties.end()); -} - -const std::vector< std::string >& -impl::atffile::tps(void) - const -{ - return m_tps; -} - -const vars_map& -impl::atffile::conf(void) - const -{ - return m_conf; -} - -const vars_map& -impl::atffile::props(void) - const -{ - return m_props; -} - -// ------------------------------------------------------------------------ -// Free functions. -// ------------------------------------------------------------------------ - -// XXX Glob expansion and file existance checks certainly do not belong in -// a *parser*. This needs to be taken out... -impl::atffile -impl::read_atffile(const tools::fs::path& filename) -{ - // Scan the directory where the atffile lives in to gather a list of - // all possible test programs in it. - tools::fs::directory dir(filename.branch_path()); - dir.erase(filename.leaf_name()); - tools::fs::directory::iterator iter = dir.begin(); - while (iter != dir.end()) { - const std::string& name = (*iter).first; - const tools::fs::file_info& fi = (*iter).second; - - // Discard hidden files and non-executable ones so that they are - // not candidates for glob matching. - if (name[0] == '.' || (!fi.is_owner_executable() && - !fi.is_group_executable())) - dir.erase(iter++); - else - iter++; - } - - // Parse the atffile. - std::ifstream is(filename.c_str()); - if (!is) - throw tools::not_found_error< tools::fs::path > - ("Cannot open Atffile", filename); - reader r(is, dir); - r.read(); - is.close(); - - // Sanity checks. - if (r.props().find("test-suite") == r.props().end()) - throw tools::not_found_error< std::string > - ("Undefined property `test-suite'", "test-suite"); - - return atffile(r.conf(), r.tps(), r.props()); -} diff --git a/tools/atffile.hpp b/tools/atffile.hpp deleted file mode 100644 index f326b24..0000000 --- a/tools/atffile.hpp +++ /dev/null @@ -1,92 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if !defined(TOOLS_ATFFILE_HPP) -#define TOOLS_ATFFILE_HPP - -#include <map> -#include <string> -#include <vector> - -#include "fs.hpp" - -namespace tools { - -// ------------------------------------------------------------------------ -// The "atf_atffile_reader" class. -// ------------------------------------------------------------------------ - -namespace detail { - -class atf_atffile_reader { - std::istream& m_is; - -protected: - virtual void got_conf(const std::string&, const std::string &); - virtual void got_prop(const std::string&, const std::string &); - virtual void got_tp(const std::string&, bool); - virtual void got_eof(void); - -public: - atf_atffile_reader(std::istream&); - virtual ~atf_atffile_reader(void); - - void read(void); -}; - -} // namespace detail - -// ------------------------------------------------------------------------ -// The "atffile" class. -// ------------------------------------------------------------------------ - -class atffile { - std::map< std::string, std::string > m_conf; - std::vector< std::string > m_tps; - std::map< std::string, std::string > m_props; - -public: - atffile(const std::map< std::string, std::string >&, - const std::vector< std::string >&, - const std::map< std::string, std::string >&); - - const std::map< std::string, std::string >& conf(void) const; - const std::vector< std::string >& tps(void) const; - const std::map< std::string, std::string >& props(void) const; -}; - -// ------------------------------------------------------------------------ -// Free functions. -// ------------------------------------------------------------------------ - -atffile read_atffile(const tools::fs::path&); - -} // namespace tools - -#endif // !defined(TOOLS_ATFFILE_HPP) diff --git a/tools/atffile_test.cpp b/tools/atffile_test.cpp deleted file mode 100644 index cb358df..0000000 --- a/tools/atffile_test.cpp +++ /dev/null @@ -1,636 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2009 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. -// - -extern "C" { -#include <sys/types.h> -#include <sys/stat.h> -} - -#include <algorithm> -#include <fstream> -#include <memory> - -#include <atf-c++.hpp> - -#include "atffile.hpp" -#include "exceptions.hpp" -#include "test_helpers.hpp" - -namespace detail = tools::detail; - -// ------------------------------------------------------------------------ -// Auxiliary functions. -// ------------------------------------------------------------------------ - -namespace { - -typedef std::map< std::string, std::string > vars_map; - -static -std::auto_ptr< std::ofstream > -new_atffile(void) -{ - std::auto_ptr< std::ofstream > os(new std::ofstream("Atffile")); - ATF_REQUIRE(*os); - - (*os) << "Content-Type: application/X-atf-atffile; version=\"1\"\n\n"; - return os; -} - -static -void -touch_exec(const char* name) -{ - std::ofstream os(name); - ATF_REQUIRE(os); - os.close(); - ATF_REQUIRE(::chmod(name, S_IRWXU) != -1); -} - -static inline -bool -is_in(const std::string& value, const std::vector< std::string >& v) -{ - return std::find(v.begin(), v.end(), value) != v.end(); -} - -} // anonymous namespace - -// ------------------------------------------------------------------------ -// Tests cases for the "atffile" parser. -// ------------------------------------------------------------------------ - -class atffile_reader : protected detail::atf_atffile_reader { - void - got_conf(const std::string& name, const std::string& val) - { - m_calls.push_back("got_conf(" + name + ", " + val + ")"); - } - - void - got_prop(const std::string& name, const std::string& val) - { - m_calls.push_back("got_prop(" + name + ", " + val + ")"); - } - - void - got_tp(const std::string& name, bool isglob) - { - m_calls.push_back("got_tp(" + name + ", " + (isglob ? "true" : "false") - + ")"); - } - - void - got_eof(void) - { - m_calls.push_back("got_eof()"); - } - -public: - atffile_reader(std::istream& is) : - detail::atf_atffile_reader(is) - { - } - - void - read(void) - { - atf_atffile_reader::read(); - } - - std::vector< std::string > m_calls; -}; - -ATF_TEST_CASE_WITHOUT_HEAD(atffile_1); -ATF_TEST_CASE_BODY(atffile_1) -{ - const char* input = - "Content-Type: application/X-atf-atffile; version=\"1\"\n" - "\n" - ; - - const char* exp_calls[] = { - "got_eof()", - NULL - }; - - const char* exp_errors[] = { - NULL - }; - - do_parser_test< atffile_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(atffile_2); -ATF_TEST_CASE_BODY(atffile_2) -{ - const char* input = - "Content-Type: application/X-atf-atffile; version=\"1\"\n" - "\n" - "# This is a comment on a line of its own.\n" - "# And this is another one.\n" - "\n" - " # Another after some whitespace.\n" - "\n" - "# The last one after an empty line.\n" - ; - - const char* exp_calls[] = { - "got_eof()", - NULL - }; - - const char* exp_errors[] = { - NULL - }; - - do_parser_test< atffile_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(atffile_3); -ATF_TEST_CASE_BODY(atffile_3) -{ - const char* input = - "Content-Type: application/X-atf-atffile; version=\"1\"\n" - "\n" - "conf: var1=value1\n" - "conf: var2 = value2\n" - "conf: var3 = value3\n" - "conf: var4 = value4\n" - "\n" - "conf:var5=value5\n" - " conf:var6=value6\n" - "\n" - "conf: var7 = \"This is a long value.\"\n" - "conf: var8 = \"Single-word\"\n" - "conf: var9 = \" Single-word \"\n" - "conf: var10 = Single-word\n" - ; - - const char* exp_calls[] = { - "got_conf(var1, value1)", - "got_conf(var2, value2)", - "got_conf(var3, value3)", - "got_conf(var4, value4)", - "got_conf(var5, value5)", - "got_conf(var6, value6)", - "got_conf(var7, This is a long value.)", - "got_conf(var8, Single-word)", - "got_conf(var9, Single-word )", - "got_conf(var10, Single-word)", - "got_eof()", - NULL - }; - - const char* exp_errors[] = { - NULL - }; - - do_parser_test< atffile_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(atffile_4); -ATF_TEST_CASE_BODY(atffile_4) -{ - const char* input = - "Content-Type: application/X-atf-atffile; version=\"1\"\n" - "\n" - "prop: var1=value1\n" - "prop: var2 = value2\n" - "prop: var3 = value3\n" - "prop: var4 = value4\n" - "\n" - "prop:var5=value5\n" - " prop:var6=value6\n" - "\n" - "prop: var7 = \"This is a long value.\"\n" - "prop: var8 = \"Single-word\"\n" - "prop: var9 = \" Single-word \"\n" - "prop: var10 = Single-word\n" - ; - - const char* exp_calls[] = { - "got_prop(var1, value1)", - "got_prop(var2, value2)", - "got_prop(var3, value3)", - "got_prop(var4, value4)", - "got_prop(var5, value5)", - "got_prop(var6, value6)", - "got_prop(var7, This is a long value.)", - "got_prop(var8, Single-word)", - "got_prop(var9, Single-word )", - "got_prop(var10, Single-word)", - "got_eof()", - NULL - }; - - const char* exp_errors[] = { - NULL - }; - - do_parser_test< atffile_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(atffile_5); -ATF_TEST_CASE_BODY(atffile_5) -{ - const char* input = - "Content-Type: application/X-atf-atffile; version=\"1\"\n" - "\n" - "tp:foo\n" - "tp: foo\n" - "tp: foo\n" - "tp: foo\n" - "tp: foo\n" - "tp: \"name with spaces\"\n" - "tp: \"single-word\"\n" - "tp: single-word\n" - "\n" - "tp-glob:foo*?bar\n" - "tp-glob: foo*?bar\n" - "tp-glob: foo*?bar\n" - "tp-glob: foo*?bar\n" - "tp-glob: foo*?bar\n" - "tp-glob: \"glob * with ? spaces\"\n" - "tp-glob: \"single-*-word\"\n" - "tp-glob: single-*-word\n" - ; - - const char* exp_calls[] = { - "got_tp(foo, false)", - "got_tp(foo, false)", - "got_tp(foo, false)", - "got_tp(foo, false)", - "got_tp(foo, false)", - "got_tp(name with spaces, false)", - "got_tp(single-word, false)", - "got_tp(single-word, false)", - "got_tp(foo*?bar, true)", - "got_tp(foo*?bar, true)", - "got_tp(foo*?bar, true)", - "got_tp(foo*?bar, true)", - "got_tp(foo*?bar, true)", - "got_tp(glob * with ? spaces, true)", - "got_tp(single-*-word, true)", - "got_tp(single-*-word, true)", - "got_eof()", - NULL - }; - - const char* exp_errors[] = { - NULL - }; - - do_parser_test< atffile_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(atffile_6); -ATF_TEST_CASE_BODY(atffile_6) -{ - const char* input = - "Content-Type: application/X-atf-atffile; version=\"1\"\n" - "\n" - "prop: foo = bar # A comment.\n" - "conf: foo = bar # A comment.\n" - "tp: foo # A comment.\n" - "tp-glob: foo # A comment.\n" - ; - - const char* exp_calls[] = { - "got_prop(foo, bar)", - "got_conf(foo, bar)", - "got_tp(foo, false)", - "got_tp(foo, true)", - "got_eof()", - NULL - }; - - const char* exp_errors[] = { - NULL - }; - - do_parser_test< atffile_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(atffile_50); -ATF_TEST_CASE_BODY(atffile_50) -{ - const char* input = - "Content-Type: application/X-atf-atffile; version=\"1\"\n" - "\n" - "foo\n" - ; - - const char* exp_calls[] = { - NULL - }; - - // NO_CHECK_STYLE_BEGIN - const char* exp_errors[] = { - "3: Unexpected token `foo'; expected conf, #, prop, tp, tp-glob, a new line or eof", - NULL - }; - // NO_CHECK_STYLE_END - - do_parser_test< atffile_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(atffile_51); -ATF_TEST_CASE_BODY(atffile_51) -{ - const char* input = - "Content-Type: application/X-atf-atffile; version=\"1\"\n" - "\n" - "foo bar\n" - "baz\n" - ; - - const char* exp_calls[] = { - NULL - }; - - // NO_CHECK_STYLE_BEGIN - const char* exp_errors[] = { - "3: Unexpected token `foo'; expected conf, #, prop, tp, tp-glob, a new line or eof", - "4: Unexpected token `baz'; expected conf, #, prop, tp, tp-glob, a new line or eof", - NULL - }; - // NO_CHECK_STYLE_END - - do_parser_test< atffile_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(atffile_52); -ATF_TEST_CASE_BODY(atffile_52) -{ - const char* input = - "Content-Type: application/X-atf-atffile; version=\"1\"\n" - "\n" - "conf\n" - "conf:\n" - "conf: foo =\n" - "conf: bar = # A comment.\n" - "\n" - "prop\n" - "prop:\n" - "prop: foo =\n" - "prop: bar = # A comment.\n" - "\n" - "tp\n" - "tp:\n" - "tp: # A comment.\n" - "\n" - "tp-glob\n" - "tp-glob:\n" - "tp-glob: # A comment.\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "3: Unexpected token `<<NEWLINE>>'; expected `:'", - "4: Unexpected token `<<NEWLINE>>'; expected variable name", - "5: Unexpected token `<<NEWLINE>>'; expected word or quoted string", - "6: Unexpected token `#'; expected word or quoted string", - "8: Unexpected token `<<NEWLINE>>'; expected `:'", - "9: Unexpected token `<<NEWLINE>>'; expected property name", - "10: Unexpected token `<<NEWLINE>>'; expected word or quoted string", - "11: Unexpected token `#'; expected word or quoted string", - "13: Unexpected token `<<NEWLINE>>'; expected `:'", - "14: Unexpected token `<<NEWLINE>>'; expected word or quoted string", - "15: Unexpected token `#'; expected word or quoted string", - "17: Unexpected token `<<NEWLINE>>'; expected `:'", - "18: Unexpected token `<<NEWLINE>>'; expected word or quoted string", - "19: Unexpected token `#'; expected word or quoted string", - NULL - }; - - do_parser_test< atffile_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(atffile_53); -ATF_TEST_CASE_BODY(atffile_53) -{ - const char* input = - "Content-Type: application/X-atf-atffile; version=\"1\"\n" - "\n" - "prop: foo = \"Correct value\" # With comment.\n" - "\n" - "prop: bar = # A comment.\n" - "\n" - "prop: baz = \"Last variable\"\n" - "\n" - "# End of file.\n" - ; - - const char* exp_calls[] = { - "got_prop(foo, Correct value)", - NULL - }; - - const char* exp_errors[] = { - "5: Unexpected token `#'; expected word or quoted string", - NULL - }; - - do_parser_test< atffile_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(atffile_54); -ATF_TEST_CASE_BODY(atffile_54) -{ - const char* input = - "Content-Type: application/X-atf-atffile; version=\"1\"\n" - "\n" - "prop: foo = \"\n" - "prop: bar = \"text\n" - "prop: baz = \"te\\\"xt\n" - "prop: last = \"\\\"\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "3: Missing double quotes before end of line", - "4: Missing double quotes before end of line", - "5: Missing double quotes before end of line", - "6: Missing double quotes before end of line", - NULL - }; - - do_parser_test< atffile_reader >(input, exp_calls, exp_errors); -} - -// ------------------------------------------------------------------------ -// Tests cases for the "atffile" class. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(atffile_getters); -ATF_TEST_CASE_HEAD(atffile_getters) {} -ATF_TEST_CASE_BODY(atffile_getters) { - vars_map config_vars; - config_vars["config-var-1"] = "value 1"; - - std::vector< std::string > test_program_names; - test_program_names.push_back("test-program-1"); - - vars_map properties; - properties["test-suite"] = "a test name"; - - const tools::atffile atffile(config_vars, test_program_names, properties); - ATF_REQUIRE(config_vars == atffile.conf()); - ATF_REQUIRE(test_program_names == atffile.tps()); - ATF_REQUIRE(properties == atffile.props()); -} - -// ------------------------------------------------------------------------ -// Tests cases for the free functions. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE_WITHOUT_HEAD(read_ok_simple); -ATF_TEST_CASE_BODY(read_ok_simple) { - std::auto_ptr< std::ofstream > os = new_atffile(); - (*os) << "prop: test-suite = foo\n"; - (*os) << "tp: tp-1\n"; - (*os) << "conf: var1 = value1\n"; - (*os) << "tp: tp-2\n"; - (*os) << "tp: tp-3\n"; - (*os) << "prop: prop1 = propvalue1\n"; - (*os) << "conf: var2 = value2\n"; - (*os).close(); - - touch_exec("tp-1"); - touch_exec("tp-2"); - touch_exec("tp-3"); - - const tools::atffile atffile = tools::read_atffile( - tools::fs::path("Atffile")); - ATF_REQUIRE_EQ(2, atffile.conf().size()); - ATF_REQUIRE_EQ("value1", atffile.conf().find("var1")->second); - ATF_REQUIRE_EQ("value2", atffile.conf().find("var2")->second); - ATF_REQUIRE_EQ(3, atffile.tps().size()); - ATF_REQUIRE(is_in("tp-1", atffile.tps())); - ATF_REQUIRE(is_in("tp-2", atffile.tps())); - ATF_REQUIRE(is_in("tp-3", atffile.tps())); - ATF_REQUIRE_EQ(2, atffile.props().size()); - ATF_REQUIRE_EQ("foo", atffile.props().find("test-suite")->second); - ATF_REQUIRE_EQ("propvalue1", atffile.props().find("prop1")->second); -} - -ATF_TEST_CASE_WITHOUT_HEAD(read_ok_some_globs); -ATF_TEST_CASE_BODY(read_ok_some_globs) { - std::auto_ptr< std::ofstream > os = new_atffile(); - (*os) << "prop: test-suite = foo\n"; - (*os) << "tp: foo\n"; - (*os) << "tp-glob: *K*\n"; - (*os) << "tp: bar\n"; - (*os) << "tp-glob: t_*\n"; - (*os).close(); - - touch_exec("foo"); - touch_exec("bar"); - touch_exec("aK"); - touch_exec("KKKKK"); - touch_exec("t_hello"); - touch_exec("zzzt_hello"); - - const tools::atffile atffile = tools::read_atffile( - tools::fs::path("Atffile")); - ATF_REQUIRE_EQ(5, atffile.tps().size()); - ATF_REQUIRE(is_in("foo", atffile.tps())); - ATF_REQUIRE(is_in("bar", atffile.tps())); - ATF_REQUIRE(is_in("aK", atffile.tps())); - ATF_REQUIRE(is_in("KKKKK", atffile.tps())); - ATF_REQUIRE(is_in("t_hello", atffile.tps())); -} - -ATF_TEST_CASE_WITHOUT_HEAD(read_missing_test_suite); -ATF_TEST_CASE_BODY(read_missing_test_suite) { - std::auto_ptr< std::ofstream > os = new_atffile(); - (*os).close(); - - try { - (void)tools::read_atffile(tools::fs::path("Atffile")); - ATF_FAIL("Missing property 'test-suite' did not raise an error"); - } catch (const tools::not_found_error< std::string >& e) { - ATF_REQUIRE_EQ("test-suite", e.get_value()); - } -} - -ATF_TEST_CASE_WITHOUT_HEAD(read_missing_test_program); -ATF_TEST_CASE_BODY(read_missing_test_program) { - std::auto_ptr< std::ofstream > os = new_atffile(); - (*os) << "tp: foo\n"; - (*os) << "tp: bar\n"; - (*os) << "tp: baz\n"; - (*os).close(); - - touch_exec("foo"); - touch_exec("baz"); - - try { - (void)tools::read_atffile(tools::fs::path("Atffile")); - ATF_FAIL("Missing file 'bar' did not raise an error"); - } catch (const tools::not_found_error< tools::fs::path >& e) { - ATF_REQUIRE_EQ("bar", e.get_value().str()); - } -} - -// ------------------------------------------------------------------------ -// Main. -// ------------------------------------------------------------------------ - -ATF_INIT_TEST_CASES(tcs) -{ - // Add the test cases for the parser class. - ATF_ADD_TEST_CASE(tcs, atffile_1); - ATF_ADD_TEST_CASE(tcs, atffile_2); - ATF_ADD_TEST_CASE(tcs, atffile_3); - ATF_ADD_TEST_CASE(tcs, atffile_4); - ATF_ADD_TEST_CASE(tcs, atffile_5); - ATF_ADD_TEST_CASE(tcs, atffile_6); - ATF_ADD_TEST_CASE(tcs, atffile_50); - ATF_ADD_TEST_CASE(tcs, atffile_51); - ATF_ADD_TEST_CASE(tcs, atffile_52); - ATF_ADD_TEST_CASE(tcs, atffile_53); - ATF_ADD_TEST_CASE(tcs, atffile_54); - - // Add the test cases for the atffile class. - ATF_ADD_TEST_CASE(tcs, atffile_getters); - - // Add the test cases for the free functions. - ATF_ADD_TEST_CASE(tcs, read_ok_simple); - ATF_ADD_TEST_CASE(tcs, read_ok_some_globs); - ATF_ADD_TEST_CASE(tcs, read_missing_test_suite); - ATF_ADD_TEST_CASE(tcs, read_missing_test_program); -} diff --git a/tools/auto_array.hpp b/tools/auto_array.hpp deleted file mode 100644 index 773f875..0000000 --- a/tools/auto_array.hpp +++ /dev/null @@ -1,179 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if !defined(TOOLS_AUTO_ARRAY_HPP) -#define TOOLS_AUTO_ARRAY_HPP - -#include <cstddef> - -namespace tools { - -// ------------------------------------------------------------------------ -// The "auto_array" class. -// ------------------------------------------------------------------------ - -template< class T > -struct auto_array_ref { - T* m_ptr; - - explicit auto_array_ref(T*); -}; - -template< class T > -auto_array_ref< T >::auto_array_ref(T* ptr) : - m_ptr(ptr) -{ -} - -template< class T > -class auto_array { - T* m_ptr; - -public: - auto_array(T* = NULL) throw(); - auto_array(auto_array< T >&) throw(); - auto_array(auto_array_ref< T >) throw(); - ~auto_array(void) throw(); - - T* get(void) throw(); - const T* get(void) const throw(); - T* release(void) throw(); - void reset(T* = NULL) throw(); - - auto_array< T >& operator=(auto_array< T >&) throw(); - auto_array< T >& operator=(auto_array_ref< T >) throw(); - - T& operator[](int) throw(); - operator auto_array_ref< T >(void) throw(); -}; - -template< class T > -auto_array< T >::auto_array(T* ptr) - throw() : - m_ptr(ptr) -{ -} - -template< class T > -auto_array< T >::auto_array(auto_array< T >& ptr) - throw() : - m_ptr(ptr.release()) -{ -} - -template< class T > -auto_array< T >::auto_array(auto_array_ref< T > ref) - throw() : - m_ptr(ref.m_ptr) -{ -} - -template< class T > -auto_array< T >::~auto_array(void) - throw() -{ - if (m_ptr != NULL) - delete [] m_ptr; -} - -template< class T > -T* -auto_array< T >::get(void) - throw() -{ - return m_ptr; -} - -template< class T > -const T* -auto_array< T >::get(void) - const throw() -{ - return m_ptr; -} - -template< class T > -T* -auto_array< T >::release(void) - throw() -{ - T* ptr = m_ptr; - m_ptr = NULL; - return ptr; -} - -template< class T > -void -auto_array< T >::reset(T* ptr) - throw() -{ - if (m_ptr != NULL) - delete [] m_ptr; - m_ptr = ptr; -} - -template< class T > -auto_array< T >& -auto_array< T >::operator=(auto_array< T >& ptr) - throw() -{ - reset(ptr.release()); - return *this; -} - -template< class T > -auto_array< T >& -auto_array< T >::operator=(auto_array_ref< T > ref) - throw() -{ - if (m_ptr != ref.m_ptr) { - delete [] m_ptr; - m_ptr = ref.m_ptr; - } - return *this; -} - -template< class T > -T& -auto_array< T >::operator[](int pos) - throw() -{ - return m_ptr[pos]; -} - -template< class T > -auto_array< T >::operator auto_array_ref< T >(void) - throw() -{ - return auto_array_ref< T >(release()); -} - -} // namespace tools - -#endif // !defined(TOOLS_AUTO_ARRAY_HPP) diff --git a/tools/auto_array_test.cpp b/tools/auto_array_test.cpp deleted file mode 100644 index 56bbae5..0000000 --- a/tools/auto_array_test.cpp +++ /dev/null @@ -1,303 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -extern "C" { -#include <sys/types.h> -} - -#include <iostream> - -#include <atf-c++.hpp> - -#include "auto_array.hpp" -#include "defs.hpp" - -// ------------------------------------------------------------------------ -// Tests for the "auto_array" class. -// ------------------------------------------------------------------------ - -class test_array { -public: - int m_value; - - static ssize_t m_nblocks; - - static - tools::auto_array< test_array > - do_copy(tools::auto_array< test_array >& ta) - { - return tools::auto_array< test_array >(ta); - } - - void* operator new(size_t size ATF_DEFS_ATTRIBUTE_UNUSED) - { - ATF_FAIL("New called but should have been new[]"); - return new int(5); - } - - void* operator new[](size_t size) - { - m_nblocks++; - void* mem = ::operator new(size); - std::cout << "Allocated 'test_array' object " << mem << "\n"; - return mem; - } - - void operator delete(void* mem ATF_DEFS_ATTRIBUTE_UNUSED) - { - ATF_FAIL("Delete called but should have been delete[]"); - } - - void operator delete[](void* mem) - { - std::cout << "Releasing 'test_array' object " << mem << "\n"; - if (m_nblocks == 0) - ATF_FAIL("Unbalanced delete[]"); - m_nblocks--; - ::operator delete(mem); - } -}; - -ssize_t test_array::m_nblocks = 0; - -ATF_TEST_CASE(auto_array_scope); -ATF_TEST_CASE_HEAD(auto_array_scope) -{ - set_md_var("descr", "Tests the automatic scope handling in the " - "auto_array smart pointer class"); -} -ATF_TEST_CASE_BODY(auto_array_scope) -{ - using tools::auto_array; - - ATF_REQUIRE_EQ(test_array::m_nblocks, 0); - { - auto_array< test_array > t(new test_array[10]); - ATF_REQUIRE_EQ(test_array::m_nblocks, 1); - } - ATF_REQUIRE_EQ(test_array::m_nblocks, 0); -} - -ATF_TEST_CASE(auto_array_copy); -ATF_TEST_CASE_HEAD(auto_array_copy) -{ - set_md_var("descr", "Tests the auto_array smart pointer class' copy " - "constructor"); -} -ATF_TEST_CASE_BODY(auto_array_copy) -{ - using tools::auto_array; - - ATF_REQUIRE_EQ(test_array::m_nblocks, 0); - { - auto_array< test_array > t1(new test_array[10]); - ATF_REQUIRE_EQ(test_array::m_nblocks, 1); - - { - auto_array< test_array > t2(t1); - ATF_REQUIRE_EQ(test_array::m_nblocks, 1); - } - ATF_REQUIRE_EQ(test_array::m_nblocks, 0); - } - ATF_REQUIRE_EQ(test_array::m_nblocks, 0); -} - -ATF_TEST_CASE(auto_array_copy_ref); -ATF_TEST_CASE_HEAD(auto_array_copy_ref) -{ - set_md_var("descr", "Tests the auto_array smart pointer class' copy " - "constructor through the auxiliary auto_array_ref object"); -} -ATF_TEST_CASE_BODY(auto_array_copy_ref) -{ - using tools::auto_array; - - ATF_REQUIRE_EQ(test_array::m_nblocks, 0); - { - auto_array< test_array > t1(new test_array[10]); - ATF_REQUIRE_EQ(test_array::m_nblocks, 1); - - { - auto_array< test_array > t2 = test_array::do_copy(t1); - ATF_REQUIRE_EQ(test_array::m_nblocks, 1); - } - ATF_REQUIRE_EQ(test_array::m_nblocks, 0); - } - ATF_REQUIRE_EQ(test_array::m_nblocks, 0); -} - -ATF_TEST_CASE(auto_array_get); -ATF_TEST_CASE_HEAD(auto_array_get) -{ - set_md_var("descr", "Tests the auto_array smart pointer class' get " - "method"); -} -ATF_TEST_CASE_BODY(auto_array_get) -{ - using tools::auto_array; - - test_array* ta = new test_array[10]; - auto_array< test_array > t(ta); - ATF_REQUIRE_EQ(t.get(), ta); -} - -ATF_TEST_CASE(auto_array_release); -ATF_TEST_CASE_HEAD(auto_array_release) -{ - set_md_var("descr", "Tests the auto_array smart pointer class' release " - "method"); -} -ATF_TEST_CASE_BODY(auto_array_release) -{ - using tools::auto_array; - - test_array* ta1 = new test_array[10]; - { - auto_array< test_array > t(ta1); - ATF_REQUIRE_EQ(test_array::m_nblocks, 1); - test_array* ta2 = t.release(); - ATF_REQUIRE_EQ(ta2, ta1); - ATF_REQUIRE_EQ(test_array::m_nblocks, 1); - } - ATF_REQUIRE_EQ(test_array::m_nblocks, 1); - delete [] ta1; -} - -ATF_TEST_CASE(auto_array_reset); -ATF_TEST_CASE_HEAD(auto_array_reset) -{ - set_md_var("descr", "Tests the auto_array smart pointer class' reset " - "method"); -} -ATF_TEST_CASE_BODY(auto_array_reset) -{ - using tools::auto_array; - - test_array* ta1 = new test_array[10]; - test_array* ta2 = new test_array[10]; - ATF_REQUIRE_EQ(test_array::m_nblocks, 2); - - { - auto_array< test_array > t(ta1); - ATF_REQUIRE_EQ(test_array::m_nblocks, 2); - t.reset(ta2); - ATF_REQUIRE_EQ(test_array::m_nblocks, 1); - t.reset(); - ATF_REQUIRE_EQ(test_array::m_nblocks, 0); - } - ATF_REQUIRE_EQ(test_array::m_nblocks, 0); -} - -ATF_TEST_CASE(auto_array_assign); -ATF_TEST_CASE_HEAD(auto_array_assign) -{ - set_md_var("descr", "Tests the auto_array smart pointer class' " - "assignment operator"); -} -ATF_TEST_CASE_BODY(auto_array_assign) -{ - using tools::auto_array; - - ATF_REQUIRE_EQ(test_array::m_nblocks, 0); - { - auto_array< test_array > t1(new test_array[10]); - ATF_REQUIRE_EQ(test_array::m_nblocks, 1); - - { - auto_array< test_array > t2; - t2 = t1; - ATF_REQUIRE_EQ(test_array::m_nblocks, 1); - } - ATF_REQUIRE_EQ(test_array::m_nblocks, 0); - } - ATF_REQUIRE_EQ(test_array::m_nblocks, 0); -} - -ATF_TEST_CASE(auto_array_assign_ref); -ATF_TEST_CASE_HEAD(auto_array_assign_ref) -{ - set_md_var("descr", "Tests the auto_array smart pointer class' " - "assignment operator through the auxiliary auto_array_ref " - "object"); -} -ATF_TEST_CASE_BODY(auto_array_assign_ref) -{ - using tools::auto_array; - - ATF_REQUIRE_EQ(test_array::m_nblocks, 0); - { - auto_array< test_array > t1(new test_array[10]); - ATF_REQUIRE_EQ(test_array::m_nblocks, 1); - - { - auto_array< test_array > t2; - t2 = test_array::do_copy(t1); - ATF_REQUIRE_EQ(test_array::m_nblocks, 1); - } - ATF_REQUIRE_EQ(test_array::m_nblocks, 0); - } - ATF_REQUIRE_EQ(test_array::m_nblocks, 0); -} - -ATF_TEST_CASE(auto_array_access); -ATF_TEST_CASE_HEAD(auto_array_access) -{ - set_md_var("descr", "Tests the auto_array smart pointer class' access " - "operator"); -} -ATF_TEST_CASE_BODY(auto_array_access) -{ - using tools::auto_array; - - auto_array< test_array > t(new test_array[10]); - - for (int i = 0; i < 10; i++) - t[i].m_value = i * 2; - - for (int i = 0; i < 10; i++) - ATF_REQUIRE_EQ(t[i].m_value, i * 2); -} - -// ------------------------------------------------------------------------ -// Main. -// ------------------------------------------------------------------------ - -ATF_INIT_TEST_CASES(tcs) -{ - // Add the test for the "auto_array" class. - ATF_ADD_TEST_CASE(tcs, auto_array_scope); - ATF_ADD_TEST_CASE(tcs, auto_array_copy); - ATF_ADD_TEST_CASE(tcs, auto_array_copy_ref); - ATF_ADD_TEST_CASE(tcs, auto_array_get); - ATF_ADD_TEST_CASE(tcs, auto_array_release); - ATF_ADD_TEST_CASE(tcs, auto_array_reset); - ATF_ADD_TEST_CASE(tcs, auto_array_assign); - ATF_ADD_TEST_CASE(tcs, auto_array_assign_ref); - ATF_ADD_TEST_CASE(tcs, auto_array_access); -} diff --git a/tools/bad_metadata_helper.c b/tools/bad_metadata_helper.c deleted file mode 100644 index 0f7fcb9..0000000 --- a/tools/bad_metadata_helper.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 <stdio.h> -#include <stdlib.h> - -int -main(void) -{ - printf("incorrectly formatted metadata\n"); - return EXIT_SUCCESS; -} diff --git a/tools/config.cpp b/tools/config.cpp deleted file mode 100644 index 95bcf55..0000000 --- a/tools/config.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 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 <cassert> -#include <map> - -#include "config.hpp" -#include "env.hpp" -#include "text.hpp" - -static std::map< std::string, std::string > m_variables; - -static struct var { - const char *name; - const char *default_value; - bool can_be_empty; -} vars[] = { - { "ATF_ARCH", ATF_ARCH, false, }, - { "ATF_BUILD_CC", ATF_BUILD_CC, false, }, - { "ATF_BUILD_CFLAGS", ATF_BUILD_CFLAGS, true, }, - { "ATF_BUILD_CPP", ATF_BUILD_CPP, false, }, - { "ATF_BUILD_CPPFLAGS", ATF_BUILD_CPPFLAGS, true, }, - { "ATF_BUILD_CXX", ATF_BUILD_CXX, false, }, - { "ATF_BUILD_CXXFLAGS", ATF_BUILD_CXXFLAGS, true, }, - { "ATF_CONFDIR", ATF_CONFDIR, false, }, - { "ATF_INCLUDEDIR", ATF_INCLUDEDIR, false, }, - { "ATF_LIBDIR", ATF_LIBDIR, false, }, - { "ATF_LIBEXECDIR", ATF_LIBEXECDIR, false, }, - { "ATF_MACHINE", ATF_MACHINE, false, }, - { "ATF_PKGDATADIR", ATF_PKGDATADIR, false, }, - { "ATF_SHELL", ATF_SHELL, false, }, - { "ATF_WORKDIR", ATF_WORKDIR, false, }, - { NULL, NULL, false, }, -}; - -// -// Adds all predefined standard build-time variables to the m_variables -// map, considering the values a user may have provided in the environment. -// -// Can only be called once during the program's lifetime. -// -static -void -init_variables(void) -{ - assert(m_variables.empty()); - - for (struct var* v = vars; v->name != NULL; v++) { - const std::string varname = tools::text::to_lower(v->name); - - if (tools::env::has(v->name)) { - const std::string envval = tools::env::get(v->name); - if (envval.empty() && !v->can_be_empty) - m_variables[varname] = v->default_value; - else - m_variables[varname] = envval; - } else { - m_variables[varname] = v->default_value; - } - } - - assert(!m_variables.empty()); -} - -const std::string& -tools::config::get(const std::string& varname) -{ - if (m_variables.empty()) - init_variables(); - - assert(has(varname)); - return m_variables[varname]; -} - -const std::map< std::string, std::string >& -tools::config::get_all(void) -{ - if (m_variables.empty()) - init_variables(); - - return m_variables; -} - -bool -tools::config::has(const std::string& varname) -{ - if (m_variables.empty()) - init_variables(); - - return m_variables.find(varname) != m_variables.end(); -} - -namespace tools { -namespace config { -// -// Auxiliary function for the t_config test program so that it can -// revert the configuration's global status to an empty state and -// do new tests from there on. -// -// Ideally this shouldn't be part of the production library... but -// this is so small that it does not matter. -// -void -__reinit(void) -{ - m_variables.clear(); -} -} // namespace config -} // namespace tools diff --git a/tools/config.hpp b/tools/config.hpp deleted file mode 100644 index 0a43873..0000000 --- a/tools/config.hpp +++ /dev/null @@ -1,75 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if !defined(TOOLS_CONFIG_HPP) -#define TOOLS_CONFIG_HPP - -#include <map> -#include <string> - -namespace tools { - -namespace config { - -//! -//! \brief Gets a build-time configuration variable's value. -//! -//! Given the name of a build-time configuration variable, returns its -//! textual value. The user is free to override these by setting their -//! corresponding environment variables. Therefore always use this -//! interface to get the value of these variables. -//! -//! \pre The variable must exist. -//! -const std::string& get(const std::string&); - -//! -//! \brief Returns all the build-time configuration variables. -//! -//! Returns a name to value map containing all build-time configuration -//! variables. -//! -const std::map< std::string, std::string >& get_all(void); - -//! -//! \brief Checks whether a build-time configuration variable exists. -//! -//! Given the name of a build-time configuration variable, checks -//! whether it is defined and returns a boolean indicating this -//! condition. The program only has to use this function to sanity-check -//! a variable name provided by the user. Otherwise it can assume that -//! the variables are defined. -//! -bool has(const std::string&); - -} // namespace config - -} // namespace tools - -#endif // !defined(TOOLS_CONFIG_HPP) diff --git a/tools/config_file.cpp b/tools/config_file.cpp deleted file mode 100644 index 3802c06..0000000 --- a/tools/config_file.cpp +++ /dev/null @@ -1,223 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 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 <cstdlib> -#include <fstream> -#include <vector> - -#include "config.hpp" -#include "config_file.hpp" -#include "defs.hpp" -#include "env.hpp" -#include "fs.hpp" -#include "parser.hpp" - -namespace impl = tools::config_file; -namespace detail = tools::config_file::detail; - -namespace { - -typedef std::map< std::string, std::string > vars_map; - -namespace atf_config { - -static const tools::parser::token_type eof_type = 0; -static const tools::parser::token_type nl_type = 1; -static const tools::parser::token_type text_type = 2; -static const tools::parser::token_type dblquote_type = 3; -static const tools::parser::token_type equal_type = 4; -static const tools::parser::token_type hash_type = 5; - -class tokenizer : public tools::parser::tokenizer< std::istream > { -public: - tokenizer(std::istream& is, size_t curline) : - tools::parser::tokenizer< std::istream > - (is, true, eof_type, nl_type, text_type, curline) - { - add_delim('=', equal_type); - add_delim('#', hash_type); - add_quote('"', dblquote_type); - } -}; - -} // namespace atf_config - -class config_reader : public detail::atf_config_reader { - vars_map m_vars; - - void - got_var(const std::string& var, const std::string& name) - { - m_vars[var] = name; - } - -public: - config_reader(std::istream& is) : - atf_config_reader(is) - { - } - - const vars_map& - get_vars(void) - const - { - return m_vars; - } -}; - -template< class K, class V > -static -void -merge_maps(std::map< K, V >& dest, const std::map< K, V >& src) -{ - for (typename std::map< K, V >::const_iterator iter = src.begin(); - iter != src.end(); iter++) - dest[(*iter).first] = (*iter).second; -} - -static -void -merge_config_file(const tools::fs::path& config_path, - vars_map& config) -{ - std::ifstream is(config_path.c_str()); - if (is) { - config_reader reader(is); - reader.read(); - merge_maps(config, reader.get_vars()); - } -} - -static -std::vector< tools::fs::path > -get_config_dirs(void) -{ - std::vector< tools::fs::path > dirs; - dirs.push_back(tools::fs::path(tools::config::get("atf_confdir"))); - if (tools::env::has("HOME")) - dirs.push_back(tools::fs::path(tools::env::get("HOME")) / ".atf"); - return dirs; -} - -} // anonymous namespace - -detail::atf_config_reader::atf_config_reader(std::istream& is) : - m_is(is) -{ -} - -detail::atf_config_reader::~atf_config_reader(void) -{ -} - -void -detail::atf_config_reader::got_var( - const std::string& var ATF_DEFS_ATTRIBUTE_UNUSED, - const std::string& val ATF_DEFS_ATTRIBUTE_UNUSED) -{ -} - -void -detail::atf_config_reader::got_eof(void) -{ -} - -void -detail::atf_config_reader::read(void) -{ - using tools::parser::parse_error; - using namespace atf_config; - - std::pair< size_t, tools::parser::headers_map > hml = - tools::parser::read_headers(m_is, 1); - tools::parser::validate_content_type(hml.second, - "application/X-atf-config", 1); - - tokenizer tkz(m_is, hml.first); - tools::parser::parser< tokenizer > p(tkz); - - for (;;) { - try { - tools::parser::token t = p.expect(eof_type, hash_type, text_type, - nl_type, - "eof, #, new line or text"); - if (t.type() == eof_type) - break; - - if (t.type() == hash_type) { - (void)p.rest_of_line(); - t = p.expect(nl_type, "new line"); - } else if (t.type() == text_type) { - std::string name = t.text(); - - t = p.expect(equal_type, "equal sign"); - - t = p.expect(text_type, "word or quoted string"); - ATF_PARSER_CALLBACK(p, got_var(name, t.text())); - - t = p.expect(nl_type, hash_type, "new line or comment"); - if (t.type() == hash_type) { - (void)p.rest_of_line(); - t = p.expect(nl_type, "new line"); - } - } else if (t.type() == nl_type) { - } else - std::abort(); - } catch (const parse_error& pe) { - p.add_error(pe); - p.reset(nl_type); - } - } - - ATF_PARSER_CALLBACK(p, got_eof()); -} - -vars_map -impl::merge_configs(const vars_map& lower, - const vars_map& upper) -{ - vars_map merged = lower; - merge_maps(merged, upper); - return merged; -} - -vars_map -impl::read_config_files(const std::string& test_suite_name) -{ - vars_map config; - - const std::vector< tools::fs::path > dirs = get_config_dirs(); - for (std::vector< tools::fs::path >::const_iterator iter = dirs.begin(); - iter != dirs.end(); iter++) { - merge_config_file((*iter) / "common.conf", config); - merge_config_file((*iter) / (test_suite_name + ".conf"), config); - } - - return config; -} diff --git a/tools/config_file.hpp b/tools/config_file.hpp deleted file mode 100644 index 0c68bcb..0000000 --- a/tools/config_file.hpp +++ /dev/null @@ -1,66 +0,0 @@ -// -// 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. -// - -#if !defined(TOOLS_CONFIG_FILE_HPP) -#define TOOLS_CONFIG_FILE_HPP - -#include <map> -#include <string> -#include <vector> - -namespace tools { -namespace config_file { - -namespace detail { - -class atf_config_reader { - std::istream& m_is; - -protected: - virtual void got_var(const std::string&, const std::string &); - virtual void got_eof(void); - -public: - atf_config_reader(std::istream&); - virtual ~atf_config_reader(void); - - void read(void); -}; - -} // namespace detail - -std::map< std::string, std::string > merge_configs( - const std::map< std::string, std::string >&, - const std::map< std::string, std::string >&); -std::map< std::string, std::string > read_config_files(const std::string&); - -} // namespace config_file -} // namespace tools - -#endif // !defined(TOOLS_CONFIG_FILE_HPP) diff --git a/tools/config_file_test.cpp b/tools/config_file_test.cpp deleted file mode 100644 index b8adc7a..0000000 --- a/tools/config_file_test.cpp +++ /dev/null @@ -1,395 +0,0 @@ -// -// 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 <atf-c++.hpp> - -#include "config.hpp" -#include "config_file.hpp" -#include "env.hpp" -#include "test_helpers.hpp" - -namespace impl = tools::config_file; -namespace detail = tools::config_file::detail; - -namespace { - -typedef std::map< std::string, std::string > vars_map; - -} // anonymous namespace - -namespace atf { -namespace config { - -void __reinit(void); - -} // namespace config -} // namespace atf - -// ------------------------------------------------------------------------- -// Tests for the "config" parser. -// ------------------------------------------------------------------------- - -class config_reader : protected detail::atf_config_reader { - void - got_var(const std::string& name, const std::string& val) - { - m_calls.push_back("got_var(" + name + ", " + val + ")"); - } - - void - got_eof(void) - { - m_calls.push_back("got_eof()"); - } - -public: - config_reader(std::istream& is) : - detail::atf_config_reader(is) - { - } - - void - read(void) - { - atf_config_reader::read(); - } - - std::vector< std::string > m_calls; -}; - -ATF_TEST_CASE_WITHOUT_HEAD(config_1); -ATF_TEST_CASE_BODY(config_1) -{ - const char* input = - "Content-Type: application/X-atf-config; version=\"1\"\n" - "\n" - ; - - const char* exp_calls[] = { - "got_eof()", - NULL - }; - - const char* exp_errors[] = { - NULL - }; - - do_parser_test< config_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(config_2); -ATF_TEST_CASE_BODY(config_2) -{ - const char* input = - "Content-Type: application/X-atf-config; version=\"1\"\n" - "\n" - "# This is a comment on a line of its own.\n" - "# And this is another one.\n" - "\n" - " # Another after some whitespace.\n" - "\n" - "# The last one after an empty line.\n" - ; - - const char* exp_calls[] = { - "got_eof()", - NULL - }; - - const char* exp_errors[] = { - NULL - }; - - do_parser_test< config_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(config_3); -ATF_TEST_CASE_BODY(config_3) -{ - const char* input = - "Content-Type: application/X-atf-config; version=\"1\"\n" - "\n" - "var1=value1\n" - "var2 = value2\n" - "var3 = value3\n" - "var4 = value4\n" - "\n" - "var5=value5\n" - " var6=value6\n" - "\n" - "var7 = \"This is a long value.\"\n" - "var8 = \"Single-word\"\n" - "var9 = \" Single-word \"\n" - "var10 = Single-word\n" - ; - - const char* exp_calls[] = { - "got_var(var1, value1)", - "got_var(var2, value2)", - "got_var(var3, value3)", - "got_var(var4, value4)", - "got_var(var5, value5)", - "got_var(var6, value6)", - "got_var(var7, This is a long value.)", - "got_var(var8, Single-word)", - "got_var(var9, Single-word )", - "got_var(var10, Single-word)", - "got_eof()", - NULL - }; - - const char* exp_errors[] = { - NULL - }; - - do_parser_test< config_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(config_4); -ATF_TEST_CASE_BODY(config_4) -{ - const char* input = - "Content-Type: application/X-atf-config; version=\"1\"\n" - "\n" - "foo = bar # A comment.\n" - ; - - const char* exp_calls[] = { - "got_var(foo, bar)", - "got_eof()", - NULL - }; - - const char* exp_errors[] = { - NULL - }; - - do_parser_test< config_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(config_50); -ATF_TEST_CASE_BODY(config_50) -{ - const char* input = - "Content-Type: application/X-atf-config; version=\"1\"\n" - "\n" - "foo\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "3: Unexpected token `<<NEWLINE>>'; expected equal sign", - NULL - }; - - do_parser_test< config_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(config_51); -ATF_TEST_CASE_BODY(config_51) -{ - const char* input = - "Content-Type: application/X-atf-config; version=\"1\"\n" - "\n" - "foo bar\n" - "baz\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "3: Unexpected token `bar'; expected equal sign", - "4: Unexpected token `<<NEWLINE>>'; expected equal sign", - NULL - }; - - do_parser_test< config_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(config_52); -ATF_TEST_CASE_BODY(config_52) -{ - const char* input = - "Content-Type: application/X-atf-config; version=\"1\"\n" - "\n" - "foo =\n" - "bar = # A comment.\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "3: Unexpected token `<<NEWLINE>>'; expected word or quoted string", - "4: Unexpected token `#'; expected word or quoted string", - NULL - }; - - do_parser_test< config_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(config_53); -ATF_TEST_CASE_BODY(config_53) -{ - const char* input = - "Content-Type: application/X-atf-config; version=\"1\"\n" - "\n" - "foo = \"Correct value\" # With comment.\n" - "\n" - "bar = # A comment.\n" - "\n" - "baz = \"Last variable\"\n" - "\n" - "# End of file.\n" - ; - - const char* exp_calls[] = { - "got_var(foo, Correct value)", - NULL - }; - - const char* exp_errors[] = { - "5: Unexpected token `#'; expected word or quoted string", - NULL - }; - - do_parser_test< config_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(config_54); -ATF_TEST_CASE_BODY(config_54) -{ - const char* input = - "Content-Type: application/X-atf-config; version=\"1\"\n" - "\n" - "foo = \"\n" - "bar = \"text\n" - "baz = \"te\\\"xt\n" - "last = \"\\\"\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "3: Missing double quotes before end of line", - "4: Missing double quotes before end of line", - "5: Missing double quotes before end of line", - "6: Missing double quotes before end of line", - NULL - }; - - do_parser_test< config_reader >(input, exp_calls, exp_errors); -} - -// ------------------------------------------------------------------------- -// Tests for the free functions. -// ------------------------------------------------------------------------- - -ATF_TEST_CASE(merge_configs_both_empty); -ATF_TEST_CASE_HEAD(merge_configs_both_empty) {} -ATF_TEST_CASE_BODY(merge_configs_both_empty) { - vars_map lower, upper; - - ATF_REQUIRE(impl::merge_configs(lower, upper).empty()); -} - -ATF_TEST_CASE(merge_configs_lower_empty); -ATF_TEST_CASE_HEAD(merge_configs_lower_empty) {} -ATF_TEST_CASE_BODY(merge_configs_lower_empty) { - vars_map lower, upper; - upper["var"] = "value"; - - vars_map merged = impl::merge_configs(lower, upper); - ATF_REQUIRE_EQ("value", merged["var"]); -} - -ATF_TEST_CASE(merge_configs_upper_empty); -ATF_TEST_CASE_HEAD(merge_configs_upper_empty) {} -ATF_TEST_CASE_BODY(merge_configs_upper_empty) { - vars_map lower, upper; - lower["var"] = "value"; - - vars_map merged = impl::merge_configs(lower, upper); - ATF_REQUIRE_EQ("value", merged["var"]); -} - -ATF_TEST_CASE(merge_configs_mixed); -ATF_TEST_CASE_HEAD(merge_configs_mixed) {} -ATF_TEST_CASE_BODY(merge_configs_mixed) { - vars_map lower, upper; - lower["var1"] = "value1"; - lower["var2"] = "value2-l"; - upper["var2"] = "value2-u"; - upper["var3"] = "value3"; - - vars_map merged = impl::merge_configs(lower, upper); - ATF_REQUIRE_EQ("value1", merged["var1"]); - ATF_REQUIRE_EQ("value2-u", merged["var2"]); - ATF_REQUIRE_EQ("value3", merged["var3"]); -} - -ATF_TEST_CASE(read_config_files_none); -ATF_TEST_CASE_HEAD(read_config_files_none) {} -ATF_TEST_CASE_BODY(read_config_files_none) { - tools::env::set("ATF_CONFDIR", "."); - atf::config::__reinit(); - ATF_REQUIRE(vars_map() == impl::read_config_files("test-suite")); -} - -// ------------------------------------------------------------------------- -// Main. -// ------------------------------------------------------------------------- - -ATF_INIT_TEST_CASES(tcs) -{ - ATF_ADD_TEST_CASE(tcs, config_1); - ATF_ADD_TEST_CASE(tcs, config_2); - ATF_ADD_TEST_CASE(tcs, config_3); - ATF_ADD_TEST_CASE(tcs, config_4); - ATF_ADD_TEST_CASE(tcs, config_50); - ATF_ADD_TEST_CASE(tcs, config_51); - ATF_ADD_TEST_CASE(tcs, config_52); - ATF_ADD_TEST_CASE(tcs, config_53); - ATF_ADD_TEST_CASE(tcs, config_54); - - ATF_ADD_TEST_CASE(tcs, merge_configs_both_empty); - ATF_ADD_TEST_CASE(tcs, merge_configs_lower_empty); - ATF_ADD_TEST_CASE(tcs, merge_configs_upper_empty); - ATF_ADD_TEST_CASE(tcs, merge_configs_mixed); - - ATF_ADD_TEST_CASE(tcs, read_config_files_none); -} diff --git a/tools/config_test.cpp b/tools/config_test.cpp deleted file mode 100644 index d7d6719..0000000 --- a/tools/config_test.cpp +++ /dev/null @@ -1,221 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include <cstring> -#include <iostream> - -#include <atf-c++.hpp> - -#include "config.hpp" -#include "env.hpp" -#include "exceptions.hpp" - -static const char *test_value = "env-value"; - -static struct varnames { - const char *lc; - const char *uc; - bool can_be_empty; -} all_vars[] = { - { "atf_arch", "ATF_ARCH", false }, - { "atf_build_cc", "ATF_BUILD_CC", false }, - { "atf_build_cflags", "ATF_BUILD_CFLAGS", true }, - { "atf_build_cpp", "ATF_BUILD_CPP", false }, - { "atf_build_cppflags", "ATF_BUILD_CPPFLAGS", true }, - { "atf_build_cxx", "ATF_BUILD_CXX", false }, - { "atf_build_cxxflags", "ATF_BUILD_CXXFLAGS", true }, - { "atf_confdir", "ATF_CONFDIR", false }, - { "atf_includedir", "ATF_INCLUDEDIR", false }, - { "atf_libdir", "ATF_LIBDIR", false }, - { "atf_libexecdir", "ATF_LIBEXECDIR", false }, - { "atf_machine", "ATF_MACHINE", false }, - { "atf_pkgdatadir", "ATF_PKGDATADIR", false }, - { "atf_shell", "ATF_SHELL", false }, - { "atf_workdir", "ATF_WORKDIR", false }, - { NULL, NULL, false } -}; - -// ------------------------------------------------------------------------ -// Auxiliary functions. -// ------------------------------------------------------------------------ - -namespace tools { - namespace config { - void __reinit(void); - } -} - -static -void -set_env_var(const char* name, const char* val) -{ - try { - tools::env::set(name, val); - } catch (const tools::system_error&) { - ATF_FAIL(std::string("set_env_var(") + name + ", " + val + - ") failed"); - } -} - -static -void -unset_env_var(const char* name) -{ - try { - tools::env::unset(name); - } catch (const tools::system_error&) { - ATF_FAIL(std::string("unset_env_var(") + name + ") failed"); - } -} - -static -size_t -all_vars_count(void) -{ - size_t count = 0; - for (const struct varnames* v = all_vars; v->lc != NULL; v++) - count++; - return count; -} - -static -void -unset_all(void) -{ - for (const struct varnames* v = all_vars; v->lc != NULL; v++) - unset_env_var(v->uc); -} - -static -void -compare_one(const char* var, const char* expvalue) -{ - std::cout << "Checking that " << var << " is set to " << expvalue << "\n"; - - for (const struct varnames* v = all_vars; v->lc != NULL; v++) { - if (std::strcmp(v->lc, var) == 0) - ATF_REQUIRE_EQ(tools::config::get(v->lc), test_value); - else - ATF_REQUIRE(tools::config::get(v->lc) != test_value); - } -} - -// ------------------------------------------------------------------------ -// Test cases for the free functions. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(get); -ATF_TEST_CASE_HEAD(get) -{ - set_md_var("descr", "Tests the config::get function"); -} -ATF_TEST_CASE_BODY(get) -{ - // Unset all known environment variables and make sure the built-in - // values do not match the bogus value we will use for testing. - unset_all(); - tools::config::__reinit(); - for (const struct varnames* v = all_vars; v->lc != NULL; v++) - ATF_REQUIRE(tools::config::get(v->lc) != test_value); - - // Test the behavior of empty values. - for (const struct varnames* v = all_vars; v->lc != NULL; v++) { - unset_all(); - if (!tools::config::get(v->lc).empty()) { - set_env_var(v->uc, ""); - tools::config::__reinit(); - if (v->can_be_empty) - ATF_REQUIRE(tools::config::get(v->lc).empty()); - else - ATF_REQUIRE(!tools::config::get(v->lc).empty()); - } - } - - // Check if the ATF_ARCH variable is recognized. - for (const struct varnames* v = all_vars; v->lc != NULL; v++) { - unset_all(); - set_env_var(v->uc, test_value); - tools::config::__reinit(); - compare_one(v->lc, test_value); - } -} - -ATF_TEST_CASE(get_all); -ATF_TEST_CASE_HEAD(get_all) -{ - set_md_var("descr", "Tests the config::get_all function"); -} -ATF_TEST_CASE_BODY(get_all) -{ - tools::config::__reinit(); - - // Check that the valid variables, and only those, are returned. - std::map< std::string, std::string > vars = tools::config::get_all(); - ATF_REQUIRE_EQ(vars.size(), all_vars_count()); - for (const struct varnames* v = all_vars; v->lc != NULL; v++) - ATF_REQUIRE(vars.find(v->lc) != vars.end()); -} - -ATF_TEST_CASE(has); -ATF_TEST_CASE_HEAD(has) -{ - set_md_var("descr", "Tests the config::has function"); -} -ATF_TEST_CASE_BODY(has) -{ - tools::config::__reinit(); - - // Check for all the variables that must exist. - for (const struct varnames* v = all_vars; v->lc != NULL; v++) - ATF_REQUIRE(tools::config::has(v->lc)); - - // Same as above, but using uppercase (which is incorrect). - for (const struct varnames* v = all_vars; v->lc != NULL; v++) - ATF_REQUIRE(!tools::config::has(v->uc)); - - // Check for some other variables that cannot exist. - ATF_REQUIRE(!tools::config::has("foo")); - ATF_REQUIRE(!tools::config::has("BAR")); - ATF_REQUIRE(!tools::config::has("atf_foo")); - ATF_REQUIRE(!tools::config::has("ATF_BAR")); - ATF_REQUIRE(!tools::config::has("atf_shel")); - ATF_REQUIRE(!tools::config::has("atf_shells")); -} - -// ------------------------------------------------------------------------ -// Main. -// ------------------------------------------------------------------------ - -ATF_INIT_TEST_CASES(tcs) -{ - // Add the test cases for the free functions. - ATF_ADD_TEST_CASE(tcs, has); - ATF_ADD_TEST_CASE(tcs, get); - ATF_ADD_TEST_CASE(tcs, get_all); -} diff --git a/tools/defs.hpp.in b/tools/defs.hpp.in deleted file mode 100644 index 9542795..0000000 --- a/tools/defs.hpp.in +++ /dev/null @@ -1,37 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2008 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if !defined(TOOLS_DEFS_HPP) -#define TOOLS_DEFS_HPP - -#define ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(a, b) @ATTRIBUTE_FORMAT_PRINTF@ -#define ATF_DEFS_ATTRIBUTE_NORETURN @ATTRIBUTE_NORETURN@ -#define ATF_DEFS_ATTRIBUTE_UNUSED @ATTRIBUTE_UNUSED@ - -#endif /* !defined(TOOLS_DEFS_HPP) */ diff --git a/tools/env.cpp b/tools/env.cpp deleted file mode 100644 index 1dbdb55..0000000 --- a/tools/env.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if defined(HAVE_CONFIG_H) -#include "bconfig.h" -#endif - -extern "C" { -#include <errno.h> -#include <stdlib.h> -#include <string.h> -} - -#include <cassert> - -#include "env.hpp" -#include "exceptions.hpp" - -namespace impl = tools::env; -#define IMPL_NAME "tools::env" - -// ------------------------------------------------------------------------ -// Free functions. -// ------------------------------------------------------------------------ - -std::string -impl::get(const std::string& name) -{ - const char* val = getenv(name.c_str()); - assert(val != NULL); - return val; -} - -bool -impl::has(const std::string& name) -{ - return getenv(name.c_str()) != NULL; -} - -void -impl::set(const std::string& name, const std::string& val) -{ -#if defined(HAVE_SETENV) - if (setenv(name.c_str(), val.c_str(), 1) == -1) - throw tools::system_error(IMPL_NAME "::set", - "Cannot set environment variable '" + name + - "' to '" + val + "'", - errno); -#elif defined(HAVE_PUTENV) - const std::string buf = name + "=" + val; - if (putenv(strdup(buf.c_str())) == -1) - throw tools::system_error(IMPL_NAME "::set", - "Cannot set environment variable '" + name + - "' to '" + val + "'", - errno); -#else -# error "Don't know how to set an environment variable." -#endif -} - -void -impl::unset(const std::string& name) -{ -#if defined(HAVE_UNSETENV) - unsetenv(name.c_str()); -#elif defined(HAVE_PUTENV) - const std::string buf = name + "="; - - if (putenv(strdup(buf.c_str())) == -1) - throw tools::system_error(IMPL_NAME "::unset", - "Cannot unset environment variable '" + - name + "'", errno); -#else -# error "Don't know how to unset an environment variable." -#endif -} diff --git a/tools/env.hpp b/tools/env.hpp deleted file mode 100644 index f87a58f..0000000 --- a/tools/env.hpp +++ /dev/null @@ -1,84 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if !defined(TOOLS_ENV_HPP) -#define TOOLS_ENV_HPP - -#include <string> - -namespace tools { -namespace env { - -// ------------------------------------------------------------------------ -// Free functions. -// ------------------------------------------------------------------------ - -//! -//! \brief Returns the value of an environment variable. -//! -//! Returns the value of the specified environment variable. The variable -//! must be defined. -//! -std::string get(const std::string&); - -//! -//! \brief Checks if the environment has a variable. -//! -//! Checks if the environment has a given variable. -//! -bool has(const std::string&); - -//! -//! \brief Sets an environment variable to a given value. -//! -//! Sets the specified environment variable to the given value. Note that -//! variables set to the empty string are different to undefined ones. -//! -//! Be aware that this alters the program's global status, which in general -//! is a bad thing to do due to the side-effects it may have. There are -//! some legitimate usages for this function, though. -//! -void set(const std::string&, const std::string&); - -//! -//! \brief Unsets an environment variable. -//! -//! Unsets the specified environment variable Note that undefined -//! variables are different to those defined but set to an empty value. -//! -//! Be aware that this alters the program's global status, which in general -//! is a bad thing to do due to the side-effects it may have. There are -//! some legitimate usages for this function, though. -//! -void unset(const std::string&); - -} // namespace env -} // namespace tools - -#endif // !defined(TOOLS_ENV_HPP) diff --git a/tools/env_test.cpp b/tools/env_test.cpp deleted file mode 100644 index 441a16f..0000000 --- a/tools/env_test.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include <atf-c++.hpp> - -#include "env.hpp" - -// ------------------------------------------------------------------------ -// Test cases for the free functions. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(has_get); -ATF_TEST_CASE_HEAD(has_get) -{ - set_md_var("descr", "Tests the has and get functions"); -} -ATF_TEST_CASE_BODY(has_get) -{ - ATF_REQUIRE(tools::env::has("PATH")); - ATF_REQUIRE(!tools::env::get("PATH").empty()); - - ATF_REQUIRE(!tools::env::has("_UNDEFINED_VARIABLE_")); -} - -ATF_TEST_CASE(set); -ATF_TEST_CASE_HEAD(set) -{ - set_md_var("descr", "Tests the set function"); -} -ATF_TEST_CASE_BODY(set) -{ - ATF_REQUIRE(tools::env::has("PATH")); - const std::string& oldval = tools::env::get("PATH"); - tools::env::set("PATH", "foo-bar"); - ATF_REQUIRE(tools::env::get("PATH") != oldval); - ATF_REQUIRE_EQ(tools::env::get("PATH"), "foo-bar"); - - ATF_REQUIRE(!tools::env::has("_UNDEFINED_VARIABLE_")); - tools::env::set("_UNDEFINED_VARIABLE_", "foo2-bar2"); - ATF_REQUIRE_EQ(tools::env::get("_UNDEFINED_VARIABLE_"), "foo2-bar2"); -} - -ATF_TEST_CASE(unset); -ATF_TEST_CASE_HEAD(unset) -{ - set_md_var("descr", "Tests the unset function"); -} -ATF_TEST_CASE_BODY(unset) -{ - ATF_REQUIRE(tools::env::has("PATH")); - tools::env::unset("PATH"); - ATF_REQUIRE(!tools::env::has("PATH")); -} - -// ------------------------------------------------------------------------ -// Main. -// ------------------------------------------------------------------------ - -ATF_INIT_TEST_CASES(tcs) -{ - // Add the test cases for the free functions. - ATF_ADD_TEST_CASE(tcs, has_get); - ATF_ADD_TEST_CASE(tcs, set); - ATF_ADD_TEST_CASE(tcs, unset); -} diff --git a/tools/exceptions.cpp b/tools/exceptions.cpp deleted file mode 100644 index 8587121..0000000 --- a/tools/exceptions.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include <cstring> - -#include "exceptions.hpp" - -// ------------------------------------------------------------------------ -// The "system_error" type. -// ------------------------------------------------------------------------ - -tools::system_error::system_error(const std::string& who, - const std::string& message, - int sys_err) : - std::runtime_error(who + ": " + message), - m_sys_err(sys_err) -{ -} - -tools::system_error::~system_error(void) - throw() -{ -} - -int -tools::system_error::code(void) - const - throw() -{ - return m_sys_err; -} - -const char* -tools::system_error::what(void) - const - throw() -{ - try { - if (m_message.length() == 0) { - m_message = std::string(std::runtime_error::what()) + ": "; - m_message += ::strerror(m_sys_err); - } - - return m_message.c_str(); - } catch (...) { - return "Unable to format system_error message"; - } -} diff --git a/tools/exceptions.hpp b/tools/exceptions.hpp deleted file mode 100644 index 4346b7b..0000000 --- a/tools/exceptions.hpp +++ /dev/null @@ -1,93 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if !defined(TOOLS_EXCEPTIONS_HPP) -#define TOOLS_EXCEPTIONS_HPP - -#include <stdexcept> -#include <string> - -namespace tools { - -template< class T > -class not_found_error : - public std::runtime_error -{ - T m_value; - -public: - not_found_error(const std::string& message, const T& value) throw(); - - virtual ~not_found_error(void) throw(); - - const T& get_value(void) const throw(); -}; - -template< class T > -inline -not_found_error< T >::not_found_error(const std::string& message, - const T& value) - throw() : - std::runtime_error(message), - m_value(value) -{ -} - -template< class T > -inline -not_found_error< T >::~not_found_error(void) - throw() -{ -} - -template< class T > -inline -const T& -not_found_error< T >::get_value(void) - const - throw() -{ - return m_value; -} - -class system_error : public std::runtime_error { - int m_sys_err; - mutable std::string m_message; - -public: - system_error(const std::string&, const std::string&, int); - ~system_error(void) throw(); - - int code(void) const throw(); - const char* what(void) const throw(); -}; - -} // namespace tools - -#endif // !defined(TOOLS_EXCEPTIONS_HPP) diff --git a/tools/expand.cpp b/tools/expand.cpp deleted file mode 100644 index 3ae27d0..0000000 --- a/tools/expand.cpp +++ /dev/null @@ -1,81 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include <stdexcept> - -#include "expand.hpp" -#include "text.hpp" - -namespace impl = tools::expand; -#define IMPL_NAME "tools::expand" - -// ------------------------------------------------------------------------ -// Auxiliary functions. -// ------------------------------------------------------------------------ - -namespace { - -std::string -glob_to_regex(const std::string& glob) -{ - std::string regex; - regex.reserve(glob.length() * 2); - - regex += '^'; - for (std::string::const_iterator iter = glob.begin(); iter != glob.end(); - iter++) { - switch (*iter) { - case '*': regex += ".*"; break; - case '?': regex += "."; break; - default: regex += *iter; - } - } - regex += '$'; - - return regex; -} - -} // anonymous namespace - -// ------------------------------------------------------------------------ -// Free functions. -// ------------------------------------------------------------------------ - -bool -impl::is_glob(const std::string& glob) -{ - // NOTE: Keep this in sync with glob_to_regex! - return glob.find_first_of("*?") != std::string::npos; -} - -bool -impl::matches_glob(const std::string& glob, const std::string& candidate) -{ - return tools::text::match(candidate, glob_to_regex(glob)); -} diff --git a/tools/expand.hpp b/tools/expand.hpp deleted file mode 100644 index b813544..0000000 --- a/tools/expand.hpp +++ /dev/null @@ -1,82 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if !defined(TOOLS_EXPAND_HPP) -#define TOOLS_EXPAND_HPP - -#include <string> -#include <vector> - -namespace tools { -namespace expand { - -// ------------------------------------------------------------------------ -// Free functions. -// ------------------------------------------------------------------------ - -//! -//! \brief Checks if the given string is a glob pattern. -//! -//! Returns true if the given string is a glob pattern; i.e. if it contains -//! any character that will be expanded by expand_glob. -//! -bool is_glob(const std::string&); - -//! -//! \brief Checks if a given string matches a glob pattern. -//! -//! Given a glob pattern and a string, checks whether the former matches -//! the latter. Returns a boolean indicating this condition. -//! -bool matches_glob(const std::string&, const std::string&); - -//! -//! \brief Expands a glob pattern among multiple candidates. -//! -//! Given a glob pattern and a set of candidate strings, checks which of -//! those strings match the glob pattern and returns them. -//! -template< class T > -std::vector< std::string > expand_glob(const std::string& glob, - const T& candidates) -{ - std::vector< std::string > exps; - - for (typename T::const_iterator iter = candidates.begin(); - iter != candidates.end(); iter++) - if (matches_glob(glob, *iter)) - exps.push_back(*iter); - - return exps; -} - -} // namespace expand -} // namespace tools - -#endif // !defined(TOOLS_EXPAND_HPP) diff --git a/tools/expand_test.cpp b/tools/expand_test.cpp deleted file mode 100644 index fb59de8..0000000 --- a/tools/expand_test.cpp +++ /dev/null @@ -1,272 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include <cstring> - -#include <atf-c++.hpp> - -#include "expand.hpp" - -// XXX Many of the tests here are duplicated in atf-c/t_expand. Should -// find a way to easily share them, or maybe remove the ones here. - -// ------------------------------------------------------------------------ -// Test cases for the free functions. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(is_glob); -ATF_TEST_CASE_HEAD(is_glob) -{ - set_md_var("descr", "Tests the is_glob function."); -} -ATF_TEST_CASE_BODY(is_glob) -{ - using tools::expand::is_glob; - - ATF_REQUIRE(!is_glob("")); - ATF_REQUIRE(!is_glob("a")); - ATF_REQUIRE(!is_glob("foo")); - - ATF_REQUIRE( is_glob("*")); - ATF_REQUIRE( is_glob("a*")); - ATF_REQUIRE( is_glob("*a")); - ATF_REQUIRE( is_glob("a*b")); - - ATF_REQUIRE( is_glob("?")); - ATF_REQUIRE( is_glob("a?")); - ATF_REQUIRE( is_glob("?a")); - ATF_REQUIRE( is_glob("a?b")); -} - -ATF_TEST_CASE(matches_glob_plain); -ATF_TEST_CASE_HEAD(matches_glob_plain) -{ - set_md_var("descr", "Tests the matches_glob function by using plain " - "text strings as patterns only."); -} -ATF_TEST_CASE_BODY(matches_glob_plain) -{ - using tools::expand::matches_glob; - - ATF_REQUIRE( matches_glob("", "")); - ATF_REQUIRE(!matches_glob("a", "")); - ATF_REQUIRE(!matches_glob("", "a")); - - ATF_REQUIRE( matches_glob("ab", "ab")); - ATF_REQUIRE(!matches_glob("abc", "ab")); - ATF_REQUIRE(!matches_glob("ab", "abc")); -} - -ATF_TEST_CASE(matches_glob_star); -ATF_TEST_CASE_HEAD(matches_glob_star) -{ - set_md_var("descr", "Tests the matches_glob function by using the '*' " - "meta-character as part of the pattern."); -} -ATF_TEST_CASE_BODY(matches_glob_star) -{ - using tools::expand::matches_glob; - - ATF_REQUIRE( matches_glob("*", "")); - ATF_REQUIRE( matches_glob("*", "a")); - ATF_REQUIRE( matches_glob("*", "ab")); - - ATF_REQUIRE(!matches_glob("a*", "")); - ATF_REQUIRE( matches_glob("a*", "a")); - ATF_REQUIRE( matches_glob("a*", "aa")); - ATF_REQUIRE( matches_glob("a*", "ab")); - ATF_REQUIRE( matches_glob("a*", "abc")); - ATF_REQUIRE(!matches_glob("a*", "ba")); - - ATF_REQUIRE( matches_glob("*a", "a")); - ATF_REQUIRE( matches_glob("*a", "ba")); - ATF_REQUIRE(!matches_glob("*a", "bc")); - ATF_REQUIRE(!matches_glob("*a", "bac")); - - ATF_REQUIRE( matches_glob("*ab", "ab")); - ATF_REQUIRE( matches_glob("*ab", "aab")); - ATF_REQUIRE( matches_glob("*ab", "aaab")); - ATF_REQUIRE( matches_glob("*ab", "bab")); - ATF_REQUIRE(!matches_glob("*ab", "bcb")); - ATF_REQUIRE(!matches_glob("*ab", "bacb")); - - ATF_REQUIRE( matches_glob("a*b", "ab")); - ATF_REQUIRE( matches_glob("a*b", "acb")); - ATF_REQUIRE( matches_glob("a*b", "acdeb")); - ATF_REQUIRE(!matches_glob("a*b", "acdebz")); - ATF_REQUIRE(!matches_glob("a*b", "zacdeb")); -} - -ATF_TEST_CASE(matches_glob_question); -ATF_TEST_CASE_HEAD(matches_glob_question) -{ - set_md_var("descr", "Tests the matches_glob function by using the '?' " - "meta-character as part of the pattern."); -} -ATF_TEST_CASE_BODY(matches_glob_question) -{ - using tools::expand::matches_glob; - - ATF_REQUIRE(!matches_glob("?", "")); - ATF_REQUIRE( matches_glob("?", "a")); - ATF_REQUIRE(!matches_glob("?", "ab")); - - ATF_REQUIRE( matches_glob("?", "b")); - ATF_REQUIRE( matches_glob("?", "c")); - - ATF_REQUIRE( matches_glob("a?", "ab")); - ATF_REQUIRE( matches_glob("a?", "ac")); - ATF_REQUIRE(!matches_glob("a?", "ca")); - - ATF_REQUIRE( matches_glob("???", "abc")); - ATF_REQUIRE( matches_glob("???", "def")); - ATF_REQUIRE(!matches_glob("???", "a")); - ATF_REQUIRE(!matches_glob("???", "ab")); - ATF_REQUIRE(!matches_glob("???", "abcd")); -} - -ATF_TEST_CASE(expand_glob_base); -ATF_TEST_CASE_HEAD(expand_glob_base) -{ - set_md_var("descr", "Tests the expand_glob function with random " - "patterns."); -} -ATF_TEST_CASE_BODY(expand_glob_base) -{ - using tools::expand::expand_glob; - - std::vector< std::string > candidates; - candidates.push_back("foo"); - candidates.push_back("bar"); - candidates.push_back("baz"); - candidates.push_back("foobar"); - candidates.push_back("foobarbaz"); - candidates.push_back("foobarbazfoo"); - - std::vector< std::string > exps; - - exps = expand_glob("foo", candidates); - ATF_REQUIRE_EQ(exps.size(), 1); - ATF_REQUIRE(exps[0] == "foo"); - - exps = expand_glob("bar", candidates); - ATF_REQUIRE_EQ(exps.size(), 1); - ATF_REQUIRE(exps[0] == "bar"); - - exps = expand_glob("foo*", candidates); - ATF_REQUIRE_EQ(exps.size(), 4); - ATF_REQUIRE(exps[0] == "foo"); - ATF_REQUIRE(exps[1] == "foobar"); - ATF_REQUIRE(exps[2] == "foobarbaz"); - ATF_REQUIRE(exps[3] == "foobarbazfoo"); - - exps = expand_glob("*foo", candidates); - ATF_REQUIRE_EQ(exps.size(), 2); - ATF_REQUIRE(exps[0] == "foo"); - ATF_REQUIRE(exps[1] == "foobarbazfoo"); - - exps = expand_glob("*foo*", candidates); - ATF_REQUIRE_EQ(exps.size(), 4); - ATF_REQUIRE(exps[0] == "foo"); - ATF_REQUIRE(exps[1] == "foobar"); - ATF_REQUIRE(exps[2] == "foobarbaz"); - ATF_REQUIRE(exps[3] == "foobarbazfoo"); - - exps = expand_glob("ba", candidates); - ATF_REQUIRE_EQ(exps.size(), 0); - - exps = expand_glob("ba*", candidates); - ATF_REQUIRE_EQ(exps.size(), 2); - ATF_REQUIRE(exps[0] == "bar"); - ATF_REQUIRE(exps[1] == "baz"); - - exps = expand_glob("*ba", candidates); - ATF_REQUIRE_EQ(exps.size(), 0); - - exps = expand_glob("*ba*", candidates); - ATF_REQUIRE_EQ(exps.size(), 5); - ATF_REQUIRE(exps[0] == "bar"); - ATF_REQUIRE(exps[1] == "baz"); - ATF_REQUIRE(exps[2] == "foobar"); - ATF_REQUIRE(exps[3] == "foobarbaz"); - ATF_REQUIRE(exps[4] == "foobarbazfoo"); -} - -ATF_TEST_CASE(expand_glob_tps); -ATF_TEST_CASE_HEAD(expand_glob_tps) -{ - set_md_var("descr", "Tests the expand_glob function with patterns that " - "match typical test program names. This is just a subcase " - "of expand_base, but it is nice to make sure that it really " - "works."); -} -ATF_TEST_CASE_BODY(expand_glob_tps) -{ - using tools::expand::expand_glob; - - std::vector< std::string > candidates; - candidates.push_back("Atffile"); - candidates.push_back("h_foo"); - candidates.push_back("t_foo"); - candidates.push_back("t_bar"); - candidates.push_back("t_baz"); - candidates.push_back("foo_helper"); - candidates.push_back("foo_test"); - candidates.push_back("bar_test"); - candidates.push_back("baz_test"); - - std::vector< std::string > exps; - - exps = expand_glob("t_*", candidates); - ATF_REQUIRE_EQ(exps.size(), 3); - ATF_REQUIRE(exps[0] == "t_foo"); - ATF_REQUIRE(exps[1] == "t_bar"); - ATF_REQUIRE(exps[2] == "t_baz"); - - exps = expand_glob("*_test", candidates); - ATF_REQUIRE_EQ(exps.size(), 3); - ATF_REQUIRE(exps[0] == "foo_test"); - ATF_REQUIRE(exps[1] == "bar_test"); - ATF_REQUIRE(exps[2] == "baz_test"); -} - -// ------------------------------------------------------------------------ -// Main. -// ------------------------------------------------------------------------ - -ATF_INIT_TEST_CASES(tcs) -{ - // Add the tests for the free functions. - ATF_ADD_TEST_CASE(tcs, is_glob); - ATF_ADD_TEST_CASE(tcs, matches_glob_plain); - ATF_ADD_TEST_CASE(tcs, matches_glob_star); - ATF_ADD_TEST_CASE(tcs, matches_glob_question); - ATF_ADD_TEST_CASE(tcs, expand_glob_base); - ATF_ADD_TEST_CASE(tcs, expand_glob_tps); -} diff --git a/tools/expect_helpers.c b/tools/expect_helpers.c deleted file mode 100644 index b38ccf5..0000000 --- a/tools/expect_helpers.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * 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 <signal.h> -#include <stdlib.h> -#include <unistd.h> - -#include <atf-c.h> - -ATF_TC_WITHOUT_HEAD(pass_and_pass); -ATF_TC_BODY(pass_and_pass, tc) -{ - atf_tc_expect_pass(); -} - -ATF_TC_WITHOUT_HEAD(pass_but_fail_requirement); -ATF_TC_BODY(pass_but_fail_requirement, tc) -{ - atf_tc_expect_pass(); - atf_tc_fail("Some reason"); -} - -ATF_TC_WITHOUT_HEAD(pass_but_fail_check); -ATF_TC_BODY(pass_but_fail_check, tc) -{ - atf_tc_expect_pass(); - atf_tc_fail_nonfatal("Some reason"); -} - -ATF_TC_WITHOUT_HEAD(fail_and_fail_requirement); -ATF_TC_BODY(fail_and_fail_requirement, tc) -{ - atf_tc_expect_fail("Fail %s", "reason"); - atf_tc_fail("The failure"); - atf_tc_expect_pass(); -} - -ATF_TC_WITHOUT_HEAD(fail_and_fail_check); -ATF_TC_BODY(fail_and_fail_check, tc) -{ - atf_tc_expect_fail("Fail first"); - atf_tc_fail_nonfatal("abc"); - atf_tc_expect_pass(); - - atf_tc_expect_fail("And fail again"); - atf_tc_fail_nonfatal("def"); - atf_tc_expect_pass(); -} - -ATF_TC_WITHOUT_HEAD(fail_but_pass); -ATF_TC_BODY(fail_but_pass, tc) -{ - atf_tc_expect_fail("Fail first"); - atf_tc_fail_nonfatal("abc"); - atf_tc_expect_pass(); - - atf_tc_expect_fail("Will not fail"); - atf_tc_expect_pass(); - - atf_tc_expect_fail("And fail again"); - atf_tc_fail_nonfatal("def"); - atf_tc_expect_pass(); -} - -ATF_TC_WITHOUT_HEAD(exit_any_and_exit); -ATF_TC_BODY(exit_any_and_exit, tc) -{ - atf_tc_expect_exit(-1, "Call will exit"); - exit(EXIT_SUCCESS); -} - -ATF_TC_WITHOUT_HEAD(exit_code_and_exit); -ATF_TC_BODY(exit_code_and_exit, tc) -{ - atf_tc_expect_exit(123, "Call will exit"); - exit(123); -} - -ATF_TC_WITHOUT_HEAD(exit_but_pass); -ATF_TC_BODY(exit_but_pass, tc) -{ - atf_tc_expect_exit(-1, "Call won't exit"); -} - -ATF_TC_WITHOUT_HEAD(signal_any_and_signal); -ATF_TC_BODY(signal_any_and_signal, tc) -{ - atf_tc_expect_signal(-1, "Call will signal"); - kill(getpid(), SIGKILL); -} - -ATF_TC_WITHOUT_HEAD(signal_no_and_signal); -ATF_TC_BODY(signal_no_and_signal, tc) -{ - atf_tc_expect_signal(SIGHUP, "Call will signal"); - kill(getpid(), SIGHUP); -} - -ATF_TC_WITHOUT_HEAD(signal_but_pass); -ATF_TC_BODY(signal_but_pass, tc) -{ - atf_tc_expect_signal(-1, "Call won't signal"); -} - -ATF_TC_WITHOUT_HEAD(death_and_exit); -ATF_TC_BODY(death_and_exit, tc) -{ - atf_tc_expect_death("Exit case"); - exit(123); -} - -ATF_TC_WITHOUT_HEAD(death_and_signal); -ATF_TC_BODY(death_and_signal, tc) -{ - atf_tc_expect_death("Signal case"); - kill(getpid(), SIGKILL); -} - -ATF_TC_WITHOUT_HEAD(death_but_pass); -ATF_TC_BODY(death_but_pass, tc) -{ - atf_tc_expect_death("Call won't die"); -} - -ATF_TC(timeout_and_hang); -ATF_TC_HEAD(timeout_and_hang, tc) -{ - atf_tc_set_md_var(tc, "timeout", "1"); -} -ATF_TC_BODY(timeout_and_hang, tc) -{ - atf_tc_expect_timeout("Will overrun"); - sleep(5); -} - -ATF_TC(timeout_but_pass); -ATF_TC_HEAD(timeout_but_pass, tc) -{ - atf_tc_set_md_var(tc, "timeout", "1"); -} -ATF_TC_BODY(timeout_but_pass, tc) -{ - atf_tc_expect_timeout("Will just exit"); -} - -ATF_TP_ADD_TCS(tp) -{ - ATF_TP_ADD_TC(tp, pass_and_pass); - ATF_TP_ADD_TC(tp, pass_but_fail_requirement); - ATF_TP_ADD_TC(tp, pass_but_fail_check); - ATF_TP_ADD_TC(tp, fail_and_fail_requirement); - ATF_TP_ADD_TC(tp, fail_and_fail_check); - ATF_TP_ADD_TC(tp, fail_but_pass); - ATF_TP_ADD_TC(tp, exit_any_and_exit); - ATF_TP_ADD_TC(tp, exit_code_and_exit); - ATF_TP_ADD_TC(tp, exit_but_pass); - ATF_TP_ADD_TC(tp, signal_any_and_signal); - ATF_TP_ADD_TC(tp, signal_no_and_signal); - ATF_TP_ADD_TC(tp, signal_but_pass); - ATF_TP_ADD_TC(tp, death_and_exit); - ATF_TP_ADD_TC(tp, death_and_signal); - ATF_TP_ADD_TC(tp, death_but_pass); - ATF_TP_ADD_TC(tp, timeout_and_hang); - ATF_TP_ADD_TC(tp, timeout_but_pass); - - return atf_no_error(); -} diff --git a/tools/fail_helper.cpp b/tools/fail_helper.cpp deleted file mode 100644 index 736b5e8..0000000 --- a/tools/fail_helper.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include <atf-c++.hpp> - -ATF_TEST_CASE(main); -ATF_TEST_CASE_HEAD(main) -{ - set_md_var("descr", "Helper test case that always fails"); -} -ATF_TEST_CASE_BODY(main) -{ - fail("This always fails"); -} - -ATF_INIT_TEST_CASES(tcs) -{ - ATF_ADD_TEST_CASE(tcs, main); -} diff --git a/tools/fs.cpp b/tools/fs.cpp deleted file mode 100644 index fde7815..0000000 --- a/tools/fs.cpp +++ /dev/null @@ -1,744 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if defined(HAVE_CONFIG_H) -#include "bconfig.h" -#endif - -extern "C" { -#include <sys/param.h> -#include <sys/types.h> -#include <sys/mount.h> -#include <sys/stat.h> -#include <sys/wait.h> - -#include <dirent.h> -#include <libgen.h> -#include <unistd.h> -} - -#include <cassert> -#include <cerrno> -#include <cstdlib> -#include <cstring> - -#include "auto_array.hpp" -#include "env.hpp" -#include "exceptions.hpp" -#include "fs.hpp" -#include "process.hpp" -#include "text.hpp" -#include "user.hpp" - -namespace impl = tools::fs; -#define IMPL_NAME "tools::fs" - -// ------------------------------------------------------------------------ -// Auxiliary functions. -// ------------------------------------------------------------------------ - -static void cleanup_aux(const impl::path&, dev_t, bool); -static void cleanup_aux_dir(const impl::path&, const impl::file_info&, - bool); -static void do_unmount(const impl::path&); -static bool safe_access(const impl::path&, int, int); - -static const int access_f = 1 << 0; -static const int access_r = 1 << 1; -static const int access_w = 1 << 2; -static const int access_x = 1 << 3; - -//! -//! An implementation of access(2) but using the effective user value -//! instead of the real one. Also avoids false positives for root when -//! asking for execute permissions, which appear in SunOS. -//! -static -void -eaccess(const tools::fs::path& p, int mode) -{ - assert(mode & access_f || mode & access_r || - mode & access_w || mode & access_x); - - struct stat st; - if (lstat(p.c_str(), &st) == -1) - throw tools::system_error(IMPL_NAME "::eaccess", - "Cannot get information from file " + - p.str(), errno); - - /* Early return if we are only checking for existence and the file - * exists (stat call returned). */ - if (mode & access_f) - return; - - bool ok = false; - if (tools::user::is_root()) { - if (!ok && !(mode & access_x)) { - /* Allow root to read/write any file. */ - ok = true; - } - - if (!ok && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) { - /* Allow root to execute the file if any of its execution bits - * are set. */ - ok = true; - } - } else { - if (!ok && (tools::user::euid() == st.st_uid)) { - ok = ((mode & access_r) && (st.st_mode & S_IRUSR)) || - ((mode & access_w) && (st.st_mode & S_IWUSR)) || - ((mode & access_x) && (st.st_mode & S_IXUSR)); - } - if (!ok && tools::user::is_member_of_group(st.st_gid)) { - ok = ((mode & access_r) && (st.st_mode & S_IRGRP)) || - ((mode & access_w) && (st.st_mode & S_IWGRP)) || - ((mode & access_x) && (st.st_mode & S_IXGRP)); - } - if (!ok && ((tools::user::euid() != st.st_uid) && - !tools::user::is_member_of_group(st.st_gid))) { - ok = ((mode & access_r) && (st.st_mode & S_IROTH)) || - ((mode & access_w) && (st.st_mode & S_IWOTH)) || - ((mode & access_x) && (st.st_mode & S_IXOTH)); - } - } - - if (!ok) - throw tools::system_error(IMPL_NAME "::eaccess", "Access check failed", - EACCES); -} - -//! -//! \brief A controlled version of access(2). -//! -//! This function reimplements the standard access(2) system call to -//! safely control its exit status and raise an exception in case of -//! failure. -//! -static -bool -safe_access(const impl::path& p, int mode, int experr) -{ - try { - eaccess(p, mode); - return true; - } catch (const tools::system_error& e) { - if (e.code() == experr) - return false; - else - throw e; - } -} - -// The cleanup routines below are tricky: they are executed immediately after -// a test case's death, and after we have forcibly killed any stale processes. -// However, even if the processes are dead, this does not mean that the file -// system we are scanning is stable. In particular, if the test case has -// mounted file systems through fuse/puffs, the fact that the processes died -// does not mean that the file system is truly unmounted. -// -// The code below attempts to cope with this by catching errors and either -// ignoring them or retrying the actions on the same file/directory a few times -// before giving up. -static const int max_retries = 5; -static const int retry_delay_in_seconds = 1; - -// The erase parameter in this routine is to control nested mount points. -// We want to descend into a mount point to unmount anything that is -// mounted under it, but we do not want to delete any files while doing -// this traversal. In other words, we erase files until we cross the -// first mount point, and after that point we only scan and unmount. -static -void -cleanup_aux(const impl::path& p, dev_t parent_device, bool erase) -{ - try { - impl::file_info fi(p); - - if (fi.get_type() == impl::file_info::dir_type) - cleanup_aux_dir(p, fi, fi.get_device() == parent_device); - - if (fi.get_device() != parent_device) - do_unmount(p); - - if (erase) { - if (fi.get_type() == impl::file_info::dir_type) - impl::rmdir(p); - else - impl::remove(p); - } - } catch (const tools::system_error& e) { - if (e.code() != ENOENT && e.code() != ENOTDIR) - throw e; - } -} - -static -void -cleanup_aux_dir(const impl::path& p, const impl::file_info& fi, - bool erase) -{ - if (erase && ((fi.get_mode() & S_IRWXU) != S_IRWXU)) { - int retries = max_retries; -retry_chmod: - if (chmod(p.c_str(), fi.get_mode() | S_IRWXU) == -1) { - if (retries > 0) { - retries--; - ::sleep(retry_delay_in_seconds); - goto retry_chmod; - } else { - throw tools::system_error(IMPL_NAME "::cleanup(" + - p.str() + ")", "chmod(2) failed", - errno); - } - } - } - - std::set< std::string > subdirs; - { - bool ok = false; - int retries = max_retries; - while (!ok) { - assert(retries > 0); - try { - const impl::directory d(p); - subdirs = d.names(); - ok = true; - } catch (const tools::system_error& e) { - retries--; - if (retries == 0) - throw e; - ::sleep(retry_delay_in_seconds); - } - } - assert(ok); - } - - for (std::set< std::string >::const_iterator iter = subdirs.begin(); - iter != subdirs.end(); iter++) { - const std::string& name = *iter; - if (name != "." && name != "..") - cleanup_aux(p / name, fi.get_device(), erase); - } -} - -static -void -do_unmount(const impl::path& in_path) -{ - // At least, FreeBSD's unmount(2) requires the path to be absolute. - // Let's make it absolute in all cases just to be safe that this does - // not affect other systems. - const impl::path& abs_path = in_path.is_absolute() ? - in_path : in_path.to_absolute(); - -#if defined(HAVE_UNMOUNT) - int retries = max_retries; -retry_unmount: - if (unmount(abs_path.c_str(), 0) == -1) { - if (errno == EBUSY && retries > 0) { - retries--; - ::sleep(retry_delay_in_seconds); - goto retry_unmount; - } else { - throw tools::system_error(IMPL_NAME "::cleanup(" + in_path.str() + - ")", "unmount(2) failed", errno); - } - } -#else - // We could use umount(2) instead if it was available... but - // trying to do so under, e.g. Linux, is a nightmare because we - // also have to update /etc/mtab to match what we did. It is - // stools::fser to just leave the system-specific umount(8) tool deal - // with it, at least for now. - - const impl::path prog("umount"); - tools::process::argv_array argv("umount", abs_path.c_str(), NULL); - - tools::process::status s = tools::process::exec(prog, argv, - tools::process::stream_inherit(), tools::process::stream_inherit()); - if (!s.exited() || s.exitstatus() != EXIT_SUCCESS) - throw std::runtime_error("Call to unmount failed"); -#endif -} - -static -std::string -normalize(const std::string& in) -{ - assert(!in.empty()); - - std::string out; - - std::string::size_type pos = 0; - do { - const std::string::size_type next_pos = in.find('/', pos); - - const std::string component = in.substr(pos, next_pos - pos); - if (!component.empty()) { - if (pos == 0) - out += component; - else if (component != ".") - out += "/" + component; - } - - if (next_pos == std::string::npos) - pos = next_pos; - else - pos = next_pos + 1; - } while (pos != std::string::npos); - - return out.empty() ? "/" : out; -} - -// ------------------------------------------------------------------------ -// The "path" class. -// ------------------------------------------------------------------------ - -impl::path::path(const std::string& s) : - m_data(normalize(s)) -{ -} - -impl::path::~path(void) -{ -} - -const char* -impl::path::c_str(void) - const -{ - return m_data.c_str(); -} - -std::string -impl::path::str(void) - const -{ - return m_data; -} - -bool -impl::path::is_absolute(void) - const -{ - return !m_data.empty() && m_data[0] == '/'; -} - -bool -impl::path::is_root(void) - const -{ - return m_data == "/"; -} - -impl::path -impl::path::branch_path(void) - const -{ - const std::string::size_type endpos = m_data.rfind('/'); - if (endpos == std::string::npos) - return path("."); - else if (endpos == 0) - return path("/"); - else - return path(m_data.substr(0, endpos)); -} - -std::string -impl::path::leaf_name(void) - const -{ - std::string::size_type begpos = m_data.rfind('/'); - if (begpos == std::string::npos) - begpos = 0; - else - begpos++; - - return m_data.substr(begpos); -} - -impl::path -impl::path::to_absolute(void) - const -{ - assert(!is_absolute()); - return get_current_dir() / m_data; -} - -bool -impl::path::operator==(const path& p) - const -{ - return m_data == p.m_data; -} - -bool -impl::path::operator!=(const path& p) - const -{ - return m_data != p.m_data; -} - -impl::path -impl::path::operator/(const std::string& p) - const -{ - return path(m_data + "/" + normalize(p)); -} - -impl::path -impl::path::operator/(const path& p) - const -{ - return path(m_data) / p.m_data; -} - -bool -impl::path::operator<(const path& p) - const -{ - return std::strcmp(m_data.c_str(), p.m_data.c_str()) < 0; -} - -// ------------------------------------------------------------------------ -// The "file_info" class. -// ------------------------------------------------------------------------ - -const int impl::file_info::blk_type = 1; -const int impl::file_info::chr_type = 2; -const int impl::file_info::dir_type = 3; -const int impl::file_info::fifo_type = 4; -const int impl::file_info::lnk_type = 5; -const int impl::file_info::reg_type = 6; -const int impl::file_info::sock_type = 7; -const int impl::file_info::wht_type = 8; - -impl::file_info::file_info(const path& p) -{ - if (lstat(p.c_str(), &m_sb) == -1) - throw system_error(IMPL_NAME "::file_info", - "Cannot get information of " + p.str() + "; " + - "lstat(2) failed", errno); - - int type = m_sb.st_mode & S_IFMT; - switch (type) { - case S_IFBLK: m_type = blk_type; break; - case S_IFCHR: m_type = chr_type; break; - case S_IFDIR: m_type = dir_type; break; - case S_IFIFO: m_type = fifo_type; break; - case S_IFLNK: m_type = lnk_type; break; - case S_IFREG: m_type = reg_type; break; - case S_IFSOCK: m_type = sock_type; break; -#if defined(S_IFWHT) - case S_IFWHT: m_type = wht_type; break; -#endif - default: - throw system_error(IMPL_NAME "::file_info", "Unknown file type " - "error", EINVAL); - } -} - -impl::file_info::~file_info(void) -{ -} - -dev_t -impl::file_info::get_device(void) - const -{ - return m_sb.st_dev; -} - -ino_t -impl::file_info::get_inode(void) - const -{ - return m_sb.st_ino; -} - -mode_t -impl::file_info::get_mode(void) - const -{ - return m_sb.st_mode & ~S_IFMT; -} - -off_t -impl::file_info::get_size(void) - const -{ - return m_sb.st_size; -} - -int -impl::file_info::get_type(void) - const -{ - return m_type; -} - -bool -impl::file_info::is_owner_readable(void) - const -{ - return m_sb.st_mode & S_IRUSR; -} - -bool -impl::file_info::is_owner_writable(void) - const -{ - return m_sb.st_mode & S_IWUSR; -} - -bool -impl::file_info::is_owner_executable(void) - const -{ - return m_sb.st_mode & S_IXUSR; -} - -bool -impl::file_info::is_group_readable(void) - const -{ - return m_sb.st_mode & S_IRGRP; -} - -bool -impl::file_info::is_group_writable(void) - const -{ - return m_sb.st_mode & S_IWGRP; -} - -bool -impl::file_info::is_group_executable(void) - const -{ - return m_sb.st_mode & S_IXGRP; -} - -bool -impl::file_info::is_other_readable(void) - const -{ - return m_sb.st_mode & S_IROTH; -} - -bool -impl::file_info::is_other_writable(void) - const -{ - return m_sb.st_mode & S_IWOTH; -} - -bool -impl::file_info::is_other_executable(void) - const -{ - return m_sb.st_mode & S_IXOTH; -} - -// ------------------------------------------------------------------------ -// The "directory" class. -// ------------------------------------------------------------------------ - -impl::directory::directory(const path& p) -{ - DIR* dp = ::opendir(p.c_str()); - if (dp == NULL) - throw system_error(IMPL_NAME "::directory::directory(" + - p.str() + ")", "opendir(3) failed", errno); - - struct dirent* dep; - while ((dep = ::readdir(dp)) != NULL) { - path entryp = p / dep->d_name; - insert(value_type(dep->d_name, file_info(entryp))); - } - - if (::closedir(dp) == -1) - throw system_error(IMPL_NAME "::directory::directory(" + - p.str() + ")", "closedir(3) failed", errno); -} - -std::set< std::string > -impl::directory::names(void) - const -{ - std::set< std::string > ns; - - for (const_iterator iter = begin(); iter != end(); iter++) - ns.insert((*iter).first); - - return ns; -} - -// ------------------------------------------------------------------------ -// The "temp_dir" class. -// ------------------------------------------------------------------------ - -impl::temp_dir::temp_dir(const path& p) -{ - tools::auto_array< char > buf(new char[p.str().length() + 1]); - std::strcpy(buf.get(), p.c_str()); - if (::mkdtemp(buf.get()) == NULL) - throw tools::system_error(IMPL_NAME "::temp_dir::temp_dir(" + - p.str() + ")", "mkdtemp(3) failed", - errno); - - m_path.reset(new path(buf.get())); -} - -impl::temp_dir::~temp_dir(void) -{ - cleanup(*m_path); -} - -const impl::path& -impl::temp_dir::get_path(void) - const -{ - return *m_path; -} - -// ------------------------------------------------------------------------ -// Free functions. -// ------------------------------------------------------------------------ - -bool -impl::exists(const path& p) -{ - try { - eaccess(p, access_f); - return true; - } catch (const system_error& e) { - if (e.code() == ENOENT) - return false; - else - throw; - } -} - -bool -impl::have_prog_in_path(const std::string& prog) -{ - assert(prog.find('/') == std::string::npos); - - // Do not bother to provide a default value for PATH. If it is not - // there something is broken in the user's environment. - if (!tools::env::has("PATH")) - throw std::runtime_error("PATH not defined in the environment"); - std::vector< std::string > dirs = - tools::text::split(tools::env::get("PATH"), ":"); - - bool found = false; - for (std::vector< std::string >::const_iterator iter = dirs.begin(); - !found && iter != dirs.end(); iter++) { - const path& dir = path(*iter); - - if (is_executable(dir / prog)) - found = true; - } - return found; -} - -bool -impl::is_executable(const path& p) -{ - if (!exists(p)) - return false; - return safe_access(p, access_x, EACCES); -} - -void -impl::remove(const path& p) -{ - if (file_info(p).get_type() == file_info::dir_type) - throw tools::system_error(IMPL_NAME "::remove(" + p.str() + ")", - "Is a directory", - EPERM); - if (::unlink(p.c_str()) == -1) - throw tools::system_error(IMPL_NAME "::remove(" + p.str() + ")", - "unlink(" + p.str() + ") failed", - errno); -} - -void -impl::rmdir(const path& p) -{ - if (::rmdir(p.c_str())) { - if (errno == EEXIST) { - /* Some operating systems (e.g. OpenSolaris 200906) return - * EEXIST instead of ENOTEMPTY for non-empty directories. - * Homogenize the return value so that callers don't need - * to bother about differences in operating systems. */ - errno = ENOTEMPTY; - } - throw system_error(IMPL_NAME "::rmdir", "Cannot remove directory", - errno); - } -} - -impl::path -impl::change_directory(const path& dir) -{ - path olddir = get_current_dir(); - - if (olddir != dir) { - if (::chdir(dir.c_str()) == -1) - throw tools::system_error(IMPL_NAME "::chdir(" + dir.str() + ")", - "chdir(2) failed", errno); - } - - return olddir; -} - -void -impl::cleanup(const path& p) -{ - impl::file_info fi(p); - cleanup_aux(p, fi.get_device(), true); -} - -impl::path -impl::get_current_dir(void) -{ - std::auto_ptr< char > cwd; -#if defined(HAVE_GETCWD_DYN) - cwd.reset(getcwd(NULL, 0)); -#else - cwd.reset(getcwd(NULL, MAXPATHLEN)); -#endif - if (cwd.get() == NULL) - throw tools::system_error(IMPL_NAME "::get_current_dir()", - "getcwd() failed", errno); - - return path(cwd.get()); -} diff --git a/tools/fs.hpp b/tools/fs.hpp deleted file mode 100644 index f45f8f1..0000000 --- a/tools/fs.hpp +++ /dev/null @@ -1,377 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if !defined(TOOLS_FS_HPP) -#define TOOLS_FS_HPP - -extern "C" { -#include <sys/types.h> -#include <sys/stat.h> -} - -#include <map> -#include <memory> -#include <ostream> -#include <set> -#include <stdexcept> -#include <string> - -namespace tools { -namespace fs { - -// ------------------------------------------------------------------------ -// The "path" class. -// ------------------------------------------------------------------------ - -//! -//! \brief A class to represent a path to a file. -//! -//! The path class represents the route to a file or directory in the -//! file system. All file manipulation operations use this class to -//! represent their arguments as it takes care of normalizing user-provided -//! strings and ensures they are valid. -//! -//! It is important to note that the file pointed to by a path need not -//! exist. -//! -class path { - //! - //! \brief Internal representation of a path. - //! - std::string m_data; - -public: - //! \brief Constructs a new path from a user-provided string. - //! - //! This constructor takes a string, either provided by the program's - //! code or by the user and constructs a new path object. The string - //! is normalized to not contain multiple delimiters together and to - //! remove any trailing one. - //! - //! The input string cannot be empty. - //! - explicit path(const std::string&); - - //! - //! \brief Destructor for the path class. - //! - ~path(void); - - //! - //! \brief Returns a pointer to a C-style string representing this path. - //! - const char* c_str(void) const; - - //! - //! \brief Returns a string representing this path. - //! XXX Really needed? - //! - std::string str(void) const; - - //! - //! \brief Returns the branch path of this path. - //! - //! Calculates and returns the branch path of this path. In other - //! words, it returns what the standard ::dirname function would return. - //! - path branch_path(void) const; - - //! - //! \brief Returns the leaf name of this path. - //! - //! Calculates and returns the leaf name of this path. In other words, - //! it returns what the standard ::basename function would return. - //! - std::string leaf_name(void) const; - - //! - //! \brief Checks whether this path is absolute or not. - //! - //! Returns a boolean indicating if this is an absolute path or not; - //! i.e. if it starts with a slash. - //! - bool is_absolute(void) const; - - //! - //! \brief Checks whether this path points to the root directory or not. - //! - //! Returns a boolean indicating if this is path points to the root - //! directory or not. The checks made by this are extremely simple (so - //! the results cannot always be trusted) but they are enough for our - //! modest sanity-checking needs. I.e. "/../" could return false. - //! - bool is_root(void) const; - - //! - //! \brief Converts the path to be absolute. - //! - //! \pre The path was not absolute. - //! - path to_absolute(void) const; - - //! - //! \brief Checks if two paths are equal. - //! - bool operator==(const path&) const; - - //! - //! \brief Checks if two paths are different. - //! - bool operator!=(const path&) const; - - //! - //! \brief Concatenates a path with a string. - //! - //! Constructs a new path object that is the concatenation of the - //! left-hand path with the right-hand string. The string is normalized - //! before the concatenation, and a path delimiter is introduced between - //! the two components if needed. - //! - path operator/(const std::string&) const; - - //! - //! \brief Concatenates a path with another path. - //! - //! Constructs a new path object that is the concatenation of the - //! left-hand path with the right-hand one. A path delimiter is - //! introduced between the two components if needed. - //! - path operator/(const path&) const; - - //! - //! \brief Checks if a path has to be sorted before another one - //! lexicographically. - //! - bool operator<(const path&) const; -}; - -// ------------------------------------------------------------------------ -// The "file_info" class. -// ------------------------------------------------------------------------ - -class directory; - -//! -//! \brief A class that contains information about a file. -//! -//! The file_info class holds information about an specific file that -//! exists in the file system. -//! -class file_info { - int m_type; - struct stat m_sb; - -public: - //! - //! \brief The file's type. - //! - static const int blk_type; - static const int chr_type; - static const int dir_type; - static const int fifo_type; - static const int lnk_type; - static const int reg_type; - static const int sock_type; - static const int wht_type; - - //! - //! \brief Constructs a new file_info based on a given file. - //! - //! This constructor creates a new file_info object and fills it with - //! the data returned by ::stat when run on the given file, which must - //! exist. - //! - explicit file_info(const path&); - - //! - //! \brief The destructor. - //! - ~file_info(void); - - //! - //! \brief Returns the device containing the file. - //! - dev_t get_device(void) const; - - //! - //! \brief Returns the file's inode. - //! - ino_t get_inode(void) const; - - //! - //! \brief Returns the file's permissions. - //! - mode_t get_mode(void) const; - - //! - //! \brief Returns the file's size. - //! - off_t get_size(void) const; - - //! - //! \brief Returns the file's type. - //! - int get_type(void) const; - - //! - //! \brief Returns whether the file is readable by its owner or not. - //! - bool is_owner_readable(void) const; - - //! - //! \brief Returns whether the file is writable by its owner or not. - //! - bool is_owner_writable(void) const; - - //! - //! \brief Returns whether the file is executable by its owner or not. - //! - bool is_owner_executable(void) const; - - //! - //! \brief Returns whether the file is readable by the users belonging - //! to its group or not. - //! - bool is_group_readable(void) const; - - //! - //! \brief Returns whether the file is writable the users belonging to - //! its group or not. - //! - bool is_group_writable(void) const; - - //! - //! \brief Returns whether the file is executable by the users - //! belonging to its group or not. - //! - bool is_group_executable(void) const; - - //! - //! \brief Returns whether the file is readable by people different - //! than the owner and those belonging to the group or not. - //! - bool is_other_readable(void) const; - - //! - //! \brief Returns whether the file is write by people different - //! than the owner and those belonging to the group or not. - //! - bool is_other_writable(void) const; - - //! - //! \brief Returns whether the file is executable by people different - //! than the owner and those belonging to the group or not. - //! - bool is_other_executable(void) const; -}; - -// ------------------------------------------------------------------------ -// The "directory" class. -// ------------------------------------------------------------------------ - -//! -//! \brief A class representing a file system directory. -//! -//! The directory class represents a group of files in the file system and -//! corresponds to exactly one directory. -//! -class directory : public std::map< std::string, file_info > { -public: - //! - //! \brief Constructs a new directory. - //! - //! Constructs a new directory object representing the given path. - //! The directory must exist at creation time as the contents of the - //! class are gathered from it. - //! - directory(const path&); - - //! - //! \brief Returns the file names of the files in the directory. - //! - //! Returns the leaf names of all files contained in the directory. - //! I.e. the keys of the directory map. - //! - std::set< std::string > names(void) const; -}; - -// ------------------------------------------------------------------------ -// The "temp_dir" class. -// ------------------------------------------------------------------------ - -class temp_dir { - std::auto_ptr< tools::fs::path > m_path; - -public: - temp_dir(const tools::fs::path&); - ~temp_dir(void); - - const tools::fs::path& get_path(void) const; -}; - -// ------------------------------------------------------------------------ -// Free functions. -// ------------------------------------------------------------------------ - -//! -//! \brief Checks if the given path exists. -//! -bool exists(const path&); - -//! -//! \brief Looks for the given program in the PATH. -//! -//! Given a program name (without slashes) looks for it in the path and -//! returns its full path name if found, otherwise an empty path. -//! -bool have_prog_in_path(const std::string&); - -//! -//! \brief Checks if the given path exists, is accessible and is executable. -//! -bool is_executable(const path&); - -//! -//! \brief Removes a given file. -//! -void remove(const path&); - -//! -//! \brief Removes an empty directory. -//! -void rmdir(const path&); - -tools::fs::path change_directory(const tools::fs::path&); -void cleanup(const tools::fs::path&); -tools::fs::path get_current_dir(void); - -} // namespace fs -} // namespace tools - -#endif // !defined(TOOLS_FS_HPP) diff --git a/tools/fs_test.cpp b/tools/fs_test.cpp deleted file mode 100644 index 5f482a4..0000000 --- a/tools/fs_test.cpp +++ /dev/null @@ -1,743 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -extern "C" { -#include <sys/types.h> -#include <sys/stat.h> -} - -#include <cerrno> -#include <cstdio> -#include <fstream> - -#include <atf-c++.hpp> - -#include "exceptions.hpp" -#include "fs.hpp" -#include "user.hpp" - -// ------------------------------------------------------------------------ -// Auxiliary functions. -// ------------------------------------------------------------------------ - -static -void -create_file(const char *name) -{ - std::ofstream os(name); - os.close(); -} - -static -void -create_files(void) -{ - ::mkdir("files", 0755); - ::mkdir("files/dir", 0755); - - std::ofstream os("files/reg"); - os.close(); - - // TODO: Should create all other file types (blk, chr, fifo, lnk, sock) - // and test for them... but the underlying file system may not support - // most of these. Specially as we are working on /tmp, which can be - // mounted with flags such as "nodev". See how to deal with this - // situation. -} - -// ------------------------------------------------------------------------ -// Test cases for the "path" class. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(path_normalize); -ATF_TEST_CASE_HEAD(path_normalize) -{ - set_md_var("descr", "Tests the path's normalization"); -} -ATF_TEST_CASE_BODY(path_normalize) -{ - using tools::fs::path; - - ATF_REQUIRE_EQ(path(".").str(), "."); - ATF_REQUIRE_EQ(path("..").str(), ".."); - - ATF_REQUIRE_EQ(path("foo").str(), "foo"); - ATF_REQUIRE_EQ(path("foo/bar").str(), "foo/bar"); - ATF_REQUIRE_EQ(path("foo/bar/").str(), "foo/bar"); - - ATF_REQUIRE_EQ(path("/foo").str(), "/foo"); - ATF_REQUIRE_EQ(path("/foo/bar").str(), "/foo/bar"); - ATF_REQUIRE_EQ(path("/foo/bar/").str(), "/foo/bar"); - - ATF_REQUIRE_EQ(path("///foo").str(), "/foo"); - ATF_REQUIRE_EQ(path("///foo///bar").str(), "/foo/bar"); - ATF_REQUIRE_EQ(path("///foo///bar///").str(), "/foo/bar"); -} - -ATF_TEST_CASE(path_is_absolute); -ATF_TEST_CASE_HEAD(path_is_absolute) -{ - set_md_var("descr", "Tests the path::is_absolute function"); -} -ATF_TEST_CASE_BODY(path_is_absolute) -{ - using tools::fs::path; - - ATF_REQUIRE( path("/").is_absolute()); - ATF_REQUIRE( path("////").is_absolute()); - ATF_REQUIRE( path("////a").is_absolute()); - ATF_REQUIRE( path("//a//").is_absolute()); - ATF_REQUIRE(!path("a////").is_absolute()); - ATF_REQUIRE(!path("../foo").is_absolute()); -} - -ATF_TEST_CASE(path_is_root); -ATF_TEST_CASE_HEAD(path_is_root) -{ - set_md_var("descr", "Tests the path::is_root function"); -} -ATF_TEST_CASE_BODY(path_is_root) -{ - using tools::fs::path; - - ATF_REQUIRE( path("/").is_root()); - ATF_REQUIRE( path("////").is_root()); - ATF_REQUIRE(!path("////a").is_root()); - ATF_REQUIRE(!path("//a//").is_root()); - ATF_REQUIRE(!path("a////").is_root()); - ATF_REQUIRE(!path("../foo").is_root()); -} - -ATF_TEST_CASE(path_branch_path); -ATF_TEST_CASE_HEAD(path_branch_path) -{ - set_md_var("descr", "Tests the path::branch_path function"); -} -ATF_TEST_CASE_BODY(path_branch_path) -{ - using tools::fs::path; - - ATF_REQUIRE_EQ(path(".").branch_path().str(), "."); - ATF_REQUIRE_EQ(path("foo").branch_path().str(), "."); - ATF_REQUIRE_EQ(path("foo/bar").branch_path().str(), "foo"); - ATF_REQUIRE_EQ(path("/foo").branch_path().str(), "/"); - ATF_REQUIRE_EQ(path("/foo/bar").branch_path().str(), "/foo"); -} - -ATF_TEST_CASE(path_leaf_name); -ATF_TEST_CASE_HEAD(path_leaf_name) -{ - set_md_var("descr", "Tests the path::leaf_name function"); -} -ATF_TEST_CASE_BODY(path_leaf_name) -{ - using tools::fs::path; - - ATF_REQUIRE_EQ(path(".").leaf_name(), "."); - ATF_REQUIRE_EQ(path("foo").leaf_name(), "foo"); - ATF_REQUIRE_EQ(path("foo/bar").leaf_name(), "bar"); - ATF_REQUIRE_EQ(path("/foo").leaf_name(), "foo"); - ATF_REQUIRE_EQ(path("/foo/bar").leaf_name(), "bar"); -} - -ATF_TEST_CASE(path_compare_equal); -ATF_TEST_CASE_HEAD(path_compare_equal) -{ - set_md_var("descr", "Tests the comparison for equality between paths"); -} -ATF_TEST_CASE_BODY(path_compare_equal) -{ - using tools::fs::path; - - ATF_REQUIRE(path("/") == path("///")); - ATF_REQUIRE(path("/a") == path("///a")); - ATF_REQUIRE(path("/a") == path("///a///")); - - ATF_REQUIRE(path("a/b/c") == path("a//b//c")); - ATF_REQUIRE(path("a/b/c") == path("a//b//c///")); -} - -ATF_TEST_CASE(path_compare_different); -ATF_TEST_CASE_HEAD(path_compare_different) -{ - set_md_var("descr", "Tests the comparison for difference between paths"); -} -ATF_TEST_CASE_BODY(path_compare_different) -{ - using tools::fs::path; - - ATF_REQUIRE(path("/") != path("//a/")); - ATF_REQUIRE(path("/a") != path("a///")); - - ATF_REQUIRE(path("a/b/c") != path("a/b")); - ATF_REQUIRE(path("a/b/c") != path("a//b")); - ATF_REQUIRE(path("a/b/c") != path("/a/b/c")); - ATF_REQUIRE(path("a/b/c") != path("/a//b//c")); -} - -ATF_TEST_CASE(path_concat); -ATF_TEST_CASE_HEAD(path_concat) -{ - set_md_var("descr", "Tests the concatenation of multiple paths"); -} -ATF_TEST_CASE_BODY(path_concat) -{ - using tools::fs::path; - - ATF_REQUIRE_EQ((path("foo") / "bar").str(), "foo/bar"); - ATF_REQUIRE_EQ((path("foo/") / "/bar").str(), "foo/bar"); - ATF_REQUIRE_EQ((path("foo/") / "/bar/baz").str(), "foo/bar/baz"); - ATF_REQUIRE_EQ((path("foo/") / "///bar///baz").str(), "foo/bar/baz"); -} - -ATF_TEST_CASE(path_to_absolute); -ATF_TEST_CASE_HEAD(path_to_absolute) -{ - set_md_var("descr", "Tests the conversion of a relative path to an " - "absolute one"); -} -ATF_TEST_CASE_BODY(path_to_absolute) -{ - using tools::fs::file_info; - using tools::fs::path; - - create_files(); - - { - const path p("."); - path pa = p.to_absolute(); - ATF_REQUIRE(pa.is_absolute()); - - file_info fi(p); - file_info fia(pa); - ATF_REQUIRE_EQ(fi.get_device(), fia.get_device()); - ATF_REQUIRE_EQ(fi.get_inode(), fia.get_inode()); - } - - { - const path p("files/reg"); - path pa = p.to_absolute(); - ATF_REQUIRE(pa.is_absolute()); - - file_info fi(p); - file_info fia(pa); - ATF_REQUIRE_EQ(fi.get_device(), fia.get_device()); - ATF_REQUIRE_EQ(fi.get_inode(), fia.get_inode()); - } -} - -ATF_TEST_CASE(path_op_less); -ATF_TEST_CASE_HEAD(path_op_less) -{ - set_md_var("descr", "Tests that the path's less-than operator works"); -} -ATF_TEST_CASE_BODY(path_op_less) -{ - using tools::fs::path; - - create_files(); - - ATF_REQUIRE(!(path("aaa") < path("aaa"))); - - ATF_REQUIRE( path("aab") < path("abc")); - ATF_REQUIRE(!(path("abc") < path("aab"))); -} - -// ------------------------------------------------------------------------ -// Test cases for the "directory" class. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(directory_read); -ATF_TEST_CASE_HEAD(directory_read) -{ - set_md_var("descr", "Tests the directory class creation, which reads " - "the contents of a directory"); -} -ATF_TEST_CASE_BODY(directory_read) -{ - using tools::fs::directory; - using tools::fs::path; - - create_files(); - - directory d(path("files")); - ATF_REQUIRE_EQ(d.size(), 4); - ATF_REQUIRE(d.find(".") != d.end()); - ATF_REQUIRE(d.find("..") != d.end()); - ATF_REQUIRE(d.find("dir") != d.end()); - ATF_REQUIRE(d.find("reg") != d.end()); -} - -ATF_TEST_CASE(directory_file_info); -ATF_TEST_CASE_HEAD(directory_file_info) -{ - set_md_var("descr", "Tests that the file_info objects attached to the " - "directory are valid"); -} -ATF_TEST_CASE_BODY(directory_file_info) -{ - using tools::fs::directory; - using tools::fs::file_info; - using tools::fs::path; - - create_files(); - - directory d(path("files")); - - { - directory::const_iterator iter = d.find("dir"); - ATF_REQUIRE(iter != d.end()); - const file_info& fi = (*iter).second; - ATF_REQUIRE(fi.get_type() == file_info::dir_type); - } - - { - directory::const_iterator iter = d.find("reg"); - ATF_REQUIRE(iter != d.end()); - const file_info& fi = (*iter).second; - ATF_REQUIRE(fi.get_type() == file_info::reg_type); - } -} - -ATF_TEST_CASE(directory_names); -ATF_TEST_CASE_HEAD(directory_names) -{ - set_md_var("descr", "Tests the directory's names method"); -} -ATF_TEST_CASE_BODY(directory_names) -{ - using tools::fs::directory; - using tools::fs::path; - - create_files(); - - directory d(path("files")); - std::set< std::string > ns = d.names(); - ATF_REQUIRE_EQ(ns.size(), 4); - ATF_REQUIRE(ns.find(".") != ns.end()); - ATF_REQUIRE(ns.find("..") != ns.end()); - ATF_REQUIRE(ns.find("dir") != ns.end()); - ATF_REQUIRE(ns.find("reg") != ns.end()); -} - -// ------------------------------------------------------------------------ -// Test cases for the "file_info" class. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(file_info_stat); -ATF_TEST_CASE_HEAD(file_info_stat) -{ - set_md_var("descr", "Tests the file_info creation and its basic contents"); -} -ATF_TEST_CASE_BODY(file_info_stat) -{ - using tools::fs::file_info; - using tools::fs::path; - - create_files(); - - { - path p("files/dir"); - file_info fi(p); - ATF_REQUIRE(fi.get_type() == file_info::dir_type); - } - - { - path p("files/reg"); - file_info fi(p); - ATF_REQUIRE(fi.get_type() == file_info::reg_type); - } -} - -ATF_TEST_CASE(file_info_perms); -ATF_TEST_CASE_HEAD(file_info_perms) -{ - set_md_var("descr", "Tests the file_info methods to get the file's " - "permissions"); -} -ATF_TEST_CASE_BODY(file_info_perms) -{ - using tools::fs::file_info; - using tools::fs::path; - - path p("file"); - - std::ofstream os(p.c_str()); - os.close(); - -#define perms(ur, uw, ux, gr, gw, gx, othr, othw, othx) \ - { \ - file_info fi(p); \ - ATF_REQUIRE(fi.is_owner_readable() == ur); \ - ATF_REQUIRE(fi.is_owner_writable() == uw); \ - ATF_REQUIRE(fi.is_owner_executable() == ux); \ - ATF_REQUIRE(fi.is_group_readable() == gr); \ - ATF_REQUIRE(fi.is_group_writable() == gw); \ - ATF_REQUIRE(fi.is_group_executable() == gx); \ - ATF_REQUIRE(fi.is_other_readable() == othr); \ - ATF_REQUIRE(fi.is_other_writable() == othw); \ - ATF_REQUIRE(fi.is_other_executable() == othx); \ - } - - ::chmod(p.c_str(), 0000); - perms(false, false, false, false, false, false, false, false, false); - - ::chmod(p.c_str(), 0001); - perms(false, false, false, false, false, false, false, false, true); - - ::chmod(p.c_str(), 0010); - perms(false, false, false, false, false, true, false, false, false); - - ::chmod(p.c_str(), 0100); - perms(false, false, true, false, false, false, false, false, false); - - ::chmod(p.c_str(), 0002); - perms(false, false, false, false, false, false, false, true, false); - - ::chmod(p.c_str(), 0020); - perms(false, false, false, false, true, false, false, false, false); - - ::chmod(p.c_str(), 0200); - perms(false, true, false, false, false, false, false, false, false); - - ::chmod(p.c_str(), 0004); - perms(false, false, false, false, false, false, true, false, false); - - ::chmod(p.c_str(), 0040); - perms(false, false, false, true, false, false, false, false, false); - - ::chmod(p.c_str(), 0400); - perms(true, false, false, false, false, false, false, false, false); - - ::chmod(p.c_str(), 0644); - perms(true, true, false, true, false, false, true, false, false); - - ::chmod(p.c_str(), 0755); - perms(true, true, true, true, false, true, true, false, true); - - ::chmod(p.c_str(), 0777); - perms(true, true, true, true, true, true, true, true, true); - -#undef perms -} - -// ------------------------------------------------------------------------ -// Test cases for the "temp_dir" class. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(temp_dir_raii); -ATF_TEST_CASE_HEAD(temp_dir_raii) -{ - set_md_var("descr", "Tests the RAII behavior of the temp_dir class"); -} -ATF_TEST_CASE_BODY(temp_dir_raii) -{ - tools::fs::path t1("non-existent"); - tools::fs::path t2("non-existent"); - - { - tools::fs::path tmpl("testdir.XXXXXX"); - tools::fs::temp_dir td1(tmpl); - tools::fs::temp_dir td2(tmpl); - t1 = td1.get_path(); - t2 = td2.get_path(); - ATF_REQUIRE(t1.str().find("XXXXXX") == std::string::npos); - ATF_REQUIRE(t2.str().find("XXXXXX") == std::string::npos); - ATF_REQUIRE(t1 != t2); - ATF_REQUIRE(!tools::fs::exists(tmpl)); - ATF_REQUIRE( tools::fs::exists(t1)); - ATF_REQUIRE( tools::fs::exists(t2)); - - tools::fs::file_info fi1(t1); - ATF_REQUIRE( fi1.is_owner_readable()); - ATF_REQUIRE( fi1.is_owner_writable()); - ATF_REQUIRE( fi1.is_owner_executable()); - ATF_REQUIRE(!fi1.is_group_readable()); - ATF_REQUIRE(!fi1.is_group_writable()); - ATF_REQUIRE(!fi1.is_group_executable()); - ATF_REQUIRE(!fi1.is_other_readable()); - ATF_REQUIRE(!fi1.is_other_writable()); - ATF_REQUIRE(!fi1.is_other_executable()); - - tools::fs::file_info fi2(t2); - ATF_REQUIRE( fi2.is_owner_readable()); - ATF_REQUIRE( fi2.is_owner_writable()); - ATF_REQUIRE( fi2.is_owner_executable()); - ATF_REQUIRE(!fi2.is_group_readable()); - ATF_REQUIRE(!fi2.is_group_writable()); - ATF_REQUIRE(!fi2.is_group_executable()); - ATF_REQUIRE(!fi2.is_other_readable()); - ATF_REQUIRE(!fi2.is_other_writable()); - ATF_REQUIRE(!fi2.is_other_executable()); - } - - ATF_REQUIRE(t1.str() != "non-existent"); - ATF_REQUIRE(!tools::fs::exists(t1)); - ATF_REQUIRE(t2.str() != "non-existent"); - ATF_REQUIRE(!tools::fs::exists(t2)); -} - - -// ------------------------------------------------------------------------ -// Test cases for the free functions. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(exists); -ATF_TEST_CASE_HEAD(exists) -{ - set_md_var("descr", "Tests the exists function"); -} -ATF_TEST_CASE_BODY(exists) -{ - using tools::fs::exists; - using tools::fs::path; - - create_files(); - - ATF_REQUIRE( exists(path("files"))); - ATF_REQUIRE(!exists(path("file"))); - ATF_REQUIRE(!exists(path("files2"))); - - ATF_REQUIRE( exists(path("files/."))); - ATF_REQUIRE( exists(path("files/.."))); - ATF_REQUIRE( exists(path("files/dir"))); - ATF_REQUIRE( exists(path("files/reg"))); - ATF_REQUIRE(!exists(path("files/foo"))); -} - -ATF_TEST_CASE(is_executable); -ATF_TEST_CASE_HEAD(is_executable) -{ - set_md_var("descr", "Tests the is_executable function"); -} -ATF_TEST_CASE_BODY(is_executable) -{ - using tools::fs::is_executable; - using tools::fs::path; - - create_files(); - - ATF_REQUIRE( is_executable(path("files"))); - ATF_REQUIRE( is_executable(path("files/."))); - ATF_REQUIRE( is_executable(path("files/.."))); - ATF_REQUIRE( is_executable(path("files/dir"))); - - ATF_REQUIRE(!is_executable(path("non-existent"))); - - ATF_REQUIRE(!is_executable(path("files/reg"))); - ATF_REQUIRE(::chmod("files/reg", 0755) != -1); - ATF_REQUIRE( is_executable(path("files/reg"))); -} - -ATF_TEST_CASE(remove); -ATF_TEST_CASE_HEAD(remove) -{ - set_md_var("descr", "Tests the remove function"); -} -ATF_TEST_CASE_BODY(remove) -{ - using tools::fs::exists; - using tools::fs::path; - using tools::fs::remove; - - create_files(); - - ATF_REQUIRE( exists(path("files/reg"))); - remove(path("files/reg")); - ATF_REQUIRE(!exists(path("files/reg"))); - - ATF_REQUIRE( exists(path("files/dir"))); - ATF_REQUIRE_THROW(tools::system_error, remove(path("files/dir"))); - ATF_REQUIRE( exists(path("files/dir"))); -} - -ATF_TEST_CASE(cleanup); -ATF_TEST_CASE_HEAD(cleanup) -{ - set_md_var("descr", "Tests the cleanup function"); -} -ATF_TEST_CASE_BODY(cleanup) -{ - using tools::fs::cleanup; - - ::mkdir("root", 0755); - ::mkdir("root/dir", 0755); - ::mkdir("root/dir/1", 0100); - ::mkdir("root/dir/2", 0644); - create_file("root/reg"); - - tools::fs::path p("root"); - ATF_REQUIRE(tools::fs::exists(p)); - ATF_REQUIRE(tools::fs::exists(p / "dir")); - ATF_REQUIRE(tools::fs::exists(p / "dir/1")); - ATF_REQUIRE(tools::fs::exists(p / "dir/2")); - ATF_REQUIRE(tools::fs::exists(p / "reg")); - cleanup(p); - ATF_REQUIRE(!tools::fs::exists(p)); -} - -ATF_TEST_CASE(cleanup_eacces_on_root); -ATF_TEST_CASE_HEAD(cleanup_eacces_on_root) -{ - set_md_var("descr", "Tests the cleanup function"); -} -ATF_TEST_CASE_BODY(cleanup_eacces_on_root) -{ - using tools::fs::cleanup; - - ::mkdir("aux", 0755); - ::mkdir("aux/root", 0755); - ATF_REQUIRE(::chmod("aux", 0555) != -1); - - try { - cleanup(tools::fs::path("aux/root")); - ATF_REQUIRE(tools::user::is_root()); - } catch (const tools::system_error& e) { - ATF_REQUIRE(!tools::user::is_root()); - ATF_REQUIRE_EQ(EACCES, e.code()); - } -} - -ATF_TEST_CASE(cleanup_eacces_on_subdir); -ATF_TEST_CASE_HEAD(cleanup_eacces_on_subdir) -{ - set_md_var("descr", "Tests the cleanup function"); -} -ATF_TEST_CASE_BODY(cleanup_eacces_on_subdir) -{ - using tools::fs::cleanup; - - ::mkdir("root", 0755); - ::mkdir("root/1", 0755); - ::mkdir("root/1/2", 0755); - ::mkdir("root/1/2/3", 0755); - ATF_REQUIRE(::chmod("root/1/2", 0555) != -1); - ATF_REQUIRE(::chmod("root/1", 0555) != -1); - - const tools::fs::path p("root"); - cleanup(p); - ATF_REQUIRE(!tools::fs::exists(p)); -} - -ATF_TEST_CASE(change_directory); -ATF_TEST_CASE_HEAD(change_directory) -{ - set_md_var("descr", "Tests the change_directory function"); -} -ATF_TEST_CASE_BODY(change_directory) -{ - using tools::fs::change_directory; - using tools::fs::get_current_dir; - - ::mkdir("files", 0755); - ::mkdir("files/dir", 0755); - create_file("files/reg"); - - const tools::fs::path old = get_current_dir(); - - ATF_REQUIRE_THROW(tools::system_error, - change_directory(tools::fs::path("files/reg"))); - ATF_REQUIRE(get_current_dir() == old); - - tools::fs::path old2 = change_directory(tools::fs::path("files")); - ATF_REQUIRE(old2 == old); - tools::fs::path old3 = change_directory(tools::fs::path("dir")); - ATF_REQUIRE(old3 == old2 / "files"); - tools::fs::path old4 = change_directory(tools::fs::path("../..")); - ATF_REQUIRE(old4 == old3 / "dir"); - ATF_REQUIRE(get_current_dir() == old); -} - -ATF_TEST_CASE(get_current_dir); -ATF_TEST_CASE_HEAD(get_current_dir) -{ - set_md_var("descr", "Tests the get_current_dir function"); -} -ATF_TEST_CASE_BODY(get_current_dir) -{ - using tools::fs::change_directory; - using tools::fs::get_current_dir; - - ::mkdir("files", 0755); - ::mkdir("files/dir", 0755); - create_file("files/reg"); - - tools::fs::path curdir = get_current_dir(); - change_directory(tools::fs::path(".")); - ATF_REQUIRE(get_current_dir() == curdir); - change_directory(tools::fs::path("files")); - ATF_REQUIRE(get_current_dir() == curdir / "files"); - change_directory(tools::fs::path("dir")); - ATF_REQUIRE(get_current_dir() == curdir / "files/dir"); - change_directory(tools::fs::path("..")); - ATF_REQUIRE(get_current_dir() == curdir / "files"); - change_directory(tools::fs::path("..")); - ATF_REQUIRE(get_current_dir() == curdir); -} - -// ------------------------------------------------------------------------ -// Main. -// ------------------------------------------------------------------------ - -ATF_INIT_TEST_CASES(tcs) -{ - // Add the tests for the "path" class. - ATF_ADD_TEST_CASE(tcs, path_normalize); - ATF_ADD_TEST_CASE(tcs, path_is_absolute); - ATF_ADD_TEST_CASE(tcs, path_is_root); - ATF_ADD_TEST_CASE(tcs, path_branch_path); - ATF_ADD_TEST_CASE(tcs, path_leaf_name); - ATF_ADD_TEST_CASE(tcs, path_compare_equal); - ATF_ADD_TEST_CASE(tcs, path_compare_different); - ATF_ADD_TEST_CASE(tcs, path_concat); - ATF_ADD_TEST_CASE(tcs, path_to_absolute); - ATF_ADD_TEST_CASE(tcs, path_op_less); - - // Add the tests for the "file_info" class. - ATF_ADD_TEST_CASE(tcs, file_info_stat); - ATF_ADD_TEST_CASE(tcs, file_info_perms); - - // Add the tests for the "directory" class. - ATF_ADD_TEST_CASE(tcs, directory_read); - ATF_ADD_TEST_CASE(tcs, directory_names); - ATF_ADD_TEST_CASE(tcs, directory_file_info); - - // Add the tests for the "temp_dir" class. - ATF_ADD_TEST_CASE(tcs, temp_dir_raii); - - // Add the tests for the free functions. - ATF_ADD_TEST_CASE(tcs, exists); - ATF_ADD_TEST_CASE(tcs, is_executable); - ATF_ADD_TEST_CASE(tcs, remove); - ATF_ADD_TEST_CASE(tcs, cleanup); - ATF_ADD_TEST_CASE(tcs, cleanup_eacces_on_root); - ATF_ADD_TEST_CASE(tcs, cleanup_eacces_on_subdir); - ATF_ADD_TEST_CASE(tcs, change_directory); - ATF_ADD_TEST_CASE(tcs, get_current_dir); -} diff --git a/tools/generate-revision.sh b/tools/generate-revision.sh deleted file mode 100755 index 169be85..0000000 --- a/tools/generate-revision.sh +++ /dev/null @@ -1,142 +0,0 @@ -#! /bin/sh -# -# Automated Testing Framework (atf) -# -# Copyright (c) 2007 The NetBSD Foundation, Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 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. -# - -# -# Generates a header file with information about the revision used to -# build ATF. -# - -set -e - -Prog_Name=${0##*/} - -GIT= -ROOT= - -# -# err message -# -err() { - echo "${Prog_Name}: ${@}" 1>&2 - exit 1 -} - -# -# call_git args -# -call_git() { - ( cd "${ROOT}" && "${GIT}" "${@}" ) -} - -# -# generate_from_dist revfile version -# -generate_from_dist() { - revfile=${1}; shift - version=${1}; shift - - >${revfile} - - echo "#define PACKAGE_REVISION_TYPE_DIST" >>${revfile} -} - -# -# generate_from_git revfile -# -generate_from_git() { - revfile=${1} - - rev_base_id=$(call_git rev-parse HEAD) - rev_branch=$(call_git branch | grep '^\* ' | cut -d ' ' -f 2-) - rev_date=$(call_git log -1 | grep '^Date:' | sed -e 's,^Date:[ \t]*,,') - if [ -z "$(call_git status -s)" ]; then - rev_modified=false - else - rev_modified=true - fi - - >${revfile} - - echo "#define PACKAGE_REVISION_TYPE_GIT" >>${revfile} - - echo "#define PACKAGE_REVISION_BRANCH \"${rev_branch}\"" >>${revfile} - echo "#define PACKAGE_REVISION_BASE \"${rev_base_id}\"" >>${revfile} - - if [ ${rev_modified} = true ]; then - echo "#define PACKAGE_REVISION_MODIFIED 1" >>${revfile} - fi - - echo "#define PACKAGE_REVISION_DATE \"${rev_date}\"" >>${revfile} -} - -# -# main -# -# Entry point. -# -main() { - outfile= - version= - while getopts :g:r:o:v: arg; do - case ${arg} in - g) - GIT=${OPTARG} - ;; - o) - outfile=${OPTARG} - ;; - r) - ROOT=${OPTARG} - ;; - v) - version=${OPTARG} - ;; - *) - err "Unknown option ${arg}" - ;; - esac - done - [ -n "${ROOT}" ] || \ - err "Must specify the top-level source directory with -r" - [ -n "${outfile}" ] || \ - err "Must specify an output file with -o" - [ -n "${version}" ] || \ - err "Must specify a version number with -v" - - if [ -n "${GIT}" -a -d ${ROOT}/.git ]; then - generate_from_git ${outfile} - else - generate_from_dist ${outfile} ${version} - fi -} - -main "${@}" - -# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/tools/io.cpp b/tools/io.cpp deleted file mode 100644 index 4cf8f6a..0000000 --- a/tools/io.cpp +++ /dev/null @@ -1,356 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 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 <poll.h> -#include <signal.h> -#include <unistd.h> -} - -#include <cassert> -#include <cerrno> -#include <cstring> - -#include "auto_array.hpp" -#include "exceptions.hpp" -#include "io.hpp" - -namespace impl = tools::io; -#define IMPL_NAME "tools::io" - -// ------------------------------------------------------------------------ -// The "file_handle" class. -// ------------------------------------------------------------------------ - -impl::file_handle::file_handle(void) : - m_handle(invalid_value()) -{ -} - -impl::file_handle::file_handle(handle_type h) : - m_handle(h) -{ - assert(m_handle != invalid_value()); -} - -impl::file_handle::file_handle(const file_handle& fh) : - m_handle(fh.m_handle) -{ - fh.m_handle = invalid_value(); -} - -impl::file_handle::~file_handle(void) -{ - if (is_valid()) - close(); -} - -impl::file_handle& -impl::file_handle::operator=(const file_handle& fh) -{ - m_handle = fh.m_handle; - fh.m_handle = invalid_value(); - - return *this; -} - -bool -impl::file_handle::is_valid(void) - const -{ - return m_handle != invalid_value(); -} - -void -impl::file_handle::close(void) -{ - assert(is_valid()); - - ::close(m_handle); - - m_handle = invalid_value(); -} - -impl::file_handle::handle_type -impl::file_handle::disown(void) -{ - assert(is_valid()); - - handle_type h = m_handle; - m_handle = invalid_value(); - return h; -} - -impl::file_handle::handle_type -impl::file_handle::get(void) - const -{ - assert(is_valid()); - - return m_handle; -} - -void -impl::file_handle::posix_remap(handle_type h) -{ - assert(is_valid()); - - if (m_handle == h) - return; - - if (::dup2(m_handle, h) == -1) - throw tools::system_error(IMPL_NAME "::file_handle::posix_remap", - "dup2(2) failed", errno); - - if (::close(m_handle) == -1) { - ::close(h); - throw tools::system_error(IMPL_NAME "::file_handle::posix_remap", - "close(2) failed", errno); - } - - m_handle = h; -} - -impl::file_handle::handle_type -impl::file_handle::invalid_value(void) -{ - return -1; -} - -// ------------------------------------------------------------------------ -// The "systembuf" class. -// ------------------------------------------------------------------------ - -impl::systembuf::systembuf(handle_type h, std::size_t bufsize) : - m_handle(h), - m_bufsize(bufsize), - m_read_buf(NULL), - m_write_buf(NULL) -{ - assert(m_handle >= 0); - assert(m_bufsize > 0); - - try { - m_read_buf = new char[bufsize]; - m_write_buf = new char[bufsize]; - } catch (...) { - if (m_read_buf != NULL) - delete [] m_read_buf; - if (m_write_buf != NULL) - delete [] m_write_buf; - throw; - } - - setp(m_write_buf, m_write_buf + m_bufsize); -} - -impl::systembuf::~systembuf(void) -{ - delete [] m_read_buf; - delete [] m_write_buf; -} - -impl::systembuf::int_type -impl::systembuf::underflow(void) -{ - assert(gptr() >= egptr()); - - bool ok; - ssize_t cnt = ::read(m_handle, m_read_buf, m_bufsize); - ok = (cnt != -1 && cnt != 0); - - if (!ok) - return traits_type::eof(); - else { - setg(m_read_buf, m_read_buf, m_read_buf + cnt); - return traits_type::to_int_type(*gptr()); - } -} - -impl::systembuf::int_type -impl::systembuf::overflow(int c) -{ - assert(pptr() >= epptr()); - if (sync() == -1) - return traits_type::eof(); - if (!traits_type::eq_int_type(c, traits_type::eof())) { - traits_type::assign(*pptr(), c); - pbump(1); - } - return traits_type::not_eof(c); -} - -int -impl::systembuf::sync(void) -{ - ssize_t cnt = pptr() - pbase(); - - bool ok; - ok = ::write(m_handle, pbase(), cnt) == cnt; - - if (ok) - pbump(-cnt); - return ok ? 0 : -1; -} - -// ------------------------------------------------------------------------ -// The "pistream" class. -// ------------------------------------------------------------------------ - -impl::pistream::pistream(const int fd) : - std::istream(NULL), - m_systembuf(fd) -{ - rdbuf(&m_systembuf); -} - -// ------------------------------------------------------------------------ -// The "muxer" class. -// ------------------------------------------------------------------------ - -static int -safe_poll(struct pollfd fds[], nfds_t nfds, int timeout) -{ - int ret = ::poll(fds, nfds, timeout); - if (ret == -1) { - if (errno == EINTR) - ret = 0; - else - throw tools::system_error(IMPL_NAME "::safe_poll", "poll(2) failed", - errno); - } - assert(ret >= 0); - return ret; -} - -static size_t -safe_read(const int fd, void* buffer, const size_t nbytes, - const bool report_errors) -{ - int ret; - while ((ret = ::read(fd, buffer, nbytes)) == -1 && errno == EINTR) {} - if (ret == -1) { - assert(errno != EINTR); - - if (report_errors) - throw tools::system_error(IMPL_NAME "::safe_read", "read(2) failed", - errno); - else - ret = 0; - } - assert(ret >= 0); - return static_cast< size_t >(ret); -} - -impl::muxer::muxer(const int* fds, const size_t nfds, const size_t bufsize) : - m_fds(fds), - m_nfds(nfds), - m_bufsize(bufsize), - m_buffers(new std::string[nfds]) -{ -} - -impl::muxer::~muxer(void) -{ -} - -size_t -impl::muxer::read_one(const size_t index, const int fd, std::string& accum, - const bool report_errors) -{ - tools::auto_array< char > buffer(new char[m_bufsize]); - const size_t nbytes = safe_read(fd, buffer.get(), m_bufsize - 1, - report_errors); - assert(nbytes < m_bufsize); - buffer[nbytes] = '\0'; - - std::string line(accum); - - size_t line_start = 0; - for (size_t i = 0; i < nbytes; i++) { - if (buffer[i] == '\n') { - line_callback(index, line); - line.clear(); - accum.clear(); - line_start = i + 1; - } else if (buffer[i] == '\r') { - // Do nothing. - } else { - line.append(1, buffer[i]); - } - } - accum.append(&buffer[line_start]); - - return nbytes; -} - -void -impl::muxer::mux(volatile const bool& terminate) -{ - tools::auto_array< struct pollfd > poll_fds(new struct pollfd[m_nfds]); - for (size_t i = 0; i < m_nfds; i++) { - poll_fds[i].fd = m_fds[i]; - poll_fds[i].events = POLLIN; - } - - size_t nactive = m_nfds; - while (nactive > 0 && !terminate) { - int ret; - while (!terminate && (ret = safe_poll(poll_fds.get(), 2, 250)) == 0) {} - - for (size_t i = 0; !terminate && i < m_nfds; i++) { - if (poll_fds[i].events == 0) - continue; - - if (poll_fds[i].revents & POLLHUP) { - // Any data still available at this point will be processed by - // a call to the flush method. - poll_fds[i].events = 0; - - assert(nactive >= 1); - nactive--; - } else if (poll_fds[i].revents & (POLLIN | POLLRDNORM | POLLRDBAND | - POLLPRI)) { - (void)read_one(i, poll_fds[i].fd, m_buffers[i], true); - } - } - } -} - -void -impl::muxer::flush(void) -{ - for (size_t i = 0; i < m_nfds; i++) { - while (read_one(i, m_fds[i], m_buffers[i], false) > 0) {} - - if (!m_buffers[i].empty()) - line_callback(i, m_buffers[i]); - } -} diff --git a/tools/io.hpp b/tools/io.hpp deleted file mode 100644 index 3fb417b..0000000 --- a/tools/io.hpp +++ /dev/null @@ -1,436 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if !defined(TOOLS_IO_HPP) -#define TOOLS_IO_HPP - -#include <istream> -#include <ostream> -#include <streambuf> - -#include "auto_array.hpp" -#include "fs.hpp" - -namespace tools { -namespace io { - -// ------------------------------------------------------------------------ -// The "file_handle" class. -// ------------------------------------------------------------------------ - -//! -//! \brief Simple RAII model for system file handles. -//! -//! The \a file_handle class is a simple RAII model for native system file -//! handles. This class wraps one of such handles grabbing its ownership, -//! and automaticaly closes it upon destruction. It is basically used -//! inside the library to avoid leaking open file handles, shall an -//! unexpected execution trace occur. -//! -//! A \a file_handle object can be copied but doing so invalidates the -//! source object. There can only be a single valid \a file_handle object -//! for a given system file handle. This is similar to std::auto_ptr\<\>'s -//! semantics. -//! -//! This class also provides some convenience methods to issue special file -//! operations under their respective platforms. -//! -class file_handle -{ -public: - //! - //! \brief Opaque name for the native handle type. - //! - //! Each operating system identifies file handles using a specific type. - //! The \a handle_type type is used to transparently refer to file - //! handles regarless of the operating system in which this class is - //! used. - //! - //! If this class is used in a POSIX system, \a NativeSystemHandle is - //! an integer type while it is a \a HANDLE in a Win32 system. - //! - typedef int handle_type; - - //! - //! \brief Constructs an invalid file handle. - //! - //! This constructor creates a new \a file_handle object that represents - //! an invalid file handle. An invalid file handle can be copied but - //! cannot be manipulated in any way (except checking for its validity). - //! - //! \see is_valid() - //! - file_handle(void); - - //! - //! \brief Constructs a new file handle from a native file handle. - //! - //! This constructor creates a new \a file_handle object that takes - //! ownership of the given \a h native file handle. The user must not - //! close \a h on his own during the lifetime of the new object. - //! Ownership can be reclaimed using disown(). - //! - //! \pre The native file handle must be valid; a close operation must - //! succeed on it. - //! - //! \see disown() - //! - file_handle(handle_type h); - - //! - //! \brief Copy constructor; invalidates the source handle. - //! - //! This copy constructor creates a new file handle from a given one. - //! Ownership of the native file handle is transferred to the new - //! object, effectively invalidating the source file handle. This - //! avoids having two live \a file_handle objects referring to the - //! same native file handle. The source file handle need not be - //! valid in the name of simplicity. - //! - //! \post The source file handle is invalid. - //! \post The new file handle owns the source's native file handle. - //! - file_handle(const file_handle& fh); - - //! - //! \brief Releases resources if the handle is valid. - //! - //! If the file handle is valid, the destructor closes it. - //! - //! \see is_valid() - //! - ~file_handle(void); - - //! - //! \brief Assignment operator; invalidates the source handle. - //! - //! This assignment operator transfers ownership of the RHS file - //! handle to the LHS one, effectively invalidating the source file - //! handle. This avoids having two live \a file_handle objects - //! referring to the same native file handle. The source file - //! handle need not be valid in the name of simplicity. - //! - //! \post The RHS file handle is invalid. - //! \post The LHS file handle owns RHS' native file handle. - //! \return A reference to the LHS file handle. - //! - file_handle& operator=(const file_handle& fh); - - //! - //! \brief Checks whether the file handle is valid or not. - //! - //! Returns a boolean indicating whether the file handle is valid or - //! not. If the file handle is invalid, no other applications can be - //! executed other than the destructor. - //! - //! \return True if the file handle is valid; false otherwise. - //! - bool is_valid(void) const; - - //! - //! \brief Closes the file handle. - //! - //! Explicitly closes the file handle, which must be valid. Upon - //! exit, the handle is not valid any more. - //! - //! \pre The file handle is valid. - //! \post The file handle is invalid. - //! \post The native file handle is closed. - //! - void close(void); - - //! - //! \brief Reclaims ownership of the native file handle. - //! - //! Explicitly reclaims ownership of the native file handle contained - //! in the \a file_handle object, returning the native file handle. - //! The caller is responsible of closing it later on. - //! - //! \pre The file handle is valid. - //! \post The file handle is invalid. - //! \return The native file handle. - //! - handle_type disown(void); - - //! - //! \brief Gets the native file handle. - //! - //! Returns the native file handle for the \a file_handle object. - //! The caller can issue any operation on it except closing it. - //! If closing is required, disown() shall be used. - //! - //! \pre The file handle is valid. - //! \return The native file handle. - //! - handle_type get(void) const; - - //! - //! \brief Changes the native file handle to the given one. - //! - //! Given a new native file handle \a h, this operation assigns this - //! handle to the current object, closing its old native file handle. - //! In other words, it first calls dup2() to remap the old handle to - //! the new one and then closes the old handle. - //! - //! If \a h matches the current value of the handle, this is a no-op. - //! This is done for simplicity, to avoid the caller having to check - //! this condition on its own. - //! - //! If \a h is open, it is automatically closed by dup2(). - //! - //! This operation is only available in POSIX systems. - //! - //! \pre The file handle is valid. - //! \pre The native file handle \a h is valid; i.e., it must be - //! closeable. - //! \post The file handle's native file handle is \a h. - //! \throw system_error If the internal remapping operation fails. - //! - void posix_remap(handle_type h); - -private: - //! - //! \brief Internal handle value. - //! - //! This variable holds the native handle value for the file handle - //! hold by this object. It is interesting to note that this needs - //! to be mutable because the copy constructor and the assignment - //! operator invalidate the source object. - //! - mutable handle_type m_handle; - - //! - //! \brief Constant function representing an invalid handle value. - //! - //! Returns the platform-specific handle value that represents an - //! invalid handle. This is a constant function rather than a regular - //! constant because, in the latter case, we cannot define it under - //! Win32 due to the value being of a complex type. - //! - static handle_type invalid_value(void); -}; - -// ------------------------------------------------------------------------ -// The "systembuf" class. -// ------------------------------------------------------------------------ - -//! -//! \brief std::streambuf implementation for system file handles. -//! -//! systembuf provides a std::streambuf implementation for system file -//! handles. Contrarywise to file_handle, this class does \b not take -//! ownership of the native file handle; this should be taken care of -//! somewhere else. -//! -//! This class follows the expected semantics of a std::streambuf object. -//! However, it is not copyable to avoid introducing inconsistences with -//! the on-disk file and the in-memory buffers. -//! -class systembuf : public std::streambuf -{ - // Non-copyable. - systembuf(const systembuf&); - systembuf& operator=(const systembuf&); - -public: - typedef int handle_type; - - //! - //! \brief Constructs a new systembuf for the given file handle. - //! - //! This constructor creates a new systembuf object that reads or - //! writes data from/to the \a h native file handle. This handle - //! is \b not owned by the created systembuf object; the code - //! should take care of it externally. - //! - //! This class buffers input and output; the buffer size may be - //! tuned through the \a bufsize parameter, which defaults to 8192 - //! bytes. - //! - //! \see pistream. - //! - explicit systembuf(handle_type h, std::size_t bufsize = 8192); - ~systembuf(void); - -private: - //! - //! \brief Native file handle used by the systembuf object. - //! - handle_type m_handle; - - //! - //! \brief Internal buffer size used during read and write operations. - //! - std::size_t m_bufsize; - - //! - //! \brief Internal buffer used during read operations. - //! - char* m_read_buf; - - //! - //! \brief Internal buffer used during write operations. - //! - char* m_write_buf; - -protected: - //! - //! \brief Reads new data from the native file handle. - //! - //! This operation is called by input methods when there are no more - //! data in the input buffer. The function fills the buffer with new - //! data, if available. - //! - //! \pre All input positions are exhausted (gptr() >= egptr()). - //! \post The input buffer has new data, if available. - //! \returns traits_type::eof() if a read error occurrs or there are - //! no more data to be read. Otherwise returns - //! traits_type::to_int_type(*gptr()). - //! - virtual int_type underflow(void); - - //! - //! \brief Makes room in the write buffer for additional data. - //! - //! This operation is called by output methods when there is no more - //! space in the output buffer to hold a new element. The function - //! first flushes the buffer's contents to disk and then clears it to - //! leave room for more characters. The given \a c character is - //! stored at the beginning of the new space. - //! - //! \pre All output positions are exhausted (pptr() >= epptr()). - //! \post The output buffer has more space if no errors occurred - //! during the write to disk. - //! \post *(pptr() - 1) is \a c. - //! \returns traits_type::eof() if a write error occurrs. Otherwise - //! returns traits_type::not_eof(c). - //! - virtual int_type overflow(int c); - - //! - //! \brief Flushes the output buffer to disk. - //! - //! Synchronizes the systembuf buffers with the contents of the file - //! associated to this object through the native file handle. The - //! output buffer is flushed to disk and cleared to leave new room - //! for more data. - //! - //! \returns 0 on success, -1 if an error occurred. - //! - virtual int sync(void); -}; - -// ------------------------------------------------------------------------ -// The "pistream" class. -// ------------------------------------------------------------------------ - -//! -//! \brief Child process' output stream. -//! -//! The pistream class represents an output communication channel with the -//! child process. The child process writes data to this stream and the -//! parent process can read it through the pistream object. In other -//! words, from the child's point of view, the communication channel is an -//! output one, but from the parent's point of view it is an input one; -//! hence the confusing pistream name. -//! -//! pistream objects cannot be copied because they own the file handle -//! they use to communicate with the child and because they buffer data -//! that flows through the communication channel. -//! -//! A pistream object behaves as a std::istream stream in all senses. -//! The class is only provided because it must provide a method to let -//! the caller explicitly close the communication channel. -//! -//! \remark <b>Blocking remarks</b>: Functions that read data from this -//! stream can block if the associated file handle blocks during the read. -//! As this class is used to communicate with child processes through -//! anonymous pipes, the most typical blocking condition happens when the -//! child has no more data to send to the pipe's system buffer. When -//! this happens, the buffer eventually empties and the system blocks -//! until the writer generates some data. -//! -class pistream : public std::istream -{ - // Non-copyable. - pistream(const pistream&); - pistream& operator=(const pistream&); - - //! - //! \brief The systembuf object used to manage this stream's data. - //! - systembuf m_systembuf; - -public: - //! - //! \brief Creates a new process' output stream. - //! - //! Given a file handle, this constructor creates a new pistream - //! object that owns the given file handle \a fh. Ownership of - //! \a fh is transferred to the created pistream object. - //! - //! \pre \a fh is valid. - //! \post \a fh is invalid. - //! \post The new pistream object owns \a fh. - //! - explicit pistream(const int); -}; - -// ------------------------------------------------------------------------ -// The "muxer" class. -// ------------------------------------------------------------------------ - -class muxer { - // Non-copyable. - muxer(const muxer&); - muxer& operator=(const muxer&); - - const int* m_fds; - const size_t m_nfds; - - const size_t m_bufsize; - tools::auto_array< std::string > m_buffers; - -protected: - virtual void line_callback(const size_t, const std::string&) = 0; - - size_t read_one(const size_t, const int, std::string&, const bool); - -public: - muxer(const int*, const size_t, const size_t bufsize = 1024); - virtual ~muxer(void); - - void mux(volatile const bool&); - void flush(void); -}; - -} // namespace io -} // namespace tools - -#endif // !defined(TOOLS_IO_HPP) diff --git a/tools/io_test.cpp b/tools/io_test.cpp deleted file mode 100644 index b55428f..0000000 --- a/tools/io_test.cpp +++ /dev/null @@ -1,471 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -extern "C" { -#include <sys/stat.h> -#include <sys/wait.h> - -#include <fcntl.h> -#include <unistd.h> -} - -#include <cassert> -#include <cerrno> -#include <cstddef> -#include <cstdlib> -#include <cstring> -#include <fstream> -#include <iostream> -#include <istream> -#include <ostream> - -#include <atf-c++.hpp> - -#include "io.hpp" -#include "signals.hpp" - -// ------------------------------------------------------------------------ -// Auxiliary functions. -// ------------------------------------------------------------------------ - -static -void -systembuf_check_data(std::istream& is, std::size_t length) -{ - char ch = 'A', chr; - std::size_t cnt = 0; - while (is >> chr) { - ATF_REQUIRE_EQ(ch, chr); - if (ch == 'Z') - ch = 'A'; - else - ch++; - cnt++; - } - ATF_REQUIRE_EQ(cnt, length); -} - -static -void -systembuf_write_data(std::ostream& os, std::size_t length) -{ - char ch = 'A'; - for (std::size_t i = 0; i < length; i++) { - os << ch; - if (ch == 'Z') - ch = 'A'; - else - ch++; - } - os.flush(); -} - -static -void -systembuf_test_read(std::size_t length, std::size_t bufsize) -{ - using tools::io::systembuf; - - std::ofstream f("test_read.txt"); - systembuf_write_data(f, length); - f.close(); - - int fd = ::open("test_read.txt", O_RDONLY); - ATF_REQUIRE(fd != -1); - systembuf sb(fd, bufsize); - std::istream is(&sb); - systembuf_check_data(is, length); - ::close(fd); - ::unlink("test_read.txt"); -} - -static -void -systembuf_test_write(std::size_t length, std::size_t bufsize) -{ - using tools::io::systembuf; - - int fd = ::open("test_write.txt", O_WRONLY | O_CREAT | O_TRUNC, - S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - ATF_REQUIRE(fd != -1); - systembuf sb(fd, bufsize); - std::ostream os(&sb); - systembuf_write_data(os, length); - ::close(fd); - - std::ifstream is("test_write.txt"); - systembuf_check_data(is, length); - is.close(); - ::unlink("test_write.txt"); -} - -// ------------------------------------------------------------------------ -// Test cases for the "file_handle" class. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(file_handle_ctor); -ATF_TEST_CASE_HEAD(file_handle_ctor) -{ - set_md_var("descr", "Tests file_handle's constructors"); -} -ATF_TEST_CASE_BODY(file_handle_ctor) -{ - using tools::io::file_handle; - - file_handle fh1; - ATF_REQUIRE(!fh1.is_valid()); - - file_handle fh2(STDOUT_FILENO); - ATF_REQUIRE(fh2.is_valid()); - fh2.disown(); -} - -ATF_TEST_CASE(file_handle_copy); -ATF_TEST_CASE_HEAD(file_handle_copy) -{ - set_md_var("descr", "Tests file_handle's copy constructor"); -} -ATF_TEST_CASE_BODY(file_handle_copy) -{ - using tools::io::file_handle; - - file_handle fh1; - file_handle fh2(STDOUT_FILENO); - - file_handle fh3(fh2); - ATF_REQUIRE(!fh2.is_valid()); - ATF_REQUIRE(fh3.is_valid()); - - fh1 = fh3; - ATF_REQUIRE(!fh3.is_valid()); - ATF_REQUIRE(fh1.is_valid()); - - fh1.disown(); -} - -ATF_TEST_CASE(file_handle_get); -ATF_TEST_CASE_HEAD(file_handle_get) -{ - set_md_var("descr", "Tests the file_handle::get method"); -} -ATF_TEST_CASE_BODY(file_handle_get) -{ - using tools::io::file_handle; - - file_handle fh1(STDOUT_FILENO); - ATF_REQUIRE_EQ(fh1.get(), STDOUT_FILENO); -} - -ATF_TEST_CASE(file_handle_posix_remap); -ATF_TEST_CASE_HEAD(file_handle_posix_remap) -{ - set_md_var("descr", "Tests the file_handle::posix_remap method"); -} -ATF_TEST_CASE_BODY(file_handle_posix_remap) -{ - using tools::io::file_handle; - - int pfd[2]; - - ATF_REQUIRE(::pipe(pfd) != -1); - file_handle rend(pfd[0]); - file_handle wend(pfd[1]); - - ATF_REQUIRE(rend.get() != 10); - ATF_REQUIRE(wend.get() != 10); - wend.posix_remap(10); - ATF_REQUIRE_EQ(wend.get(), 10); - ATF_REQUIRE(::write(wend.get(), "test-posix-remap", 16) != -1); - { - char buf[17]; - ATF_REQUIRE_EQ(::read(rend.get(), buf, sizeof(buf)), 16); - buf[16] = '\0'; - ATF_REQUIRE(std::strcmp(buf, "test-posix-remap") == 0); - } - - // Redo previous to ensure that remapping over the same descriptor - // has no side-effects. - ATF_REQUIRE_EQ(wend.get(), 10); - wend.posix_remap(10); - ATF_REQUIRE_EQ(wend.get(), 10); - ATF_REQUIRE(::write(wend.get(), "test-posix-remap", 16) != -1); - { - char buf[17]; - ATF_REQUIRE_EQ(::read(rend.get(), buf, sizeof(buf)), 16); - buf[16] = '\0'; - ATF_REQUIRE(std::strcmp(buf, "test-posix-remap") == 0); - } -} - -// ------------------------------------------------------------------------ -// Test cases for the "systembuf" class. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(systembuf_short_read); -ATF_TEST_CASE_HEAD(systembuf_short_read) -{ - set_md_var("descr", "Tests that a short read (one that fits in the " - "internal buffer) works when using systembuf"); -} -ATF_TEST_CASE_BODY(systembuf_short_read) -{ - systembuf_test_read(64, 1024); -} - -ATF_TEST_CASE(systembuf_long_read); -ATF_TEST_CASE_HEAD(systembuf_long_read) -{ - set_md_var("descr", "Tests that a long read (one that does not fit in " - "the internal buffer) works when using systembuf"); -} -ATF_TEST_CASE_BODY(systembuf_long_read) -{ - systembuf_test_read(64 * 1024, 1024); -} - -ATF_TEST_CASE(systembuf_short_write); -ATF_TEST_CASE_HEAD(systembuf_short_write) -{ - set_md_var("descr", "Tests that a short write (one that fits in the " - "internal buffer) works when using systembuf"); -} -ATF_TEST_CASE_BODY(systembuf_short_write) -{ - systembuf_test_write(64, 1024); -} - -ATF_TEST_CASE(systembuf_long_write); -ATF_TEST_CASE_HEAD(systembuf_long_write) -{ - set_md_var("descr", "Tests that a long write (one that does not fit " - "in the internal buffer) works when using systembuf"); -} -ATF_TEST_CASE_BODY(systembuf_long_write) -{ - systembuf_test_write(64 * 1024, 1024); -} - -// ------------------------------------------------------------------------ -// Test cases for the "pistream" class. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(pistream); -ATF_TEST_CASE_HEAD(pistream) -{ - set_md_var("descr", "Tests the pistream class"); -} -ATF_TEST_CASE_BODY(pistream) -{ - using tools::io::file_handle; - using tools::io::pistream; - using tools::io::systembuf; - - int fds[2]; - ATF_REQUIRE(::pipe(fds) != -1); - - pistream rend(fds[0]); - - systembuf wbuf(fds[1]); - std::ostream wend(&wbuf); - - // XXX This assumes that the pipe's buffer is big enough to accept - // the data written without blocking! - wend << "1Test 1message\n"; - wend.flush(); - std::string tmp; - rend >> tmp; - ATF_REQUIRE_EQ(tmp, "1Test"); - rend >> tmp; - ATF_REQUIRE_EQ(tmp, "1message"); -} - -// ------------------------------------------------------------------------ -// Tests for the "muxer" class. -// ------------------------------------------------------------------------ - -namespace { - -static void -check_stream(std::ostream& os) -{ - // 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. - ATF_REQUIRE(os.good() || (os.bad() && errno == EINTR)); - os.clear(); -} - -class mock_muxer : public tools::io::muxer { - void line_callback(const size_t index, const std::string& line) - { - // The following should be enabled but causes the output to be so big - // that it is annoying. Reenable at some point if we make atf store - // the output of the test cases in some other way (e.g. only if a test - // failes), because this message is the only help in seeing how the - // test fails. - //std::cout << "line_callback(" << index << ", " << line << ")\n"; - check_stream(std::cout); - switch (index) { - case 0: lines0.push_back(line); break; - case 1: lines1.push_back(line); break; - default: ATF_REQUIRE(false); - } - } - -public: - mock_muxer(const int* fds, const size_t nfds, const size_t bufsize) : - muxer(fds, nfds, bufsize) {} - - std::vector< std::string > lines0; - std::vector< std::string > lines1; -}; - -static bool child_finished = false; -static void sigchld_handler(int signo) -{ - assert(signo == SIGCHLD); - child_finished = true; -} - -static void -child_printer(const int pipeout[2], const int pipeerr[2], - const size_t iterations) -{ - ::close(pipeout[0]); - ::close(pipeerr[0]); - ATF_REQUIRE(::dup2(pipeout[1], STDOUT_FILENO) != -1); - ATF_REQUIRE(::dup2(pipeerr[1], STDERR_FILENO) != -1); - ::close(pipeout[1]); - ::close(pipeerr[1]); - - for (size_t i = 0; i < iterations; i++) { - std::cout << "stdout " << i << "\n"; - std::cerr << "stderr " << i << "\n"; - } - - std::cout << "stdout eof\n"; - std::cerr << "stderr eof\n"; - std::exit(EXIT_SUCCESS); -} - -static void -muxer_test(const size_t bufsize, const size_t iterations) -{ - int pipeout[2], pipeerr[2]; - ATF_REQUIRE(pipe(pipeout) != -1); - ATF_REQUIRE(pipe(pipeerr) != -1); - - tools::signals::signal_programmer sigchld(SIGCHLD, sigchld_handler); - - std::cout.flush(); - std::cerr.flush(); - - pid_t pid = ::fork(); - ATF_REQUIRE(pid != -1); - if (pid == 0) { - sigchld.unprogram(); - child_printer(pipeout, pipeerr, iterations); - std::abort(); - } - ::close(pipeout[1]); - ::close(pipeerr[1]); - - int fds[2] = {pipeout[0], pipeerr[0]}; - mock_muxer mux(fds, 2, bufsize); - - mux.mux(child_finished); - check_stream(std::cout); - std::cout << "mux done\n"; - - mux.flush(); - std::cout << "flush done\n"; - check_stream(std::cout); - - sigchld.unprogram(); - int status; - ATF_REQUIRE(::waitpid(pid, &status, 0) != -1); - ATF_REQUIRE(WIFEXITED(status)); - ATF_REQUIRE(WEXITSTATUS(status) == EXIT_SUCCESS); - - ATF_REQUIRE(std::cout.good()); - ATF_REQUIRE(std::cerr.good()); - for (size_t i = 0; i < iterations; i++) { - std::ostringstream exp0, exp1; - exp0 << "stdout " << i; - exp1 << "stderr " << i; - - ATF_REQUIRE(mux.lines0.size() > i); - ATF_REQUIRE_EQ(exp0.str(), mux.lines0[i]); - ATF_REQUIRE(mux.lines1.size() > i); - ATF_REQUIRE_EQ(exp1.str(), mux.lines1[i]); - } - ATF_REQUIRE_EQ("stdout eof", mux.lines0[iterations]); - ATF_REQUIRE_EQ("stderr eof", mux.lines1[iterations]); - std::cout << "all done\n"; -} - -} // anonymous namespace - -ATF_TEST_CASE_WITHOUT_HEAD(muxer_small_buffer); -ATF_TEST_CASE_BODY(muxer_small_buffer) -{ - muxer_test(4, 20000); -} - -ATF_TEST_CASE_WITHOUT_HEAD(muxer_large_buffer); -ATF_TEST_CASE_BODY(muxer_large_buffer) -{ - muxer_test(1024, 50000); -} - -// ------------------------------------------------------------------------ -// Main. -// ------------------------------------------------------------------------ - -ATF_INIT_TEST_CASES(tcs) -{ - // Add the tests for the "file_handle" class. - ATF_ADD_TEST_CASE(tcs, file_handle_ctor); - ATF_ADD_TEST_CASE(tcs, file_handle_copy); - ATF_ADD_TEST_CASE(tcs, file_handle_get); - ATF_ADD_TEST_CASE(tcs, file_handle_posix_remap); - - // Add the tests for the "systembuf" class. - ATF_ADD_TEST_CASE(tcs, systembuf_short_read); - ATF_ADD_TEST_CASE(tcs, systembuf_long_read); - ATF_ADD_TEST_CASE(tcs, systembuf_short_write); - ATF_ADD_TEST_CASE(tcs, systembuf_long_write); - - // Add the tests for the "pistream" class. - ATF_ADD_TEST_CASE(tcs, pistream); - - // Add the tests for the "muxer" class. - ATF_ADD_TEST_CASE(tcs, muxer_small_buffer); - ATF_ADD_TEST_CASE(tcs, muxer_large_buffer); -} diff --git a/tools/misc_helpers.cpp b/tools/misc_helpers.cpp deleted file mode 100644 index 8ec4dde..0000000 --- a/tools/misc_helpers.cpp +++ /dev/null @@ -1,448 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -extern "C" { -#include <sys/stat.h> - -#include <signal.h> -#include <unistd.h> -} - -#include <cstdlib> -#include <fstream> -#include <iomanip> -#include <ios> -#include <iostream> -#include <string> - -#include <atf-c++.hpp> - -#include "env.hpp" -#include "fs.hpp" -#include "process.hpp" - -// ------------------------------------------------------------------------ -// Auxiliary functions. -// ------------------------------------------------------------------------ - -static -void -touch(const std::string& path) -{ - std::ofstream os(path.c_str()); - if (!os) - ATF_FAIL("Could not create file " + path); - os.close(); -} - -// ------------------------------------------------------------------------ -// Helper tests for "atf-run_test". -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(pass); -ATF_TEST_CASE_HEAD(pass) -{ - set_md_var("descr", "Helper test case for the t_integration test program"); -} -ATF_TEST_CASE_BODY(pass) -{ -} - -ATF_TEST_CASE(config); -ATF_TEST_CASE_HEAD(config) -{ - set_md_var("descr", "Helper test case for the t_integration test program"); -} -ATF_TEST_CASE_BODY(config) -{ - std::cout << "1st: " << get_config_var("1st") << "\n"; - std::cout << "2nd: " << get_config_var("2nd") << "\n"; - std::cout << "3rd: " << get_config_var("3rd") << "\n"; - std::cout << "4th: " << get_config_var("4th") << "\n"; -} - -ATF_TEST_CASE(fds); -ATF_TEST_CASE_HEAD(fds) -{ - set_md_var("descr", "Helper test case for the t_integration test program"); -} -ATF_TEST_CASE_BODY(fds) -{ - std::cout << "msg1 to stdout" << "\n"; - std::cout << "msg2 to stdout" << "\n"; - std::cerr << "msg1 to stderr" << "\n"; - std::cerr << "msg2 to stderr" << "\n"; -} - -ATF_TEST_CASE_WITHOUT_HEAD(mux_streams); -ATF_TEST_CASE_BODY(mux_streams) -{ - for (size_t i = 0; i < 10000; i++) { - switch (i % 5) { - case 0: - std::cout << "stdout " << i << "\n"; - break; - case 1: - std::cerr << "stderr " << i << "\n"; - break; - case 2: - std::cout << "stdout " << i << "\n"; - std::cerr << "stderr " << i << "\n"; - break; - case 3: - std::cout << "stdout " << i << "\n"; - std::cout << "stdout " << i << "\n"; - std::cerr << "stderr " << i << "\n"; - break; - case 4: - std::cout << "stdout " << i << "\n"; - std::cerr << "stderr " << i << "\n"; - std::cerr << "stderr " << i << "\n"; - break; - default: - std::abort(); - } - } -} - -ATF_TEST_CASE(testvar); -ATF_TEST_CASE_HEAD(testvar) -{ - set_md_var("descr", "Helper test case for the t_integration test program"); -} -ATF_TEST_CASE_BODY(testvar) -{ - if (!has_config_var("testvar")) - fail("testvar variable not defined"); - std::cout << "testvar: " << get_config_var("testvar") << "\n"; -} - -ATF_TEST_CASE(env_list); -ATF_TEST_CASE_HEAD(env_list) -{ - set_md_var("descr", "Helper test case for the t_integration test program"); -} -ATF_TEST_CASE_BODY(env_list) -{ - const tools::process::status s = - tools::process::exec(tools::fs::path("env"), - tools::process::argv_array("env", NULL), - tools::process::stream_inherit(), - tools::process::stream_inherit()); - ATF_REQUIRE(s.exited()); - ATF_REQUIRE(s.exitstatus() == EXIT_SUCCESS); -} - -ATF_TEST_CASE(env_home); -ATF_TEST_CASE_HEAD(env_home) -{ - set_md_var("descr", "Helper test case for the t_integration test program"); -} -ATF_TEST_CASE_BODY(env_home) -{ - ATF_REQUIRE(tools::env::has("HOME")); - tools::fs::path p(tools::env::get("HOME")); - tools::fs::file_info fi1(p); - tools::fs::file_info fi2(tools::fs::path(".")); - ATF_REQUIRE_EQ(fi1.get_device(), fi2.get_device()); - ATF_REQUIRE_EQ(fi1.get_inode(), fi2.get_inode()); -} - -ATF_TEST_CASE(read_stdin); -ATF_TEST_CASE_HEAD(read_stdin) -{ - set_md_var("descr", "Helper test case for the t_integration test program"); -} -ATF_TEST_CASE_BODY(read_stdin) -{ - char buf[100]; - ssize_t len = ::read(STDIN_FILENO, buf, sizeof(buf) - 1); - ATF_REQUIRE(len != -1); - - buf[len + 1] = '\0'; - for (ssize_t i = 0; i < len; i++) { - if (buf[i] != '\0') { - fail("The stdin of the test case does not seem to be /dev/zero; " - "got '" + std::string(buf) + "'"); - } - } -} - -ATF_TEST_CASE(umask); -ATF_TEST_CASE_HEAD(umask) -{ - set_md_var("descr", "Helper test case for the t_integration test program"); -} -ATF_TEST_CASE_BODY(umask) -{ - mode_t m = ::umask(0); - std::cout << "umask: " << std::setw(4) << std::setfill('0') - << std::oct << m << "\n"; - (void)::umask(m); -} - -ATF_TEST_CASE_WITH_CLEANUP(cleanup_states); -ATF_TEST_CASE_HEAD(cleanup_states) -{ - set_md_var("descr", "Helper test case for the t_integration test program"); -} -ATF_TEST_CASE_BODY(cleanup_states) -{ - touch(get_config_var("statedir") + "/to-delete"); - touch(get_config_var("statedir") + "/to-stay"); - - if (get_config_var("state") == "fail") - ATF_FAIL("On purpose"); - else if (get_config_var("state") == "skip") - ATF_SKIP("On purpose"); -} -ATF_TEST_CASE_CLEANUP(cleanup_states) -{ - tools::fs::remove(tools::fs::path(get_config_var("statedir") + "/to-delete")); -} - -ATF_TEST_CASE_WITH_CLEANUP(cleanup_curdir); -ATF_TEST_CASE_HEAD(cleanup_curdir) -{ - set_md_var("descr", "Helper test case for the t_integration test program"); -} -ATF_TEST_CASE_BODY(cleanup_curdir) -{ - std::ofstream os("oldvalue"); - if (!os) - ATF_FAIL("Failed to create oldvalue file"); - os << 1234; - os.close(); -} -ATF_TEST_CASE_CLEANUP(cleanup_curdir) -{ - std::ifstream is("oldvalue"); - if (is) { - int i; - is >> i; - std::cout << "Old value: " << i << "\n"; - is.close(); - } -} - -ATF_TEST_CASE(require_arch); -ATF_TEST_CASE_HEAD(require_arch) -{ - set_md_var("descr", "Helper test case for the t_integration test program"); - set_md_var("require.arch", get_config_var("arch", "not-set")); -} -ATF_TEST_CASE_BODY(require_arch) -{ -} - -ATF_TEST_CASE(require_config); -ATF_TEST_CASE_HEAD(require_config) -{ - set_md_var("descr", "Helper test case for the t_integration test program"); - set_md_var("require.config", "var1 var2"); -} -ATF_TEST_CASE_BODY(require_config) -{ - std::cout << "var1: " << get_config_var("var1") << "\n"; - std::cout << "var2: " << get_config_var("var2") << "\n"; -} - -ATF_TEST_CASE(require_files); -ATF_TEST_CASE_HEAD(require_files) -{ - set_md_var("descr", "Helper test case for the t_integration test program"); - set_md_var("require.files", get_config_var("files", "not-set")); -} -ATF_TEST_CASE_BODY(require_files) -{ -} - -ATF_TEST_CASE(require_machine); -ATF_TEST_CASE_HEAD(require_machine) -{ - set_md_var("descr", "Helper test case for the t_integration test program"); - set_md_var("require.machine", get_config_var("machine", "not-set")); -} -ATF_TEST_CASE_BODY(require_machine) -{ -} - -ATF_TEST_CASE(require_progs); -ATF_TEST_CASE_HEAD(require_progs) -{ - set_md_var("descr", "Helper test case for the t_integration test program"); - set_md_var("require.progs", get_config_var("progs", "not-set")); -} -ATF_TEST_CASE_BODY(require_progs) -{ -} - -ATF_TEST_CASE(require_user); -ATF_TEST_CASE_HEAD(require_user) -{ - set_md_var("descr", "Helper test case for the t_integration test program"); - set_md_var("require.user", get_config_var("user", "not-set")); -} -ATF_TEST_CASE_BODY(require_user) -{ -} - -ATF_TEST_CASE(timeout); -ATF_TEST_CASE_HEAD(timeout) -{ - set_md_var("descr", "Helper test case for the t_integration test program"); - set_md_var("timeout", "1"); -} -ATF_TEST_CASE_BODY(timeout) -{ - sleep(10); - touch(get_config_var("statedir") + "/finished"); -} - -ATF_TEST_CASE(timeout_forkexit); -ATF_TEST_CASE_HEAD(timeout_forkexit) -{ - set_md_var("descr", "Helper test case for the t_integration test program"); -} -ATF_TEST_CASE_BODY(timeout_forkexit) -{ - pid_t pid = fork(); - ATF_REQUIRE(pid != -1); - - if (pid == 0) { - sigset_t mask; - sigemptyset(&mask); - - std::cout << "Waiting in subprocess\n"; - std::cout.flush(); - ::sigsuspend(&mask); - - touch(get_config_var("statedir") + "/child-finished"); - std::cout << "Subprocess exiting\n"; - std::cout.flush(); - exit(EXIT_SUCCESS); - } else { - // Don't wait for the child process and let atf-run deal with it. - touch(get_config_var("statedir") + "/parent-finished"); - std::cout << "Parent process exiting\n"; - ATF_PASS(); - } -} - -ATF_TEST_CASE(use_fs); -ATF_TEST_CASE_HEAD(use_fs) -{ - set_md_var("descr", "Helper test case for the t_integration test program"); - set_md_var("use.fs", "this-is-deprecated"); -} -ATF_TEST_CASE_BODY(use_fs) -{ - touch("test-file"); -} - -// ------------------------------------------------------------------------ -// Helper tests for "atf-report_test". -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(diff); -ATF_TEST_CASE_HEAD(diff) -{ - set_md_var("descr", "Helper test case for the t_integration program"); -} -ATF_TEST_CASE_BODY(diff) -{ - std::cout << "--- a 2007-11-04 14:00:41.000000000 +0100\n"; - std::cout << "+++ b 2007-11-04 14:00:48.000000000 +0100\n"; - std::cout << "@@ -1,7 +1,7 @@\n"; - std::cout << " This test is meant to simulate a diff.\n"; - std::cout << " Blank space at beginning of context lines must be " - "preserved.\n"; - std::cout << " \n"; - std::cout << "-First original line.\n"; - std::cout << "-Second original line.\n"; - std::cout << "+First modified line.\n"; - std::cout << "+Second modified line.\n"; - std::cout << " \n"; - std::cout << " EOF\n"; -} - -// ------------------------------------------------------------------------ -// Main. -// ------------------------------------------------------------------------ - -ATF_INIT_TEST_CASES(tcs) -{ - std::string which = tools::env::get("TESTCASE"); - - // Add helper tests for atf-run_test. - if (which == "pass") - ATF_ADD_TEST_CASE(tcs, pass); - if (which == "config") - ATF_ADD_TEST_CASE(tcs, config); - if (which == "fds") - ATF_ADD_TEST_CASE(tcs, fds); - if (which == "mux_streams") - ATF_ADD_TEST_CASE(tcs, mux_streams); - if (which == "testvar") - ATF_ADD_TEST_CASE(tcs, testvar); - if (which == "env_list") - ATF_ADD_TEST_CASE(tcs, env_list); - if (which == "env_home") - ATF_ADD_TEST_CASE(tcs, env_home); - if (which == "read_stdin") - ATF_ADD_TEST_CASE(tcs, read_stdin); - if (which == "umask") - ATF_ADD_TEST_CASE(tcs, umask); - if (which == "cleanup_states") - ATF_ADD_TEST_CASE(tcs, cleanup_states); - if (which == "cleanup_curdir") - ATF_ADD_TEST_CASE(tcs, cleanup_curdir); - if (which == "require_arch") - ATF_ADD_TEST_CASE(tcs, require_arch); - if (which == "require_config") - ATF_ADD_TEST_CASE(tcs, require_config); - if (which == "require_files") - ATF_ADD_TEST_CASE(tcs, require_files); - if (which == "require_machine") - ATF_ADD_TEST_CASE(tcs, require_machine); - if (which == "require_progs") - ATF_ADD_TEST_CASE(tcs, require_progs); - if (which == "require_user") - ATF_ADD_TEST_CASE(tcs, require_user); - if (which == "timeout") - ATF_ADD_TEST_CASE(tcs, timeout); - if (which == "timeout_forkexit") - ATF_ADD_TEST_CASE(tcs, timeout_forkexit); - if (which == "use_fs") - ATF_ADD_TEST_CASE(tcs, use_fs); - - // Add helper tests for atf-report_test. - if (which == "diff") - ATF_ADD_TEST_CASE(tcs, diff); -} diff --git a/tools/parser.cpp b/tools/parser.cpp deleted file mode 100644 index e6b3a3b..0000000 --- a/tools/parser.cpp +++ /dev/null @@ -1,384 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 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 <cassert> -#include <sstream> - -#include "parser.hpp" -#include "text.hpp" - -namespace impl = tools::parser; -#define IMPL_NAME "tools::parser" - -// ------------------------------------------------------------------------ -// The "parse_error" class. -// ------------------------------------------------------------------------ - -impl::parse_error::parse_error(size_t line, std::string msg) : - std::runtime_error(msg), - std::pair< size_t, std::string >(line, msg) -{ -} - -impl::parse_error::~parse_error(void) - throw() -{ -} - -const char* -impl::parse_error::what(void) - const throw() -{ - try { - std::ostringstream oss; - oss << "LONELY PARSE ERROR: " << first << ": " << second; - m_msg = oss.str(); - return m_msg.c_str(); - } catch (...) { - return "Could not format message for parsing error."; - } -} - -impl::parse_error::operator std::string(void) - const -{ - return tools::text::to_string(first) + ": " + second; -} - -// ------------------------------------------------------------------------ -// The "parse_errors" class. -// ------------------------------------------------------------------------ - -impl::parse_errors::parse_errors(void) : - std::runtime_error("No parsing errors yet") -{ - m_msg.clear(); -} - -impl::parse_errors::~parse_errors(void) - throw() -{ -} - -const char* -impl::parse_errors::what(void) - const throw() -{ - try { - m_msg = tools::text::join(*this, "\n"); - return m_msg.c_str(); - } catch (...) { - return "Could not format messages for parsing errors."; - } -} - -// ------------------------------------------------------------------------ -// The "format_error" class. -// ------------------------------------------------------------------------ - -impl::format_error::format_error(const std::string& w) : - std::runtime_error(w.c_str()) -{ -} - -// ------------------------------------------------------------------------ -// The "token" class. -// ------------------------------------------------------------------------ - -impl::token::token(void) : - m_inited(false) -{ -} - -impl::token::token(size_t p_line, - const token_type& p_type, - const std::string& p_text) : - m_inited(true), - m_line(p_line), - m_type(p_type), - m_text(p_text) -{ -} - -size_t -impl::token::lineno(void) - const -{ - return m_line; -} - -const impl::token_type& -impl::token::type(void) - const -{ - return m_type; -} - -const std::string& -impl::token::text(void) - const -{ - return m_text; -} - -impl::token::operator bool(void) - const -{ - return m_inited; -} - -bool -impl::token::operator!(void) - const -{ - return !m_inited; -} - -// ------------------------------------------------------------------------ -// The "header_entry" class. -// ------------------------------------------------------------------------ - -impl::header_entry::header_entry(void) -{ -} - -impl::header_entry::header_entry(const std::string& n, const std::string& v, - attrs_map as) : - m_name(n), - m_value(v), - m_attrs(as) -{ -} - -const std::string& -impl::header_entry::name(void) const -{ - return m_name; -} - -const std::string& -impl::header_entry::value(void) const -{ - return m_value; -} - -const impl::attrs_map& -impl::header_entry::attrs(void) const -{ - return m_attrs; -} - -bool -impl::header_entry::has_attr(const std::string& n) const -{ - return m_attrs.find(n) != m_attrs.end(); -} - -const std::string& -impl::header_entry::get_attr(const std::string& n) const -{ - attrs_map::const_iterator iter = m_attrs.find(n); - assert(iter != m_attrs.end()); - return (*iter).second; -} - -// ------------------------------------------------------------------------ -// The header tokenizer. -// ------------------------------------------------------------------------ - -namespace header { - -static const impl::token_type eof_type = 0; -static const impl::token_type nl_type = 1; -static const impl::token_type text_type = 2; -static const impl::token_type colon_type = 3; -static const impl::token_type semicolon_type = 4; -static const impl::token_type dblquote_type = 5; -static const impl::token_type equal_type = 6; - -class tokenizer : public impl::tokenizer< std::istream > { -public: - tokenizer(std::istream& is, size_t curline) : - impl::tokenizer< std::istream > - (is, true, eof_type, nl_type, text_type, curline) - { - add_delim(';', semicolon_type); - add_delim(':', colon_type); - add_delim('=', equal_type); - add_quote('"', dblquote_type); - } -}; - -static -impl::parser< header::tokenizer >& -read(impl::parser< header::tokenizer >& p, impl::header_entry& he) -{ - using namespace header; - - impl::token t = p.expect(text_type, nl_type, "a header name"); - if (t.type() == nl_type) { - he = impl::header_entry(); - return p; - } - std::string hdr_name = t.text(); - - t = p.expect(colon_type, "`:'"); - - t = p.expect(text_type, "a textual value"); - std::string hdr_value = t.text(); - - impl::attrs_map attrs; - - for (;;) { - t = p.expect(eof_type, semicolon_type, nl_type, - "eof, `;' or new line"); - if (t.type() == eof_type || t.type() == nl_type) - break; - - t = p.expect(text_type, "an attribute name"); - std::string attr_name = t.text(); - - t = p.expect(equal_type, "`='"); - - t = p.expect(text_type, "word or quoted string"); - std::string attr_value = t.text(); - attrs[attr_name] = attr_value; - } - - he = impl::header_entry(hdr_name, hdr_value, attrs); - - return p; -} - -static -std::ostream& -write(std::ostream& os, const impl::header_entry& he) -{ - std::string line = he.name() + ": " + he.value(); - impl::attrs_map as = he.attrs(); - for (impl::attrs_map::const_iterator iter = as.begin(); iter != as.end(); - iter++) { - assert((*iter).second.find('\"') == std::string::npos); - line += "; " + (*iter).first + "=\"" + (*iter).second + "\""; - } - - os << line << "\n"; - - return os; -} - -} // namespace header - -// ------------------------------------------------------------------------ -// Free functions. -// ------------------------------------------------------------------------ - -std::pair< size_t, impl::headers_map > -impl::read_headers(std::istream& is, size_t curline) -{ - using impl::format_error; - - headers_map hm; - - // - // Grammar - // - // header = entry+ nl - // entry = line nl - // line = text colon text - // (semicolon (text equal (text | dblquote string dblquote)))* - // string = quoted_string - // - - header::tokenizer tkz(is, curline); - impl::parser< header::tokenizer > p(tkz); - - bool first = true; - for (;;) { - try { - header_entry he; - if (!header::read(p, he).good() || he.name().empty()) - break; - - if (first && he.name() != "Content-Type") - throw format_error("Could not determine content type"); - else - first = false; - - hm[he.name()] = he; - } catch (const impl::parse_error& pe) { - p.add_error(pe); - p.reset(header::nl_type); - } - } - - if (!is.good()) - throw format_error("Unexpected end of stream"); - - return std::pair< size_t, headers_map >(tkz.lineno(), hm); -} - -void -impl::write_headers(const impl::headers_map& hm, std::ostream& os) -{ - assert(!hm.empty()); - headers_map::const_iterator ct = hm.find("Content-Type"); - assert(ct != hm.end()); - header::write(os, (*ct).second); - for (headers_map::const_iterator iter = hm.begin(); iter != hm.end(); - iter++) { - if ((*iter).first != "Content-Type") - header::write(os, (*iter).second); - } - os << "\n"; -} - -void -impl::validate_content_type(const impl::headers_map& hm, const std::string& fmt, - int version) -{ - using impl::format_error; - - headers_map::const_iterator iter = hm.find("Content-Type"); - if (iter == hm.end()) - throw format_error("Could not determine content type"); - - const header_entry& he = (*iter).second; - if (he.value() != fmt) - throw format_error("Mismatched content type: expected `" + fmt + - "' but got `" + he.value() + "'"); - - if (!he.has_attr("version")) - throw format_error("Could not determine version"); - const std::string& vstr = tools::text::to_string(version); - if (he.get_attr("version") != vstr) - throw format_error("Mismatched version: expected `" + - vstr + "' but got `" + - he.get_attr("version") + "'"); -} diff --git a/tools/parser.hpp b/tools/parser.hpp deleted file mode 100644 index eb00cb4..0000000 --- a/tools/parser.hpp +++ /dev/null @@ -1,607 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if !defined(TOOLS_PARSER_HPP) -#define TOOLS_PARSER_HPP - -#include <istream> -#include <map> -#include <ostream> -#include <stdexcept> -#include <string> -#include <utility> -#include <vector> - -namespace tools { -namespace parser { - -// ------------------------------------------------------------------------ -// The "parse_error" class. -// ------------------------------------------------------------------------ - -class parse_error : public std::runtime_error, - public std::pair< size_t, std::string > { - mutable std::string m_msg; - -public: - parse_error(size_t, std::string); - ~parse_error(void) throw(); - - const char* what(void) const throw(); - - operator std::string(void) const; -}; - -// ------------------------------------------------------------------------ -// The "parse_errors" class. -// ------------------------------------------------------------------------ - -class parse_errors : public std::runtime_error, - public std::vector< parse_error > { - std::vector< parse_error > m_errors; - mutable std::string m_msg; - -public: - parse_errors(void); - ~parse_errors(void) throw(); - - const char* what(void) const throw(); -}; - -// ------------------------------------------------------------------------ -// The "format_error" class. -// ------------------------------------------------------------------------ - -class format_error : public std::runtime_error { -public: - format_error(const std::string&); -}; - -// ------------------------------------------------------------------------ -// The "token" class. -// ------------------------------------------------------------------------ - -typedef int token_type; - -//! -//! \brief Representation of a read token. -//! -//! A pair that contains the information of a token read from a stream. -//! It contains the token's type and its associated data, if any. -//! -struct token { - bool m_inited; - size_t m_line; - token_type m_type; - std::string m_text; - -public: - token(void); - token(size_t, const token_type&, const std::string& = ""); - - size_t lineno(void) const; - const token_type& type(void) const; - const std::string& text(void) const; - - operator bool(void) const; - bool operator!(void) const; -}; - -// ------------------------------------------------------------------------ -// The "tokenizer" class. -// ------------------------------------------------------------------------ - -//! -//! \brief A stream tokenizer. -//! -//! This template implements an extremely simple, line-oriented stream -//! tokenizer. It is only able to recognize one character-long delimiters, -//! random-length keywords, skip whitespace and, anything that does not -//! match these rules is supposed to be a word. -//! -//! Parameter IS: The input stream's type. -//! -template< class IS > -class tokenizer { - IS& m_is; - size_t m_lineno; - token m_la; - - bool m_skipws; - token_type m_eof_type, m_nl_type, m_text_type; - - std::map< char, token_type > m_delims_map; - std::string m_delims_str; - - char m_quotech; - token_type m_quotetype; - - std::map< std::string, token_type > m_keywords_map; - - token_type alloc_type(void); - - template< class TKZ > - friend - class parser; - -public: - tokenizer(IS&, bool, const token_type&, const token_type&, - const token_type&, size_t = 1); - - size_t lineno(void) const; - - void add_delim(char, const token_type&); - void add_keyword(const std::string&, const token_type&); - void add_quote(char, const token_type&); - - token next(void); - std::string rest_of_line(void); -}; - -template< class IS > -tokenizer< IS >::tokenizer(IS& p_is, - bool p_skipws, - const token_type& p_eof_type, - const token_type& p_nl_type, - const token_type& p_text_type, - size_t p_lineno) : - m_is(p_is), - m_lineno(p_lineno), - m_skipws(p_skipws), - m_eof_type(p_eof_type), - m_nl_type(p_nl_type), - m_text_type(p_text_type), - m_quotech(-1) -{ -} - -template< class IS > -size_t -tokenizer< IS >::lineno(void) - const -{ - return m_lineno; -} - -template< class IS > -void -tokenizer< IS >::add_delim(char delim, const token_type& type) -{ - m_delims_map[delim] = type; - m_delims_str += delim; -} - -template< class IS > -void -tokenizer< IS >::add_keyword(const std::string& keyword, - const token_type& type) -{ - m_keywords_map[keyword] = type; -} - -template< class IS > -void -tokenizer< IS >::add_quote(char ch, const token_type& type) -{ - m_quotech = ch; - m_quotetype = type; -} - -template< class IS > -token -tokenizer< IS >::next(void) -{ - if (m_la) { - token t = m_la; - m_la = token(); - if (t.type() == m_nl_type) - m_lineno++; - return t; - } - - char ch; - std::string text; - - bool done = false, quoted = false; - token t(m_lineno, m_eof_type, "<<EOF>>"); - while (!done && m_is.get(ch).good()) { - if (ch == m_quotech) { - if (text.empty()) { - bool escaped = false; - while (!done && m_is.get(ch).good()) { - if (!escaped) { - if (ch == '\\') - escaped = true; - else if (ch == '\n') { - m_la = token(m_lineno, m_nl_type, "<<NEWLINE>>"); - throw parse_error(t.lineno(), - "Missing double quotes before " - "end of line"); - } else if (ch == m_quotech) - done = true; - else - text += ch; - } else { - text += ch; - escaped = false; - } - } - if (!m_is.good()) - throw parse_error(t.lineno(), - "Missing double quotes before " - "end of file"); - t = token(m_lineno, m_text_type, text); - quoted = true; - } else { - m_is.putback(ch); - done = true; - } - } else { - typename std::map< char, token_type >::const_iterator idelim; - idelim = m_delims_map.find(ch); - if (idelim != m_delims_map.end()) { - done = true; - if (text.empty()) - t = token(m_lineno, (*idelim).second, - std::string("") + ch); - else - m_is.putback(ch); - } else if (ch == '\n') { - done = true; - if (text.empty()) - t = token(m_lineno, m_nl_type, "<<NEWLINE>>"); - else - m_is.putback(ch); - } else if (m_skipws && (ch == ' ' || ch == '\t')) { - if (!text.empty()) - done = true; - } else - text += ch; - } - } - - if (!quoted && !text.empty()) { - typename std::map< std::string, token_type >::const_iterator ikw; - ikw = m_keywords_map.find(text); - if (ikw != m_keywords_map.end()) - t = token(m_lineno, (*ikw).second, text); - else - t = token(m_lineno, m_text_type, text); - } - - if (t.type() == m_nl_type) - m_lineno++; - - return t; -} - -template< class IS > -std::string -tokenizer< IS >::rest_of_line(void) -{ - std::string str; - while (m_is.good() && m_is.peek() != '\n') - str += m_is.get(); - return str; -} - -// ------------------------------------------------------------------------ -// The "parser" class. -// ------------------------------------------------------------------------ - -template< class TKZ > -class parser { - TKZ& m_tkz; - token m_last; - parse_errors m_errors; - bool m_thrown; - -public: - parser(TKZ& tkz); - ~parser(void); - - bool good(void) const; - void add_error(const parse_error&); - bool has_errors(void) const; - - token next(void); - std::string rest_of_line(void); - token reset(const token_type&); - - token - expect(const token_type&, - const std::string&); - - token - expect(const token_type&, - const token_type&, - const std::string&); - - token - expect(const token_type&, - const token_type&, - const token_type&, - const std::string&); - - token - expect(const token_type&, - const token_type&, - const token_type&, - const token_type&, - const std::string&); - - token - expect(const token_type&, - const token_type&, - const token_type&, - const token_type&, - const token_type&, - const token_type&, - const token_type&, - const std::string&); - - token - expect(const token_type&, - const token_type&, - const token_type&, - const token_type&, - const token_type&, - const token_type&, - const token_type&, - const token_type&, - const std::string&); -}; - -template< class TKZ > -parser< TKZ >::parser(TKZ& tkz) : - m_tkz(tkz), - m_thrown(false) -{ -} - -template< class TKZ > -parser< TKZ >::~parser(void) -{ - if (!m_errors.empty() && !m_thrown) - throw m_errors; -} - -template< class TKZ > -bool -parser< TKZ >::good(void) - const -{ - return m_tkz.m_is.good(); -} - -template< class TKZ > -void -parser< TKZ >::add_error(const parse_error& pe) -{ - m_errors.push_back(pe); -} - -template< class TKZ > -bool -parser< TKZ >::has_errors(void) - const -{ - return !m_errors.empty(); -} - -template< class TKZ > -token -parser< TKZ >::next(void) -{ - token t = m_tkz.next(); - - m_last = t; - - if (t.type() == m_tkz.m_eof_type) { - if (!m_errors.empty()) { - m_thrown = true; - throw m_errors; - } - } - - return t; -} - -template< class TKZ > -std::string -parser< TKZ >::rest_of_line(void) -{ - return m_tkz.rest_of_line(); -} - -template< class TKZ > -token -parser< TKZ >::reset(const token_type& stop) -{ - token t = m_last; - - while (t.type() != m_tkz.m_eof_type && t.type() != stop) - t = next(); - - return t; -} - -template< class TKZ > -token -parser< TKZ >::expect(const token_type& t1, - const std::string& textual) -{ - token t = next(); - - if (t.type() != t1) - throw parse_error(t.lineno(), - "Unexpected token `" + t.text() + - "'; expected " + textual); - - return t; -} - -template< class TKZ > -token -parser< TKZ >::expect(const token_type& t1, - const token_type& t2, - const std::string& textual) -{ - token t = next(); - - if (t.type() != t1 && t.type() != t2) - throw parse_error(t.lineno(), - "Unexpected token `" + t.text() + - "'; expected " + textual); - - return t; -} - -template< class TKZ > -token -parser< TKZ >::expect(const token_type& t1, - const token_type& t2, - const token_type& t3, - const std::string& textual) -{ - token t = next(); - - if (t.type() != t1 && t.type() != t2 && t.type() != t3) - throw parse_error(t.lineno(), - "Unexpected token `" + t.text() + - "'; expected " + textual); - - return t; -} - -template< class TKZ > -token -parser< TKZ >::expect(const token_type& t1, - const token_type& t2, - const token_type& t3, - const token_type& t4, - const std::string& textual) -{ - token t = next(); - - if (t.type() != t1 && t.type() != t2 && t.type() != t3 && - t.type() != t4) - throw parse_error(t.lineno(), - "Unexpected token `" + t.text() + - "'; expected " + textual); - - return t; -} - -template< class TKZ > -token -parser< TKZ >::expect(const token_type& t1, - const token_type& t2, - const token_type& t3, - const token_type& t4, - const token_type& t5, - const token_type& t6, - const token_type& t7, - const std::string& textual) -{ - token t = next(); - - if (t.type() != t1 && t.type() != t2 && t.type() != t3 && - t.type() != t4 && t.type() != t5 && t.type() != t6 && - t.type() != t7) - throw parse_error(t.lineno(), - "Unexpected token `" + t.text() + - "'; expected " + textual); - - return t; -} - -template< class TKZ > -token -parser< TKZ >::expect(const token_type& t1, - const token_type& t2, - const token_type& t3, - const token_type& t4, - const token_type& t5, - const token_type& t6, - const token_type& t7, - const token_type& t8, - const std::string& textual) -{ - token t = next(); - - if (t.type() != t1 && t.type() != t2 && t.type() != t3 && - t.type() != t4 && t.type() != t5 && t.type() != t6 && - t.type() != t7 && t.type() != t8) - throw parse_error(t.lineno(), - "Unexpected token `" + t.text() + - "'; expected " + textual); - - return t; -} - -#define ATF_PARSER_CALLBACK(parser, func) \ - do { \ - if (!(parser).has_errors()) \ - func; \ - } while (false) - -// ------------------------------------------------------------------------ -// Header parsing. -// ------------------------------------------------------------------------ - -typedef std::map< std::string, std::string > attrs_map; - -class header_entry { - std::string m_name; - std::string m_value; - attrs_map m_attrs; - -public: - header_entry(void); - header_entry(const std::string&, const std::string&, - attrs_map = attrs_map()); - - const std::string& name(void) const; - const std::string& value(void) const; - const attrs_map& attrs(void) const; - bool has_attr(const std::string&) const; - const std::string& get_attr(const std::string&) const; -}; - -typedef std::map< std::string, header_entry > headers_map; - -std::pair< size_t, headers_map > read_headers(std::istream&, size_t); -void write_headers(const headers_map&, std::ostream&); -void validate_content_type(const headers_map&, const std::string&, int); - -} // namespace parser -} // namespace tools - -#endif // !defined(TOOLS_PARSER_HPP) diff --git a/tools/parser_test.cpp b/tools/parser_test.cpp deleted file mode 100644 index 434a1a6..0000000 --- a/tools/parser_test.cpp +++ /dev/null @@ -1,1043 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include <sstream> - -#include <atf-c++.hpp> - -#include "parser.hpp" -#include "test_helpers.hpp" - -// ------------------------------------------------------------------------ -// Tests for the "parse_error" class. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(parse_error_to_string); -ATF_TEST_CASE_HEAD(parse_error_to_string) -{ - set_md_var("descr", "Tests the parse_error conversion to strings"); -} -ATF_TEST_CASE_BODY(parse_error_to_string) -{ - using tools::parser::parse_error; - - const parse_error e(123, "This is the message"); - ATF_REQUIRE_EQ("123: This is the message", std::string(e)); -} - -// ------------------------------------------------------------------------ -// Tests for the "parse_errors" class. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(parse_errors_what); -ATF_TEST_CASE_HEAD(parse_errors_what) -{ - set_md_var("descr", "Tests the parse_errors description"); -} -ATF_TEST_CASE_BODY(parse_errors_what) -{ - using tools::parser::parse_error; - using tools::parser::parse_errors; - - parse_errors es; - es.push_back(parse_error(2, "Second error")); - es.push_back(parse_error(1, "First error")); - - ATF_REQUIRE_EQ("2: Second error\n1: First error", std::string(es.what())); -} - -// ------------------------------------------------------------------------ -// Tests for the "token" class. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(token_getters); -ATF_TEST_CASE_HEAD(token_getters) -{ - set_md_var("descr", "Tests the token getters"); -} -ATF_TEST_CASE_BODY(token_getters) -{ - using tools::parser::token; - - { - token t(10, 0); - ATF_REQUIRE_EQ(t.lineno(), 10); - ATF_REQUIRE_EQ(t.type(), 0); - ATF_REQUIRE(t.text().empty()); - } - - { - token t(10, 0, "foo"); - ATF_REQUIRE_EQ(t.lineno(), 10); - ATF_REQUIRE_EQ(t.type(), 0); - ATF_REQUIRE_EQ(t.text(), "foo"); - } - - { - token t(20, 1); - ATF_REQUIRE_EQ(t.lineno(), 20); - ATF_REQUIRE_EQ(t.type(), 1); - ATF_REQUIRE(t.text().empty()); - } - - { - token t(20, 1, "bar"); - ATF_REQUIRE_EQ(t.lineno(), 20); - ATF_REQUIRE_EQ(t.type(), 1); - ATF_REQUIRE_EQ(t.text(), "bar"); - } -} - -// ------------------------------------------------------------------------ -// Tests for the "tokenizer" class. -// ------------------------------------------------------------------------ - -#define EXPECT(tkz, ttype, ttext) \ - do { \ - tools::parser::token t = tkz.next(); \ - ATF_REQUIRE(t.type() == ttype); \ - ATF_REQUIRE_EQ(t.text(), ttext); \ - } while (false); - -namespace minimal { - - static const tools::parser::token_type eof_type = 0; - static const tools::parser::token_type nl_type = 1; - static const tools::parser::token_type word_type = 2; - - class tokenizer : public tools::parser::tokenizer< std::istream > { - public: - tokenizer(std::istream& is, bool skipws) : - tools::parser::tokenizer< std::istream > - (is, skipws, eof_type, nl_type, word_type) - { - } - }; - -} - -namespace delims { - - static const tools::parser::token_type eof_type = 0; - static const tools::parser::token_type nl_type = 1; - static const tools::parser::token_type word_type = 2; - static const tools::parser::token_type plus_type = 3; - static const tools::parser::token_type minus_type = 4; - static const tools::parser::token_type equal_type = 5; - - class tokenizer : public tools::parser::tokenizer< std::istream > { - public: - tokenizer(std::istream& is, bool skipws) : - tools::parser::tokenizer< std::istream > - (is, skipws, eof_type, nl_type, word_type) - { - add_delim('+', plus_type); - add_delim('-', minus_type); - add_delim('=', equal_type); - } - }; - -} - -namespace keywords { - - static const tools::parser::token_type eof_type = 0; - static const tools::parser::token_type nl_type = 1; - static const tools::parser::token_type word_type = 2; - static const tools::parser::token_type var_type = 3; - static const tools::parser::token_type loop_type = 4; - static const tools::parser::token_type endloop_type = 5; - - class tokenizer : public tools::parser::tokenizer< std::istream > { - public: - tokenizer(std::istream& is, bool skipws) : - tools::parser::tokenizer< std::istream > - (is, skipws, eof_type, nl_type, word_type) - { - add_keyword("var", var_type); - add_keyword("loop", loop_type); - add_keyword("endloop", endloop_type); - } - }; - -} - -namespace quotes { - - static const tools::parser::token_type eof_type = 0; - static const tools::parser::token_type nl_type = 1; - static const tools::parser::token_type word_type = 2; - static const tools::parser::token_type dblquote_type = 3; - - class tokenizer : public tools::parser::tokenizer< std::istream > { - public: - tokenizer(std::istream& is, bool skipws) : - tools::parser::tokenizer< std::istream > - (is, skipws, eof_type, nl_type, word_type) - { - add_quote('"', dblquote_type); - } - }; - -} - -ATF_TEST_CASE(tokenizer_minimal_nows); -ATF_TEST_CASE_HEAD(tokenizer_minimal_nows) -{ - set_md_var("descr", "Tests the tokenizer class using a minimal parser " - "and not skipping whitespace"); -} -ATF_TEST_CASE_BODY(tokenizer_minimal_nows) -{ - using namespace minimal; - - { - std::istringstream iss(""); - tokenizer mt(iss, false); - - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("\n"); - tokenizer mt(iss, false); - - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("\n\n\n"); - tokenizer mt(iss, false); - - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("line 1"); - tokenizer mt(iss, false); - - EXPECT(mt, word_type, "line 1"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("line 1\n"); - tokenizer mt(iss, false); - - EXPECT(mt, word_type, "line 1"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("line 1\nline 2"); - tokenizer mt(iss, false); - - EXPECT(mt, word_type, "line 1"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, word_type, "line 2"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("line 1\nline 2\nline 3\n"); - tokenizer mt(iss, false); - - EXPECT(mt, word_type, "line 1"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, word_type, "line 2"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, word_type, "line 3"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } -} - -ATF_TEST_CASE(tokenizer_minimal_ws); -ATF_TEST_CASE_HEAD(tokenizer_minimal_ws) -{ - set_md_var("descr", "Tests the tokenizer class using a minimal parser " - "and skipping whitespace"); -} -ATF_TEST_CASE_BODY(tokenizer_minimal_ws) -{ - using namespace minimal; - - { - std::istringstream iss(""); - minimal::tokenizer mt(iss, true); - - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss(" \t "); - tokenizer mt(iss, true); - - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("\n"); - tokenizer mt(iss, true); - - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss(" \t \n \t "); - tokenizer mt(iss, true); - - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("\n\n\n"); - tokenizer mt(iss, true); - - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("line 1"); - tokenizer mt(iss, true); - - EXPECT(mt, word_type, "line"); - EXPECT(mt, word_type, "1"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss(" \tline\t 1\t"); - tokenizer mt(iss, true); - - EXPECT(mt, word_type, "line"); - EXPECT(mt, word_type, "1"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("line 1\n"); - tokenizer mt(iss, true); - - EXPECT(mt, word_type, "line"); - EXPECT(mt, word_type, "1"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("line 1\nline 2"); - tokenizer mt(iss, true); - - EXPECT(mt, word_type, "line"); - EXPECT(mt, word_type, "1"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, word_type, "line"); - EXPECT(mt, word_type, "2"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("line 1\nline 2\nline 3\n"); - tokenizer mt(iss, true); - - EXPECT(mt, word_type, "line"); - EXPECT(mt, word_type, "1"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, word_type, "line"); - EXPECT(mt, word_type, "2"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, word_type, "line"); - EXPECT(mt, word_type, "3"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss(" \t line \t 1\n\tline\t2\n line 3 \n"); - tokenizer mt(iss, true); - - EXPECT(mt, word_type, "line"); - EXPECT(mt, word_type, "1"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, word_type, "line"); - EXPECT(mt, word_type, "2"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, word_type, "line"); - EXPECT(mt, word_type, "3"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } -} - -ATF_TEST_CASE(tokenizer_delims_nows); -ATF_TEST_CASE_HEAD(tokenizer_delims_nows) -{ - set_md_var("descr", "Tests the tokenizer class using a parser with some " - "additional delimiters and not skipping whitespace"); -} -ATF_TEST_CASE_BODY(tokenizer_delims_nows) -{ - using namespace delims; - - { - std::istringstream iss("+-="); - tokenizer mt(iss, false); - - EXPECT(mt, plus_type, "+"); - EXPECT(mt, minus_type, "-"); - EXPECT(mt, equal_type, "="); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("+++"); - tokenizer mt(iss, false); - - EXPECT(mt, plus_type, "+"); - EXPECT(mt, plus_type, "+"); - EXPECT(mt, plus_type, "+"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("\n+\n++\n"); - tokenizer mt(iss, false); - - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, plus_type, "+"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, plus_type, "+"); - EXPECT(mt, plus_type, "+"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("foo+bar=baz"); - tokenizer mt(iss, false); - - EXPECT(mt, word_type, "foo"); - EXPECT(mt, plus_type, "+"); - EXPECT(mt, word_type, "bar"); - EXPECT(mt, equal_type, "="); - EXPECT(mt, word_type, "baz"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss(" foo\t+\tbar = baz "); - tokenizer mt(iss, false); - - EXPECT(mt, word_type, " foo\t"); - EXPECT(mt, plus_type, "+"); - EXPECT(mt, word_type, "\tbar "); - EXPECT(mt, equal_type, "="); - EXPECT(mt, word_type, " baz "); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } -} - -ATF_TEST_CASE(tokenizer_delims_ws); -ATF_TEST_CASE_HEAD(tokenizer_delims_ws) -{ - set_md_var("descr", "Tests the tokenizer class using a parser with some " - "additional delimiters and skipping whitespace"); -} -ATF_TEST_CASE_BODY(tokenizer_delims_ws) -{ - using namespace delims; - - { - std::istringstream iss(" foo\t+\tbar = baz "); - tokenizer mt(iss, true); - - EXPECT(mt, word_type, "foo"); - EXPECT(mt, plus_type, "+"); - EXPECT(mt, word_type, "bar"); - EXPECT(mt, equal_type, "="); - EXPECT(mt, word_type, "baz"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } -} - -ATF_TEST_CASE(tokenizer_keywords_nows); -ATF_TEST_CASE_HEAD(tokenizer_keywords_nows) -{ - set_md_var("descr", "Tests the tokenizer class using a parser with some " - "additional keywords and not skipping whitespace"); -} -ATF_TEST_CASE_BODY(tokenizer_keywords_nows) -{ - using namespace keywords; - - { - std::istringstream iss("var"); - tokenizer mt(iss, false); - - EXPECT(mt, var_type, "var"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("va"); - tokenizer mt(iss, false); - - EXPECT(mt, word_type, "va"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("vara"); - tokenizer mt(iss, false); - - EXPECT(mt, word_type, "vara"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("var "); - tokenizer mt(iss, false); - - EXPECT(mt, word_type, "var "); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("var\nloop\nendloop"); - tokenizer mt(iss, false); - - EXPECT(mt, var_type, "var"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, loop_type, "loop"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, endloop_type, "endloop"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } -} - -ATF_TEST_CASE(tokenizer_keywords_ws); -ATF_TEST_CASE_HEAD(tokenizer_keywords_ws) -{ - set_md_var("descr", "Tests the tokenizer class using a parser with some " - "additional keywords and not skipping whitespace"); -} -ATF_TEST_CASE_BODY(tokenizer_keywords_ws) -{ - using namespace keywords; - - { - std::istringstream iss("var "); - tokenizer mt(iss, true); - - EXPECT(mt, var_type, "var"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss(" var \n\tloop\t\n \tendloop \t"); - tokenizer mt(iss, true); - - EXPECT(mt, var_type, "var"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, loop_type, "loop"); - EXPECT(mt, nl_type, "<<NEWLINE>>"); - EXPECT(mt, endloop_type, "endloop"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("var loop endloop"); - tokenizer mt(iss, true); - - EXPECT(mt, var_type, "var"); - EXPECT(mt, loop_type, "loop"); - EXPECT(mt, endloop_type, "endloop"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } -} - -ATF_TEST_CASE(tokenizer_quotes_nows); -ATF_TEST_CASE_HEAD(tokenizer_quotes_nows) -{ - set_md_var("descr", "Tests the tokenizer class using a parser with " - "quoted strings and not skipping whitespace"); -} -ATF_TEST_CASE_BODY(tokenizer_quotes_nows) -{ - using namespace quotes; - - { - std::istringstream iss("var"); - tokenizer mt(iss, false); - - EXPECT(mt, word_type, "var"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("\"var\""); - tokenizer mt(iss, false); - - EXPECT(mt, word_type, "var"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("var1\"var2\""); - tokenizer mt(iss, false); - - EXPECT(mt, word_type, "var1"); - EXPECT(mt, word_type, "var2"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss("var1\" var2 \""); - tokenizer mt(iss, false); - - EXPECT(mt, word_type, "var1"); - EXPECT(mt, word_type, " var2 "); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } -} - -ATF_TEST_CASE(tokenizer_quotes_ws); -ATF_TEST_CASE_HEAD(tokenizer_quotes_ws) -{ - set_md_var("descr", "Tests the tokenizer class using a parser with " - "quoted strings and skipping whitespace"); -} -ATF_TEST_CASE_BODY(tokenizer_quotes_ws) -{ - using namespace quotes; - - { - std::istringstream iss(" var "); - tokenizer mt(iss, true); - - EXPECT(mt, word_type, "var"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss(" \"var\" "); - tokenizer mt(iss, true); - - EXPECT(mt, word_type, "var"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss(" var1 \"var2\" "); - tokenizer mt(iss, true); - - EXPECT(mt, word_type, "var1"); - EXPECT(mt, word_type, "var2"); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } - - { - std::istringstream iss(" var1 \" var2 \" "); - tokenizer mt(iss, true); - - EXPECT(mt, word_type, "var1"); - EXPECT(mt, word_type, " var2 "); - EXPECT(mt, eof_type, "<<EOF>>"); - EXPECT(mt, eof_type, "<<EOF>>"); - } -} - -// ------------------------------------------------------------------------ -// Tests for the headers parser. -// ------------------------------------------------------------------------ - -class header_reader { - std::istream& m_is; - -public: - header_reader(std::istream& is) : - m_is(is) - { - } - - void - read(void) - { - std::pair< size_t, tools::parser::headers_map > hml = - tools::parser::read_headers(m_is, 1); - tools::parser::validate_content_type(hml.second, - "application/X-atf-headers-test", 1234); - } - - std::vector< std::string > m_calls; -}; - -ATF_TEST_CASE_WITHOUT_HEAD(headers_1); -ATF_TEST_CASE_BODY(headers_1) -{ - const char* input = - "" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "1: Unexpected token `<<EOF>>'; expected a header name", - NULL - }; - - do_parser_test< header_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(headers_2); -ATF_TEST_CASE_BODY(headers_2) -{ - const char* input = - "Content-Type\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "1: Unexpected token `<<NEWLINE>>'; expected `:'", - NULL - }; - - do_parser_test< header_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(headers_3); -ATF_TEST_CASE_BODY(headers_3) -{ - const char* input = - "Content-Type:\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "1: Unexpected token `<<NEWLINE>>'; expected a textual value", - NULL - }; - - do_parser_test< header_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(headers_4); -ATF_TEST_CASE_BODY(headers_4) -{ - const char* input = - "Content-Type: application/X-atf-headers-test\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "2: Unexpected token `<<EOF>>'; expected a header name", - NULL - }; - - do_parser_test< header_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(headers_5); -ATF_TEST_CASE_BODY(headers_5) -{ - const char* input = - "Content-Type: application/X-atf-headers-test;\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "1: Unexpected token `<<NEWLINE>>'; expected an attribute name", - NULL - }; - - do_parser_test< header_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(headers_6); -ATF_TEST_CASE_BODY(headers_6) -{ - const char* input = - "Content-Type: application/X-atf-headers-test; version\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "1: Unexpected token `<<NEWLINE>>'; expected `='", - NULL - }; - - do_parser_test< header_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(headers_7); -ATF_TEST_CASE_BODY(headers_7) -{ - const char* input = - "Content-Type: application/X-atf-headers-test; version=\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "1: Unexpected token `<<NEWLINE>>'; expected word or quoted string", - NULL - }; - - do_parser_test< header_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(headers_8); -ATF_TEST_CASE_BODY(headers_8) -{ - const char* input = - "Content-Type: application/X-atf-headers-test; version=\"1234\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "1: Missing double quotes before end of line", - NULL - }; - - do_parser_test< header_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(headers_9); -ATF_TEST_CASE_BODY(headers_9) -{ - const char* input = - "Content-Type: application/X-atf-headers-test; version=1234\"\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "1: Missing double quotes before end of line", - NULL - }; - - do_parser_test< header_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(headers_10); -ATF_TEST_CASE_BODY(headers_10) -{ - const char* input = - "Content-Type: application/X-atf-headers-test; version=1234\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "2: Unexpected token `<<EOF>>'; expected a header name", - NULL - }; - - do_parser_test< header_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(headers_11); -ATF_TEST_CASE_BODY(headers_11) -{ - const char* input = - "Content-Type: application/X-atf-headers-test; version=\"1234\"\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "2: Unexpected token `<<EOF>>'; expected a header name", - NULL - }; - - do_parser_test< header_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(headers_12); -ATF_TEST_CASE_BODY(headers_12) -{ - const char* input = - "Content-Type: application/X-atf-headers-test; version=\"1234\"\n" - "a b\n" - "a-b:\n" - "a-b: foo;\n" - "a-b: foo; var\n" - "a-b: foo; var=\n" - "a-b: foo; var=\"a\n" - "a-b: foo; var=a\"\n" - "a-b: foo; var=\"a\";\n" - "a-b: foo; var=\"a\"; second\n" - "a-b: foo; var=\"a\"; second=\n" - "a-b: foo; var=\"a\"; second=\"b\n" - "a-b: foo; var=\"a\"; second=b\"\n" - "a-b: foo; var=\"a\"; second=\"b\"\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "2: Unexpected token `b'; expected `:'", - "3: Unexpected token `<<NEWLINE>>'; expected a textual value", - "4: Unexpected token `<<NEWLINE>>'; expected an attribute name", - "5: Unexpected token `<<NEWLINE>>'; expected `='", - "6: Unexpected token `<<NEWLINE>>'; expected word or quoted string", - "7: Missing double quotes before end of line", - "8: Missing double quotes before end of line", - "9: Unexpected token `<<NEWLINE>>'; expected an attribute name", - "10: Unexpected token `<<NEWLINE>>'; expected `='", - "11: Unexpected token `<<NEWLINE>>'; expected word or quoted string", - "12: Missing double quotes before end of line", - "13: Missing double quotes before end of line", - NULL - }; - - do_parser_test< header_reader >(input, exp_calls, exp_errors); -} - -// ------------------------------------------------------------------------ -// Main. -// ------------------------------------------------------------------------ - -ATF_INIT_TEST_CASES(tcs) -{ - // Add test cases for the "parse_error" class. - ATF_ADD_TEST_CASE(tcs, parse_error_to_string); - - // Add test cases for the "parse_errors" class. - ATF_ADD_TEST_CASE(tcs, parse_errors_what); - - // Add test cases for the "token" class. - ATF_ADD_TEST_CASE(tcs, token_getters); - - // Add test cases for the "tokenizer" class. - ATF_ADD_TEST_CASE(tcs, tokenizer_minimal_nows); - ATF_ADD_TEST_CASE(tcs, tokenizer_minimal_ws); - ATF_ADD_TEST_CASE(tcs, tokenizer_delims_nows); - ATF_ADD_TEST_CASE(tcs, tokenizer_delims_ws); - ATF_ADD_TEST_CASE(tcs, tokenizer_keywords_nows); - ATF_ADD_TEST_CASE(tcs, tokenizer_keywords_ws); - ATF_ADD_TEST_CASE(tcs, tokenizer_quotes_nows); - ATF_ADD_TEST_CASE(tcs, tokenizer_quotes_ws); - - // Add the tests for the headers parser. - - // Add the test cases for the header file. - ATF_ADD_TEST_CASE(tcs, headers_1); - ATF_ADD_TEST_CASE(tcs, headers_2); - ATF_ADD_TEST_CASE(tcs, headers_3); - ATF_ADD_TEST_CASE(tcs, headers_4); - ATF_ADD_TEST_CASE(tcs, headers_5); - ATF_ADD_TEST_CASE(tcs, headers_6); - ATF_ADD_TEST_CASE(tcs, headers_7); - ATF_ADD_TEST_CASE(tcs, headers_8); - ATF_ADD_TEST_CASE(tcs, headers_9); - ATF_ADD_TEST_CASE(tcs, headers_10); - ATF_ADD_TEST_CASE(tcs, headers_11); - ATF_ADD_TEST_CASE(tcs, headers_12); -} diff --git a/tools/pass_helper.cpp b/tools/pass_helper.cpp deleted file mode 100644 index 4fa75b4..0000000 --- a/tools/pass_helper.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include <atf-c++.hpp> - -ATF_TEST_CASE(main); -ATF_TEST_CASE_HEAD(main) -{ - set_md_var("descr", "Helper test case that always passes"); -} -ATF_TEST_CASE_BODY(main) -{ -} - -ATF_INIT_TEST_CASES(tcs) -{ - ATF_ADD_TEST_CASE(tcs, main); -} diff --git a/tools/process.cpp b/tools/process.cpp deleted file mode 100644 index 987a60e..0000000 --- a/tools/process.cpp +++ /dev/null @@ -1,492 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2008 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -extern "C" { -#include <sys/types.h> -#include <sys/wait.h> - -#include <fcntl.h> -#include <signal.h> -} - -#include <cassert> -#include <cstdarg> -#include <cerrno> -#include <cstring> -#include <iostream> - -#include "defs.hpp" -#include "exceptions.hpp" -#include "text.hpp" -#include "process.hpp" - -namespace detail = tools::process::detail; -namespace impl = tools::process; -#define IMPL_NAME "tools::process" - -// ------------------------------------------------------------------------ -// Auxiliary functions. -// ------------------------------------------------------------------------ - -template< class C > -tools::auto_array< const char* > -collection_to_argv(const C& c) -{ - tools::auto_array< const char* > argv(new const char*[c.size() + 1]); - - std::size_t pos = 0; - for (typename C::const_iterator iter = c.begin(); iter != c.end(); - iter++) { - argv[pos] = (*iter).c_str(); - pos++; - } - assert(pos == c.size()); - argv[pos] = NULL; - - return argv; -} - -template< class C > -C -argv_to_collection(const char* const* argv) -{ - C c; - - for (const char* const* iter = argv; *iter != NULL; iter++) - c.push_back(std::string(*iter)); - - return c; -} - -static -void -safe_dup(const int oldfd, const int newfd) -{ - if (oldfd != newfd) { - if (dup2(oldfd, newfd) == -1) { - throw tools::system_error(IMPL_NAME "::safe_dup", - "Could not allocate file descriptor", - errno); - } else { - ::close(oldfd); - } - } -} - -static -int -const_execvp(const char *file, const char *const *argv) -{ -#define UNCONST(a) ((void *)(unsigned long)(const void *)(a)) - return ::execvp(file, (char* const*)(UNCONST(argv))); -#undef UNCONST -} - -void -detail::do_exec(void *v) -{ - struct exec_args *ea = reinterpret_cast<struct exec_args *>(v); - - if (ea->m_prehook != NULL) - ea->m_prehook(); - - const int ret = const_execvp(ea->m_prog.c_str(), ea->m_argv.exec_argv()); - const int errnocopy = errno; - assert(ret == -1); - std::cerr << "exec(" << ea->m_prog.str() << ") failed: " - << std::strerror(errnocopy) << "\n"; - std::exit(EXIT_FAILURE); -} - -// ------------------------------------------------------------------------ -// The "argv_array" type. -// ------------------------------------------------------------------------ - -impl::argv_array::argv_array(void) : - m_exec_argv(collection_to_argv(m_args)) -{ -} - -impl::argv_array::argv_array(const char* arg1, ...) -{ - m_args.push_back(arg1); - - { - va_list ap; - const char* nextarg; - - va_start(ap, arg1); - while ((nextarg = va_arg(ap, const char*)) != NULL) - m_args.push_back(nextarg); - va_end(ap); - } - - ctor_init_exec_argv(); -} - -impl::argv_array::argv_array(const char* const* ca) : - m_args(argv_to_collection< args_vector >(ca)), - m_exec_argv(collection_to_argv(m_args)) -{ -} - -impl::argv_array::argv_array(const argv_array& a) : - m_args(a.m_args), - m_exec_argv(collection_to_argv(m_args)) -{ -} - -void -impl::argv_array::ctor_init_exec_argv(void) -{ - m_exec_argv = collection_to_argv(m_args); -} - -const char* const* -impl::argv_array::exec_argv(void) - const -{ - return m_exec_argv.get(); -} - -impl::argv_array::size_type -impl::argv_array::size(void) - const -{ - return m_args.size(); -} - -const char* -impl::argv_array::operator[](int idx) - const -{ - return m_args[idx].c_str(); -} - -impl::argv_array::const_iterator -impl::argv_array::begin(void) - const -{ - return m_args.begin(); -} - -impl::argv_array::const_iterator -impl::argv_array::end(void) - const -{ - return m_args.end(); -} - -impl::argv_array& -impl::argv_array::operator=(const argv_array& a) -{ - if (this != &a) { - m_args = a.m_args; - m_exec_argv = collection_to_argv(m_args); - } - return *this; -} - -// ------------------------------------------------------------------------ -// The "stream" types. -// ------------------------------------------------------------------------ - -impl::stream_capture::stream_capture(void) -{ - for (int i = 0; i < 2; i++) - m_pipefds[i] = -1; -} - -impl::stream_capture::~stream_capture(void) -{ - for (int i = 0; i < 2; i++) - if (m_pipefds[i] != -1) - ::close(m_pipefds[i]); -} - -void -impl::stream_capture::prepare(void) -{ - if (pipe(m_pipefds) == -1) - throw system_error(IMPL_NAME "::stream_capture::prepare", - "Failed to create pipe", errno); -} - -int -impl::stream_capture::connect_parent(void) -{ - ::close(m_pipefds[1]); m_pipefds[1] = -1; - const int fd = m_pipefds[0]; - m_pipefds[0] = -1; - return fd; -} - -void -impl::stream_capture::connect_child(const int fd) -{ - ::close(m_pipefds[0]); m_pipefds[0] = -1; - if (m_pipefds[1] != fd) { - safe_dup(m_pipefds[1], fd); - } - m_pipefds[1] = -1; -} - -impl::stream_connect::stream_connect(const int src_fd, const int tgt_fd) : - m_src_fd(src_fd), m_tgt_fd(tgt_fd) -{ -} - -void -impl::stream_connect::prepare(void) -{ -} - -int -impl::stream_connect::connect_parent(void) -{ - return -1; -} - -void -impl::stream_connect::connect_child(const int fd ATF_DEFS_ATTRIBUTE_UNUSED) -{ - safe_dup(m_tgt_fd, m_src_fd); -} - -impl::stream_inherit::stream_inherit(void) -{ -} - -void -impl::stream_inherit::prepare(void) -{ -} - -int -impl::stream_inherit::connect_parent(void) -{ - return -1; -} - -void -impl::stream_inherit::connect_child(const int fd ATF_DEFS_ATTRIBUTE_UNUSED) -{ -} - -impl::stream_redirect_fd::stream_redirect_fd(const int fd) : - m_fd(fd) -{ -} - -void -impl::stream_redirect_fd::prepare(void) -{ -} - -int -impl::stream_redirect_fd::connect_parent(void) -{ - return -1; -} - -void -impl::stream_redirect_fd::connect_child(const int fd) -{ - safe_dup(m_fd, fd); -} - -impl::stream_redirect_path::stream_redirect_path(const tools::fs::path& p) : - m_path(p) -{ -} - -void -impl::stream_redirect_path::prepare(void) -{ -} - -int -impl::stream_redirect_path::connect_parent(void) -{ - return -1; -} - -void -impl::stream_redirect_path::connect_child(const int fd) -{ - const int aux = ::open(m_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (aux == -1) - throw system_error(IMPL_NAME "::stream_redirect_path::connect_child", - "Could not create " + m_path.str(), errno); - else - safe_dup(aux, fd); -} - -// ------------------------------------------------------------------------ -// The "status" type. -// ------------------------------------------------------------------------ - -impl::status::status(int s) : - m_status(s) -{ -} - -impl::status::~status(void) -{ -} - -bool -impl::status::exited(void) - const -{ - int mutable_status = m_status; - return WIFEXITED(mutable_status); -} - -int -impl::status::exitstatus(void) - const -{ - assert(exited()); - int mutable_status = m_status; - return WEXITSTATUS(mutable_status); -} - -bool -impl::status::signaled(void) - const -{ - int mutable_status = m_status; - return WIFSIGNALED(mutable_status); -} - -int -impl::status::termsig(void) - const -{ - assert(signaled()); - int mutable_status = m_status; - return WTERMSIG(mutable_status); -} - -bool -impl::status::coredump(void) - const -{ - assert(signaled()); -#if defined(WCOREDUMP) - int mutable_status = m_status; - return WCOREDUMP(mutable_status); -#else - return false; -#endif -} - -// ------------------------------------------------------------------------ -// The "child" type. -// ------------------------------------------------------------------------ - -impl::child::child(const pid_t pid_arg, const int stdout_fd_arg, - const int stderr_fd_arg) : - m_pid(pid_arg), - m_stdout(stdout_fd_arg), - m_stderr(stderr_fd_arg), - m_waited(false) -{ -} - -impl::child::~child(void) -{ - if (!m_waited) { - ::kill(m_pid, SIGTERM); - (void)wait(); - - if (m_stdout != -1) - ::close(m_stdout); - if (m_stderr != -1) - ::close(m_stderr); - } -} - -impl::status -impl::child::wait(void) -{ - int s; - - if (::waitpid(m_pid, &s, 0) == -1) - throw system_error(IMPL_NAME "::child::wait", "Failed waiting for " - "process " + text::to_string(m_pid), errno); - - if (m_stdout != -1) - ::close(m_stdout); m_stdout = -1; - if (m_stderr != -1) - ::close(m_stderr); m_stderr = -1; - - m_waited = true; - return status(s); -} - -pid_t -impl::child::pid(void) - const -{ - return m_pid; -} - -int -impl::child::stdout_fd(void) -{ - return m_stdout; -} - -int -impl::child::stderr_fd(void) -{ - return m_stderr; -} - -// ------------------------------------------------------------------------ -// Free functions. -// ------------------------------------------------------------------------ - -void -detail::flush_streams(void) -{ - // This is a weird hack to ensure that the output of the parent process - // is flushed before executing a child which prevents, for example, the - // output of the atf-run hooks to appear before the output of atf-run - // itself. - // - // TODO: This should only be executed when inheriting the stdout or - // stderr file descriptors. However, the flushing is specific to the - // iostreams, so we cannot do it from the C library where all the process - // logic is performed. Come up with a better design. - std::cout.flush(); - std::cerr.flush(); -} diff --git a/tools/process.hpp b/tools/process.hpp deleted file mode 100644 index 2ebd865..0000000 --- a/tools/process.hpp +++ /dev/null @@ -1,324 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2008 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if !defined(TOOLS_PROCESS_HPP) -#define TOOLS_PROCESS_HPP - -extern "C" { -#include <sys/types.h> - -#include <unistd.h> -} - -#include <cerrno> -#include <cstdlib> -#include <iostream> -#include <string> -#include <vector> - -#include "auto_array.hpp" -#include "exceptions.hpp" -#include "fs.hpp" - -namespace tools { -namespace process { - -class child; -class status; - -// ------------------------------------------------------------------------ -// The "argv_array" type. -// ------------------------------------------------------------------------ - -class argv_array { - typedef std::vector< std::string > args_vector; - args_vector m_args; - - // TODO: This is immutable, so we should be able to use - // std::tr1::shared_array instead when it becomes widely available. - // The reason would be to remove all copy constructors and assignment - // operators from this class. - auto_array< const char* > m_exec_argv; - void ctor_init_exec_argv(void); - -public: - typedef args_vector::const_iterator const_iterator; - typedef args_vector::size_type size_type; - - argv_array(void); - argv_array(const char*, ...); - explicit argv_array(const char* const*); - template< class C > explicit argv_array(const C&); - argv_array(const argv_array&); - - const char* const* exec_argv(void) const; - size_type size(void) const; - const char* operator[](int) const; - - const_iterator begin(void) const; - const_iterator end(void) const; - - argv_array& operator=(const argv_array&); -}; - -template< class C > -argv_array::argv_array(const C& c) -{ - for (typename C::const_iterator iter = c.begin(); iter != c.end(); - iter++) - m_args.push_back(*iter); - ctor_init_exec_argv(); -} - -// ------------------------------------------------------------------------ -// The "stream" types. -// ------------------------------------------------------------------------ - -class stream_capture { - int m_pipefds[2]; - - // Allow access to the getters. - template< class OutStream, class ErrStream > friend - child fork(void (*)(void*), OutStream, ErrStream, void*); - template< class OutStream, class ErrStream > friend - status exec(const tools::fs::path&, const argv_array&, - const OutStream&, const ErrStream&, void (*)(void)); - - void prepare(void); - int connect_parent(void); - void connect_child(const int); - -public: - stream_capture(void); - ~stream_capture(void); -}; - -class stream_connect { - int m_src_fd; - int m_tgt_fd; - - // Allow access to the getters. - template< class OutStream, class ErrStream > friend - child fork(void (*)(void*), OutStream, ErrStream, void*); - template< class OutStream, class ErrStream > friend - status exec(const tools::fs::path&, const argv_array&, - const OutStream&, const ErrStream&, void (*)(void)); - - void prepare(void); - int connect_parent(void); - void connect_child(const int); - -public: - stream_connect(const int, const int); -}; - -class stream_inherit { - // Allow access to the getters. - template< class OutStream, class ErrStream > friend - child fork(void (*)(void*), OutStream, ErrStream, void*); - template< class OutStream, class ErrStream > friend - status exec(const tools::fs::path&, const argv_array&, - const OutStream&, const ErrStream&, void (*)(void)); - - void prepare(void); - int connect_parent(void); - void connect_child(const int); - -public: - stream_inherit(void); -}; - -class stream_redirect_fd { - int m_fd; - - // Allow access to the getters. - template< class OutStream, class ErrStream > friend - child fork(void (*)(void*), OutStream, ErrStream, void*); - template< class OutStream, class ErrStream > friend - status exec(const tools::fs::path&, const argv_array&, - const OutStream&, const ErrStream&, void (*)(void)); - - void prepare(void); - int connect_parent(void); - void connect_child(const int); - -public: - stream_redirect_fd(const int); -}; - -class stream_redirect_path { - const tools::fs::path m_path; - - // Allow access to the getters. - template< class OutStream, class ErrStream > friend - child fork(void (*)(void*), OutStream, ErrStream, void*); - template< class OutStream, class ErrStream > friend - status exec(const tools::fs::path&, const argv_array&, - const OutStream&, const ErrStream&, void (*)(void)); - - void prepare(void); - int connect_parent(void); - void connect_child(const int); - -public: - stream_redirect_path(const tools::fs::path&); -}; - -// ------------------------------------------------------------------------ -// The "status" type. -// ------------------------------------------------------------------------ - -class status { - int m_status; - - friend class child; - template< class OutStream, class ErrStream > friend - status exec(const tools::fs::path&, const argv_array&, - const OutStream&, const ErrStream&, void (*)(void)); - - status(int); - -public: - ~status(void); - - bool exited(void) const; - int exitstatus(void) const; - - bool signaled(void) const; - int termsig(void) const; - bool coredump(void) const; -}; - -// ------------------------------------------------------------------------ -// The "child" type. -// ------------------------------------------------------------------------ - -class child { - pid_t m_pid; - - int m_stdout; - int m_stderr; - - bool m_waited; - - template< class OutStream, class ErrStream > friend - child fork(void (*)(void*), OutStream, ErrStream, void*); - - child(const pid_t, const int, const int); - -public: - ~child(void); - - status wait(void); - - pid_t pid(void) const; - int stdout_fd(void); - int stderr_fd(void); -}; - -// ------------------------------------------------------------------------ -// Free functions. -// ------------------------------------------------------------------------ - -namespace detail { -void flush_streams(void); - -struct exec_args { - const tools::fs::path m_prog; - const argv_array& m_argv; - void (*m_prehook)(void); -}; - -void do_exec(void *); -} // namespace detail - -// TODO: The void* cookie can probably be templatized, thus also allowing -// const data structures. -template< class OutStream, class ErrStream > -child -fork(void (*start)(void*), OutStream outsb, ErrStream errsb, void* v) -{ - detail::flush_streams(); - - outsb.prepare(); - errsb.prepare(); - - pid_t pid = ::fork(); - if (pid == -1) { - throw system_error("tools::process::child::fork", - "Failed to fork", errno); - } else if (pid == 0) { - try { - outsb.connect_child(STDOUT_FILENO); - errsb.connect_child(STDERR_FILENO); - start(v); - std::abort(); - } catch (...) { - std::cerr << "Unhandled error while running subprocess\n"; - std::exit(EXIT_FAILURE); - } - } else { - const int stdout_fd = outsb.connect_parent(); - const int stderr_fd = errsb.connect_parent(); - return child(pid, stdout_fd, stderr_fd); - } -} - -template< class OutStream, class ErrStream > -status -exec(const tools::fs::path& prog, const argv_array& argv, - const OutStream& outsb, const ErrStream& errsb, - void (*prehook)(void)) -{ - struct detail::exec_args ea = { prog, argv, prehook }; - child c = fork(detail::do_exec, outsb, errsb, &ea); - -again: - try { - return c.wait(); - } catch (const system_error& e) { - if (e.code() == EINTR) - goto again; - else - throw e; - } -} - -template< class OutStream, class ErrStream > -status -exec(const tools::fs::path& prog, const argv_array& argv, - const OutStream& outsb, const ErrStream& errsb) -{ - return exec(prog, argv, outsb, errsb, NULL); -} - -} // namespace process -} // namespace tools - -#endif // !defined(TOOLS_PROCESS_HPP) diff --git a/tools/process_helpers.c b/tools/process_helpers.c deleted file mode 100644 index 61f1b67..0000000 --- a/tools/process_helpers.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Automated Testing Framework (atf) - * - * Copyright (c) 2008 The NetBSD Foundation, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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 <sys/types.h> - -#include <assert.h> /* NO_CHECK_STYLE */ -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -static -int -h_echo(const char *msg) -{ - printf("%s\n", msg); - return EXIT_SUCCESS; -} - -static -int -h_exit_failure(void) -{ - return EXIT_FAILURE; -} - -static -int -h_exit_signal(void) -{ - kill(getpid(), SIGKILL); - assert(0); /* NO_CHECK_STYLE */ - return EXIT_FAILURE; -} - -static -int -h_exit_success(void) -{ - return EXIT_SUCCESS; -} - -static -int -h_stdout_stderr(const char *id) -{ - fprintf(stdout, "Line 1 to stdout for %s\n", id); - fprintf(stdout, "Line 2 to stdout for %s\n", id); - fprintf(stderr, "Line 1 to stderr for %s\n", id); - fprintf(stderr, "Line 2 to stderr for %s\n", id); - - return EXIT_SUCCESS; -} - -static -void -check_args(const int argc, const char *const argv[], const int required) -{ - if (argc < required) { - fprintf(stderr, "Usage: %s helper-name [args]\n", argv[0]); - exit(EXIT_FAILURE); - } -} - -int -main(int argc, const char *const argv[]) -{ - int exitcode; - - check_args(argc, argv, 2); - - if (strcmp(argv[1], "echo") == 0) { - check_args(argc, argv, 3); - exitcode = h_echo(argv[2]); - } else if (strcmp(argv[1], "exit-failure") == 0) - exitcode = h_exit_failure(); - else if (strcmp(argv[1], "exit-signal") == 0) - exitcode = h_exit_signal(); - else if (strcmp(argv[1], "exit-success") == 0) - exitcode = h_exit_success(); - else if (strcmp(argv[1], "stdout-stderr") == 0) { - check_args(argc, argv, 3); - exitcode = h_stdout_stderr(argv[2]); - } else { - fprintf(stderr, "%s: Unknown helper %s\n", argv[0], argv[1]); - exitcode = EXIT_FAILURE; - } - - return exitcode; -} diff --git a/tools/process_test.cpp b/tools/process_test.cpp deleted file mode 100644 index 70da919d..0000000 --- a/tools/process_test.cpp +++ /dev/null @@ -1,360 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2008 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 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 <cstdlib> -#include <cstring> - -#include <atf-c++.hpp> - -#include "process.hpp" -#include "test_helpers.hpp" - -// TODO: Testing the fork function is a huge task and I'm afraid of -// copy/pasting tons of stuff from the C version. I'd rather not do that -// until some code can be shared, which cannot happen until the C++ binding -// is cleaned by a fair amount. Instead... just rely (at the moment) on -// the system tests for the tools using this module. - -// ------------------------------------------------------------------------ -// Auxiliary functions. -// ------------------------------------------------------------------------ - -static -std::size_t -array_size(const char* const* array) -{ - std::size_t size = 0; - - for (const char* const* ptr = array; *ptr != NULL; ptr++) - size++; - - return size; -} - -static -tools::process::status -exec_process_helpers(const atf::tests::tc& tc, const char* helper_name) -{ - using tools::process::exec; - - const tools::fs::path helpers = tools::fs::path(tc.get_config_var("srcdir")) / - "process_helpers"; - - std::vector< std::string > argv; - argv.push_back(helpers.leaf_name()); - argv.push_back(helper_name); - - return exec(helpers, - tools::process::argv_array(argv), - tools::process::stream_inherit(), - tools::process::stream_inherit()); -} - -// ------------------------------------------------------------------------ -// Tests for the "argv_array" type. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(argv_array_init_carray); -ATF_TEST_CASE_HEAD(argv_array_init_carray) -{ - set_md_var("descr", "Tests that argv_array is correctly constructed " - "from a C-style array of strings"); -} -ATF_TEST_CASE_BODY(argv_array_init_carray) -{ - { - const char* const carray[] = { NULL }; - tools::process::argv_array argv(carray); - - ATF_REQUIRE_EQ(argv.size(), 0); - } - - { - const char* const carray[] = { "arg0", NULL }; - tools::process::argv_array argv(carray); - - ATF_REQUIRE_EQ(argv.size(), 1); - ATF_REQUIRE(std::strcmp(argv[0], carray[0]) == 0); - } - - { - const char* const carray[] = { "arg0", "arg1", "arg2", NULL }; - tools::process::argv_array argv(carray); - - ATF_REQUIRE_EQ(argv.size(), 3); - ATF_REQUIRE(std::strcmp(argv[0], carray[0]) == 0); - ATF_REQUIRE(std::strcmp(argv[1], carray[1]) == 0); - ATF_REQUIRE(std::strcmp(argv[2], carray[2]) == 0); - } -} - -ATF_TEST_CASE(argv_array_init_col); -ATF_TEST_CASE_HEAD(argv_array_init_col) -{ - set_md_var("descr", "Tests that argv_array is correctly constructed " - "from a string collection"); -} -ATF_TEST_CASE_BODY(argv_array_init_col) -{ - { - std::vector< std::string > col; - tools::process::argv_array argv(col); - - ATF_REQUIRE_EQ(argv.size(), 0); - } - - { - std::vector< std::string > col; - col.push_back("arg0"); - tools::process::argv_array argv(col); - - ATF_REQUIRE_EQ(argv.size(), 1); - ATF_REQUIRE_EQ(argv[0], col[0]); - } - - { - std::vector< std::string > col; - col.push_back("arg0"); - col.push_back("arg1"); - col.push_back("arg2"); - tools::process::argv_array argv(col); - - ATF_REQUIRE_EQ(argv.size(), 3); - ATF_REQUIRE_EQ(argv[0], col[0]); - ATF_REQUIRE_EQ(argv[1], col[1]); - ATF_REQUIRE_EQ(argv[2], col[2]); - } -} - -ATF_TEST_CASE(argv_array_init_empty); -ATF_TEST_CASE_HEAD(argv_array_init_empty) -{ - set_md_var("descr", "Tests that argv_array is correctly constructed " - "by the default constructor"); -} -ATF_TEST_CASE_BODY(argv_array_init_empty) -{ - tools::process::argv_array argv; - - ATF_REQUIRE_EQ(argv.size(), 0); -} - -ATF_TEST_CASE(argv_array_init_varargs); -ATF_TEST_CASE_HEAD(argv_array_init_varargs) -{ - set_md_var("descr", "Tests that argv_array is correctly constructed " - "from a variable list of arguments"); -} -ATF_TEST_CASE_BODY(argv_array_init_varargs) -{ - { - tools::process::argv_array argv("arg0", NULL); - - ATF_REQUIRE_EQ(argv.size(), 1); - ATF_REQUIRE_EQ(argv[0], std::string("arg0")); - } - - { - tools::process::argv_array argv("arg0", "arg1", "arg2", NULL); - - ATF_REQUIRE_EQ(argv.size(), 3); - ATF_REQUIRE_EQ(argv[0], std::string("arg0")); - ATF_REQUIRE_EQ(argv[1], std::string("arg1")); - ATF_REQUIRE_EQ(argv[2], std::string("arg2")); - } -} - -ATF_TEST_CASE(argv_array_assign); -ATF_TEST_CASE_HEAD(argv_array_assign) -{ - set_md_var("descr", "Tests that assigning an argv_array works"); -} -ATF_TEST_CASE_BODY(argv_array_assign) -{ - using tools::process::argv_array; - - const char* const carray1[] = { "arg1", NULL }; - const char* const carray2[] = { "arg1", "arg2", NULL }; - - std::auto_ptr< argv_array > argv1(new argv_array(carray1)); - std::auto_ptr< argv_array > argv2(new argv_array(carray2)); - - *argv2 = *argv1; - ATF_REQUIRE_EQ(argv2->size(), argv1->size()); - ATF_REQUIRE(std::strcmp((*argv2)[0], (*argv1)[0]) == 0); - - ATF_REQUIRE(argv2->exec_argv() != argv1->exec_argv()); - argv1.release(); - { - const char* const* eargv2 = argv2->exec_argv(); - ATF_REQUIRE(std::strcmp(eargv2[0], carray1[0]) == 0); - ATF_REQUIRE_EQ(eargv2[1], static_cast< const char* >(NULL)); - } - - argv2.release(); -} - -ATF_TEST_CASE(argv_array_copy); -ATF_TEST_CASE_HEAD(argv_array_copy) -{ - set_md_var("descr", "Tests that copying an argv_array constructed from " - "a C-style array of strings works"); -} -ATF_TEST_CASE_BODY(argv_array_copy) -{ - using tools::process::argv_array; - - const char* const carray[] = { "arg0", NULL }; - - std::auto_ptr< argv_array > argv1(new argv_array(carray)); - std::auto_ptr< argv_array > argv2(new argv_array(*argv1)); - - ATF_REQUIRE_EQ(argv2->size(), argv1->size()); - ATF_REQUIRE(std::strcmp((*argv2)[0], (*argv1)[0]) == 0); - - ATF_REQUIRE(argv2->exec_argv() != argv1->exec_argv()); - argv1.release(); - { - const char* const* eargv2 = argv2->exec_argv(); - ATF_REQUIRE(std::strcmp(eargv2[0], carray[0]) == 0); - ATF_REQUIRE_EQ(eargv2[1], static_cast< const char* >(NULL)); - } - - argv2.release(); -} - -ATF_TEST_CASE(argv_array_exec_argv); -ATF_TEST_CASE_HEAD(argv_array_exec_argv) -{ - set_md_var("descr", "Tests that the exec argv provided by an argv_array " - "is correct"); -} -ATF_TEST_CASE_BODY(argv_array_exec_argv) -{ - using tools::process::argv_array; - - { - argv_array argv; - const char* const* eargv = argv.exec_argv(); - ATF_REQUIRE_EQ(array_size(eargv), 0); - ATF_REQUIRE_EQ(eargv[0], static_cast< const char* >(NULL)); - } - - { - const char* const carray[] = { "arg0", NULL }; - argv_array argv(carray); - const char* const* eargv = argv.exec_argv(); - ATF_REQUIRE_EQ(array_size(eargv), 1); - ATF_REQUIRE(std::strcmp(eargv[0], "arg0") == 0); - ATF_REQUIRE_EQ(eargv[1], static_cast< const char* >(NULL)); - } - - { - std::vector< std::string > col; - col.push_back("arg0"); - argv_array argv(col); - const char* const* eargv = argv.exec_argv(); - ATF_REQUIRE_EQ(array_size(eargv), 1); - ATF_REQUIRE(std::strcmp(eargv[0], "arg0") == 0); - ATF_REQUIRE_EQ(eargv[1], static_cast< const char* >(NULL)); - } -} - -ATF_TEST_CASE(argv_array_iter); -ATF_TEST_CASE_HEAD(argv_array_iter) -{ - set_md_var("descr", "Tests that an argv_array can be iterated"); -} -ATF_TEST_CASE_BODY(argv_array_iter) -{ - using tools::process::argv_array; - - std::vector< std::string > vector; - vector.push_back("arg0"); - vector.push_back("arg1"); - vector.push_back("arg2"); - - argv_array argv(vector); - ATF_REQUIRE_EQ(argv.size(), 3); - std::vector< std::string >::size_type pos = 0; - for (argv_array::const_iterator iter = argv.begin(); iter != argv.end(); - iter++) { - ATF_REQUIRE_EQ(*iter, vector[pos]); - pos++; - } -} - -// ------------------------------------------------------------------------ -// Tests cases for the free functions. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(exec_failure); -ATF_TEST_CASE_HEAD(exec_failure) -{ - set_md_var("descr", "Tests execing a command that reports failure"); -} -ATF_TEST_CASE_BODY(exec_failure) -{ - const tools::process::status s = exec_process_helpers(*this, "exit-failure"); - ATF_REQUIRE(s.exited()); - ATF_REQUIRE_EQ(s.exitstatus(), EXIT_FAILURE); -} - -ATF_TEST_CASE(exec_success); -ATF_TEST_CASE_HEAD(exec_success) -{ - set_md_var("descr", "Tests execing a command that reports success"); -} -ATF_TEST_CASE_BODY(exec_success) -{ - const tools::process::status s = exec_process_helpers(*this, "exit-success"); - ATF_REQUIRE(s.exited()); - ATF_REQUIRE_EQ(s.exitstatus(), EXIT_SUCCESS); -} - -// ------------------------------------------------------------------------ -// Main. -// ------------------------------------------------------------------------ - -ATF_INIT_TEST_CASES(tcs) -{ - // Add the test cases for the "argv_array" type. - ATF_ADD_TEST_CASE(tcs, argv_array_assign); - ATF_ADD_TEST_CASE(tcs, argv_array_copy); - ATF_ADD_TEST_CASE(tcs, argv_array_exec_argv); - ATF_ADD_TEST_CASE(tcs, argv_array_init_carray); - ATF_ADD_TEST_CASE(tcs, argv_array_init_col); - ATF_ADD_TEST_CASE(tcs, argv_array_init_empty); - ATF_ADD_TEST_CASE(tcs, argv_array_init_varargs); - ATF_ADD_TEST_CASE(tcs, argv_array_iter); - - // Add the test cases for the free functions. - ATF_ADD_TEST_CASE(tcs, exec_failure); - ATF_ADD_TEST_CASE(tcs, exec_success); -} diff --git a/tools/reader.cpp b/tools/reader.cpp deleted file mode 100644 index 67fce66..0000000 --- a/tools/reader.cpp +++ /dev/null @@ -1,440 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -extern "C" { -#include <sys/time.h> -} - -#include <cassert> -#include <cstdlib> -#include <map> -#include <sstream> -#include <utility> - -#include "defs.hpp" -#include "parser.hpp" -#include "reader.hpp" -#include "text.hpp" - -namespace impl = tools::atf_report; -#define IMPL_NAME "tools::atf_report" - -// ------------------------------------------------------------------------ -// Auxiliary functions. -// ------------------------------------------------------------------------ - -template< typename Type > -Type -string_to_int(const std::string& str) -{ - std::istringstream ss(str); - Type s; - ss >> s; - - return s; -} - -// ------------------------------------------------------------------------ -// The "atf_tps" auxiliary parser. -// ------------------------------------------------------------------------ - -namespace atf_tps { - -static const tools::parser::token_type eof_type = 0; -static const tools::parser::token_type nl_type = 1; -static const tools::parser::token_type text_type = 2; -static const tools::parser::token_type colon_type = 3; -static const tools::parser::token_type comma_type = 4; -static const tools::parser::token_type tps_count_type = 5; -static const tools::parser::token_type tp_start_type = 6; -static const tools::parser::token_type tp_end_type = 7; -static const tools::parser::token_type tc_start_type = 8; -static const tools::parser::token_type tc_so_type = 9; -static const tools::parser::token_type tc_se_type = 10; -static const tools::parser::token_type tc_end_type = 11; -static const tools::parser::token_type passed_type = 12; -static const tools::parser::token_type failed_type = 13; -static const tools::parser::token_type skipped_type = 14; -static const tools::parser::token_type info_type = 16; -static const tools::parser::token_type expected_death_type = 17; -static const tools::parser::token_type expected_exit_type = 18; -static const tools::parser::token_type expected_failure_type = 19; -static const tools::parser::token_type expected_signal_type = 20; -static const tools::parser::token_type expected_timeout_type = 21; - -class tokenizer : public tools::parser::tokenizer< std::istream > { -public: - tokenizer(std::istream& is, size_t curline) : - tools::parser::tokenizer< std::istream > - (is, true, eof_type, nl_type, text_type, curline) - { - add_delim(':', colon_type); - add_delim(',', comma_type); - add_keyword("tps-count", tps_count_type); - add_keyword("tp-start", tp_start_type); - add_keyword("tp-end", tp_end_type); - add_keyword("tc-start", tc_start_type); - add_keyword("tc-so", tc_so_type); - add_keyword("tc-se", tc_se_type); - add_keyword("tc-end", tc_end_type); - add_keyword("passed", passed_type); - add_keyword("failed", failed_type); - add_keyword("skipped", skipped_type); - add_keyword("info", info_type); - add_keyword("expected_death", expected_death_type); - add_keyword("expected_exit", expected_exit_type); - add_keyword("expected_failure", expected_failure_type); - add_keyword("expected_signal", expected_signal_type); - add_keyword("expected_timeout", expected_timeout_type); - } -}; - -} // namespace atf_tps - -struct timeval -read_timeval(tools::parser::parser< atf_tps::tokenizer >& parser) -{ - using namespace atf_tps; - - tools::parser::token t = parser.expect(text_type, "timestamp"); - const std::string::size_type divider = t.text().find('.'); - if (divider == std::string::npos || divider == 0 || - divider == t.text().length() - 1) - throw tools::parser::parse_error(t.lineno(), - "Malformed timestamp value " + t.text()); - - struct timeval tv; - tv.tv_sec = string_to_int< long >(t.text().substr(0, divider)); - tv.tv_usec = string_to_int< long >(t.text().substr(divider + 1)); - return tv; -} - -// ------------------------------------------------------------------------ -// The "atf_tps_reader" class. -// ------------------------------------------------------------------------ - -impl::atf_tps_reader::atf_tps_reader(std::istream& is) : - m_is(is) -{ -} - -impl::atf_tps_reader::~atf_tps_reader(void) -{ -} - -void -impl::atf_tps_reader::got_info( - const std::string& what ATF_DEFS_ATTRIBUTE_UNUSED, - const std::string& val ATF_DEFS_ATTRIBUTE_UNUSED) -{ -} - -void -impl::atf_tps_reader::got_ntps(size_t ntps ATF_DEFS_ATTRIBUTE_UNUSED) -{ -} - -void -impl::atf_tps_reader::got_tp_start( - const std::string& tp ATF_DEFS_ATTRIBUTE_UNUSED, - size_t ntcs ATF_DEFS_ATTRIBUTE_UNUSED) -{ -} - -void -impl::atf_tps_reader::got_tp_end( - struct timeval* tv ATF_DEFS_ATTRIBUTE_UNUSED, - const std::string& reason ATF_DEFS_ATTRIBUTE_UNUSED) -{ -} - -void -impl::atf_tps_reader::got_tc_start( - const std::string& tcname ATF_DEFS_ATTRIBUTE_UNUSED) -{ -} - -void -impl::atf_tps_reader::got_tc_stdout_line( - const std::string& line ATF_DEFS_ATTRIBUTE_UNUSED) -{ -} - -void -impl::atf_tps_reader::got_tc_stderr_line( - const std::string& line ATF_DEFS_ATTRIBUTE_UNUSED) -{ -} - -void -impl::atf_tps_reader::got_tc_end( - const std::string& state ATF_DEFS_ATTRIBUTE_UNUSED, - struct timeval* tv ATF_DEFS_ATTRIBUTE_UNUSED, - const std::string& reason ATF_DEFS_ATTRIBUTE_UNUSED) -{ -} - -void -impl::atf_tps_reader::got_eof(void) -{ -} - -void -impl::atf_tps_reader::read_info(void* pptr) -{ - using tools::parser::parse_error; - using namespace atf_tps; - - tools::parser::parser< tokenizer >& p = - *reinterpret_cast< tools::parser::parser< tokenizer >* > - (pptr); - - (void)p.expect(colon_type, "`:'"); - - tools::parser::token t = p.expect(text_type, "info property name"); - (void)p.expect(comma_type, "`,'"); - got_info(t.text(), tools::text::trim(p.rest_of_line())); - - (void)p.expect(nl_type, "new line"); -} - -void -impl::atf_tps_reader::read_tp(void* pptr) -{ - using tools::parser::parse_error; - using namespace atf_tps; - - tools::parser::parser< tokenizer >& p = - *reinterpret_cast< tools::parser::parser< tokenizer >* > - (pptr); - - tools::parser::token t = p.expect(tp_start_type, - "start of test program"); - - t = p.expect(colon_type, "`:'"); - - struct timeval s1 = read_timeval(p); - - t = p.expect(comma_type, "`,'"); - - t = p.expect(text_type, "test program name"); - std::string tpname = t.text(); - - t = p.expect(comma_type, "`,'"); - - t = p.expect(text_type, "number of test programs"); - size_t ntcs = string_to_int< std::size_t >(t.text()); - - t = p.expect(nl_type, "new line"); - - ATF_PARSER_CALLBACK(p, got_tp_start(tpname, ntcs)); - - size_t i = 0; - while (p.good() && i < ntcs) { - try { - read_tc(&p); - i++; - } catch (const parse_error& pe) { - p.add_error(pe); - p.reset(nl_type); - } - } - t = p.expect(tp_end_type, "end of test program"); - - t = p.expect(colon_type, "`:'"); - - struct timeval s2 = read_timeval(p); - - struct timeval s3; - timersub(&s2, &s1, &s3); - - t = p.expect(comma_type, "`,'"); - - t = p.expect(text_type, "test program name"); - if (t.text() != tpname) - throw parse_error(t.lineno(), "Test program name used in " - "terminator does not match " - "opening"); - - t = p.expect(nl_type, comma_type, - "new line or comma_type"); - std::string reason; - if (t.type() == comma_type) { - reason = tools::text::trim(p.rest_of_line()); - if (reason.empty()) - throw parse_error(t.lineno(), - "Empty reason for failed test program"); - t = p.next(); - } - - ATF_PARSER_CALLBACK(p, got_tp_end(&s3, reason)); -} - -void -impl::atf_tps_reader::read_tc(void* pptr) -{ - using tools::parser::parse_error; - using namespace atf_tps; - - tools::parser::parser< tokenizer >& p = - *reinterpret_cast< tools::parser::parser< tokenizer >* > - (pptr); - - tools::parser::token t = p.expect(tc_start_type, "start of test case"); - - t = p.expect(colon_type, "`:'"); - - struct timeval s1 = read_timeval(p); - - t = p.expect(comma_type, "`,'"); - - t = p.expect(text_type, "test case name"); - std::string tcname = t.text(); - - ATF_PARSER_CALLBACK(p, got_tc_start(tcname)); - - t = p.expect(nl_type, "new line"); - - t = p.expect(tc_end_type, tc_so_type, tc_se_type, - "end of test case or test case's stdout/stderr line"); - while (t.type() != tc_end_type && - (t.type() == tc_so_type || t.type() == tc_se_type)) { - tools::parser::token t2 = t; - - t = p.expect(colon_type, "`:'"); - - std::string line = p.rest_of_line(); - - if (t2.type() == tc_so_type) { - ATF_PARSER_CALLBACK(p, got_tc_stdout_line(line)); - } else { - assert(t2.type() == tc_se_type); - ATF_PARSER_CALLBACK(p, got_tc_stderr_line(line)); - } - - t = p.expect(nl_type, "new line"); - - t = p.expect(tc_end_type, tc_so_type, tc_se_type, - "end of test case or test case's stdout/stderr line"); - } - - t = p.expect(colon_type, "`:'"); - - struct timeval s2 = read_timeval(p); - - struct timeval s3; - timersub(&s2, &s1, &s3); - - t = p.expect(comma_type, "`,'"); - - t = p.expect(text_type, "test case name"); - if (t.text() != tcname) - throw parse_error(t.lineno(), - "Test case name used in terminator does not " - "match opening"); - - t = p.expect(comma_type, "`,'"); - - t = p.expect(expected_death_type, expected_exit_type, expected_failure_type, - expected_signal_type, expected_timeout_type, passed_type, failed_type, - skipped_type, "expected_{death,exit,failure,signal,timeout}, failed, " - "passed or skipped"); - if (t.type() == passed_type) { - ATF_PARSER_CALLBACK(p, got_tc_end("passed", &s3, "")); - } else { - std::string state; - if (t.type() == expected_death_type) state = "expected_death"; - else if (t.type() == expected_exit_type) state = "expected_exit"; - else if (t.type() == expected_failure_type) state = "expected_failure"; - else if (t.type() == expected_signal_type) state = "expected_signal"; - else if (t.type() == expected_timeout_type) state = "expected_timeout"; - else if (t.type() == failed_type) state = "failed"; - else if (t.type() == skipped_type) state = "skipped"; - else std::abort(); - - t = p.expect(comma_type, "`,'"); - std::string reason = tools::text::trim(p.rest_of_line()); - if (reason.empty()) - throw parse_error(t.lineno(), "Empty reason for " + state + - " test case result"); - ATF_PARSER_CALLBACK(p, got_tc_end(state, &s3, reason)); - } - - t = p.expect(nl_type, "new line"); -} - -void -impl::atf_tps_reader::read(void) -{ - using tools::parser::parse_error; - using namespace atf_tps; - - std::pair< size_t, tools::parser::headers_map > hml = - tools::parser::read_headers(m_is, 1); - tools::parser::validate_content_type(hml.second, - "application/X-atf-tps", 3); - - tokenizer tkz(m_is, hml.first); - tools::parser::parser< tokenizer > p(tkz); - - try { - tools::parser::token t; - - while ((t = p.expect(tps_count_type, info_type, "tps-count or info " - "field")).type() == info_type) - read_info(&p); - - t = p.expect(colon_type, "`:'"); - - t = p.expect(text_type, "number of test programs"); - size_t ntps = string_to_int< std::size_t >(t.text()); - ATF_PARSER_CALLBACK(p, got_ntps(ntps)); - - t = p.expect(nl_type, "new line"); - - size_t i = 0; - while (p.good() && i < ntps) { - try { - read_tp(&p); - i++; - } catch (const parse_error& pe) { - p.add_error(pe); - p.reset(nl_type); - } - } - - while ((t = p.expect(eof_type, info_type, "end of stream or info " - "field")).type() == info_type) - read_info(&p); - ATF_PARSER_CALLBACK(p, got_eof()); - } catch (const parse_error& pe) { - p.add_error(pe); - p.reset(nl_type); - } -} diff --git a/tools/reader.hpp b/tools/reader.hpp deleted file mode 100644 index 34d5d25..0000000 --- a/tools/reader.hpp +++ /dev/null @@ -1,89 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if !defined(TOOLS_FORMATS_HPP) -#define TOOLS_FORMATS_HPP - -extern "C" { -#include <sys/time.h> -} - -#include <istream> -#include <string> - -namespace tools { -namespace atf_report { - -struct test_case_result { - enum state_enum { - PASSED, - FAILED, - SKIPPED, - }; - const state_enum state; - const std::string& reason; - - test_case_result(const state_enum p_state, const std::string& p_reason) : - state(p_state), - reason(p_reason) - { - } -}; - -class atf_tps_reader { - std::istream& m_is; - - void read_info(void*); - void read_tp(void*); - void read_tc(void*); - -protected: - virtual void got_info(const std::string&, const std::string&); - virtual void got_ntps(size_t); - virtual void got_tp_start(const std::string&, size_t); - virtual void got_tp_end(struct timeval*, const std::string&); - - virtual void got_tc_start(const std::string&); - virtual void got_tc_stdout_line(const std::string&); - virtual void got_tc_stderr_line(const std::string&); - virtual void got_tc_end(const std::string&, struct timeval*, - const std::string&); - virtual void got_eof(void); - -public: - atf_tps_reader(std::istream&); - virtual ~atf_tps_reader(void); - - void read(void); -}; - -} // namespace atf_report -} // namespace tools - -#endif // !defined(TOOLS_FORMATS_HPP) diff --git a/tools/reader_test.cpp b/tools/reader_test.cpp deleted file mode 100644 index 3e53e06..0000000 --- a/tools/reader_test.cpp +++ /dev/null @@ -1,987 +0,0 @@ -// -// 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 <iostream> -#include <sstream> -#include <string> -#include <utility> -#include <vector> - -#include <atf-c++.hpp> - -#include "parser.hpp" -#include "reader.hpp" -#include "test_helpers.hpp" -#include "text.hpp" - -namespace impl = tools::atf_report; - -class tps_reader : protected impl::atf_tps_reader { - void - got_info(const std::string& what, const std::string& val) - { - m_calls.push_back("got_info(" + what + ", " + val + ")"); - } - - void - got_ntps(size_t ntps) - { - m_calls.push_back("got_ntps(" + tools::text::to_string(ntps) + ")"); - } - - void - got_tp_start(const std::string& tpname, size_t ntcs) - { - m_calls.push_back("got_tp_start(" + tpname + ", " + - tools::text::to_string(ntcs) + ")"); - } - - void - got_tp_end(struct timeval* tv ATF_DEFS_ATTRIBUTE_UNUSED, - const std::string& reason) - { - m_calls.push_back("got_tp_end(" + reason + ")"); - } - - void - got_tc_start(const std::string& tcname) - { - m_calls.push_back("got_tc_start(" + tcname + ")"); - } - - void - got_tc_end(const std::string& state, - struct timeval* tv ATF_DEFS_ATTRIBUTE_UNUSED, - const std::string& reason) - { - const std::string r = state + (reason.empty() ? "" : ", " + reason); - m_calls.push_back("got_tc_end(" + r + ")"); - } - - void - got_tc_stdout_line(const std::string& line) - { - m_calls.push_back("got_tc_stdout_line(" + line + ")"); - } - - void - got_tc_stderr_line(const std::string& line) - { - m_calls.push_back("got_tc_stderr_line(" + line + ")"); - } - - void - got_eof(void) - { - m_calls.push_back("got_eof()"); - } - -public: - tps_reader(std::istream& is) : - impl::atf_tps_reader(is) - { - } - - void - read(void) - { - atf_tps_reader::read(); - } - - std::vector< std::string > m_calls; -}; - -ATF_TEST_CASE_WITHOUT_HEAD(tps_1); -ATF_TEST_CASE_BODY(tps_1) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "tps-count: 0\n" - ; - - const char* exp_calls[] = { - "got_ntps(0)", - "got_eof()", - NULL - }; - - const char* exp_errors[] = { - NULL - }; - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(tps_2); -ATF_TEST_CASE_BODY(tps_2) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "tps-count: 2\n" - "tp-start: 123.456, first-prog, 0\n" - "tp-end: 123.567, first-prog\n" - "tp-start: 123.678, second-prog, 0\n" - "tp-end: 123.789, second-prog, This program failed\n" - ; - - const char* exp_calls[] = { - "got_ntps(2)", - "got_tp_start(first-prog, 0)", - "got_tp_end()", - "got_tp_start(second-prog, 0)", - "got_tp_end(This program failed)", - "got_eof()", - NULL - }; - - const char* exp_errors[] = { - NULL - }; - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(tps_3); -ATF_TEST_CASE_BODY(tps_3) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "tps-count: 2\n" - "tp-start: 123.123, first-prog, 3\n" - "tc-start: 123.234, first-test\n" - "tc-end: 123.345, first-test, passed\n" - "tc-start: 123.456, second-test\n" - "tc-end: 123.567, second-test, skipped, Testing skipped reason\n" - "tc-start: 123.678, third.test\n" - "tc-end: 123.789, third.test, failed, Testing failed reason\n" - "tp-end: 123.890, first-prog\n" - "tp-start: 124.901, second-prog, 3\n" - "tc-start: 124.1012, first-test\n" - "tc-so:first stdout line for 1st test\n" - "tc-se:first stderr line for 1st test\n" - "tc-so:second stdout line for 1st test\n" - "tc-se:second stderr line for 1st test\n" - "tc-end: 124.1123, first-test, passed\n" - "tc-start: 124.1234, second-test\n" - "tc-so:first stdout line for 2nd test\n" - "tc-se:first stderr line for 2nd test\n" - "tc-so:second stdout line for 2nd test\n" - "tc-se:second stderr line for 2nd test\n" - "tc-end: 124.1345, second-test, skipped, Testing skipped reason\n" - "tc-start: 124.1456, third.test\n" - "tc-so:first stdout line for 3rd test\n" - "tc-se:first stderr line for 3rd test\n" - "tc-so:second stdout line for 3rd test\n" - "tc-se:second stderr line for 3rd test\n" - "tc-end: 124.1567, third.test, failed, Testing failed reason\n" - "tp-end: 124.1678, second-prog, This program failed\n" - ; - - const char* exp_calls[] = { - "got_ntps(2)", - "got_tp_start(first-prog, 3)", - "got_tc_start(first-test)", - "got_tc_end(passed)", - "got_tc_start(second-test)", - "got_tc_end(skipped, Testing skipped reason)", - "got_tc_start(third.test)", - "got_tc_end(failed, Testing failed reason)", - "got_tp_end()", - "got_tp_start(second-prog, 3)", - "got_tc_start(first-test)", - "got_tc_stdout_line(first stdout line for 1st test)", - "got_tc_stderr_line(first stderr line for 1st test)", - "got_tc_stdout_line(second stdout line for 1st test)", - "got_tc_stderr_line(second stderr line for 1st test)", - "got_tc_end(passed)", - "got_tc_start(second-test)", - "got_tc_stdout_line(first stdout line for 2nd test)", - "got_tc_stderr_line(first stderr line for 2nd test)", - "got_tc_stdout_line(second stdout line for 2nd test)", - "got_tc_stderr_line(second stderr line for 2nd test)", - "got_tc_end(skipped, Testing skipped reason)", - "got_tc_start(third.test)", - "got_tc_stdout_line(first stdout line for 3rd test)", - "got_tc_stderr_line(first stderr line for 3rd test)", - "got_tc_stdout_line(second stdout line for 3rd test)", - "got_tc_stderr_line(second stderr line for 3rd test)", - "got_tc_end(failed, Testing failed reason)", - "got_tp_end(This program failed)", - "got_eof()", - NULL - }; - - const char* exp_errors[] = { - NULL - }; - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(tps_4); -ATF_TEST_CASE_BODY(tps_4) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "info: a, foo\n" - "info: b, bar\n" - "info: c, baz\n" - "tps-count: 2\n" - "tp-start: 234.1, first-prog, 3\n" - "tc-start: 234.12, first-test\n" - "tc-end: 234.23, first-test, passed\n" - "tc-start: 234.34, second-test\n" - "tc-end: 234.45, second-test, skipped, Testing skipped reason\n" - "tc-start: 234.56, third-test\n" - "tc-end: 234.67, third-test, failed, Testing failed reason\n" - "tp-end: 234.78, first-prog\n" - "tp-start: 234.89, second-prog, 3\n" - "tc-start: 234.90, first-test\n" - "tc-so:first stdout line for 1st test\n" - "tc-se:first stderr line for 1st test\n" - "tc-so:second stdout line for 1st test\n" - "tc-se:second stderr line for 1st test\n" - "tc-end: 234.101, first-test, passed\n" - "tc-start: 234.112, second-test\n" - "tc-so:first stdout line for 2nd test\n" - "tc-se:first stderr line for 2nd test\n" - "tc-so:second stdout line for 2nd test\n" - "tc-se:second stderr line for 2nd test\n" - "tc-end: 234.123, second-test, skipped, Testing skipped reason\n" - "tc-start: 234.134, third-test\n" - "tc-so:first stdout line for 3rd test\n" - "tc-se:first stderr line for 3rd test\n" - "tc-so:second stdout line for 3rd test\n" - "tc-se:second stderr line for 3rd test\n" - "tc-end: 234.145, third-test, failed, Testing failed reason\n" - "tp-end: 234.156, second-prog, This program failed\n" - "info: d, foo\n" - "info: e, bar\n" - "info: f, baz\n" - ; - - const char* exp_calls[] = { - "got_info(a, foo)", - "got_info(b, bar)", - "got_info(c, baz)", - "got_ntps(2)", - "got_tp_start(first-prog, 3)", - "got_tc_start(first-test)", - "got_tc_end(passed)", - "got_tc_start(second-test)", - "got_tc_end(skipped, Testing skipped reason)", - "got_tc_start(third-test)", - "got_tc_end(failed, Testing failed reason)", - "got_tp_end()", - "got_tp_start(second-prog, 3)", - "got_tc_start(first-test)", - "got_tc_stdout_line(first stdout line for 1st test)", - "got_tc_stderr_line(first stderr line for 1st test)", - "got_tc_stdout_line(second stdout line for 1st test)", - "got_tc_stderr_line(second stderr line for 1st test)", - "got_tc_end(passed)", - "got_tc_start(second-test)", - "got_tc_stdout_line(first stdout line for 2nd test)", - "got_tc_stderr_line(first stderr line for 2nd test)", - "got_tc_stdout_line(second stdout line for 2nd test)", - "got_tc_stderr_line(second stderr line for 2nd test)", - "got_tc_end(skipped, Testing skipped reason)", - "got_tc_start(third-test)", - "got_tc_stdout_line(first stdout line for 3rd test)", - "got_tc_stderr_line(first stderr line for 3rd test)", - "got_tc_stdout_line(second stdout line for 3rd test)", - "got_tc_stderr_line(second stderr line for 3rd test)", - "got_tc_end(failed, Testing failed reason)", - "got_tp_end(This program failed)", - "got_info(d, foo)", - "got_info(e, bar)", - "got_info(f, baz)", - "got_eof()", - NULL - }; - - const char* exp_errors[] = { - NULL - }; - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(tps_5); -ATF_TEST_CASE_BODY(tps_5) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "tps-count: 1\n" - "tp-start: 345.123, the-prog, 1\n" - "tc-start: 345.134, the-test\n" - "tc-so:--- a 2007-11-04 14:00:41.000000000 +0100\n" - "tc-so:+++ b 2007-11-04 14:00:48.000000000 +0100\n" - "tc-so:@@ -1,7 +1,7 @@\n" - "tc-so: This test is meant to simulate a diff.\n" - "tc-so: Blank space at beginning of context lines must be preserved.\n" - "tc-so: \n" - "tc-so:-First original line.\n" - "tc-so:-Second original line.\n" - "tc-so:+First modified line.\n" - "tc-so:+Second modified line.\n" - "tc-so: \n" - "tc-so: EOF\n" - "tc-end: 345.145, the-test, passed\n" - "tp-end: 345.156, the-prog\n" - ; - - // NO_CHECK_STYLE_BEGIN - const char* exp_calls[] = { - "got_ntps(1)", - "got_tp_start(the-prog, 1)", - "got_tc_start(the-test)", - "got_tc_stdout_line(--- a 2007-11-04 14:00:41.000000000 +0100)", - "got_tc_stdout_line(+++ b 2007-11-04 14:00:48.000000000 +0100)", - "got_tc_stdout_line(@@ -1,7 +1,7 @@)", - "got_tc_stdout_line( This test is meant to simulate a diff.)", - "got_tc_stdout_line( Blank space at beginning of context lines must be preserved.)", - "got_tc_stdout_line( )", - "got_tc_stdout_line(-First original line.)", - "got_tc_stdout_line(-Second original line.)", - "got_tc_stdout_line(+First modified line.)", - "got_tc_stdout_line(+Second modified line.)", - "got_tc_stdout_line( )", - "got_tc_stdout_line( EOF)", - "got_tc_end(passed)", - "got_tp_end()", - "got_eof()", - NULL - }; - // NO_CHECK_STYLE_END - - const char* exp_errors[] = { - NULL - }; - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(tps_6); -ATF_TEST_CASE_BODY(tps_6) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "tps-count: 1\n" - "tp-start: 321.1, the-prog, 8\n" - "tc-start: 321.12, one\n" - "tc-end: 321.23, one, expected_death, The reason\n" - "tc-start: 321.34, two\n" - "tc-end: 321.45, two, expected_exit, This would be an exit\n" - "tc-start: 321.56, three\n" - "tc-end: 321.67, three, expected_failure, And this a failure\n" - "tc-start: 321.78, four\n" - "tc-end: 321.89, four, expected_signal, And this a signal\n" - "tc-start: 321.90, five\n" - "tc-end: 321.101, five, failed, Another reason\n" - "tc-start: 321.112, six\n" - "tc-end: 321.123, six, passed\n" - "tc-start: 321.134, seven\n" - "tc-end: 321.145, seven, skipped, Skipping it\n" - "tc-start: 321.156, eight\n" - "tc-end: 321.167, eight, expected_timeout, Some hang reason\n" - "tp-end: 321.178, the-prog\n" - ; - - // NO_CHECK_STYLE_BEGIN - const char* exp_calls[] = { - "got_ntps(1)", - "got_tp_start(the-prog, 8)", - "got_tc_start(one)", - "got_tc_end(expected_death, The reason)", - "got_tc_start(two)", - "got_tc_end(expected_exit, This would be an exit)", - "got_tc_start(three)", - "got_tc_end(expected_failure, And this a failure)", - "got_tc_start(four)", - "got_tc_end(expected_signal, And this a signal)", - "got_tc_start(five)", - "got_tc_end(failed, Another reason)", - "got_tc_start(six)", - "got_tc_end(passed)", - "got_tc_start(seven)", - "got_tc_end(skipped, Skipping it)", - "got_tc_start(eight)", - "got_tc_end(expected_timeout, Some hang reason)", - "got_tp_end()", - "got_eof()", - NULL - }; - // NO_CHECK_STYLE_END - - const char* exp_errors[] = { - NULL - }; - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - - -ATF_TEST_CASE_WITHOUT_HEAD(tps_50); -ATF_TEST_CASE_BODY(tps_50) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "foo\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "3: Unexpected token `foo'; expected tps-count or info field", - NULL - }; - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(tps_51); -ATF_TEST_CASE_BODY(tps_51) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "tps-count\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "3: Unexpected token `<<NEWLINE>>'; expected `:'", - NULL - }; - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(tps_52); -ATF_TEST_CASE_BODY(tps_52) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "tps-count:\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "3: Unexpected token `<<NEWLINE>>'; expected number of test programs", - NULL - }; - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(tps_53); -ATF_TEST_CASE_BODY(tps_53) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "tps-count: 1\n" - "foo\n" - ; - - const char* exp_calls[] = { - "got_ntps(1)", - NULL - }; - - const char* exp_errors[] = { - "4: Unexpected token `foo'; expected start of test program", - NULL - }; - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(tps_54); -ATF_TEST_CASE_BODY(tps_54) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "tps-count: 1\n" - "foo\n" - "tp-start\n" - "tp-start:\n" - "tp-start: 123\n" - "tp-start: 123.\n" - "tp-start: 123.456\n" - "tp-start: 123.456,\n" - "tp-start: 123.456, foo\n" - "tp-start: 123.456, foo,\n" - "tp-start: 123.456, foo, 0\n" - "bar\n" - "tp-start: 456.789, foo, 0\n" - "tp-end\n" - "tp-start: 777.777, foo, 0\n" - "tp-end:\n" - "tp-start: 777.777, foo, 0\n" - "tp-end: 777\n" - "tp-start: 777.777, foo, 0\n" - "tp-end: 777.\n" - "tp-start: 777.777, foo, 0\n" - "tp-end: 777.888\n" - "tp-start: 777.777, foo, 0\n" - "tp-end: 777.888, \n" - "tp-start: 777.777, foo, 0\n" - "tp-end: 777.888, bar\n" - "tp-start: 777.777, foo, 0\n" - "tp-end: 777.888, foo,\n" - ; - - const char* exp_calls[] = { - "got_ntps(1)", - NULL - }; - - const char* exp_errors[] = { - "4: Unexpected token `foo'; expected start of test program", - "5: Unexpected token `<<NEWLINE>>'; expected `:'", - "6: Unexpected token `<<NEWLINE>>'; expected timestamp", - "7: Malformed timestamp value 123", - "8: Malformed timestamp value 123.", - "9: Unexpected token `<<NEWLINE>>'; expected `,'", - "10: Unexpected token `<<NEWLINE>>'; expected test program name", - "11: Unexpected token `<<NEWLINE>>'; expected `,'", - "12: Unexpected token `<<NEWLINE>>'; expected number of test programs", - "14: Unexpected token `bar'; expected end of test program", - "16: Unexpected token `<<NEWLINE>>'; expected `:'", - "18: Unexpected token `<<NEWLINE>>'; expected timestamp", - "20: Malformed timestamp value 777", - "22: Malformed timestamp value 777.", - "24: Unexpected token `<<NEWLINE>>'; expected `,'", - - "26: Unexpected token `<<NEWLINE>>'; expected test program name", - "28: Test program name used in terminator does not match opening", - "30: Empty reason for failed test program", - NULL - }; - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(tps_55); -ATF_TEST_CASE_BODY(tps_55) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "tps-count: 1\n" - "tp-start: 100.200, foo, 1\n" - "foo\n" - "tc-start\n" - "tc-start:\n" - "tc-start: 111\n" - "tc-start: 111.\n" - "tc-start: 111.222\n" - "tc-start: 111.222,\n" - "tc-start: 111.222, foo\n" - "bar\n" - "tc-start: 111.333, foo\n" - "tc-end\n" - "tc-start: 111.444, foo\n" - "tc-end:\n" - "tc-start: 111.444, foo\n" - "tc-end: 111\n" - "tc-start: 111.444, foo\n" - "tc-end: 111.\n" - "tc-start: 111.444, foo\n" - "tc-end: 111.555\n" - "tc-start: 111.444, foo\n" - "tc-end: 111.555, \n" - "tc-start: 111.444, foo\n" - "tc-end: 111.555, bar\n" - "tc-start: 111.444, foo\n" - "tc-end: 111.555, foo\n" - "tc-start: 111.444, foo\n" - "tc-end: 111.555, foo,\n" - "tp-end: 111.666, foo\n" - ; - - const char* exp_calls[] = { - "got_ntps(1)", - "got_tp_start(foo, 1)", - NULL - }; - - // NO_CHECK_STYLE_BEGIN - const char* exp_errors[] = { - "5: Unexpected token `foo'; expected start of test case", - "6: Unexpected token `<<NEWLINE>>'; expected `:'", - "7: Unexpected token `<<NEWLINE>>'; expected timestamp", - "8: Malformed timestamp value 111", - "9: Malformed timestamp value 111.", - "10: Unexpected token `<<NEWLINE>>'; expected `,'", - "11: Unexpected token `<<NEWLINE>>'; expected test case name", - "13: Unexpected token `bar'; expected end of test case or test case's stdout/stderr line", - "15: Unexpected token `<<NEWLINE>>'; expected `:'", - "17: Unexpected token `<<NEWLINE>>'; expected timestamp", - "19: Malformed timestamp value 111", - "21: Malformed timestamp value 111.", - "23: Unexpected token `<<NEWLINE>>'; expected `,'", - "25: Unexpected token `<<NEWLINE>>'; expected test case name", - "27: Test case name used in terminator does not match opening", - "29: Unexpected token `<<NEWLINE>>'; expected `,'", - "31: Unexpected token `<<NEWLINE>>'; expected expected_{death,exit,failure,signal,timeout}, failed, passed or skipped", - "32: Unexpected token `tp-end'; expected start of test case", - NULL - }; - // NO_CHECK_STYLE_END - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(tps_56); -ATF_TEST_CASE_BODY(tps_56) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "tps-count: 1\n" - "tp-start: 111.222, foo, 1\n" - "tc-start: 111.333, foo\n" - "tc-end: 111.444, foo, passe\n" - "tc-start: 111.333, foo\n" - "tc-end: 111.444, foo, passed,\n" - "tc-start: 111.555, bar\n" - "tc-end: 111.666, bar, failed\n" - "tc-start: 111.555, bar\n" - "tc-end: 111.666, bar, failed,\n" - "tc-start: 111.555, baz\n" - "tc-end: 111.666, baz, skipped\n" - "tc-start: 111.555, baz\n" - "tc-end: 111.666, baz, skipped,\n" - "tp-end: 111.777, foo\n" - ; - - const char* exp_calls[] = { - "got_ntps(1)", - "got_tp_start(foo, 1)", - "got_tc_start(foo)", - NULL - }; - - // NO_CHECK_STYLE_BEGIN - const char* exp_errors[] = { - "6: Unexpected token `passe'; expected expected_{death,exit,failure,signal,timeout}, failed, passed or skipped", - "8: Unexpected token `,'; expected new line", - "10: Unexpected token `<<NEWLINE>>'; expected `,'", - "12: Empty reason for failed test case result", - "14: Unexpected token `<<NEWLINE>>'; expected `,'", - "16: Empty reason for skipped test case result", - "17: Unexpected token `tp-end'; expected start of test case", - NULL - }; - // NO_CHECK_STYLE_END - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(tps_57); -ATF_TEST_CASE_BODY(tps_57) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "tps-count: 2\n" - "tp-start: 111.222, foo, 0\n" - "tp-end: 111.333, foo\n" - ; - - const char* exp_calls[] = { - "got_ntps(2)", - "got_tp_start(foo, 0)", - "got_tp_end()", - NULL - }; - - const char* exp_errors[] = { - "6: Unexpected token `<<EOF>>'; expected start of test program", - NULL - }; - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(tps_58); -ATF_TEST_CASE_BODY(tps_58) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "tps-count: 1\n" - "tp-start: 111.222, foo, 0\n" - "tp-end: 111.333, foo\n" - "tp-start: 111.444, bar, 0\n" - "tp-end: 111.555, bar\n" - ; - - const char* exp_calls[] = { - "got_ntps(1)", - "got_tp_start(foo, 0)", - "got_tp_end()", - NULL - }; - - const char* exp_errors[] = { - "6: Unexpected token `tp-start'; expected end of stream or info field", - NULL - }; - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(tps_59); -ATF_TEST_CASE_BODY(tps_59) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "info\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "3: Unexpected token `<<NEWLINE>>'; expected `:'", - NULL - }; - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(tps_60); -ATF_TEST_CASE_BODY(tps_60) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "info:\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "3: Unexpected token `<<NEWLINE>>'; expected info property name", - NULL - }; - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(tps_61); -ATF_TEST_CASE_BODY(tps_61) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "info: a\n" - ; - - const char* exp_calls[] = { - NULL - }; - - const char* exp_errors[] = { - "3: Unexpected token `<<NEWLINE>>'; expected `,'", - NULL - }; - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(tps_62); -ATF_TEST_CASE_BODY(tps_62) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "info: a,\n" - ; - - const char* exp_calls[] = { - "got_info(a, )", - NULL - }; - - const char* exp_errors[] = { - "4: Unexpected token `<<EOF>>'; expected tps-count or info field", - NULL - }; - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(tps_63); -ATF_TEST_CASE_BODY(tps_63) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "info: a, b\n" - ; - - const char* exp_calls[] = { - "got_info(a, b)", - NULL - }; - - const char* exp_errors[] = { - "4: Unexpected token `<<EOF>>'; expected tps-count or info field", - NULL - }; - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(tps_64); -ATF_TEST_CASE_BODY(tps_64) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "info: a, b\n" - "info: a.b.c.def, g\n" - "tps-count\n" - ; - - const char* exp_calls[] = { - "got_info(a, b)", - "got_info(a.b.c.def, g)", - NULL - }; - - const char* exp_errors[] = { - "5: Unexpected token `<<NEWLINE>>'; expected `:'", - NULL - }; - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(tps_65); -ATF_TEST_CASE_BODY(tps_65) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "info: a, b\n" - "tps-count:\n" - ; - - const char* exp_calls[] = { - "got_info(a, b)", - NULL - }; - - const char* exp_errors[] = { - "4: Unexpected token `<<NEWLINE>>'; expected number of test programs", - NULL - }; - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_TEST_CASE_WITHOUT_HEAD(tps_66); -ATF_TEST_CASE_BODY(tps_66) -{ - const char* input = - "Content-Type: application/X-atf-tps; version=\"3\"\n" - "\n" - "info: a, b\n" - "tps-count: 0\n" - "info\n" - ; - - const char* exp_calls[] = { - "got_info(a, b)", - "got_ntps(0)", - NULL - }; - - const char* exp_errors[] = { - "5: Unexpected token `<<NEWLINE>>'; expected `:'", - NULL - }; - - do_parser_test< tps_reader >(input, exp_calls, exp_errors); -} - -ATF_INIT_TEST_CASES(tcs) -{ - ATF_ADD_TEST_CASE(tcs, tps_1); - ATF_ADD_TEST_CASE(tcs, tps_2); - ATF_ADD_TEST_CASE(tcs, tps_3); - ATF_ADD_TEST_CASE(tcs, tps_4); - ATF_ADD_TEST_CASE(tcs, tps_5); - ATF_ADD_TEST_CASE(tcs, tps_6); - ATF_ADD_TEST_CASE(tcs, tps_50); - ATF_ADD_TEST_CASE(tcs, tps_51); - ATF_ADD_TEST_CASE(tcs, tps_52); - ATF_ADD_TEST_CASE(tcs, tps_53); - ATF_ADD_TEST_CASE(tcs, tps_54); - ATF_ADD_TEST_CASE(tcs, tps_55); - ATF_ADD_TEST_CASE(tcs, tps_56); - ATF_ADD_TEST_CASE(tcs, tps_57); - ATF_ADD_TEST_CASE(tcs, tps_58); - ATF_ADD_TEST_CASE(tcs, tps_59); - ATF_ADD_TEST_CASE(tcs, tps_60); - ATF_ADD_TEST_CASE(tcs, tps_61); - ATF_ADD_TEST_CASE(tcs, tps_62); - ATF_ADD_TEST_CASE(tcs, tps_63); - ATF_ADD_TEST_CASE(tcs, tps_64); - ATF_ADD_TEST_CASE(tcs, tps_65); - ATF_ADD_TEST_CASE(tcs, tps_66); -} - diff --git a/tools/requirements.cpp b/tools/requirements.cpp deleted file mode 100644 index 97fcdc8..0000000 --- a/tools/requirements.cpp +++ /dev/null @@ -1,325 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -extern "C" { -#include <sys/param.h> -#include <sys/sysctl.h> -} - -#include <cassert> -#include <cerrno> -#include <cstdlib> -#include <cstring> -#include <stdexcept> - -#include "config.hpp" -#include "defs.hpp" -#include "env.hpp" -#include "fs.hpp" -#include "requirements.hpp" -#include "text.hpp" -#include "user.hpp" - -namespace impl = tools; - -namespace { - -typedef std::map< std::string, std::string > vars_map; - -static -bool -has_program(const tools::fs::path& program) -{ - bool found = false; - - if (program.is_absolute()) { - found = tools::fs::is_executable(program); - } else { - if (program.str().find('/') != std::string::npos) - throw std::runtime_error("Relative paths are not allowed " - "when searching for a program (" + - program.str() + ")"); - - const std::vector< std::string > dirs = tools::text::split( - tools::env::get("PATH"), ":"); - for (std::vector< std::string >::const_iterator iter = dirs.begin(); - !found && iter != dirs.end(); iter++) { - const tools::fs::path& p = tools::fs::path(*iter) / program; - if (tools::fs::is_executable(p)) - found = true; - } - } - - return found; -} - -static -std::string -check_arch(const std::string& arches) -{ - const std::vector< std::string > v = tools::text::split(arches, " "); - - for (std::vector< std::string >::const_iterator iter = v.begin(); - iter != v.end(); iter++) { - if ((*iter) == tools::config::get("atf_arch")) - return ""; - } - - if (v.size() == 1) - return "Requires the '" + arches + "' architecture"; - else - return "Requires one of the '" + arches + "' architectures"; -} - -static -std::string -check_config(const std::string& variables, const vars_map& config) -{ - const std::vector< std::string > v = tools::text::split(variables, " "); - for (std::vector< std::string >::const_iterator iter = v.begin(); - iter != v.end(); iter++) { - if (config.find((*iter)) == config.end()) - return "Required configuration variable '" + (*iter) + "' not " - "defined"; - } - return ""; -} - -static -std::string -check_files(const std::string& progs) -{ - const std::vector< std::string > v = tools::text::split(progs, " "); - for (std::vector< std::string >::const_iterator iter = v.begin(); - iter != v.end(); iter++) { - const tools::fs::path file(*iter); - if (!file.is_absolute()) - throw std::runtime_error("Relative paths are not allowed when " - "checking for a required file (" + file.str() + ")"); - if (!tools::fs::exists(file)) - return "Required file '" + file.str() + "' not found"; - } - return ""; -} - -static -std::string -check_machine(const std::string& machines) -{ - const std::vector< std::string > v = tools::text::split(machines, " "); - - for (std::vector< std::string >::const_iterator iter = v.begin(); - iter != v.end(); iter++) { - if ((*iter) == tools::config::get("atf_machine")) - return ""; - } - - if (v.size() == 1) - return "Requires the '" + machines + "' machine type"; - else - return "Requires one of the '" + machines + "' machine types"; -} - -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) -static -std::string -check_memory_sysctl(const int64_t needed, const char* sysctl_variable) -{ - int64_t available; - std::size_t available_length = sizeof(available); - if (::sysctlbyname(sysctl_variable, &available, &available_length, - NULL, 0) == -1) { - const char* e = std::strerror(errno); - return "Failed to get sysctl(hw.usermem64) value: " + std::string(e); - } - - if (available < needed) { - return "Not enough memory; needed " + tools::text::to_string(needed) + - ", available " + tools::text::to_string(available); - } else - return ""; -} -# if defined(__APPLE__) -static -std::string -check_memory_darwin(const int64_t needed) -{ - return check_memory_sysctl(needed, "hw.usermem"); -} -# elif defined(__FreeBSD__) -static -std::string -check_memory_freebsd(const int64_t needed) -{ - return check_memory_sysctl(needed, "hw.usermem"); -} -# elif defined(__NetBSD__) -static -std::string -check_memory_netbsd(const int64_t needed) -{ - return check_memory_sysctl(needed, "hw.usermem64"); -} -# else -# error "Conditional error" -# endif -#else -static -std::string -check_memory_unknown(const int64_t needed ATF_DEFS_ATTRIBUTE_UNUSED) -{ - return ""; -} -#endif - -static -std::string -check_memory(const std::string& raw_memory) -{ - const int64_t needed = tools::text::to_bytes(raw_memory); - -#if defined(__APPLE__) - return check_memory_darwin(needed); -#elif defined(__FreeBSD__) - return check_memory_freebsd(needed); -#elif defined(__NetBSD__) - return check_memory_netbsd(needed); -#else - return check_memory_unknown(needed); -#endif -} - -static -std::string -check_progs(const std::string& progs) -{ - const std::vector< std::string > v = tools::text::split(progs, " "); - for (std::vector< std::string >::const_iterator iter = v.begin(); - iter != v.end(); iter++) { - if (!has_program(tools::fs::path(*iter))) - return "Required program '" + (*iter) + "' not found in the PATH"; - } - return ""; -} - -static -std::string -check_user(const std::string& user, const vars_map& config) -{ - if (user == "root") { - if (!tools::user::is_root()) - return "Requires root privileges"; - else - return ""; - } else if (user == "unprivileged") { - if (tools::user::is_root()) { - const vars_map::const_iterator iter = config.find( - "unprivileged-user"); - if (iter == config.end()) - return "Requires an unprivileged user and the " - "'unprivileged-user' configuration variable is not set"; - else { - const std::string& unprivileged_user = (*iter).second; - try { - (void)tools::user::get_user_ids(unprivileged_user); - return ""; - } catch (const std::runtime_error& e) { - return "Failed to get information for user " + - unprivileged_user; - } - } - } else - return ""; - } else - throw std::runtime_error("Invalid value '" + user + "' for property " - "require.user"); -} - -} // anonymous namespace - -std::string -impl::check_requirements(const vars_map& metadata, - const vars_map& config) -{ - std::string failure_reason = ""; - - for (vars_map::const_iterator iter = metadata.begin(); - failure_reason.empty() && iter != metadata.end(); iter++) { - const std::string& name = (*iter).first; - const std::string& value = (*iter).second; - assert(!value.empty()); // Enforced by application/X-atf-tp parser. - - if (name == "require.arch") - failure_reason = check_arch(value); - else if (name == "require.config") - failure_reason = check_config(value, config); - else if (name == "require.files") - failure_reason = check_files(value); - else if (name == "require.machine") - failure_reason = check_machine(value); - else if (name == "require.memory") - failure_reason = check_memory(value); - else if (name == "require.progs") - failure_reason = check_progs(value); - else if (name == "require.user") - failure_reason = check_user(value, config); - else { - // Unknown require.* properties are forbidden by the - // application/X-atf-tp parser. - assert(failure_reason.find("require.") != 0); - } - } - - return failure_reason; -} - -std::pair< int, int > -impl::get_required_user(const vars_map& metadata, - const vars_map& config) -{ - const vars_map::const_iterator user = metadata.find( - "require.user"); - if (user == metadata.end()) - return std::make_pair(-1, -1); - - if ((*user).second == "unprivileged") { - if (tools::user::is_root()) { - const vars_map::const_iterator iter = config.find( - "unprivileged-user"); - try { - return tools::user::get_user_ids((*iter).second); - } catch (const std::exception& e) { - std::abort(); // This has been validated by check_user. - } - } else { - return std::make_pair(-1, -1); - } - } else - return std::make_pair(-1, -1); -} diff --git a/tools/requirements.hpp b/tools/requirements.hpp deleted file mode 100644 index 1eefdaf..0000000 --- a/tools/requirements.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// -// 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. -// - -#if !defined(TOOLS_REQUIREMENTS_HPP) -#define TOOLS_REQUIREMENTS_HPP - -#include <map> -#include <string> -#include <utility> - -namespace tools { - -std::string check_requirements(const std::map< std::string, std::string >&, - const std::map< std::string, std::string >&); -std::pair< int, int > get_required_user( - const std::map< std::string, std::string >&, - const std::map< std::string, std::string >&); - -} // namespace tools - -#endif // !defined(TOOLS_REQUIREMENTS_HPP) diff --git a/tools/requirements_test.cpp b/tools/requirements_test.cpp deleted file mode 100644 index 6d37d75..0000000 --- a/tools/requirements_test.cpp +++ /dev/null @@ -1,400 +0,0 @@ -// -// 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 <atf-c++.hpp> - -#include "config.hpp" -#include "requirements.hpp" -#include "text.hpp" -#include "user.hpp" - -namespace impl = tools; - -// ------------------------------------------------------------------------- -// Auxiliary functions. -// ------------------------------------------------------------------------- - -namespace { - -typedef std::map< std::string, std::string > vars_map; - -const vars_map no_config; - -void -do_check(const std::string& expected, const vars_map& metadata, - const vars_map& config = no_config) -{ - const std::string actual = impl::check_requirements(metadata, config); - if (!tools::text::match(actual, expected)) - ATF_FAIL("Requirements failure reason \"" + actual + "\" does not " - "match \"" + expected + "\""); -} - -} // anonymous namespace - -// ------------------------------------------------------------------------- -// Tests for the require.arch metadata property. -// ------------------------------------------------------------------------- - -ATF_TEST_CASE(require_arch_one_ok); -ATF_TEST_CASE_HEAD(require_arch_one_ok) {} -ATF_TEST_CASE_BODY(require_arch_one_ok) { - vars_map metadata; - metadata["require.arch"] = tools::config::get("atf_arch"); - do_check("", metadata); -} - -ATF_TEST_CASE(require_arch_one_fail); -ATF_TEST_CASE_HEAD(require_arch_one_fail) {} -ATF_TEST_CASE_BODY(require_arch_one_fail) { - vars_map metadata; - metadata["require.arch"] = "__fake_arch__"; - do_check("Requires the '__fake_arch__' architecture", metadata); -} - -ATF_TEST_CASE(require_arch_many_ok); -ATF_TEST_CASE_HEAD(require_arch_many_ok) {} -ATF_TEST_CASE_BODY(require_arch_many_ok) { - vars_map metadata; - metadata["require.arch"] = "__foo__ " + tools::config::get("atf_arch") + - " __bar__"; - do_check("", metadata); -} - -ATF_TEST_CASE(require_arch_many_fail); -ATF_TEST_CASE_HEAD(require_arch_many_fail) {} -ATF_TEST_CASE_BODY(require_arch_many_fail) { - vars_map metadata; - metadata["require.arch"] = "__foo__ __bar__ __baz__"; - do_check("Requires one of the '__foo__ __bar__ __baz__' architectures", - metadata); -} - -// ------------------------------------------------------------------------- -// Tests for the require.config metadata property. -// ------------------------------------------------------------------------- - -ATF_TEST_CASE(require_config_one_ok); -ATF_TEST_CASE_HEAD(require_config_one_ok) {} -ATF_TEST_CASE_BODY(require_config_one_ok) { - vars_map metadata, config; - metadata["require.config"] = "var1"; - config["var1"] = "some-value"; - do_check("", metadata, config); -} - -ATF_TEST_CASE(require_config_one_fail); -ATF_TEST_CASE_HEAD(require_config_one_fail) {} -ATF_TEST_CASE_BODY(require_config_one_fail) { - vars_map metadata, config; - metadata["require.config"] = "var1"; - do_check("Required configuration variable 'var1' not defined", metadata, - config); -} - -ATF_TEST_CASE(require_config_many_ok); -ATF_TEST_CASE_HEAD(require_config_many_ok) {} -ATF_TEST_CASE_BODY(require_config_many_ok) { - vars_map metadata, config; - metadata["require.config"] = "var1 var2 var3"; - config["var1"] = "first-value"; - config["var2"] = "second-value"; - config["var3"] = "third-value"; - do_check("", metadata, config); -} - -ATF_TEST_CASE(require_config_many_fail); -ATF_TEST_CASE_HEAD(require_config_many_fail) {} -ATF_TEST_CASE_BODY(require_config_many_fail) { - vars_map metadata, config; - metadata["require.config"] = "var1 var2 var3"; - config["var1"] = "first-value"; - config["var3"] = "third-value"; - do_check("Required configuration variable 'var2' not defined", metadata, - config); -} - -// ------------------------------------------------------------------------- -// Tests for the require.files metadata property. -// ------------------------------------------------------------------------- - -ATF_TEST_CASE_WITHOUT_HEAD(require_files_one_ok); -ATF_TEST_CASE_BODY(require_files_one_ok) { - vars_map metadata; - metadata["require.files"] = "/bin/ls"; - do_check("", metadata); -} - -ATF_TEST_CASE_WITHOUT_HEAD(require_files_one_missing); -ATF_TEST_CASE_BODY(require_files_one_missing) { - vars_map metadata; - metadata["require.files"] = "/non-existent/foo"; - do_check("Required file '/non-existent/foo' not found", metadata); -} - -ATF_TEST_CASE_WITHOUT_HEAD(require_files_one_fail); -ATF_TEST_CASE_BODY(require_files_one_fail) { - vars_map metadata; - metadata["require.files"] = "/bin/cp this-is-relative"; - ATF_REQUIRE_THROW_RE(std::runtime_error, "Relative.*(this-is-relative)", - impl::check_requirements(metadata, no_config)); -} - -ATF_TEST_CASE_WITHOUT_HEAD(require_files_many_ok); -ATF_TEST_CASE_BODY(require_files_many_ok) { - vars_map metadata; - metadata["require.files"] = "/bin/ls /bin/cp"; - do_check("", metadata); -} - -ATF_TEST_CASE_WITHOUT_HEAD(require_files_many_missing); -ATF_TEST_CASE_BODY(require_files_many_missing) { - vars_map metadata; - metadata["require.files"] = "/bin/ls /non-existent/bar /bin/cp"; - do_check("Required file '/non-existent/bar' not found", metadata); -} - -ATF_TEST_CASE_WITHOUT_HEAD(require_files_many_fail); -ATF_TEST_CASE_BODY(require_files_many_fail) { - vars_map metadata; - metadata["require.files"] = "/bin/cp also-relative"; - ATF_REQUIRE_THROW_RE(std::runtime_error, "Relative.*(also-relative)", - impl::check_requirements(metadata, no_config)); -} - -// ------------------------------------------------------------------------- -// Tests for the require.machine metadata property. -// ------------------------------------------------------------------------- - -ATF_TEST_CASE(require_machine_one_ok); -ATF_TEST_CASE_HEAD(require_machine_one_ok) {} -ATF_TEST_CASE_BODY(require_machine_one_ok) { - vars_map metadata; - metadata["require.machine"] = tools::config::get("atf_machine"); - do_check("", metadata); -} - -ATF_TEST_CASE(require_machine_one_fail); -ATF_TEST_CASE_HEAD(require_machine_one_fail) {} -ATF_TEST_CASE_BODY(require_machine_one_fail) { - vars_map metadata; - metadata["require.machine"] = "__fake_machine__"; - do_check("Requires the '__fake_machine__' machine type", metadata); -} - -ATF_TEST_CASE(require_machine_many_ok); -ATF_TEST_CASE_HEAD(require_machine_many_ok) {} -ATF_TEST_CASE_BODY(require_machine_many_ok) { - vars_map metadata; - metadata["require.machine"] = "__foo__ " + - tools::config::get("atf_machine") + " __bar__"; - do_check("", metadata); -} - -ATF_TEST_CASE(require_machine_many_fail); -ATF_TEST_CASE_HEAD(require_machine_many_fail) {} -ATF_TEST_CASE_BODY(require_machine_many_fail) { - vars_map metadata; - metadata["require.machine"] = "__foo__ __bar__ __baz__"; - do_check("Requires one of the '__foo__ __bar__ __baz__' machine types", - metadata); -} - -// ------------------------------------------------------------------------- -// Tests for the require.memory metadata property. -// ------------------------------------------------------------------------- - -ATF_TEST_CASE_WITHOUT_HEAD(require_memory_ok); -ATF_TEST_CASE_BODY(require_memory_ok) { - vars_map metadata; - metadata["require.memory"] = "1m"; - do_check("", metadata); -} - -ATF_TEST_CASE_WITHOUT_HEAD(require_memory_not_enough); -ATF_TEST_CASE_BODY(require_memory_not_enough) { - vars_map metadata; - metadata["require.memory"] = "128t"; -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) - do_check("Not enough memory; needed 140737488355328, available [0-9]*", - metadata); -#else - skip("Don't know how to check for the amount of physical memory"); -#endif -} - -ATF_TEST_CASE_WITHOUT_HEAD(require_memory_fail); -ATF_TEST_CASE_BODY(require_memory_fail) { - vars_map metadata; - metadata["require.memory"] = "foo"; - ATF_REQUIRE_THROW(std::runtime_error, - impl::check_requirements(metadata, no_config)); -} - -// ------------------------------------------------------------------------- -// Tests for the require.progs metadata property. -// ------------------------------------------------------------------------- - -ATF_TEST_CASE(require_progs_one_ok); -ATF_TEST_CASE_HEAD(require_progs_one_ok) {} -ATF_TEST_CASE_BODY(require_progs_one_ok) { - vars_map metadata; - metadata["require.progs"] = "cp"; - do_check("", metadata); -} - -ATF_TEST_CASE(require_progs_one_missing); -ATF_TEST_CASE_HEAD(require_progs_one_missing) {} -ATF_TEST_CASE_BODY(require_progs_one_missing) { - vars_map metadata; - metadata["require.progs"] = "cp __non-existent__"; - do_check("Required program '__non-existent__' not found in the PATH", - metadata); -} - -ATF_TEST_CASE(require_progs_one_fail); -ATF_TEST_CASE_HEAD(require_progs_one_fail) {} -ATF_TEST_CASE_BODY(require_progs_one_fail) { - vars_map metadata; - metadata["require.progs"] = "bin/cp"; - ATF_REQUIRE_THROW(std::runtime_error, - impl::check_requirements(metadata, no_config)); -} - -ATF_TEST_CASE(require_progs_many_ok); -ATF_TEST_CASE_HEAD(require_progs_many_ok) {} -ATF_TEST_CASE_BODY(require_progs_many_ok) { - vars_map metadata; - metadata["require.progs"] = "cp ls mv"; - do_check("", metadata); -} - -ATF_TEST_CASE(require_progs_many_missing); -ATF_TEST_CASE_HEAD(require_progs_many_missing) {} -ATF_TEST_CASE_BODY(require_progs_many_missing) { - vars_map metadata; - metadata["require.progs"] = "mv ls __foo__ cp"; - do_check("Required program '__foo__' not found in the PATH", metadata); -} - -ATF_TEST_CASE(require_progs_many_fail); -ATF_TEST_CASE_HEAD(require_progs_many_fail) {} -ATF_TEST_CASE_BODY(require_progs_many_fail) { - vars_map metadata; - metadata["require.progs"] = "ls cp ../bin/cp"; - ATF_REQUIRE_THROW(std::runtime_error, - impl::check_requirements(metadata, no_config)); -} - -// ------------------------------------------------------------------------- -// Tests for the require.user metadata property. -// ------------------------------------------------------------------------- - -ATF_TEST_CASE(require_user_root); -ATF_TEST_CASE_HEAD(require_user_root) {} -ATF_TEST_CASE_BODY(require_user_root) { - vars_map metadata; - metadata["require.user"] = "root"; - if (tools::user::is_root()) - do_check("", metadata); - else - do_check("Requires root privileges", metadata); -} - -ATF_TEST_CASE(require_user_unprivileged); -ATF_TEST_CASE_HEAD(require_user_unprivileged) {} -ATF_TEST_CASE_BODY(require_user_unprivileged) { - vars_map metadata; - metadata["require.user"] = "unprivileged"; - if (tools::user::is_root()) - do_check("Requires an unprivileged user and the 'unprivileged-user' " - "configuration variable is not set", metadata); - else - do_check("", metadata); -} - -ATF_TEST_CASE(require_user_fail); -ATF_TEST_CASE_HEAD(require_user_fail) {} -ATF_TEST_CASE_BODY(require_user_fail) { - vars_map metadata; - metadata["require.user"] = "nobody"; - ATF_REQUIRE_THROW(std::runtime_error, - impl::check_requirements(metadata, no_config)); -} - -// ------------------------------------------------------------------------- -// Main. -// ------------------------------------------------------------------------- - -ATF_INIT_TEST_CASES(tcs) -{ - // Add test cases for require.arch. - ATF_ADD_TEST_CASE(tcs, require_arch_one_ok); - ATF_ADD_TEST_CASE(tcs, require_arch_one_fail); - ATF_ADD_TEST_CASE(tcs, require_arch_many_ok); - ATF_ADD_TEST_CASE(tcs, require_arch_many_fail); - - // Add test cases for require.config. - ATF_ADD_TEST_CASE(tcs, require_config_one_ok); - ATF_ADD_TEST_CASE(tcs, require_config_one_fail); - ATF_ADD_TEST_CASE(tcs, require_config_many_ok); - ATF_ADD_TEST_CASE(tcs, require_config_many_fail); - - // Add test cases for require.files. - ATF_ADD_TEST_CASE(tcs, require_files_one_ok); - ATF_ADD_TEST_CASE(tcs, require_files_one_missing); - ATF_ADD_TEST_CASE(tcs, require_files_one_fail); - ATF_ADD_TEST_CASE(tcs, require_files_many_ok); - ATF_ADD_TEST_CASE(tcs, require_files_many_missing); - ATF_ADD_TEST_CASE(tcs, require_files_many_fail); - - // Add test cases for require.machine. - ATF_ADD_TEST_CASE(tcs, require_machine_one_ok); - ATF_ADD_TEST_CASE(tcs, require_machine_one_fail); - ATF_ADD_TEST_CASE(tcs, require_machine_many_ok); - ATF_ADD_TEST_CASE(tcs, require_machine_many_fail); - - // Add test cases for require.memory. - ATF_ADD_TEST_CASE(tcs, require_memory_ok); - ATF_ADD_TEST_CASE(tcs, require_memory_not_enough); - ATF_ADD_TEST_CASE(tcs, require_memory_fail); - - // Add test cases for require.progs. - ATF_ADD_TEST_CASE(tcs, require_progs_one_ok); - ATF_ADD_TEST_CASE(tcs, require_progs_one_missing); - ATF_ADD_TEST_CASE(tcs, require_progs_one_fail); - ATF_ADD_TEST_CASE(tcs, require_progs_many_ok); - ATF_ADD_TEST_CASE(tcs, require_progs_many_missing); - ATF_ADD_TEST_CASE(tcs, require_progs_many_fail); - - // Add test cases for require.user. - ATF_ADD_TEST_CASE(tcs, require_user_root); - ATF_ADD_TEST_CASE(tcs, require_user_unprivileged); - ATF_ADD_TEST_CASE(tcs, require_user_fail); -} diff --git a/tools/sample/atf-run.hooks b/tools/sample/atf-run.hooks deleted file mode 100644 index 86d187d..0000000 --- a/tools/sample/atf-run.hooks +++ /dev/null @@ -1,23 +0,0 @@ -# -# Definition of custom hooks for atf-run. -# -# Uncomment any hooks that you want to override and add your own code -# to them. Some sample calls are included in them. Be very careful -# with what you print from here. -# -# See atf-run(1) for more details. -# - -#info_start_hook() -#{ -# default_info_start_hook "${@}" -# -# atf_tps_writer_info "extra.info" "An example" -#} - -#info_end_hook() -#{ -# default_info_end_hook "${@}" -# -# atf_tps_writer_info "extra.info" "An example" -#} diff --git a/tools/sample/common.conf b/tools/sample/common.conf deleted file mode 100644 index 464ee96..0000000 --- a/tools/sample/common.conf +++ /dev/null @@ -1,11 +0,0 @@ -Content-Type: application/X-atf-config; version="1" - -# -# Sample configuration file for properties affecting all test suites. -# - -# When running the test suite as root, some tests require to switch to -# an unprivileged user to perform extra checks. Set this variable to -# the user you want to use in those cases. If not set, those tests will -# be skipped. -#unprivileged-user = "_atf" diff --git a/tools/several_tcs_helper.c b/tools/several_tcs_helper.c deleted file mode 100644 index d287c81..0000000 --- a/tools/several_tcs_helper.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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 <atf-c.h> - -ATF_TC(first); -ATF_TC_HEAD(first, tc) -{ - atf_tc_set_md_var(tc, "descr", "Description 1"); -} -ATF_TC_BODY(first, tc) -{ -} - -ATF_TC_WITH_CLEANUP(second); -ATF_TC_HEAD(second, tc) -{ - atf_tc_set_md_var(tc, "descr", "Description 2"); - atf_tc_set_md_var(tc, "timeout", "500"); - atf_tc_set_md_var(tc, "X-property", "Custom property"); -} -ATF_TC_BODY(second, tc) -{ -} -ATF_TC_CLEANUP(second, tc) -{ -} - -ATF_TC_WITHOUT_HEAD(third); -ATF_TC_BODY(third, tc) -{ -} - -ATF_TP_ADD_TCS(tp) -{ - ATF_TP_ADD_TC(tp, first); - ATF_TP_ADD_TC(tp, second); - ATF_TP_ADD_TC(tp, third); - - return atf_no_error(); -} diff --git a/tools/share/atf-run.hooks b/tools/share/atf-run.hooks deleted file mode 100644 index c94f3bc..0000000 --- a/tools/share/atf-run.hooks +++ /dev/null @@ -1,94 +0,0 @@ -# -# Automated Testing Framework (atf) -# -# Copyright (c) 2007 The NetBSD Foundation, Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -atf_tps_writer_info() -{ - class=${1}; shift - echo "info: ${class}, $*" -} - -info_start_hook() -{ - default_info_start_hook "${@}" -} - -default_info_start_hook() -{ - atf_tps_writer_info "atf.version" $(atf-version | head -n 1) - - atf_tps_writer_info "tests.root" $(pwd) - - atf_tps_writer_info "time.start" $(date) - - atf_tps_writer_info "uname.sysname" $(uname -s) - atf_tps_writer_info "uname.nodename" $(uname -n) - atf_tps_writer_info "uname.release" $(uname -r) - atf_tps_writer_info "uname.version" $(uname -v) - atf_tps_writer_info "uname.machine" $(uname -m) - - # Add all the environment variables to the report. We have to be - # careful with those that span over multiple lines; otherwise their - # values could be printed as multiple different variables (one per - # line), which is incorrect. - oldifs="${IFS}" - IFS=' -' - set -- $(env) - val=${1}; shift - while [ ${#} -gt 0 ]; do - if echo "${1}" | grep '^[a-zA-Z0-0_][a-zA-Z0-9_]*=' >/dev/null; then - atf_tps_writer_info "env" "${val}" - val="${1}" - else - val="${val} ${1}" - fi - shift - done - atf_tps_writer_info "env" "${val}" - IFS="${oldifs}" -} - -info_end_hook() -{ - default_info_end_hook "${@}" -} - -default_info_end_hook() -{ - atf_tps_writer_info "time.end" $(date) -} - -sitehooks=$(atf-config -t atf_confdir)/atf-run.hooks -userhooks=${HOME}/.atf/atf-run.hooks -[ -f ${sitehooks} ] && . ${sitehooks} -[ -f ${userhooks} ] && . ${userhooks} - -eval ${1} - -# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/tools/signals.cpp b/tools/signals.cpp deleted file mode 100644 index 0e731de..0000000 --- a/tools/signals.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if defined(HAVE_CONFIG_H) -#include "bconfig.h" -#endif - -extern "C" { -#include <signal.h> -#include <unistd.h> -} - -#include <cerrno> -#include <cstdlib> - -#include "exceptions.hpp" -#include "signals.hpp" - -namespace impl = tools::signals; -#define IMPL_NAME "tools::signals" - -const int impl::last_signo = LAST_SIGNO; - -// ------------------------------------------------------------------------ -// The "signal_holder" class. -// ------------------------------------------------------------------------ - -namespace { - -static bool happened[LAST_SIGNO + 1]; - -static -void -holder_handler(const int signo) -{ - happened[signo] = true; -} - -} // anonymous namespace - -impl::signal_holder::signal_holder(const int signo) : - m_signo(signo), - m_sp(NULL) -{ - happened[signo] = false; - m_sp = new signal_programmer(m_signo, holder_handler); -} - -impl::signal_holder::~signal_holder(void) -{ - if (m_sp != NULL) - delete m_sp; - - if (happened[m_signo]) - ::kill(::getpid(), m_signo); -} - -void -impl::signal_holder::process(void) -{ - if (happened[m_signo]) { - delete m_sp; - m_sp = NULL; - happened[m_signo] = false; - ::kill(::getpid(), m_signo); - m_sp = new signal_programmer(m_signo, holder_handler); - } -} - -// ------------------------------------------------------------------------ -// The "signal_programmer" class. -// ------------------------------------------------------------------------ - -impl::signal_programmer::signal_programmer(const int signo, const handler h) : - m_signo(signo), - m_handler(h), - m_programmed(false) -{ - struct ::sigaction sa; - - sa.sa_handler = m_handler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - - if (::sigaction(m_signo, &sa, &m_oldsa) == -1) - throw tools::system_error(IMPL_NAME, "Could not install handler for " - "signal", errno); - m_programmed = true; -} - -impl::signal_programmer::~signal_programmer(void) -{ - unprogram(); -} - -void -impl::signal_programmer::unprogram(void) -{ - if (m_programmed) { - if (::sigaction(m_signo, &m_oldsa, NULL) == -1) - std::abort(); - m_programmed = false; - } -} - -// ------------------------------------------------------------------------ -// Free functions. -// ------------------------------------------------------------------------ - -void -impl::reset(const int signo) -{ - struct ::sigaction sa; - - sa.sa_handler = SIG_DFL; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - - (void)::sigaction(signo, &sa, NULL); -} diff --git a/tools/signals.hpp b/tools/signals.hpp deleted file mode 100644 index 549a2ca..0000000 --- a/tools/signals.hpp +++ /dev/null @@ -1,92 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if !defined(TOOLS_SIGNALS_HPP) -#define TOOLS_SIGNALS_HPP - -extern "C" { -#include <signal.h> -} - -namespace tools { -namespace signals { - -extern const int last_signo; -typedef void (*handler)(const int); - -class signal_programmer; - -// ------------------------------------------------------------------------ -// The "signal_holder" class. -// ------------------------------------------------------------------------ - -// -// A RAII model to hold a signal while the object is alive. -// -class signal_holder { - const int m_signo; - signal_programmer* m_sp; - -public: - signal_holder(const int); - ~signal_holder(void); - - void process(void); -}; - -// ------------------------------------------------------------------------ -// The "signal_programmer" class. -// ------------------------------------------------------------------------ - -// -// A RAII model to program a signal while the object is alive. -// -class signal_programmer { - const int m_signo; - const handler m_handler; - bool m_programmed; - struct sigaction m_oldsa; - -public: - signal_programmer(const int, const handler); - ~signal_programmer(void); - - void unprogram(void); -}; - -// ------------------------------------------------------------------------ -// Free functions. -// ------------------------------------------------------------------------ - -void reset(const int); - -} // namespace signals -} // namespace tools - -#endif // !defined(TOOLS_SIGNALS_HPP) diff --git a/tools/signals_test.cpp b/tools/signals_test.cpp deleted file mode 100644 index aa6a8e5..0000000 --- a/tools/signals_test.cpp +++ /dev/null @@ -1,275 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2008 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -extern "C" { -#include <sys/types.h> -#include <signal.h> -#include <unistd.h> -} - -#include <cerrno> -#include <cstdlib> -#include <iostream> - -#include <atf-c++.hpp> - -#include "defs.hpp" -#include "exceptions.hpp" -#include "process.hpp" -#include "signals.hpp" - -// ------------------------------------------------------------------------ -// Auxiliary functions. -// ------------------------------------------------------------------------ - -namespace sigusr1 { - static bool happened = false; - - static - void - handler(int signo ATF_DEFS_ATTRIBUTE_UNUSED) - { - happened = true; - } - - static - void - program(void) - { - struct sigaction sa; - sa.sa_handler = handler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - if (::sigaction(SIGUSR1, &sa, NULL) == -1) - throw tools::system_error("sigusr1::program", - "sigaction(2) failed", errno); - } -} // namespace sigusr1 - -namespace sigusr1_2 { - static bool happened = false; - - static - void - handler(int signo ATF_DEFS_ATTRIBUTE_UNUSED) - { - happened = true; - } -} // namespace sigusr1_2 - -// ------------------------------------------------------------------------ -// Tests for the "signal_holder" class. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(signal_holder_preserve); -ATF_TEST_CASE_HEAD(signal_holder_preserve) -{ - set_md_var("descr", "Tests that signal_holder preserves the original " - "signal handler and restores it upon destruction"); -} -ATF_TEST_CASE_BODY(signal_holder_preserve) -{ - using tools::signals::signal_holder; - - sigusr1::program(); - - sigusr1::happened = false; - ::kill(::getpid(), SIGUSR1); - ATF_REQUIRE(sigusr1::happened); - - { - signal_holder hld(SIGUSR1); - ::kill(::getpid(), SIGUSR1); - } - - sigusr1::happened = false; - ::kill(::getpid(), SIGUSR1); - ATF_REQUIRE(sigusr1::happened); -} - -ATF_TEST_CASE(signal_holder_destructor); -ATF_TEST_CASE_HEAD(signal_holder_destructor) -{ - set_md_var("descr", "Tests that signal_holder processes a pending " - "signal upon destruction"); -} -ATF_TEST_CASE_BODY(signal_holder_destructor) -{ - using tools::signals::signal_holder; - - sigusr1::program(); - - sigusr1::happened = false; - ::kill(::getpid(), SIGUSR1); - ATF_REQUIRE(sigusr1::happened); - - { - signal_holder hld(SIGUSR1); - - sigusr1::happened = false; - ::kill(::getpid(), SIGUSR1); - ATF_REQUIRE(!sigusr1::happened); - } - ATF_REQUIRE(sigusr1::happened); -} - -ATF_TEST_CASE(signal_holder_process); -ATF_TEST_CASE_HEAD(signal_holder_process) -{ - set_md_var("descr", "Tests that signal_holder's process method works " - "to process a delayed signal explicitly"); -} -ATF_TEST_CASE_BODY(signal_holder_process) -{ - using tools::signals::signal_holder; - - sigusr1::program(); - - sigusr1::happened = false; - ::kill(::getpid(), SIGUSR1); - ATF_REQUIRE(sigusr1::happened); - - { - signal_holder hld(SIGUSR1); - - sigusr1::happened = false; - ::kill(::getpid(), SIGUSR1); - ATF_REQUIRE(!sigusr1::happened); - - hld.process(); - ATF_REQUIRE(sigusr1::happened); - - sigusr1::happened = false; - } - ATF_REQUIRE(!sigusr1::happened); -} - -// ------------------------------------------------------------------------ -// Tests for the "signal_programmer" class. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(signal_programmer_program); -ATF_TEST_CASE_HEAD(signal_programmer_program) -{ - set_md_var("descr", "Tests that signal_programmer correctly installs a " - "handler"); -} -ATF_TEST_CASE_BODY(signal_programmer_program) -{ - using tools::signals::signal_programmer; - - signal_programmer sp(SIGUSR1, sigusr1_2::handler); - - sigusr1_2::happened = false; - ::kill(::getpid(), SIGUSR1); - ATF_REQUIRE(sigusr1_2::happened); -} - -ATF_TEST_CASE(signal_programmer_preserve); -ATF_TEST_CASE_HEAD(signal_programmer_preserve) -{ - set_md_var("descr", "Tests that signal_programmer uninstalls the " - "handler during destruction"); -} -ATF_TEST_CASE_BODY(signal_programmer_preserve) -{ - using tools::signals::signal_programmer; - - sigusr1::program(); - sigusr1::happened = false; - - { - signal_programmer sp(SIGUSR1, sigusr1_2::handler); - - sigusr1_2::happened = false; - ::kill(::getpid(), SIGUSR1); - ATF_REQUIRE(sigusr1_2::happened); - } - - ATF_REQUIRE(!sigusr1::happened); - ::kill(::getpid(), SIGUSR1); - ATF_REQUIRE(sigusr1::happened); -} - -// ------------------------------------------------------------------------ -// Tests cases for the free functions. -// ------------------------------------------------------------------------ - -static -void -reset_child(void *v ATF_DEFS_ATTRIBUTE_UNUSED) -{ - sigusr1::program(); - - sigusr1::happened = false; - tools::signals::reset(SIGUSR1); - kill(::getpid(), SIGUSR1); - - if (sigusr1::happened) { - std::cerr << "Signal was not resetted correctly\n"; - std::abort(); - } else { - std::exit(EXIT_SUCCESS); - } -} - -ATF_TEST_CASE(reset); -ATF_TEST_CASE_HEAD(reset) -{ - set_md_var("descr", "Tests the reset function"); -} -ATF_TEST_CASE_BODY(reset) -{ - tools::process::child c = - tools::process::fork(reset_child, tools::process::stream_inherit(), - tools::process::stream_inherit(), NULL); - - const tools::process::status s = c.wait(); - ATF_REQUIRE(s.exited() || s.signaled()); - ATF_REQUIRE(!s.signaled() || s.termsig() == SIGUSR1); -} - -// ------------------------------------------------------------------------ -// Main. -// ------------------------------------------------------------------------ - -ATF_INIT_TEST_CASES(tcs) -{ - // Add the tests for the "signal_holder" class. - ATF_ADD_TEST_CASE(tcs, signal_holder_preserve); - ATF_ADD_TEST_CASE(tcs, signal_holder_destructor); - ATF_ADD_TEST_CASE(tcs, signal_holder_process); - - // Add the tests for the "signal_programmer" class. - ATF_ADD_TEST_CASE(tcs, signal_programmer_program); - ATF_ADD_TEST_CASE(tcs, signal_programmer_preserve); - - // Add the test cases for the free functions. - ATF_ADD_TEST_CASE(tcs, reset); -} diff --git a/tools/test-program.cpp b/tools/test-program.cpp deleted file mode 100644 index 91ad78a..0000000 --- a/tools/test-program.cpp +++ /dev/null @@ -1,790 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -extern "C" { -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/time.h> - -#include <fcntl.h> -#include <signal.h> -#include <unistd.h> -} - -#include <cassert> -#include <cerrno> -#include <cstdlib> -#include <cstring> -#include <fstream> -#include <iostream> - -#include "config_file.hpp" -#include "defs.hpp" -#include "env.hpp" -#include "fs.hpp" -#include "io.hpp" -#include "parser.hpp" -#include "process.hpp" -#include "requirements.hpp" -#include "signals.hpp" -#include "test-program.hpp" -#include "text.hpp" -#include "timers.hpp" -#include "user.hpp" - -namespace impl = tools::test_program; -namespace detail = tools::test_program::detail; - -namespace { - -typedef std::map< std::string, std::string > vars_map; - -static void -check_stream(std::ostream& os) -{ - // 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. - if (os.bad()) { - if (errno == EINTR) - os.clear(); - else - throw std::runtime_error("Failed"); - } -} - -namespace atf_tp { - -static const tools::parser::token_type eof_type = 0; -static const tools::parser::token_type nl_type = 1; -static const tools::parser::token_type text_type = 2; -static const tools::parser::token_type colon_type = 3; -static const tools::parser::token_type dblquote_type = 4; - -class tokenizer : public tools::parser::tokenizer< std::istream > { -public: - tokenizer(std::istream& is, size_t curline) : - tools::parser::tokenizer< std::istream > - (is, true, eof_type, nl_type, text_type, curline) - { - add_delim(':', colon_type); - add_quote('"', dblquote_type); - } -}; - -} // namespace atf_tp - -class metadata_reader : public detail::atf_tp_reader { - impl::test_cases_map m_tcs; - - void got_tc(const std::string& ident, const vars_map& props) - { - if (m_tcs.find(ident) != m_tcs.end()) - throw(std::runtime_error("Duplicate test case " + ident + - " in test program")); - m_tcs[ident] = props; - - if (m_tcs[ident].find("has.cleanup") == m_tcs[ident].end()) - m_tcs[ident].insert(std::make_pair("has.cleanup", "false")); - - if (m_tcs[ident].find("timeout") == m_tcs[ident].end()) - m_tcs[ident].insert(std::make_pair("timeout", "300")); - } - -public: - metadata_reader(std::istream& is) : - detail::atf_tp_reader(is) - { - } - - const impl::test_cases_map& - get_tcs(void) - const - { - return m_tcs; - } -}; - -struct get_metadata_params { - const tools::fs::path& executable; - const vars_map& config; - - get_metadata_params(const tools::fs::path& p_executable, - const vars_map& p_config) : - executable(p_executable), - config(p_config) - { - } -}; - -struct test_case_params { - const tools::fs::path& executable; - const std::string& test_case_name; - const std::string& test_case_part; - const vars_map& metadata; - const vars_map& config; - const tools::fs::path& resfile; - const tools::fs::path& workdir; - - test_case_params(const tools::fs::path& p_executable, - const std::string& p_test_case_name, - const std::string& p_test_case_part, - const vars_map& p_metadata, - const vars_map& p_config, - const tools::fs::path& p_resfile, - const tools::fs::path& p_workdir) : - executable(p_executable), - test_case_name(p_test_case_name), - test_case_part(p_test_case_part), - metadata(p_metadata), - config(p_config), - resfile(p_resfile), - workdir(p_workdir) - { - } -}; - -static -std::string -generate_timestamp(void) -{ - struct timeval tv; - if (gettimeofday(&tv, NULL) == -1) - return "0.0"; - - char buf[32]; - const int len = snprintf(buf, sizeof(buf), "%ld.%ld", - static_cast< long >(tv.tv_sec), - static_cast< long >(tv.tv_usec)); - if (len >= static_cast< int >(sizeof(buf)) || len < 0) - return "0.0"; - else - return buf; -} - -static -void -append_to_vector(std::vector< std::string >& v1, - const std::vector< std::string >& v2) -{ - std::copy(v2.begin(), v2.end(), - std::back_insert_iterator< std::vector< std::string > >(v1)); -} - -static -char** -vector_to_argv(const std::vector< std::string >& v) -{ - char** argv = new char*[v.size() + 1]; - for (std::vector< std::string >::size_type i = 0; i < v.size(); i++) { - argv[i] = strdup(v[i].c_str()); - } - argv[v.size()] = NULL; - return argv; -} - -static -void -exec_or_exit(const tools::fs::path& executable, - const std::vector< std::string >& argv) -{ - // This leaks memory in case of a failure, but it is OK. Exiting will - // do the necessary cleanup. - char* const* native_argv = vector_to_argv(argv); - - ::execv(executable.c_str(), native_argv); - - const std::string message = "Failed to execute '" + executable.str() + - "': " + std::strerror(errno) + "\n"; - if (::write(STDERR_FILENO, message.c_str(), message.length()) == -1) - std::abort(); - std::exit(EXIT_FAILURE); -} - -static -std::vector< std::string > -config_to_args(const vars_map& config) -{ - std::vector< std::string > args; - - for (vars_map::const_iterator iter = config.begin(); - iter != config.end(); iter++) - args.push_back("-v" + (*iter).first + "=" + (*iter).second); - - return args; -} - -static -void -silence_stdin(void) -{ - ::close(STDIN_FILENO); - int fd = ::open("/dev/null", O_RDONLY); - if (fd == -1) - throw std::runtime_error("Could not open /dev/null"); - assert(fd == STDIN_FILENO); -} - -static -void -prepare_child(const tools::fs::path& workdir) -{ - const int ret = ::setpgid(::getpid(), 0); - assert(ret != -1); - - ::umask(S_IWGRP | S_IWOTH); - - for (int i = 1; i <= tools::signals::last_signo; i++) - tools::signals::reset(i); - - tools::env::set("HOME", workdir.str()); - tools::env::unset("LANG"); - tools::env::unset("LC_ALL"); - tools::env::unset("LC_COLLATE"); - tools::env::unset("LC_CTYPE"); - tools::env::unset("LC_MESSAGES"); - tools::env::unset("LC_MONETARY"); - tools::env::unset("LC_NUMERIC"); - tools::env::unset("LC_TIME"); - tools::env::set("TZ", "UTC"); - - tools::env::set("__RUNNING_INSIDE_ATF_RUN", "internal-yes-value"); - - tools::fs::change_directory(workdir); - - silence_stdin(); -} - -static -void -get_metadata_child(void* raw_params) -{ - const get_metadata_params* params = - static_cast< const get_metadata_params* >(raw_params); - - std::vector< std::string > argv; - argv.push_back(params->executable.leaf_name()); - argv.push_back("-l"); - argv.push_back("-s" + params->executable.branch_path().str()); - append_to_vector(argv, config_to_args(params->config)); - - exec_or_exit(params->executable, argv); -} - -void -run_test_case_child(void* raw_params) -{ - const test_case_params* params = - static_cast< const test_case_params* >(raw_params); - - const std::pair< int, int > user = tools::get_required_user( - params->metadata, params->config); - if (user.first != -1 && user.second != -1) - tools::user::drop_privileges(user); - - // The input 'tp' parameter may be relative and become invalid once - // we change the current working directory. - const tools::fs::path absolute_executable = params->executable.to_absolute(); - - // 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). - std::vector< std::string > argv; - argv.push_back(absolute_executable.leaf_name()); - argv.push_back("-r" + params->resfile.str()); - argv.push_back("-s" + absolute_executable.branch_path().str()); - append_to_vector(argv, config_to_args(params->config)); - argv.push_back(params->test_case_name + ":" + params->test_case_part); - - prepare_child(params->workdir); - exec_or_exit(absolute_executable, argv); -} - -static void -tokenize_result(const std::string& line, std::string& out_state, - std::string& out_arg, std::string& out_reason) -{ - const std::string::size_type pos = line.find_first_of(":("); - if (pos == std::string::npos) { - out_state = line; - out_arg = ""; - out_reason = ""; - } else if (line[pos] == ':') { - out_state = line.substr(0, pos); - out_arg = ""; - out_reason = tools::text::trim(line.substr(pos + 1)); - } else if (line[pos] == '(') { - const std::string::size_type pos2 = line.find("):", pos); - if (pos2 == std::string::npos) - throw std::runtime_error("Invalid test case result '" + line + - "': unclosed optional argument"); - out_state = line.substr(0, pos); - out_arg = line.substr(pos + 1, pos2 - pos - 1); - out_reason = tools::text::trim(line.substr(pos2 + 2)); - } else - std::abort(); -} - -static impl::test_case_result -handle_result(const std::string& state, const std::string& arg, - const std::string& reason) -{ - assert(state == "passed"); - - if (!arg.empty() || !reason.empty()) - throw std::runtime_error("The test case result '" + state + "' cannot " - "be accompanied by a reason nor an expected value"); - - return impl::test_case_result(state, -1, reason); -} - -static impl::test_case_result -handle_result_with_reason(const std::string& state, const std::string& arg, - const std::string& reason) -{ - assert(state == "expected_death" || state == "expected_failure" || - state == "expected_timeout" || state == "failed" || state == "skipped"); - - if (!arg.empty() || reason.empty()) - throw std::runtime_error("The test case result '" + state + "' must " - "be accompanied by a reason but not by an expected value"); - - return impl::test_case_result(state, -1, reason); -} - -static impl::test_case_result -handle_result_with_reason_and_arg(const std::string& state, - const std::string& arg, - const std::string& reason) -{ - assert(state == "expected_exit" || state == "expected_signal"); - - if (reason.empty()) - throw std::runtime_error("The test case result '" + state + "' must " - "be accompanied by a reason"); - - int value; - if (arg.empty()) { - value = -1; - } else { - try { - value = tools::text::to_type< int >(arg); - } catch (const std::runtime_error&) { - throw std::runtime_error("The value '" + arg + "' passed to the '" + - state + "' state must be an integer"); - } - } - - return impl::test_case_result(state, value, reason); -} - -} // anonymous namespace - -detail::atf_tp_reader::atf_tp_reader(std::istream& is) : - m_is(is) -{ -} - -detail::atf_tp_reader::~atf_tp_reader(void) -{ -} - -void -detail::atf_tp_reader::got_tc( - const std::string& ident ATF_DEFS_ATTRIBUTE_UNUSED, - const std::map< std::string, std::string >& md ATF_DEFS_ATTRIBUTE_UNUSED) -{ -} - -void -detail::atf_tp_reader::got_eof(void) -{ -} - -void -detail::atf_tp_reader::validate_and_insert(const std::string& name, - const std::string& value, const size_t lineno, - std::map< std::string, std::string >& md) -{ - using tools::parser::parse_error; - - if (value.empty()) - throw parse_error(lineno, "The value for '" + name +"' cannot be " - "empty"); - - const std::string ident_regex = "^[_A-Za-z0-9]+$"; - const std::string integer_regex = "^[0-9]+$"; - - if (name == "descr") { - // Any non-empty value is valid. - } else if (name == "has.cleanup") { - try { - (void)tools::text::to_bool(value); - } catch (const std::runtime_error&) { - throw parse_error(lineno, "The has.cleanup property requires a" - " boolean value"); - } - } else if (name == "ident") { - if (!tools::text::match(value, ident_regex)) - throw parse_error(lineno, "The identifier must match " + - ident_regex + "; was '" + value + "'"); - } 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 { - (void)tools::text::to_bytes(value); - } catch (const std::runtime_error&) { - throw parse_error(lineno, "The require.memory property requires an " - "integer value representing an amount of bytes"); - } - } else if (name == "require.progs") { - } else if (name == "require.user") { - } else if (name == "timeout") { - if (!tools::text::match(value, integer_regex)) - throw parse_error(lineno, "The timeout property requires an integer" - " value"); - } else if (name == "use.fs") { - // Deprecated; ignore it. - } else if (name.size() > 2 && name[0] == 'X' && name[1] == '-') { - // Any non-empty value is valid. - } else { - throw parse_error(lineno, "Unknown property '" + name + "'"); - } - - md.insert(std::make_pair(name, value)); -} - -void -detail::atf_tp_reader::read(void) -{ - using tools::parser::parse_error; - using namespace atf_tp; - - std::pair< size_t, tools::parser::headers_map > hml = - tools::parser::read_headers(m_is, 1); - tools::parser::validate_content_type(hml.second, - "application/X-atf-tp", 1); - - tokenizer tkz(m_is, hml.first); - tools::parser::parser< tokenizer > p(tkz); - - try { - tools::parser::token t = p.expect(text_type, "property name"); - if (t.text() != "ident") - throw parse_error(t.lineno(), "First property of a test case " - "must be 'ident'"); - - std::map< std::string, std::string > props; - do { - const std::string name = t.text(); - t = p.expect(colon_type, "`:'"); - const std::string value = tools::text::trim(p.rest_of_line()); - t = p.expect(nl_type, "new line"); - validate_and_insert(name, value, t.lineno(), props); - - t = p.expect(eof_type, nl_type, text_type, "property name, new " - "line or eof"); - if (t.type() == nl_type || t.type() == eof_type) { - const std::map< std::string, std::string >::const_iterator - iter = props.find("ident"); - if (iter == props.end()) - throw parse_error(t.lineno(), "Test case definition did " - "not define an 'ident' property"); - ATF_PARSER_CALLBACK(p, got_tc((*iter).second, props)); - props.clear(); - - if (t.type() == nl_type) { - t = p.expect(text_type, "property name"); - if (t.text() != "ident") - throw parse_error(t.lineno(), "First property of a " - "test case must be 'ident'"); - } - } - } while (t.type() != eof_type); - ATF_PARSER_CALLBACK(p, got_eof()); - } catch (const parse_error& pe) { - p.add_error(pe); - p.reset(nl_type); - } -} - -impl::test_case_result -detail::parse_test_case_result(const std::string& line) -{ - std::string state, arg, reason; - tokenize_result(line, state, arg, reason); - - if (state == "expected_death") - return handle_result_with_reason(state, arg, reason); - else if (state.compare(0, 13, "expected_exit") == 0) - return handle_result_with_reason_and_arg(state, arg, reason); - else if (state.compare(0, 16, "expected_failure") == 0) - return handle_result_with_reason(state, arg, reason); - else if (state.compare(0, 15, "expected_signal") == 0) - return handle_result_with_reason_and_arg(state, arg, reason); - else if (state.compare(0, 16, "expected_timeout") == 0) - return handle_result_with_reason(state, arg, reason); - else if (state == "failed") - return handle_result_with_reason(state, arg, reason); - else if (state == "passed") - return handle_result(state, arg, reason); - else if (state == "skipped") - return handle_result_with_reason(state, arg, reason); - else - throw std::runtime_error("Unknown test case result type in: " + line); -} - -impl::atf_tps_writer::atf_tps_writer(std::ostream& os) : - m_os(os) -{ - tools::parser::headers_map hm; - tools::parser::attrs_map ct_attrs; - ct_attrs["version"] = "3"; - hm["Content-Type"] = - tools::parser::header_entry("Content-Type", "application/X-atf-tps", - ct_attrs); - tools::parser::write_headers(hm, m_os); -} - -void -impl::atf_tps_writer::info(const std::string& what, const std::string& val) -{ - m_os << "info: " << what << ", " << val << "\n"; - m_os.flush(); -} - -void -impl::atf_tps_writer::ntps(size_t p_ntps) -{ - m_os << "tps-count: " << p_ntps << "\n"; - m_os.flush(); -} - -void -impl::atf_tps_writer::start_tp(const std::string& tp, size_t ntcs) -{ - m_tpname = tp; - m_os << "tp-start: " << generate_timestamp() << ", " << tp << ", " - << ntcs << "\n"; - m_os.flush(); -} - -void -impl::atf_tps_writer::end_tp(const std::string& reason) -{ - assert(reason.find('\n') == std::string::npos); - if (reason.empty()) - m_os << "tp-end: " << generate_timestamp() << ", " << m_tpname << "\n"; - else - m_os << "tp-end: " << generate_timestamp() << ", " << m_tpname - << ", " << reason << "\n"; - m_os.flush(); -} - -void -impl::atf_tps_writer::start_tc(const std::string& tcname) -{ - m_tcname = tcname; - m_os << "tc-start: " << generate_timestamp() << ", " << tcname << "\n"; - m_os.flush(); -} - -void -impl::atf_tps_writer::stdout_tc(const std::string& line) -{ - m_os << "tc-so:" << line << "\n"; - check_stream(m_os); - m_os.flush(); - check_stream(m_os); -} - -void -impl::atf_tps_writer::stderr_tc(const std::string& line) -{ - m_os << "tc-se:" << line << "\n"; - check_stream(m_os); - m_os.flush(); - check_stream(m_os); -} - -void -impl::atf_tps_writer::end_tc(const std::string& state, - const std::string& reason) -{ - std::string str = ", " + m_tcname + ", " + state; - if (!reason.empty()) - str += ", " + reason; - m_os << "tc-end: " << generate_timestamp() << str << "\n"; - m_os.flush(); -} - -impl::metadata -impl::get_metadata(const tools::fs::path& executable, - const vars_map& config) -{ - get_metadata_params params(executable, config); - tools::process::child child = - tools::process::fork(get_metadata_child, - tools::process::stream_capture(), - tools::process::stream_inherit(), - static_cast< void * >(¶ms)); - - tools::io::pistream outin(child.stdout_fd()); - - metadata_reader parser(outin); - parser.read(); - - const tools::process::status status = child.wait(); - if (!status.exited() || status.exitstatus() != EXIT_SUCCESS) - throw tools::parser::format_error("Test program returned failure " - "exit status for test case list"); - - return metadata(parser.get_tcs()); -} - -impl::test_case_result -impl::read_test_case_result(const tools::fs::path& results_path) -{ - std::ifstream results_file(results_path.c_str()); - if (!results_file) - throw std::runtime_error("Failed to open " + results_path.str()); - - std::string line, extra_line; - std::getline(results_file, line); - if (!results_file.good()) - throw std::runtime_error("Results file is empty"); - - while (std::getline(results_file, extra_line).good()) - line += "<<NEWLINE UNEXPECTED>>" + extra_line; - - results_file.close(); - - return detail::parse_test_case_result(line); -} - -namespace { - -static volatile bool terminate_poll; - -static void -sigchld_handler(const int signo ATF_DEFS_ATTRIBUTE_UNUSED) -{ - terminate_poll = true; -} - -class child_muxer : public tools::io::muxer { - impl::atf_tps_writer& m_writer; - - void - line_callback(const size_t index, const std::string& line) - { - switch (index) { - case 0: m_writer.stdout_tc(line); break; - case 1: m_writer.stderr_tc(line); break; - default: std::abort(); - } - } - -public: - child_muxer(const int* fds, const size_t nfds, - impl::atf_tps_writer& writer) : - muxer(fds, nfds), - m_writer(writer) - { - } -}; - -} // anonymous namespace - -std::pair< std::string, tools::process::status > -impl::run_test_case(const tools::fs::path& executable, - const std::string& test_case_name, - const std::string& test_case_part, - const vars_map& metadata, - const vars_map& config, - const tools::fs::path& resfile, - const tools::fs::path& workdir, - atf_tps_writer& writer) -{ - // TODO: Capture termination signals and deliver them to the subprocess - // instead. Or maybe do something else; think about it. - - test_case_params params(executable, test_case_name, test_case_part, - metadata, config, resfile, workdir); - tools::process::child child = - tools::process::fork(run_test_case_child, - tools::process::stream_capture(), - tools::process::stream_capture(), - static_cast< void * >(¶ms)); - - terminate_poll = false; - - const vars_map::const_iterator iter = metadata.find("timeout"); - assert(iter != metadata.end()); - const unsigned int timeout = - tools::text::to_type< unsigned int >((*iter).second); - const pid_t child_pid = child.pid(); - - // Get the input stream of stdout and stderr. - tools::io::file_handle outfh = child.stdout_fd(); - tools::io::file_handle errfh = child.stderr_fd(); - - bool timed_out = false; - - // Process the test case's output and multiplex it into our output - // stream as we read it. - int fds[2] = {outfh.get(), errfh.get()}; - child_muxer mux(fds, 2, writer); - try { - timers::child_timer timeout_timer(timeout, child_pid, terminate_poll); - signals::signal_programmer sigchld(SIGCHLD, sigchld_handler); - mux.mux(terminate_poll); - timed_out = timeout_timer.fired(); - } catch (...) { - std::abort(); - } - - ::killpg(child_pid, SIGKILL); - mux.flush(); - tools::process::status status = child.wait(); - - std::string reason; - - 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. - reason = "Test case timed out after " + tools::text::to_string(timeout) + - " " + (timeout == 1 ? "second" : "seconds"); - } - - return std::make_pair(reason, status); -} diff --git a/tools/test-program.hpp b/tools/test-program.hpp deleted file mode 100644 index f2f1972..0000000 --- a/tools/test-program.hpp +++ /dev/null @@ -1,157 +0,0 @@ -// -// 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. -// - -#if !defined(TOOLS_TEST_PROGRAM_HPP) -#define TOOLS_TEST_PROGRAM_HPP - -#include <map> -#include <string> - -#include "fs.hpp" -#include "process.hpp" - -namespace tools { -namespace test_program { - -struct test_case_result { - std::string m_state; - int m_value; - std::string m_reason; - -public: - test_case_result(void) : - m_state("UNINITIALIZED"), - m_value(-1), - m_reason("") - { - } - - test_case_result(const std::string& p_state, const int p_value, - const std::string& p_reason) : - m_state(p_state), - m_value(p_value), - m_reason(p_reason) - { - } - - const std::string& - state(void) const - { - return m_state; - } - - int - value(void) const - { - return m_value; - } - - const std::string& - reason(void) const - { - return m_reason; - } -}; - -namespace detail { - -class atf_tp_reader { - std::istream& m_is; - - void validate_and_insert(const std::string&, const std::string&, - const size_t, - std::map< std::string, std::string >&); - -protected: - virtual void got_tc(const std::string&, - const std::map< std::string, std::string >&); - virtual void got_eof(void); - -public: - atf_tp_reader(std::istream&); - virtual ~atf_tp_reader(void); - - void read(void); -}; - -test_case_result parse_test_case_result(const std::string&); - -} // namespace detail - -class atf_tps_writer { - std::ostream& m_os; - - std::string m_tpname, m_tcname; - -public: - atf_tps_writer(std::ostream&); - - void info(const std::string&, const std::string&); - void ntps(size_t); - - void start_tp(const std::string&, size_t); - void end_tp(const std::string&); - - void start_tc(const std::string&); - void stdout_tc(const std::string&); - void stderr_tc(const std::string&); - void end_tc(const std::string&, const std::string&); -}; - -typedef std::map< std::string, std::map< std::string, std::string > > - test_cases_map; - -struct metadata { - test_cases_map test_cases; - - metadata(void) - { - } - - metadata(const test_cases_map& p_test_cases) : - test_cases(p_test_cases) - { - } -}; - -class atf_tps_writer; - -metadata get_metadata(const tools::fs::path&, - const std::map< std::string, std::string >&); -test_case_result read_test_case_result(const tools::fs::path&); -std::pair< std::string, tools::process::status > run_test_case( - const tools::fs::path&, const std::string&, const std::string&, - const std::map< std::string, std::string >&, - const std::map< std::string, std::string >&, - const tools::fs::path&, const tools::fs::path&, atf_tps_writer&); - -} // namespace test_program -} // namespace tools - -#endif // !defined(TOOLS_TEST_PROGRAM_HPP) diff --git a/tools/test_helpers.hpp b/tools/test_helpers.hpp deleted file mode 100644 index 3ac92d0..0000000 --- a/tools/test_helpers.hpp +++ /dev/null @@ -1,116 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2009 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. -// - -#if defined(TOOLS_TEST_HELPERS_H) -# error "Cannot include test_helpers.hpp more than once." -#else -# define TOOLS_TEST_HELPERS_H -#endif - -#include <iostream> -#include <sstream> -#include <utility> - -#include <atf-c++.hpp> - -#include "parser.hpp" -#include "text.hpp" - -namespace test_helpers_detail { - -typedef std::vector< std::string > string_vector; - -template< class Reader > -std::pair< string_vector, string_vector > -do_read(const char* input) -{ - string_vector errors; - - std::istringstream is(input); - Reader reader(is); - try { - reader.read(); - } catch (const tools::parser::parse_errors& pes) { - for (std::vector< tools::parser::parse_error >::const_iterator iter = - pes.begin(); iter != pes.end(); iter++) - errors.push_back(*iter); - } catch (const tools::parser::parse_error& pe) { - ATF_FAIL("Raised a lonely parse error: " + - tools::text::to_string(pe.first) + ": " + pe.second); - } - - return std::make_pair(reader.m_calls, errors); -} - -void -check_equal(const char* expected[], const string_vector& actual) -{ - const char** expected_iter = expected; - string_vector::const_iterator actual_iter = actual.begin(); - - bool equals = true; - while (equals && *expected_iter != NULL && actual_iter != actual.end()) { - if (*expected_iter != *actual_iter) { - equals = false; - } else { - expected_iter++; - actual_iter++; - } - } - if (equals && ((*expected_iter == NULL && actual_iter != actual.end()) || - (*expected_iter != NULL && actual_iter == actual.end()))) - equals = false; - - if (!equals) { - std::cerr << "EXPECTED:\n"; - for (expected_iter = expected; *expected_iter != NULL; expected_iter++) - std::cerr << *expected_iter << "\n"; - - std::cerr << "ACTUAL:\n"; - for (actual_iter = actual.begin(); actual_iter != actual.end(); - actual_iter++) - std::cerr << *actual_iter << "\n"; - - ATF_FAIL("Expected results differ to actual values"); - } -} - -} // namespace test_helpers_detail - -template< class Reader > -void -do_parser_test(const char* input, const char* exp_calls[], - const char* exp_errors[]) -{ - const std::pair< test_helpers_detail::string_vector, - test_helpers_detail::string_vector > - actual = test_helpers_detail::do_read< Reader >(input); - test_helpers_detail::check_equal(exp_calls, actual.first); - test_helpers_detail::check_equal(exp_errors, actual.second); -} diff --git a/tools/test_program_test.cpp b/tools/test_program_test.cpp deleted file mode 100644 index 693790d..0000000 --- a/tools/test_program_test.cpp +++ /dev/null @@ -1,1023 +0,0 @@ -// -// 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. -} diff --git a/tools/tests-results.css b/tools/tests-results.css deleted file mode 100644 index 24fc12c..0000000 --- a/tools/tests-results.css +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Automated Testing Framework (atf) - * - * Copyright (c) 2007 The NetBSD Foundation, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 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. - */ - -body { - margin: 0 0 0 0; -} - -.nobr { - white-space: nowrap; -} - -h1 { - background: black; - color: white; - font-family: Arial; - font-size: 24pt; - padding: 5pt; -} - -h2 { - background: #eeeeee; - font-family: Arial; - font-size: 16pt; - margin-left: 10pt; - margin-right: 10pt; - padding: 3pt; -} - -h3 { - font-family: Arial; - font-size: 12pt; - margin-left: 20pt; - margin-right: 20pt; - padding: 3pt; -} - -p.details { - margin-left: 20pt; - margin-right: 20pt; -} - -p.term { - margin-left: 40pt; - margin-right: 40pt; -} - -pre.so { - margin-left: 40pt; - margin-right: 40pt; -} - -pre.se { - margin-left: 40pt; - margin-right: 40pt; -} - -table.summary { - border-collapse: collapse; - border-color: black; - border-style: solid; - border-width: 1pt; - margin-left: auto; - margin-right: auto; -} - -table.summary th { - background: #aaaadd; - border-style: solid; - border-width: 1pt; - padding: 3pt 6pt 3pt 6pt; -} - -table.summary td { - border-style: solid; - border-width: 1pt; - padding: 3pt 6pt 3pt 6pt; -} - -table.summary td.numeric p { - text-align: right; -} - -table.summary td.numeric-error p { - text-align: right; - color: red; -} - -table.summary td.numeric-warning p { - text-align: right; - color: #aaaa00; -} - -table.summary tr.group { - background: #dddddd; -} - -table.summary tr.entry td p { - margin-left: 10pt; -} - -table.tcs-summary { - border-collapse: collapse; - border-color: black; - border-style: solid; - border-width: 1pt; - margin-left: auto; - margin-right: auto; - width: 80%; -} - -table.tcs-summary td { - border-style: solid; - border-width: 1pt; - padding: 3pt 6pt 3pt 6pt; -} - -table.tcs-summary th { - background: #aaaadd; - border-style: solid; - border-width: 1pt; - padding: 3pt 6pt 3pt 6pt; -} - -table.tcs-summary td.numeric { - width: 1pt; -} - -table.tcs-summary td.numeric p { - text-align: right; -} - -table.tcs-summary td.tp-numeric { - background: #dddddd; - width: 1pt; -} - -table.tcs-summary td.tp-numeric p { - text-align: right; -} - -table.tcs-summary td.tp-id { - background: #dddddd; - font-weight: bold; - width: 1pt; -} - -table.tcs-summary td.tc-id p { - margin-left: 10pt; -} - -table.tcs-summary td.tcr-passed { - background: #aaffaa; - width: 1pt; -} - -table.tcs-summary td.tcr-failed { - background: #ffaaaa; - width: 1pt; -} - -table.tcs-summary td.tcr-skipped { - background: #ffffaa; - width: 1pt; -} - -table.tcs-summary td.tcr-xfail { - background: #ffaaff; - width: 1pt; -} - -table.tcs-summary td.tcr-reason { - width: 100%; -} diff --git a/tools/tests-results.dtd b/tools/tests-results.dtd deleted file mode 100644 index c16f7ed..0000000 --- a/tools/tests-results.dtd +++ /dev/null @@ -1,61 +0,0 @@ -<!-- - ++ Automated Testing Framework (atf) - ++ - ++ Copyright (c) 2007 The NetBSD Foundation, Inc. - ++ All rights reserved. - ++ - ++ Redistribution and use in source and binary forms, with or without - ++ modification, are permitted provided that the following conditions - ++ are met: - ++ 1. Redistributions of source code must retain the above copyright - ++ notice, this list of conditions and the following disclaimer. - ++ 2. Redistributions in binary form must reproduce the above copyright - ++ notice, this list of conditions and the following disclaimer in the - ++ documentation and/or other materials provided with the distribution. - ++ - ++ THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND - ++ CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - ++ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - ++ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - ++ IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY - ++ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - ++ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - ++ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - ++ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - ++ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - ++ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - ++ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - --> - -<!-- TODO(1.0): Set the version of the DTD to 1.0 --> - -<!-- - ++ PUBLIC: -//NetBSD//DTD ATF Tests Results 0.1//EN - ++ URI: http://www.NetBSD.org/XML/atf/tests-results.dtd - --> - -<!ELEMENT tests-results (info*, tp*, info*)> - -<!ELEMENT info (#PCDATA)> -<!ATTLIST info class CDATA #REQUIRED> - -<!ELEMENT tp (tc*, failed?)> -<!ATTLIST tp id ID #REQUIRED> - -<!ELEMENT tc ((so, se)*, (passed, failed, skipped))> -<!ATTLIST tc id NMTOKEN #REQUIRED> - -<!ELEMENT expected_death (#PCDATA)> -<!ELEMENT expected_exit (#PCDATA)> -<!ELEMENT expected_failure (#PCDATA)> -<!ELEMENT expected_signal (#PCDATA)> -<!ELEMENT expected_timeout (#PCDATA)> -<!ELEMENT passed EMPTY> -<!ELEMENT failed (#PCDATA)> -<!ELEMENT skipped (#PCDATA)> -<!ELEMENT so (#PCDATA)> -<!ELEMENT se (#PCDATA)> - -<!ENTITY amp "/"> -<!ENTITY lt "J"> -<!ENTITY gt "L"> diff --git a/tools/tests-results.xsl b/tools/tests-results.xsl deleted file mode 100644 index 91b77c5..0000000 --- a/tools/tests-results.xsl +++ /dev/null @@ -1,564 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<!DOCTYPE xsl:stylesheet [<!ENTITY nbsp " ">]> - -<!-- - ++ Automated Testing Framework (atf) - ++ - ++ Copyright (c) 2007 The NetBSD Foundation, Inc. - ++ All rights reserved. - ++ - ++ Redistribution and use in source and binary forms, with or without - ++ modification, are permitted provided that the following conditions - ++ are met: - ++ 1. Redistributions of source code must retain the above copyright - ++ notice, this list of conditions and the following disclaimer. - ++ 2. Redistributions in binary form must reproduce the above copyright - ++ notice, this list of conditions and the following disclaimer in the - ++ documentation and/or other materials provided with the distribution. - ++ - ++ 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. - --> - -<xsl:stylesheet version="1.0" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> - - <!-- Parameters that can be overriden by the user. --> - <xsl:param name="global.css">tests-results.css</xsl:param> - <xsl:param name="global.title">ATF Tests Results</xsl:param> - - <xsl:variable name="ntps" - select="count(tests-results/tp)" /> - <xsl:variable name="ntps-failed" - select="count(tests-results/tp/failed)" /> - <xsl:variable name="ntcs" - select="count(tests-results/tp/tc)" /> - <xsl:variable name="ntcs-passed" - select="count(tests-results/tp/tc/passed)" /> - <xsl:variable name="ntcs-failed" - select="count(tests-results/tp/tc/failed)" /> - <xsl:variable name="ntcs-skipped" - select="count(tests-results/tp/tc/skipped)" /> - <xsl:variable name="ntcs-xfail" - select="count(tests-results/tp/tc/expected_death) + - count(tests-results/tp/tc/expected_exit) + - count(tests-results/tp/tc/expected_failure) + - count(tests-results/tp/tc/expected_signal) + - count(tests-results/tp/tc/expected_timeout)" /> - - <xsl:template match="/"> - <xsl:copy> - <xsl:apply-templates select="@*|node()" /> - </xsl:copy> - </xsl:template> - - <xsl:template match="tests-results"> - <html xmlns="http://www.w3.org/1999/xhtml"> - <head> - <meta http-equiv="Content-Type" - content="text/html; charset=iso-8859-1" /> - <link rel="stylesheet" type="text/css" href="{$global.css}" /> - - <title><xsl:value-of select="$global.title" /></title> - </head> - - <body> - <h1><xsl:value-of select="$global.title" /></h1> - - <xsl:call-template name="info-top" /> - <xsl:call-template name="tcs-summary" /> - <xsl:if test="$ntcs-failed > 0"> - <xsl:call-template name="failed-tcs-summary" /> - </xsl:if> - <xsl:if test="$ntcs-xfail > 0"> - <xsl:call-template name="xfail-tcs-summary" /> - </xsl:if> - <xsl:if test="$ntcs-skipped > 0"> - <xsl:call-template name="skipped-tcs-summary" /> - </xsl:if> - <xsl:if test="$ntps-failed > 0"> - <xsl:call-template name="failed-tps-summary" /> - </xsl:if> - <xsl:call-template name="info-bottom" /> - - <xsl:apply-templates select="tp" mode="details" /> - </body> - </html> - </xsl:template> - - <xsl:template name="info-top"> - <h2>Execution summary</h2> - - <table class="summary"> - <tr> - <th class="nobr"><p>Item</p></th> - <th class="nobr"><p>Value</p></th> - </tr> - - <tr class="group"> - <td colspan="2"><p>ATF</p></td> - </tr> - <tr class="entry"> - <td><p>Version</p></td> - <td><p><xsl:apply-templates - select="info[@class = 'atf.version']" /></p></td> - </tr> - - <tr class="group"> - <td colspan="2"><p>Timings</p></td> - </tr> - <tr class="entry"> - <td><p>Start time of tests</p></td> - <td><p><xsl:apply-templates - select="info[@class = 'time.start']" /></p></td> - </tr> - <tr class="entry"> - <td><p>End time of tests</p></td> - <td><p><xsl:apply-templates - select="info[@class = 'time.end']" /></p></td> - </tr> - - <tr class="group"> - <td colspan="2"><p>System information</p></td> - </tr> - <tr class="entry"> - <td><p>Host name</p></td> - <td><p><xsl:apply-templates - select="info[@class = 'uname.nodename']" /></p></td> - </tr> - <tr class="entry"> - <td><p>Operating system</p></td> - <td><p><xsl:apply-templates - select="info[@class = 'uname.sysname']" /></p></td> - </tr> - <tr class="entry"> - <td><p>Operating system release</p></td> - <td><p><xsl:apply-templates - select="info[@class = 'uname.release']" /></p></td> - </tr> - <tr class="entry"> - <td><p>Operating system version</p></td> - <td><p><xsl:apply-templates - select="info[@class = 'uname.version']" /></p></td> - </tr> - <tr class="entry"> - <td><p>Platform</p></td> - <td><p><xsl:apply-templates - select="info[@class = 'uname.machine']" /></p></td> - </tr> - - <tr class="group"> - <td colspan="2"><p>Tests results</p></td> - </tr> - <tr class="entry"> - <td><p>Root</p></td> - <td><p><xsl:value-of - select="info[@class = 'tests.root']" /></p></td> - </tr> - <tr class="entry"> - <td><p>Test programs</p></td> - <td class="numeric"><p><xsl:value-of select="$ntps" /></p></td> - </tr> - <tr class="entry"> - <xsl:choose> - <xsl:when test="$ntps-failed > 0"> - <td><p><a href="#failed-tps-summary">Bogus test - programs</a></p></td> - <td class="numeric-error"> - <p><xsl:value-of select="$ntps-failed" /></p> - </td> - </xsl:when> - <xsl:otherwise> - <td><p>Bogus test programs</p></td> - <td class="numeric"> - <p><xsl:value-of select="$ntps-failed" /></p> - </td> - </xsl:otherwise> - </xsl:choose> - </tr> - <tr class="entry"> - <td><p>Test cases</p></td> - <td class="numeric"><p><xsl:value-of select="$ntcs" /></p></td> - </tr> - <tr class="entry"> - <td><p>Passed test cases</p></td> - <td class="numeric"><p><xsl:value-of select="$ntcs-passed" /></p></td> - </tr> - <tr class="entry"> - <xsl:choose> - <xsl:when test="$ntcs-failed > 0"> - <td><p><a href="#failed-tcs-summary">Failed test - cases</a></p></td> - <td class="numeric-error"> - <p><xsl:value-of select="$ntcs-failed" /></p> - </td> - </xsl:when> - <xsl:otherwise> - <td><p>Failed test cases</p></td> - <td class="numeric"> - <p><xsl:value-of select="$ntcs-failed" /></p> - </td> - </xsl:otherwise> - </xsl:choose> - </tr> - <tr class="entry"> - <xsl:choose> - <xsl:when test="$ntcs-xfail > 0"> - <td><p><a href="#xfail-tcs-summary">Expected - failures</a></p></td> - <td class="numeric-warning"> - <p><xsl:value-of select="$ntcs-xfail" /></p> - </td> - </xsl:when> - <xsl:otherwise> - <td><p>Expected failures</p></td> - <td class="numeric"> - <p><xsl:value-of select="$ntcs-xfail" /></p> - </td> - </xsl:otherwise> - </xsl:choose> - </tr> - <tr class="entry"> - <xsl:choose> - <xsl:when test="$ntcs-skipped > 0"> - <td><p><a href="#skipped-tcs-summary">Skipped test - cases</a></p></td> - <td class="numeric-warning"> - <p><xsl:value-of select="$ntcs-skipped" /></p> - </td> - </xsl:when> - <xsl:otherwise> - <td><p>Skipped test cases</p></td> - <td class="numeric"> - <p><xsl:value-of select="$ntcs-skipped" /></p> - </td> - </xsl:otherwise> - </xsl:choose> - </tr> - - <tr class="group"> - <td colspan="2"><p><a href="#execution-details">See more execution - details</a></p></td> - </tr> - </table> - </xsl:template> - - <xsl:template name="info-bottom"> - <a name="execution-details" /> - <h2 id="execution-details">Execution details</h2> - - <h3>Environment variables</h3> - - <ul> - <xsl:apply-templates select="info[@class = 'env']"> - <xsl:sort /> - </xsl:apply-templates> - </ul> - </xsl:template> - - <xsl:template match="info[@class = 'env']"> - <li> - <p><xsl:apply-templates /></p> - </li> - </xsl:template> - - <xsl:template name="tcs-summary"> - <h2>Test cases summary</h2> - - <table class="tcs-summary"> - <tr> - <th class="nobr"><p>Test case</p></th> - <th class="nobr"><p>Result</p></th> - <th class="nobr"><p>Reason</p></th> - <th class="nobr"><p>Duration</p></th> - </tr> - <xsl:apply-templates select="tp" mode="summary"> - <xsl:with-param name="which">all</xsl:with-param> - </xsl:apply-templates> - </table> - </xsl:template> - - <xsl:template name="xfail-tcs-summary"> - <a name="xfail-tcs-summary" /> - <h2 id="xfail-tcs-summary">Expected failures summary</h2> - - <table class="tcs-summary"> - <tr> - <th class="nobr"><p>Test case</p></th> - <th class="nobr"><p>Result</p></th> - <th class="nobr"><p>Reason</p></th> - <th class="nobr"><p>Duration</p></th> - </tr> - <xsl:apply-templates select="tp" mode="summary"> - <xsl:with-param name="which">xfail</xsl:with-param> - </xsl:apply-templates> - </table> - </xsl:template> - - <xsl:template name="failed-tcs-summary"> - <a name="failed-tcs-summary" /> - <h2 id="failed-tcs-summary">Failed test cases summary</h2> - - <table class="tcs-summary"> - <tr> - <th class="nobr"><p>Test case</p></th> - <th class="nobr"><p>Result</p></th> - <th class="nobr"><p>Reason</p></th> - <th class="nobr"><p>Duration</p></th> - </tr> - <xsl:apply-templates select="tp" mode="summary"> - <xsl:with-param name="which">failed</xsl:with-param> - </xsl:apply-templates> - </table> - </xsl:template> - - <xsl:template name="failed-tps-summary"> - <a name="failed-tps-summary" /> - <h2 id="failed-tps-summary">Bogus test programs summary</h2> - - <table class="tcs-summary"> - <tr> - <th class="nobr">Test program</th> - </tr> - <xsl:apply-templates select="tp" mode="summary"> - <xsl:with-param name="which">bogus</xsl:with-param> - </xsl:apply-templates> - </table> - </xsl:template> - - <xsl:template name="skipped-tcs-summary"> - <a name="skipped-tcs-summary" /> - <h2 id="skipped-tcs-summary">Skipped test cases summary</h2> - - <table class="tcs-summary"> - <tr> - <th class="nobr"><p>Test case</p></th> - <th class="nobr"><p>Result</p></th> - <th class="nobr"><p>Reason</p></th> - <th class="nobr"><p>Duration</p></th> - </tr> - <xsl:apply-templates select="tp" mode="summary"> - <xsl:with-param name="which">skipped</xsl:with-param> - </xsl:apply-templates> - </table> - </xsl:template> - - <xsl:template match="tp" mode="summary"> - <xsl:param name="which" /> - - <xsl:variable name="chosen"> - <xsl:choose> - <xsl:when test="$which = 'bogus' and failed">yes</xsl:when> - <xsl:when test="$which = 'passed' and tc/passed">yes</xsl:when> - <xsl:when test="$which = 'failed' and tc/failed">yes</xsl:when> - <xsl:when test="$which = 'xfail' and - tc/expected_death">yes</xsl:when> - <xsl:when test="$which = 'xfail' and - tc/expected_exit">yes</xsl:when> - <xsl:when test="$which = 'xfail' and - tc/expected_failure">yes</xsl:when> - <xsl:when test="$which = 'xfail' and - tc/expected_signal">yes</xsl:when> - <xsl:when test="$which = 'xfail' and - tc/expected_timeout">yes</xsl:when> - <xsl:when test="$which = 'skipped' and tc/skipped">yes</xsl:when> - <xsl:when test="$which = 'all'">yes</xsl:when> - <xsl:otherwise>no</xsl:otherwise> - </xsl:choose> - </xsl:variable> - - <xsl:if test="$chosen = 'yes'"> - <tr> - <td class="tp-id" colspan="3"> - <p><xsl:value-of select="@id" /></p> - </td> - <td class="tp-numeric"> - <p><xsl:value-of select="tp-time" />s</p> - </td> - </tr> - <xsl:if test="$which != 'bogus'"> - <xsl:apply-templates select="tc" mode="summary"> - <xsl:with-param name="which" select="$which" /> - </xsl:apply-templates> - </xsl:if> - </xsl:if> - </xsl:template> - - <xsl:template match="tc" mode="summary"> - <xsl:param name="which" /> - - <xsl:variable name="full-id" - select="concat(translate(../@id, '/', '_'), '_', @id)" /> - - <xsl:variable name="chosen"> - <xsl:choose> - <xsl:when test="$which = 'passed' and ./passed">yes</xsl:when> - <xsl:when test="$which = 'failed' and ./failed">yes</xsl:when> - <xsl:when test="$which = 'xfail' and - ./expected_death">yes</xsl:when> - <xsl:when test="$which = 'xfail' and - ./expected_exit">yes</xsl:when> - <xsl:when test="$which = 'xfail' and - ./expected_failure">yes</xsl:when> - <xsl:when test="$which = 'xfail' and - ./expected_signal">yes</xsl:when> - <xsl:when test="$which = 'xfail' and - ./expected_timeout">yes</xsl:when> - <xsl:when test="$which = 'skipped' and ./skipped">yes</xsl:when> - <xsl:when test="$which = 'all'">yes</xsl:when> - <xsl:otherwise>no</xsl:otherwise> - </xsl:choose> - </xsl:variable> - - <xsl:if test="$chosen = 'yes'"> - <tr> - <td class="tc-id"> - <xsl:choose> - <xsl:when test="expected_death|expected_exit|expected_failure| - expected_signal|expected_timeout|failed|skipped"> - <p><a href="#{$full-id}"><xsl:value-of select="@id" /></a></p> - </xsl:when> - <xsl:otherwise> - <p><xsl:value-of select="@id" /></p> - </xsl:otherwise> - </xsl:choose> - </td> - <xsl:apply-templates select="expected_death|expected_exit| - expected_failure|expected_timeout| - expected_signal|failed|passed| - skipped" mode="tc" /> - <td class="numeric"> - <p><xsl:value-of select="tc-time" />s</p> - </td> - </tr> - </xsl:if> - </xsl:template> - - <xsl:template match="passed" mode="tc"> - <td class="tcr-passed"><p class="nobr">Passed</p></td> - <td class="tcr-reason"><p>N/A</p></td> - </xsl:template> - - <xsl:template match="expected_death" mode="tc"> - <td class="tcr-xfail"><p class="nobr">Expected death</p></td> - <td class="tcr-reason"><p><xsl:apply-templates /></p></td> - </xsl:template> - - <xsl:template match="expected_exit" mode="tc"> - <td class="tcr-xfail"><p class="nobr">Expected exit</p></td> - <td class="tcr-reason"><p><xsl:apply-templates /></p></td> - </xsl:template> - - <xsl:template match="expected_failure" mode="tc"> - <td class="tcr-xfail"><p class="nobr">Expected failure</p></td> - <td class="tcr-reason"><p><xsl:apply-templates /></p></td> - </xsl:template> - - <xsl:template match="expected_timeout" mode="tc"> - <td class="tcr-xfail"><p class="nobr">Expected timeout</p></td> - <td class="tcr-reason"><p><xsl:apply-templates /></p></td> - </xsl:template> - - <xsl:template match="expected_signal" mode="tc"> - <td class="tcr-xfail"><p class="nobr">Expected signal</p></td> - <td class="tcr-reason"><p><xsl:apply-templates /></p></td> - </xsl:template> - - <xsl:template match="failed" mode="tc"> - <td class="tcr-failed"><p class="nobr">Failed</p></td> - <td class="tcr-reason"><p><xsl:apply-templates /></p></td> - </xsl:template> - - <xsl:template match="skipped" mode="tc"> - <td class="tcr-skipped"><p class="nobr">Skipped</p></td> - <td class="tcr-reason"><p><xsl:apply-templates /></p></td> - </xsl:template> - - <xsl:template match="tp" mode="details"> - <xsl:apply-templates select="tc[expected_death|expected_exit| - expected_failure|expected_signal| - expected_timeout|failed|skipped]" - mode="details" /> - </xsl:template> - - <xsl:template match="failed" mode="details"> - <p class="term"><strong>FAILED</strong>: <xsl:apply-templates /></p> - </xsl:template> - - <xsl:template match="expected_death|expected_exit|expected_failure| - expected_signal|expected_timeout" mode="details"> - <p class="term"><strong>XFAIL</strong>: <xsl:apply-templates /></p> - </xsl:template> - - <xsl:template match="skipped" mode="details"> - <p class="term"><strong>SKIPPED</strong>: <xsl:apply-templates /></p> - </xsl:template> - - <xsl:template match="tc" mode="details"> - <xsl:variable name="full-id" - select="concat(translate(../@id, '/', '_'), '_', @id)" /> - - <a name="{$full-id}" /> - <h2 id="{$full-id}">Test case: - <xsl:value-of select="../@id" /><xsl:text>/</xsl:text> - <xsl:value-of select="@id" /></h2> - - <xsl:if test="tc-time"> - <p class="details">Duration: - <xsl:apply-templates select="tc-time" mode="details" /></p> - </xsl:if> - - <h3>Termination reason</h3> - <xsl:apply-templates select="expected_death|expected_exit|expected_failure| - expected_signal|expected_timeout| - failed|skipped" - mode="details" /> - - <xsl:if test="so"> - <h3>Standard output stream</h3> - <pre class="so"><xsl:apply-templates select="so" mode="details" /></pre> - </xsl:if> - - <xsl:if test="se"> - <h3>Standard error stream</h3> - <pre class="se"><xsl:apply-templates select="se" mode="details" /></pre> - </xsl:if> - </xsl:template> - - <xsl:template match="tc-time" mode="details"> - <xsl:apply-templates /> seconds - </xsl:template> - - <xsl:template match="so" mode="details"> - <xsl:apply-templates /> - <xsl:if test="position() != last()"> - <xsl:text> -</xsl:text> - </xsl:if> - </xsl:template> - - <xsl:template match="se" mode="details"> - <xsl:apply-templates /> - <xsl:if test="position() != last()"> - <xsl:text> -</xsl:text> - </xsl:if> - </xsl:template> - - <xsl:template match="@*|node()" priority="-1"> - <xsl:copy> - <xsl:apply-templates select="@*|node()" /> - </xsl:copy> - </xsl:template> - -</xsl:stylesheet> diff --git a/tools/text.cpp b/tools/text.cpp deleted file mode 100644 index 9084f7e..0000000 --- a/tools/text.cpp +++ /dev/null @@ -1,158 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -extern "C" { -#include <regex.h> -} - -#include <cctype> -#include <cerrno> -#include <cstring> - -#include "exceptions.hpp" -#include "text.hpp" - -namespace impl = tools::text; -#define IMPL_NAME "tools::text" - -char* -impl::duplicate(const char* str) -{ - char* copy = new char[std::strlen(str) + 1]; - std::strcpy(copy, str); - return copy; -} - -bool -impl::match(const std::string& str, const std::string& regex) -{ - bool found; - - // Special case: regcomp does not like empty regular expressions. - if (regex.empty()) { - found = str.empty(); - } else { - ::regex_t preg; - - if (::regcomp(&preg, regex.c_str(), REG_EXTENDED) != 0) - throw std::runtime_error("Invalid regular expression '" + regex + - "'"); - - const int res = ::regexec(&preg, str.c_str(), 0, NULL, 0); - regfree(&preg); - if (res != 0 && res != REG_NOMATCH) - throw std::runtime_error("Invalid regular expression " + regex); - - found = res == 0; - } - - return found; -} - -std::string -impl::to_lower(const std::string& str) -{ - std::string lc; - for (std::string::const_iterator iter = str.begin(); iter != str.end(); - iter++) - lc += std::tolower(*iter); - return lc; -} - -std::vector< std::string > -impl::split(const std::string& str, const std::string& delim) -{ - std::vector< std::string > words; - - std::string::size_type pos = 0, newpos = 0; - while (pos < str.length() && newpos != std::string::npos) { - newpos = str.find(delim, pos); - if (newpos != pos) - words.push_back(str.substr(pos, newpos - pos)); - pos = newpos + delim.length(); - } - - return words; -} - -std::string -impl::trim(const std::string& str) -{ - std::string::size_type pos1 = str.find_first_not_of(" \t"); - std::string::size_type pos2 = str.find_last_not_of(" \t"); - - if (pos1 == std::string::npos && pos2 == std::string::npos) - return ""; - else if (pos1 == std::string::npos) - return str.substr(0, str.length() - pos2); - else if (pos2 == std::string::npos) - return str.substr(pos1); - else - return str.substr(pos1, pos2 - pos1 + 1); -} - -bool -impl::to_bool(const std::string& str) -{ - const std::string lower = to_lower(str); - if (lower == "yes" || lower == "true") - return true; - else if (lower == "no" || lower == "false") - return false; - else { - // XXX Not really a libc error. - throw system_error(IMPL_NAME "::to_bool", "Cannot convert string " - "'" + str + "' to boolean", EINVAL); - } -} - -int64_t -impl::to_bytes(std::string str) -{ - if (str.empty()) - throw std::runtime_error("Empty value"); - - const char unit = str[str.length() - 1]; - int64_t multiplier; - switch (unit) { - case 'k': case 'K': multiplier = 1 << 10; break; - case 'm': case 'M': multiplier = 1 << 20; break; - case 'g': case 'G': multiplier = 1 << 30; break; - case 't': case 'T': multiplier = int64_t(1) << 40; break; - default: - if (!std::isdigit(unit)) - throw std::runtime_error(std::string("Unknown size unit '") + unit - + "'"); - multiplier = 1; - } - if (multiplier != 1) - str.erase(str.length() - 1); - - return to_type< int64_t >(str) * multiplier; -} diff --git a/tools/text.hpp b/tools/text.hpp deleted file mode 100644 index 0b3dbaa..0000000 --- a/tools/text.hpp +++ /dev/null @@ -1,153 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if !defined(TOOLS_TEXT_HPP) -#define TOOLS_TEXT_HPP - -extern "C" { -#include <stdint.h> -} - -#include <sstream> -#include <stdexcept> -#include <string> -#include <vector> - -namespace tools { -namespace text { - -//! -//! \brief Duplicates a C string using the new[] allocator. -//! -//! Replaces the functionality of strdup by using the new[] allocator and -//! thus allowing the resulting memory to be managed by utils::auto_array. -//! -char* duplicate(const char*); - -//! -//! \brief Joins multiple words into a string. -//! -//! Joins a list of words into a string, separating them using the provided -//! separator. Empty words are not omitted. -//! -template< class T > -std::string -join(const T& words, const std::string& separator) -{ - std::string str; - - typename T::const_iterator iter = words.begin(); - bool done = iter == words.end(); - while (!done) { - str += *iter; - iter++; - if (iter != words.end()) - str += separator; - else - done = true; - } - - return str; -} - -//! -//! \brief Checks if the string matches a regular expression. -//! -bool match(const std::string&, const std::string&); - -//! -//! \brief Splits a string into words. -//! -//! Splits the given string into multiple words, all separated by the -//! given delimiter. Multiple occurrences of the same delimiter are -//! not condensed so that rejoining the words later on using the same -//! delimiter results in the original string. -//! -std::vector< std::string > split(const std::string&, const std::string&); - -//! -//! \brief Removes whitespace from the beginning and end of a string. -//! -std::string trim(const std::string&); - -//! -//! \brief Converts a string to a boolean value. -//! -bool to_bool(const std::string&); - -//! -//! \brief Converts the given string to a bytes size. -//! -int64_t to_bytes(std::string); - -//! -//! \brief Changes the case of a string to lowercase. -//! -//! Returns a new string that is a lowercased version of the original -//! one. -//! -std::string to_lower(const std::string&); - -//! -//! \brief Converts the given object to a string. -//! -//! Returns a string with the representation of the given object. There -//! must exist an operator<< method for that object. -//! -template< class T > -std::string -to_string(const T& ob) -{ - std::ostringstream ss; - ss << ob; - return ss.str(); -} - -//! -//! \brief Converts the given string to another type. -//! -//! Attempts to convert the given string to the requested type. Throws -//! an exception if the conversion failed. -//! -template< class T > -T -to_type(const std::string& str) -{ - std::istringstream ss(str); - T value; - ss >> value; - if (!ss.eof() || (ss.eof() && (ss.fail() || ss.bad()))) - throw std::runtime_error("Cannot convert string to requested type"); - return value; -} - -} // namespace text -} // namespace tools - -#endif // !defined(TOOLS_TEXT_HPP) diff --git a/tools/text_test.cpp b/tools/text_test.cpp deleted file mode 100644 index 0fa31d8..0000000 --- a/tools/text_test.cpp +++ /dev/null @@ -1,390 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#include <cstring> -#include <set> -#include <vector> - -#include <atf-c++.hpp> - -#include "text.hpp" - -// ------------------------------------------------------------------------ -// Test cases for the free functions. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(duplicate); -ATF_TEST_CASE_HEAD(duplicate) -{ - set_md_var("descr", "Tests the duplicate function"); -} -ATF_TEST_CASE_BODY(duplicate) -{ - using tools::text::duplicate; - - const char* orig = "foo"; - - char* copy = duplicate(orig); - ATF_REQUIRE_EQ(std::strlen(copy), 3); - ATF_REQUIRE(std::strcmp(copy, "foo") == 0); - - std::strcpy(copy, "bar"); - ATF_REQUIRE(std::strcmp(copy, "bar") == 0); - ATF_REQUIRE(std::strcmp(orig, "foo") == 0); -} - -ATF_TEST_CASE(join); -ATF_TEST_CASE_HEAD(join) -{ - set_md_var("descr", "Tests the join function"); -} -ATF_TEST_CASE_BODY(join) -{ - using tools::text::join; - - // First set of tests using a non-sorted collection, std::vector. - { - std::vector< std::string > words; - std::string str; - - words.clear(); - str = join(words, ","); - ATF_REQUIRE_EQ(str, ""); - - words.clear(); - words.push_back(""); - str = join(words, ","); - ATF_REQUIRE_EQ(str, ""); - - words.clear(); - words.push_back(""); - words.push_back(""); - str = join(words, ","); - ATF_REQUIRE_EQ(str, ","); - - words.clear(); - words.push_back("foo"); - words.push_back(""); - words.push_back("baz"); - str = join(words, ","); - ATF_REQUIRE_EQ(str, "foo,,baz"); - - words.clear(); - words.push_back("foo"); - words.push_back("bar"); - words.push_back("baz"); - str = join(words, ","); - ATF_REQUIRE_EQ(str, "foo,bar,baz"); - } - - // Second set of tests using a sorted collection, std::set. - { - std::set< std::string > words; - std::string str; - - words.clear(); - str = join(words, ","); - ATF_REQUIRE_EQ(str, ""); - - words.clear(); - words.insert(""); - str = join(words, ","); - ATF_REQUIRE_EQ(str, ""); - - words.clear(); - words.insert("foo"); - words.insert(""); - words.insert("baz"); - str = join(words, ","); - ATF_REQUIRE_EQ(str, ",baz,foo"); - - words.clear(); - words.insert("foo"); - words.insert("bar"); - words.insert("baz"); - str = join(words, ","); - ATF_REQUIRE_EQ(str, "bar,baz,foo"); - } -} - -ATF_TEST_CASE(match); -ATF_TEST_CASE_HEAD(match) -{ - set_md_var("descr", "Tests the match function"); -} -ATF_TEST_CASE_BODY(match) -{ - using tools::text::match; - - ATF_REQUIRE_THROW(std::runtime_error, match("", "[")); - - ATF_REQUIRE(match("", "")); - ATF_REQUIRE(!match("foo", "")); - - ATF_REQUIRE(match("", ".*")); - ATF_REQUIRE(match("", "[a-z]*")); - - ATF_REQUIRE(match("hello", "hello")); - ATF_REQUIRE(match("hello", "[a-z]+")); - ATF_REQUIRE(match("hello", "^[a-z]+$")); - - ATF_REQUIRE(!match("hello", "helooo")); - ATF_REQUIRE(!match("hello", "[a-z]+5")); - ATF_REQUIRE(!match("hello", "^ [a-z]+$")); -} - -ATF_TEST_CASE(split); -ATF_TEST_CASE_HEAD(split) -{ - set_md_var("descr", "Tests the split function"); -} -ATF_TEST_CASE_BODY(split) -{ - using tools::text::split; - - std::vector< std::string > words; - - words = split("", " "); - ATF_REQUIRE_EQ(words.size(), 0); - - words = split(" ", " "); - ATF_REQUIRE_EQ(words.size(), 0); - - words = split(" ", " "); - ATF_REQUIRE_EQ(words.size(), 0); - - words = split("a b", " "); - ATF_REQUIRE_EQ(words.size(), 2); - ATF_REQUIRE_EQ(words[0], "a"); - ATF_REQUIRE_EQ(words[1], "b"); - - words = split("a b c d", " "); - ATF_REQUIRE_EQ(words.size(), 4); - ATF_REQUIRE_EQ(words[0], "a"); - ATF_REQUIRE_EQ(words[1], "b"); - ATF_REQUIRE_EQ(words[2], "c"); - ATF_REQUIRE_EQ(words[3], "d"); - - words = split("foo bar", " "); - ATF_REQUIRE_EQ(words.size(), 2); - ATF_REQUIRE_EQ(words[0], "foo"); - ATF_REQUIRE_EQ(words[1], "bar"); - - words = split("foo bar baz foobar", " "); - ATF_REQUIRE_EQ(words.size(), 4); - ATF_REQUIRE_EQ(words[0], "foo"); - ATF_REQUIRE_EQ(words[1], "bar"); - ATF_REQUIRE_EQ(words[2], "baz"); - ATF_REQUIRE_EQ(words[3], "foobar"); - - words = split(" foo bar", " "); - ATF_REQUIRE_EQ(words.size(), 2); - ATF_REQUIRE_EQ(words[0], "foo"); - ATF_REQUIRE_EQ(words[1], "bar"); - - words = split("foo bar", " "); - ATF_REQUIRE_EQ(words.size(), 2); - ATF_REQUIRE_EQ(words[0], "foo"); - ATF_REQUIRE_EQ(words[1], "bar"); - - words = split("foo bar ", " "); - ATF_REQUIRE_EQ(words.size(), 2); - ATF_REQUIRE_EQ(words[0], "foo"); - ATF_REQUIRE_EQ(words[1], "bar"); - - words = split(" foo bar ", " "); - ATF_REQUIRE_EQ(words.size(), 2); - ATF_REQUIRE_EQ(words[0], "foo"); - ATF_REQUIRE_EQ(words[1], "bar"); -} - -ATF_TEST_CASE(split_delims); -ATF_TEST_CASE_HEAD(split_delims) -{ - set_md_var("descr", "Tests the split function using different delimiters"); -} -ATF_TEST_CASE_BODY(split_delims) -{ - using tools::text::split; - - std::vector< std::string > words; - - words = split("", "/"); - ATF_REQUIRE_EQ(words.size(), 0); - - words = split(" ", "/"); - ATF_REQUIRE_EQ(words.size(), 1); - ATF_REQUIRE_EQ(words[0], " "); - - words = split(" ", "/"); - ATF_REQUIRE_EQ(words.size(), 1); - ATF_REQUIRE_EQ(words[0], " "); - - words = split("a/b", "/"); - ATF_REQUIRE_EQ(words.size(), 2); - ATF_REQUIRE_EQ(words[0], "a"); - ATF_REQUIRE_EQ(words[1], "b"); - - words = split("aLONGDELIMbcdLONGDELIMef", "LONGDELIM"); - ATF_REQUIRE_EQ(words.size(), 3); - ATF_REQUIRE_EQ(words[0], "a"); - ATF_REQUIRE_EQ(words[1], "bcd"); - ATF_REQUIRE_EQ(words[2], "ef"); -} - -ATF_TEST_CASE(trim); -ATF_TEST_CASE_HEAD(trim) -{ - set_md_var("descr", "Tests the trim function"); -} -ATF_TEST_CASE_BODY(trim) -{ - using tools::text::trim; - - ATF_REQUIRE_EQ(trim(""), ""); - ATF_REQUIRE_EQ(trim(" "), ""); - ATF_REQUIRE_EQ(trim("\t"), ""); - - ATF_REQUIRE_EQ(trim(" foo"), "foo"); - ATF_REQUIRE_EQ(trim("\t foo"), "foo"); - ATF_REQUIRE_EQ(trim(" \tfoo"), "foo"); - ATF_REQUIRE_EQ(trim("foo\t "), "foo"); - ATF_REQUIRE_EQ(trim("foo \t"), "foo"); - - ATF_REQUIRE_EQ(trim("foo bar"), "foo bar"); - ATF_REQUIRE_EQ(trim("\t foo bar"), "foo bar"); - ATF_REQUIRE_EQ(trim(" \tfoo bar"), "foo bar"); - ATF_REQUIRE_EQ(trim("foo bar\t "), "foo bar"); - ATF_REQUIRE_EQ(trim("foo bar \t"), "foo bar"); -} - -ATF_TEST_CASE(to_bool); -ATF_TEST_CASE_HEAD(to_bool) -{ - set_md_var("descr", "Tests the to_string function"); -} -ATF_TEST_CASE_BODY(to_bool) -{ - using tools::text::to_bool; - - ATF_REQUIRE(to_bool("true")); - ATF_REQUIRE(to_bool("TRUE")); - ATF_REQUIRE(to_bool("yes")); - ATF_REQUIRE(to_bool("YES")); - - ATF_REQUIRE(!to_bool("false")); - ATF_REQUIRE(!to_bool("FALSE")); - ATF_REQUIRE(!to_bool("no")); - ATF_REQUIRE(!to_bool("NO")); - - ATF_REQUIRE_THROW(std::runtime_error, to_bool("")); - ATF_REQUIRE_THROW(std::runtime_error, to_bool("tru")); - ATF_REQUIRE_THROW(std::runtime_error, to_bool("true2")); - ATF_REQUIRE_THROW(std::runtime_error, to_bool("fals")); - ATF_REQUIRE_THROW(std::runtime_error, to_bool("false2")); -} - -ATF_TEST_CASE(to_bytes); -ATF_TEST_CASE_HEAD(to_bytes) -{ - set_md_var("descr", "Tests the to_bytes function"); -} -ATF_TEST_CASE_BODY(to_bytes) -{ - using tools::text::to_bytes; - - ATF_REQUIRE_EQ(0, to_bytes("0")); - ATF_REQUIRE_EQ(12345, to_bytes("12345")); - ATF_REQUIRE_EQ(2 * 1024, to_bytes("2k")); - ATF_REQUIRE_EQ(4 * 1024 * 1024, to_bytes("4m")); - ATF_REQUIRE_EQ(int64_t(8) * 1024 * 1024 * 1024, to_bytes("8g")); - ATF_REQUIRE_EQ(int64_t(16) * 1024 * 1024 * 1024 * 1024, to_bytes("16t")); - - ATF_REQUIRE_THROW_RE(std::runtime_error, "Empty", to_bytes("")); - ATF_REQUIRE_THROW_RE(std::runtime_error, "Unknown size unit 'd'", - to_bytes("12d")); - ATF_REQUIRE_THROW(std::runtime_error, to_bytes(" ")); - ATF_REQUIRE_THROW(std::runtime_error, to_bytes(" k")); -} - -ATF_TEST_CASE(to_string); -ATF_TEST_CASE_HEAD(to_string) -{ - set_md_var("descr", "Tests the to_string function"); -} -ATF_TEST_CASE_BODY(to_string) -{ - using tools::text::to_string; - - ATF_REQUIRE_EQ(to_string('a'), "a"); - ATF_REQUIRE_EQ(to_string("a"), "a"); - ATF_REQUIRE_EQ(to_string(5), "5"); -} - -ATF_TEST_CASE(to_type); -ATF_TEST_CASE_HEAD(to_type) -{ - set_md_var("descr", "Tests the to_type function"); -} -ATF_TEST_CASE_BODY(to_type) -{ - using tools::text::to_type; - - ATF_REQUIRE_EQ(to_type< int >("0"), 0); - ATF_REQUIRE_EQ(to_type< int >("1234"), 1234); - ATF_REQUIRE_THROW(std::runtime_error, to_type< int >(" ")); - ATF_REQUIRE_THROW(std::runtime_error, to_type< int >("0 a")); - ATF_REQUIRE_THROW(std::runtime_error, to_type< int >("a")); - - ATF_REQUIRE_EQ(to_type< float >("0.5"), 0.5); - ATF_REQUIRE_EQ(to_type< float >("1234.5"), 1234.5); - ATF_REQUIRE_THROW(std::runtime_error, to_type< float >("0.5 a")); - ATF_REQUIRE_THROW(std::runtime_error, to_type< float >("a")); - - ATF_REQUIRE_EQ(to_type< std::string >("a"), "a"); -} - -// ------------------------------------------------------------------------ -// Main. -// ------------------------------------------------------------------------ - -ATF_INIT_TEST_CASES(tcs) -{ - // Add the test cases for the free functions. - ATF_ADD_TEST_CASE(tcs, duplicate); - ATF_ADD_TEST_CASE(tcs, join); - ATF_ADD_TEST_CASE(tcs, match); - ATF_ADD_TEST_CASE(tcs, split); - ATF_ADD_TEST_CASE(tcs, split_delims); - ATF_ADD_TEST_CASE(tcs, trim); - ATF_ADD_TEST_CASE(tcs, to_bool); - ATF_ADD_TEST_CASE(tcs, to_bytes); - ATF_ADD_TEST_CASE(tcs, to_string); - ATF_ADD_TEST_CASE(tcs, to_type); -} diff --git a/tools/timers.cpp b/tools/timers.cpp deleted file mode 100644 index 371a416..0000000 --- a/tools/timers.cpp +++ /dev/null @@ -1,211 +0,0 @@ -// -// 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. -// - -#if defined(HAVE_CONFIG_H) -# include <bconfig.h> -#endif - -extern "C" { -#include <sys/time.h> -} - -#include <cassert> -#include <cerrno> -#include <csignal> -#include <ctime> - -#include "defs.hpp" -#include "exceptions.hpp" -#include "signals.hpp" -#include "timers.hpp" - -namespace impl = tools::timers; -#define IMPL_NAME "tools::timers" - -#if !defined(HAVE_TIMER_T) -static impl::timer* compat_handle; -#endif - -// ------------------------------------------------------------------------ -// Auxiliary functions. -// ------------------------------------------------------------------------ - -#if defined(HAVE_TIMER_T) -static -void -handler(const int signo ATF_DEFS_ATTRIBUTE_UNUSED, siginfo_t* si, - void* uc ATF_DEFS_ATTRIBUTE_UNUSED) -{ - impl::timer* timer = static_cast< impl::timer* >(si->si_value.sival_ptr); - timer->set_fired(); - timer->timeout_callback(); -} -#else -static -void -handler(const int signo ATF_DEFS_ATTRIBUTE_UNUSED, - siginfo_t* si ATF_DEFS_ATTRIBUTE_UNUSED, - void* uc ATF_DEFS_ATTRIBUTE_UNUSED) -{ - compat_handle->set_fired(); - compat_handle->timeout_callback(); -} -#endif - -// ------------------------------------------------------------------------ -// The "timer" class. -// ------------------------------------------------------------------------ - -struct impl::timer::impl { -#if defined(HAVE_TIMER_T) - ::timer_t m_timer; - ::itimerspec m_old_it; -#else - ::itimerval m_old_it; -#endif - - struct ::sigaction m_old_sa; - volatile bool m_fired; - - impl(void) : m_fired(false) - { - } -}; - -impl::timer::timer(const unsigned int seconds) : - m_pimpl(new impl()) -{ - struct ::sigaction sa; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_SIGINFO; - sa.sa_sigaction = ::handler; - if (::sigaction(SIGALRM, &sa, &m_pimpl->m_old_sa) == -1) - throw tools::system_error(IMPL_NAME "::timer::timer", - "Failed to set signal handler", errno); - -#if defined(HAVE_TIMER_T) - struct ::sigevent se; - se.sigev_notify = SIGEV_SIGNAL; - se.sigev_signo = SIGALRM; - se.sigev_value.sival_ptr = static_cast< void* >(this); - se.sigev_notify_function = NULL; - se.sigev_notify_attributes = NULL; - if (::timer_create(CLOCK_MONOTONIC, &se, &m_pimpl->m_timer) == -1) { - ::sigaction(SIGALRM, &m_pimpl->m_old_sa, NULL); - throw tools::system_error(IMPL_NAME "::timer::timer", - "Failed to create timer", errno); - } - - struct ::itimerspec it; - it.it_interval.tv_sec = 0; - it.it_interval.tv_nsec = 0; - it.it_value.tv_sec = seconds; - it.it_value.tv_nsec = 0; - if (::timer_settime(m_pimpl->m_timer, 0, &it, &m_pimpl->m_old_it) == -1) { - ::sigaction(SIGALRM, &m_pimpl->m_old_sa, NULL); - ::timer_delete(m_pimpl->m_timer); - throw tools::system_error(IMPL_NAME "::timer::timer", - "Failed to program timer", errno); - } -#else - ::itimerval it; - it.it_interval.tv_sec = 0; - it.it_interval.tv_usec = 0; - it.it_value.tv_sec = seconds; - it.it_value.tv_usec = 0; - if (::setitimer(ITIMER_REAL, &it, &m_pimpl->m_old_it) == -1) { - ::sigaction(SIGALRM, &m_pimpl->m_old_sa, NULL); - throw tools::system_error(IMPL_NAME "::timer::timer", - "Failed to program timer", errno); - } - assert(compat_handle == NULL); - compat_handle = this; -#endif -} - -impl::timer::~timer(void) -{ -#if defined(HAVE_TIMER_T) - { - const int ret = ::timer_delete(m_pimpl->m_timer); - assert(ret != -1); - } -#else - { - const int ret = ::setitimer(ITIMER_REAL, &m_pimpl->m_old_it, NULL); - assert(ret != -1); - } -#endif - const int ret = ::sigaction(SIGALRM, &m_pimpl->m_old_sa, NULL); - assert(ret != -1); - -#if !defined(HAVE_TIMER_T) - compat_handle = NULL; -#endif -} - -bool -impl::timer::fired(void) - const -{ - return m_pimpl->m_fired; -} - -void -impl::timer::set_fired(void) -{ - m_pimpl->m_fired = true; -} - -// ------------------------------------------------------------------------ -// The "child_timer" class. -// ------------------------------------------------------------------------ - -impl::child_timer::child_timer(const unsigned int seconds, const pid_t pid, - volatile bool& terminate) : - timer(seconds), - m_pid(pid), - m_terminate(terminate) -{ -} - -impl::child_timer::~child_timer(void) -{ -} - -void -impl::child_timer::timeout_callback(void) -{ - static const timespec ts = { 1, 0 }; - m_terminate = true; - ::kill(-m_pid, SIGTERM); - ::nanosleep(&ts, NULL); - if (::kill(-m_pid, 0) != -1) - ::kill(-m_pid, SIGKILL); -} diff --git a/tools/timers.hpp b/tools/timers.hpp deleted file mode 100644 index bf43ffb..0000000 --- a/tools/timers.hpp +++ /dev/null @@ -1,83 +0,0 @@ -// -// 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. -// - -#if !defined(TOOLS_TIMERS_HPP) -#define TOOLS_TIMERS_HPP - -extern "C" { -#include <sys/types.h> -} - -#include <memory> - -namespace tools { -namespace timers { - -class signal_programmer; - -// ------------------------------------------------------------------------ -// The "timer" class. -// ------------------------------------------------------------------------ - -class timer { - // Non-copyable. - timer(const timer&); - timer& operator=(const timer&); - - struct impl; - std::auto_ptr< impl > m_pimpl; - -public: - timer(const unsigned int); - virtual ~timer(void); - - bool fired(void) const; - void set_fired(void); - virtual void timeout_callback(void) = 0; -}; - -// ------------------------------------------------------------------------ -// The "child_timer" class. -// ------------------------------------------------------------------------ - -class child_timer : public timer { - const pid_t m_pid; - volatile bool& m_terminate; - -public: - child_timer(const unsigned int, const pid_t, volatile bool&); - virtual ~child_timer(void); - - void timeout_callback(void); -}; - -} // namespace timers -} // namespace tools - -#endif // !defined(TOOLS_TIMERS_HPP) diff --git a/tools/ui.cpp b/tools/ui.cpp deleted file mode 100644 index 56426ec..0000000 --- a/tools/ui.cpp +++ /dev/null @@ -1,172 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -extern "C" { -#include <sys/ioctl.h> - -#include <termios.h> -#include <unistd.h> -} - -#include <cassert> -#include <sstream> - -#include "env.hpp" -#include "text.hpp" -#include "ui.hpp" - -namespace impl = tools::ui; -#define IMPL_NAME "tools::ui" - -static -size_t -terminal_width(void) -{ - static bool done = false; - static size_t width = 0; - - if (!done) { - if (tools::env::has("COLUMNS")) { - const std::string cols = tools::env::get("COLUMNS"); - if (cols.length() > 0) { - width = tools::text::to_type< size_t >(cols); - } - } else { - struct winsize ws; - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) - width = ws.ws_col; - } - - if (width >= 80) - width -= 5; - - done = true; - } - - return width; -} - -static -std::string -format_paragraph(const std::string& text, - const std::string& tag, - const bool first, - const bool repeat, - const size_t col) -{ - assert(text.find('\n') == std::string::npos); - - const std::string pad(col - tag.length(), ' '); - const std::string fullpad(col, ' '); - - std::string formatted; - if (first || repeat) - formatted = tag + pad; - else - formatted = fullpad; - assert(formatted.length() == col); - size_t curcol = col; - - const size_t maxcol = terminal_width(); - - std::vector< std::string > words = tools::text::split(text, " "); - for (std::vector< std::string >::const_iterator iter = words.begin(); - iter != words.end(); iter++) { - const std::string& word = *iter; - - if (iter != words.begin() && maxcol > 0 && - curcol + word.length() + 1 > maxcol) { - if (repeat) - formatted += '\n' + tag + pad; - else - formatted += '\n' + fullpad; - curcol = col; - } else if (iter != words.begin()) { - formatted += ' '; - curcol++; - } - - formatted += word; - curcol += word.length(); - } - - return formatted; -} - -std::string -impl::format_error(const std::string& prog_name, const std::string& error) -{ - return format_text_with_tag("ERROR: " + error, prog_name + ": ", true); -} - -std::string -impl::format_info(const std::string& prog_name, const std::string& msg) -{ - return format_text_with_tag(msg, prog_name + ": ", true); -} - -std::string -impl::format_text(const std::string& text) -{ - return format_text_with_tag(text, "", false, 0); -} - -std::string -impl::format_text_with_tag(const std::string& text, const std::string& tag, - bool repeat, size_t col) -{ - assert(col == 0 || col >= tag.length()); - if (col == 0) - col = tag.length(); - - std::string formatted; - - std::vector< std::string > lines = tools::text::split(text, "\n"); - for (std::vector< std::string >::const_iterator iter = lines.begin(); - iter != lines.end(); iter++) { - const std::string& line = *iter; - - formatted += format_paragraph(line, tag, iter == lines.begin(), - repeat, col); - if (iter + 1 != lines.end()) { - if (repeat) - formatted += "\n" + tag + "\n"; - else - formatted += "\n\n"; - } - } - - return formatted; -} - -std::string -impl::format_warning(const std::string& prog_name, const std::string& error) -{ - return format_text_with_tag("WARNING: " + error, prog_name + ": ", true); -} diff --git a/tools/ui.hpp b/tools/ui.hpp deleted file mode 100644 index 4e0e431..0000000 --- a/tools/ui.hpp +++ /dev/null @@ -1,105 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if !defined(TOOLS_UI_HPP) -#define TOOLS_UI_HPP - -#include <string> - -namespace tools { -namespace ui { - -//! -//! \brief Formats an error message to fit on screen. -//! -//! Given the program's name and an error message, properly formats it to -//! fit on screen. -//! -//! The program's name is not stored globally to prevent the usage of this -//! function from inside the library. Making it a explicit parameter -//! restricts its usage to the frontend. -//! -std::string format_error(const std::string&, const std::string&); - -//! -//! \brief Formats an informational message to fit on screen. -//! -//! Given the program's name and an informational message, properly formats -//! it to fit on screen. -//! -//! The program's name is not stored globally to prevent the usage of this -//! function from inside the library. Making it a explicit parameter -//! restricts its usage to the frontend. -//! -std::string format_info(const std::string&, const std::string&); - -//! -//! \brief Formats a block of text to fit nicely on screen. -//! -//! Given a text, which is composed of multiple paragraphs separated by -//! a single '\n' character, reformats it to fill on the current screen's -//! width with proper line wrapping. -//! -//! This is just a special case of format_text_with_tag, provided for -//! simplicity. -//! -std::string format_text(const std::string&); - -//! -//! \brief Formats a block of text to fit nicely on screen, prepending a -//! tag to it. -//! -//! Given a text, which is composed of multiple paragraphs separated by -//! a single '\n' character, reformats it to fill on the current screen's -//! width with proper line wrapping. The text is prepended with a tag; -//! i.e. a word that is printed at the beginning of the first paragraph and -//! optionally repeated at the beginning of each word. The last parameter -//! specifies the column on which the text should start, and that position -//! must be greater than the tag's length or 0, in which case it -//! automatically takes the correct value. -//! -std::string format_text_with_tag(const std::string&, const std::string&, - bool, size_t = 0); - -//! -//! \brief Formats a warning message to fit on screen. -//! -//! Given the program's name and a warning message, properly formats it to -//! fit on screen. -//! -//! The program's name is not stored globally to prevent the usage of this -//! function from inside the library. Making it a explicit parameter -//! restricts its usage to the frontend. -//! -std::string format_warning(const std::string&, const std::string&); - -} // namespace ui -} // namespace tools - -#endif // !defined(TOOLS_UI_HPP) diff --git a/tools/ui_test.cpp b/tools/ui_test.cpp deleted file mode 100644 index e4d9050..0000000 --- a/tools/ui_test.cpp +++ /dev/null @@ -1,462 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2009 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 <cstring> -#include <iostream> - -#include <atf-c++.hpp> - -#include "env.hpp" -#include "ui.hpp" - -// ------------------------------------------------------------------------ -// Test cases for the free functions. -// ------------------------------------------------------------------------ - -struct test { - const char *tc; - const char *tag; - bool repeat; - size_t col; - const char *fmt; - const char *result; -} tests[] = { - // - // wo_tag - // - - { - "wo_tag", - "", - false, - 0, - "12345", - "12345", - }, - - { - "wo_tag", - "", - false, - 0, - "12345 ", - "12345", - }, - - { - "wo_tag", - "", - false, - 0, - "12345 7890", - "12345 7890", - }, - - { - "wo_tag", - "", - false, - 0, - "12345 789012 45", - "12345 789012 45", - }, - - { - "wo_tag", - "", - false, - 0, - "12345 789012 456", - "12345 789012\n456", - }, - - { - "wo_tag", - "", - false, - 0, - "1234567890123456", - "1234567890123456", - }, - - // TODO(jmmv): Fix the code to pass this test... -// { -// "wo_tag", -// "", -// false, -// 0, -// " 2345678901234567", -// "\n2345678901234567", -// }, - - { - "wo_tag", - "", - false, - 0, - "12345 789012345 78", - "12345 789012345\n78", - }, - - // - // wo_tag_col - // - - { - "wo_tag_col", - "", - false, - 10, - "12345", - " 12345", - }, - - { - "wo_tag_col", - "", - false, - 10, - "12345 7890", - " 12345\n" - " 7890", - }, - - { - "wo_tag_col", - "", - false, - 10, - "1 3 5 7 9", - " 1 3 5\n" - " 7 9", - }, - - // - // w_tag_no_repeat - // - - { - "w_tag_no_repeat", - "1234: ", - false, - 0, - "789012345", - "1234: 789012345", - }, - - { - "w_tag_no_repeat", - "1234: ", - false, - 0, - "789 1234 56789", - "1234: 789 1234\n" - " 56789", - }, - - { - "w_tag_no_repeat", - "1234: ", - false, - 0, - "789012345", - "1234: 789012345", - }, - - { - "w_tag_no_repeat", - "1234: ", - false, - 0, - "789012345 7890", - "1234: 789012345\n" - " 7890", - }, - - // - // w_tag_repeat - // - - { - "w_tag_repeat", - "1234: ", - true, - 0, - "789012345", - "1234: 789012345", - }, - - { - "w_tag_repeat", - "1234: ", - true, - 0, - "789 1234 56789", - "1234: 789 1234\n" - "1234: 56789", - }, - - { - "w_tag_repeat", - "1234: ", - true, - 0, - "789012345", - "1234: 789012345", - }, - - { - "w_tag_no_repeat", - "1234: ", - true, - 0, - "789012345 7890", - "1234: 789012345\n" - "1234: 7890", - }, - - // - // w_tag_col - // - - { - "w_tag_col", - "1234:", - false, - 10, - "1 3 5", - "1234: 1 3 5", - }, - - { - "w_tag_col", - "1234:", - false, - 10, - "1 3 5 7 9", - "1234: 1 3 5\n" - " 7 9", - }, - - { - "w_tag_col", - "1234:", - true, - 10, - "1 3 5 7 9", - "1234: 1 3 5\n" - "1234: 7 9", - }, - - // - // paragraphs - // - - { - "paragraphs", - "", - false, - 0, - "1 3 5\n\n", - "1 3 5" - }, - - { - "paragraphs", - "", - false, - 0, - "1 3 5\n2 4 6", - "1 3 5\n\n2 4 6" - }, - - { - "paragraphs", - "", - false, - 0, - "1234 6789 123456\n2 4 6", - "1234 6789\n123456\n\n2 4 6" - }, - - { - "paragraphs", - "12: ", - false, - 0, - "56789 123456\n2 4 6", - "12: 56789\n 123456\n\n 2 4 6" - }, - - { - "paragraphs", - "12: ", - true, - 0, - "56789 123456\n2 4 6", - "12: 56789\n12: 123456\n12: \n12: 2 4 6" - }, - - { - "paragraphs", - "12:", - false, - 4, - "56789 123456\n2 4 6", - "12: 56789\n 123456\n\n 2 4 6" - }, - - { - "paragraphs", - "12:", - true, - 4, - "56789 123456\n2 4 6", - "12: 56789\n12: 123456\n12:\n12: 2 4 6" - }, - - // - // end - // - - { - NULL, - NULL, - false, - 0, - NULL, - NULL, - }, -}; - -static -void -run_tests(const char *tc) -{ - struct test *t; - - std::cout << "Running tests for " << tc << "\n"; - - tools::env::set("COLUMNS", "15"); - - for (t = &tests[0]; t->tc != NULL; t++) { - if (std::strcmp(t->tc, tc) == 0) { - std::cout << "\n"; - std::cout << "Testing with tag '" << t->tag << "', '" - << (t->repeat ? "repeat" : "no repeat") << "', col " - << t->col << "\n"; - std::cout << "Input: >>>" << t->fmt << "<<<\n"; - std::cout << "Expected output: >>>" << t->result << "<<<\n"; - - std::string result = tools::ui::format_text_with_tag(t->fmt, t->tag, - t->repeat, t->col); - std::cout << "Output : >>>" << result << "<<<\n"; - ATF_REQUIRE_EQ(t->result, result); - } - } -} - -ATF_TEST_CASE(wo_tag); -ATF_TEST_CASE_HEAD(wo_tag) -{ - set_md_var("descr", "Checks formatting without tags"); -} -ATF_TEST_CASE_BODY(wo_tag) -{ - run_tests("wo_tag"); -} - -ATF_TEST_CASE(wo_tag_col); -ATF_TEST_CASE_HEAD(wo_tag_col) -{ - set_md_var("descr", "Checks formatting without tags and with a non-zero " - "starting column"); -} -ATF_TEST_CASE_BODY(wo_tag_col) -{ - run_tests("wo_tag_col"); -} - -ATF_TEST_CASE(w_tag_no_repeat); -ATF_TEST_CASE_HEAD(w_tag_no_repeat) -{ - set_md_var("descr", "Checks formatting with a tag"); -} -ATF_TEST_CASE_BODY(w_tag_no_repeat) -{ - run_tests("w_tag_no_repeat"); -} - -ATF_TEST_CASE(w_tag_repeat); -ATF_TEST_CASE_HEAD(w_tag_repeat) -{ - set_md_var("descr", "Checks formatting with a tag and repeating it on " - "each line"); -} -ATF_TEST_CASE_BODY(w_tag_repeat) -{ - run_tests("w_tag_repeat"); -} - -ATF_TEST_CASE(w_tag_col); -ATF_TEST_CASE_HEAD(w_tag_col) -{ - set_md_var("descr", "Checks formatting with a tag and starting at a " - "column greater than its length"); -} -ATF_TEST_CASE_BODY(w_tag_col) -{ - run_tests("w_tag_col"); -} - -ATF_TEST_CASE(paragraphs); -ATF_TEST_CASE_HEAD(paragraphs) -{ - set_md_var("descr", "Checks formatting a string that contains multiple " - "paragraphs"); -} -ATF_TEST_CASE_BODY(paragraphs) -{ - run_tests("paragraphs"); -} - -// ------------------------------------------------------------------------ -// Main. -// ------------------------------------------------------------------------ - -ATF_INIT_TEST_CASES(tcs) -{ - // Add the test cases for the free functions. - ATF_ADD_TEST_CASE(tcs, wo_tag); - ATF_ADD_TEST_CASE(tcs, wo_tag_col); - ATF_ADD_TEST_CASE(tcs, w_tag_no_repeat); - ATF_ADD_TEST_CASE(tcs, w_tag_repeat); - ATF_ADD_TEST_CASE(tcs, w_tag_col); - ATF_ADD_TEST_CASE(tcs, paragraphs); -} diff --git a/tools/user.cpp b/tools/user.cpp deleted file mode 100644 index 85d7e50..0000000 --- a/tools/user.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -extern "C" { -#include <sys/param.h> -#include <sys/types.h> - -#include <limits.h> -#include <pwd.h> -#include <unistd.h> -} - -#include <cassert> -#include <stdexcept> -#include <string> - -#include "user.hpp" - -namespace impl = tools::user; -#define IMPL_NAME "tools::user" - -uid_t -impl::euid(void) -{ - return ::geteuid(); -} - -void -impl::drop_privileges(const std::pair< int, int > ids) -{ - if (::setgid(ids.second) == -1) - throw std::runtime_error("Failed to drop group privileges"); - if (::setuid(ids.first) == -1) - throw std::runtime_error("Failed to drop user privileges"); -} - -std::pair< int, int > -impl::get_user_ids(const std::string& user) -{ - const struct passwd* pw = ::getpwnam(user.c_str()); - if (pw == NULL) - throw std::runtime_error("Failed to get information for user " + user); - return std::make_pair(pw->pw_uid, pw->pw_gid); -} - -bool -impl::is_member_of_group(gid_t gid) -{ - static gid_t groups[NGROUPS_MAX]; - static int ngroups = -1; - bool found; - int i; - - if (ngroups == -1) { - ngroups = getgroups(NGROUPS_MAX, groups); - assert(ngroups >= 0); - } - - found = false; - for (i = 0; !found && i < ngroups; i++) - if (groups[i] == gid) - found = true; - return found; -} - -bool -impl::is_root(void) -{ - return ::geteuid() == 0; -} - -bool -impl::is_unprivileged(void) -{ - return ::geteuid() != 0; -} diff --git a/tools/user.hpp b/tools/user.hpp deleted file mode 100644 index 1758eb0..0000000 --- a/tools/user.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -#if !defined(TOOLS_USER_HPP) -#define TOOLS_USER_HPP - -extern "C" { -#include <sys/types.h> -} - -#include <utility> - -namespace tools { -namespace user { - -uid_t euid(void); -void drop_privileges(const std::pair< int, int >); -std::pair< int, int > get_user_ids(const std::string&); -bool is_member_of_group(gid_t); -bool is_root(void); -bool is_unprivileged(void); - -} // namespace user -} // namespace tools - -#endif // !defined(TOOLS_USER_HPP) diff --git a/tools/user_test.cpp b/tools/user_test.cpp deleted file mode 100644 index 4c385d3..0000000 --- a/tools/user_test.cpp +++ /dev/null @@ -1,148 +0,0 @@ -// -// Automated Testing Framework (atf) -// -// Copyright (c) 2007 The NetBSD Foundation, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND -// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY -// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// - -extern "C" { -#include <sys/param.h> -#include <sys/types.h> -#include <limits.h> -#include <unistd.h> -} - -#include <iostream> -#include <set> - -#include <atf-c++.hpp> - -#include "user.hpp" - -// ------------------------------------------------------------------------ -// Test cases for the free functions. -// ------------------------------------------------------------------------ - -ATF_TEST_CASE(euid); -ATF_TEST_CASE_HEAD(euid) -{ - set_md_var("descr", "Tests the euid function"); -} -ATF_TEST_CASE_BODY(euid) -{ - using tools::user::euid; - - ATF_REQUIRE_EQ(euid(), ::geteuid()); -} - -ATF_TEST_CASE(is_member_of_group); -ATF_TEST_CASE_HEAD(is_member_of_group) -{ - set_md_var("descr", "Tests the is_member_of_group function"); -} -ATF_TEST_CASE_BODY(is_member_of_group) -{ - using tools::user::is_member_of_group; - - std::set< gid_t > groups; - gid_t maxgid = 0; - { - gid_t gids[NGROUPS_MAX]; - int ngids = ::getgroups(NGROUPS_MAX, gids); - if (ngids == -1) - ATF_FAIL("Call to ::getgroups failed"); - for (int i = 0; i < ngids; i++) { - groups.insert(gids[i]); - if (gids[i] > maxgid) - maxgid = gids[i]; - } - std::cout << "User belongs to " << ngids << " groups\n"; - std::cout << "Last GID is " << maxgid << "\n"; - } - - const gid_t maxgid_limit = 1 << 16; - if (maxgid > maxgid_limit) { - std::cout << "Test truncated from " << maxgid << " groups to " - << maxgid_limit << " to keep the run time reasonable " - "enough\n"; - maxgid = maxgid_limit; - } - - for (gid_t g = 0; g <= maxgid; g++) { - if (groups.find(g) == groups.end()) { - std::cout << "Checking if user does not belong to group " - << g << "\n"; - ATF_REQUIRE(!is_member_of_group(g)); - } else { - std::cout << "Checking if user belongs to group " << g << "\n"; - ATF_REQUIRE(is_member_of_group(g)); - } - } -} - -ATF_TEST_CASE(is_root); -ATF_TEST_CASE_HEAD(is_root) -{ - set_md_var("descr", "Tests the is_root function"); -} -ATF_TEST_CASE_BODY(is_root) -{ - using tools::user::is_root; - - if (::geteuid() == 0) { - ATF_REQUIRE(is_root()); - } else { - ATF_REQUIRE(!is_root()); - } -} - -ATF_TEST_CASE(is_unprivileged); -ATF_TEST_CASE_HEAD(is_unprivileged) -{ - set_md_var("descr", "Tests the is_unprivileged function"); -} -ATF_TEST_CASE_BODY(is_unprivileged) -{ - using tools::user::is_unprivileged; - - if (::geteuid() != 0) { - ATF_REQUIRE(is_unprivileged()); - } else { - ATF_REQUIRE(!is_unprivileged()); - } -} - -// ------------------------------------------------------------------------ -// Main. -// ------------------------------------------------------------------------ - -ATF_INIT_TEST_CASES(tcs) -{ - // Add the tests for the free functions. - ATF_ADD_TEST_CASE(tcs, euid); - ATF_ADD_TEST_CASE(tcs, is_member_of_group); - ATF_ADD_TEST_CASE(tcs, is_root); - ATF_ADD_TEST_CASE(tcs, is_unprivileged); -} diff --git a/tools/zero_tcs_helper.c b/tools/zero_tcs_helper.c deleted file mode 100644 index d4068b1..0000000 --- a/tools/zero_tcs_helper.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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 <atf-c.h> - -ATF_TP_ADD_TCS(tp) -{ - if (tp != NULL) {} /* Use tp. */ - return atf_no_error(); -} |