test-interactive: Allow querying the interactive test for a description

It would be nice if the interactive tests had a way to be queried for a
description, instead of "Just Knowing" what they are meant to be doing.
This commit is contained in:
Emmanuele Bassi 2011-09-27 17:40:51 +01:00
parent 4ebdeede9f
commit d640c56cef
2 changed files with 211 additions and 24 deletions

View File

@ -74,11 +74,13 @@ endif
# For convenience, this provides a way to easily run individual unit tests:
wrappers: stamp-test-interactive
@true
stamp-test-interactive: Makefile test-interactive$(EXEEXT)
stamp-test-interactive: Makefile
@wrapper=$(abs_builddir)/wrapper.sh ; \
chmod +x $$wrapper && \
( echo "/stamp-test-interactive" ; \
echo "/stamp-test-unit-names" ; \
echo "/test-interactive" ; \
echo "/test-unit-names.h" ; \
echo "*.o" ; \
echo ".gitignore" ) > .gitignore ; \
for i in $(UNIT_TESTS); \
@ -93,6 +95,21 @@ stamp-test-interactive: Makefile test-interactive$(EXEEXT)
done \
&& echo timestamp > $(@F)
test-unit-names.h: stamp-test-unit-names
@true
stamp-test-unit-names: Makefile
@( echo "/* ** This file is autogenerated. Do not edit. ** */" ; \
echo "" ; \
echo "const char *test_unit_names[] = {" ) > test-unit-names.h ; \
for i in $(UNIT_TESTS); \
do \
test_bin=$${i%*.c} ; \
echo " \"$$test_bin\"," >> test-unit-names.h ; \
done \
&& echo "};" >> test-unit-names.h \
&& echo timestamp > $(@F)
clean-wrappers:
@for i in $(UNIT_TESTS); \
do \
@ -115,7 +132,7 @@ common_ldadd = $(top_builddir)/clutter/libclutter-@CLUTTER_SONAME_INFIX@-@CLUTTE
noinst_PROGRAMS = test-interactive
test_interactive_SOURCES = test-main.c $(UNIT_TESTS)
test_interactive_SOURCES = test-main.c test-unit-names.h $(UNIT_TESTS)
test_interactive_CFLAGS = $(CLUTTER_CFLAGS) $(MAINTAINER_CFLAGS)
test_interactive_CPPFLAGS = \
-DTESTS_DATADIR=\""$(abs_top_srcdir)/tests/data"\" \
@ -126,8 +143,8 @@ test_interactive_LDFLAGS = -export-dynamic
test_interactive_LDADD = $(CLUTTER_LIBS) $(common_ldadd) -lm
EXTRA_DIST = wrapper.sh.in
DISTCLEANFILES = wrapper.sh .gitignore
DISTCLEANFILES = wrapper.sh .gitignore test-unit-names.h
BUILT_SOURCES = wrappers
BUILT_SOURCES = wrappers test-unit-names.h
clean-local: clean-wrappers

View File

@ -1,37 +1,207 @@
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <gmodule.h>
#include "test-unit-names.h"
#define MAX_DESC_SIZE 72
static GModule *module = NULL;
static gpointer
get_symbol_with_suffix (const char *unit_name,
const char *suffix)
{
char *main_symbol_name;
gpointer func;
main_symbol_name = g_strconcat (unit_name, "_", suffix, NULL);
main_symbol_name = g_strdelimit (main_symbol_name, "-", '_');
g_module_symbol (module, main_symbol_name, &func);
g_free (main_symbol_name);
return func;
}
static gpointer
get_unit_name_main (const char *unit_name)
{
return get_symbol_with_suffix (unit_name, "main");
}
static char *
get_unit_name_description (const char *unit_name,
gssize max_len)
{
const char *description;
gpointer func;
char *retval;
func = get_symbol_with_suffix (unit_name, "describe");
if (func == NULL)
description = "No description found";
else
{
const char *(* unit_test_describe) (void);
unit_test_describe = func;
description = unit_test_describe ();
}
if (max_len > 0 && strlen (description) >= max_len)
{
GString *buf = g_string_sized_new (max_len);
char *newline;
newline = strchr (description, '\n');
if (newline != NULL)
{
g_string_append_len (buf, description,
MIN (newline - description - 1, max_len - 3));
}
else
g_string_append_len (buf, description, max_len - 3);
g_string_append (buf, "...");
retval = g_string_free (buf, FALSE);
}
else
retval = g_strdup (description);
return retval;
}
static gboolean list_all = FALSE;
static gboolean describe = FALSE;
static char **unit_names = NULL;
static GOptionEntry entries[] = {
{
"describe", 'd',
0,
G_OPTION_ARG_NONE, &describe,
"Describe the interactive unit test", NULL,
},
{
"list-all", 'l',
0,
G_OPTION_ARG_NONE, &list_all,
"List all available units", NULL,
},
{
G_OPTION_REMAINING, 0,
0,
G_OPTION_ARG_STRING_ARRAY, &unit_names,
"The interactive unit test", "UNIT_NAME"
},
{ NULL }
};
int
main (int argc, char **argv)
{
GModule *module;
char *unit_test;
char *main_symbol_name;
gpointer func;
int (*unit_test_main) (int argc, char **argv);
int ret;
int ret, i, n_unit_names;
GOptionContext *context;
context = g_option_context_new (" - Interactive test suite");
g_option_context_add_main_entries (context, entries, NULL);
g_option_context_set_help_enabled (context, TRUE);
g_option_context_set_ignore_unknown_options (context, TRUE);
if (!g_option_context_parse (context, &argc, &argv, NULL))
{
g_print ("Usage: test-interactive <unit_test>\n");
return EXIT_FAILURE;
}
g_option_context_free (context);
if (argc < 2)
g_error ("Usage: %s unit_test", argv[0]);
module = g_module_open (NULL, 0);
if (!module)
g_error ("Failed to open self for symbol lookup");
g_error ("*** Failed to open self for symbol lookup");
unit_test = g_path_get_basename (argv[1]);
ret = EXIT_SUCCESS;
main_symbol_name = g_strdup_printf ("%s_main", unit_test);
main_symbol_name = g_strdelimit (main_symbol_name, "-", '_');
if (list_all)
{
g_print ("* Available unit tests:\n");
if (!g_module_symbol (module, main_symbol_name, &func))
g_error ("Failed to look up main symbol for the test: %s", unit_test);
for (i = 0; i < G_N_ELEMENTS (test_unit_names); i++)
{
char *str;
gsize len;
unit_test_main = func;
ret = unit_test_main (argc - 1, argv + 1);
g_free (unit_test);
g_free (main_symbol_name);
len = MAX_DESC_SIZE - strlen (test_unit_names[i]);
str = get_unit_name_description (test_unit_names[i], len - 2);
g_print (" - %s:%*s%s\n",
test_unit_names[i],
(int) len - strlen (str), " ",
str);
g_free (str);
}
ret = EXIT_SUCCESS;
goto out;
}
n_unit_names = g_strv_length (unit_names);
for (i = 0; i < n_unit_names; i++)
{
const char *unit_name = unit_names[i];
char *unit_test = NULL;
gboolean found;
int j;
unit_test = g_path_get_basename (unit_name);
found = FALSE;
for (j = 0; j < G_N_ELEMENTS (test_unit_names); j++)
{
if (strcmp (test_unit_names[j], unit_test) == 0)
{
found = TRUE;
break;
}
}
if (!found)
g_error ("*** Unit '%s' does not exist", unit_test);
if (describe)
{
char *str;
str = get_unit_name_description (unit_test, -1);
g_print ("* %s:\n%s\n\n", unit_test, str);
g_free (str);
ret = EXIT_SUCCESS;
}
else
{
int (* unit_test_main) (int argc, char **argv);
gpointer func;
func = get_unit_name_main (unit_test);
if (func == NULL)
g_error ("*** Unable to find the main entry point for '%s'", unit_test);
unit_test_main = func;
ret = unit_test_main (argc, argv);
}
g_free (unit_test);
}
out:
g_module_close (module);
return ret;