1*11be35a1SLionel Sambuc /*
2*11be35a1SLionel Sambuc * Automated Testing Framework (atf)
3*11be35a1SLionel Sambuc *
4*11be35a1SLionel Sambuc * Copyright (c) 2008 The NetBSD Foundation, Inc.
5*11be35a1SLionel Sambuc * All rights reserved.
6*11be35a1SLionel Sambuc *
7*11be35a1SLionel Sambuc * Redistribution and use in source and binary forms, with or without
8*11be35a1SLionel Sambuc * modification, are permitted provided that the following conditions
9*11be35a1SLionel Sambuc * are met:
10*11be35a1SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
11*11be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer.
12*11be35a1SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
13*11be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
14*11be35a1SLionel Sambuc * documentation and/or other materials provided with the distribution.
15*11be35a1SLionel Sambuc *
16*11be35a1SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17*11be35a1SLionel Sambuc * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18*11be35a1SLionel Sambuc * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19*11be35a1SLionel Sambuc * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20*11be35a1SLionel Sambuc * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21*11be35a1SLionel Sambuc * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*11be35a1SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23*11be35a1SLionel Sambuc * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*11be35a1SLionel Sambuc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25*11be35a1SLionel Sambuc * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26*11be35a1SLionel Sambuc * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27*11be35a1SLionel Sambuc * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*11be35a1SLionel Sambuc */
29*11be35a1SLionel Sambuc
30*11be35a1SLionel Sambuc #include <stdarg.h>
31*11be35a1SLionel Sambuc #include <stdio.h>
32*11be35a1SLionel Sambuc #include <stdlib.h>
33*11be35a1SLionel Sambuc #include <string.h>
34*11be35a1SLionel Sambuc
35*11be35a1SLionel Sambuc #include "atf-c/error.h"
36*11be35a1SLionel Sambuc
37*11be35a1SLionel Sambuc #include "detail/sanity.h"
38*11be35a1SLionel Sambuc
39*11be35a1SLionel Sambuc /* Theoretically, there can only be a single error intance at any given
40*11be35a1SLionel Sambuc * point in time, because errors are raised at one point and must be
41*11be35a1SLionel Sambuc * handled immediately. If another error has to be raised during the
42*11be35a1SLionel Sambuc * handling process, something else has to be done with the previous
43*11be35a1SLionel Sambuc * error.
44*11be35a1SLionel Sambuc *
45*11be35a1SLionel Sambuc * This is per-thread information and will break threaded tests, but we
46*11be35a1SLionel Sambuc * currently do not have any threading support; therefore, this is fine. */
47*11be35a1SLionel Sambuc static bool error_on_flight = false;
48*11be35a1SLionel Sambuc
49*11be35a1SLionel Sambuc /* ---------------------------------------------------------------------
50*11be35a1SLionel Sambuc * Auxiliary functions.
51*11be35a1SLionel Sambuc * --------------------------------------------------------------------- */
52*11be35a1SLionel Sambuc
53*11be35a1SLionel Sambuc static
54*11be35a1SLionel Sambuc void
error_format(const atf_error_t err,char * buf,size_t buflen)55*11be35a1SLionel Sambuc error_format(const atf_error_t err, char *buf, size_t buflen)
56*11be35a1SLionel Sambuc {
57*11be35a1SLionel Sambuc PRE(err != NULL);
58*11be35a1SLionel Sambuc snprintf(buf, buflen, "Error '%s'", err->m_type);
59*11be35a1SLionel Sambuc }
60*11be35a1SLionel Sambuc
61*11be35a1SLionel Sambuc static
62*11be35a1SLionel Sambuc bool
error_init(atf_error_t err,const char * type,void * data,size_t datalen,void (* format)(const atf_error_t,char *,size_t))63*11be35a1SLionel Sambuc error_init(atf_error_t err, const char *type, void *data, size_t datalen,
64*11be35a1SLionel Sambuc void (*format)(const atf_error_t, char *, size_t))
65*11be35a1SLionel Sambuc {
66*11be35a1SLionel Sambuc bool ok;
67*11be35a1SLionel Sambuc
68*11be35a1SLionel Sambuc PRE(data != NULL || datalen == 0);
69*11be35a1SLionel Sambuc PRE(datalen != 0 || data == NULL);
70*11be35a1SLionel Sambuc
71*11be35a1SLionel Sambuc err->m_free = false;
72*11be35a1SLionel Sambuc err->m_type = type;
73*11be35a1SLionel Sambuc err->m_format = (format == NULL) ? error_format : format;
74*11be35a1SLionel Sambuc
75*11be35a1SLionel Sambuc ok = true;
76*11be35a1SLionel Sambuc if (data == NULL) {
77*11be35a1SLionel Sambuc err->m_data = NULL;
78*11be35a1SLionel Sambuc } else {
79*11be35a1SLionel Sambuc err->m_data = malloc(datalen);
80*11be35a1SLionel Sambuc if (err->m_data == NULL) {
81*11be35a1SLionel Sambuc ok = false;
82*11be35a1SLionel Sambuc } else
83*11be35a1SLionel Sambuc memcpy(err->m_data, data, datalen);
84*11be35a1SLionel Sambuc }
85*11be35a1SLionel Sambuc
86*11be35a1SLionel Sambuc return ok;
87*11be35a1SLionel Sambuc }
88*11be35a1SLionel Sambuc
89*11be35a1SLionel Sambuc /* ---------------------------------------------------------------------
90*11be35a1SLionel Sambuc * The "atf_error" type.
91*11be35a1SLionel Sambuc * --------------------------------------------------------------------- */
92*11be35a1SLionel Sambuc
93*11be35a1SLionel Sambuc atf_error_t
atf_error_new(const char * type,void * data,size_t datalen,void (* format)(const atf_error_t,char *,size_t))94*11be35a1SLionel Sambuc atf_error_new(const char *type, void *data, size_t datalen,
95*11be35a1SLionel Sambuc void (*format)(const atf_error_t, char *, size_t))
96*11be35a1SLionel Sambuc {
97*11be35a1SLionel Sambuc atf_error_t err;
98*11be35a1SLionel Sambuc
99*11be35a1SLionel Sambuc PRE(!error_on_flight);
100*11be35a1SLionel Sambuc PRE(data != NULL || datalen == 0);
101*11be35a1SLionel Sambuc PRE(datalen != 0 || data == NULL);
102*11be35a1SLionel Sambuc
103*11be35a1SLionel Sambuc err = malloc(sizeof(*err));
104*11be35a1SLionel Sambuc if (err == NULL)
105*11be35a1SLionel Sambuc err = atf_no_memory_error();
106*11be35a1SLionel Sambuc else {
107*11be35a1SLionel Sambuc if (!error_init(err, type, data, datalen, format)) {
108*11be35a1SLionel Sambuc free(err);
109*11be35a1SLionel Sambuc err = atf_no_memory_error();
110*11be35a1SLionel Sambuc } else {
111*11be35a1SLionel Sambuc err->m_free = true;
112*11be35a1SLionel Sambuc error_on_flight = true;
113*11be35a1SLionel Sambuc }
114*11be35a1SLionel Sambuc }
115*11be35a1SLionel Sambuc
116*11be35a1SLionel Sambuc INV(err != NULL);
117*11be35a1SLionel Sambuc POST(error_on_flight);
118*11be35a1SLionel Sambuc return err;
119*11be35a1SLionel Sambuc }
120*11be35a1SLionel Sambuc
121*11be35a1SLionel Sambuc void
atf_error_free(atf_error_t err)122*11be35a1SLionel Sambuc atf_error_free(atf_error_t err)
123*11be35a1SLionel Sambuc {
124*11be35a1SLionel Sambuc bool freeit;
125*11be35a1SLionel Sambuc
126*11be35a1SLionel Sambuc PRE(error_on_flight);
127*11be35a1SLionel Sambuc PRE(err != NULL);
128*11be35a1SLionel Sambuc
129*11be35a1SLionel Sambuc freeit = err->m_free;
130*11be35a1SLionel Sambuc
131*11be35a1SLionel Sambuc if (err->m_data != NULL)
132*11be35a1SLionel Sambuc free(err->m_data);
133*11be35a1SLionel Sambuc
134*11be35a1SLionel Sambuc if (freeit)
135*11be35a1SLionel Sambuc free(err);
136*11be35a1SLionel Sambuc
137*11be35a1SLionel Sambuc error_on_flight = false;
138*11be35a1SLionel Sambuc }
139*11be35a1SLionel Sambuc
140*11be35a1SLionel Sambuc atf_error_t
atf_no_error(void)141*11be35a1SLionel Sambuc atf_no_error(void)
142*11be35a1SLionel Sambuc {
143*11be35a1SLionel Sambuc return NULL;
144*11be35a1SLionel Sambuc }
145*11be35a1SLionel Sambuc
146*11be35a1SLionel Sambuc bool
atf_is_error(const atf_error_t err)147*11be35a1SLionel Sambuc atf_is_error(const atf_error_t err)
148*11be35a1SLionel Sambuc {
149*11be35a1SLionel Sambuc return err != NULL;
150*11be35a1SLionel Sambuc }
151*11be35a1SLionel Sambuc
152*11be35a1SLionel Sambuc bool
atf_error_is(const atf_error_t err,const char * type)153*11be35a1SLionel Sambuc atf_error_is(const atf_error_t err, const char *type)
154*11be35a1SLionel Sambuc {
155*11be35a1SLionel Sambuc PRE(err != NULL);
156*11be35a1SLionel Sambuc
157*11be35a1SLionel Sambuc return strcmp(err->m_type, type) == 0;
158*11be35a1SLionel Sambuc }
159*11be35a1SLionel Sambuc
160*11be35a1SLionel Sambuc const void *
atf_error_data(const atf_error_t err)161*11be35a1SLionel Sambuc atf_error_data(const atf_error_t err)
162*11be35a1SLionel Sambuc {
163*11be35a1SLionel Sambuc PRE(err != NULL);
164*11be35a1SLionel Sambuc
165*11be35a1SLionel Sambuc return err->m_data;
166*11be35a1SLionel Sambuc }
167*11be35a1SLionel Sambuc
168*11be35a1SLionel Sambuc void
atf_error_format(const atf_error_t err,char * buf,size_t buflen)169*11be35a1SLionel Sambuc atf_error_format(const atf_error_t err, char *buf, size_t buflen)
170*11be35a1SLionel Sambuc {
171*11be35a1SLionel Sambuc PRE(err != NULL);
172*11be35a1SLionel Sambuc err->m_format(err, buf, buflen);
173*11be35a1SLionel Sambuc }
174*11be35a1SLionel Sambuc
175*11be35a1SLionel Sambuc /* ---------------------------------------------------------------------
176*11be35a1SLionel Sambuc * Common error types.
177*11be35a1SLionel Sambuc * --------------------------------------------------------------------- */
178*11be35a1SLionel Sambuc
179*11be35a1SLionel Sambuc /*
180*11be35a1SLionel Sambuc * The "libc" error.
181*11be35a1SLionel Sambuc */
182*11be35a1SLionel Sambuc
183*11be35a1SLionel Sambuc struct atf_libc_error_data {
184*11be35a1SLionel Sambuc int m_errno;
185*11be35a1SLionel Sambuc char m_what[4096];
186*11be35a1SLionel Sambuc };
187*11be35a1SLionel Sambuc typedef struct atf_libc_error_data atf_libc_error_data_t;
188*11be35a1SLionel Sambuc
189*11be35a1SLionel Sambuc static
190*11be35a1SLionel Sambuc void
libc_format(const atf_error_t err,char * buf,size_t buflen)191*11be35a1SLionel Sambuc libc_format(const atf_error_t err, char *buf, size_t buflen)
192*11be35a1SLionel Sambuc {
193*11be35a1SLionel Sambuc const atf_libc_error_data_t *data;
194*11be35a1SLionel Sambuc
195*11be35a1SLionel Sambuc PRE(atf_error_is(err, "libc"));
196*11be35a1SLionel Sambuc
197*11be35a1SLionel Sambuc data = atf_error_data(err);
198*11be35a1SLionel Sambuc snprintf(buf, buflen, "%s: %s", data->m_what, strerror(data->m_errno));
199*11be35a1SLionel Sambuc }
200*11be35a1SLionel Sambuc
201*11be35a1SLionel Sambuc atf_error_t
atf_libc_error(int syserrno,const char * fmt,...)202*11be35a1SLionel Sambuc atf_libc_error(int syserrno, const char *fmt, ...)
203*11be35a1SLionel Sambuc {
204*11be35a1SLionel Sambuc atf_error_t err;
205*11be35a1SLionel Sambuc atf_libc_error_data_t data;
206*11be35a1SLionel Sambuc va_list ap;
207*11be35a1SLionel Sambuc
208*11be35a1SLionel Sambuc data.m_errno = syserrno;
209*11be35a1SLionel Sambuc va_start(ap, fmt);
210*11be35a1SLionel Sambuc vsnprintf(data.m_what, sizeof(data.m_what), fmt, ap);
211*11be35a1SLionel Sambuc va_end(ap);
212*11be35a1SLionel Sambuc
213*11be35a1SLionel Sambuc err = atf_error_new("libc", &data, sizeof(data), libc_format);
214*11be35a1SLionel Sambuc
215*11be35a1SLionel Sambuc return err;
216*11be35a1SLionel Sambuc }
217*11be35a1SLionel Sambuc
218*11be35a1SLionel Sambuc int
atf_libc_error_code(const atf_error_t err)219*11be35a1SLionel Sambuc atf_libc_error_code(const atf_error_t err)
220*11be35a1SLionel Sambuc {
221*11be35a1SLionel Sambuc const struct atf_libc_error_data *data;
222*11be35a1SLionel Sambuc
223*11be35a1SLionel Sambuc PRE(atf_error_is(err, "libc"));
224*11be35a1SLionel Sambuc
225*11be35a1SLionel Sambuc data = atf_error_data(err);
226*11be35a1SLionel Sambuc
227*11be35a1SLionel Sambuc return data->m_errno;
228*11be35a1SLionel Sambuc }
229*11be35a1SLionel Sambuc
230*11be35a1SLionel Sambuc const char *
atf_libc_error_msg(const atf_error_t err)231*11be35a1SLionel Sambuc atf_libc_error_msg(const atf_error_t err)
232*11be35a1SLionel Sambuc {
233*11be35a1SLionel Sambuc const struct atf_libc_error_data *data;
234*11be35a1SLionel Sambuc
235*11be35a1SLionel Sambuc PRE(atf_error_is(err, "libc"));
236*11be35a1SLionel Sambuc
237*11be35a1SLionel Sambuc data = atf_error_data(err);
238*11be35a1SLionel Sambuc
239*11be35a1SLionel Sambuc return data->m_what;
240*11be35a1SLionel Sambuc }
241*11be35a1SLionel Sambuc
242*11be35a1SLionel Sambuc /*
243*11be35a1SLionel Sambuc * The "no_memory" error.
244*11be35a1SLionel Sambuc */
245*11be35a1SLionel Sambuc
246*11be35a1SLionel Sambuc static struct atf_error no_memory_error;
247*11be35a1SLionel Sambuc
248*11be35a1SLionel Sambuc static
249*11be35a1SLionel Sambuc void
no_memory_format(const atf_error_t err,char * buf,size_t buflen)250*11be35a1SLionel Sambuc no_memory_format(const atf_error_t err, char *buf, size_t buflen)
251*11be35a1SLionel Sambuc {
252*11be35a1SLionel Sambuc PRE(atf_error_is(err, "no_memory"));
253*11be35a1SLionel Sambuc
254*11be35a1SLionel Sambuc snprintf(buf, buflen, "Not enough memory");
255*11be35a1SLionel Sambuc }
256*11be35a1SLionel Sambuc
257*11be35a1SLionel Sambuc atf_error_t
atf_no_memory_error(void)258*11be35a1SLionel Sambuc atf_no_memory_error(void)
259*11be35a1SLionel Sambuc {
260*11be35a1SLionel Sambuc PRE(!error_on_flight);
261*11be35a1SLionel Sambuc
262*11be35a1SLionel Sambuc error_init(&no_memory_error, "no_memory", NULL, 0,
263*11be35a1SLionel Sambuc no_memory_format);
264*11be35a1SLionel Sambuc
265*11be35a1SLionel Sambuc error_on_flight = true;
266*11be35a1SLionel Sambuc return &no_memory_error;
267*11be35a1SLionel Sambuc }
268