1 //
2 // Automated Testing Framework (atf)
3 //
4 // Copyright (c) 2010 The NetBSD Foundation, Inc.
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 // 1. Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 // 2. Redistributions in binary form must reproduce the above copyright
13 // notice, this list of conditions and the following disclaimer in the
14 // documentation and/or other materials provided with the distribution.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17 // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 //
29
30 #include <atf-c++.hpp>
31
32 #include "config.hpp"
33 #include "requirements.hpp"
34 #include "text.hpp"
35 #include "user.hpp"
36
37 namespace impl = tools;
38
39 // -------------------------------------------------------------------------
40 // Auxiliary functions.
41 // -------------------------------------------------------------------------
42
43 namespace {
44
45 typedef std::map< std::string, std::string > vars_map;
46
47 const vars_map no_config;
48
49 void
do_check(const std::string & expected,const vars_map & metadata,const vars_map & config=no_config)50 do_check(const std::string& expected, const vars_map& metadata,
51 const vars_map& config = no_config)
52 {
53 const std::string actual = impl::check_requirements(metadata, config);
54 if (!tools::text::match(actual, expected))
55 ATF_FAIL("Requirements failure reason \"" + actual + "\" does not "
56 "match \"" + expected + "\"");
57 }
58
59 } // anonymous namespace
60
61 // -------------------------------------------------------------------------
62 // Tests for the require.arch metadata property.
63 // -------------------------------------------------------------------------
64
65 ATF_TEST_CASE(require_arch_one_ok);
ATF_TEST_CASE_HEAD(require_arch_one_ok)66 ATF_TEST_CASE_HEAD(require_arch_one_ok) {}
ATF_TEST_CASE_BODY(require_arch_one_ok)67 ATF_TEST_CASE_BODY(require_arch_one_ok) {
68 vars_map metadata;
69 metadata["require.arch"] = tools::config::get("atf_arch");
70 do_check("", metadata);
71 }
72
73 ATF_TEST_CASE(require_arch_one_fail);
ATF_TEST_CASE_HEAD(require_arch_one_fail)74 ATF_TEST_CASE_HEAD(require_arch_one_fail) {}
ATF_TEST_CASE_BODY(require_arch_one_fail)75 ATF_TEST_CASE_BODY(require_arch_one_fail) {
76 vars_map metadata;
77 metadata["require.arch"] = "__fake_arch__";
78 do_check("Requires the '__fake_arch__' architecture", metadata);
79 }
80
81 ATF_TEST_CASE(require_arch_many_ok);
ATF_TEST_CASE_HEAD(require_arch_many_ok)82 ATF_TEST_CASE_HEAD(require_arch_many_ok) {}
ATF_TEST_CASE_BODY(require_arch_many_ok)83 ATF_TEST_CASE_BODY(require_arch_many_ok) {
84 vars_map metadata;
85 metadata["require.arch"] = "__foo__ " + tools::config::get("atf_arch") +
86 " __bar__";
87 do_check("", metadata);
88 }
89
90 ATF_TEST_CASE(require_arch_many_fail);
ATF_TEST_CASE_HEAD(require_arch_many_fail)91 ATF_TEST_CASE_HEAD(require_arch_many_fail) {}
ATF_TEST_CASE_BODY(require_arch_many_fail)92 ATF_TEST_CASE_BODY(require_arch_many_fail) {
93 vars_map metadata;
94 metadata["require.arch"] = "__foo__ __bar__ __baz__";
95 do_check("Requires one of the '__foo__ __bar__ __baz__' architectures",
96 metadata);
97 }
98
99 // -------------------------------------------------------------------------
100 // Tests for the require.config metadata property.
101 // -------------------------------------------------------------------------
102
103 ATF_TEST_CASE(require_config_one_ok);
ATF_TEST_CASE_HEAD(require_config_one_ok)104 ATF_TEST_CASE_HEAD(require_config_one_ok) {}
ATF_TEST_CASE_BODY(require_config_one_ok)105 ATF_TEST_CASE_BODY(require_config_one_ok) {
106 vars_map metadata, config;
107 metadata["require.config"] = "var1";
108 config["var1"] = "some-value";
109 do_check("", metadata, config);
110 }
111
112 ATF_TEST_CASE(require_config_one_fail);
ATF_TEST_CASE_HEAD(require_config_one_fail)113 ATF_TEST_CASE_HEAD(require_config_one_fail) {}
ATF_TEST_CASE_BODY(require_config_one_fail)114 ATF_TEST_CASE_BODY(require_config_one_fail) {
115 vars_map metadata, config;
116 metadata["require.config"] = "var1";
117 do_check("Required configuration variable 'var1' not defined", metadata,
118 config);
119 }
120
121 ATF_TEST_CASE(require_config_many_ok);
ATF_TEST_CASE_HEAD(require_config_many_ok)122 ATF_TEST_CASE_HEAD(require_config_many_ok) {}
ATF_TEST_CASE_BODY(require_config_many_ok)123 ATF_TEST_CASE_BODY(require_config_many_ok) {
124 vars_map metadata, config;
125 metadata["require.config"] = "var1 var2 var3";
126 config["var1"] = "first-value";
127 config["var2"] = "second-value";
128 config["var3"] = "third-value";
129 do_check("", metadata, config);
130 }
131
132 ATF_TEST_CASE(require_config_many_fail);
ATF_TEST_CASE_HEAD(require_config_many_fail)133 ATF_TEST_CASE_HEAD(require_config_many_fail) {}
ATF_TEST_CASE_BODY(require_config_many_fail)134 ATF_TEST_CASE_BODY(require_config_many_fail) {
135 vars_map metadata, config;
136 metadata["require.config"] = "var1 var2 var3";
137 config["var1"] = "first-value";
138 config["var3"] = "third-value";
139 do_check("Required configuration variable 'var2' not defined", metadata,
140 config);
141 }
142
143 // -------------------------------------------------------------------------
144 // Tests for the require.files metadata property.
145 // -------------------------------------------------------------------------
146
147 ATF_TEST_CASE_WITHOUT_HEAD(require_files_one_ok);
ATF_TEST_CASE_BODY(require_files_one_ok)148 ATF_TEST_CASE_BODY(require_files_one_ok) {
149 vars_map metadata;
150 metadata["require.files"] = "/bin/ls";
151 do_check("", metadata);
152 }
153
154 ATF_TEST_CASE_WITHOUT_HEAD(require_files_one_missing);
ATF_TEST_CASE_BODY(require_files_one_missing)155 ATF_TEST_CASE_BODY(require_files_one_missing) {
156 vars_map metadata;
157 metadata["require.files"] = "/non-existent/foo";
158 do_check("Required file '/non-existent/foo' not found", metadata);
159 }
160
161 ATF_TEST_CASE_WITHOUT_HEAD(require_files_one_fail);
ATF_TEST_CASE_BODY(require_files_one_fail)162 ATF_TEST_CASE_BODY(require_files_one_fail) {
163 vars_map metadata;
164 metadata["require.files"] = "/bin/cp this-is-relative";
165 ATF_REQUIRE_THROW_RE(std::runtime_error, "Relative.*(this-is-relative)",
166 impl::check_requirements(metadata, no_config));
167 }
168
169 ATF_TEST_CASE_WITHOUT_HEAD(require_files_many_ok);
ATF_TEST_CASE_BODY(require_files_many_ok)170 ATF_TEST_CASE_BODY(require_files_many_ok) {
171 vars_map metadata;
172 metadata["require.files"] = "/bin/ls /bin/cp";
173 do_check("", metadata);
174 }
175
176 ATF_TEST_CASE_WITHOUT_HEAD(require_files_many_missing);
ATF_TEST_CASE_BODY(require_files_many_missing)177 ATF_TEST_CASE_BODY(require_files_many_missing) {
178 vars_map metadata;
179 metadata["require.files"] = "/bin/ls /non-existent/bar /bin/cp";
180 do_check("Required file '/non-existent/bar' not found", metadata);
181 }
182
183 ATF_TEST_CASE_WITHOUT_HEAD(require_files_many_fail);
ATF_TEST_CASE_BODY(require_files_many_fail)184 ATF_TEST_CASE_BODY(require_files_many_fail) {
185 vars_map metadata;
186 metadata["require.files"] = "/bin/cp also-relative";
187 ATF_REQUIRE_THROW_RE(std::runtime_error, "Relative.*(also-relative)",
188 impl::check_requirements(metadata, no_config));
189 }
190
191 // -------------------------------------------------------------------------
192 // Tests for the require.machine metadata property.
193 // -------------------------------------------------------------------------
194
195 ATF_TEST_CASE(require_machine_one_ok);
ATF_TEST_CASE_HEAD(require_machine_one_ok)196 ATF_TEST_CASE_HEAD(require_machine_one_ok) {}
ATF_TEST_CASE_BODY(require_machine_one_ok)197 ATF_TEST_CASE_BODY(require_machine_one_ok) {
198 vars_map metadata;
199 metadata["require.machine"] = tools::config::get("atf_machine");
200 do_check("", metadata);
201 }
202
203 ATF_TEST_CASE(require_machine_one_fail);
ATF_TEST_CASE_HEAD(require_machine_one_fail)204 ATF_TEST_CASE_HEAD(require_machine_one_fail) {}
ATF_TEST_CASE_BODY(require_machine_one_fail)205 ATF_TEST_CASE_BODY(require_machine_one_fail) {
206 vars_map metadata;
207 metadata["require.machine"] = "__fake_machine__";
208 do_check("Requires the '__fake_machine__' machine type", metadata);
209 }
210
211 ATF_TEST_CASE(require_machine_many_ok);
ATF_TEST_CASE_HEAD(require_machine_many_ok)212 ATF_TEST_CASE_HEAD(require_machine_many_ok) {}
ATF_TEST_CASE_BODY(require_machine_many_ok)213 ATF_TEST_CASE_BODY(require_machine_many_ok) {
214 vars_map metadata;
215 metadata["require.machine"] = "__foo__ " +
216 tools::config::get("atf_machine") + " __bar__";
217 do_check("", metadata);
218 }
219
220 ATF_TEST_CASE(require_machine_many_fail);
ATF_TEST_CASE_HEAD(require_machine_many_fail)221 ATF_TEST_CASE_HEAD(require_machine_many_fail) {}
ATF_TEST_CASE_BODY(require_machine_many_fail)222 ATF_TEST_CASE_BODY(require_machine_many_fail) {
223 vars_map metadata;
224 metadata["require.machine"] = "__foo__ __bar__ __baz__";
225 do_check("Requires one of the '__foo__ __bar__ __baz__' machine types",
226 metadata);
227 }
228
229 // -------------------------------------------------------------------------
230 // Tests for the require.memory metadata property.
231 // -------------------------------------------------------------------------
232
233 ATF_TEST_CASE_WITHOUT_HEAD(require_memory_ok);
ATF_TEST_CASE_BODY(require_memory_ok)234 ATF_TEST_CASE_BODY(require_memory_ok) {
235 vars_map metadata;
236 metadata["require.memory"] = "1m";
237 do_check("", metadata);
238 }
239
240 ATF_TEST_CASE_WITHOUT_HEAD(require_memory_not_enough);
ATF_TEST_CASE_BODY(require_memory_not_enough)241 ATF_TEST_CASE_BODY(require_memory_not_enough) {
242 vars_map metadata;
243 metadata["require.memory"] = "128t";
244 do_check("Not enough memory; needed 140737488355328, available [0-9]*",
245 metadata);
246 }
247
248 ATF_TEST_CASE_WITHOUT_HEAD(require_memory_fail);
ATF_TEST_CASE_BODY(require_memory_fail)249 ATF_TEST_CASE_BODY(require_memory_fail) {
250 vars_map metadata;
251 metadata["require.memory"] = "foo";
252 ATF_REQUIRE_THROW(std::runtime_error,
253 impl::check_requirements(metadata, no_config));
254 }
255
256 // -------------------------------------------------------------------------
257 // Tests for the require.progs metadata property.
258 // -------------------------------------------------------------------------
259
260 ATF_TEST_CASE(require_progs_one_ok);
ATF_TEST_CASE_HEAD(require_progs_one_ok)261 ATF_TEST_CASE_HEAD(require_progs_one_ok) {}
ATF_TEST_CASE_BODY(require_progs_one_ok)262 ATF_TEST_CASE_BODY(require_progs_one_ok) {
263 vars_map metadata;
264 metadata["require.progs"] = "cp";
265 do_check("", metadata);
266 }
267
268 ATF_TEST_CASE(require_progs_one_missing);
ATF_TEST_CASE_HEAD(require_progs_one_missing)269 ATF_TEST_CASE_HEAD(require_progs_one_missing) {}
ATF_TEST_CASE_BODY(require_progs_one_missing)270 ATF_TEST_CASE_BODY(require_progs_one_missing) {
271 vars_map metadata;
272 metadata["require.progs"] = "cp __non-existent__";
273 do_check("Required program '__non-existent__' not found in the PATH",
274 metadata);
275 }
276
277 ATF_TEST_CASE(require_progs_one_fail);
ATF_TEST_CASE_HEAD(require_progs_one_fail)278 ATF_TEST_CASE_HEAD(require_progs_one_fail) {}
ATF_TEST_CASE_BODY(require_progs_one_fail)279 ATF_TEST_CASE_BODY(require_progs_one_fail) {
280 vars_map metadata;
281 metadata["require.progs"] = "bin/cp";
282 ATF_REQUIRE_THROW(std::runtime_error,
283 impl::check_requirements(metadata, no_config));
284 }
285
286 ATF_TEST_CASE(require_progs_many_ok);
ATF_TEST_CASE_HEAD(require_progs_many_ok)287 ATF_TEST_CASE_HEAD(require_progs_many_ok) {}
ATF_TEST_CASE_BODY(require_progs_many_ok)288 ATF_TEST_CASE_BODY(require_progs_many_ok) {
289 vars_map metadata;
290 metadata["require.progs"] = "cp ls mv";
291 do_check("", metadata);
292 }
293
294 ATF_TEST_CASE(require_progs_many_missing);
ATF_TEST_CASE_HEAD(require_progs_many_missing)295 ATF_TEST_CASE_HEAD(require_progs_many_missing) {}
ATF_TEST_CASE_BODY(require_progs_many_missing)296 ATF_TEST_CASE_BODY(require_progs_many_missing) {
297 vars_map metadata;
298 metadata["require.progs"] = "mv ls __foo__ cp";
299 do_check("Required program '__foo__' not found in the PATH", metadata);
300 }
301
302 ATF_TEST_CASE(require_progs_many_fail);
ATF_TEST_CASE_HEAD(require_progs_many_fail)303 ATF_TEST_CASE_HEAD(require_progs_many_fail) {}
ATF_TEST_CASE_BODY(require_progs_many_fail)304 ATF_TEST_CASE_BODY(require_progs_many_fail) {
305 vars_map metadata;
306 metadata["require.progs"] = "ls cp ../bin/cp";
307 ATF_REQUIRE_THROW(std::runtime_error,
308 impl::check_requirements(metadata, no_config));
309 }
310
311 // -------------------------------------------------------------------------
312 // Tests for the require.user metadata property.
313 // -------------------------------------------------------------------------
314
315 ATF_TEST_CASE(require_user_root);
ATF_TEST_CASE_HEAD(require_user_root)316 ATF_TEST_CASE_HEAD(require_user_root) {}
ATF_TEST_CASE_BODY(require_user_root)317 ATF_TEST_CASE_BODY(require_user_root) {
318 vars_map metadata;
319 metadata["require.user"] = "root";
320 if (tools::user::is_root())
321 do_check("", metadata);
322 else
323 do_check("Requires root privileges", metadata);
324 }
325
326 ATF_TEST_CASE(require_user_unprivileged);
ATF_TEST_CASE_HEAD(require_user_unprivileged)327 ATF_TEST_CASE_HEAD(require_user_unprivileged) {}
ATF_TEST_CASE_BODY(require_user_unprivileged)328 ATF_TEST_CASE_BODY(require_user_unprivileged) {
329 vars_map metadata;
330 metadata["require.user"] = "unprivileged";
331 if (tools::user::is_root())
332 do_check("Requires an unprivileged user and the 'unprivileged-user' "
333 "configuration variable is not set", metadata);
334 else
335 do_check("", metadata);
336 }
337
338 ATF_TEST_CASE(require_user_fail);
ATF_TEST_CASE_HEAD(require_user_fail)339 ATF_TEST_CASE_HEAD(require_user_fail) {}
ATF_TEST_CASE_BODY(require_user_fail)340 ATF_TEST_CASE_BODY(require_user_fail) {
341 vars_map metadata;
342 metadata["require.user"] = "nobody";
343 ATF_REQUIRE_THROW(std::runtime_error,
344 impl::check_requirements(metadata, no_config));
345 }
346
347 // -------------------------------------------------------------------------
348 // Main.
349 // -------------------------------------------------------------------------
350
ATF_INIT_TEST_CASES(tcs)351 ATF_INIT_TEST_CASES(tcs)
352 {
353 // Add test cases for require.arch.
354 ATF_ADD_TEST_CASE(tcs, require_arch_one_ok);
355 ATF_ADD_TEST_CASE(tcs, require_arch_one_fail);
356 ATF_ADD_TEST_CASE(tcs, require_arch_many_ok);
357 ATF_ADD_TEST_CASE(tcs, require_arch_many_fail);
358
359 // Add test cases for require.config.
360 ATF_ADD_TEST_CASE(tcs, require_config_one_ok);
361 ATF_ADD_TEST_CASE(tcs, require_config_one_fail);
362 ATF_ADD_TEST_CASE(tcs, require_config_many_ok);
363 ATF_ADD_TEST_CASE(tcs, require_config_many_fail);
364
365 // Add test cases for require.files.
366 ATF_ADD_TEST_CASE(tcs, require_files_one_ok);
367 ATF_ADD_TEST_CASE(tcs, require_files_one_missing);
368 ATF_ADD_TEST_CASE(tcs, require_files_one_fail);
369 ATF_ADD_TEST_CASE(tcs, require_files_many_ok);
370 ATF_ADD_TEST_CASE(tcs, require_files_many_missing);
371 ATF_ADD_TEST_CASE(tcs, require_files_many_fail);
372
373 // Add test cases for require.machine.
374 ATF_ADD_TEST_CASE(tcs, require_machine_one_ok);
375 ATF_ADD_TEST_CASE(tcs, require_machine_one_fail);
376 ATF_ADD_TEST_CASE(tcs, require_machine_many_ok);
377 ATF_ADD_TEST_CASE(tcs, require_machine_many_fail);
378
379 // Add test cases for require.memory.
380 ATF_ADD_TEST_CASE(tcs, require_memory_ok);
381 ATF_ADD_TEST_CASE(tcs, require_memory_not_enough);
382 ATF_ADD_TEST_CASE(tcs, require_memory_fail);
383
384 // Add test cases for require.progs.
385 ATF_ADD_TEST_CASE(tcs, require_progs_one_ok);
386 ATF_ADD_TEST_CASE(tcs, require_progs_one_missing);
387 ATF_ADD_TEST_CASE(tcs, require_progs_one_fail);
388 ATF_ADD_TEST_CASE(tcs, require_progs_many_ok);
389 ATF_ADD_TEST_CASE(tcs, require_progs_many_missing);
390 ATF_ADD_TEST_CASE(tcs, require_progs_many_fail);
391
392 // Add test cases for require.user.
393 ATF_ADD_TEST_CASE(tcs, require_user_root);
394 ATF_ADD_TEST_CASE(tcs, require_user_unprivileged);
395 ATF_ADD_TEST_CASE(tcs, require_user_fail);
396 }
397