예제 #1
0
std::string
impl::check_requirements(const atf::tests::vars_map& metadata,
                         const atf::tests::vars_map& config)
{
    std::string failure_reason = "";

    for (atf::tests::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;
        INV(!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.machine")
            failure_reason = check_machine(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.
            INV(failure_reason.find("require.") != 0);
        }
    }

    return failure_reason;
}
예제 #2
0
std::pair< int, int >
impl::get_required_user(const atf::tests::vars_map& metadata,
                        const atf::tests::vars_map& config)
{
    const atf::tests::vars_map::const_iterator user = metadata.find(
        "require.user");
    if (user == metadata.end())
        return std::make_pair(-1, -1);

    if ((*user).second == "unprivileged") {
        if (impl::is_root()) {
            const atf::tests::vars_map::const_iterator iter = config.find(
                "unprivileged-user");
            try {
                return impl::get_user_ids((*iter).second);
            } catch (const std::exception& e) {
                UNREACHABLE;  // This has been validated by check_user.
                throw e;
            }
        } else {
            return std::make_pair(-1, -1);
        }
    } else
        return std::make_pair(-1, -1);
}
예제 #3
0
std::pair< std::string, atf::process::status >
impl::run_test_case(const atf::fs::path& executable,
                    const std::string& test_case_name,
                    const std::string& test_case_part,
                    const atf::tests::vars_map& metadata,
                    const atf::tests::vars_map& config,
                    const atf::fs::path& resfile,
                    const atf::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);
    atf::process::child child =
        atf::process::fork(run_test_case_child,
                           atf::process::stream_capture(),
                           atf::process::stream_capture(),
                           static_cast< void * >(&params));

    terminate_poll = false;

    const atf::tests::vars_map::const_iterator iter = metadata.find("timeout");
    INV(iter != metadata.end());
    const unsigned int timeout =
        atf::text::to_type< unsigned int >((*iter).second);
    const pid_t child_pid = child.pid();

    // Get the input stream of stdout and stderr.
    impl::file_handle outfh = child.stdout_fd();
    impl::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 {
        child_timer timeout_timer(timeout, child_pid, terminate_poll);
        signal_programmer sigchld(SIGCHLD, sigchld_handler);
        mux.mux(terminate_poll);
        timed_out = timeout_timer.fired();
    } catch (...) {
        UNREACHABLE;
    }

    ::killpg(child_pid, SIGKILL);
    mux.flush();
    atf::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 " + atf::text::to_string(timeout) +
            " " + (timeout == 1 ? "second" : "seconds");
    }

    return std::make_pair(reason, status);
}