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];
|
return str_list[num];
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
gboolean
|
||||||
test_silent_logger( const char *log_domain, GLogLevelFlags log_level,
|
test_null_handler (const char *log_domain, GLogLevelFlags log_level,
|
||||||
const gchar *msg, gpointer user_data )
|
const gchar *msg, gpointer user_data )
|
||||||
{
|
{
|
||||||
//Silent, remember?
|
//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
|
gboolean
|
||||||
test_handle_faults( const char *log_domain, GLogLevelFlags log_level,
|
test_list_handler (const char *log_domain, GLogLevelFlags log_level,
|
||||||
const gchar *msg, gpointer user_data )
|
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;
|
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;
|
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;
|
return FALSE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -79,11 +79,21 @@ Otherwise, only failures are printed out.
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test Support
|
* Suppressing Expected Errors
|
||||||
*
|
*
|
||||||
* Struct and functions for unit test support:
|
* Functions for suppressing expected errors during tests. Pass
|
||||||
* Intercept and report GLib error messages to test functions.
|
*
|
||||||
* Ensure that mock functions are called, and with the right data pointer
|
* 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;
|
} TestErrorStruct;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pass this to g_test_log_set_fatal_handler(), setting user_data to
|
* Check the user_data against the actual error and assert on any
|
||||||
* a pointer to TestErrorStruct to intercept and handle expected
|
* differences. Displays the error (and asserts if G_LOG_FLAG_FATAL
|
||||||
* error and warning messages. It will g_assert if an error is
|
* is TRUE) if NULL is passed as user_data, but a NULL or 0 value
|
||||||
* received which doesn't match the log_level, log_domain, and
|
* member matches anything.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
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);
|
const gchar *msg, gpointer user_data);
|
||||||
/**
|
/**
|
||||||
* When you know you're going to get a useless log message, pass this
|
* Just returns FALSE or suppresses the message regardless of what the
|
||||||
* to g_log_set_default_handler to shut it up.
|
* error is. Use this only as a last resort.
|
||||||
*/
|
*/
|
||||||
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 );
|
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
|
* Call this from a mock object to indicate that the mock has in fact
|
||||||
* been called
|
* 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_assert_hits (TestSignal sig, guint hits);
|
||||||
void test_signal_free (TestSignal sig);
|
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 */
|
#endif /* TEST_STUFF_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user