iPXE
test.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2011 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 /** @file
27  *
28  * Self-test infrastructure
29  *
30  */
31 
32 /* Forcibly enable assertions */
33 #undef NDEBUG
34 
35 #include <stddef.h>
36 #include <stdio.h>
37 #include <errno.h>
38 #include <assert.h>
39 #include <ipxe/test.h>
40 #include <ipxe/init.h>
41 #include <ipxe/image.h>
42 #include <usr/profstat.h>
43 
44 /** Current self-test set */
45 static struct self_test *current_tests;
46 
47 /**
48  * Report test result
49  *
50  * @v success Test succeeded
51  * @v file Test code file
52  * @v line Test code line
53  * @v test Test code
54  */
55 void test_ok ( int success, const char *file, unsigned int line,
56  const char *test ) {
57 
58  /* Sanity check */
59  assert ( current_tests != NULL );
60 
61  /* Increment test counter */
63 
64  /* Report failure if applicable */
65  if ( ! success ) {
67  printf ( "FAILURE: \"%s\" test failed at %s line %d: ( %s )\n",
68  current_tests->name, file, line, test );
69  }
70 }
71 
72 /**
73  * Run self-test set
74  *
75  */
76 static void run_tests ( struct self_test *tests ) {
77  unsigned int old_assertion_failures = assertion_failures;
78 
79  /* Sanity check */
80  assert ( current_tests == NULL );
81 
82  /* Record current test set */
83  current_tests = tests;
84 
85  /* Run tests */
86  tests->exec();
87 
88  /* Clear current test set */
90 
91  /* Record number of assertion failures */
92  tests->assertion_failures =
93  ( assertion_failures - old_assertion_failures );
94 
95  /* Print test set summary */
96  if ( tests->failures || tests->assertion_failures ) {
97  printf ( "FAILURE: \"%s\" %d of %d tests failed",
98  tests->name, tests->failures, tests->total );
99  if ( tests->assertion_failures ) {
100  printf ( " with %d assertion failures",
101  tests->assertion_failures );
102  }
103  printf ( "\n" );
104  } else {
105  printf ( "OK: \"%s\" %d tests passed\n",
106  tests->name, tests->total );
107  }
108 }
109 
110 /**
111  * Run all self-tests
112  *
113  * @ret rc Return status code
114  */
115 static int run_all_tests ( void ) {
116  struct self_test *tests;
117  unsigned int failures = 0;
118  unsigned int assertions = 0;
119  unsigned int total = 0;
120 
121  /* Run all compiled-in self-tests */
122  printf ( "Starting %s self-tests\n", _S2 ( ARCH ) );
124  run_tests ( tests );
125 
126  /* Print overall summary */
127  for_each_table_entry ( tests, SELF_TESTS ) {
128  total += tests->total;
129  failures += tests->failures;
130  assertions += tests->assertion_failures;
131  }
132  if ( failures || assertions ) {
133  printf ( "FAILURE: %d of %d tests failed",
134  failures, total );
135  if ( assertions ) {
136  printf ( " with %d assertion failures", assertions );
137  }
138  printf ( "\n" );
139  return -EINPROGRESS;
140  } else {
141  printf ( "OK: all %d tests passed\n", total );
142  profstat();
143  return 0;
144  }
145 }
146 
147 static int test_image_probe ( struct image *image __unused ) {
148  return -ENOTTY;
149 }
150 
151 static int test_image_exec ( struct image *image __unused ) {
152  return run_all_tests();
153 }
154 
155 static struct image_type test_image_type = {
156  .name = "self-tests",
157  .probe = test_image_probe,
158  .exec = test_image_exec,
159 };
160 
161 static struct image test_image = {
162  .refcnt = REF_INIT ( ref_no_free ),
163  .name = "<TESTS>",
164  .type = &test_image_type,
165 };
166 
167 static void test_init ( void ) {
168  int rc;
169 
170  /* Register self-tests image */
171  if ( ( rc = register_image ( &test_image ) ) != 0 ) {
172  DBG ( "Could not register self-test image: %s\n",
173  strerror ( rc ) );
174  /* No way to report failure */
175  return;
176  }
177 }
178 
179 /** Self-test initialisation function */
180 struct init_fn test_init_fn __init_fn ( INIT_EARLY ) = {
182 };
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition: vsprintf.c:464
unsigned int failures
Number of test failures.
Definition: test.h:23
void(* initialise)(void)
Definition: init.h:15
unsigned int total
Number of tests run.
Definition: test.h:21
#define _S2(x)
Stringify expanded argument.
Definition: compiler.h:53
Error codes.
static int run_all_tests(void)
Run all self-tests.
Definition: test.c:115
#define INIT_EARLY
Early initialisation.
Definition: init.h:28
An executable image type.
Definition: image.h:76
void(* exec)(void)
Run self-tests.
Definition: test.h:19
Self-test infrastructure.
const char * name
Test set name.
Definition: test.h:17
An executable image.
Definition: image.h:24
A self-test set.
Definition: test.h:15
unsigned int assertion_failures
Number of assertion failures triggered.
Definition: assert.c:35
char * name
Name of this image type.
Definition: image.h:78
struct init_fn test_init_fn __init_fn(INIT_EARLY)
Self-test initialisation function.
void profstat(void)
Print profiling statistics.
Definition: profstat.c:40
An initialisation function.
Definition: init.h:14
Assertions.
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
Executable images.
static void test_init(void)
Definition: test.c:167
static struct image_type test_image_type
Definition: test.c:155
#define EINPROGRESS
Operation in progress.
Definition: errno.h:418
int register_image(struct image *image)
Register executable image.
Definition: image.c:264
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
#define SELF_TESTS
Self-test table.
Definition: test.h:29
static int test_image_exec(struct image *image __unused)
Definition: test.c:151
unsigned int assertion_failures
Number of assertion failures.
Definition: test.h:25
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:385
void test_ok(int success, const char *file, unsigned int line, const char *test)
Report test result.
Definition: test.c:55
Profiling.
static void run_tests(struct self_test *tests)
Run self-test set.
Definition: test.c:76
static int test_image_probe(struct image *image __unused)
Definition: test.c:147
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
#define ENOTTY
Inappropriate I/O control operation.
Definition: errno.h:594
#define REF_INIT(free_fn)
Initialise a static reference counter.
Definition: refcnt.h:77
static struct self_test * current_tests
Current self-test set.
Definition: test.c:45
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
static struct image test_image
Definition: test.c:161
void ref_no_free(struct refcnt *refcnt __unused)
Do not free reference-counted object.
Definition: refcnt.c:101
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
static int test
Definition: epic100.c:73
struct refcnt refcnt
Reference count.
Definition: image.h:26