From c1228dfc993bf60fe0ef89fa3231086bc05ac0c0 Mon Sep 17 00:00:00 2001 From: Aaron Bockover Date: Mon, 21 Aug 2006 22:22:50 +0000 Subject: [PATCH] 2006-08-21 Aaron Bockover * src/gstr.c: fixed bug/invalid read/write on malloc-only case (no realloc/delimiter token not found); use memcpy instead of strncpy for better performance * test/test.c (run_group): allow running specific tests under a group; added copied g_strsplit/g_strfreev from EGlib source as eg_strsplit and eg_strfreev to avoid performance skews in the driver * test/driver.c: allow user-specified group name to contain specific test to run under the group as 'group_name:test1,test2,...testN' * test/string-util.c: Added more g_strsplit tests * test/slist.c: * test/ptrarray.c: * test/fake.c: * test/string.c: * test/list.c: * test/array.c: * test/hashtable.c: make test names shorter (no need to prefix with the group since it runs under the group) svn path=/trunk/mono/; revision=64167 --- eglib/ChangeLog | 24 ++++++++ eglib/src/gstr.c | 19 +++--- eglib/test/array.c | 10 ++-- eglib/test/driver.c | 47 ++++++++++++--- eglib/test/fake.c | 2 +- eglib/test/hashtable.c | 10 ++-- eglib/test/list.c | 24 ++++---- eglib/test/ptrarray.c | 28 ++++----- eglib/test/slist.c | 12 ++-- eglib/test/string-util.c | 35 ++++++++--- eglib/test/string.c | 4 +- eglib/test/test.c | 121 ++++++++++++++++++++++++++++++++++++--- eglib/test/test.h | 4 +- 13 files changed, 262 insertions(+), 78 deletions(-) diff --git a/eglib/ChangeLog b/eglib/ChangeLog index 3872a7c2aac..123ab48f12e 100644 --- a/eglib/ChangeLog +++ b/eglib/ChangeLog @@ -1,3 +1,27 @@ +2006-08-21 Aaron Bockover + + * src/gstr.c: fixed bug/invalid read/write on malloc-only case (no + realloc/delimiter token not found); use memcpy instead of strncpy for + better performance + + * test/test.c (run_group): allow running specific tests under a group; + added copied g_strsplit/g_strfreev from EGlib source as eg_strsplit + and eg_strfreev to avoid performance skews in the driver + + * test/driver.c: allow user-specified group name to contain specific + test to run under the group as 'group_name:test1,test2,...testN' + + * test/string-util.c: Added more g_strsplit tests + + * test/slist.c: + * test/ptrarray.c: + * test/fake.c: + * test/string.c: + * test/list.c: + * test/array.c: + * test/hashtable.c: make test names shorter (no need to prefix with + the group since it runs under the group) + 2006-08-21 Miguel de Icaza * src/glib.h (g_hash_table_new_full): Add missing prototype. diff --git a/eglib/src/gstr.c b/eglib/src/gstr.c index 6d041995453..36951471944 100644 --- a/eglib/src/gstr.c +++ b/eglib/src/gstr.c @@ -171,24 +171,24 @@ g_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens) g_return_val_if_fail(string != NULL, NULL); g_return_val_if_fail(delimiter != NULL, NULL); - g_return_val_if_fail(delimiter[0] != '\0', NULL); + g_return_val_if_fail(delimiter[0] != 0, NULL); token_length = strlen(string); string_c = (gchar *)g_malloc(token_length + 1); - strncpy(string_c, string, token_length); - string_c[token_length] = '\0'; + memcpy(string_c, string, token_length); + string_c[token_length] = 0; vector = NULL; token = (gchar *)strtok_r(string_c, delimiter, &strtok_save); - + while(token != NULL) { token_length = strlen(token); token_c = (gchar *)g_malloc(token_length + 1); - strncpy(token_c, token, token_length); - token_c[token_length] = '\0'; + memcpy(token_c, token, token_length); + token_c[token_length] = 0; vector = vector == NULL ? - (gchar **)g_malloc(sizeof(vector)) : + (gchar **)g_malloc(2 * sizeof(vector)) : (gchar **)g_realloc(vector, (size + 1) * sizeof(vector)); vector[size - 1] = token_c; @@ -205,7 +205,10 @@ g_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens) } } - vector[size - 1] = NULL; + if(vector != NULL && size > 0) { + vector[size - 1] = NULL; + } + g_free(string_c); string_c = NULL; diff --git a/eglib/test/array.c b/eglib/test/array.c index 64f7b427f97..8acea5bbaba 100644 --- a/eglib/test/array.c +++ b/eglib/test/array.c @@ -108,11 +108,11 @@ test_array_remove () } static Test array_tests [] = { - {"array_big", test_array_big}, - {"array_append", test_array_append}, - {"array_index", test_array_index}, - {"array_remove", test_array_remove}, - {"array_append_zero_terminated", test_array_append_zero_terminated}, + {"big", test_array_big}, + {"append", test_array_append}, + {"index", test_array_index}, + {"remove", test_array_remove}, + {"append_zero_term", test_array_append_zero_terminated}, {NULL, NULL} }; diff --git a/eglib/test/driver.c b/eglib/test/driver.c index fa6a950476e..e53c7b2bf69 100644 --- a/eglib/test/driver.c +++ b/eglib/test/driver.c @@ -145,20 +145,34 @@ gint main(gint argc, gchar **argv) for(j = 0; test_groups[j].name != NULL; j++) { gboolean run = TRUE; - + gchar *tests = NULL; + gchar *group = NULL; + if(tests_to_run != NULL) { gint k; run = FALSE; - for(k = 0; k < tests_to_run->length; k++) { - if(strcmp((char *)tests_to_run->strings[k], - test_groups[j].name) == 0) { + + for(k = 0; k < tests_to_run->length; k++) { + gchar *user = tests_to_run->strings[k]; + const gchar *table = test_groups[j].name; + gint user_len = strlen(user); + gint table_len = strlen(table); + + if(strncmp(user, table, table_len) == 0) { + if(user_len > table_len && user[table_len] != ':') { + break; + } + run = TRUE; + group = tests_to_run->strings[k]; break; } } } - + if(run) { + gchar **split = NULL; + if(debug && test_groups[j].handler != fake_tests_init) { printf("Skipping %s, in driver debug mode\n", test_groups[j].name); @@ -166,9 +180,28 @@ gint main(gint argc, gchar **argv) } else if(!debug && test_groups[j].handler == fake_tests_init) { continue; } - + + if(group != NULL) { + split = eg_strsplit(group, ":", -1); + if(split != NULL) { + gint m; + for(m = 0; split[m] != NULL; m++) { + if(m == 1) { + tests = strdup(split[m]); + break; + } + } + eg_strfreev(split); + } + } + gboolean passed = run_group(&(test_groups[j]), - iterations, quiet, report_time); + iterations, quiet, report_time, tests); + + if(tests != NULL) { + g_free(tests); + } + if(!passed && !global_failure) { global_failure = TRUE; } diff --git a/eglib/test/fake.c b/eglib/test/fake.c index 5ceb65dab71..c8d9af61165 100644 --- a/eglib/test/fake.c +++ b/eglib/test/fake.c @@ -11,7 +11,7 @@ test_fake() } static Test fake_tests [] = { - {"test_fake", test_fake}, + {"fake", test_fake}, {NULL, NULL} }; diff --git a/eglib/test/hashtable.c b/eglib/test/hashtable.c index 621977522c6..48b2d1696eb 100644 --- a/eglib/test/hashtable.c +++ b/eglib/test/hashtable.c @@ -131,11 +131,11 @@ RESULT hash_grow (void) } static Test hashtable_tests [] = { - {"hash_t1", hash_t1}, - {"hash_t2", hash_t2}, - {"hash_grow", hash_grow}, - {"hash_default", hash_default}, - {"hash_null_lookup", hash_null_lookup}, + {"t1", hash_t1}, + {"t2", hash_t2}, + {"grow", hash_grow}, + {"default", hash_default}, + {"null_lookup", hash_null_lookup}, {NULL, NULL} }; diff --git a/eglib/test/list.c b/eglib/test/list.c index 7460ec7b53e..41bae3f19df 100644 --- a/eglib/test/list.c +++ b/eglib/test/list.c @@ -300,18 +300,18 @@ test_list_insert_before () } static Test list_tests [] = { - {"list_length", test_list_length}, - {"list_nth", test_list_nth}, - {"list_index", test_list_index}, - {"list_last", test_list_last}, - {"list_append", test_list_append}, - {"list_concat", test_list_concat}, - {"list_insert_sorted", test_list_insert_sorted}, - {"list_insert_before", test_list_insert_before}, - {"list_copy", test_list_copy}, - {"list_reverse", test_list_reverse}, - {"list_remove", test_list_remove}, - {"list_remove_link", test_list_remove_link}, + {"length", test_list_length}, + {"nth", test_list_nth}, + {"index", test_list_index}, + {"last", test_list_last}, + {"append", test_list_append}, + {"concat", test_list_concat}, + {"insert_sorted", test_list_insert_sorted}, + {"insert_before", test_list_insert_before}, + {"copy", test_list_copy}, + {"reverse", test_list_reverse}, + {"remove", test_list_remove}, + {"remove_link", test_list_remove_link}, {NULL, NULL} }; diff --git a/eglib/test/ptrarray.c b/eglib/test/ptrarray.c index 53f4584bf66..23c5cba1c5f 100644 --- a/eglib/test/ptrarray.c +++ b/eglib/test/ptrarray.c @@ -205,18 +205,18 @@ RESULT ptrarray_sort() { GPtrArray *array = g_ptr_array_new(); gint i; - static const gchar *letters [] = { "A", "B", "C", "D", "E" }; + gchar *letters [] = { "A", "B", "C", "D", "E" }; - g_ptr_array_add(array, (gpointer)letters[1]); - g_ptr_array_add(array, (gpointer)letters[3]); - g_ptr_array_add(array, (gpointer)letters[0]); - g_ptr_array_add(array, (gpointer)letters[2]); - g_ptr_array_add(array, (gpointer)letters[4]); + g_ptr_array_add(array, letters[0]); + g_ptr_array_add(array, letters[1]); + g_ptr_array_add(array, letters[2]); + g_ptr_array_add(array, letters[3]); + g_ptr_array_add(array, letters[4]); g_ptr_array_sort(array, ptrarray_sort_compare); for(i = 0; i < array->len; i++) { - if(strcmp((const gchar *)array->pdata[i], letters[i]) != 0) { + if(array->pdata[i] != letters[i]) { return FAILED("Array out of order, expected %s got %s", (gchar *)array->pdata[i], letters[i]); } @@ -228,13 +228,13 @@ RESULT ptrarray_sort() } static Test ptrarray_tests [] = { - {"ptrarray_alloc", ptrarray_alloc}, - {"ptrarray_for_iterate", ptrarray_for_iterate}, - {"ptrarray_foreach_iterate", ptrarray_foreach_iterate}, - {"ptrarray_set_size", ptrarray_set_size}, - {"ptrarray_remove_index", ptrarray_remove_index}, - {"ptrarray_remove", ptrarray_remove}, - {"ptrarray_sort", ptrarray_sort}, + {"alloc", ptrarray_alloc}, + {"for_iterate", ptrarray_for_iterate}, + {"foreach_iterate", ptrarray_foreach_iterate}, + {"set_size", ptrarray_set_size}, + {"remove_index", ptrarray_remove_index}, + {"remove", ptrarray_remove}, + {"sort", ptrarray_sort}, {NULL, NULL} }; diff --git a/eglib/test/slist.c b/eglib/test/slist.c index 046eea41706..f369dc9e27f 100644 --- a/eglib/test/slist.c +++ b/eglib/test/slist.c @@ -139,12 +139,12 @@ test_slist_insert_sorted () } static Test slist_tests [] = { - {"slist_append", test_slist_append}, - {"slist_concat", test_slist_concat}, - {"slist_find", test_slist_find}, - {"slist_remove", test_slist_remove}, - {"slist_remove_link", test_slist_remove_link}, - {"slist_insert_sorted", test_slist_insert_sorted}, + {"append", test_slist_append}, + {"concat", test_slist_concat}, + {"find", test_slist_find}, + {"remove", test_slist_remove}, + {"remove_link", test_slist_remove_link}, + {"insert_sorted", test_slist_insert_sorted}, {NULL, NULL} }; diff --git a/eglib/test/string-util.c b/eglib/test/string-util.c index f6f53efffc6..b519b871dcb 100644 --- a/eglib/test/string-util.c +++ b/eglib/test/string-util.c @@ -32,19 +32,38 @@ test_concat () RESULT test_split () { - gchar **v = g_strsplit("Hello world, how are we doing today?", " ", 0); - int i = 0; + const gchar *to_split = "Hello world, how are we doing today?"; + gint i; + gchar **v; + + v= g_strsplit(to_split, " ", 0); if(v == NULL) { - return "split failed, got NULL vector"; - } else { - for(i = 0; v[i] != NULL; i++); - if(i != 7) { - return FAILED("split failed, expected 7 tokens, got %d\n", i); - } + return FAILED("split failed, got NULL vector (1)"); + } + + for(i = 0; v[i] != NULL; i++); + if(i != 7) { + return FAILED("split failed, expected 7 tokens, got %d", i); } g_strfreev(v); + + v = g_strsplit(to_split, ":", -1); + if(v == NULL) { + return FAILED("split failed, got NULL vector (2)"); + } + + for(i = 0; v[i] != NULL; i++); + if(i != 1) { + return FAILED("split failed, expected 1 token, got %d", i); + } + + if(strcmp(v[0], to_split) != 0) { + return FAILED("expected vector[0] to be '%s' but it was '%s'", + to_split, v[0]); + } + return OK; } diff --git a/eglib/test/string.c b/eglib/test/string.c index d75f11ca7c6..73fb86488ee 100644 --- a/eglib/test/string.c +++ b/eglib/test/string.c @@ -204,8 +204,8 @@ test_appendlen () static Test string_tests [] = { {"append-speed", test_append_speed}, {"append_c-speed", test_append_c_speed}, - {"constructors+append", test_gstring }, - {"constructor-sized", test_sized }, + {"ctor+append", test_gstring }, + {"ctor+sized", test_sized }, {"truncate", test_truncate }, {"prepend", test_prepend }, {"append_len", test_appendlen }, diff --git a/eglib/test/test.c b/eglib/test/test.c index 8400cde0fa0..d9da87180b9 100644 --- a/eglib/test/test.c +++ b/eglib/test/test.c @@ -52,12 +52,14 @@ run_test(Test *test, gchar **result_out) } gboolean -run_group(Group *group, gint iterations, gboolean quiet, gboolean time) +run_group(Group *group, gint iterations, gboolean quiet, + gboolean time, gchar *tests_to_run_s) { Test *tests = group->handler(); - gint i, j, passed = 0; + gint i, j, passed = 0, total = 0; gdouble start_time_group, start_time_test; - + gchar **tests_to_run = NULL; + if(!quiet) { if(iterations > 1) { printf("[%s] (%dx)\n", group->name, iterations); @@ -66,12 +68,35 @@ run_group(Group *group, gint iterations, gboolean quiet, gboolean time) } } + if(tests_to_run_s != NULL) { + tests_to_run = eg_strsplit(tests_to_run_s, ",", -1); + } + start_time_group = get_timestamp(); for(i = 0; tests[i].name != NULL; i++) { gchar *result; - gboolean iter_pass; - + gboolean iter_pass, run; + + if(tests_to_run != NULL) { + gint j; + run = FALSE; + for(j = 0; tests_to_run[j] != NULL; j++) { + if(strcmp(tests_to_run[j], tests[i].name) == 0) { + run = TRUE; + break; + } + } + } else { + run = TRUE; + } + + if(!run) { + continue; + } + + total++; + if(!quiet) { printf(" %s: ", tests[i].name); } @@ -107,16 +132,20 @@ run_group(Group *group, gint iterations, gboolean quiet, gboolean time) } if(!quiet) { - gdouble pass_percentage = ((gdouble)passed / (gdouble)i) * 100.0; + gdouble pass_percentage = ((gdouble)passed / (gdouble)total) * 100.0; if(time) { - printf(" %d / %d (%g%%, %g)\n", passed, i, + printf(" %d / %d (%g%%, %g)\n", passed, total, pass_percentage, get_timestamp() - start_time_group); } else { - printf(" %d / %d (%g%%)\n", passed, i, pass_percentage); + printf(" %d / %d (%g%%)\n", passed, total, pass_percentage); } } - return passed == i; + if(tests_to_run != NULL) { + eg_strfreev(tests_to_run); + } + + return passed == total; } RESULT @@ -147,3 +176,77 @@ get_timestamp() return (gdouble)tp.tv_sec + (1.e-6) * tp.tv_usec; } +/* + * Duplicating code here from EGlib to avoid g_strsplit skew between + * EGLib and GLib + */ + +gchar ** +eg_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens) +{ + gchar *string_c; + gchar *strtok_save, **vector; + gchar *token, *token_c; + gint size = 1; + gint token_length; + + g_return_val_if_fail(string != NULL, NULL); + g_return_val_if_fail(delimiter != NULL, NULL); + g_return_val_if_fail(delimiter[0] != 0, NULL); + + token_length = strlen(string); + string_c = (gchar *)g_malloc(token_length + 1); + memcpy(string_c, string, token_length); + string_c[token_length] = 0; + + vector = NULL; + token = (gchar *)strtok_r(string_c, delimiter, &strtok_save); + + while(token != NULL) { + token_length = strlen(token); + token_c = (gchar *)g_malloc(token_length + 1); + memcpy(token_c, token, token_length); + token_c[token_length] = 0; + + vector = vector == NULL ? + (gchar **)g_malloc(2 * sizeof(vector)) : + (gchar **)g_realloc(vector, (size + 1) * sizeof(vector)); + + vector[size - 1] = token_c; + size++; + + if(max_tokens > 0 && size >= max_tokens) { + if(size > max_tokens) { + break; + } + + token = strtok_save; + } else { + token = (gchar *)strtok_r(NULL, delimiter, &strtok_save); + } + } + + if(vector != NULL && size > 0) { + vector[size - 1] = NULL; + } + + g_free(string_c); + string_c = NULL; + + return vector; +} + +void +eg_strfreev (gchar **str_array) +{ + gchar **orig = str_array; + if (str_array == NULL) + return; + while (*str_array != NULL){ + g_free (*str_array); + str_array++; + } + g_free (orig); +} + + diff --git a/eglib/test/test.h b/eglib/test/test.h index 33a1c1f9c8f..834cd9621bf 100644 --- a/eglib/test/test.h +++ b/eglib/test/test.h @@ -51,9 +51,11 @@ struct _Group { }; gboolean run_group(Group *group, gint iterations, gboolean quiet, - gboolean time); + gboolean time, gchar *tests); RESULT FAILED(const gchar *format, ...); gdouble get_timestamp(); +gchar ** eg_strsplit (const gchar *string, const gchar *delimiter, gint max_tokens); +void eg_strfreev (gchar **str_array); #define OK NULL -- 2.25.1