NetBSD-5.0.2/dist/atf/tests/atf/test_programs/h_cpp.cpp

//
// Automated Testing Framework (atf)
//
// Copyright (c) 2007, 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/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
}

#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <stdexcept>

#include "atf-c++/env.hpp"
#include "atf-c++/fs.hpp"
#include "atf-c++/macros.hpp"
#include "atf-c++/text.hpp"

// ------------------------------------------------------------------------
// Auxiliary functions.
// ------------------------------------------------------------------------

static
void
safe_mkdir(const char* path)
{
    if (::mkdir(path, 0755) == -1)
        ATF_FAIL(std::string("mkdir(2) of ") + path + " failed");
}

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 "t_cleanup".
// ------------------------------------------------------------------------

ATF_TEST_CASE_WITH_CLEANUP(cleanup_pass);
ATF_TEST_CASE_HEAD(cleanup_pass)
{
    set_md_var("descr", "Helper test case for the t_cleanup test program");
}
ATF_TEST_CASE_BODY(cleanup_pass)
{
    touch(get_config_var("tmpfile"));
}
ATF_TEST_CASE_CLEANUP(cleanup_pass)
{
    if (atf::text::to_bool(get_config_var("cleanup")))
        atf::fs::remove(atf::fs::path(get_config_var("tmpfile")));
}

ATF_TEST_CASE_WITH_CLEANUP(cleanup_fail);
ATF_TEST_CASE_HEAD(cleanup_fail)
{
    set_md_var("descr", "Helper test case for the t_cleanup test program");
}
ATF_TEST_CASE_BODY(cleanup_fail)
{
    touch(get_config_var("tmpfile"));
    ATF_FAIL("On purpose");
}
ATF_TEST_CASE_CLEANUP(cleanup_fail)
{
    if (atf::text::to_bool(get_config_var("cleanup")))
        atf::fs::remove(atf::fs::path(get_config_var("tmpfile")));
}

ATF_TEST_CASE_WITH_CLEANUP(cleanup_skip);
ATF_TEST_CASE_HEAD(cleanup_skip)
{
    set_md_var("descr", "Helper test case for the t_cleanup test program");
}
ATF_TEST_CASE_BODY(cleanup_skip)
{
    touch(get_config_var("tmpfile"));
    ATF_SKIP("On purpose");
}
ATF_TEST_CASE_CLEANUP(cleanup_skip)
{
    if (atf::text::to_bool(get_config_var("cleanup")))
        atf::fs::remove(atf::fs::path(get_config_var("tmpfile")));
}

ATF_TEST_CASE_WITH_CLEANUP(cleanup_curdir);
ATF_TEST_CASE_HEAD(cleanup_curdir)
{
    set_md_var("descr", "Helper test case for the t_cleanup 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 << std::endl;
        is.close();
    }
}

ATF_TEST_CASE_WITH_CLEANUP(cleanup_sigterm);
ATF_TEST_CASE_HEAD(cleanup_sigterm)
{
    set_md_var("descr", "Helper test case for the t_cleanup test program");
}
ATF_TEST_CASE_BODY(cleanup_sigterm)
{
    touch(get_config_var("tmpfile"));
    ::kill(::getpid(), SIGTERM);
    touch(get_config_var("tmpfile") + ".no");
}
ATF_TEST_CASE_CLEANUP(cleanup_sigterm)
{
    atf::fs::remove(atf::fs::path(get_config_var("tmpfile")));
}

ATF_TEST_CASE_WITH_CLEANUP(cleanup_fork);
ATF_TEST_CASE_HEAD(cleanup_fork)
{
    set_md_var("descr", "Helper test case for the t_cleanup test program");
}
ATF_TEST_CASE_BODY(cleanup_fork)
{
}
ATF_TEST_CASE_CLEANUP(cleanup_fork)
{
    ::close(STDOUT_FILENO);
    ::close(STDERR_FILENO);
    ::close(3);
}

// ------------------------------------------------------------------------
// Helper tests for "t_config".
// ------------------------------------------------------------------------

ATF_TEST_CASE(config_unset);
ATF_TEST_CASE_HEAD(config_unset)
{
    set_md_var("descr", "Helper test case for the t_config test program");
}
ATF_TEST_CASE_BODY(config_unset)
{
    ATF_CHECK(!has_config_var("test"));
}

ATF_TEST_CASE(config_empty);
ATF_TEST_CASE_HEAD(config_empty)
{
    set_md_var("descr", "Helper test case for the t_config test program");
}
ATF_TEST_CASE_BODY(config_empty)
{
    ATF_CHECK_EQUAL(get_config_var("test"), "");
}

ATF_TEST_CASE(config_value);
ATF_TEST_CASE_HEAD(config_value)
{
    set_md_var("descr", "Helper test case for the t_config test program");
}
ATF_TEST_CASE_BODY(config_value)
{
    ATF_CHECK_EQUAL(get_config_var("test"), "foo");
}

ATF_TEST_CASE(config_multi_value);
ATF_TEST_CASE_HEAD(config_multi_value)
{
    set_md_var("descr", "Helper test case for the t_config test program");
}
ATF_TEST_CASE_BODY(config_multi_value)
{
    ATF_CHECK_EQUAL(get_config_var("test"), "foo bar");
}

// ------------------------------------------------------------------------
// Helper tests for "t_env".
// ------------------------------------------------------------------------

ATF_TEST_CASE(env_home);
ATF_TEST_CASE_HEAD(env_home)
{
    set_md_var("descr", "Helper test case for the t_env test program");
}
ATF_TEST_CASE_BODY(env_home)
{
    ATF_CHECK(atf::env::has("HOME"));
    atf::fs::path p(atf::env::get("HOME"));
    atf::fs::file_info fi1(p);
    atf::fs::file_info fi2(atf::fs::get_current_dir());
    ATF_CHECK_EQUAL(fi1.get_device(), fi2.get_device());
    ATF_CHECK_EQUAL(fi1.get_inode(), fi2.get_inode());
}

ATF_TEST_CASE(env_list);
ATF_TEST_CASE_HEAD(env_list)
{
    set_md_var("descr", "Helper test case for the t_env test program");
}
ATF_TEST_CASE_BODY(env_list)
{
    int exitcode = std::system("env");
    ATF_CHECK(WIFEXITED(exitcode));
    ATF_CHECK(WEXITSTATUS(exitcode) == EXIT_SUCCESS);
}

// ------------------------------------------------------------------------
// Helper tests for "t_fork".
// ------------------------------------------------------------------------

ATF_TEST_CASE(fork_mangle_fds);
ATF_TEST_CASE_HEAD(fork_mangle_fds)
{
    set_md_var("descr", "Helper test case for the t_fork test program");
}
ATF_TEST_CASE_BODY(fork_mangle_fds)
{
    int resfd = std::atoi(get_config_var("resfd").c_str());

    if (::close(STDIN_FILENO) == -1)
        ATF_FAIL("Failed to close stdin");
    if (::close(STDOUT_FILENO) == -1)
        ATF_FAIL("Failed to close stdout");
    if (::close(STDERR_FILENO) == -1)
        ATF_FAIL("Failed to close stderr");
    if (::close(resfd) == -1)
        ATF_FAIL("Failed to close results descriptor");

#if defined(F_CLOSEM)
    if (::fcntl(0, F_CLOSEM) == -1)
        ATF_FAIL("Failed to close everything");
#endif
}

ATF_TEST_CASE(fork_stop);
ATF_TEST_CASE_HEAD(fork_stop)
{
    set_md_var("descr", "Helper test case for the t_fork test program");
}
ATF_TEST_CASE_BODY(fork_stop)
{
    std::ofstream os(get_config_var("pidfile").c_str());
    os << ::getpid() << std::endl;
    os.close();
    std::cout << "Wrote pid file" << std::endl;
    std::cout << "Waiting for done file" << std::endl;
    while (::access(get_config_var("donefile").c_str(), F_OK) != 0)
        ::usleep(10000);
    std::cout << "Exiting" << std::endl;
}

ATF_TEST_CASE(fork_umask);
ATF_TEST_CASE_HEAD(fork_umask)
{
    set_md_var("descr", "Helper test case for the t_fork test program");
}
ATF_TEST_CASE_BODY(fork_umask)
{
    mode_t m = ::umask(0);
    std::cout << "umask: " << std::setw(4) << std::setfill('0')
              << std::oct << m << std::endl;
    (void)::umask(m);
}

// ------------------------------------------------------------------------
// Helper tests for "t_meta_data".
// ------------------------------------------------------------------------

ATF_TEST_CASE(ident_1);
ATF_TEST_CASE_HEAD(ident_1)
{
    set_md_var("descr", "Helper test case for the t_meta_data test program");
}
ATF_TEST_CASE_BODY(ident_1)
{
    ATF_CHECK_EQUAL(get_md_var("ident"), "ident_1");
}

ATF_TEST_CASE(ident_2);
ATF_TEST_CASE_HEAD(ident_2)
{
    set_md_var("descr", "Helper test case for the t_meta_data test program");
}
ATF_TEST_CASE_BODY(ident_2)
{
    ATF_CHECK_EQUAL(get_md_var("ident"), "ident_2");
}

ATF_TEST_CASE(require_arch);
ATF_TEST_CASE_HEAD(require_arch)
{
    set_md_var("descr", "Helper test case for the t_meta_data 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_meta_data test program");
    set_md_var("require.config", "var1 var2");
}
ATF_TEST_CASE_BODY(require_config)
{
    std::cout << "var1: " << get_config_var("var1") << std::endl;
    std::cout << "var2: " << get_config_var("var2") << std::endl;
}

ATF_TEST_CASE(require_machine);
ATF_TEST_CASE_HEAD(require_machine)
{
    set_md_var("descr", "Helper test case for the t_meta_data test program");
    set_md_var("require.machine", get_config_var("machine", "not-set"));
}
ATF_TEST_CASE_BODY(require_machine)
{
}

ATF_TEST_CASE(require_progs_body);
ATF_TEST_CASE_HEAD(require_progs_body)
{
    set_md_var("descr", "Helper test case for the t_meta_data test program");
}
ATF_TEST_CASE_BODY(require_progs_body)
{
    require_prog(get_config_var("progs"));
}

ATF_TEST_CASE(require_progs_head);
ATF_TEST_CASE_HEAD(require_progs_head)
{
    set_md_var("descr", "Helper test case for the t_meta_data test program");
    set_md_var("require.progs", get_config_var("progs", "not-set"));
}
ATF_TEST_CASE_BODY(require_progs_head)
{
}

ATF_TEST_CASE(require_user);
ATF_TEST_CASE_HEAD(require_user)
{
    set_md_var("descr", "Helper test case for the t_meta_data test program");
    set_md_var("require.user", get_config_var("user", "not-set"));
}
ATF_TEST_CASE_BODY(require_user)
{
}

ATF_TEST_CASE(require_user2);
ATF_TEST_CASE_HEAD(require_user2)
{
    set_md_var("descr", "Helper test case for the t_meta_data test program");
    set_md_var("require.user", get_config_var("user2", "not-set"));
}
ATF_TEST_CASE_BODY(require_user2)
{
}

ATF_TEST_CASE(require_user3);
ATF_TEST_CASE_HEAD(require_user3)
{
    set_md_var("descr", "Helper test case for the t_meta_data test program");
    set_md_var("require.user", get_config_var("user3", "not-set"));
}
ATF_TEST_CASE_BODY(require_user3)
{
}

ATF_TEST_CASE(timeout);
ATF_TEST_CASE_HEAD(timeout)
{
    set_md_var("descr", "Helper test case for the t_meta_data test program");
    set_md_var("timeout", get_config_var("timeout", "0"));
}
ATF_TEST_CASE_BODY(timeout)
{
    sleep(atf::text::to_type< int >(get_config_var("sleep")));
}

ATF_TEST_CASE(timeout2);
ATF_TEST_CASE_HEAD(timeout2)
{
    set_md_var("descr", "Helper test case for the t_meta_data test program");
    set_md_var("timeout", get_config_var("timeout2", "0"));
}
ATF_TEST_CASE_BODY(timeout2)
{
    sleep(atf::text::to_type< int >(get_config_var("sleep2")));
}

// ------------------------------------------------------------------------
// Helper tests for "t_srcdir".
// ------------------------------------------------------------------------

ATF_TEST_CASE(srcdir_exists);
ATF_TEST_CASE_HEAD(srcdir_exists)
{
    set_md_var("descr", "Helper test case for the t_srcdir test program");
}
ATF_TEST_CASE_BODY(srcdir_exists)
{
    if (!atf::fs::exists(atf::fs::path(get_config_var("srcdir")) /
        "datafile"))
        ATF_FAIL("Cannot find datafile");
}

// ------------------------------------------------------------------------
// Helper tests for "t_status".
// ------------------------------------------------------------------------

ATF_TEST_CASE(status_newlines_fail);
ATF_TEST_CASE_HEAD(status_newlines_fail)
{
    set_md_var("descr", "Helper test case for the t_status test program");
}
ATF_TEST_CASE_BODY(status_newlines_fail)
{
    ATF_FAIL("First line\nSecond line");
}

ATF_TEST_CASE(status_newlines_skip);
ATF_TEST_CASE_HEAD(status_newlines_skip)
{
    set_md_var("descr", "Helper test case for the t_status test program");
}
ATF_TEST_CASE_BODY(status_newlines_skip)
{
    ATF_SKIP("First line\nSecond line");
}

// ------------------------------------------------------------------------
// Helper tests for "t_workdir".
// ------------------------------------------------------------------------

ATF_TEST_CASE(workdir_path);
ATF_TEST_CASE_HEAD(workdir_path)
{
    set_md_var("descr", "Helper test case for the t_workdir test program");
}
ATF_TEST_CASE_BODY(workdir_path)
{
    const std::string& p = get_config_var("pathfile");

    std::ofstream os(p.c_str());
    if (!os)
        ATF_FAIL("Could not open " + p + " for writing");

    os << atf::fs::get_current_dir().str() << std::endl;

    os.close();
}

ATF_TEST_CASE(workdir_cleanup);
ATF_TEST_CASE_HEAD(workdir_cleanup)
{
    set_md_var("descr", "Helper test case for the t_workdir test program");
}
ATF_TEST_CASE_BODY(workdir_cleanup)
{
    const std::string& p = get_config_var("pathfile");

    std::ofstream os(p.c_str());
    if (!os)
        ATF_FAIL("Could not open " + p + " for writing");

    os << atf::fs::get_current_dir().str() << std::endl;

    os.close();

    safe_mkdir("1");
    safe_mkdir("1/1");
    safe_mkdir("1/2");
    safe_mkdir("1/3");
    safe_mkdir("1/3/1");
    safe_mkdir("1/3/2");
    safe_mkdir("2");
    touch("2/1");
    touch("2/2");
    safe_mkdir("2/3");
    touch("2/3/1");
}

// ------------------------------------------------------------------------
// Main.
// ------------------------------------------------------------------------

ATF_INIT_TEST_CASES(tcs)
{
    // Add helper tests for t_cleanup.
    ATF_ADD_TEST_CASE(tcs, cleanup_pass);
    ATF_ADD_TEST_CASE(tcs, cleanup_fail);
    ATF_ADD_TEST_CASE(tcs, cleanup_skip);
    ATF_ADD_TEST_CASE(tcs, cleanup_curdir);
    ATF_ADD_TEST_CASE(tcs, cleanup_sigterm);
    ATF_ADD_TEST_CASE(tcs, cleanup_fork);

    // Add helper tests for t_config.
    ATF_ADD_TEST_CASE(tcs, config_unset);
    ATF_ADD_TEST_CASE(tcs, config_empty);
    ATF_ADD_TEST_CASE(tcs, config_value);
    ATF_ADD_TEST_CASE(tcs, config_multi_value);

    // Add helper tests for t_env.
    ATF_ADD_TEST_CASE(tcs, env_home);
    ATF_ADD_TEST_CASE(tcs, env_list);

    // Add helper tests for t_fork.
    ATF_ADD_TEST_CASE(tcs, fork_mangle_fds);
    ATF_ADD_TEST_CASE(tcs, fork_stop);
    ATF_ADD_TEST_CASE(tcs, fork_umask);

    // Add helper tests for t_meta_data.
    ATF_ADD_TEST_CASE(tcs, ident_1);
    ATF_ADD_TEST_CASE(tcs, ident_2);
    ATF_ADD_TEST_CASE(tcs, require_arch);
    ATF_ADD_TEST_CASE(tcs, require_config);
    ATF_ADD_TEST_CASE(tcs, require_machine);
    ATF_ADD_TEST_CASE(tcs, require_progs_body);
    ATF_ADD_TEST_CASE(tcs, require_progs_head);
    ATF_ADD_TEST_CASE(tcs, require_user);
    ATF_ADD_TEST_CASE(tcs, require_user2);
    ATF_ADD_TEST_CASE(tcs, require_user3);
    ATF_ADD_TEST_CASE(tcs, timeout);
    ATF_ADD_TEST_CASE(tcs, timeout2);

    // Add helper tests for t_srcdir.
    ATF_ADD_TEST_CASE(tcs, srcdir_exists);

    // Add helper tests for t_status.
    ATF_ADD_TEST_CASE(tcs, status_newlines_fail);
    ATF_ADD_TEST_CASE(tcs, status_newlines_skip);

    // Add helper tests for t_workdir.
    ATF_ADD_TEST_CASE(tcs, workdir_path);
    ATF_ADD_TEST_CASE(tcs, workdir_cleanup);
}