Merge Monty.
[m6w6/libmemcached] / tests / test.c
1 /* uTest
2 * Copyright (C) 2006-2009 Brian Aker
3 * All rights reserved.
4 *
5 * Use and distribution licensed under the BSD license. See
6 * the COPYING file in the parent directory for full text.
7 */
8
9 /*
10 Sample test application.
11 */
12 #include <assert.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <sys/time.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <sys/wait.h>
19 #include <unistd.h>
20 #include <time.h>
21 #include <fnmatch.h>
22 #include "server.h"
23
24 #include "test.h"
25
26 static void world_stats_print(world_stats_st *stats)
27 {
28 fprintf(stderr, "Total\t\t\t\t%u\n", stats->total);
29 fprintf(stderr, "\tFailed\t\t\t%u\n", stats->failed);
30 fprintf(stderr, "\tSkipped\t\t\t%u\n", stats->skipped);
31 fprintf(stderr, "\tSucceeded\t\t%u\n", stats->success);
32 }
33
34 static long int timedif(struct timeval a, struct timeval b)
35 {
36 register int us, s;
37
38 us = (int)(a.tv_usec - b.tv_usec);
39 us /= 1000;
40 s = (int)(a.tv_sec - b.tv_sec);
41 s *= 1000;
42 return s + us;
43 }
44
45 static const char *test_strerror(test_return_t code)
46 {
47 switch (code) {
48 case TEST_SUCCESS:
49 return "ok";
50 case TEST_FAILURE:
51 return "failed";
52 case TEST_MEMORY_ALLOCATION_FAILURE:
53 return "memory allocation";
54 case TEST_SKIPPED:
55 return "skipped";
56 case TEST_MAXIMUM_RETURN:
57 default:
58 fprintf(stderr, "Unknown return value\n");
59 abort();
60 }
61
62 }
63
64 void create_core(void)
65 {
66 if (getenv("LIBMEMCACHED_NO_COREDUMP") == NULL)
67 {
68 pid_t pid= fork();
69
70 if (pid == 0)
71 {
72 abort();
73 }
74 else
75 {
76 while (waitpid(pid, NULL, 0) != pid)
77 {
78 ;
79 }
80 }
81 }
82 }
83
84
85 static test_return_t _runner_default(test_callback_fn func, void *p)
86 {
87 if (func)
88 {
89 return func(p);
90 }
91 else
92 {
93 return TEST_SUCCESS;
94 }
95 }
96
97 static world_runner_st defualt_runners= {
98 _runner_default,
99 _runner_default,
100 _runner_default
101 };
102
103
104 int main(int argc, char *argv[])
105 {
106 test_return_t return_code;
107 unsigned int x;
108 char *collection_to_run= NULL;
109 char *wildcard= NULL;
110 world_st world;
111 collection_st *collection;
112 collection_st *next;
113 void *world_ptr;
114
115 world_stats_st stats;
116
117 memset(&stats, 0, sizeof(stats));
118 memset(&world, 0, sizeof(world));
119 get_world(&world);
120
121 if (! world.runner)
122 {
123 world.runner= &defualt_runners;
124 }
125
126 collection= world.collections;
127
128 if (world.create)
129 world_ptr= world.create();
130 else
131 world_ptr= NULL;
132
133 if (argc > 1)
134 collection_to_run= argv[1];
135
136 if (argc == 3)
137 wildcard= argv[2];
138
139 for (next= collection; next->name; next++)
140 {
141 test_st *run;
142
143 run= next->tests;
144 if (collection_to_run && fnmatch(collection_to_run, next->name, 0))
145 continue;
146
147 fprintf(stderr, "\n%s\n\n", next->name);
148
149 for (x= 0; run->name; run++)
150 {
151 struct timeval start_time, end_time;
152 long int load_time= 0;
153
154 if (wildcard && fnmatch(wildcard, run->name, 0))
155 continue;
156
157 fprintf(stderr, "Testing %s", run->name);
158
159 if (world.collection_startup)
160 {
161 world.collection_startup(world_ptr);
162 }
163
164 if (run->requires_flush && world.flush)
165 {
166 world.flush(world_ptr);
167 }
168
169 if (world.pre_run)
170 {
171 world.pre_run(world_ptr);
172 }
173
174
175 if (next->pre)
176 {
177 return_code= world.runner->pre(next->pre, world_ptr);
178
179 if (return_code != TEST_SUCCESS)
180 {
181 goto error;
182 }
183 }
184
185 gettimeofday(&start_time, NULL);
186 return_code= world.runner->run(run->test_fn, world_ptr);
187 gettimeofday(&end_time, NULL);
188 load_time= timedif(end_time, start_time);
189
190 if (next->post)
191 {
192 (void) world.runner->pre(next->pre, world_ptr);
193 }
194
195 if (world.post_run)
196 {
197 world.post_run(world_ptr);
198 }
199
200 error:
201 stats.total++;
202
203 fprintf(stderr, "\t\t\t\t\t");
204
205 switch (return_code)
206 {
207 case TEST_SUCCESS:
208 fprintf(stderr, "%ld.%03ld ", load_time / 1000, load_time % 1000);
209 stats.success++;
210 break;
211 case TEST_FAILURE:
212 stats.failed++;
213 break;
214 case TEST_SKIPPED:
215 stats.skipped++;
216 break;
217 case TEST_MEMORY_ALLOCATION_FAILURE:
218 case TEST_MAXIMUM_RETURN:
219 default:
220 break;
221 }
222
223 fprintf(stderr, "[ %s ]\n", test_strerror(return_code));
224
225 if (world.on_error)
226 {
227 test_return_t rc;
228 rc= world.on_error(return_code, world_ptr);
229
230 if (rc != TEST_SUCCESS)
231 break;
232 }
233 }
234 }
235
236 fprintf(stderr, "All tests completed successfully\n\n");
237
238 if (world.destroy)
239 world.destroy(world_ptr);
240
241 world_stats_print(&stats);
242
243 return stats.failed == 0 ? 0 : 1;
244 }