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