#!/usr/bin/perl -w # exotic 0.4 # Copyright (c) 2007-2012, Jan Vidar Krey use strict; my $program = $0; my $file; my $line; my @tests; my $found; my $test; my @files; if ($#ARGV == -1) { die "Usage: $program files\n"; } my $version = "0.4"; foreach my $arg (@ARGV) { push(@files, $arg); } print "/* THIS FILE IS AUTOMATICALLY GENERATED BY EXOTIC - DO NOT EDIT THIS FILE! */\n"; print "/* exotic/$version (Mon Nov 7 11:15:31 CET 2011) */\n\n"; print "#define __EXOTIC__STANDALONE__\n"; standalone_include_exotic_h(); if ($#ARGV >= 0) { foreach $file (@ARGV) { $found = 0; open( FILE, "$file") || next; my @data = ; my $comment = 0; foreach $line (@data) { chomp($line); if ($comment == 1) { if ($line =~ /^(.*\*\/)(.*)/) { $line = $2; $comment = 0; } else { next; # ignore comment data } } if ($line =~ /^(.*)\/\*(.*)\*\/(.*)$/) { $line = $1 . " " . $3; # exclude comment stuff in between "/*" and "*/". } if ($line =~ /^(.*)(\/\/.*)$/) { $line = $1; # exclude stuff after "//" (FIXME: does not work if they are inside a string) } if ($line =~ /\/\*/) { $comment = 1; next; } if ($line =~ /^\s*EXO_TEST\(\s*(\w+)\s*,/) { $found++; push(@tests, $1); } } if ($found > 0) { print "#include \"" . $file . "\"\n"; } close(FILE); } print "\n"; } # Write a main() that will start the test run print "int main(int argc, char** argv)\n{\n"; print "\tstruct exotic_handle handle;\n\n"; print "\tif (exotic_initialize(&handle, argc, argv) == -1)\n\t\treturn -1;\n\n"; if ($#tests > 0) { print "\t/* Register the tests to be run */\n"; foreach $test (@tests) { print "\texotic_add_test(&handle, &exotic_test_" . $test . ", \"" . $test . "\");\n"; } } else { print "\t/* No tests are found! */\n"; } print "\n"; print "\treturn exotic_run(&handle);\n"; print "}\n\n"; standalone_include_exotic_c(); sub standalone_include_exotic_h { print ' /* * Exotic (EXtatic.Org Test InfrastuCture) * Copyright (c) 2007, Jan Vidar Krey */ #ifndef EXO_TEST #define EXO_TEST(NAME, block) int exotic_test_ ## NAME (void) block #endif #ifndef HAVE_EXOTIC_AUTOTEST_H #define HAVE_EXOTIC_AUTOTEST_H #ifdef __cplusplus extern "C" { #endif typedef int(*exo_test_t)(); enum exo_toggle { cfg_default, cfg_off, cfg_on }; struct exotic_handle { enum exo_toggle config_show_summary; enum exo_toggle config_show_pass; enum exo_toggle config_show_fail; unsigned int fail; unsigned int pass; struct exo_test_data* first; struct exo_test_data* current; }; extern int exotic_initialize(struct exotic_handle* handle, int argc, char** argv); extern void exotic_add_test(struct exotic_handle* handle, exo_test_t, const char* name); extern int exotic_run(struct exotic_handle* handle); #ifdef __cplusplus } #endif #endif /* HAVE_EXOTIC_AUTOTEST_H */ '; } sub standalone_include_exotic_c { print ' /* * Exotic - C/C++ source code testing * Copyright (c) 2007, Jan Vidar Krey */ #include #include #include #include static void exotic_version(); #ifndef __EXOTIC__STANDALONE__ #include "autotest.h" static void exotic_version() { printf("Extatic.org Test Infrastructure: exotic " "${version}" "\n\n"); printf("Copyright (C) 2007 Jan Vidar Krey, janvidar@extatic.org\n"); printf("This is free software with ABSOLUTELY NO WARRANTY.\n\n"); } #endif struct exo_test_data { exo_test_t test; char* name; struct exo_test_data* next; }; static void exotic_summary(struct exotic_handle* handle) { int total = handle->pass + handle->fail; int pass_rate = total ? (100*handle->pass / total) : 0; int fail_rate = total ? (100*handle->fail / total) : 0; printf("\n"); printf("--------------------------------------------\n"); printf("Results:\n"); printf(" * Total tests run: %8d\n", total); printf(" * Tests passed: %8d (~%d%%)\n", (int) handle->pass, pass_rate); printf(" * Tests failed: %8d (~%d%%)\n", (int) handle->fail, fail_rate); printf("--------------------------------------------\n"); } static void exotic_help(const char* program) { printf("Usage: %s [OPTIONS]\n\n", program); printf("Options:\n"); printf(" --help -h Show this message\n"); printf(" --version -v Show version\n"); printf(" --summary -s show only summary)\n"); printf(" --fail -f show only test failures\n"); printf(" --pass -p show only test passes\n"); printf("\nExamples:\n"); printf(" %s -s -f\n\n", program); } int exotic_initialize(struct exotic_handle* handle, int argc, char** argv) { int n; if (!handle || !argv) return -1; memset(handle, 0, sizeof(struct exotic_handle)); for (n = 1; n < argc; n++) { if (!strcmp(argv[n], "-h") || !strcmp(argv[n], "--help")) { exotic_help(argv[0]); exit(0); } if (!strcmp(argv[n], "-v") || !strcmp(argv[n], "--version")) { exotic_version(); exit(0); } if (!strcmp(argv[n], "-s") || !strcmp(argv[n], "--summary")) { handle->config_show_summary = cfg_on; continue; } if (!strcmp(argv[n], "-f") || !strcmp(argv[n], "--fail")) { handle->config_show_fail = cfg_on; continue; } if (!strcmp(argv[n], "-p") || !strcmp(argv[n], "--pass")) { handle->config_show_pass = cfg_on; continue; } fprintf(stderr, "Unknown argument: %s\n\n", argv[n]); exotic_help(argv[0]); exit(0); } if (handle->config_show_summary == cfg_on) { if (handle->config_show_pass == cfg_default) handle->config_show_pass = cfg_off; if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; } else if (handle->config_show_pass == cfg_on) { if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_off; if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; } else if (handle->config_show_fail == cfg_on) { if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_off; if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_off; } else { if (handle->config_show_summary == cfg_default) handle->config_show_summary = cfg_on; if (handle->config_show_fail == cfg_default) handle->config_show_fail = cfg_on; if (handle->config_show_pass == cfg_default) handle->config_show_pass = cfg_on; } return 0; } void exotic_add_test(struct exotic_handle* handle, exo_test_t func, const char* name) { if (!handle) { fprintf(stderr, "exotic_add_test: failed, no handle!\n"); exit(-1); } struct exo_test_data* test = (struct exo_test_data*) malloc(sizeof(struct exo_test_data)); if (!test) { fprintf(stderr, "exotic_add_test: out of memory!\n"); exit(-1); } /* Create the test */ memset(test, 0, sizeof(struct exo_test_data)); test->test = func; test->name = strdup(name); /* Register the test in the handle */ if (!handle->first) { handle->first = test; handle->current = test; } else { handle->current->next = test; handle->current = test; } } int exotic_run(struct exotic_handle* handle) { struct exo_test_data* tmp = NULL; if (!handle) { fprintf(stderr, "Error: exotic is not initialized\n"); return -1; } handle->current = handle->first; while (handle->current) { tmp = handle->current; if (handle->current->test()) { if (handle->config_show_pass == cfg_on) printf("* PASS test \'%s\'\n", tmp->name); handle->pass++; } else { if (handle->config_show_fail == cfg_on) printf("* FAIL test \'%s\'\n", tmp->name); handle->fail++; } handle->current = handle->current->next; free(tmp->name); free(tmp); } if (!handle->first) { printf("(No tests added)\n"); } if (handle->config_show_summary == cfg_on) exotic_summary(handle); return (handle->fail) ? handle->fail : 0; } static void exotic_version() { printf("exotic 0.4-standalone\n\n"); printf("Copyright (C) 2007 Jan Vidar Krey, janvidar@extatic.org\n"); printf("This is free software with ABSOLUTELY NO WARRANTY.\n\n"); } '; }