head	1.2;
access;
symbols
	perseant-exfatfs-base-20250801:1.2
	perseant-exfatfs-base-20240630:1.2
	perseant-exfatfs:1.2.0.24
	perseant-exfatfs-base:1.2
	cjep_sun2x:1.2.0.22
	cjep_sun2x-base:1.2
	cjep_staticlib_x-base1:1.2
	cjep_staticlib_x:1.2.0.20
	cjep_staticlib_x-base:1.2
	phil-wifi-20200421:1.2
	phil-wifi-20200411:1.2
	phil-wifi-20200406:1.2
	pgoyette-compat-merge-20190127:1.2
	pgoyette-compat-20190127:1.2
	pgoyette-compat-20190118:1.2
	pgoyette-compat-1226:1.2
	pgoyette-compat-1126:1.2
	pgoyette-compat-1020:1.2
	pgoyette-compat-0930:1.2
	pgoyette-compat-0906:1.2
	pgoyette-compat-0728:1.2
	pgoyette-compat-0625:1.2
	pgoyette-compat-0521:1.2
	pgoyette-compat-0502:1.2
	pgoyette-compat-0422:1.2
	pgoyette-compat-0415:1.2
	pgoyette-compat-0407:1.2
	pgoyette-compat-0330:1.2
	pgoyette-compat-0322:1.2
	pgoyette-compat-0315:1.2
	pgoyette-compat:1.2.0.18
	pgoyette-compat-base:1.2
	perseant-stdc-iso10646:1.2.0.16
	perseant-stdc-iso10646-base:1.2
	prg-localcount2-base3:1.2
	prg-localcount2-base2:1.2
	prg-localcount2-base1:1.2
	prg-localcount2:1.2.0.14
	prg-localcount2-base:1.2
	pgoyette-localcount-20170426:1.2
	bouyer-socketcan-base1:1.2
	pgoyette-localcount-20170320:1.2
	bouyer-socketcan:1.2.0.12
	bouyer-socketcan-base:1.2
	pgoyette-localcount-20170107:1.2
	pgoyette-localcount-20161104:1.2
	localcount-20160914:1.2
	pgoyette-localcount-20160806:1.2
	pgoyette-localcount-20160726:1.2
	pgoyette-localcount:1.2.0.10
	pgoyette-localcount-base:1.2
	yamt-pagecache-base9:1.2
	yamt-pagecache-tag8:1.2
	tls-earlyentropy:1.2.0.6
	tls-earlyentropy-base:1.2
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.2
	riastradh-drm2-base3:1.2
	agc-symver:1.2.0.8
	agc-symver-base:1.2
	tls-maxphys-base:1.2
	yamt-pagecache-base8:1.2
	yamt-pagecache-base7:1.2
	yamt-pagecache-base6:1.2
	yamt-pagecache-base5:1.2
	yamt-pagecache-base4:1.2
	yamt-pagecache-base3:1.2
	yamt-pagecache-base2:1.2
	yamt-pagecache:1.2.0.4
	yamt-pagecache-base:1.2
	bouyer-quota2-nbase:1.2
	bouyer-quota2:1.2.0.2
	bouyer-quota2-base:1.2
	atf-0-7:1.1.1.2
	matt-premerge-20091211:1.1.1.1
	jym-xensuspend-nbase:1.1.1.1
	jym-xensuspend:1.1.1.1.0.2
	jym-xensuspend-base:1.1.1.1
	atf-0-6:1.1.1.1
	TNF:1.1.1;
locks; strict;
comment	@// @;


1.2
date	2010.05.08.08.11.05;	author jmmv;	state dead;
branches;
next	1.1;

1.1
date	2009.01.19.07.11.52;	author jmmv;	state Exp;
branches
	1.1.1.1;
next	;

1.1.1.1
date	2009.01.19.07.11.52;	author jmmv;	state Exp;
branches;
next	1.1.1.2;

1.1.1.2
date	2009.12.22.13.26.07;	author jmmv;	state Exp;
branches;
next	;


desc
@@


1.2
log
@Merge atf 0.8.
@
text
@//
// 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/time.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
}

#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>

#include "atf-c++/application.hpp"
#include "atf-c++/exceptions.hpp"
#include "atf-c++/process.hpp"
#include "atf-c++/sanity.hpp"
#include "atf-c++/signals.hpp"
#include "atf-c++/text.hpp"

namespace sigalarm {
    static bool happened = false;

    void
    handler(int signo)
    {
        happened = true;
    }
}

class atf_exec : public atf::application::app {
    static const char* m_description;

    std::string specific_args(void) const;
    options_set specific_options(void) const;
    void process_option(int, const char*);

    void process_option_t(const std::string&);
    unsigned int m_timeout_secs;
    std::string m_timeout_file;

public:
    atf_exec(void);

    int main(void);
};

const char* atf_exec::m_description =
    "atf-exec executes the given command in a controlled manner.";

atf_exec::atf_exec(void) :
    app(m_description, "atf-exec(1)", "atf(7)"),
    m_timeout_secs(0)
{
}

std::string
atf_exec::specific_args(void)
    const
{
    return "<command>";
}

atf_exec::options_set
atf_exec::specific_options(void)
    const
{
    using atf::application::option;
    options_set opts;
    opts.insert(option('t', "secs:file", "Kills the command after the "
                                         "specified amount of time and "
                                         "creates the given file"));
    return opts;
}

void
atf_exec::process_option_t(const std::string& arg)
{
    using atf::application::usage_error;

    std::string::size_type pos = arg.find(':');
    if (pos == std::string::npos)
        throw usage_error("Invalid value for -t option; must be of the "
                          "form secs:file");
    if (pos == 0)
        throw usage_error("Invalid value for -t option; secs cannot be "
                          "empty");
    if (pos == arg.length() - 1)
        throw usage_error("Invalid value for -t option; file cannot be "
                          "empty");

    m_timeout_secs = atf::text::to_type< unsigned int >(arg.substr(0, pos));
    m_timeout_file = arg.substr(pos + 1);
}

void
atf_exec::process_option(int ch, const char* arg)
{
    switch (ch) {
    case 't':
        process_option_t(arg);
        break;

    default:
        UNREACHABLE;
    }
}

int
atf_exec::main(void)
{
    if (m_argc < 1)
        throw atf::application::usage_error("No command specified");

    int exitcode = EXIT_FAILURE;

    pid_t pid = atf::process::fork();
    if (pid == 0) {
        if (::setpgid(::getpid(), 0) == -1)
            throw atf::system_error("main", "setpgid failed", errno);

        char** argv = new char*[m_argc + 1];
        for (int i = 0; i < m_argc; i++)
            argv[i] = ::strdup(m_argv[i]);
        argv[m_argc] = NULL;

        ::execvp(m_argv[0], argv);
        return EXIT_FAILURE;
    } else {
        atf::signals::signal_programmer sp(SIGALRM, sigalarm::handler);

        if (m_timeout_secs > 0) {
            struct itimerval itv;

            timerclear(&itv.it_interval);
            timerclear(&itv.it_value);
            itv.it_value.tv_sec = m_timeout_secs;
            if (setitimer(ITIMER_REAL, &itv, NULL) == -1)
                throw atf::system_error("main", "setitimer failed", errno);
        }

        int status;
        if (::waitpid(pid, &status, 0) != pid) {
            if (!(errno == EINTR && sigalarm::happened))
                throw atf::system_error("main", "waitpid failed", errno);
        }

        if (sigalarm::happened) {
            INV(m_timeout_secs > 0);

            ::killpg(pid, SIGTERM);

            std::ofstream os(m_timeout_file.c_str());
            os.close();

            INV(exitcode == EXIT_FAILURE);
        } else {
            if (WIFEXITED(status))
                exitcode = WEXITSTATUS(status);
            else if (WIFSIGNALED(status))
                ::kill(0, WTERMSIG(status));
            else
                UNREACHABLE;
        }
    }

    return exitcode;
}

int
main(int argc, char* const* argv)
{
    return atf_exec().run(argc, argv);
}
@


1.1
log
@Initial revision
@
text
@@


1.1.1.1
log
@Import ATF 0.6.  Replaces the old ATF 0.5 that was in dist/atf.

Changes in this release:

* Make atf-exec be able to kill its child process after a certain period of
  time; this is controlled through the new -t option.

* Change atf-sh to use atf-exec's -t option to control the test case's
  timeouts, instead of doing it internally.  Same behavior as before, but
  noticeably faster.

* atf-exec's -g option and atf-killpg are gone due to the previous change.

* Added the atf-check(1) tool, a program that executes a given command and
  checks its exit code against a known value and allows the management of
  stdout and stderr in multiple ways.  This replaces the previous atf_check
  function in the atf-sh library and exposes this functionality to both
  atf-c and atf-c++.

* Added the ATF_REQUIRE family of macros to the C interface.  These help
  in checking for fatal test conditions.  The old ATF_CHECK macros now
  perform non-fatal checks only.  I.e. by using ATF_CHECK, the test case
  can now continue its execution and the failures will not be reported
  until the end of the whole run.

* Extended the amount of ATF_CHECK_* C macros with new ones to provide more
  features to the developer.  These also have their corresponding
  counterparts in the ATF_REQUIRE_* family.  The new macros (listing the
  suffixes only) are: _EQ (replaces _EQUAL), _EQ_MSG, _STREQ and
  _STREQ_MSG.
@
text
@@


1.1.1.2
log
@Import atf 0.7.  Changes in this release:

* Added build-time checks to atf-c and atf-c++.  A binding for atf-sh
  will come later.

* Migrated all build-time checks for header files to proper ATF tests.
  This demonstrates the use of the new feature described above.

* Added an internal API for child process management.

* Converted all plain-text distribution documents to a Docbook canonical
  version, and include pre-generated plain text and HTML copies in the
  distribution file.

* Simplified the contents of the Makefile.am by regenerating it from a
  canonical Makefile.am.m4 source.  As a side-effect, some dependency
  specifications were fixed.

* Migrated all checks from the check target to installcheck, as these
  require ATF to be installed.

* Fixed sign comparison mismatches triggered by the now-enabled
  -Wsign-compare.

* Fixed many memory and object leaks.
@
text
@d4 1
a4 1
// Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
d33 1
a71 5
    static void route_do_exec(void *);
    void do_exec(void) const;

    static int handle_status(const atf::process::status&);

a138 39
void
atf_exec::route_do_exec(void *v)
{
    atf_exec* ae = static_cast< atf_exec* >(v);
    ae->do_exec();
}

void
atf_exec::do_exec(void)
    const
{
    if (::setpgid(::getpid(), 0) == -1)
        throw atf::system_error("main", "setpgid failed", errno);

    char** argv = new char*[m_argc + 1];
    for (int i = 0; i < m_argc; i++)
        argv[i] = ::strdup(m_argv[i]);
    argv[m_argc] = NULL;

    ::execvp(m_argv[0], argv);
    // TODO: Handle error code from execvp.
    std::abort();
}

int
atf_exec::handle_status(const atf::process::status& s)
{
    int exitcode = EXIT_FAILURE;

    if (s.exited())
        exitcode = s.exitstatus();
    else if (s.signaled())
        ::kill(0, s.termsig());
    else
        UNREACHABLE;

    return exitcode;
}

d145 50
a194 16
    atf::process::child c =
        atf::process::fork(route_do_exec,
                           atf::process::stream_inherit(),
                           atf::process::stream_inherit(),
                           this);

    atf::signals::signal_programmer sp(SIGALRM, sigalarm::handler);

    if (m_timeout_secs > 0) {
        struct itimerval itv;

        timerclear(&itv.it_interval);
        timerclear(&itv.it_value);
        itv.it_value.tv_sec = m_timeout_secs;
        if (setitimer(ITIMER_REAL, &itv, NULL) == -1)
            throw atf::system_error("main", "setitimer failed", errno);
a196 23
    int exitcode;
    try {
        const atf::process::status s = c.wait();
        exitcode = handle_status(s);
    } catch (const atf::system_error& e) {
        if (e.code() == EINTR) {
            if (sigalarm::happened) {
                INV(m_timeout_secs > 0);

                ::killpg(c.pid(), SIGTERM);

                std::ofstream os(m_timeout_file.c_str());
                os.close();

                exitcode = EXIT_FAILURE;
                (void)c.wait();
            } else {
                // TODO: Retry wait.
                abort();
            }
        } else
            throw;
    }
@

