+2006-08-18 Aaron Bockover <abockover@novell.com>
+
+ * test/driver.c: Added getopt support and code timing, among other
+ nice features to make testing/profiling easier
+
+ * test/test.c: Add support for suppressing output (quiet) and
+ define RESULT, FAILED, and OK
+
+ * src/glib.h:
+ * src/glist.c: Added g_list_nth_data implementation
+
+ * test/slist.c:
+ * test/string-util.c:
+ * test/ptrarray.c:
+ * test/string.c:
+ * test/hashtable.c:
+ * test/list.c: Use RESULT, FAILURE, and OK for tests
+
2006-08-18 Miguel de Icaza <miguel@novell.com>
* src/eglib-config.h (G_OS_): Add the G_OS_UNIX and G_OS_WIN32
gconstpointer data);
GList *g_list_nth (GList *list,
guint n);
+gpointer g_list_nth_data (GList *list,
+ guint n);
GList *g_list_last (GList *list);
GList *g_list_concat (GList *list1,
GList *list2);
return value;
}
+gpointer
+g_list_nth_data (GList *list, guint n)
+{
+ return g_list_nth(list, n)->data;
+}
+
GList*
g_list_copy (GList *list)
{
#include <stdio.h>
#include <glib.h>
+#include <stddef.h>
+#include <sys/time.h>
+#include <getopt.h>
#include "test.h"
#include "tests.h"
{
gint i;
- printf("Usage: %s [options] [iterations [test1 test2 ... testN]]\n\n", s);
+ printf("Usage: %s [options] [test1 test2 ... testN]\n\n", s);
printf(" options are:\n");
- printf(" --help show this help\n\n");
- printf(" iterations: number of times to run tests\n");
+ printf(" --help|-h show this help\n");
+ printf(" --time|-t time the tests\n");
+ printf(" --iterations|-i number of times to run tests\n");
+ printf(" --quiet|-q do not print test results; if -t\n");
+ printf(" is passed, the time will print\n\n");
printf(" test1..testN name of test to run (all run by default)\n\n");
printf(" available tests:\n");
gint main(gint argc, gchar **argv)
{
- gint i, j, k, iterations = 1, tests_to_run_count = 0;
- gchar **tests_to_run = NULL;
+ gint i, j, c, iterations = 1;
+ GList *tests_to_run = NULL;
+ double time_start, time_end;
+ struct timeval tp;
+ gboolean report_time = FALSE;
+ gboolean quiet = FALSE;
- if(argc > 1) {
- for(i = 1; i < argc; i++) {
- if(strcmp(argv[i], "--help") == 0) {
+ static struct option long_options [] = {
+ {"help", no_argument, 0, 'h'},
+ {"time", no_argument, 0, 't'},
+ {"iterations", required_argument, 0, 'i'},
+ {0, 0, 0, 0}
+ };
+
+ while((c = getopt_long(argc, argv, "htqi:", long_options, NULL)) != -1) { switch(c) {
+ case 'h':
print_help(argv[0]);
return 1;
- }
+ case 't':
+ report_time = TRUE;
+ break;
+ case 'i':
+ iterations = atoi(optarg);
+ break;
+ case 'q':
+ quiet = TRUE;
+ break;
}
-
- iterations = atoi(argv[1]);
- tests_to_run_count = argc - 2;
-
- if(tests_to_run_count > 0) {
- tests_to_run = (gchar **)g_new0(gchar *, tests_to_run_count + 1);
-
- for(i = 0; i < tests_to_run_count; i++) {
- tests_to_run[i] = argv[i + 2];
- }
+ }
- tests_to_run[tests_to_run_count] = NULL;
+ for(i = optind; i < argc; i++) {
+ if(argv[i][0] == '-') {
+ continue;
}
+
+ tests_to_run = g_list_append(tests_to_run, argv[i]);
}
+ gettimeofday(&tp, NULL);
+ time_start = (double)tp.tv_sec + (1.e-6) * tp.tv_usec;
+
for(i = 0; i < iterations; i++) {
for(j = 0; test_groups[j].name != NULL; j++) {
gboolean run = TRUE;
if(tests_to_run != NULL) {
+ gint k, n;
run = FALSE;
- for(k = 0; tests_to_run[k] != NULL; k++) {
- if(strcmp(tests_to_run[k], test_groups[j].name) == 0) {
+ for(k = 0, n = g_list_length(tests_to_run); k < n; k++) {
+ if(strcmp((char *)g_list_nth_data(tests_to_run, k),
+ test_groups[j].name) == 0) {
run = TRUE;
break;
}
if(run) {
gint total, passed;
- run_group(&(test_groups[j]), &total, &passed);
- printf(" -- %d / %d (%g%%) --\n", passed, total,
- ((gdouble)passed / (gdouble)total) * 100.0);
+ run_group(&(test_groups[j]), &total, &passed, quiet);
+ if(!quiet) {
+ printf(" -- %d / %d (%g%%) --\n", passed, total,
+ ((gdouble)passed / (gdouble)total) * 100.0);
+ }
}
}
}
+
+ gettimeofday(&tp, NULL);
+ time_end = (double)tp.tv_sec + (1.e-6) * tp.tv_usec;
+
+ if(report_time) {
+ gdouble duration = time_end - time_start;
+ printf("Total Time: %gs\n", duration);
+ }
if(tests_to_run != NULL) {
- g_free(tests_to_run);
+ g_list_free(tests_to_run);
}
return 0;
foreach_fail = 1;
}
-char *hash_t1 (void)
+RESULT hash_t1 (void)
{
GHashTable *t = g_hash_table_new (g_str_hash, g_str_equal);
return "unexpected size";
g_hash_table_destroy (t);
- return NULL;
+ return OK;
}
-char *hash_t2 (void)
+RESULT hash_t2 (void)
{
- return NULL;
+ return OK;
}
static Test hashtable_tests [] = {
#include <glib.h>
#include "test.h"
-char*
+RESULT
test_list_length ()
{
GList *list = g_list_prepend (NULL, "foo");
return NULL;
}
-char*
+RESULT
test_list_nth ()
{
char *foo = "foo";
if (nth->data != baz)
return "nth failed. #3";
- return NULL;
+ return OK;
}
-char*
+RESULT
test_list_index ()
{
int i;
if (i != 2)
return "index failed. #3";
- return NULL;
+ return OK;
}
-char*
+RESULT
test_list_append ()
{
GList *list = g_list_prepend (NULL, "first");
if (g_list_length (list) != 2)
return "Append failed";
- return NULL;
+ return OK;
}
-char *
+
+RESULT
test_list_last ()
{
GList *foo = g_list_prepend (NULL, "foo");
if (strcmp ("quux", last->data))
return "last failed. #2";
- return NULL;
+ return OK;
}
-char *
+RESULT
test_list_concat ()
{
GList *foo = g_list_prepend (NULL, "foo");
if (g_list_last (list) != bar)
return "Concat failed. #5";
- return NULL;
+ return OK;
}
return 1;
}
-char*
+RESULT
test_list_insert_sorted ()
{
GList *list = g_list_prepend (NULL, "a");
/* insert at the middle */
list = g_list_insert_sorted (list, "aa", compare);
if (strcmp ("aa", list->next->data))
- return result ("insert_sorted failed. #1");
+ return FAILED ("insert_sorted failed. #1");
/* insert at the beginning */
list = g_list_insert_sorted (list, "", compare);
if (strcmp ("", list->data))
- return result ("insert_sorted failed. #2");
+ return FAILED ("insert_sorted failed. #2");
/* insert at the end */
list = g_list_insert_sorted (list, "aaaa", compare);
if (strcmp ("aaaa", g_list_last (list)->data))
- return result ("insert_sorted failed. #3");
+ return FAILED ("insert_sorted failed. #3");
- return NULL;
+ return OK;
}
-char *
+RESULT
test_list_copy ()
{
int i, length;
if (strcmp (g_list_nth (list, i)->data,
g_list_nth (copy, i)->data))
return "copy failed.";
- return NULL;
+ return OK;
}
-char *
+RESULT
test_list_reverse ()
{
guint i, length;
g_list_nth (reverse, j)->data))
return "reverse failed. #2";
}
- return NULL;
+ return OK;
}
static Test list_tests [] = {
return size;
}
-char *ptrarray_alloc()
+RESULT ptrarray_alloc()
{
GPtrArrayPriv *array;
gint i;
array = (GPtrArrayPriv *)ptrarray_alloc_and_fill(&i);
if(array->size != guess_size(array->len)) {
- return result("Size should be %d, but it is %d",
+ return FAILED("Size should be %d, but it is %d",
guess_size(array->len), array->size);
}
if(array->len != i) {
- return result("Expected %d node(s) in the array", i);
+ return FAILED("Expected %d node(s) in the array", i);
}
g_ptr_array_free((GPtrArray *)array, TRUE);
- return NULL;
+ return OK;
}
-char *ptrarray_for_iterate()
+RESULT ptrarray_for_iterate()
{
GPtrArray *array = ptrarray_alloc_and_fill(NULL);
gint i;
for(i = 0; i < array->len; i++) {
char *item = (char *)g_ptr_array_index(array, i);
if(item != items[i]) {
- return result(
+ return FAILED(
"Expected item at %d to be %s, but it was %s",
i, items[i], item);
}
g_ptr_array_free(array, TRUE);
- return NULL;
+ return OK;
}
static gint foreach_iterate_index = 0;
}
if(item != item_cmp) {
- foreach_iterate_error = result(
+ foreach_iterate_error = FAILED(
"Expected item at %d to be %s, but it was %s",
foreach_iterate_index - 1, item_cmp, item);
}
}
-char *ptrarray_foreach_iterate()
+RESULT ptrarray_foreach_iterate()
{
GPtrArray *array = ptrarray_alloc_and_fill(NULL);
return foreach_iterate_error;
}
-char *ptrarray_set_size()
+RESULT ptrarray_set_size()
{
GPtrArray *array = g_ptr_array_new();
gint i, grow_length = 50;
g_ptr_array_set_size(array, grow_length);
if(array->len != grow_length) {
- return result("Array length should be 50, it is %d", array->len);
+ return FAILED("Array length should be 50, it is %d", array->len);
} else if(array->pdata[0] != items[0]) {
- return result("Item 0 was overwritten, should be %s", items[0]);
+ return FAILED("Item 0 was overwritten, should be %s", items[0]);
} else if(array->pdata[1] != items[1]) {
- return result("Item 1 was overwritten, should be %s", items[1]);
+ return FAILED("Item 1 was overwritten, should be %s", items[1]);
}
for(i = 2; i < array->len; i++) {
if(array->pdata[i] != NULL) {
- return result("Item %d is not NULL, it is %p", i, array->pdata[i]);
+ return FAILED("Item %d is not NULL, it is %p", i, array->pdata[i]);
}
}
g_ptr_array_free(array, TRUE);
- return NULL;
+ return OK;
}
-char *ptrarray_remove_index()
+RESULT ptrarray_remove_index()
{
GPtrArray *array;
gint i;
g_ptr_array_remove_index(array, 0);
if(array->pdata[0] != items[1]) {
- return result("First item is not %s, it is %s", items[1],
+ return FAILED("First item is not %s, it is %s", items[1],
array->pdata[0]);
}
g_ptr_array_remove_index(array, array->len - 1);
if(array->pdata[array->len - 1] != items[array->len]) {
- return result("Last item is not %s, it is %s",
+ return FAILED("Last item is not %s, it is %s",
items[array->len - 2], array->pdata[array->len - 1]);
}
- return NULL;
+ return OK;
}
-char *ptrarray_remove()
+RESULT ptrarray_remove()
{
GPtrArray *array;
gint i;
g_ptr_array_remove(array, (gpointer)items[7]);
if(!g_ptr_array_remove(array, (gpointer)items[4])) {
- return result("Item %s not removed", items[4]);
+ return FAILED("Item %s not removed", items[4]);
}
if(g_ptr_array_remove(array, (gpointer)items[4])) {
- return result("Item %s still in array after removal", items[4]);
+ return FAILED("Item %s still in array after removal", items[4]);
}
if(array->pdata[array->len - 1] != items[array->len + 1]) {
- return result("Last item in GPtrArray not correct");
+ return FAILED("Last item in GPtrArray not correct");
}
- return NULL;
+ return OK;
}
static gint ptrarray_sort_compare(gconstpointer a, gconstpointer b)
return strcmp(a, b);
}
-char *ptrarray_sort()
+RESULT ptrarray_sort()
{
GPtrArray *array = g_ptr_array_new();
gint i;
for(i = 0; i < array->len; i++) {
if(strcmp((gchar *)array->pdata[i], letters[i]) != 0) {
- return result("Array out of order, expected %s got %s",
+ return FAILED("Array out of order, expected %s got %s",
(gchar *)array->pdata[i], letters[i]);
}
}
g_ptr_array_free(array, TRUE);
- return NULL;
+ return OK;
}
static Test ptrarray_tests [] = {
#include <glib.h>
#include "test.h"
-char*
+RESULT
test_slist_append ()
{
GSList *list = g_slist_prepend (NULL, "first");
if (g_slist_length (list) != 2)
return "Append failed";
- return NULL;
+ return OK;
}
-char *
+RESULT
test_slist_concat ()
{
GSList *foo = g_slist_prepend (NULL, "foo");
if (g_slist_length (list) != 2)
return "Concat failed.";
- return NULL;
+ return OK;
}
-char*
+RESULT
test_slist_find ()
{
GSList *list = g_slist_prepend (NULL, "three");
if (found->data != data)
return "Find failed";
- return NULL;
+ return OK;
}
-char*
+RESULT
test_slist_remove ()
{
GSList *list = g_slist_prepend (NULL, "three");
if (strcmp ("two", list->data) != 0)
return "Remove failed";
- return NULL;
+ return OK;
}
-char*
+RESULT
test_slist_remove_link ()
{
GSList *foo = g_slist_prepend (NULL, "a");
list = g_slist_remove_link (list, bar);
if (g_slist_length (list) != 2)
- return g_strdup ("remove_link failed #1");
+ return FAILED ("remove_link failed #1");
if (bar->next != NULL)
- return g_strdup ("remove_link failed #2");
+ return FAILED ("remove_link failed #2");
- return NULL;
+ return OK;
}
static gint
return 1;
}
-char*
+RESULT
test_slist_insert_sorted ()
{
GSList *list = g_slist_prepend (NULL, "a");
/* insert at the middle */
list = g_slist_insert_sorted (list, "aa", compare);
if (strcmp ("aa", list->next->data))
- return g_strdup("insert_sorted failed #1");
+ return FAILED("insert_sorted failed #1");
/* insert at the beginning */
list = g_slist_insert_sorted (list, "", compare);
if (strcmp ("", list->data))
- return g_strdup ("insert_sorted failed #2");
+ return FAILED ("insert_sorted failed #2");
/* insert at the end */
list = g_slist_insert_sorted (list, "aaaa", compare);
if (strcmp ("aaaa", g_slist_last (list)->data))
- return g_strdup ("insert_sorted failed #3");
+ return FAILED ("insert_sorted failed #3");
- return NULL;
+ return OK;
}
static Test slist_tests [] = {
#include "test.h"
/* This test is just to be used with valgrind */
-char *
+RESULT
test_strfreev ()
{
gchar **array = g_new (gchar *, 4);
g_strfreev (array);
g_strfreev (NULL);
- return NULL;
+ return OK;
}
-char *
+RESULT
test_concat ()
{
gchar *x = g_strconcat ("Hello", ", ", "world", NULL);
if (strcmp (x, "Hello, world") != 0)
- return result("concat failed, got: %s", x);
+ return FAILED("concat failed, got: %s", x);
g_free (x);
- return NULL;
+ return OK;
}
-char *
+RESULT
test_split ()
{
gchar **v = g_strsplit("Hello world, how are we doing today?", " ", 0);
} else {
for(i = 0; v[i] != NULL; i++);
if(i != 7) {
- return result("split failed, expected 7 tokens, got %d\n", i);
+ return FAILED("split failed, expected 7 tokens, got %d\n", i);
}
}
g_strfreev(v);
- return NULL;
+ return OK;
}
-char *
+RESULT
test_strreverse ()
{
gchar *a = g_strdup ("onetwothree");
if (strcmp (a, a_target)) {
g_free (b);
g_free (a);
- return result("strreverse failed. Expecting: '%s' and got '%s'\n", a, a_target);
+ return FAILED("strreverse failed. Expecting: '%s' and got '%s'\n", a, a_target);
}
g_strreverse (b);
if (strcmp (b, b_target)) {
g_free (b);
g_free (a);
- return result("strreverse failed. Expecting: '%s' and got '%s'\n", b, b_target);
+ return FAILED("strreverse failed. Expecting: '%s' and got '%s'\n", b, b_target);
}
g_free (b);
g_free (a);
- return NULL;
+ return OK;
}
-char *
+RESULT
test_strjoin ()
{
char *s;
if (s == NULL || (strcmp (s, "") != 0))
return "Failed to join empty arguments";
- return NULL;
+ return OK;
}
-char *
+RESULT
test_strchug ()
{
char *str = g_strdup (" \t\n hola");
return "Failed.";
}
g_free (str);
- return NULL;
+ return OK;
}
-char *
+RESULT
test_strchomp ()
{
char *str = g_strdup ("hola \t");
return "Failed.";
}
g_free (str);
- return NULL;
+ return OK;
}
-char *
+RESULT
test_strstrip ()
{
char *str = g_strdup (" \t hola ");
return "Failed.";
}
g_free (str);
- return NULL;
+ return OK;
}
static Test strutil_tests [] = {
#include <stdio.h>
#include "test.h"
-#define sfail(k,p) if (s->str [p] != k) { g_string_free (s,TRUE); return result ("Got %s, Failed at %d, expected '%c'", s->str, p, k);}
+#define sfail(k,p) if (s->str [p] != k) { g_string_free (s,TRUE); return FAILED("Got %s, Failed at %d, expected '%c'", s->str, p, k);}
-char *
+RESULT
test_gstring ()
{
GString *s = g_string_new_len ("My stuff", 2);
if (s->str [2] != 0)
return "Null as not copied";
if (strncmp (s->str+4, "Relala", 6) != 0){
- return result("Did not copy correctly, got: %s", s->str+4);
+ return FAILED("Did not copy correctly, got: %s", s->str+4);
}
g_string_free (s, TRUE);
g_string_append (s, "x");
}
if (strlen (s->str) != 1024){
- return result("Incorrect string size, got: %s %d", s->str, strlen (s->str));
+ return FAILED("Incorrect string size, got: %s %d", s->str, strlen (s->str));
}
g_string_free (s, TRUE);
g_string_append_c (s, 'x');
}
if (strlen (s->str) != 1024){
- return result("Incorrect string size, got: %s %d\n", s->str, strlen (s->str));
+ return FAILED("Incorrect string size, got: %s %d\n", s->str, strlen (s->str));
}
g_string_free (s, TRUE);
s = g_string_new ("hola");
g_string_sprintfa (s, "%s%d", ", bola", 5);
if (strcmp (s->str, "hola, bola5") != 0){
- return result("Incorrect data, got: %s\n", s->str);
+ return FAILED("Incorrect data, got: %s\n", s->str);
}
g_string_free (s, TRUE);
sfail ('2', 5);
g_string_free (s, TRUE);
- return NULL;
+ return OK;
}
static Test string_tests [] = {
static gchar *last_result = NULL;
gboolean
-run_test(Test *test)
+run_test(Test *test, gboolean quiet)
{
gchar *result;
- printf(" %s: ", test->name);
- fflush(stdout);
+
+ if(!quiet) {
+ printf(" %s: ", test->name);
+ fflush(stdout);
+ }
+
if((result = test->handler()) == NULL) {
- printf("OK\n");
+ if(!quiet) {
+ printf("OK\n");
+ }
+
return TRUE;
} else {
- printf("FAILED (%s)\n", result);
+ if(!quiet) {
+ printf("FAILED (%s)\n", result);
+ }
+
if(last_result == result) {
last_result = NULL;
g_free(result);
}
void
-run_group(Group *group, gint *total, gint *passed)
+run_group(Group *group, gint *total, gint *passed, gboolean quiet)
{
Test *tests = group->handler();
gint i, _passed = 0;
- printf("[%s]\n", group->name);
+ if(!quiet) {
+ printf("[%s]\n", group->name);
+ }
for(i = 0; tests[i].name != NULL; i++) {
- _passed += run_test(&(tests[i]));
+ _passed += run_test(&(tests[i]), quiet);
}
if(total != NULL) {
}
}
-gchar *
-result(const gchar *format, ...)
+RESULT
+FAILED(const gchar *format, ...)
{
gchar *ret;
va_list args;
#include <stdarg.h>
#include <glib.h>
+typedef gchar * RESULT;
+
typedef struct _Test Test;
typedef struct _Group Group;
LoadGroupHandler handler;
};
-gboolean run_test(Test *test);
-void run_group(Group *group, gint *total, gint *passed);
-gchar *result(const gchar *format, ...);
+gboolean run_test(Test *test, gboolean quiet);
+void run_group(Group *group, gint *total, gint *passed, gboolean quiet);
+RESULT FAILED(const gchar *format, ...);
+
+#define OK NULL
#define DEFINE_TEST_GROUP_INIT(name, table) \
Test * (name)() { return table; }