[gtk/wip/otte/sortlistmodel: 26/33] testsuite: Support different models
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/sortlistmodel: 26/33] testsuite: Support different models
- Date: Wed, 22 Jul 2020 01:24:55 +0000 (UTC)
commit 7d95bc4dc6842bf2eefa0f41ff8af5baae6f4ec9
Author: Benjamin Otte <otte redhat com>
Date: Sun Jul 19 01:02:38 2020 +0200
testsuite: Support different models
In particular, add a GtkTreeModel of GtkDirectoryList that enumerates
the full tree of everything below G_TEST_SRCDIR.
You can set it to ~ or / to get lots of files.
Use this to test numeric sorting, string sorting, the treelistrow
sorter and the multisorter.
And while doing all of that, try to use something that is still
realistic.
testsuite/gtk/sort-performance.c | 384 ++++++++++++++++++++++++++++++---------
1 file changed, 302 insertions(+), 82 deletions(-)
---
diff --git a/testsuite/gtk/sort-performance.c b/testsuite/gtk/sort-performance.c
index aadbf6ca3c..3bd48c5342 100644
--- a/testsuite/gtk/sort-performance.c
+++ b/testsuite/gtk/sort-performance.c
@@ -15,6 +15,16 @@ quick_random (guint prev)
static guint comparisons = 0;
+static int
+count_comparisons (gconstpointer a,
+ gconstpointer b,
+ gpointer unused)
+{
+ comparisons++;
+
+ return GTK_ORDERING_EQUAL;
+}
+
static int
compare_string_object (gconstpointer a,
gconstpointer b,
@@ -29,12 +39,6 @@ compare_string_object (gconstpointer a,
gtk_string_object_get_string (sb)));
}
-static GtkSorter *
-create_sorter (void)
-{
- return gtk_custom_sorter_new (compare_string_object, NULL, NULL);
-}
-
static void
count_changed_cb (GListModel *model,
guint position,
@@ -80,22 +84,20 @@ set_model (const char *testname,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
gint64 start, end, max, total;
GtkSliceListModel *slice;
- GtkSorter *sorter;
GListModel *sort;
guint n_changed, size = 1000;
slice = gtk_slice_list_model_new (source, 0, size);
- sorter = create_sorter ();
sort = g_object_new (type,
"sorter", sorter,
incremental ? "incremental" : NULL, TRUE,
NULL);
g_signal_connect (sort, "items-changed", G_CALLBACK (count_changed_cb), &n_changed);
- g_object_unref (sorter);
while (TRUE)
{
@@ -118,12 +120,11 @@ set_model (const char *testname,
print_result (testname, type, incremental, size, total, max, comparisons, n_changed);
- if (total > MAX_TIME)
+ if (total > MAX_TIME ||
+ size >= g_list_model_get_n_items (source))
break;
size *= 2;
- if (4 * total > 2 * MAX_TIME)
- break;
g_object_set (sort, "model", NULL, NULL);
gtk_slice_list_model_set_size (slice, size);
@@ -138,24 +139,22 @@ append (const char *testname,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random,
guint fraction)
{
gint64 start, end, max, total;
GtkSliceListModel *slice;
- GtkSorter *sorter;
GListModel *sort;
guint n_changed, size = 1000;
slice = gtk_slice_list_model_new (source, 0, (fraction - 1) * size / fraction);
- sorter = create_sorter ();
sort = g_object_new (type,
"model", slice,
"sorter", sorter,
incremental ? "incremental" : NULL, TRUE,
NULL);
g_signal_connect (sort, "items-changed", G_CALLBACK (count_changed_cb), &n_changed);
- g_object_unref (sorter);
while (TRUE)
{
@@ -179,13 +178,11 @@ append (const char *testname,
print_result (testname, type, incremental, size, total, max, comparisons, n_changed);
- if (total > MAX_TIME)
+ if (total > MAX_TIME ||
+ size >= g_list_model_get_n_items (source))
break;
size *= 2;
- if (4 * total > 2 * MAX_TIME ||
- size > MAX_SIZE)
- break;
}
g_object_unref (sort);
@@ -197,9 +194,10 @@ append_half (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- append (name, type, incremental, source, random, 2);
+ append (name, type, incremental, source, sorter, random, 2);
}
static void
@@ -207,9 +205,10 @@ append_10th (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- append (name, type, incremental, source, random, 10);
+ append (name, type, incremental, source, sorter, random, 10);
}
static void
@@ -217,9 +216,10 @@ append_100th (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- append (name, type, incremental, source, random, 100);
+ append (name, type, incremental, source, sorter, random, 100);
}
static void
@@ -227,24 +227,22 @@ remove_test (const char *testname,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random,
guint fraction)
{
gint64 start, end, max, total;
GtkSliceListModel *slice;
- GtkSorter *sorter;
GListModel *sort;
guint n_changed, size = 1000;
slice = gtk_slice_list_model_new (source, 0, size);
- sorter = create_sorter ();
sort = g_object_new (type,
"model", slice,
"sorter", sorter,
incremental ? "incremental" : NULL, TRUE,
NULL);
g_signal_connect (sort, "items-changed", G_CALLBACK (count_changed_cb), &n_changed);
- g_object_unref (sorter);
while (TRUE)
{
@@ -268,13 +266,11 @@ remove_test (const char *testname,
print_result (testname, type, incremental, size, total, max, comparisons, n_changed);
- if (total > MAX_TIME)
+ if (total > MAX_TIME ||
+ size >= g_list_model_get_n_items (source))
break;
size *= 2;
- if (4 * total > 2 * MAX_TIME ||
- size > MAX_SIZE)
- break;
}
g_object_unref (sort);
@@ -286,9 +282,10 @@ remove_half (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- remove_test (name, type, incremental, source, random, 2);
+ remove_test (name, type, incremental, source, sorter, random, 2);
}
static void
@@ -296,9 +293,10 @@ remove_10th (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- remove_test (name, type, incremental, source, random, 10);
+ remove_test (name, type, incremental, source, sorter, random, 10);
}
static void
@@ -306,9 +304,10 @@ remove_100th (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- remove_test (name, type, incremental, source, random, 100);
+ remove_test (name, type, incremental, source, sorter, random, 100);
}
static void
@@ -316,24 +315,22 @@ append_n (const char *testname,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random,
guint n)
{
gint64 start, end, max, total;
GtkSliceListModel *slice;
- GtkSorter *sorter;
GListModel *sort;
guint i, n_changed, size = 1000;
slice = gtk_slice_list_model_new (source, 0, size);
- sorter = create_sorter ();
sort = g_object_new (type,
"model", slice,
"sorter", sorter,
incremental ? "incremental" : NULL, TRUE,
NULL);
g_signal_connect (sort, "items-changed", G_CALLBACK (count_changed_cb), &n_changed);
- g_object_unref (sorter);
while (TRUE)
{
@@ -360,13 +357,11 @@ append_n (const char *testname,
print_result (testname, type, incremental, size, total, max, comparisons, n_changed);
- if (total > MAX_TIME)
+ if (total > MAX_TIME ||
+ size >= g_list_model_get_n_items (source))
break;
size *= 2;
- if (4 * total > 2 * MAX_TIME ||
- size > MAX_SIZE)
- break;
}
g_object_unref (sort);
@@ -378,9 +373,10 @@ append_1 (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- append_n (name, type, incremental, source, random, 1);
+ append_n (name, type, incremental, source, sorter, random, 1);
}
static void
@@ -388,9 +384,10 @@ append_2 (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- append_n (name, type, incremental, source, random, 2);
+ append_n (name, type, incremental, source, sorter, random, 2);
}
static void
@@ -398,9 +395,10 @@ append_10 (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- append_n (name, type, incremental, source, random, 10);
+ append_n (name, type, incremental, source, sorter, random, 10);
}
static void
@@ -408,24 +406,22 @@ remove_n (const char *testname,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random,
guint n)
{
gint64 start, end, max, total;
GtkSliceListModel *slice;
- GtkSorter *sorter;
GListModel *sort;
guint i, n_changed, size = 1000;
slice = gtk_slice_list_model_new (source, 0, size);
- sorter = create_sorter ();
sort = g_object_new (type,
"model", slice,
"sorter", sorter,
incremental ? "incremental" : NULL, TRUE,
NULL);
g_signal_connect (sort, "items-changed", G_CALLBACK (count_changed_cb), &n_changed);
- g_object_unref (sorter);
while (TRUE)
{
@@ -452,13 +448,11 @@ remove_n (const char *testname,
print_result (testname, type, incremental, size, total, max, comparisons, n_changed);
- if (total > MAX_TIME)
+ if (total > MAX_TIME ||
+ size >= g_list_model_get_n_items (source))
break;
size *= 2;
- if (4 * total > 2 * MAX_TIME ||
- size > MAX_SIZE)
- break;
}
g_object_unref (sort);
@@ -470,9 +464,10 @@ remove_1 (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- remove_n (name, type, incremental, source, random, 1);
+ remove_n (name, type, incremental, source, sorter, random, 1);
}
static void
@@ -480,26 +475,158 @@ remove_2 (const char *name,
GType type,
gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- remove_n (name, type, incremental, source, random, 2);
+ remove_n (name, type, incremental, source, sorter, random, 2);
}
static void
remove_10 (const char *name,
GType type,
- gboolean incremental,
+ gboolean incremental,
GListModel *source,
+ GtkSorter *sorter,
guint random)
{
- remove_n (name, type, incremental, source, random, 10);
+ remove_n (name, type, incremental, source, sorter, random, 10);
+}
+
+static void
+done_loading_directory (GtkDirectoryList *dir,
+ GParamSpec *pspec,
+ gpointer data)
+{
+ /* When we get G_IO_ERROR_TOO_MANY_OPEN_FILES we enqueue directories here for reloading
+ * as more file descriptors get available
+ */
+ static GSList *too_many = NULL;
+
+ const GError *error;
+ guint *counters = data;
+
+ /* happens when restarting the load below */
+ if (gtk_directory_list_is_loading (dir))
+ return;
+
+ error = gtk_directory_list_get_error (dir);
+ if (error)
+ {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_TOO_MANY_OPEN_FILES))
+ {
+ too_many = g_slist_prepend (too_many, g_object_ref (dir));
+ return;
+ }
+ }
+ counters[1]++;
+ if (too_many)
+ {
+ GtkDirectoryList *reload = too_many->data;
+ GFile *file;
+
+ too_many = g_slist_remove (too_many, reload);
+ file = g_object_ref (gtk_directory_list_get_file (reload));
+ gtk_directory_list_set_file (reload, NULL);
+ gtk_directory_list_set_file (reload, file);
+ g_object_unref (file);
+ }
+}
+
+static gboolean
+file_info_is_directory (GFileInfo *file_info)
+{
+ if (g_file_info_get_is_symlink (file_info))
+ return FALSE;
+
+ return g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY;
+}
+
+static GListModel *
+create_directory_list (gpointer item,
+ gpointer data)
+{
+ GFileInfo *file_info = G_FILE_INFO (item);
+ guint *counters = data;
+ GtkDirectoryList *dir;
+ GFile *file;
+
+ if (!file_info_is_directory (file_info))
+ return NULL;
+ file = G_FILE (g_file_info_get_attribute_object (file_info, "standard::file"));
+ if (file == NULL)
+ return NULL;
+
+ dir = gtk_directory_list_new (G_FILE_ATTRIBUTE_STANDARD_TYPE
+ "," G_FILE_ATTRIBUTE_STANDARD_NAME
+ "," G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME
+ "," G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK,
+ NULL);
+ gtk_directory_list_set_io_priority (dir, G_PRIORITY_DEFAULT + g_random_int_range (-5, 5));
+ gtk_directory_list_set_monitored (dir, FALSE);
+ gtk_directory_list_set_file (dir, file);
+ counters[0]++;
+ g_signal_connect (dir, "notify::loading", G_CALLBACK (done_loading_directory), counters);
+ g_assert (gtk_directory_list_is_loading (dir));
+
+ return G_LIST_MODEL (dir);
+}
+
+static GListModel *
+get_file_infos (void)
+{
+ static GtkTreeListModel *tree = NULL;
+ gint64 start, end, max;
+ GtkDirectoryList *dir;
+ GFile *root;
+ guint counters[2] = { 1, 0 };
+
+ if (tree)
+ return G_LIST_MODEL (g_object_ref (tree));
+
+ if (g_getenv ("G_TEST_SRCDIR"))
+ root = g_file_new_for_path (g_getenv ("G_TEST_SRCDIR"));
+ else
+ root = g_file_new_for_path (g_get_home_dir ());
+
+ start = end = g_get_monotonic_time ();
+ max = 0;
+ dir = gtk_directory_list_new (G_FILE_ATTRIBUTE_STANDARD_TYPE
+ "," G_FILE_ATTRIBUTE_STANDARD_NAME
+ "," G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME
+ "," G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK,
+ NULL);
+ gtk_directory_list_set_monitored (dir, FALSE);
+ gtk_directory_list_set_file (dir, root);
+ tree = gtk_tree_list_model_new (FALSE,
+ G_LIST_MODEL (dir),
+ TRUE,
+ create_directory_list,
+ counters, NULL);
+ g_signal_connect (dir, "notify::loading", G_CALLBACK (done_loading_directory), counters);
+ end = snapshot_time (end, &max);
+ while (counters[0] != counters[1])
+ {
+ g_main_context_iteration (NULL, TRUE);
+ end = snapshot_time (end, &max);
+ }
+ //g_print ("%u/%u\n", counters[0], counters[1]);
+
+ end = snapshot_time (end, &max);
+
+ print_result ("load-directory", GTK_TYPE_DIRECTORY_LIST, FALSE, g_list_model_get_n_items (G_LIST_MODEL
(tree)), end - start, max, 0, counters[0]);
+
+ g_object_unref (dir);
+ g_object_unref (root);
+
+ return G_LIST_MODEL (g_object_ref (tree));
}
static void
-run_test (GtkStringList *source,
+run_test (GListModel *source,
+ GtkSorter *sorter,
const char * const *tests,
const char *test_name,
- void (* test_func) (const char *name, GType type, gboolean incremental, GListModel *source, guint
random))
+ void (* test_func) (const char *name, GType type, gboolean incremental, GListModel *source,
GtkSorter *sorter, guint random))
{
struct {
GType type;
@@ -524,51 +651,144 @@ run_test (GtkStringList *source,
guint random = g_random_int ();
guint i;
- if (tests != NULL && !g_strv_contains (tests, test_name))
- return;
-
for (i = 0; i < G_N_ELEMENTS (types); i++)
{
- test_func (test_name, types[i].type, types[i].incremental, G_LIST_MODEL (source), random);
+ test_func (test_name, types[i].type, types[i].incremental, source, sorter, random);
+ }
+}
+
+static GListModel *
+get_string_list (void)
+{
+ static GtkStringList *string_list = NULL;
+
+ if (string_list == NULL)
+ {
+ guint i, random;
+ random = g_test_rand_int ();
+ string_list = gtk_string_list_new (NULL);
+ for (i = 0; i < MAX_SIZE; i++)
+ {
+ gtk_string_list_take (string_list, g_strdup_printf ("%u", random));
+ random = quick_random (random);
+ }
+ }
+
+ return G_LIST_MODEL (g_object_ref (string_list));
+}
+
+static void
+run_tests (const char * const *tests,
+ const char *test_name,
+ void (* test_func) (const char *name, GType type, gboolean incremental, GListModel *source,
GtkSorter *sorter, guint random))
+{
+ const char *suffixes[] = { "string", "tree", "filename" };
+ gsize i;
+
+ for (i = 0; i < G_N_ELEMENTS(suffixes); i++)
+ {
+ GListModel *source;
+ GtkSorter *sorter;
+ char *name;
+
+ name = g_strdup_printf ("%s-%s", test_name, suffixes[i]);
+ if (tests != NULL && !g_strv_contains (tests, name))
+ {
+ g_free (name);
+ continue;
+ }
+
+ switch (i)
+ {
+ case 0:
+ source = get_string_list ();
+ sorter = gtk_custom_sorter_new (compare_string_object, NULL, NULL);
+ break;
+
+ case 1:
+ source = get_file_infos ();
+ sorter = gtk_multi_sorter_new ();
+ gtk_multi_sorter_append (GTK_MULTI_SORTER (sorter), gtk_custom_sorter_new (count_comparisons,
NULL, NULL));
+ gtk_multi_sorter_append (GTK_MULTI_SORTER (sorter),
+ gtk_numeric_sorter_new (gtk_cclosure_expression_new (G_TYPE_BOOLEAN,
+ NULL,
+ 0,
+ NULL,
+ (GCallback)
file_info_is_directory,
+ NULL, NULL)));
+ gtk_multi_sorter_append (GTK_MULTI_SORTER (sorter),
+ gtk_numeric_sorter_new (gtk_cclosure_expression_new (G_TYPE_UINT64,
+ NULL,
+ 1,
+ (GtkExpression *[1])
{
+
gtk_constant_expression_new (G_TYPE_STRING, G_FILE_ATTRIBUTE_STANDARD_SIZE)
+ },
+ (GCallback)
g_file_info_get_attribute_uint64,
+ NULL, NULL)));
+ sorter = gtk_tree_list_row_sorter_new (sorter);
+ break;
+
+ case 2:
+ {
+ GListModel *infos = get_file_infos ();
+ source = G_LIST_MODEL (gtk_map_list_model_new (infos,
+ (GtkMapListModelMapFunc)
gtk_tree_list_row_get_item,
+ NULL, NULL));
+ sorter = gtk_string_sorter_new (
+ gtk_cclosure_expression_new (G_TYPE_STRING,
+ NULL,
+ 1,
+ (GtkExpression *[1]) {
+ gtk_constant_expression_new (G_TYPE_STRING,
G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME)
+ },
+ (GCallback) g_file_info_get_attribute_as_string,
+ NULL,
+ NULL));
+ g_object_unref (infos);
+ }
+ break;
+
+ default:
+ g_assert_not_reached ();
+ return;
+ }
+
+ run_test (source, sorter, tests, name, test_func);
+
+ g_free (name);
+ g_object_unref (sorter);
+ g_object_unref (source);
}
}
int
main (int argc, char *argv[])
{
- GtkStringList *source;
- guint random = g_random_int ();
- guint i;
const char * const *tests;
gtk_test_init (&argc, &argv);
- source = gtk_string_list_new (NULL);
- for (i = 0; i < MAX_SIZE; i++)
- {
- gtk_string_list_take (source, g_strdup_printf ("%u", random));
- random = quick_random (random);
- }
-
if (argc < 2)
tests = NULL;
else
tests = (const char **) argv + 1;
g_print ("# \"test\",\"model\",\"model size\",\"time\",\"max time\",\"comparisons\",\"changes\"\n");
- run_test (source, tests, "set-model", set_model);
- run_test (source, tests, "append-half", append_half);
- run_test (source, tests, "append-10th", append_10th);
- run_test (source, tests, "append-100th", append_100th);
- run_test (source, tests, "remove-half", remove_half);
- run_test (source, tests, "remove-10th", remove_10th);
- run_test (source, tests, "remove-100th", remove_100th);
- run_test (source, tests, "append-1", append_1);
- run_test (source, tests, "append-2", append_2);
- run_test (source, tests, "append-10", append_10);
- run_test (source, tests, "remove-1", remove_1);
- run_test (source, tests, "remove-2", remove_2);
- run_test (source, tests, "remove-10", remove_10);
+ run_tests (tests, "set-model", set_model);
+ run_tests (tests, "append-half", append_half);
+ run_tests (tests, "append-10th", append_10th);
+ run_tests (tests, "append-100th", append_100th);
+ run_tests (tests, "remove-half", remove_half);
+ run_tests (tests, "remove-10th", remove_10th);
+ run_tests (tests, "remove-100th", remove_100th);
+ run_tests (tests, "append-1", append_1);
+ run_tests (tests, "append-2", append_2);
+ run_tests (tests, "append-10", append_10);
+ run_tests (tests, "remove-1", remove_1);
+ run_tests (tests, "remove-2", remove_2);
+ run_tests (tests, "remove-10", remove_10);
+ run_tests (tests, "remove-10", remove_10);
+
return g_test_run ();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]