/* Unit tests for DiaCanvas2 * Copyright (c) 2001 Arjan Molenaar and Phlip * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /* unit-test.h * ----------- * This is a very small testing framework for DiaCanvas2. * * You should create a function that sets up the testing environment and * a function that does the cleanup, like this: * void do_setup (void) * void do_teardown (void) * * To start the testing part use the TEST_BEGIN() macro. It takes three * arguments (don't forget TEST_END() at the end): * name: a string that represents the name of the test case. * setup: the function used to set up the environment (e.g. do_setup) * teardown: the functio used to do the cleanup (e.g. do_teardown) * * Now you can create a new test with the TEST_NEW() macro: * TEST_NEW(name_of_function_to_test) * * You can thread the TEST_NEW() macro as the beginning of a function. The test * is written just like a C function, enclosed in curly braces ('{' and '}'). * * To test a value you can use the following macros: * TEST(expr) * Test 'expr'. 'expr' should be a boolean expression. * TESTEQ(v1, v2) * Test if 'v1' is equal to 'v2'. * TESTFL(v1, v2) * Test if 'v1' is equal to 'v2', within some margin * (TESTFL_EPSILON). * * Other useful macros: * TEST_INITIALIZATION * You can set this macro to a series of operations that has to * be done before the tests are executed. If not set it defaults * to 'g_type_init()'. * TEST_WEAK_REF(obj, notifier) * You should initialize 'notifier' to FALSE. If 'obj' is * destroyed 'notifier' id set to TRUE. * TEST_EMPTY_QUEUE() * Process all pending events in the GLib main context. */ #ifndef __UNIT_TEST_H__ #define __UNIT_TEST_H__ #include #include #include #define TESTFL_EPSILON 10e-4 #define TESTING_MESSAGE(expr) g_print (" Testing '" expr "' on line %d... ", __LINE__); #ifndef TEST_INITIALIZATION # define TEST_INITIALIZATION g_type_init(); #endif /* Outputting the failure in "FILE:LINE:MESSAGE" format lets my * interactive editor navigate to the offending line automatically, like * a gcc error message. */ #define FAIL_TEST() \ g_print ("\n" __FILE__ ":%i: Test Failed!\n", __LINE__); \ exit (1); #define TOLERATE(x,y) (fabs((x)-(y)) < TESTFL_EPSILON) #define TEST(expr) \ TESTING_MESSAGE(#expr); \ if (!(expr)) { FAIL_TEST(); } \ g_print ("Okay!\n"); #define TESTEQ(expr1, expr2) \ G_STMT_START { \ int val1 = (expr1), val2 = (expr2); \ TESTING_MESSAGE(#expr1 " == " #expr2); \ if (val1 != val2) { \ g_print ("%d != %d\n", val1, val2); \ FAIL_TEST(); } \ g_print ("Okay!\n"); \ } G_STMT_END #define TESTFL(expr1, expr2) \ G_STMT_START { \ double val1 = (expr1), val2 = (expr2); \ TESTING_MESSAGE(#expr1 " == " #expr2); \ if (!TOLERATE(val1, val2)) { \ g_print ("%g != %g\n", val1, val2); \ FAIL_TEST(); } \ g_print ("Okay!\n"); \ } G_STMT_END #define TEST_BEGIN(name, setup, teardown) \ int main (int argc, char *argv[]) { \ const char *_module_name = #name; \ GVoidFunc _unit_test_setup = setup; \ GVoidFunc _unit_test_teardown = teardown; \ TEST_INITIALIZATION; \ g_print ("======== Unit tests for DiaCanvas2 " __DATE__ " ========\n");\ _unit_test_setup (); \ G_STMT_START { gboolean t = 0; test_weak_notify (&t); g_assert (t); \ t = 0; test_property_notify (NULL, NULL, &t); g_assert (t); } #define TEST_END() \ G_STMT_END; \ _unit_test_teardown (); \ return 0; \ } #define TEST_NEW(name) \ G_STMT_END; \ _unit_test_teardown (); \ g_print ("-------- Starting test: %s." #name " --------\n", \ _module_name ); \ _unit_test_setup (); \ G_STMT_START #define TEST_PROPERTY_NOTIFY(obj, property, notifier) \ g_signal_connect (G_OBJECT (obj), \ "notify::" property, \ (GCallback) test_property_notify, \ &(notifier)) #define TEST_WEAK_REF(obj, notifier) \ g_object_weak_ref (G_OBJECT (obj), \ (GWeakNotify) test_weak_notify, \ &(notifier)) static void test_weak_notify (gboolean *notify) { *notify = TRUE; } static void test_property_notify (void *object, void *pspec, gboolean *notify) { *notify = TRUE; } /* Run events in the GTK+ event queue. */ #define TEST_EMPTY_QUEUE() \ while (g_main_context_pending (NULL)) \ g_main_context_iteration (NULL, FALSE); #endif /* __UNIT_TEST_H__ */