diff options
Diffstat (limited to 'unittest')
-rw-r--r-- | unittest/Makefile.am | 13 | ||||
-rw-r--r-- | unittest/README.txt | 7 | ||||
-rw-r--r-- | unittest/examples/Makefile.am | 2 | ||||
-rw-r--r-- | unittest/examples/core-t.c | 19 | ||||
-rw-r--r-- | unittest/mysys/base64-t.c | 2 | ||||
-rw-r--r-- | unittest/mysys/my_atomic-t.c | 20 | ||||
-rw-r--r-- | unittest/mytap/tap.c | 49 | ||||
-rw-r--r-- | unittest/mytap/tap.h | 48 |
8 files changed, 143 insertions, 17 deletions
diff --git a/unittest/Makefile.am b/unittest/Makefile.am index ca3291efde0..7f1dd525d3b 100644 --- a/unittest/Makefile.am +++ b/unittest/Makefile.am @@ -1,15 +1,12 @@ SUBDIRS = mytap . mysys examples -noinst_SCRIPTS = unit EXTRA_DIST = unit.pl CLEANFILES = unit -unittests = mytap mysys +unittests = mytap mysys @mysql_se_unittest_dirs@ @mysql_pg_unittest_dirs@ -test: unit - ./unit run $(unittests) - -unit: $(srcdir)/unit.pl - cp $(srcdir)/unit.pl $@ - chmod 700 $@ +test: + perl unit.pl run $(unittests) +test-verbose: + HARNESS_VERBOSE=1 perl unit.pl run $(unittests) diff --git a/unittest/README.txt b/unittest/README.txt index 72f76c30b67..ea94a50595b 100644 --- a/unittest/README.txt +++ b/unittest/README.txt @@ -9,7 +9,9 @@ mytap Source for the MyTAP library mysys Tests for mysys components bitmap-t.c Unit test for MY_BITMAP base64-t.c Unit test for base64 encoding functions -examples Example unit tests +examples Example unit tests. + core-t.c Example of raising a signal in the middle of the test + THIS TEST WILL STOP ALL FURTHER TESTING! simple-t.c Example of a standard TAP unit test skip-t.c Example where some test points are skipped skip_all-t.c Example of a test where the entire test is skipped @@ -24,6 +26,9 @@ To make and execute all unit tests in the directory: make test +Observe that the tests in the examples/ directory are just various +examples of tests and are not expected to pass. + Adding unit tests ----------------- diff --git a/unittest/examples/Makefile.am b/unittest/examples/Makefile.am index f3c70b654a1..8aefb351220 100644 --- a/unittest/examples/Makefile.am +++ b/unittest/examples/Makefile.am @@ -5,5 +5,5 @@ AM_LDFLAGS = -L$(top_builddir)/unittest/mytap LDADD = -lmytap -noinst_PROGRAMS = simple-t skip-t todo-t skip_all-t no_plan-t +noinst_PROGRAMS = simple-t skip-t todo-t skip_all-t no_plan-t core-t diff --git a/unittest/examples/core-t.c b/unittest/examples/core-t.c new file mode 100644 index 00000000000..3572d72868b --- /dev/null +++ b/unittest/examples/core-t.c @@ -0,0 +1,19 @@ + +#include "my_config.h" + +#include <stdlib.h> +#include <tap.h> + +/* + This is a simple test to demonstrate what happens if a signal that + generates a core is raised. + + Note that this test will stop all further testing! + */ + +int main() { + plan(3); + ok(1, "First test"); + abort(); + return exit_status(); +} diff --git a/unittest/mysys/base64-t.c b/unittest/mysys/base64-t.c index 6d85964b20d..ccec0c77086 100644 --- a/unittest/mysys/base64-t.c +++ b/unittest/mysys/base64-t.c @@ -54,7 +54,7 @@ main(void) /* Decode */ dst= (char *) malloc(base64_needed_decoded_length(strlen(str))); - dst_len= base64_decode(str, strlen(str), dst); + dst_len= base64_decode(str, strlen(str), dst, NULL); ok(dst_len == src_len, "Comparing lengths"); cmp= memcmp(src, dst, src_len); diff --git a/unittest/mysys/my_atomic-t.c b/unittest/mysys/my_atomic-t.c index 4e2e496c3b1..fe93b0942ce 100644 --- a/unittest/mysys/my_atomic-t.c +++ b/unittest/mysys/my_atomic-t.c @@ -32,7 +32,7 @@ pthread_handler_t test_atomic_add_handler(void *arg) { int m=*(int *)arg; int32 x; - for (x=((int)(&m)); m ; m--) + for (x=((int)((long)(&m))); m ; m--) { x=x*m+0x87654321; my_atomic_rwlock_wrlock(&rwl); @@ -104,7 +104,7 @@ pthread_handler_t test_atomic_cas_handler(void *arg) { int m=*(int *)arg, ok; int32 x,y; - for (x=((int)(&m)); m ; m--) + for (x=((int)((long)(&m))); m ; m--) { my_atomic_rwlock_wrlock(&rwl); y=my_atomic_load32(&a32); @@ -140,13 +140,21 @@ void test_atomic(const char *test, pthread_handler handler, int n, int m) diag("Testing %s with %d threads, %d iterations... ", test, n, m); for (N=n ; n ; n--) - pthread_create(&t, &thr_attr, handler, &m); + { + if (pthread_create(&t, &thr_attr, handler, &m) != 0) + { + diag("Could not create thread"); + a32= 1; + goto err; + } + } pthread_mutex_lock(&mutex); while (N) pthread_cond_wait(&cond, &mutex); pthread_mutex_unlock(&mutex); now=my_getsystime()-now; +err: ok(a32 == 0, "tested %s in %g secs", test, ((double)now)/1e7); } @@ -170,6 +178,12 @@ int main() test_atomic("my_atomic_swap32", test_atomic_swap_handler, 100,10000); test_atomic("my_atomic_cas32", test_atomic_cas_handler, 100,10000); + /* + workaround until we know why it crashes randomly on some machine + (BUG#22320). + */ + sleep(2); + pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); pthread_attr_destroy(&thr_attr); diff --git a/unittest/mytap/tap.c b/unittest/mytap/tap.c index 0bfa4b61094..fceac951aff 100644 --- a/unittest/mytap/tap.c +++ b/unittest/mytap/tap.c @@ -20,10 +20,13 @@ #include "tap.h" +#include "my_config.h" + #include <stdlib.h> #include <stdarg.h> #include <stdio.h> #include <string.h> +#include <signal.h> /** @defgroup MyTAP_Internal MyTAP Internals @@ -78,7 +81,7 @@ vemit_tap(int pass, char const *fmt, va_list ap) /** Emit a TAP directive. - TAP directives are comments after a have the form + TAP directives are comments after that have the form: @code ok 1 # skip reason for skipping @@ -108,6 +111,24 @@ emit_endl() fprintf(tapout, "\n"); } +static void +handle_core_signal(int signo) +{ + BAIL_OUT("Signal %d thrown", signo); +} + +void +BAIL_OUT(char const *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(tapout, "Bail out! "); + vfprintf(tapout, fmt, ap); + emit_endl(); + va_end(ap); + exit(255); +} + void diag(char const *fmt, ...) @@ -116,14 +137,38 @@ diag(char const *fmt, ...) va_start(ap, fmt); fprintf(tapout, "# "); vfprintf(tapout, fmt, ap); - fprintf(tapout, "\n"); + emit_endl(); va_end(ap); } +typedef struct signal_entry { + int signo; + void (*handler)(int); +} signal_entry; + +static signal_entry install_signal[]= { + { SIGQUIT, handle_core_signal }, + { SIGILL, handle_core_signal }, + { SIGABRT, handle_core_signal }, + { SIGFPE, handle_core_signal }, + { SIGSEGV, handle_core_signal }, + { SIGBUS, handle_core_signal }, + { SIGXCPU, handle_core_signal }, + { SIGXFSZ, handle_core_signal }, + { SIGSYS, handle_core_signal }, + { SIGTRAP, handle_core_signal } +}; void plan(int const count) { + /* + Install signal handler + */ + size_t i; + for (i= 0; i < sizeof(install_signal)/sizeof(*install_signal); ++i) + signal(install_signal[i].signo, install_signal[i].handler); + g_test.plan= count; switch (count) { diff --git a/unittest/mytap/tap.h b/unittest/mytap/tap.h index ca2aa54a7ba..a47060fa3cc 100644 --- a/unittest/mytap/tap.h +++ b/unittest/mytap/tap.h @@ -23,6 +23,11 @@ #include "my_global.h" +/* + @defgroup MyTAP MySQL support for performing unit tests according to + the Test Anything Protocol (TAP). +*/ + #define NO_PLAN (0) /** @@ -33,6 +38,7 @@ @internal We are using the "typedef struct X { ... } X" idiom to create class/struct X both in C and C++. */ + typedef struct TEST_DATA { /** Number of tests that is planned to execute. @@ -72,8 +78,13 @@ extern "C" { it was called with <code>NO_PLAN</code>, i.e., the test plan will be printed after all the test lines. + The plan() function will install signal handlers for all signals + that generate a core, so if you want to override these signals, do + it <em>after</em> you have called the plan() function. + @param count The planned number of tests to run. */ + void plan(int count); @@ -92,9 +103,11 @@ void plan(int count); @param fmt Format string in printf() format. NULL is allowed, in which case nothing is printed. */ + void ok(int pass, char const *fmt, ...) __attribute__((format(printf,2,3))); + /** Skip a determined number of tests. @@ -122,6 +135,7 @@ void ok(int pass, char const *fmt, ...) @param how_many Number of tests that are to be skipped. @param reason A reason for skipping the tests */ + void skip(int how_many, char const *reason, ...) __attribute__((format(printf,2,3))); @@ -142,17 +156,43 @@ void skip(int how_many, char const *reason, ...) @see skip */ + #define SKIP_BLOCK_IF(SKIP_IF_TRUE, COUNT, REASON) \ if (SKIP_IF_TRUE) skip((COUNT),(REASON)); else + /** Print a diagnostics message. @param fmt Diagnostics message in printf() format. */ + void diag(char const *fmt, ...) __attribute__((format(printf,1,2))); + +/** + Print a bail out message. + + A bail out message can be issued when no further testing can be + done, e.g., when there are missing dependencies. + + The test will exit with status 255. This function does not return. + + @code + BAIL_OUT("Lost connection to server %s", server_name); + @endcode + + @note A bail out message is printed if a signal that generates a + core is raised. + + @param fmt Bail out message in printf() format. +*/ + +void BAIL_OUT(char const *fmt, ...) + __attribute__((noreturn, format(printf,1,2))); + + /** Print summary report and return exit status. @@ -168,6 +208,7 @@ void diag(char const *fmt, ...) @returns @c EXIT_SUCCESS if all tests passed, @c EXIT_FAILURE if one or more tests failed. */ + int exit_status(void); @@ -178,9 +219,11 @@ int exit_status(void); automatically call exit(), so there is no need to have checks around it. */ + void skip_all(char const *reason, ...) __attribute__((noreturn, format(printf, 1, 2))); + /** Start section of tests that are not yet ready. @@ -201,12 +244,15 @@ void skip_all(char const *reason, ...) @param message Message that will be printed before the todo tests. */ + void todo_start(char const *message, ...) - __attribute__((format (printf, 1, 2))); + __attribute__((format(printf, 1, 2))); + /** End a section of tests that are not yet ready. */ + void todo_end(); /** @} */ |