xref: /freebsd/contrib/atf/atf-c++/macros_test.cpp (revision a4128aad8503277614f2d214011ef60a19447b83)
1 // Copyright (c) 2008 The NetBSD Foundation, 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
6 // are met:
7 // 1. Redistributions of source code must retain the above copyright
8 //    notice, this list of conditions and the following disclaimer.
9 // 2. Redistributions in binary form must reproduce the above copyright
10 //    notice, this list of conditions and the following disclaimer in the
11 //    documentation and/or other materials provided with the distribution.
12 //
13 // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
14 // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
15 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
18 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20 // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24 // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 #include "atf-c++/macros.hpp"
27 
28 extern "C" {
29 #include <fcntl.h>
30 #include <unistd.h>
31 }
32 
33 #include <cerrno>
34 #include <cstdlib>
35 #include <iostream>
36 #include <stdexcept>
37 
38 #include <atf-c++.hpp>
39 
40 #include "atf-c++/detail/fs.hpp"
41 #include "atf-c++/detail/process.hpp"
42 #include "atf-c++/detail/sanity.hpp"
43 #include "atf-c++/detail/test_helpers.hpp"
44 #include "atf-c++/detail/text.hpp"
45 #include "atf-c++/utils.hpp"
46 
47 // ------------------------------------------------------------------------
48 // Auxiliary functions.
49 // ------------------------------------------------------------------------
50 
51 static
52 void
53 create_ctl_file(const char *name)
54 {
55     ATF_REQUIRE(open(name, O_CREAT | O_WRONLY | O_TRUNC, 0644) != -1);
56 }
57 
58 // ------------------------------------------------------------------------
59 // Auxiliary test cases.
60 // ------------------------------------------------------------------------
61 
62 ATF_TEST_CASE(h_pass);
63 ATF_TEST_CASE_HEAD(h_pass)
64 {
65     set_md_var("descr", "Helper test case");
66 }
67 ATF_TEST_CASE_BODY(h_pass)
68 {
69     create_ctl_file("before");
70     ATF_PASS();
71     create_ctl_file("after");
72 }
73 
74 ATF_TEST_CASE(h_fail);
75 ATF_TEST_CASE_HEAD(h_fail)
76 {
77     set_md_var("descr", "Helper test case");
78 }
79 ATF_TEST_CASE_BODY(h_fail)
80 {
81     create_ctl_file("before");
82     ATF_FAIL("Failed on purpose");
83     create_ctl_file("after");
84 }
85 
86 ATF_TEST_CASE(h_skip);
87 ATF_TEST_CASE_HEAD(h_skip)
88 {
89     set_md_var("descr", "Helper test case");
90 }
91 ATF_TEST_CASE_BODY(h_skip)
92 {
93     create_ctl_file("before");
94     ATF_SKIP("Skipped on purpose");
95     create_ctl_file("after");
96 }
97 
98 ATF_TEST_CASE(h_require);
99 ATF_TEST_CASE_HEAD(h_require)
100 {
101     set_md_var("descr", "Helper test case");
102 }
103 ATF_TEST_CASE_BODY(h_require)
104 {
105     bool condition = atf::text::to_bool(get_config_var("condition"));
106 
107     create_ctl_file("before");
108     ATF_REQUIRE(condition);
109     create_ctl_file("after");
110 }
111 
112 ATF_TEST_CASE(h_require_eq);
113 ATF_TEST_CASE_HEAD(h_require_eq)
114 {
115     set_md_var("descr", "Helper test case");
116 }
117 ATF_TEST_CASE_BODY(h_require_eq)
118 {
119     long v1 = atf::text::to_type< long >(get_config_var("v1"));
120     long v2 = atf::text::to_type< long >(get_config_var("v2"));
121 
122     create_ctl_file("before");
123     ATF_REQUIRE_EQ(v1, v2);
124     create_ctl_file("after");
125 }
126 
127 ATF_TEST_CASE(h_require_in);
128 ATF_TEST_CASE_HEAD(h_require_in)
129 {
130     set_md_var("descr", "Helper test case");
131 }
132 ATF_TEST_CASE_BODY(h_require_in)
133 {
134     const std::string element = get_config_var("value");
135 
136     std::set< std::string > collection;
137     collection.insert("foo");
138     collection.insert("bar");
139     collection.insert("baz");
140 
141     create_ctl_file("before");
142     ATF_REQUIRE_IN(element, collection);
143     create_ctl_file("after");
144 }
145 
146 ATF_TEST_CASE(h_require_match);
147 ATF_TEST_CASE_HEAD(h_require_match)
148 {
149     set_md_var("descr", "Helper test case");
150 }
151 ATF_TEST_CASE_BODY(h_require_match)
152 {
153     const std::string regexp = get_config_var("regexp");
154     const std::string string = get_config_var("string");
155 
156     create_ctl_file("before");
157     ATF_REQUIRE_MATCH(regexp, string);
158     create_ctl_file("after");
159 }
160 
161 ATF_TEST_CASE(h_require_not_in);
162 ATF_TEST_CASE_HEAD(h_require_not_in)
163 {
164     set_md_var("descr", "Helper test case");
165 }
166 ATF_TEST_CASE_BODY(h_require_not_in)
167 {
168     const std::string element = get_config_var("value");
169 
170     std::set< std::string > collection;
171     collection.insert("foo");
172     collection.insert("bar");
173     collection.insert("baz");
174 
175     create_ctl_file("before");
176     ATF_REQUIRE_NOT_IN(element, collection);
177     create_ctl_file("after");
178 }
179 
180 ATF_TEST_CASE(h_require_throw);
181 ATF_TEST_CASE_HEAD(h_require_throw)
182 {
183     set_md_var("descr", "Helper test case");
184 }
185 ATF_TEST_CASE_BODY(h_require_throw)
186 {
187     create_ctl_file("before");
188 
189     if (get_config_var("what") == "throw_int")
190         ATF_REQUIRE_THROW(std::runtime_error, if (1) throw int(5));
191     else if (get_config_var("what") == "throw_rt")
192         ATF_REQUIRE_THROW(std::runtime_error,
193                         if (1) throw std::runtime_error("e"));
194     else if (get_config_var("what") == "no_throw_rt")
195         ATF_REQUIRE_THROW(std::runtime_error,
196                         if (0) throw std::runtime_error("e"));
197 
198     create_ctl_file("after");
199 }
200 
201 ATF_TEST_CASE(h_require_throw_re);
202 ATF_TEST_CASE_HEAD(h_require_throw_re)
203 {
204     set_md_var("descr", "Helper test case");
205 }
206 ATF_TEST_CASE_BODY(h_require_throw_re)
207 {
208     create_ctl_file("before");
209 
210     if (get_config_var("what") == "throw_int")
211         ATF_REQUIRE_THROW_RE(std::runtime_error, "5", if (1) throw int(5));
212     else if (get_config_var("what") == "throw_rt_match")
213         ATF_REQUIRE_THROW_RE(std::runtime_error, "foo.*baz",
214                              if (1) throw std::runtime_error("a foo bar baz"));
215     else if (get_config_var("what") == "throw_rt_no_match")
216         ATF_REQUIRE_THROW_RE(std::runtime_error, "foo.*baz",
217                              if (1) throw std::runtime_error("baz foo bar a"));
218     else if (get_config_var("what") == "no_throw_rt")
219         ATF_REQUIRE_THROW_RE(std::runtime_error, "e",
220                              if (0) throw std::runtime_error("e"));
221 
222     create_ctl_file("after");
223 }
224 
225 static int
226 errno_fail_stub(const int raised_errno)
227 {
228     errno = raised_errno;
229     return -1;
230 }
231 
232 static int
233 errno_ok_stub(void)
234 {
235     return 0;
236 }
237 
238 ATF_TEST_CASE(h_check_errno);
239 ATF_TEST_CASE_HEAD(h_check_errno)
240 {
241     set_md_var("descr", "Helper test case");
242 }
243 ATF_TEST_CASE_BODY(h_check_errno)
244 {
245     create_ctl_file("before");
246 
247     if (get_config_var("what") == "no_error")
248         ATF_CHECK_ERRNO(-1, errno_ok_stub() == -1);
249     else if (get_config_var("what") == "errno_ok")
250         ATF_CHECK_ERRNO(2, errno_fail_stub(2) == -1);
251     else if (get_config_var("what") == "errno_fail")
252         ATF_CHECK_ERRNO(3, errno_fail_stub(4) == -1);
253     else
254         UNREACHABLE;
255 
256     create_ctl_file("after");
257 }
258 
259 ATF_TEST_CASE(h_require_errno);
260 ATF_TEST_CASE_HEAD(h_require_errno)
261 {
262     set_md_var("descr", "Helper test case");
263 }
264 ATF_TEST_CASE_BODY(h_require_errno)
265 {
266     create_ctl_file("before");
267 
268     if (get_config_var("what") == "no_error")
269         ATF_REQUIRE_ERRNO(-1, errno_ok_stub() == -1);
270     else if (get_config_var("what") == "errno_ok")
271         ATF_REQUIRE_ERRNO(2, errno_fail_stub(2) == -1);
272     else if (get_config_var("what") == "errno_fail")
273         ATF_REQUIRE_ERRNO(3, errno_fail_stub(4) == -1);
274     else
275         UNREACHABLE;
276 
277     create_ctl_file("after");
278 }
279 
280 // ------------------------------------------------------------------------
281 // Test cases for the macros.
282 // ------------------------------------------------------------------------
283 
284 ATF_TEST_CASE(pass);
285 ATF_TEST_CASE_HEAD(pass)
286 {
287     set_md_var("descr", "Tests the ATF_PASS macro");
288 }
289 ATF_TEST_CASE_BODY(pass)
290 {
291     ATF_TEST_CASE_USE(h_pass);
292     run_h_tc< ATF_TEST_CASE_NAME(h_pass) >();
293     ATF_REQUIRE(atf::utils::grep_file("^passed", "result"));
294     ATF_REQUIRE(atf::fs::exists(atf::fs::path("before")));
295     ATF_REQUIRE(!atf::fs::exists(atf::fs::path("after")));
296 }
297 
298 ATF_TEST_CASE(fail);
299 ATF_TEST_CASE_HEAD(fail)
300 {
301     set_md_var("descr", "Tests the ATF_FAIL macro");
302 }
303 ATF_TEST_CASE_BODY(fail)
304 {
305     ATF_TEST_CASE_USE(h_fail);
306     run_h_tc< ATF_TEST_CASE_NAME(h_fail) >();
307     ATF_REQUIRE(atf::utils::grep_file("^failed: Failed on purpose", "result"));
308     ATF_REQUIRE(atf::fs::exists(atf::fs::path("before")));
309     ATF_REQUIRE(!atf::fs::exists(atf::fs::path("after")));
310 }
311 
312 ATF_TEST_CASE(skip);
313 ATF_TEST_CASE_HEAD(skip)
314 {
315     set_md_var("descr", "Tests the ATF_SKIP macro");
316 }
317 ATF_TEST_CASE_BODY(skip)
318 {
319     ATF_TEST_CASE_USE(h_skip);
320     run_h_tc< ATF_TEST_CASE_NAME(h_skip) >();
321     ATF_REQUIRE(atf::utils::grep_file("^skipped: Skipped on purpose",
322         "result"));
323     ATF_REQUIRE(atf::fs::exists(atf::fs::path("before")));
324     ATF_REQUIRE(!atf::fs::exists(atf::fs::path("after")));
325 }
326 
327 ATF_TEST_CASE(require);
328 ATF_TEST_CASE_HEAD(require)
329 {
330     set_md_var("descr", "Tests the ATF_REQUIRE macro");
331 }
332 ATF_TEST_CASE_BODY(require)
333 {
334     struct test {
335         const char *cond;
336         bool ok;
337     } *t, tests[] = {
338         { "false", false },
339         { "true", true },
340         { NULL, false }
341     };
342 
343     const atf::fs::path before("before");
344     const atf::fs::path after("after");
345 
346     for (t = &tests[0]; t->cond != NULL; t++) {
347         atf::tests::vars_map config;
348         config["condition"] = t->cond;
349 
350         std::cout << "Checking with a " << t->cond << " value\n";
351 
352         ATF_TEST_CASE_USE(h_require);
353         run_h_tc< ATF_TEST_CASE_NAME(h_require) >(config);
354 
355         ATF_REQUIRE(atf::fs::exists(before));
356         if (t->ok) {
357             ATF_REQUIRE(atf::utils::grep_file("^passed", "result"));
358             ATF_REQUIRE(atf::fs::exists(after));
359         } else {
360             ATF_REQUIRE(atf::utils::grep_file(
361                 "^failed: .*condition not met", "result"));
362             ATF_REQUIRE(!atf::fs::exists(after));
363         }
364 
365         atf::fs::remove(before);
366         if (t->ok)
367             atf::fs::remove(after);
368     }
369 }
370 
371 ATF_TEST_CASE(require_eq);
372 ATF_TEST_CASE_HEAD(require_eq)
373 {
374     set_md_var("descr", "Tests the ATF_REQUIRE_EQ macro");
375 }
376 ATF_TEST_CASE_BODY(require_eq)
377 {
378     struct test {
379         const char *v1;
380         const char *v2;
381         bool ok;
382     } *t, tests[] = {
383         { "1", "1", true },
384         { "1", "2", false },
385         { "2", "1", false },
386         { "2", "2", true },
387         { NULL, NULL, false }
388     };
389 
390     const atf::fs::path before("before");
391     const atf::fs::path after("after");
392 
393     for (t = &tests[0]; t->v1 != NULL; t++) {
394         atf::tests::vars_map config;
395         config["v1"] = t->v1;
396         config["v2"] = t->v2;
397 
398         std::cout << "Checking with " << t->v1 << ", " << t->v2
399                   << " and expecting " << (t->ok ? "true" : "false")
400                   << "\n";
401 
402         ATF_TEST_CASE_USE(h_require_eq);
403         run_h_tc< ATF_TEST_CASE_NAME(h_require_eq) >(config);
404 
405         ATF_REQUIRE(atf::fs::exists(before));
406         if (t->ok) {
407             ATF_REQUIRE(atf::utils::grep_file("^passed", "result"));
408             ATF_REQUIRE(atf::fs::exists(after));
409         } else {
410             ATF_REQUIRE(atf::utils::grep_file("^failed: .*v1 != v2", "result"));
411             ATF_REQUIRE(!atf::fs::exists(after));
412         }
413 
414         atf::fs::remove(before);
415         if (t->ok)
416             atf::fs::remove(after);
417     }
418 }
419 
420 ATF_TEST_CASE(require_in);
421 ATF_TEST_CASE_HEAD(require_in)
422 {
423     set_md_var("descr", "Tests the ATF_REQUIRE_IN macro");
424 }
425 ATF_TEST_CASE_BODY(require_in)
426 {
427     struct test {
428         const char *value;
429         bool ok;
430     } *t, tests[] = {
431         { "foo", true },
432         { "bar", true },
433         { "baz", true },
434         { "xxx", false },
435         { "fooa", false },
436         { "foo ", false },
437         { NULL, false }
438     };
439 
440     const atf::fs::path before("before");
441     const atf::fs::path after("after");
442 
443     for (t = &tests[0]; t->value != NULL; t++) {
444         atf::tests::vars_map config;
445         config["value"] = t->value;
446 
447         ATF_TEST_CASE_USE(h_require_in);
448         run_h_tc< ATF_TEST_CASE_NAME(h_require_in) >(config);
449 
450         ATF_REQUIRE(atf::fs::exists(before));
451         if (t->ok) {
452             ATF_REQUIRE(atf::utils::grep_file("^passed", "result"));
453             ATF_REQUIRE(atf::fs::exists(after));
454         } else {
455             ATF_REQUIRE(atf::utils::grep_file("^failed: ", "result"));
456             ATF_REQUIRE(!atf::fs::exists(after));
457         }
458 
459         atf::fs::remove(before);
460         if (t->ok)
461             atf::fs::remove(after);
462     }
463 }
464 
465 ATF_TEST_CASE(require_match);
466 ATF_TEST_CASE_HEAD(require_match)
467 {
468     set_md_var("descr", "Tests the ATF_REQUIRE_MATCH macro");
469 }
470 ATF_TEST_CASE_BODY(require_match)
471 {
472     struct test {
473         const char *regexp;
474         const char *string;
475         bool ok;
476     } *t, tests[] = {
477         { "foo.*bar", "this is a foo, bar, baz", true },
478         { "bar.*baz", "this is a baz, bar, foo", false },
479         { NULL, NULL, false }
480     };
481 
482     const atf::fs::path before("before");
483     const atf::fs::path after("after");
484 
485     for (t = &tests[0]; t->regexp != NULL; t++) {
486         atf::tests::vars_map config;
487         config["regexp"] = t->regexp;
488         config["string"] = t->string;
489 
490         std::cout << "Checking with " << t->regexp << ", " << t->string
491                   << " and expecting " << (t->ok ? "true" : "false")
492                   << "\n";
493 
494         ATF_TEST_CASE_USE(h_require_match);
495         run_h_tc< ATF_TEST_CASE_NAME(h_require_match) >(config);
496 
497         ATF_REQUIRE(atf::fs::exists(before));
498         if (t->ok) {
499             ATF_REQUIRE(atf::utils::grep_file("^passed", "result"));
500             ATF_REQUIRE(atf::fs::exists(after));
501         } else {
502             ATF_REQUIRE(atf::utils::grep_file("^failed: ", "result"));
503             ATF_REQUIRE(!atf::fs::exists(after));
504         }
505 
506         atf::fs::remove(before);
507         if (t->ok)
508             atf::fs::remove(after);
509     }
510 }
511 
512 ATF_TEST_CASE(require_not_in);
513 ATF_TEST_CASE_HEAD(require_not_in)
514 {
515     set_md_var("descr", "Tests the ATF_REQUIRE_NOT_IN macro");
516 }
517 ATF_TEST_CASE_BODY(require_not_in)
518 {
519     struct test {
520         const char *value;
521         bool ok;
522     } *t, tests[] = {
523         { "foo", false },
524         { "bar", false },
525         { "baz", false },
526         { "xxx", true },
527         { "fooa", true },
528         { "foo ", true },
529         { NULL, false }
530     };
531 
532     const atf::fs::path before("before");
533     const atf::fs::path after("after");
534 
535     for (t = &tests[0]; t->value != NULL; t++) {
536         atf::tests::vars_map config;
537         config["value"] = t->value;
538 
539         ATF_TEST_CASE_USE(h_require_not_in);
540         run_h_tc< ATF_TEST_CASE_NAME(h_require_not_in) >(config);
541 
542         ATF_REQUIRE(atf::fs::exists(before));
543         if (t->ok) {
544             ATF_REQUIRE(atf::utils::grep_file("^passed", "result"));
545             ATF_REQUIRE(atf::fs::exists(after));
546         } else {
547             ATF_REQUIRE(atf::utils::grep_file("^failed: ", "result"));
548             ATF_REQUIRE(!atf::fs::exists(after));
549         }
550 
551         atf::fs::remove(before);
552         if (t->ok)
553             atf::fs::remove(after);
554     }
555 }
556 
557 ATF_TEST_CASE(require_throw);
558 ATF_TEST_CASE_HEAD(require_throw)
559 {
560     set_md_var("descr", "Tests the ATF_REQUIRE_THROW macro");
561 }
562 ATF_TEST_CASE_BODY(require_throw)
563 {
564     struct test {
565         const char *what;
566         bool ok;
567         const char *msg;
568     } *t, tests[] = {
569         { "throw_int", false, "unexpected error" },
570         { "throw_rt", true, NULL },
571         { "no_throw_rt", false, "did not throw" },
572         { NULL, false, NULL }
573     };
574 
575     const atf::fs::path before("before");
576     const atf::fs::path after("after");
577 
578     for (t = &tests[0]; t->what != NULL; t++) {
579         atf::tests::vars_map config;
580         config["what"] = t->what;
581 
582         std::cout << "Checking with " << t->what << " and expecting "
583                   << (t->ok ? "true" : "false") << "\n";
584 
585         ATF_TEST_CASE_USE(h_require_throw);
586         run_h_tc< ATF_TEST_CASE_NAME(h_require_throw) >(config);
587 
588         ATF_REQUIRE(atf::fs::exists(before));
589         if (t->ok) {
590             ATF_REQUIRE(atf::utils::grep_file("^passed", "result"));
591             ATF_REQUIRE(atf::fs::exists(after));
592         } else {
593             std::cout << "Checking that message contains '" << t->msg
594                       << "'\n";
595             std::string exp_result = std::string("^failed: .*") + t->msg;
596             ATF_REQUIRE(atf::utils::grep_file(exp_result.c_str(), "result"));
597             ATF_REQUIRE(!atf::fs::exists(after));
598         }
599 
600         atf::fs::remove(before);
601         if (t->ok)
602             atf::fs::remove(after);
603     }
604 }
605 
606 ATF_TEST_CASE(require_throw_re);
607 ATF_TEST_CASE_HEAD(require_throw_re)
608 {
609     set_md_var("descr", "Tests the ATF_REQUIRE_THROW_RE macro");
610 }
611 ATF_TEST_CASE_BODY(require_throw_re)
612 {
613     struct test {
614         const char *what;
615         bool ok;
616         const char *msg;
617     } *t, tests[] = {
618         { "throw_int", false, "unexpected error" },
619         { "throw_rt_match", true, NULL },
620         { "throw_rt_no_match", false,
621           "threw.*runtime_error\\(baz foo bar a\\).*"
622           "does not match 'foo\\.\\*baz'" },
623         { "no_throw_rt", false, "did not throw" },
624         { NULL, false, NULL }
625     };
626 
627     const atf::fs::path before("before");
628     const atf::fs::path after("after");
629 
630     for (t = &tests[0]; t->what != NULL; t++) {
631         atf::tests::vars_map config;
632         config["what"] = t->what;
633 
634         std::cout << "Checking with " << t->what << " and expecting "
635                   << (t->ok ? "true" : "false") << "\n";
636 
637         ATF_TEST_CASE_USE(h_require_throw_re);
638         run_h_tc< ATF_TEST_CASE_NAME(h_require_throw_re) >(config);
639 
640         ATF_REQUIRE(atf::fs::exists(before));
641         if (t->ok) {
642             ATF_REQUIRE(atf::utils::grep_file("^passed", "result"));
643             ATF_REQUIRE(atf::fs::exists(after));
644         } else {
645             std::cout << "Checking that message contains '" << t->msg
646                       << "'\n";
647             std::string exp_result = std::string("^failed: .*") + t->msg;
648             ATF_REQUIRE(atf::utils::grep_file(exp_result.c_str(), "result"));
649             ATF_REQUIRE(!atf::fs::exists(after));
650         }
651 
652         atf::fs::remove(before);
653         if (t->ok)
654             atf::fs::remove(after);
655     }
656 }
657 
658 ATF_TEST_CASE(check_errno);
659 ATF_TEST_CASE_HEAD(check_errno)
660 {
661     set_md_var("descr", "Tests the ATF_CHECK_ERRNO macro");
662 }
663 ATF_TEST_CASE_BODY(check_errno)
664 {
665     struct test {
666         const char *what;
667         bool ok;
668         const char *msg;
669     } *t, tests[] = {
670         { "no_error", false,
671           "Expected true value in errno_ok_stub\\(\\) == -1" },
672         { "errno_ok", true, NULL },
673         { "errno_fail", false,
674           "Expected errno 3, got 4, in errno_fail_stub\\(4\\) == -1" },
675         { NULL, false, NULL }
676     };
677 
678     const atf::fs::path before("before");
679     const atf::fs::path after("after");
680 
681     for (t = &tests[0]; t->what != NULL; t++) {
682         atf::tests::vars_map config;
683         config["what"] = t->what;
684 
685         ATF_TEST_CASE_USE(h_check_errno);
686         run_h_tc< ATF_TEST_CASE_NAME(h_check_errno) >(config);
687 
688         ATF_REQUIRE(atf::fs::exists(before));
689         ATF_REQUIRE(atf::fs::exists(after));
690 
691         if (t->ok) {
692             ATF_REQUIRE(atf::utils::grep_file("^passed", "result"));
693         } else {
694             ATF_REQUIRE(atf::utils::grep_file("^failed", "result"));
695 
696             std::string exp_result = "macros_test.cpp:[0-9]+: " +
697                 std::string(t->msg) + "$";
698             ATF_REQUIRE(atf::utils::grep_file(exp_result.c_str(), "stderr"));
699         }
700 
701         atf::fs::remove(before);
702         atf::fs::remove(after);
703     }
704 }
705 
706 ATF_TEST_CASE(require_errno);
707 ATF_TEST_CASE_HEAD(require_errno)
708 {
709     set_md_var("descr", "Tests the ATF_REQUIRE_ERRNO macro");
710 }
711 ATF_TEST_CASE_BODY(require_errno)
712 {
713     struct test {
714         const char *what;
715         bool ok;
716         const char *msg;
717     } *t, tests[] = {
718         { "no_error", false,
719           "Expected true value in errno_ok_stub\\(\\) == -1" },
720         { "errno_ok", true, NULL },
721         { "errno_fail", false,
722           "Expected errno 3, got 4, in errno_fail_stub\\(4\\) == -1" },
723         { NULL, false, NULL }
724     };
725 
726     const atf::fs::path before("before");
727     const atf::fs::path after("after");
728 
729     for (t = &tests[0]; t->what != NULL; t++) {
730         atf::tests::vars_map config;
731         config["what"] = t->what;
732 
733         ATF_TEST_CASE_USE(h_require_errno);
734         run_h_tc< ATF_TEST_CASE_NAME(h_require_errno) >(config);
735 
736         ATF_REQUIRE(atf::fs::exists(before));
737         if (t->ok) {
738             ATF_REQUIRE(atf::utils::grep_file("^passed", "result"));
739             ATF_REQUIRE(atf::fs::exists(after));
740         } else {
741             std::string exp_result = "^failed: .*macros_test.cpp:[0-9]+: " +
742                 std::string(t->msg) + "$";
743             ATF_REQUIRE(atf::utils::grep_file(exp_result.c_str(), "result"));
744 
745             ATF_REQUIRE(!atf::fs::exists(after));
746         }
747 
748         atf::fs::remove(before);
749         if (t->ok)
750             atf::fs::remove(after);
751     }
752 }
753 
754 // ------------------------------------------------------------------------
755 // Tests cases for the header file.
756 // ------------------------------------------------------------------------
757 
758 BUILD_TC(use, "macros_hpp_test.cpp",
759          "Tests that the macros provided by the atf-c++/macros.hpp file "
760          "do not cause syntax errors when used",
761          "Build of macros_hpp_test.cpp failed; some macros in "
762          "atf-c++/macros.hpp are broken");
763 
764 ATF_TEST_CASE(detect_unused_tests);
765 ATF_TEST_CASE_HEAD(detect_unused_tests)
766 {
767     set_md_var("descr",
768                "Tests that defining an unused test case raises a warning (and "
769                "thus an error)");
770 }
771 ATF_TEST_CASE_BODY(detect_unused_tests)
772 {
773     const char* validate_compiler =
774         "class test_class { public: int dummy; };\n"
775         "#define define_unused static test_class unused\n"
776         "define_unused;\n";
777 
778     atf::utils::create_file("compiler_test.cpp", validate_compiler);
779     if (build_check_cxx_o("compiler_test.cpp"))
780         expect_fail("Compiler does not raise a warning on an unused "
781                     "static global variable declared by a macro");
782 
783     if (build_check_cxx_o_srcdir(*this, "unused_test.cpp"))
784         ATF_FAIL("Build of unused_test.cpp passed; unused test cases are "
785                  "not properly detected");
786 }
787 
788 // ------------------------------------------------------------------------
789 // Main.
790 // ------------------------------------------------------------------------
791 
792 ATF_INIT_TEST_CASES(tcs)
793 {
794     // Add the test cases for the macros.
795     ATF_ADD_TEST_CASE(tcs, pass);
796     ATF_ADD_TEST_CASE(tcs, fail);
797     ATF_ADD_TEST_CASE(tcs, skip);
798     ATF_ADD_TEST_CASE(tcs, check_errno);
799     ATF_ADD_TEST_CASE(tcs, require);
800     ATF_ADD_TEST_CASE(tcs, require_eq);
801     ATF_ADD_TEST_CASE(tcs, require_in);
802     ATF_ADD_TEST_CASE(tcs, require_match);
803     ATF_ADD_TEST_CASE(tcs, require_not_in);
804     ATF_ADD_TEST_CASE(tcs, require_throw);
805     ATF_ADD_TEST_CASE(tcs, require_throw_re);
806     ATF_ADD_TEST_CASE(tcs, require_errno);
807 
808     // Add the test cases for the header file.
809     ATF_ADD_TEST_CASE(tcs, use);
810     ATF_ADD_TEST_CASE(tcs, detect_unused_tests);
811 }
812