macros_test.cpp revision 275988
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
28extern "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
51static
52void
53create_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
62ATF_TEST_CASE(h_pass);
63ATF_TEST_CASE_HEAD(h_pass)
64{
65    set_md_var("descr", "Helper test case");
66}
67ATF_TEST_CASE_BODY(h_pass)
68{
69    create_ctl_file("before");
70    ATF_PASS();
71    create_ctl_file("after");
72}
73
74ATF_TEST_CASE(h_fail);
75ATF_TEST_CASE_HEAD(h_fail)
76{
77    set_md_var("descr", "Helper test case");
78}
79ATF_TEST_CASE_BODY(h_fail)
80{
81    create_ctl_file("before");
82    ATF_FAIL("Failed on purpose");
83    create_ctl_file("after");
84}
85
86ATF_TEST_CASE(h_skip);
87ATF_TEST_CASE_HEAD(h_skip)
88{
89    set_md_var("descr", "Helper test case");
90}
91ATF_TEST_CASE_BODY(h_skip)
92{
93    create_ctl_file("before");
94    ATF_SKIP("Skipped on purpose");
95    create_ctl_file("after");
96}
97
98ATF_TEST_CASE(h_require);
99ATF_TEST_CASE_HEAD(h_require)
100{
101    set_md_var("descr", "Helper test case");
102}
103ATF_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
112ATF_TEST_CASE(h_require_eq);
113ATF_TEST_CASE_HEAD(h_require_eq)
114{
115    set_md_var("descr", "Helper test case");
116}
117ATF_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
127ATF_TEST_CASE(h_require_in);
128ATF_TEST_CASE_HEAD(h_require_in)
129{
130    set_md_var("descr", "Helper test case");
131}
132ATF_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
146ATF_TEST_CASE(h_require_match);
147ATF_TEST_CASE_HEAD(h_require_match)
148{
149    set_md_var("descr", "Helper test case");
150}
151ATF_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
161ATF_TEST_CASE(h_require_not_in);
162ATF_TEST_CASE_HEAD(h_require_not_in)
163{
164    set_md_var("descr", "Helper test case");
165}
166ATF_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
180ATF_TEST_CASE(h_require_throw);
181ATF_TEST_CASE_HEAD(h_require_throw)
182{
183    set_md_var("descr", "Helper test case");
184}
185ATF_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
201ATF_TEST_CASE(h_require_throw_re);
202ATF_TEST_CASE_HEAD(h_require_throw_re)
203{
204    set_md_var("descr", "Helper test case");
205}
206ATF_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
225static int
226errno_fail_stub(const int raised_errno)
227{
228    errno = raised_errno;
229    return -1;
230}
231
232static int
233errno_ok_stub(void)
234{
235    return 0;
236}
237
238ATF_TEST_CASE(h_check_errno);
239ATF_TEST_CASE_HEAD(h_check_errno)
240{
241    set_md_var("descr", "Helper test case");
242}
243ATF_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
259ATF_TEST_CASE(h_require_errno);
260ATF_TEST_CASE_HEAD(h_require_errno)
261{
262    set_md_var("descr", "Helper test case");
263}
264ATF_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
284ATF_TEST_CASE(pass);
285ATF_TEST_CASE_HEAD(pass)
286{
287    set_md_var("descr", "Tests the ATF_PASS macro");
288}
289ATF_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
298ATF_TEST_CASE(fail);
299ATF_TEST_CASE_HEAD(fail)
300{
301    set_md_var("descr", "Tests the ATF_FAIL macro");
302}
303ATF_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
312ATF_TEST_CASE(skip);
313ATF_TEST_CASE_HEAD(skip)
314{
315    set_md_var("descr", "Tests the ATF_SKIP macro");
316}
317ATF_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
327ATF_TEST_CASE(require);
328ATF_TEST_CASE_HEAD(require)
329{
330    set_md_var("descr", "Tests the ATF_REQUIRE macro");
331}
332ATF_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
371ATF_TEST_CASE(require_eq);
372ATF_TEST_CASE_HEAD(require_eq)
373{
374    set_md_var("descr", "Tests the ATF_REQUIRE_EQ macro");
375}
376ATF_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
420ATF_TEST_CASE(require_in);
421ATF_TEST_CASE_HEAD(require_in)
422{
423    set_md_var("descr", "Tests the ATF_REQUIRE_IN macro");
424}
425ATF_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
465ATF_TEST_CASE(require_match);
466ATF_TEST_CASE_HEAD(require_match)
467{
468    set_md_var("descr", "Tests the ATF_REQUIRE_MATCH macro");
469}
470ATF_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
512ATF_TEST_CASE(require_not_in);
513ATF_TEST_CASE_HEAD(require_not_in)
514{
515    set_md_var("descr", "Tests the ATF_REQUIRE_NOT_IN macro");
516}
517ATF_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
557ATF_TEST_CASE(require_throw);
558ATF_TEST_CASE_HEAD(require_throw)
559{
560    set_md_var("descr", "Tests the ATF_REQUIRE_THROW macro");
561}
562ATF_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
606ATF_TEST_CASE(require_throw_re);
607ATF_TEST_CASE_HEAD(require_throw_re)
608{
609    set_md_var("descr", "Tests the ATF_REQUIRE_THROW_RE macro");
610}
611ATF_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
658ATF_TEST_CASE(check_errno);
659ATF_TEST_CASE_HEAD(check_errno)
660{
661    set_md_var("descr", "Tests the ATF_CHECK_ERRNO macro");
662}
663ATF_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
706ATF_TEST_CASE(require_errno);
707ATF_TEST_CASE_HEAD(require_errno)
708{
709    set_md_var("descr", "Tests the ATF_REQUIRE_ERRNO macro");
710}
711ATF_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
758BUILD_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
764ATF_TEST_CASE(detect_unused_tests);
765ATF_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}
771ATF_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
792ATF_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