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 <stdlib.h>
32#include <string.h>
33#include <unistd.h>
34
35#include "atf-c/error.h"
36#include "atf-c/tc.h"
37#include "atf-c/tp.h"
38
39#include "detail/fs.h"
40#include "detail/map.h"
41#include "detail/sanity.h"
42
43struct atf_tp_impl {
44    atf_list_t m_tcs;
45    atf_map_t m_config;
46};
47
48/* ---------------------------------------------------------------------
49 * Auxiliary functions.
50 * --------------------------------------------------------------------- */
51
52static
53const atf_tc_t *
54find_tc(const atf_tp_t *tp, const char *ident)
55{
56    const atf_tc_t *tc;
57    atf_list_citer_t iter;
58
59    tc = NULL;
60    atf_list_for_each_c(iter, &tp->pimpl->m_tcs) {
61        const atf_tc_t *tc2;
62        tc2 = atf_list_citer_data(iter);
63        if (strcmp(atf_tc_get_ident(tc2), ident) == 0) {
64            tc = tc2;
65            break;
66        }
67    }
68    return tc;
69}
70
71/* ---------------------------------------------------------------------
72 * The "atf_tp" type.
73 * --------------------------------------------------------------------- */
74
75/*
76 * Constructors/destructors.
77 */
78
79atf_error_t
80atf_tp_init(atf_tp_t *tp, const char *const *config)
81{
82    atf_error_t err;
83
84    PRE(config != NULL);
85
86    tp->pimpl = malloc(sizeof(struct atf_tp_impl));
87    if (tp->pimpl == NULL)
88        return atf_no_memory_error();
89
90    err = atf_list_init(&tp->pimpl->m_tcs);
91    if (atf_is_error(err))
92        goto out;
93
94    err = atf_map_init_charpp(&tp->pimpl->m_config, config);
95    if (atf_is_error(err)) {
96        atf_list_fini(&tp->pimpl->m_tcs);
97        goto out;
98    }
99
100    INV(!atf_is_error(err));
101out:
102    return err;
103}
104
105void
106atf_tp_fini(atf_tp_t *tp)
107{
108    atf_list_iter_t iter;
109
110    atf_map_fini(&tp->pimpl->m_config);
111
112    atf_list_for_each(iter, &tp->pimpl->m_tcs) {
113        atf_tc_t *tc = atf_list_iter_data(iter);
114        atf_tc_fini(tc);
115    }
116    atf_list_fini(&tp->pimpl->m_tcs);
117
118    free(tp->pimpl);
119}
120
121/*
122 * Getters.
123 */
124
125char **
126atf_tp_get_config(const atf_tp_t *tp)
127{
128    return atf_map_to_charpp(&tp->pimpl->m_config);
129}
130
131bool
132atf_tp_has_tc(const atf_tp_t *tp, const char *id)
133{
134    const atf_tc_t *tc = find_tc(tp, id);
135    return tc != NULL;
136}
137
138const atf_tc_t *
139atf_tp_get_tc(const atf_tp_t *tp, const char *id)
140{
141    const atf_tc_t *tc = find_tc(tp, id);
142    PRE(tc != NULL);
143    return tc;
144}
145
146const atf_tc_t *const *
147atf_tp_get_tcs(const atf_tp_t *tp)
148{
149    const atf_tc_t **array;
150    atf_list_citer_t iter;
151    size_t i;
152
153    array = malloc(sizeof(atf_tc_t *) *
154                   (atf_list_size(&tp->pimpl->m_tcs) + 1));
155    if (array == NULL)
156        goto out;
157
158    i = 0;
159    atf_list_for_each_c(iter, &tp->pimpl->m_tcs) {
160        array[i] = atf_list_citer_data(iter);
161        if (array[i] == NULL) {
162            free(array);
163            array = NULL;
164            goto out;
165        }
166
167        i++;
168    }
169    array[i] = NULL;
170
171out:
172    return array;
173}
174
175/*
176 * Modifiers.
177 */
178
179atf_error_t
180atf_tp_add_tc(atf_tp_t *tp, atf_tc_t *tc)
181{
182    atf_error_t err;
183
184    PRE(find_tc(tp, atf_tc_get_ident(tc)) == NULL);
185
186    err = atf_list_append(&tp->pimpl->m_tcs, tc, false);
187
188    POST(find_tc(tp, atf_tc_get_ident(tc)) != NULL);
189
190    return err;
191}
192
193/* ---------------------------------------------------------------------
194 * Free functions.
195 * --------------------------------------------------------------------- */
196
197atf_error_t
198atf_tp_run(const atf_tp_t *tp, const char *tcname, const char *resfile)
199{
200    const atf_tc_t *tc;
201
202    tc = find_tc(tp, tcname);
203    PRE(tc != NULL);
204
205    return atf_tc_run(tc, resfile);
206}
207
208atf_error_t
209atf_tp_cleanup(const atf_tp_t *tp, const char *tcname)
210{
211    const atf_tc_t *tc;
212
213    tc = find_tc(tp, tcname);
214    PRE(tc != NULL);
215
216    return atf_tc_cleanup(tc);
217}
218