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