[gtk/wip/otte/sortlistmodel: 39/39] testsuite: Support different models



commit 69a18fa08bb114cb4c1aed6cee51cbdb9d91103a
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 and the treelistrow
    sorter.

 testsuite/gtk/sort-performance.c | 366 ++++++++++++++++++++++++++++++---------
 1 file changed, 284 insertions(+), 82 deletions(-)
---
diff --git a/testsuite/gtk/sort-performance.c b/testsuite/gtk/sort-performance.c
index 4228eaa867..c543900204 100644
--- a/testsuite/gtk/sort-performance.c
+++ b/testsuite/gtk/sort-performance.c
@@ -29,12 +29,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 +74,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 +110,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 +129,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 +168,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 +184,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 +195,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 +206,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 +217,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 +256,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 +272,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 +283,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 +294,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 +305,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 +347,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 +363,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 +374,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 +385,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 +396,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 +438,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 +454,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 +465,150 @@ 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 GListModel *
+create_directory_list (gpointer item,
+                       gpointer data)
+{
+  GFileInfo *file_info = G_FILE_INFO (item);
+  guint *counters = data;
+  GtkDirectoryList *dir;
+  GFile *file;
+
+  if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_DIRECTORY ||
+      g_file_info_get_is_symlink (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;
@@ -523,51 +632,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", "filesize" };
+  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_tree_list_row_sorter_new (gtk_string_sorter_new (gtk_cclosure_expression_new 
(G_TYPE_STRING, NULL, 1, (GtkExpression *[1]) { gtk_constant_expression_new (G_TYPE_STRING, 
"standard::display-name") }, (GCallback) g_file_info_get_attribute_as_string, NULL, NULL)));
+          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;
+
+        case 3:
+          {
+            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_numeric_sorter_new (gtk_cclosure_expression_new (G_TYPE_UINT64,
+                                                                          NULL,
+                                                                          1,
+                                                                          (GtkExpression *[1]) {
+                                                                            gtk_constant_expression_new 
(G_TYPE_UINT64, G_FILE_ATTRIBUTE_STANDARD_SIZE)
+                                                                          },
+                                                                          (GCallback) 
g_file_info_get_attribute_as_string,
+                                                                          NULL,
+                                                                          NULL));
+            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]