mirror of
https://github.com/Gnucash/gnucash.git
synced 2024-12-01 13:09:41 -06:00
[Testing] Provide list error handler, rename some functions
Add an GTestFatalFunc which can examine a list of error conditions and suppress those messages and prevent their exiting while passing through any unexpected errors. Rename test_silent_logger to test_null_handler and change it to a GTestFatalFunc (it can still be used as a GLogFunc). Rename test_handle_faults to test_checked_handler and improve its flow and message display. It no longer asserts on a bad match. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@21668 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
609a23e431
commit
f7604f117f
@ -358,37 +358,95 @@ get_random_string_in_array(const char* str_list[])
|
||||
return str_list[num];
|
||||
}
|
||||
|
||||
void
|
||||
test_silent_logger( const char *log_domain, GLogLevelFlags log_level,
|
||||
gboolean
|
||||
test_null_handler (const char *log_domain, GLogLevelFlags log_level,
|
||||
const gchar *msg, gpointer user_data )
|
||||
{
|
||||
//Silent, remember?
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
test_log_level (GLogLevelFlags flags)
|
||||
{
|
||||
const gchar *message[] = {"RECURSIVE", "FATAL", "ERROR", "CRITICAL",
|
||||
"WARNING","MESSAGE", "INFO", "DEBUG"};
|
||||
guint i = 0, last = 0, max_bit = 7;
|
||||
gchar *msg = NULL;
|
||||
|
||||
for (i; i <= max_bit; i++)
|
||||
if (flags & 1 << i)
|
||||
{
|
||||
gchar *tmp_msg = msg;
|
||||
gchar *sep = (last < 2 ? " " : "|");
|
||||
last = i;
|
||||
msg = (tmp_msg ? g_strjoin (sep, tmp_msg, message[i], NULL)
|
||||
: g_strdup (message[i]));
|
||||
if (tmp_msg)
|
||||
g_free (tmp_msg);
|
||||
}
|
||||
|
||||
if (msg == NULL)
|
||||
msg = g_strdup ("");
|
||||
return msg;
|
||||
}
|
||||
|
||||
static GList *message_queue = NULL;
|
||||
|
||||
void
|
||||
test_add_error (TestErrorStruct *error)
|
||||
{
|
||||
message_queue = g_list_append (message_queue, error);
|
||||
}
|
||||
|
||||
void
|
||||
test_clear_error_list (void)
|
||||
{
|
||||
g_list_free (message_queue);
|
||||
message_queue = NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
test_handle_faults( const char *log_domain, GLogLevelFlags log_level,
|
||||
const gchar *msg, gpointer user_data )
|
||||
test_list_handler (const char *log_domain, GLogLevelFlags log_level,
|
||||
const gchar *msg, gpointer user_data )
|
||||
{
|
||||
GList *list = g_list_first (message_queue);
|
||||
const guint fatal = G_LOG_FLAG_FATAL;
|
||||
|
||||
while (list)
|
||||
{
|
||||
TestErrorStruct *error = (TestErrorStruct*)list->data;
|
||||
if (!g_strcmp0 (log_domain, error->log_domain)
|
||||
&& ((log_level | fatal) == (error->log_level | fatal))
|
||||
&& !g_strcmp0 (msg, error->msg))
|
||||
return FALSE;
|
||||
list = g_list_next (list);
|
||||
}
|
||||
/* No list or no matches, fall through */
|
||||
return test_checked_handler (log_domain, log_level, msg, user_data);
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
test_checked_handler (const char *log_domain, GLogLevelFlags log_level,
|
||||
const gchar *msg, gpointer user_data )
|
||||
{
|
||||
TestErrorStruct *tdata = (TestErrorStruct*)user_data;
|
||||
if (tdata == NULL)
|
||||
|
||||
if ((tdata == NULL)
|
||||
|| (tdata->log_domain != NULL
|
||||
&& g_strcmp0 (tdata->log_domain, log_domain))
|
||||
|| (tdata->log_level && tdata->log_level != log_level)
|
||||
|| (tdata->msg && g_strcmp0 (tdata->msg, msg)))
|
||||
{
|
||||
g_printf("Received Log Message %s\n", msg);
|
||||
gchar *level = test_log_level (log_level);
|
||||
g_printf ( "<%s> (%s) %s\n", level, log_domain, msg);
|
||||
g_free (level);
|
||||
g_assert (log_level ^ G_LOG_FLAG_FATAL);
|
||||
return FALSE;
|
||||
}
|
||||
/* If it's a lower loglevel than we expected, report it and move on */
|
||||
if (tdata->log_level && log_level < tdata->log_level)
|
||||
{
|
||||
g_printf ("Received Log Message %s\n", msg);
|
||||
return FALSE;
|
||||
}
|
||||
if (tdata->log_domain != NULL)
|
||||
g_assert_cmpstr (tdata->log_domain, ==, log_domain);
|
||||
if (tdata->log_level)
|
||||
g_assert_cmpuint (tdata->log_level, ==, log_level);
|
||||
if (tdata->log_level)
|
||||
g_assert_cmpstr (tdata->msg, ==, msg);
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -79,11 +79,21 @@ Otherwise, only failures are printed out.
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Support
|
||||
* Suppressing Expected Errors
|
||||
*
|
||||
* Struct and functions for unit test support:
|
||||
* Intercept and report GLib error messages to test functions.
|
||||
* Ensure that mock functions are called, and with the right data pointer
|
||||
* Functions for suppressing expected errors during tests. Pass
|
||||
*
|
||||
* Note that you need to call both g_log_set_handler *and*
|
||||
* g_test_log_set_fatal_handler to both avoid the assertion and
|
||||
* suppress the error message. The callbacks work in either role, just
|
||||
* cast them appropriately for the use.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Struct to pass as user_data for the handlers. Setting a parameter
|
||||
* to NULL or 0 will match any value in the error, so if you have the
|
||||
* same message and log level being issued in two domains you can
|
||||
* match both of them by setting log_domain = NULL.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -95,22 +105,41 @@ typedef struct
|
||||
} TestErrorStruct;
|
||||
|
||||
/**
|
||||
* Pass this to g_test_log_set_fatal_handler(), setting user_data to
|
||||
* a pointer to TestErrorStruct to intercept and handle expected
|
||||
* error and warning messages. It will g_assert if an error is
|
||||
* received which doesn't match the log_level, log_domain, and
|
||||
* message in the struct (if they're set), or return FALSE to prevent
|
||||
* the message from aborting. Be sure to g_free() the
|
||||
* TestErrorData:msg after you're done testing it.
|
||||
* Check the user_data against the actual error and assert on any
|
||||
* differences. Displays the error (and asserts if G_LOG_FLAG_FATAL
|
||||
* is TRUE) if NULL is passed as user_data, but a NULL or 0 value
|
||||
* member matches anything.
|
||||
*/
|
||||
gboolean test_handle_faults( const char *log_domain, GLogLevelFlags log_level,
|
||||
gboolean test_checked_handler (const char *log_domain, GLogLevelFlags log_level,
|
||||
const gchar *msg, gpointer user_data);
|
||||
/**
|
||||
* When you know you're going to get a useless log message, pass this
|
||||
* to g_log_set_default_handler to shut it up.
|
||||
* Just returns FALSE or suppresses the message regardless of what the
|
||||
* error is. Use this only as a last resort.
|
||||
*/
|
||||
void test_silent_logger( const char *log_domain, GLogLevelFlags log_level,
|
||||
const gchar *msg, gpointer user_data );
|
||||
gboolean test_null_handler (const char *log_domain, GLogLevelFlags log_level,
|
||||
const gchar *msg, gpointer user_data );
|
||||
/**
|
||||
* Maintains an internal list of TestErrorStructs which are each
|
||||
* checked by the list handler. If an error matches any entry on the
|
||||
* list, test_list_handler will return FALSE, blocking the error from
|
||||
* halting the program.
|
||||
*
|
||||
* Call test_add_error for each TestErrorStruct to check against and
|
||||
* test_clear_error_list when you no longer expect the errors.
|
||||
*/
|
||||
void test_add_error (TestErrorStruct *error);
|
||||
void test_clear_error_list (void);
|
||||
|
||||
/**
|
||||
* Checks received errors against the list created by
|
||||
* test_add_error. If the list is empty or nothing matches, passes
|
||||
* control on to test_checked_handler, giving the opportunity for an
|
||||
* additional check that's not in the list (set user_data to NULL if
|
||||
* you want test_checked_handler to immediately print the error).
|
||||
*/
|
||||
gboolean test_list_handler (const char *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
const gchar *msg, gpointer user_data );
|
||||
/**
|
||||
* Call this from a mock object to indicate that the mock has in fact
|
||||
* been called
|
||||
@ -237,4 +266,10 @@ TestSignal test_signal_new (QofInstance *entity, QofEventId eventType,
|
||||
void test_signal_assert_hits (TestSignal sig, guint hits);
|
||||
void test_signal_free (TestSignal sig);
|
||||
|
||||
/* For Scheme testing access:
|
||||
void gnc_log_init_filename_special (gchar *filename);
|
||||
void gnc_log_shutdown (void);
|
||||
void gnc_log_set_handler (guint logdomain, gchar *logdomain, GLogFunc * func, gpointer data);
|
||||
*/
|
||||
|
||||
#endif /* TEST_STUFF_H */
|
||||
|
Loading…
Reference in New Issue
Block a user