Cycle tests should not be run on CI
[m6w6/libmemcached] / libtest / main.cc
1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2 *
3 * Data Differential YATL (i.e. libtest) library
4 *
5 * Copyright (C) 2012 Data Differential, http://datadifferential.com/
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * * Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following disclaimer
16 * in the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * * The names of its contributors may not be used to endorse or
20 * promote products derived from this software without specific prior
21 * written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 */
36
37 #include <config.h>
38 #include <libtest/common.h>
39
40 #include <cassert>
41 #include <cstdlib>
42 #include <cstring>
43 #include <ctime>
44 #include <fnmatch.h>
45 #include <iostream>
46 #include <fstream>
47 #include <memory>
48 #include <sys/stat.h>
49 #include <sys/time.h>
50 #include <sys/types.h>
51 #include <sys/wait.h>
52 #include <unistd.h>
53
54 #include <signal.h>
55
56 #ifndef __INTEL_COMPILER
57 #pragma GCC diagnostic ignored "-Wold-style-cast"
58 #endif
59
60 using namespace libtest;
61
62 static void stats_print(libtest::Framework *frame)
63 {
64 if (frame->failed() == 0 and frame->success() == 0)
65 {
66 return;
67 }
68
69 Outn();
70 Out << "Collections\t\t\t\t\t" << frame->total();
71 Out << "\tFailed\t\t\t\t\t" << frame->failed();
72 Out << "\tSkipped\t\t\t\t\t" << frame->skipped();
73 Out << "\tSucceeded\t\t\t\t" << frame->success();
74 Outn();
75 Out << "Tests\t\t\t\t\t" << frame->sum_total();
76 Out << "\tFailed\t\t\t\t" << frame->sum_failed();
77 Out << "\tSkipped\t\t\t\t" << frame->sum_skipped();
78 Out << "\tSucceeded\t\t\t" << frame->sum_success();
79 }
80
81 #include <getopt.h>
82 #include <unistd.h>
83
84 int main(int argc, char *argv[])
85 {
86 Out << "BEGIN:" << argv[0];
87 bool opt_massive= false;
88 unsigned long int opt_repeat= 1; // Run all tests once
89 bool opt_quiet= false;
90 std::string collection_to_run;
91 std::string wildcard;
92 std::string binary_name;
93
94 const char *just_filename= rindex(argv[0], '/');
95 if (just_filename)
96 {
97 just_filename++;
98 }
99 else
100 {
101 just_filename= argv[0];
102 }
103
104 if (just_filename[0] == 'l' and just_filename[1] == 't' and just_filename[2] == '-')
105 {
106 just_filename+= 3;
107 }
108 binary_name.append(just_filename);
109
110 /*
111 Valgrind does not currently work reliably, or sometimes at all, on OSX
112 - Fri Jun 15 11:24:07 EDT 2012
113 */
114 #if defined(TARGET_OS_OSX) && TARGET_OS_OSX
115 if (valgrind_is_caller())
116 {
117 return EXIT_SKIP;
118 }
119 #endif
120
121 // Options parsing
122 {
123 enum long_option_t {
124 OPT_LIBYATL_VERSION,
125 OPT_LIBYATL_MATCH_COLLECTION,
126 OPT_LIBYATL_MASSIVE,
127 OPT_LIBYATL_QUIET,
128 OPT_LIBYATL_MATCH_WILDCARD,
129 OPT_LIBYATL_REPEAT
130 };
131
132 static struct option long_options[]=
133 {
134 { "version", no_argument, NULL, OPT_LIBYATL_VERSION },
135 { "quiet", no_argument, NULL, OPT_LIBYATL_QUIET },
136 { "repeat", no_argument, NULL, OPT_LIBYATL_REPEAT },
137 { "collection", required_argument, NULL, OPT_LIBYATL_MATCH_COLLECTION },
138 { "wildcard", required_argument, NULL, OPT_LIBYATL_MATCH_WILDCARD },
139 { "massive", no_argument, NULL, OPT_LIBYATL_MASSIVE },
140 { 0, 0, 0, 0 }
141 };
142
143 int option_index= 0;
144 while (1)
145 {
146 int option_rv= getopt_long(argc, argv, "", long_options, &option_index);
147 if (option_rv == -1)
148 {
149 break;
150 }
151
152 switch (option_rv)
153 {
154 case OPT_LIBYATL_VERSION:
155 break;
156
157 case OPT_LIBYATL_QUIET:
158 opt_quiet= true;
159 break;
160
161 case OPT_LIBYATL_REPEAT:
162 opt_repeat= strtoul(optarg, (char **) NULL, 10);
163 break;
164
165 case OPT_LIBYATL_MATCH_COLLECTION:
166 collection_to_run= optarg;
167 break;
168
169 case OPT_LIBYATL_MATCH_WILDCARD:
170 wildcard= optarg;
171 break;
172
173 case OPT_LIBYATL_MASSIVE:
174 opt_massive= true;
175 break;
176
177 case '?':
178 /* getopt_long already printed an error message. */
179 Error << "unknown option to getopt_long()";
180 exit(EXIT_FAILURE);
181
182 default:
183 break;
184 }
185 }
186 }
187
188 srandom((unsigned int)time(NULL));
189
190 if (bool(getenv("YATL_REPEAT")) and (strtoul(getenv("YATL_REPEAT"), (char **) NULL, 10) > 1))
191 {
192 opt_repeat= strtoul(getenv("YATL_REPEAT"), (char **) NULL, 10);
193 }
194
195 if ((bool(getenv("YATL_QUIET")) and (strcmp(getenv("YATL_QUIET"), "0") == 0)) or opt_quiet)
196 {
197 opt_quiet= true;
198 }
199 else if (getenv("JENKINS_URL"))
200 {
201 if (bool(getenv("YATL_QUIET")) and (strcmp(getenv("YATL_QUIET"), "1") == 0))
202 { }
203 else
204 {
205 opt_quiet= true;
206 }
207 }
208
209 if ((bool(getenv("YATL_RUN_MASSIVE_TESTS"))) or opt_massive)
210 {
211 opt_massive= true;
212 }
213
214 if (opt_quiet)
215 {
216 close(STDOUT_FILENO);
217 }
218
219 if (opt_massive)
220 {
221 is_massive(opt_massive);
222 }
223
224 char tmp_directory[1024];
225 if (getenv("LIBTEST_TMP"))
226 {
227 snprintf(tmp_directory, sizeof(tmp_directory), "%s", getenv("LIBTEST_TMP"));
228 }
229 else
230 {
231 snprintf(tmp_directory, sizeof(tmp_directory), "%s", LIBTEST_TEMP);
232 }
233
234 if (chdir(tmp_directory) == -1)
235 {
236 char getcwd_buffer[1024];
237 char *dir= getcwd(getcwd_buffer, sizeof(getcwd_buffer));
238
239 Error << "Unable to chdir() from " << dir << " to " << tmp_directory << " errno:" << strerror(errno);
240 return EXIT_FAILURE;
241 }
242
243 if (libtest::libtool() == NULL)
244 {
245 Error << "Failed to locate libtool";
246 return EXIT_FAILURE;
247 }
248
249 if (getenv("YATL_COLLECTION_TO_RUN"))
250 {
251 if (strlen(getenv("YATL_COLLECTION_TO_RUN")))
252 {
253 collection_to_run= getenv("YATL_COLLECTION_TO_RUN");
254 }
255 }
256
257 if (collection_to_run.compare("none") == 0)
258 {
259 return EXIT_SUCCESS;
260 }
261
262 if (collection_to_run.empty() == false)
263 {
264 Out << "Only testing " << collection_to_run;
265 }
266
267 int exit_code;
268
269 try
270 {
271 do
272 {
273 exit_code= EXIT_SUCCESS;
274 fatal_assert(sigignore(SIGPIPE) == 0);
275
276 libtest::SignalThread signal;
277 if (signal.setup() == false)
278 {
279 Error << "Failed to setup signals";
280 return EXIT_FAILURE;
281 }
282
283 std::auto_ptr<libtest::Framework> frame(new libtest::Framework(signal, binary_name, collection_to_run, wildcard));
284
285 // Run create(), bail on error.
286 {
287 switch (frame->create())
288 {
289 case TEST_SUCCESS:
290 break;
291
292 case TEST_SKIPPED:
293 return EXIT_SKIP;
294
295 case TEST_FAILURE:
296 std::cerr << __FILE__ << ":" << __LINE__ << ": " << "frame->create()" << std::endl;
297 return EXIT_FAILURE;
298 }
299 }
300
301 frame->exec();
302
303 if (signal.is_shutdown() == false)
304 {
305 signal.set_shutdown(SHUTDOWN_GRACEFUL);
306 }
307
308 shutdown_t status= signal.get_shutdown();
309 if (status == SHUTDOWN_FORCED)
310 {
311 Out << "Tests were aborted.";
312 exit_code= EXIT_FAILURE;
313 }
314 else if (frame->failed())
315 {
316 Out << "Some test failed.";
317 exit_code= EXIT_FAILURE;
318 }
319 else if (frame->skipped() and frame->failed() and frame->success())
320 {
321 Out << "Some tests were skipped.";
322 }
323 else if (frame->success() and (frame->failed() == 0))
324 {
325 Out;
326 Out << "All tests completed successfully.";
327 }
328
329 stats_print(frame.get());
330
331 std::ofstream xml_file;
332 std::string file_name;
333 file_name.append(tmp_directory);
334 file_name.append(frame->name());
335 file_name.append(".xml");
336 xml_file.open(file_name.c_str(), std::ios::trunc);
337 libtest::Formatter::xml(*frame, xml_file);
338
339 Outn(); // Generate a blank to break up the messages if make check/test has been run
340 } while (exit_code == EXIT_SUCCESS and --opt_repeat);
341 }
342 catch (libtest::fatal& e)
343 {
344 std::cerr << __FILE__ << ":" << __LINE__ << ": " << "FATAL:" << e.what() << std::endl;
345 exit_code= EXIT_FAILURE;
346 }
347 catch (libtest::disconnected& e)
348 {
349 std::cerr << __FILE__ << ":" << __LINE__ << ": " << "Unhandled disconnection occurred:" << e.what() << std::endl;
350 exit_code= EXIT_FAILURE;
351 }
352 catch (std::exception& e)
353 {
354 std::cerr << __FILE__ << ":" << __LINE__ << ": " << "std::exception:" << e.what() << std::endl;
355 exit_code= EXIT_FAILURE;
356 }
357 catch (char const*)
358 {
359 std::cerr << __FILE__ << ":" << __LINE__ << ": " << "Exception:" << std::endl;
360 exit_code= EXIT_FAILURE;
361 }
362 catch (...)
363 {
364 std::cerr << __FILE__ << ":" << __LINE__ << ": " << "Unknown exception halted execution." << std::endl;
365 exit_code= EXIT_FAILURE;
366 }
367
368 Out << "END:" << argv[0];
369
370 return exit_code;
371 }