143412Snewton//
243412Snewton// Automated Testing Framework (atf)
343412Snewton//
443412Snewton// Copyright (c) 2007 The NetBSD Foundation, Inc.
543412Snewton// All rights reserved.
643412Snewton//
743412Snewton// Redistribution and use in source and binary forms, with or without
843412Snewton// modification, are permitted provided that the following conditions
943412Snewton// are met:
1043412Snewton// 1. Redistributions of source code must retain the above copyright
1143412Snewton//    notice, this list of conditions and the following disclaimer.
1243412Snewton// 2. Redistributions in binary form must reproduce the above copyright
1343412Snewton//    notice, this list of conditions and the following disclaimer in the
1443412Snewton//    documentation and/or other materials provided with the distribution.
1543412Snewton//
1643412Snewton// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
1743412Snewton// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
1843412Snewton// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1943412Snewton// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2043412Snewton// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
2143412Snewton// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2243412Snewton// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
2343412Snewton// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2443412Snewton// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
2543412Snewton// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2643412Snewton// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
2743412Snewton// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2843412Snewton//
2943412Snewton
3043412Snewtonextern "C" {
3143412Snewton#include <fcntl.h>
3243412Snewton#include <signal.h>
3343412Snewton#include <unistd.h>
3443412Snewton}
3543412Snewton
36139743Simp#include <cstdlib>
3743412Snewton#include <cstring>
3843412Snewton#include <fstream>
3943412Snewton#include <iostream>
4043412Snewton#include <list>
4143412Snewton#include <memory>
4243412Snewton#include <vector>
4343412Snewton
4443412Snewton#include <atf-c++.hpp>
4543412Snewton
4643412Snewton#include "check.hpp"
4743412Snewton#include "config.hpp"
4843412Snewton#include "utils.hpp"
4943412Snewton
5043412Snewton#include "detail/fs.hpp"
5143412Snewton#include "detail/process.hpp"
5243412Snewton#include "detail/test_helpers.hpp"
5343412Snewton#include "detail/text.hpp"
5443412Snewton
5543412Snewton// ------------------------------------------------------------------------
5643412Snewton// Auxiliary functions.
5743412Snewton// ------------------------------------------------------------------------
5843412Snewton
5943412Snewtonstatic
6043412Snewtonstd::auto_ptr< atf::check::check_result >
6143412Snewtondo_exec(const atf::tests::tc* tc, const char* helper_name)
6243412Snewton{
6343412Snewton    std::vector< std::string > argv;
6443412Snewton    argv.push_back(get_process_helpers_path(*tc, false).str());
6543412Snewton    argv.push_back(helper_name);
6643412Snewton    std::cout << "Executing " << argv[0] << " " << argv[1] << "\n";
6743412Snewton
6843412Snewton    atf::process::argv_array argva(argv);
6943412Snewton    return atf::check::exec(argva);
70116174Sobrien}
7143412Snewton
7243412Snewtonstatic
73116174Sobrienstd::auto_ptr< atf::check::check_result >
74116174Sobriendo_exec(const atf::tests::tc* tc, const char* helper_name, const char *carg2)
75116174Sobrien{
76147817Sjhb    std::vector< std::string > argv;
77147817Sjhb    argv.push_back(get_process_helpers_path(*tc, false).str());
7843412Snewton    argv.push_back(helper_name);
79147817Sjhb    argv.push_back(carg2);
80147817Sjhb    std::cout << "Executing " << argv[0] << " " << argv[1] << " "
8143412Snewton              << argv[2] << "\n";
82147817Sjhb
83147817Sjhb    atf::process::argv_array argva(argv);
84147817Sjhb    return atf::check::exec(argva);
85147817Sjhb}
86147817Sjhb
8743412Snewton// ------------------------------------------------------------------------
8843412Snewton// Helper test cases for the free functions.
8965302Sobrien// ------------------------------------------------------------------------
9065302Sobrien
9165302SobrienATF_TEST_CASE(h_build_c_o_ok);
9265302SobrienATF_TEST_CASE_HEAD(h_build_c_o_ok)
9365302Sobrien{
9465302Sobrien    set_md_var("descr", "Helper test case for build_c_o");
9543412Snewton}
9643412SnewtonATF_TEST_CASE_BODY(h_build_c_o_ok)
9792761Salfred{
9892761Salfred    std::ofstream sfile("test.c");
9992761Salfred    sfile << "#include <stdio.h>\n";
10092761Salfred    sfile.close();
10143412Snewton
10243412Snewton    ATF_REQUIRE(atf::check::build_c_o("test.c", "test.o",
10343412Snewton                                      atf::process::argv_array()));
10492761Salfred}
10592761Salfred
10692761SalfredATF_TEST_CASE(h_build_c_o_fail);
10792761SalfredATF_TEST_CASE_HEAD(h_build_c_o_fail)
10892761Salfred{
10992761Salfred    set_md_var("descr", "Helper test case for build_c_o");
110147817Sjhb}
111147817SjhbATF_TEST_CASE_BODY(h_build_c_o_fail)
112147817Sjhb{
11343412Snewton    std::ofstream sfile("test.c");
11443412Snewton    sfile << "void foo(void) { int a = UNDEFINED_SYMBOL; }\n";
11543412Snewton    sfile.close();
11692761Salfred
11792761Salfred    ATF_REQUIRE(!atf::check::build_c_o("test.c", "test.o",
11892761Salfred                                       atf::process::argv_array()));
11992761Salfred}
120147817Sjhb
121147817SjhbATF_TEST_CASE(h_build_cpp_ok);
122147817SjhbATF_TEST_CASE_HEAD(h_build_cpp_ok)
123147817Sjhb{
12443412Snewton    set_md_var("descr", "Helper test case for build_cpp");
12543412Snewton}
12643412SnewtonATF_TEST_CASE_BODY(h_build_cpp_ok)
12792761Salfred{
12892761Salfred    std::ofstream sfile("test.c");
12992761Salfred    sfile << "#define A foo\n";
13092761Salfred    sfile << "#define B bar\n";
131147817Sjhb    sfile << "A B\n";
132147817Sjhb    sfile.close();
133147817Sjhb
134147817Sjhb    ATF_REQUIRE(atf::check::build_cpp("test.c", "test.p",
13543412Snewton                                      atf::process::argv_array()));
13643412Snewton}
13743412Snewton
13843412SnewtonATF_TEST_CASE(h_build_cpp_fail);
13943412SnewtonATF_TEST_CASE_HEAD(h_build_cpp_fail)
14043412Snewton{
14143412Snewton    set_md_var("descr", "Helper test case for build_cpp");
14243412Snewton}
14343412SnewtonATF_TEST_CASE_BODY(h_build_cpp_fail)
14443412Snewton{
14543412Snewton    std::ofstream sfile("test.c");
14643412Snewton    sfile << "#include \"./non-existent.h\"\n";
14743412Snewton    sfile.close();
14843412Snewton
14943412Snewton    ATF_REQUIRE(!atf::check::build_cpp("test.c", "test.p",
15043412Snewton                                       atf::process::argv_array()));
15143412Snewton}
15243412Snewton
15343412SnewtonATF_TEST_CASE(h_build_cxx_o_ok);
15443412SnewtonATF_TEST_CASE_HEAD(h_build_cxx_o_ok)
15543412Snewton{
15643412Snewton    set_md_var("descr", "Helper test case for build_cxx_o");
15743412Snewton}
15843412SnewtonATF_TEST_CASE_BODY(h_build_cxx_o_ok)
15943412Snewton{
16043412Snewton    std::ofstream sfile("test.cpp");
16143412Snewton    sfile << "#include <iostream>\n";
16243412Snewton    sfile.close();
16343412Snewton
16443412Snewton    ATF_REQUIRE(atf::check::build_cxx_o("test.cpp", "test.o",
16543412Snewton                                        atf::process::argv_array()));
16643412Snewton}
16743412Snewton
16843412SnewtonATF_TEST_CASE(h_build_cxx_o_fail);
16943412SnewtonATF_TEST_CASE_HEAD(h_build_cxx_o_fail)
17043412Snewton{
17143412Snewton    set_md_var("descr", "Helper test case for build_cxx_o");
17243412Snewton}
17343412SnewtonATF_TEST_CASE_BODY(h_build_cxx_o_fail)
17443412Snewton{
17543412Snewton    std::ofstream sfile("test.cpp");
17643412Snewton    sfile << "void foo(void) { int a = UNDEFINED_SYMBOL; }\n";
17743412Snewton    sfile.close();
17843412Snewton
17943412Snewton    ATF_REQUIRE(!atf::check::build_cxx_o("test.cpp", "test.o",
18043412Snewton                                         atf::process::argv_array()));
18143412Snewton}
18243412Snewton
18343412Snewton// ------------------------------------------------------------------------
18443412Snewton// Test cases for the free functions.
18543412Snewton// ------------------------------------------------------------------------
18643412Snewton
18743412SnewtonATF_TEST_CASE(build_c_o);
18843412SnewtonATF_TEST_CASE_HEAD(build_c_o)
18943412Snewton{
19043412Snewton    set_md_var("descr", "Tests the build_c_o function");
19143412Snewton}
19243412SnewtonATF_TEST_CASE_BODY(build_c_o)
19343412Snewton{
19443412Snewton    ATF_TEST_CASE_USE(h_build_c_o_ok);
19543412Snewton    run_h_tc< ATF_TEST_CASE_NAME(h_build_c_o_ok) >();
19643412Snewton    ATF_REQUIRE(grep_file("stdout", "-o test.o"));
19743412Snewton    ATF_REQUIRE(grep_file("stdout", "-c test.c"));
19843412Snewton
19943412Snewton    ATF_TEST_CASE_USE(h_build_c_o_fail);
20043412Snewton    run_h_tc< ATF_TEST_CASE_NAME(h_build_c_o_fail) >();
20143412Snewton    ATF_REQUIRE(grep_file("stdout", "-o test.o"));
20243412Snewton    ATF_REQUIRE(grep_file("stdout", "-c test.c"));
20343412Snewton    ATF_REQUIRE(grep_file("stderr", "test.c"));
20443412Snewton    ATF_REQUIRE(grep_file("stderr", "UNDEFINED_SYMBOL"));
20543412Snewton}
20643412Snewton
20743412SnewtonATF_TEST_CASE(build_cpp);
208147817SjhbATF_TEST_CASE_HEAD(build_cpp)
209147817Sjhb{
210147817Sjhb    set_md_var("descr", "Tests the build_cpp function");
211147817Sjhb}
212147817SjhbATF_TEST_CASE_BODY(build_cpp)
21343412Snewton{
21443412Snewton    ATF_TEST_CASE_USE(h_build_cpp_ok);
21543412Snewton    run_h_tc< ATF_TEST_CASE_NAME(h_build_cpp_ok) >();
216147817Sjhb    ATF_REQUIRE(grep_file("stdout", "-o.*test.p"));
217147817Sjhb    ATF_REQUIRE(grep_file("stdout", "test.c"));
21843412Snewton    ATF_REQUIRE(grep_file("test.p", "foo bar"));
21943412Snewton
22043412Snewton    ATF_TEST_CASE_USE(h_build_cpp_fail);
22143412Snewton    run_h_tc< ATF_TEST_CASE_NAME(h_build_cpp_fail) >();
222147817Sjhb    ATF_REQUIRE(grep_file("stdout", "-o test.p"));
22343412Snewton    ATF_REQUIRE(grep_file("stdout", "test.c"));
22443412Snewton    ATF_REQUIRE(grep_file("stderr", "test.c"));
22571447Sjhb    ATF_REQUIRE(grep_file("stderr", "non-existent.h"));
22643412Snewton}
227107849Salfred
228107849SalfredATF_TEST_CASE(build_cxx_o);
22943412SnewtonATF_TEST_CASE_HEAD(build_cxx_o)
230107849Salfred{
23143412Snewton    set_md_var("descr", "Tests the build_cxx_o function");
23243412Snewton}
23343412SnewtonATF_TEST_CASE_BODY(build_cxx_o)
23443412Snewton{
235107849Salfred    ATF_TEST_CASE_USE(h_build_cxx_o_ok);
23643412Snewton    run_h_tc< ATF_TEST_CASE_NAME(h_build_cxx_o_ok) >();
237107849Salfred    ATF_REQUIRE(grep_file("stdout", "-o test.o"));
23843412Snewton    ATF_REQUIRE(grep_file("stdout", "-c test.cpp"));
23943412Snewton
240107849Salfred    ATF_TEST_CASE_USE(h_build_cxx_o_fail);
24143412Snewton    run_h_tc< ATF_TEST_CASE_NAME(h_build_cxx_o_fail) >();
24243412Snewton    ATF_REQUIRE(grep_file("stdout", "-o test.o"));
243107849Salfred    ATF_REQUIRE(grep_file("stdout", "-c test.cpp"));
24443412Snewton    ATF_REQUIRE(grep_file("stderr", "test.cpp"));
24543412Snewton    ATF_REQUIRE(grep_file("stderr", "UNDEFINED_SYMBOL"));
246107849Salfred}
24743412Snewton
24843412SnewtonATF_TEST_CASE(exec_cleanup);
249147817SjhbATF_TEST_CASE_HEAD(exec_cleanup)
25043412Snewton{
25143412Snewton    set_md_var("descr", "Tests that exec properly cleans up the temporary "
252107849Salfred               "files it creates");
25343412Snewton}
25443412SnewtonATF_TEST_CASE_BODY(exec_cleanup)
255107849Salfred{
256147817Sjhb    std::auto_ptr< atf::fs::path > out;
25743412Snewton    std::auto_ptr< atf::fs::path > err;
25843412Snewton
259107849Salfred    {
26043412Snewton        std::auto_ptr< atf::check::check_result > r =
26143412Snewton            do_exec(this, "exit-success");
262107849Salfred        out.reset(new atf::fs::path(r->stdout_path()));
263147817Sjhb        err.reset(new atf::fs::path(r->stderr_path()));
26443412Snewton        ATF_REQUIRE(atf::fs::exists(*out.get()));
26543412Snewton        ATF_REQUIRE(atf::fs::exists(*err.get()));
266107849Salfred    }
26743412Snewton    ATF_REQUIRE(!atf::fs::exists(*out.get()));
26843412Snewton    ATF_REQUIRE(!atf::fs::exists(*err.get()));
269107849Salfred}
270147817Sjhb
27143412SnewtonATF_TEST_CASE(exec_exitstatus);
27243412SnewtonATF_TEST_CASE_HEAD(exec_exitstatus)
273107849Salfred{
27443412Snewton    set_md_var("descr", "Tests that exec properly captures the exit "
275107849Salfred               "status of the executed command");
27643412Snewton}
27743412SnewtonATF_TEST_CASE_BODY(exec_exitstatus)
27843412Snewton{
279147817Sjhb    {
28043412Snewton        std::auto_ptr< atf::check::check_result > r =
28143412Snewton            do_exec(this, "exit-success");
28243412Snewton        ATF_REQUIRE(r->exited());
28343412Snewton        ATF_REQUIRE(!r->signaled());
28443412Snewton        ATF_REQUIRE_EQ(r->exitcode(), EXIT_SUCCESS);
285107849Salfred    }
28643412Snewton
28743412Snewton    {
288107849Salfred        std::auto_ptr< atf::check::check_result > r =
28943412Snewton            do_exec(this, "exit-failure");
290107849Salfred        ATF_REQUIRE(r->exited());
29143412Snewton        ATF_REQUIRE(!r->signaled());
29243412Snewton        ATF_REQUIRE_EQ(r->exitcode(), EXIT_FAILURE);
29343412Snewton    }
294107849Salfred
29543412Snewton    {
29643412Snewton        std::auto_ptr< atf::check::check_result > r =
29743412Snewton            do_exec(this, "exit-signal");
29843412Snewton        ATF_REQUIRE(!r->exited());
29943412Snewton        ATF_REQUIRE(r->signaled());
30043412Snewton        ATF_REQUIRE_EQ(r->termsig(), SIGKILL);
301147817Sjhb    }
30243412Snewton}
30343412Snewton
304107849Salfredstatic
30543412Snewtonvoid
306107849Salfredcheck_lines(const std::string& path, const char* outname,
30743412Snewton            const char* resname)
30843412Snewton{
30943412Snewton    std::ifstream f(path.c_str());
310107849Salfred    ATF_REQUIRE(f);
31143412Snewton
31243412Snewton    std::string line;
31343412Snewton    std::getline(f, line);
31443412Snewton    ATF_REQUIRE_EQ(line, std::string("Line 1 to ") + outname + " for " +
31543412Snewton                    resname);
31643412Snewton    std::getline(f, line);
317147817Sjhb    ATF_REQUIRE_EQ(line, std::string("Line 2 to ") + outname + " for " +
31843412Snewton                    resname);
31943412Snewton}
32043412Snewton
32143412SnewtonATF_TEST_CASE(exec_stdout_stderr);
32243412SnewtonATF_TEST_CASE_HEAD(exec_stdout_stderr)
32343412Snewton{
32443412Snewton    set_md_var("descr", "Tests that exec properly captures the stdout "
325147817Sjhb               "and stderr streams of the child process");
326147817Sjhb}
327147817SjhbATF_TEST_CASE_BODY(exec_stdout_stderr)
328147817Sjhb{
32943412Snewton    std::auto_ptr< atf::check::check_result > r1 =
33043412Snewton        do_exec(this, "stdout-stderr", "result1");
33143412Snewton    ATF_REQUIRE(r1->exited());
332147817Sjhb    ATF_REQUIRE_EQ(r1->exitcode(), EXIT_SUCCESS);
333147817Sjhb
33443412Snewton    std::auto_ptr< atf::check::check_result > r2 =
33543412Snewton        do_exec(this, "stdout-stderr", "result2");
33643412Snewton    ATF_REQUIRE(r2->exited());
337147817Sjhb    ATF_REQUIRE_EQ(r2->exitcode(), EXIT_SUCCESS);
33843412Snewton
339107849Salfred    const std::string out1 = r1->stdout_path();
340107849Salfred    const std::string out2 = r2->stdout_path();
341107849Salfred    const std::string err1 = r1->stderr_path();
34243412Snewton    const std::string err2 = r2->stderr_path();
343147817Sjhb
34443412Snewton    ATF_REQUIRE(out1.find("check.XXXXXX") == std::string::npos);
34543412Snewton    ATF_REQUIRE(out2.find("check.XXXXXX") == std::string::npos);
34643412Snewton    ATF_REQUIRE(err1.find("check.XXXXXX") == std::string::npos);
347147817Sjhb    ATF_REQUIRE(err2.find("check.XXXXXX") == std::string::npos);
348147817Sjhb
349147817Sjhb    ATF_REQUIRE(out1.find("/check") != std::string::npos);
350147817Sjhb    ATF_REQUIRE(out2.find("/check") != std::string::npos);
35143412Snewton    ATF_REQUIRE(err1.find("/check") != std::string::npos);
35243412Snewton    ATF_REQUIRE(err2.find("/check") != std::string::npos);
35343412Snewton
354147817Sjhb    ATF_REQUIRE(out1.find("/stdout") != std::string::npos);
355147817Sjhb    ATF_REQUIRE(out2.find("/stdout") != std::string::npos);
35643412Snewton    ATF_REQUIRE(err1.find("/stderr") != std::string::npos);
35743412Snewton    ATF_REQUIRE(err2.find("/stderr") != std::string::npos);
35843412Snewton
359147817Sjhb    ATF_REQUIRE(out1 != out2);
36043412Snewton    ATF_REQUIRE(err1 != err2);
361107849Salfred
36243412Snewton    check_lines(out1, "stdout", "result1");
363107849Salfred    check_lines(out2, "stdout", "result2");
364107849Salfred    check_lines(err1, "stderr", "result1");
36543412Snewton    check_lines(err2, "stderr", "result2");
366147817Sjhb}
36743412Snewton
36843412SnewtonATF_TEST_CASE(exec_unknown);
36943412SnewtonATF_TEST_CASE_HEAD(exec_unknown)
370147817Sjhb{
371147817Sjhb    set_md_var("descr", "Tests that running a non-existing binary "
372147817Sjhb               "is handled correctly");
37343412Snewton}
37443412SnewtonATF_TEST_CASE_BODY(exec_unknown)
375107849Salfred{
37643412Snewton    std::vector< std::string > argv;
377107849Salfred    argv.push_back(atf::config::get("atf_workdir") + "/non-existent");
37843412Snewton
379147817Sjhb    atf::process::argv_array argva(argv);
38043412Snewton    std::auto_ptr< atf::check::check_result > r = atf::check::exec(argva);
381147817Sjhb    ATF_REQUIRE(r->exited());
38243412Snewton    ATF_REQUIRE_EQ(r->exitcode(), 127);
383147817Sjhb}
38443412Snewton
38543412Snewton// ------------------------------------------------------------------------
38643412Snewton// Tests cases for the header file.
38743412Snewton// ------------------------------------------------------------------------
388148541Sjhb
389148541SjhbHEADER_TC(include, "atf-c++/check.hpp");
39043412Snewton
39143412Snewton// ------------------------------------------------------------------------
39243412Snewton// Main.
39343412Snewton// ------------------------------------------------------------------------
39443412Snewton
39543412SnewtonATF_INIT_TEST_CASES(tcs)
39643412Snewton{
39743412Snewton    // Add the test cases for the free functions.
39843412Snewton    ATF_ADD_TEST_CASE(tcs, build_c_o);
39943412Snewton    ATF_ADD_TEST_CASE(tcs, build_cpp);
40043412Snewton    ATF_ADD_TEST_CASE(tcs, build_cxx_o);
40143412Snewton    ATF_ADD_TEST_CASE(tcs, exec_cleanup);
40243412Snewton    ATF_ADD_TEST_CASE(tcs, exec_exitstatus);
40343412Snewton    ATF_ADD_TEST_CASE(tcs, exec_stdout_stderr);
40443412Snewton    ATF_ADD_TEST_CASE(tcs, exec_unknown);
40543412Snewton
40643412Snewton    // Add the test cases for the header file.
40743412Snewton    ATF_ADD_TEST_CASE(tcs, include);
40843412Snewton}
40943412Snewton