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