MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
tap.c
1 /* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
15 
16  Library for providing TAP support for testing C and C++ was written
17  by Mats Kindahl <mats@mysql.com>.
18 */
19 
20 #include "tap.h"
21 
22 #include "my_global.h"
23 #include "my_stacktrace.h"
24 
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <signal.h>
30 
31 /*
32  Visual Studio 2003 does not know vsnprintf but knows _vsnprintf.
33  We don't put this #define elsewhere because we prefer my_vsnprintf
34  everywhere instead, except when linking with libmysys is not
35  desirable - the case here.
36 */
37 #if defined(_MSC_VER) && ( _MSC_VER == 1310 )
38 #define vsnprintf _vsnprintf
39 #endif
40 
54 static TEST_DATA g_test = { NO_PLAN, 0, 0, "" };
55 
63 #define tapout stdout
64 
79 static void
80 vemit_tap(int pass, char const *fmt, va_list ap)
81 {
82  fprintf(tapout, "%sok %d%s",
83  pass ? "" : "not ",
84  ++g_test.last,
85  (fmt && *fmt) ? " - " : "");
86  if (fmt && *fmt)
87  vfprintf(tapout, fmt, ap);
88  fflush(tapout);
89 }
90 
91 
107 static void
108 emit_dir(const char *dir, const char *why)
109 {
110  fprintf(tapout, " # %s %s", dir, why);
111  fflush(tapout);
112 }
113 
114 
120 static void
121 emit_endl()
122 {
123  fprintf(tapout, "\n");
124  fflush(tapout);
125 }
126 
127 static void
128 handle_core_signal(int signo)
129 {
130  /* BAIL_OUT("Signal %d thrown", signo); */
131 #ifdef HAVE_STACKTRACE
132  fprintf(stderr, "Signal %d thrown, attempting backtrace.\n", signo);
133  my_print_stacktrace(NULL, 0);
134 #endif
135  signal(signo, SIG_DFL);
136  raise(signo);
137  _exit(EXIT_FAILURE);
138 }
139 
140 void
141 BAIL_OUT(char const *fmt, ...)
142 {
143  va_list ap;
144  va_start(ap, fmt);
145  fprintf(tapout, "Bail out! ");
146  vfprintf(tapout, fmt, ap);
147  emit_endl();
148  va_end(ap);
149  exit(255);
150 }
151 
152 
153 void
154 diag(char const *fmt, ...)
155 {
156  va_list ap;
157  va_start(ap, fmt);
158  fprintf(tapout, "# ");
159  vfprintf(tapout, fmt, ap);
160  emit_endl();
161  va_end(ap);
162 }
163 
164 typedef struct signal_entry {
165  int signo;
166  void (*handler)(int);
167 } signal_entry;
168 
169 static signal_entry install_signal[]= {
170  { SIGQUIT, handle_core_signal },
171  { SIGILL, handle_core_signal },
172  { SIGABRT, handle_core_signal },
173  { SIGFPE, handle_core_signal },
174  { SIGSEGV, handle_core_signal }
175 #ifdef SIGBUS
176  , { SIGBUS, handle_core_signal }
177 #endif
178 #ifdef SIGXCPU
179  , { SIGXCPU, handle_core_signal }
180 #endif
181 #ifdef SIGXCPU
182  , { SIGXFSZ, handle_core_signal }
183 #endif
184 #ifdef SIGXCPU
185  , { SIGSYS, handle_core_signal }
186 #endif
187 #ifdef SIGXCPU
188  , { SIGTRAP, handle_core_signal }
189 #endif
190 };
191 
192 int skip_big_tests= 1;
193 
194 void
195 plan(int const count)
196 {
197  char *config= getenv("MYTAP_CONFIG");
198  size_t i;
199 
200  if (config)
201  skip_big_tests= strcmp(config, "big");
202 
203  /*
204  Install signal handler
205  */
206 
207  for (i= 0; i < sizeof(install_signal)/sizeof(*install_signal); ++i)
208  signal(install_signal[i].signo, install_signal[i].handler);
209 
210  g_test.plan= count;
211  switch (count)
212  {
213  case NO_PLAN:
214  break;
215  default:
216  if (count > 0)
217  {
218  fprintf(tapout, "1..%d\n", count);
219  fflush(tapout);
220  }
221  break;
222  }
223 }
224 
225 
226 void
227 skip_all(char const *reason, ...)
228 {
229  va_list ap;
230  va_start(ap, reason);
231  fprintf(tapout, "1..0 # skip ");
232  vfprintf(tapout, reason, ap);
233  fflush(tapout);
234  va_end(ap);
235  exit(0);
236 }
237 
238 void
239 ok(int const pass, char const *fmt, ...)
240 {
241  va_list ap;
242  va_start(ap, fmt);
243 
244  if (!pass && *g_test.todo == '\0')
245  ++g_test.failed;
246 
247  vemit_tap(pass, fmt, ap);
248  va_end(ap);
249  if (*g_test.todo != '\0')
250  emit_dir("todo", g_test.todo);
251  emit_endl();
252 }
253 
254 void
255 ok1(int const pass)
256 {
257  va_list ap;
258 
259  memset(&ap, 0, sizeof(ap));
260 
261  if (!pass && *g_test.todo == '\0')
262  ++g_test.failed;
263 
264  vemit_tap(pass, NULL, ap);
265 
266  if (*g_test.todo != '\0')
267  emit_dir("todo", g_test.todo);
268 
269  emit_endl();
270 }
271 
272 void
273 skip(int how_many, char const *fmt, ...)
274 {
275  char reason[80];
276  if (fmt && *fmt)
277  {
278  va_list ap;
279  va_start(ap, fmt);
280  vsnprintf(reason, sizeof(reason), fmt, ap);
281  va_end(ap);
282  }
283  else
284  reason[0] = '\0';
285 
286  while (how_many-- > 0)
287  {
288  va_list ap;
289  memset((char*) &ap, 0, sizeof(ap)); /* Keep compiler happy */
290  vemit_tap(1, NULL, ap);
291  emit_dir("skip", reason);
292  emit_endl();
293  }
294 }
295 
296 void
297 todo_start(char const *message, ...)
298 {
299  va_list ap;
300  va_start(ap, message);
301  vsnprintf(g_test.todo, sizeof(g_test.todo), message, ap);
302  va_end(ap);
303 }
304 
305 void
307 {
308  *g_test.todo = '\0';
309 }
310 
311 int exit_status() {
312  /*
313  If there were no plan, we write one last instead.
314  */
315  if (g_test.plan == NO_PLAN)
316  plan(g_test.last);
317 
318  if (g_test.plan != g_test.last)
319  {
320  diag("%d tests planned but%s %d executed",
321  g_test.plan, (g_test.plan > g_test.last ? " only" : ""), g_test.last);
322  return EXIT_FAILURE;
323  }
324 
325  if (g_test.failed > 0)
326  {
327  diag("Failed %d tests!", g_test.failed);
328  return EXIT_FAILURE;
329  }
330 
331  return EXIT_SUCCESS;
332 }
333