xref: /netbsd-src/external/bsd/kyua-cli/dist/engine/test_case_atf_helpers.cpp (revision 6b3a42af15b5e090c339512c790dd68f3d11a9d8)
1 // Copyright 2010 Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 //   notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 //   notice, this list of conditions and the following disclaimer in the
12 //   documentation and/or other materials provided with the distribution.
13 // * Neither the name of Google Inc. nor the names of its contributors
14 //   may be used to endorse or promote products derived from this software
15 //   without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 extern "C" {
30 #include <sys/stat.h>
31 
32 #include <signal.h>
33 #include <unistd.h>
34 }
35 
36 #include <cstdlib>
37 #include <fstream>
38 #include <iostream>
39 #include <sstream>
40 
41 #include <atf-c++.hpp>
42 
43 #include "utils/env.hpp"
44 #include "utils/fs/operations.hpp"
45 #include "utils/fs/path.hpp"
46 #include "utils/optional.ipp"
47 
48 namespace fs = utils::fs;
49 
50 
51 namespace {
52 
53 
54 /// Creates an empty file in the given directory.
55 ///
56 /// \param test_case The test case currently running.
57 /// \param directory The name of the configuration variable that holds the path
58 ///     to the directory in which to create the cookie file.
59 /// \param name The name of the cookie file to create.
60 static void
create_cookie(const atf::tests::tc * test_case,const char * directory,const char * name)61 create_cookie(const atf::tests::tc* test_case, const char* directory,
62               const char* name)
63 {
64     if (!test_case->has_config_var(directory))
65         test_case->fail(std::string(name) + " not provided");
66 
67     const fs::path control_dir(test_case->get_config_var(directory));
68     std::ofstream file((control_dir / name).c_str());
69     if (!file)
70         test_case->fail("Failed to create the control cookie");
71     file.close();
72 }
73 
74 
75 }  // anonymous namespace
76 
77 
78 ATF_TEST_CASE_WITH_CLEANUP(check_cleanup_workdir);
ATF_TEST_CASE_HEAD(check_cleanup_workdir)79 ATF_TEST_CASE_HEAD(check_cleanup_workdir)
80 {
81     set_md_var("require.config", "control_dir");
82 }
ATF_TEST_CASE_BODY(check_cleanup_workdir)83 ATF_TEST_CASE_BODY(check_cleanup_workdir)
84 {
85     std::ofstream cookie("workdir_cookie");
86     cookie << "1234\n";
87     cookie.close();
88     skip("cookie created");
89 }
ATF_TEST_CASE_CLEANUP(check_cleanup_workdir)90 ATF_TEST_CASE_CLEANUP(check_cleanup_workdir)
91 {
92     const fs::path control_dir(get_config_var("control_dir"));
93 
94     std::ifstream cookie("workdir_cookie");
95     if (!cookie) {
96         std::ofstream((control_dir / "missing_cookie").c_str()).close();
97         std::exit(EXIT_FAILURE);
98     }
99 
100     std::string value;
101     cookie >> value;
102     if (value != "1234") {
103         std::ofstream((control_dir / "invalid_cookie").c_str()).close();
104         std::exit(EXIT_FAILURE);
105     }
106 
107     std::ofstream((control_dir / "cookie_ok").c_str()).close();
108     std::exit(EXIT_SUCCESS);
109 }
110 
111 
112 ATF_TEST_CASE_WITHOUT_HEAD(check_unprivileged);
ATF_TEST_CASE_BODY(check_unprivileged)113 ATF_TEST_CASE_BODY(check_unprivileged)
114 {
115     if (::getuid() == 0)
116         fail("Running as root, but I shouldn't be");
117 
118     std::ofstream file("cookie");
119     if (!file)
120         fail("Failed to create the cookie; work directory probably owned by "
121              "root");
122     file.close();
123 }
124 
125 
126 ATF_TEST_CASE_WITHOUT_HEAD(crash);
ATF_TEST_CASE_BODY(crash)127 ATF_TEST_CASE_BODY(crash)
128 {
129     std::abort();
130 }
131 
132 
133 ATF_TEST_CASE_WITH_CLEANUP(crash_cleanup);
ATF_TEST_CASE_HEAD(crash_cleanup)134 ATF_TEST_CASE_HEAD(crash_cleanup)
135 {
136 }
ATF_TEST_CASE_BODY(crash_cleanup)137 ATF_TEST_CASE_BODY(crash_cleanup)
138 {
139 }
ATF_TEST_CASE_CLEANUP(crash_cleanup)140 ATF_TEST_CASE_CLEANUP(crash_cleanup)
141 {
142     std::abort();
143 }
144 
145 
146 ATF_TEST_CASE_WITHOUT_HEAD(create_cookie_in_control_dir);
ATF_TEST_CASE_BODY(create_cookie_in_control_dir)147 ATF_TEST_CASE_BODY(create_cookie_in_control_dir)
148 {
149     create_cookie(this, "control_dir", "cookie");
150 }
151 
152 
153 ATF_TEST_CASE_WITHOUT_HEAD(create_cookie_in_workdir);
ATF_TEST_CASE_BODY(create_cookie_in_workdir)154 ATF_TEST_CASE_BODY(create_cookie_in_workdir)
155 {
156     std::ofstream file("cookie");
157     if (!file)
158         fail("Failed to create the cookie");
159     file.close();
160 }
161 
162 
163 ATF_TEST_CASE_WITH_CLEANUP(create_cookie_from_cleanup);
ATF_TEST_CASE_HEAD(create_cookie_from_cleanup)164 ATF_TEST_CASE_HEAD(create_cookie_from_cleanup)
165 {
166 }
ATF_TEST_CASE_BODY(create_cookie_from_cleanup)167 ATF_TEST_CASE_BODY(create_cookie_from_cleanup)
168 {
169 }
ATF_TEST_CASE_CLEANUP(create_cookie_from_cleanup)170 ATF_TEST_CASE_CLEANUP(create_cookie_from_cleanup)
171 {
172     create_cookie(this, "control_dir", "cookie");
173 }
174 
175 
176 ATF_TEST_CASE_WITH_CLEANUP(output);
ATF_TEST_CASE_HEAD(output)177 ATF_TEST_CASE_HEAD(output)
178 {
179 }
ATF_TEST_CASE_BODY(output)180 ATF_TEST_CASE_BODY(output)
181 {
182     std::cout << "Body message to stdout\n";
183     std::cerr << "Body message to stderr\n";
184 }
ATF_TEST_CASE_CLEANUP(output)185 ATF_TEST_CASE_CLEANUP(output)
186 {
187     std::cout << "Cleanup message to stdout\n";
188     std::cerr << "Cleanup message to stderr\n";
189 }
190 
191 
192 ATF_TEST_CASE_WITHOUT_HEAD(pass);
ATF_TEST_CASE_BODY(pass)193 ATF_TEST_CASE_BODY(pass)
194 {
195 }
196 
197 
198 ATF_TEST_CASE(spawn_blocking_child);
ATF_TEST_CASE_HEAD(spawn_blocking_child)199 ATF_TEST_CASE_HEAD(spawn_blocking_child)
200 {
201     set_md_var("require.config", "control_dir");
202 }
ATF_TEST_CASE_BODY(spawn_blocking_child)203 ATF_TEST_CASE_BODY(spawn_blocking_child)
204 {
205     pid_t pid = ::fork();
206     if (pid == -1)
207         fail("Cannot fork subprocess");
208     else if (pid == 0) {
209         for (;;)
210             ::pause();
211     } else {
212         const fs::path name = fs::path(get_config_var("control_dir")) / "pid";
213         std::ofstream pidfile(name.c_str());
214         ATF_REQUIRE(pidfile);
215         pidfile << pid;
216         pidfile.close();
217     }
218 }
219 
220 
221 ATF_TEST_CASE(timeout_body);
ATF_TEST_CASE_HEAD(timeout_body)222 ATF_TEST_CASE_HEAD(timeout_body)
223 {
224     if (has_config_var("timeout"))
225         set_md_var("timeout", get_config_var("timeout"));
226 }
ATF_TEST_CASE_BODY(timeout_body)227 ATF_TEST_CASE_BODY(timeout_body)
228 {
229     ::sleep(10);
230     create_cookie(this, "control_dir", "cookie");
231 }
232 
233 
234 ATF_TEST_CASE_WITH_CLEANUP(timeout_cleanup);
ATF_TEST_CASE_HEAD(timeout_cleanup)235 ATF_TEST_CASE_HEAD(timeout_cleanup)
236 {
237     if (has_config_var("timeout"))
238         set_md_var("timeout", get_config_var("timeout"));
239 }
ATF_TEST_CASE_BODY(timeout_cleanup)240 ATF_TEST_CASE_BODY(timeout_cleanup)
241 {
242 }
ATF_TEST_CASE_CLEANUP(timeout_cleanup)243 ATF_TEST_CASE_CLEANUP(timeout_cleanup)
244 {
245     ::sleep(10);
246     create_cookie(this, "control_dir", "cookie");
247 }
248 
249 
250 ATF_TEST_CASE_WITHOUT_HEAD(validate_isolation);
ATF_TEST_CASE_BODY(validate_isolation)251 ATF_TEST_CASE_BODY(validate_isolation)
252 {
253     ATF_REQUIRE(utils::getenv("HOME").get() != "fake-value");
254     ATF_REQUIRE(!utils::getenv("LANG"));
255 }
256 
257 
ATF_INIT_TEST_CASES(tcs)258 ATF_INIT_TEST_CASES(tcs)
259 {
260     ATF_ADD_TEST_CASE(tcs, check_cleanup_workdir);
261     ATF_ADD_TEST_CASE(tcs, check_unprivileged);
262     ATF_ADD_TEST_CASE(tcs, crash);
263     ATF_ADD_TEST_CASE(tcs, crash_cleanup);
264     ATF_ADD_TEST_CASE(tcs, create_cookie_in_control_dir);
265     ATF_ADD_TEST_CASE(tcs, create_cookie_in_workdir);
266     ATF_ADD_TEST_CASE(tcs, create_cookie_from_cleanup);
267     ATF_ADD_TEST_CASE(tcs, output);
268     ATF_ADD_TEST_CASE(tcs, pass);
269     ATF_ADD_TEST_CASE(tcs, spawn_blocking_child);
270     ATF_ADD_TEST_CASE(tcs, timeout_body);
271     ATF_ADD_TEST_CASE(tcs, timeout_cleanup);
272     ATF_ADD_TEST_CASE(tcs, validate_isolation);
273 }
274