xref: /netbsd-src/external/bsd/atf/dist/atf-c/tp.c (revision 274254cdae52594c1aa480a736aef78313d15c9c)
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 
30 #include <stdio.h>
31 #include <string.h>
32 
33 #include "atf-c/error.h"
34 #include "atf-c/fs.h"
35 #include "atf-c/io.h"
36 #include "atf-c/sanity.h"
37 #include "atf-c/tc.h"
38 #include "atf-c/tcr.h"
39 #include "atf-c/tp.h"
40 
41 /* ---------------------------------------------------------------------
42  * Auxiliary functions.
43  * --------------------------------------------------------------------- */
44 
45 static
46 const atf_tc_t *
47 find_tc(const atf_tp_t *tp, const char *ident)
48 {
49     const atf_tc_t *tc;
50     atf_list_citer_t iter;
51 
52     tc = NULL;
53     atf_list_for_each_c(iter, &tp->m_tcs) {
54         const atf_tc_t *tc2;
55         tc2 = atf_list_citer_data(iter);
56         if (strcmp(tc2->m_ident, ident) == 0) {
57             tc = tc2;
58             break;
59         }
60     }
61     return tc;
62 }
63 
64 /* ---------------------------------------------------------------------
65  * The "atf_tp" type.
66  * --------------------------------------------------------------------- */
67 
68 /*
69  * Constructors/destructors.
70  */
71 
72 atf_error_t
73 atf_tp_init(atf_tp_t *tp, struct atf_map *config)
74 {
75     atf_error_t err;
76 
77     PRE(config != NULL);
78 
79     atf_object_init(&tp->m_object);
80 
81     err = atf_list_init(&tp->m_tcs);
82     if (atf_is_error(err))
83         goto err_object;
84 
85     tp->m_config = config;
86 
87     INV(!atf_is_error(err));
88     return err;
89 
90 err_object:
91     atf_object_fini(&tp->m_object);
92     return err;
93 }
94 
95 void
96 atf_tp_fini(atf_tp_t *tp)
97 {
98     atf_list_iter_t iter;
99 
100     atf_list_for_each(iter, &tp->m_tcs) {
101         atf_tc_t *tc = atf_list_iter_data(iter);
102         atf_tc_fini(tc);
103     }
104     atf_list_fini(&tp->m_tcs);
105 
106     atf_object_fini(&tp->m_object);
107 }
108 
109 /*
110  * Getters.
111  */
112 
113 const struct atf_map *
114 atf_tp_get_config(const atf_tp_t *tp)
115 {
116     return tp->m_config;
117 }
118 
119 const atf_tc_t *
120 atf_tp_get_tc(const atf_tp_t *tp, const char *id)
121 {
122     const atf_tc_t *tc = find_tc(tp, id);
123     PRE(tc != NULL);
124     return tc;
125 }
126 
127 const atf_list_t *
128 atf_tp_get_tcs(const atf_tp_t *tp)
129 {
130     return &tp->m_tcs;
131 }
132 
133 /*
134  * Modifiers.
135  */
136 
137 atf_error_t
138 atf_tp_add_tc(atf_tp_t *tp, atf_tc_t *tc)
139 {
140     atf_error_t err;
141 
142     PRE(find_tc(tp, tc->m_ident) == NULL);
143 
144     err = atf_list_append(&tp->m_tcs, tc);
145 
146     POST(find_tc(tp, tc->m_ident) != NULL);
147 
148     return err;
149 }
150 
151 /* ---------------------------------------------------------------------
152  * Free functions.
153  * --------------------------------------------------------------------- */
154 
155 atf_error_t
156 atf_tp_run(const atf_tp_t *tp, const atf_list_t *ids, int fd,
157            const atf_fs_path_t *workdir, size_t *failcount)
158 {
159     atf_error_t err;
160     atf_list_citer_t iter;
161     size_t count;
162 
163     err = atf_io_write_fmt(fd, "Content-Type: application/X-atf-tcs; "
164                            "version=\"1\"\n\n");
165     if (atf_is_error(err))
166         goto out;
167     err = atf_io_write_fmt(fd, "tcs-count: %d\n", atf_list_size(ids));
168     if (atf_is_error(err))
169         goto out;
170 
171     *failcount = count = 0;
172     atf_list_for_each_c(iter, ids) {
173         const char *ident = atf_list_citer_data(iter);
174         const atf_tc_t *tc;
175         atf_tcr_t tcr;
176         int state;
177 
178         err = atf_io_write_fmt(fd, "tc-start: %s\n", ident);
179         if (atf_is_error(err))
180             goto out;
181 
182         tc = find_tc(tp, ident);
183         PRE(tc != NULL);
184 
185         err = atf_tc_run(tc, &tcr, workdir);
186         if (atf_is_error(err))
187             goto out;
188 
189         count++;
190         if (count < atf_list_size(ids)) {
191             fprintf(stdout, "__atf_tc_separator__\n");
192             fprintf(stderr, "__atf_tc_separator__\n");
193         }
194         fflush(stdout);
195         fflush(stderr);
196 
197         state = atf_tcr_get_state(&tcr);
198         if (state == atf_tcr_passed_state) {
199             err = atf_io_write_fmt(fd, "tc-end: %s, passed\n", ident);
200         } else if (state == atf_tcr_failed_state) {
201             const atf_dynstr_t *reason = atf_tcr_get_reason(&tcr);
202             err = atf_io_write_fmt(fd, "tc-end: %s, failed, %s\n", ident,
203                                    atf_dynstr_cstring(reason));
204             (*failcount)++;
205         } else if (state == atf_tcr_skipped_state) {
206             const atf_dynstr_t *reason = atf_tcr_get_reason(&tcr);
207             err = atf_io_write_fmt(fd, "tc-end: %s, skipped, %s\n", ident,
208                                    atf_dynstr_cstring(reason));
209         } else
210             UNREACHABLE;
211         atf_tcr_fini(&tcr);
212         if (atf_is_error(err))
213             goto out;
214     }
215 
216 out:
217     return err;
218 }
219