1#!/usr/bin/perl -w 2# exotic 0.4 3# Copyright (c) 2007-2012, Jan Vidar Krey 4 5use strict; 6 7my $program = $0; 8my $file; 9my $line; 10my @tests; 11my $found; 12my $test; 13my @files; 14 15if ($#ARGV == -1) 16{ 17 die "Usage: $program files\n"; 18} 19 20my $version = "0.4"; 21 22foreach my $arg (@ARGV) 23{ 24 push(@files, $arg); 25} 26 27 28print "/* THIS FILE IS AUTOMATICALLY GENERATED BY EXOTIC - DO NOT EDIT THIS FILE! */\n"; 29print "/* exotic/$version (Mon Nov 7 11:15:31 CET 2011) */\n\n"; 30 31print "#define __EXOTIC__STANDALONE__\n"; 32standalone_include_exotic_h(); 33 34if ($#ARGV >= 0) 35{ 36 foreach $file (@ARGV) 37 { 38 $found = 0; 39 open( FILE, "$file") || next; 40 my @data = <FILE>; 41 my $comment = 0; 42 43 foreach $line (@data) { 44 chomp($line); 45 46 if ($comment == 1) 47 { 48 if ($line =~ /^(.*\*\/)(.*)/) 49 { 50 $line = $2; 51 $comment = 0; 52 } 53 else 54 { 55 next; # ignore comment data 56 } 57 } 58 59 if ($line =~ /^(.*)\/\*(.*)\*\/(.*)$/) 60 { 61 $line = $1 . " " . $3; # exclude comment stuff in between "/*" and "*/". 62 } 63 64 if ($line =~ /^(.*)(\/\/.*)$/) { 65 $line = $1; # exclude stuff after "//" (FIXME: does not work if they are inside a string) 66 } 67 68 if ($line =~ /\/\*/) { 69 $comment = 1; 70 next; 71 } 72 73 if ($line =~ /^\s*EXO_TEST\(\s*(\w+)\s*,/) 74 { 75 $found++; 76 push(@tests, $1); 77 } 78 } 79 80 if ($found > 0) { 81 print "#include \"" . $file . "\"\n"; 82 } 83 84 close(FILE); 85 } 86 print "\n"; 87} 88 89# Write a main() that will start the test run 90print "int main(int argc, char** argv)\n{\n"; 91print "\tstruct exotic_handle handle;\n\n"; 92print "\tif (exotic_initialize(&handle, argc, argv) == -1)\n\t\treturn -1;\n\n"; 93 94if ($#tests > 0) 95{ 96 print "\t/* Register the tests to be run */\n"; 97 foreach $test (@tests) 98 { 99 print "\texotic_add_test(&handle, &exotic_test_" . $test . ", \"" . $test . "\");\n"; 100 } 101} 102else 103{ 104 print "\t/* No tests are found! */\n"; 105} 106 107print "\n"; 108print "\treturn exotic_run(&handle);\n"; 109print "}\n\n"; 110 111 112standalone_include_exotic_c(); 113 114sub standalone_include_exotic_h { 115print ' 116/* 117 * Exotic (EXtatic.Org Test InfrastuCture) 118 * Copyright (c) 2007, Jan Vidar Krey 119 */ 120 121#ifndef EXO_TEST 122#define EXO_TEST(NAME, block) int exotic_test_ ## NAME (void) block 123#endif 124 125#ifndef HAVE_EXOTIC_AUTOTEST_H 126#define HAVE_EXOTIC_AUTOTEST_H 127 128#ifdef __cplusplus 129extern "C" { 130#endif 131 132typedef int(*exo_test_t)(); 133 134enum exo_toggle { cfg_default, cfg_off, cfg_on }; 135 136struct exotic_handle 137{ 138 enum exo_toggle config_show_summary; 139 enum exo_toggle config_show_pass; 140 enum exo_toggle config_show_fail; 141 unsigned int fail; 142 unsigned int pass; 143 struct exo_test_data* first; 144 struct exo_test_data* current; 145}; 146 147extern int exotic_initialize(struct exotic_handle* handle, int argc, char** argv); 148extern void exotic_add_test(struct exotic_handle* handle, exo_test_t, const char* name); 149extern int exotic_run(struct exotic_handle* handle); 150 151#ifdef __cplusplus 152} 153#endif 154 155#endif /* HAVE_EXOTIC_AUTOTEST_H */ 156 157'; } 158sub standalone_include_exotic_c { 159print ' 160/* 161 * Exotic - C/C++ source code testing 162 * Copyright (c) 2007, Jan Vidar Krey 163 */ 164 165#include <sys/types.h> 166#include <stdio.h> 167#include <stdlib.h> 168#include <string.h> 169 170static void exotic_version(); 171 172#ifndef __EXOTIC__STANDALONE__ 173#include "autotest.h" 174static void exotic_version() 175{ 176 printf("Extatic.org Test Infrastructure: exotic " "${version}" "\n\n"); 177 printf("Copyright (C) 2007 Jan Vidar Krey, janvidar@extatic.org\n"); 178 printf("This is free software with ABSOLUTELY NO WARRANTY.\n\n"); 179} 180#endif 181 182struct exo_test_data 183{ 184 exo_test_t test; 185 char* name; 186 struct exo_test_data* next; 187}; 188 189 190static void exotic_summary(struct exotic_handle* handle) 191{ 192 int total = handle->pass + handle->fail; 193 int pass_rate = total ? (100*handle->pass / total) : 0; 194 int fail_rate = total ? (100*handle->fail / total) : 0; 195 196 printf("\n"); 197 printf("--------------------------------------------\n"); 198 printf("Results:\n"); 199 printf(" * Total tests run: %8d\n", total); 200 printf(" * Tests passed: %8d (~%d%%)\n", (int) handle->pass, pass_rate); 201 printf(" * Tests failed: %8d (~%d%%)\n", (int) handle->fail, fail_rate); 202 printf("--------------------------------------------\n"); 203} 204 205 206static void exotic_help(const char* program) 207{ 208 printf("Usage: %s [OPTIONS]\n\n", program); 209 printf("Options:\n"); 210 printf(" --help -h Show this message\n"); 211 printf(" --version -v Show version\n"); 212 printf(" --summary -s show only summary)\n"); 213 printf(" --fail -f show only test failures\n"); 214 printf(" --pass -p show only test passes\n"); 215 printf("\nExamples:\n"); 216 printf(" %s -s -f\n\n", program); 217} 218 219 220int exotic_initialize(struct exotic_handle* handle, int argc, char** argv) 221{ 222 int n; 223 if (!handle || !argv) return -1; 224 225 memset(handle, 0, sizeof(struct exotic_handle)); 226 227 for (n = 1; n < argc; n++) 228 { 229 if (!strcmp(argv[n], "-h") || !strcmp(argv[n], "--help")) 230 { 231 exotic_help(argv[0]); 232 exit(0); 233 } 234 235 if (!strcmp(argv[n], "-v") || !strcmp(argv[n], "--version")) 236 { 237 exotic_version(); 238 exit(0); 239 } 240 241 if (!strcmp(argv[n], "-s") || !strcmp(argv[n], "--summary")) 242 { 243 handle->config_show_summary = cfg_on; 244 continue; 245 } 246 247 if (!strcmp(argv[n], "-f") || !strcmp(argv[n], "--fail")) 248 { 249 handle->config_show_fail = cfg_on; 250 continue; 251 } 252 253 if (!strcmp(argv[n], "-p") || !strcmp(argv[n], "--pass")) 254 { 255 handle->config_show_pass = cfg_on; 256 continue; 257 } 258 259 fprintf(stderr, "Unknown argument: %s\n\n", argv[n]); 260 exotic_help(argv[0]); 261 exit(0); 262 } 263 264 if (handle->config_show_summary == cfg_on) 265 { 266 if (handle->config_show_pass == cfg_default) handle->config_show_pass = cfg_off; 267 if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; 268 269 } 270 else if (handle->config_show_pass == cfg_on) 271 { 272 if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_off; 273 if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; 274 } 275 else if (handle->config_show_fail == cfg_on) 276 { 277 if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_off; 278 if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; 279 } 280 else 281 { 282 if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_on; 283 if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_on; 284 if (handle->config_show_pass == cfg_default) handle->config_show_pass = cfg_on; 285 } 286 return 0; 287} 288 289 290void exotic_add_test(struct exotic_handle* handle, exo_test_t func, const char* name) 291{ 292 struct exo_test_data* test; 293 if (!handle) 294 { 295 fprintf(stderr, "exotic_add_test: failed, no handle!\n"); 296 exit(-1); 297 } 298 299 test = (struct exo_test_data*) malloc(sizeof(struct exo_test_data)); 300 if (!test) 301 { 302 fprintf(stderr, "exotic_add_test: out of memory!\n"); 303 exit(-1); 304 } 305 306 /* Create the test */ 307 memset(test, 0, sizeof(struct exo_test_data)); 308 test->test = func; 309 test->name = strdup(name); 310 311 /* Register the test in the handle */ 312 if (!handle->first) 313 { 314 handle->first = test; 315 handle->current = test; 316 } 317 else 318 { 319 handle->current->next = test; 320 handle->current = test; 321 } 322} 323 324 325int exotic_run(struct exotic_handle* handle) 326{ 327 struct exo_test_data* tmp = NULL; 328 329 if (!handle) 330 { 331 fprintf(stderr, "Error: exotic is not initialized\n"); 332 return -1; 333 } 334 335 handle->current = handle->first; 336 while (handle->current) 337 { 338 tmp = handle->current; 339 340 if (handle->current->test()) { 341 if (handle->config_show_pass == cfg_on) printf("* PASS test \'%s\'\n", tmp->name); 342 handle->pass++; 343 } else { 344 if (handle->config_show_fail == cfg_on) printf("* FAIL test \'%s\'\n", tmp->name); 345 handle->fail++; 346 } 347 348 handle->current = handle->current->next; 349 350 free(tmp->name); 351 free(tmp); 352 } 353 354 if (!handle->first) 355 { 356 printf("(No tests added)\n"); 357 } 358 359 if (handle->config_show_summary == cfg_on) 360 exotic_summary(handle); 361 362 return (handle->fail) ? handle->fail : 0; 363} 364 365 366static void exotic_version() { 367 printf("exotic 0.4-standalone\n\n"); 368 printf("Copyright (C) 2007 Jan Vidar Krey, janvidar@extatic.org\n"); 369 printf("This is free software with ABSOLUTELY NO WARRANTY.\n\n"); 370} 371'; } 372 373