1 /******************************************************************** 2 * unittest-support.h: Support structures for GLib Unit Testing * 3 * Copyright 2011-12 John Ralls <jralls@ceridwen.us> * 4 * Copyright 2011 Muslim Chochlov <muslim.chochlov@gmail.com> * 5 * * 6 * This program is free software; you can redistribute it and/or * 7 * modify it under the terms of the GNU General Public License as * 8 * published by the Free Software Foundation; either version 2 of * 9 * the License, or (at your option) any later version. * 10 * * 11 * This program is distributed in the hope that it will be useful, * 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 14 * GNU General Public License for more details. * 15 * * 16 * You should have received a copy of the GNU General Public License* 17 * along with this program; if not, contact: * 18 * * 19 * Free Software Foundation Voice: +1-617-542-5942 * 20 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * 21 * Boston, MA 02110-1301, USA gnu@gnu.org * 22 ********************************************************************/ 23 #ifndef UNITTEST_SUPPORT_H 24 #define UNITTEST_SUPPORT_H 25 26 #include <glib.h> 27 #include <qof.h> 28 /** @file unittest-support.h 29 * @brief Macros and logging-capture functions to ease writing GLib-testing 30 * based unit tests. 31 */ 32 33 /** @name Unit Test Macros 34 * These macros facilitate combining a suite name and a test name to make a path 35 * when registering a test function with the corresponding g_test_add and 36 * g_test_add_func. Create a const char* suitename somewhere in the file and 37 * pass it as the first parameter, and the test name as the second. The 38 * remaining parameters are the same as in the underlying function. 39 */ 40 41 /** 42 * Wraps gnc_test_add() for test functions needing a fixture. 43 */ 44 45 #define GNC_TEST_ADD( suite, path, fixture, data, setup, test, teardown )\ 46 {\ 47 gchar *testpath = g_strdup_printf( "%s/%s", suite, path );\ 48 g_test_add( testpath, fixture, data, setup, test, teardown );\ 49 g_free( testpath );\ 50 } 51 52 /** 53 * Wraps gnc_test_add_func() for test functions which don't require a fixture. 54 */ 55 56 #define GNC_TEST_ADD_FUNC( suite, path, test )\ 57 {\ 58 gchar *testpath = g_strdup_printf( "%s/%s", suite, path );\ 59 g_test_add_func( testpath, test );\ 60 g_free( testpath );\ 61 } 62 /** @} */ 63 /** @name Suppressing Expected Errors 64 * 65 * Functions for suppressing expected errors during tests. Pass 66 * 67 * Note that you need to call both g_log_set_handler *and* 68 * g_test_log_set_fatal_handler to both avoid the assertion and 69 * suppress the error message. The callbacks work in either role, just 70 * cast them appropriately for the use. 71 * 72 * To simplify the process a bit and make sure that everything gets 73 * cleaned up at the end of each test, add a GSList for handlers to 74 * your Fixture and set it to NULL in setup(), then call 75 * g_slist_free_full() on it with test_free_log_handler as the 76 * function. Create new TestErrorStruct instances with 77 * test_error_struct_new, and pass that along with your handler of 78 * choice to test_log_set_handler or test_log_set_fatal_handler. This 79 * is much simpler, as teardown will clean everything up for you and 80 * you need call only those functions. As an added bonus, the hit 81 * count won't be doubled as it is if you do everything by hand. 82 * 83 * NB: If you have more than one fatal error in a test function be 84 * sure to use the test_list_handler: You can have only one fatal 85 * handler. 86 * @{ 87 */ 88 89 /** 90 * Struct to pass as user_data for the handlers. Setting a parameter 91 * to NULL or 0 will match any value in the error, so if you have the 92 * same message and log level being issued in two domains you can 93 * match both of them by setting log_domain = NULL. 94 * 95 */ 96 97 typedef struct 98 { 99 GLogLevelFlags log_level; 100 char *log_domain; 101 char *msg; 102 guint hits; 103 } TestErrorStruct; 104 105 /** 106 * Convenience function to create an error struct. If you use this 107 * with test_set_log_handler it will get cleaned up at tesrdown, 108 * otherwise call test_error_free() at the end of your test function. 109 * 110 * NB: If you need to change the message, be sure to free the old one 111 * and to allocate the new one on the stack. 112 * 113 * @param log_domain: The string representing the domain of the log message 114 * @param log_level: The GLogLevelFlags for the message 115 * @param msg: The exact error message that the logger will emit 116 * @return: A TestErrorStruct * 117 */ 118 TestErrorStruct* test_error_struct_new (const char *log_domain, 119 const GLogLevelFlags log_level, 120 const char *msg); 121 122 /** 123 * Free a TestErrorStruct created with test_error_struct_new 124 * @param error: The TestErrorStruct to be freed 125 */ 126 void test_error_struct_free (TestErrorStruct *); 127 128 /** 129 * Holds a handler instance with its TestErrorStruct, handler id, and whether 130 * it's a list handler. A test fixture can be set up to hold a GSList of these 131 * so that they can be automatically unregistered and freed during teardown. 132 */ 133 typedef struct 134 { 135 TestErrorStruct *error; 136 gint handler; 137 gboolean list_handler; 138 } TestLogHandler; 139 140 141 /** 142 * Set a log handler and add it to a GList for removal at teardown 143 * 144 * Don't pass a NULL TestErrorStruct! It's needed to set the 145 * parameters for g_log_set_handler. Use a TestErrorStruct created 146 * with test_error_struct_new() or you'll have errors with freeing it 147 * in teardown. 148 * 149 * @param handler_list: A GSList of LogHandlers 150 * @param error: A TestErrorStruct with the necessary data 151 * @param handler: The Handler to set the data with 152 * @return: The new GSList pointer. 153 */ 154 GSList *test_log_set_handler (GSList *list, TestErrorStruct *error, 155 GLogFunc handler); 156 157 /** 158 * Set a log handler and add it to a GList for removal at teardown; 159 * also set the fatal handler so that the test program doesn't abort 160 * for fatal log messages. If a test function has more than one fatal 161 * message, be sure to use the test_list_handler! 162 * 163 * Don't pass a NULL TestErrorStruct! It's needed to set the 164 * parameters for g_log_set_handler. Use a TestErrorStruct created 165 * with test_error_struct_new() or you'll have errors with freeing it 166 * in teardown. 167 * 168 * @param handler_list: A GSList of LogHandlers 169 * @param error: A TestErrorStruct with the necessary data 170 * @param handler: The Handler to set the data with 171 * @return: The new GSList pointer. 172 */ 173 GSList *test_log_set_fatal_handler (GSList *list, TestErrorStruct *error, 174 GLogFunc handler); 175 176 /** 177 * Clears all the log handlers. Pass this to g_slist_free() in teardown. 178 */ 179 void test_free_log_handler (gpointer item); 180 181 /** 182 * Check that the user_data error message is a substring of the 183 * actual error otherwise assert. Displays the error (and asserts 184 * if G_LOG_FLAG_FATAL is TRUE) if NULL is passed as user_data, 185 * but a NULL or 0 value member matches anything. 186 */ 187 gboolean test_checked_substring_handler (const char *log_domain, GLogLevelFlags log_level, 188 const gchar *msg, gpointer user_data); 189 /** 190 * Check the user_data against the actual error and assert on any 191 * differences. Displays the error (and asserts if G_LOG_FLAG_FATAL 192 * is TRUE) if NULL is passed as user_data, but a NULL or 0 value 193 * member matches anything. 194 */ 195 gboolean test_checked_handler (const char *log_domain, GLogLevelFlags log_level, 196 const gchar *msg, gpointer user_data); 197 198 /** 199 * Just print the log message. Since GLib has a habit of eating its 200 * log messages, it's sometimes useful to call 201 * g_test_log_set_fatal_handler() with this to make sure that 202 * g_return_if_fail() error messages make it to the surface. 203 */ 204 gboolean test_log_handler (const char *log_domain, GLogLevelFlags log_level, 205 const gchar *msg, gpointer user_data); 206 /** 207 * Just returns FALSE or suppresses the message regardless of what the 208 * error is. Use this only as a last resort. 209 */ 210 gboolean test_null_handler (const char *log_domain, GLogLevelFlags log_level, 211 const gchar *msg, gpointer user_data ); 212 /** 213 * Maintains an internal list of TestErrorStructs which are each 214 * checked by the list handler. If an error matches any entry on the 215 * list, test_list_handler will return FALSE, blocking the error from 216 * halting the program. 217 * 218 * Call test_add_error for each TestErrorStruct to check against and 219 * test_clear_error_list when you no longer expect the errors. 220 */ 221 void test_add_error (TestErrorStruct *error); 222 void test_clear_error_list (void); 223 224 /** 225 * Checks received errors against the list created by 226 * test_add_error. Rather than checking for an exact match, this function 227 * checks using a substring match. If the list is empty or nothing 228 * matches, passes control on to test_checked_substring_handler, giving 229 * the opportunity for an additional check that's not in the list 230 * (set user_data to NULL if you want test_checked_handler to 231 * immediately print the error). 232 */ 233 gboolean test_list_substring_handler (const char *log_domain, GLogLevelFlags log_level, 234 const gchar *msg, gpointer user_data); 235 236 /** 237 * Checks received errors against the list created by 238 * test_add_error. If the list is empty or nothing matches, passes 239 * control on to test_checked_handler, giving the opportunity for an 240 * additional check that's not in the list (set user_data to NULL if 241 * you want test_checked_handler to immediately print the error). 242 */ 243 gboolean test_list_handler (const char *log_domain, 244 GLogLevelFlags log_level, 245 const gchar *msg, gpointer user_data ); 246 /** 247 * Call this from a mock object to indicate that the mock has in fact 248 * been called 249 */ 250 void test_set_called( const gboolean val ); 251 252 /** 253 * Destructively tests (meaning that it resets called to FALSE) and 254 * returns the value of called. 255 */ 256 gboolean test_reset_called( void ); 257 258 /** 259 * Set the test data pointer with the what you expect your mock to be 260 * called with. 261 */ 262 void test_set_data( gpointer data ); 263 264 /** 265 * Destructively retrieves the test data pointer. Call from your mock 266 * to ensure that it received the expected data. 267 */ 268 gpointer test_reset_data( void ); 269 270 /** 271 * A handy function to use to free memory from lists of simple 272 * pointers. Call g_list_free_full(list, (GDestroyNotify)*test_free). 273 */ 274 void test_free( gpointer data ); 275 276 /** @} 277 */ 278 /** @name Test Signals 279 * Test the emission of signals from objects. Signals are used to coordinate the 280 * behavior of the GUI with events in other parts of the program. @{ 281 */ 282 /** 283 * TestSignal is an opaque struct used to mock handling signals 284 * emitted by functions-under-test. It registers a handler and counts 285 * how many times it is called with the right instance and type. The 286 * struct is allocated using g_slice_new, and it registers a 287 * qof_event_handler; test_signal_free cleans up at the end of the 288 * test function (or sooner, if you want to reuse a TestSignal). If 289 * event_data isn't NULL, the mock signal handler will test that it 290 * matches the event_data passed with the signal and assert if it 291 * isn't the same object (pointer comparison). If the actual event 292 * data is a local variable, it won't be accessible, so the event_data 293 * passed to test_signal_new should be NULL to avoid the test. 294 */ 295 typedef gpointer TestSignal; 296 297 /** 298 * Create a test signal. 299 * @param entity: The QofInstance emitting the signal 300 * @param eventType: The type of the signal 301 * @param event_data: Any data required by the signal or NULL if none is. 302 * @return A newly created TestSignal. Use test_signal_free to release it. 303 */ 304 305 TestSignal test_signal_new (QofInstance *entity, QofEventId eventType, 306 gpointer event_data); 307 /** 308 * gets the number of times the TestSignal has been called. 309 */ 310 guint test_signal_return_hits (TestSignal sig); 311 312 /** 313 * Convenience macro which wraps test_signal_return_hits with and equality 314 * assertion. 315 */ 316 317 #define test_signal_assert_hits(sig, hits) \ 318 g_assert_cmpint (test_signal_return_hits (sig), ==, hits) 319 320 /** 321 * Free a test signal. 322 */ 323 void test_signal_free (TestSignal sig); 324 325 /** @} 326 */ 327 328 /** @name Testing for object disposal 329 * Sometimes we need to make sure that certain objects that we've created aren't leaking. These functions can help. 330 * @{ 331 */ 332 333 /** 334 * Unrefs obj and returns true if its finalize method was called. 335 */ 336 337 gboolean test_object_checked_destroy (GObject *obj); 338 339 /** 340 * Ensures that a GObject is still alive at the time 341 * it's called and that it is finalized. The first assertion will 342 * trigger if you pass it a ponter which isn't a GObject -- which 343 * could be the case if the object has already been finalized. Then it 344 * calls test_object_checked_destroy() on it, asserting if the 345 * finalize method wasn't called (which indicates a leak). 346 */ 347 348 #define test_destroy(obj) \ 349 g_assert (obj != NULL && G_IS_OBJECT (obj)); \ 350 g_assert (test_object_checked_destroy (G_OBJECT (obj))) 351 352 /** @} */ 353 /* For Scheme testing access: 354 void gnc_log_init_filename_special (gchar *filename); 355 void gnc_log_shutdown (void); 356 void gnc_log_set_handler (guint logdomain, gchar *logdomain, GLogFunc * func, gpointer data); 357 */ 358 359 #endif /*UNITTEST_SUPPORT_H*/ 360