1 /* Extensive GtkTreeModelFilter tests.
2  * Copyright (C) 2009,2011  Kristian Rietveld  <kris@gtk.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <gtk/gtk.h>
19 #include <string.h>
20 
21 #include "treemodel.h"
22 #include "gtktreemodelrefcount.h"
23 
24 /* Left to do:
25  *   - Proper coverage checking to see if the unit tests cover
26  *     all possible cases.
27  *   - Check if the iterator stamp is incremented at the correct times.
28  *
29  * For more thorough testing:
30  *   - Test with randomized models.
31  *   - Extensively test a filter model wrapping a sort model,
32  *     or a sort model wrapping a filter model by:
33  *       # Checking structure.
34  *       # Checking for correct signals emissions.
35  *       # Checking correct reference counting.
36  *       # Tests should be done with the sort and filter model
37  *         in various filtering and sorting states.
38  */
39 
40 
41 /*
42  * Model creation
43  */
44 
45 #define LEVEL_LENGTH 5
46 
47 static void
create_tree_store_set_values(GtkTreeStore * store,GtkTreeIter * iter,gboolean visible)48 create_tree_store_set_values (GtkTreeStore *store,
49                               GtkTreeIter  *iter,
50                               gboolean      visible)
51 {
52   GtkTreePath *path;
53   char *path_string;
54 
55   path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), iter);
56   path_string = gtk_tree_path_to_string (path);
57 
58   gtk_tree_store_set (store, iter,
59                       0, path_string,
60                       1, visible,
61                       -1);
62 
63   gtk_tree_path_free (path);
64   g_free (path_string);
65 }
66 
67 static void
create_tree_store_recurse(int depth,GtkTreeStore * store,GtkTreeIter * parent,gboolean visible)68 create_tree_store_recurse (int           depth,
69                            GtkTreeStore *store,
70                            GtkTreeIter  *parent,
71                            gboolean      visible)
72 {
73   int i;
74 
75   for (i = 0; i < LEVEL_LENGTH; i++)
76     {
77       GtkTreeIter iter;
78 
79       gtk_tree_store_insert (store, &iter, parent, i);
80       create_tree_store_set_values (store, &iter, visible);
81 
82       if (depth > 0)
83         create_tree_store_recurse (depth - 1, store, &iter, visible);
84     }
85 }
86 
87 static GtkTreeStore *
create_tree_store(int depth,gboolean visible)88 create_tree_store (int      depth,
89                    gboolean visible)
90 {
91   GtkTreeStore *store;
92 
93   store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
94 
95   create_tree_store_recurse (depth, store, NULL, visible);
96 
97   return store;
98 }
99 
100 /*
101  * Fixture
102  */
103 
104 typedef struct
105 {
106   GtkWidget *tree_view;
107 
108   GtkTreeStore *store;
109   GtkTreeModelFilter *filter;
110 
111   SignalMonitor *monitor;
112 
113   guint block_signals : 1;
114 } FilterTest;
115 
116 
117 static void
filter_test_store_signal(FilterTest * fixture)118 filter_test_store_signal (FilterTest *fixture)
119 {
120   if (fixture->block_signals)
121     g_signal_stop_emission_by_name (fixture->store, "row-changed");
122 }
123 
124 
125 static void
filter_test_setup_generic(FilterTest * fixture,gconstpointer test_data,int depth,gboolean empty,gboolean unfiltered)126 filter_test_setup_generic (FilterTest    *fixture,
127                            gconstpointer  test_data,
128                            int            depth,
129                            gboolean       empty,
130                            gboolean       unfiltered)
131 {
132   const GtkTreePath *vroot = test_data;
133   GtkTreeModel *filter;
134 
135   fixture->store = create_tree_store (depth, !empty);
136 
137   g_signal_connect_swapped (fixture->store, "row-changed",
138                             G_CALLBACK (filter_test_store_signal), fixture);
139 
140   /* Please forgive me for casting const away. */
141   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture->store),
142                                       (GtkTreePath *)vroot);
143   fixture->filter = GTK_TREE_MODEL_FILTER (filter);
144 
145   if (!unfiltered)
146     gtk_tree_model_filter_set_visible_column (fixture->filter, 1);
147 
148   /* We need a tree view that's listening to get ref counting from that
149    * side.
150    */
151   fixture->tree_view = gtk_tree_view_new_with_model (filter);
152 
153   fixture->monitor = signal_monitor_new (filter);
154 }
155 
156 static void
filter_test_setup_expand_root(FilterTest * fixture)157 filter_test_setup_expand_root (FilterTest *fixture)
158 {
159   int i;
160   GtkTreePath *path;
161 
162   path = gtk_tree_path_new_from_indices (0, -1);
163 
164   for (i = 0; i < LEVEL_LENGTH; i++)
165     {
166       gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view),
167                                 path, FALSE);
168       gtk_tree_path_next (path);
169     }
170   gtk_tree_path_free (path);
171 }
172 
173 static void
filter_test_setup(FilterTest * fixture,gconstpointer test_data)174 filter_test_setup (FilterTest    *fixture,
175                    gconstpointer  test_data)
176 {
177   filter_test_setup_generic (fixture, test_data, 3, FALSE, FALSE);
178 }
179 
180 static void
filter_test_setup_empty(FilterTest * fixture,gconstpointer test_data)181 filter_test_setup_empty (FilterTest    *fixture,
182                          gconstpointer  test_data)
183 {
184   filter_test_setup_generic (fixture, test_data, 3, TRUE, FALSE);
185 }
186 
187 static void
filter_test_setup_unfiltered(FilterTest * fixture,gconstpointer test_data)188 filter_test_setup_unfiltered (FilterTest    *fixture,
189                               gconstpointer  test_data)
190 {
191   filter_test_setup_generic (fixture, test_data, 3, FALSE, TRUE);
192 }
193 
194 static void
filter_test_setup_unfiltered_root_expanded(FilterTest * fixture,gconstpointer test_data)195 filter_test_setup_unfiltered_root_expanded (FilterTest    *fixture,
196                                             gconstpointer  test_data)
197 {
198   filter_test_setup_unfiltered (fixture, test_data);
199   filter_test_setup_expand_root (fixture);
200 }
201 
202 static void
filter_test_setup_empty_unfiltered(FilterTest * fixture,gconstpointer test_data)203 filter_test_setup_empty_unfiltered (FilterTest    *fixture,
204                                     gconstpointer  test_data)
205 {
206   filter_test_setup_generic (fixture, test_data, 3, TRUE, TRUE);
207 }
208 
209 static void
filter_test_setup_empty_unfiltered_root_expanded(FilterTest * fixture,gconstpointer test_data)210 filter_test_setup_empty_unfiltered_root_expanded (FilterTest    *fixture,
211                                                   gconstpointer  test_data)
212 {
213   filter_test_setup_empty_unfiltered (fixture, test_data);
214   filter_test_setup_expand_root (fixture);
215 }
216 
217 static GtkTreePath *
strip_virtual_root(GtkTreePath * path,GtkTreePath * root_path)218 strip_virtual_root (GtkTreePath *path,
219                     GtkTreePath *root_path)
220 {
221   GtkTreePath *real_path;
222 
223   if (root_path)
224     {
225       int j;
226       int depth = gtk_tree_path_get_depth (path);
227       int root_depth = gtk_tree_path_get_depth (root_path);
228 
229       real_path = gtk_tree_path_new ();
230 
231       for (j = 0; j < depth - root_depth; j++)
232         gtk_tree_path_append_index (real_path,
233                                     gtk_tree_path_get_indices (path)[root_depth + j]);
234     }
235   else
236     real_path = gtk_tree_path_copy (path);
237 
238   return real_path;
239 }
240 
241 static int
count_visible(FilterTest * fixture,GtkTreePath * store_path)242 count_visible (FilterTest  *fixture,
243                GtkTreePath *store_path)
244 {
245   int i;
246   int n_visible = 0;
247   GtkTreeIter iter;
248 
249   gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
250                            &iter, store_path);
251 
252   for (i = 0; i < LEVEL_LENGTH; i++)
253     {
254       gboolean visible;
255 
256       gtk_tree_model_get (GTK_TREE_MODEL (fixture->store), &iter,
257                           1, &visible,
258                           -1);
259 
260       if (visible)
261         n_visible++;
262     }
263 
264   return n_visible;
265 }
266 
267 static void
filter_test_append_refilter_signals_recurse(FilterTest * fixture,GtkTreePath * store_path,GtkTreePath * filter_path,int depth,GtkTreePath * root_path)268 filter_test_append_refilter_signals_recurse (FilterTest  *fixture,
269                                              GtkTreePath *store_path,
270                                              GtkTreePath *filter_path,
271                                              int          depth,
272                                              GtkTreePath *root_path)
273 {
274   int i;
275   int rows_deleted = 0;
276   GtkTreeIter iter;
277 
278   gtk_tree_path_down (store_path);
279   gtk_tree_path_down (filter_path);
280 
281   gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
282                            &iter, store_path);
283 
284   for (i = 0; i < LEVEL_LENGTH; i++)
285     {
286       gboolean visible;
287       GtkTreePath *real_path;
288 
289       gtk_tree_model_get (GTK_TREE_MODEL (fixture->store), &iter,
290                           1, &visible,
291                           -1);
292 
293       if (root_path &&
294           (!gtk_tree_path_is_descendant (store_path, root_path)
295            || !gtk_tree_path_compare (store_path, root_path)))
296         {
297           if (!gtk_tree_path_compare (store_path, root_path))
298             {
299               if (depth > 1
300                   && gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->store),
301                                                     &iter))
302                 {
303                   GtkTreePath *store_copy;
304                   GtkTreePath *filter_copy;
305 
306                   store_copy = gtk_tree_path_copy (store_path);
307                   filter_copy = gtk_tree_path_copy (filter_path);
308                   filter_test_append_refilter_signals_recurse (fixture,
309                                                                store_copy,
310                                                                filter_copy,
311                                                                depth - 1,
312                                                                root_path);
313                   gtk_tree_path_free (store_copy);
314                   gtk_tree_path_free (filter_copy);
315                 }
316             }
317 
318           gtk_tree_path_next (store_path);
319           gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
320 
321           if (visible)
322             gtk_tree_path_next (filter_path);
323 
324           continue;
325         }
326 
327       real_path = strip_virtual_root (filter_path, root_path);
328 
329       if (visible)
330         {
331           /* This row will be inserted */
332           signal_monitor_append_signal_path (fixture->monitor, ROW_CHANGED,
333                                              real_path);
334 
335           if (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->store),
336                                              &iter))
337             {
338               signal_monitor_append_signal_path (fixture->monitor,
339                                                  ROW_HAS_CHILD_TOGGLED,
340                                                  real_path);
341 
342               if (depth > 1)
343                 {
344                   GtkTreePath *store_copy;
345                   GtkTreePath *filter_copy;
346 
347                   store_copy = gtk_tree_path_copy (store_path);
348                   filter_copy = gtk_tree_path_copy (filter_path);
349                   filter_test_append_refilter_signals_recurse (fixture,
350                                                                store_copy,
351                                                                filter_copy,
352                                                                depth - 1,
353                                                                root_path);
354                   gtk_tree_path_free (store_copy);
355                   gtk_tree_path_free (filter_copy);
356                 }
357               else if (depth == 1)
358                 {
359                   GtkTreePath *tmp_path;
360 
361                   /* If all child rows are invisible, then the last row to
362                    * become invisible will emit row-has-child-toggled on the
363                    * parent.
364                    */
365 
366                   tmp_path = gtk_tree_path_copy (store_path);
367                   gtk_tree_path_append_index (tmp_path, 0);
368 
369                   if (count_visible (fixture, tmp_path) == 0)
370                     signal_monitor_append_signal_path (fixture->monitor,
371                                                        ROW_HAS_CHILD_TOGGLED,
372                                                        real_path);
373 
374                   gtk_tree_path_free (tmp_path);
375                 }
376             }
377 
378           gtk_tree_path_next (filter_path);
379         }
380       else
381         {
382           /* This row will be deleted */
383           rows_deleted++;
384           signal_monitor_append_signal_path (fixture->monitor, ROW_DELETED,
385                                              real_path);
386         }
387 
388       gtk_tree_path_free (real_path);
389 
390       gtk_tree_path_next (store_path);
391       gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
392     }
393 
394   if (rows_deleted == LEVEL_LENGTH
395       && gtk_tree_path_get_depth (filter_path) > 1)
396     {
397       GtkTreePath *real_path;
398 
399       gtk_tree_path_up (store_path);
400       gtk_tree_path_up (filter_path);
401 
402       /* A row-has-child-toggled will be emitted on the parent */
403       if (!root_path
404           || (root_path
405               && gtk_tree_path_is_descendant (store_path, root_path)
406               && gtk_tree_path_compare (store_path, root_path)))
407         {
408           real_path = strip_virtual_root (filter_path, root_path);
409           signal_monitor_append_signal_path (fixture->monitor,
410                                              ROW_HAS_CHILD_TOGGLED,
411                                              real_path);
412 
413           gtk_tree_path_free (real_path);
414         }
415     }
416 }
417 
418 static void
filter_test_append_refilter_signals(FilterTest * fixture,int depth)419 filter_test_append_refilter_signals (FilterTest *fixture,
420                                      int         depth)
421 {
422   /* A special function that walks the tree store like the
423    * model validation functions below.
424    */
425   GtkTreePath *path;
426   GtkTreePath *filter_path;
427 
428   path = gtk_tree_path_new ();
429   filter_path = gtk_tree_path_new ();
430   filter_test_append_refilter_signals_recurse (fixture,
431                                                path,
432                                                filter_path,
433                                                depth,
434                                                NULL);
435   gtk_tree_path_free (path);
436   gtk_tree_path_free (filter_path);
437 }
438 
439 static void
filter_test_append_refilter_signals_with_vroot(FilterTest * fixture,int depth,GtkTreePath * root_path)440 filter_test_append_refilter_signals_with_vroot (FilterTest  *fixture,
441                                                 int          depth,
442                                                 GtkTreePath *root_path)
443 {
444   /* A special function that walks the tree store like the
445    * model validation functions below.
446    */
447   GtkTreePath *path;
448   GtkTreePath *filter_path;
449 
450   path = gtk_tree_path_new ();
451   filter_path = gtk_tree_path_new ();
452   filter_test_append_refilter_signals_recurse (fixture,
453                                                path,
454                                                filter_path,
455                                                depth,
456                                                root_path);
457   gtk_tree_path_free (path);
458   gtk_tree_path_free (filter_path);
459 }
460 
461 static void
filter_test_enable_filter(FilterTest * fixture)462 filter_test_enable_filter (FilterTest *fixture)
463 {
464   gtk_tree_model_filter_set_visible_column (fixture->filter, 1);
465   gtk_tree_model_filter_refilter (fixture->filter);
466 }
467 
468 static void
filter_test_block_signals(FilterTest * fixture)469 filter_test_block_signals (FilterTest *fixture)
470 {
471   fixture->block_signals = TRUE;
472 }
473 
474 static void
filter_test_unblock_signals(FilterTest * fixture)475 filter_test_unblock_signals (FilterTest *fixture)
476 {
477   fixture->block_signals = FALSE;
478 }
479 
480 static void
filter_test_teardown(FilterTest * fixture,gconstpointer test_data)481 filter_test_teardown (FilterTest    *fixture,
482                       gconstpointer  test_data)
483 {
484   signal_monitor_free (fixture->monitor);
485 
486   g_object_unref (g_object_ref_sink (fixture->tree_view));
487 
488   g_object_unref (fixture->filter);
489   g_object_unref (fixture->store);
490 }
491 
492 /*
493  * Model structure validation
494  */
495 
496 static void
check_filter_model_recurse(FilterTest * fixture,GtkTreePath * store_parent_path,GtkTreePath * filter_parent_path)497 check_filter_model_recurse (FilterTest  *fixture,
498                             GtkTreePath *store_parent_path,
499                             GtkTreePath *filter_parent_path)
500 {
501   int i;
502   GtkTreeIter store_iter;
503   GtkTreeIter filter_iter;
504   gboolean store_has_next, filter_has_next;
505 
506   gtk_tree_path_down (store_parent_path);
507   gtk_tree_path_down (filter_parent_path);
508 
509   store_has_next = gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
510                                             &store_iter, store_parent_path);
511   filter_has_next = gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->filter),
512                                              &filter_iter, filter_parent_path);
513 
514   for (i = 0; i < LEVEL_LENGTH; i++)
515     {
516       gboolean visible;
517 
518       g_assert_true (store_has_next);
519 
520       gtk_tree_model_get (GTK_TREE_MODEL (fixture->store),
521                           &store_iter,
522                           1, &visible,
523                           -1);
524 
525       if (visible)
526         {
527           GtkTreePath *tmp;
528           char *filter_str, *store_str;
529 
530           g_assert_true (filter_has_next);
531 
532           /* Verify path */
533           tmp = gtk_tree_model_get_path (GTK_TREE_MODEL (fixture->filter),
534                                          &filter_iter);
535           g_assert_cmpint (gtk_tree_path_compare (tmp, filter_parent_path), ==, 0);
536 
537           /* Verify model content */
538           gtk_tree_model_get (GTK_TREE_MODEL (fixture->store),
539                               &store_iter,
540                               0, &store_str,
541                               -1);
542           gtk_tree_model_get (GTK_TREE_MODEL (fixture->filter),
543                               &filter_iter,
544                               0, &filter_str,
545                               -1);
546 
547           g_assert_cmpint (g_strcmp0 (store_str, filter_str), ==, 0);
548 
549           g_free (store_str);
550           g_free (filter_str);
551 
552           if (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->filter),
553                                              &filter_iter))
554             {
555               g_assert_true (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (fixture->store), &store_iter));
556 
557               check_filter_model_recurse (fixture,
558                                           gtk_tree_path_copy (store_parent_path),
559                                           tmp);
560             }
561           else
562             /* Only when we do not recurse we need to free tmp */
563             gtk_tree_path_free (tmp);
564 
565           gtk_tree_path_next (filter_parent_path);
566           filter_has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->filter), &filter_iter);
567         }
568 
569       gtk_tree_path_next (store_parent_path);
570       store_has_next = gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &store_iter);
571     }
572 
573   /* Both models should have no more content! */
574   g_assert_false (store_has_next);
575   g_assert_false (filter_has_next);
576 
577   gtk_tree_path_free (store_parent_path);
578   gtk_tree_path_free (filter_parent_path);
579 }
580 
581 static void
check_filter_model(FilterTest * fixture)582 check_filter_model (FilterTest *fixture)
583 {
584   GtkTreePath *path;
585 
586   if (fixture->monitor)
587     signal_monitor_assert_is_empty (fixture->monitor);
588 
589   path = gtk_tree_path_new ();
590 
591   check_filter_model_recurse (fixture, path, gtk_tree_path_copy (path));
592 }
593 
594 static void
check_filter_model_with_root(FilterTest * fixture,GtkTreePath * path)595 check_filter_model_with_root (FilterTest  *fixture,
596                               GtkTreePath *path)
597 {
598   if (fixture->monitor)
599     signal_monitor_assert_is_empty (fixture->monitor);
600 
601   check_filter_model_recurse (fixture,
602                               gtk_tree_path_copy (path),
603                               gtk_tree_path_new ());
604 }
605 
606 /* Helpers */
607 
608 static void
check_level_length(GtkTreeModelFilter * filter,const char * level,const int expected_length)609 check_level_length (GtkTreeModelFilter *filter,
610                     const char         *level,
611                     const int           expected_length)
612 {
613   if (!level)
614     {
615       int model_length;
616 
617       model_length = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (filter), NULL);
618       g_assert_cmpint (model_length, ==, expected_length);
619     }
620   else
621     {
622       int model_length;
623       gboolean retrieved_iter = FALSE;
624       GtkTreeIter iter;
625 
626       retrieved_iter = gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (filter),
627                                                             &iter, level);
628       g_assert_true (retrieved_iter);
629       model_length = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (filter), &iter);
630       g_assert_cmpint (model_length, ==, expected_length);
631     }
632 }
633 
634 static void
set_path_visibility(FilterTest * fixture,const char * path,gboolean visible)635 set_path_visibility (FilterTest  *fixture,
636                      const char *path,
637                      gboolean     visible)
638 {
639   GtkTreeIter store_iter;
640 
641   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
642                                        &store_iter, path);
643   gtk_tree_store_set (fixture->store, &store_iter,
644                       1, visible,
645                       -1);
646 }
647 
648 #if 0
649 static void
650 insert_path_with_visibility (FilterTest  *fixture,
651                              const char *path_string,
652                              gboolean     visible)
653 {
654   int position;
655   GtkTreePath *path;
656   GtkTreeIter parent, iter;
657 
658   path = gtk_tree_path_new_from_string (path_string);
659   position = gtk_tree_path_get_indices (path)[gtk_tree_path_get_depth (path)];
660   gtk_tree_path_up (path);
661 
662   if (gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store), &parent, path))
663     {
664       gtk_tree_store_insert (fixture->store, &iter, &parent, position);
665       create_tree_store_set_values (fixture->store, &iter, visible);
666     }
667   gtk_tree_path_free (path);
668 }
669 #endif
670 
671 /*
672  * The actual tests.
673  */
674 
675 static void
verify_test_suite(FilterTest * fixture,gconstpointer user_data)676 verify_test_suite (FilterTest    *fixture,
677                    gconstpointer  user_data)
678 {
679   check_filter_model (fixture);
680 }
681 
682 static void
verify_test_suite_vroot(FilterTest * fixture,gconstpointer user_data)683 verify_test_suite_vroot (FilterTest    *fixture,
684                          gconstpointer  user_data)
685 {
686   check_filter_model_with_root (fixture, (GtkTreePath *)user_data);
687 }
688 
689 
690 static void
filled_hide_root_level(FilterTest * fixture,gconstpointer user_data)691 filled_hide_root_level (FilterTest    *fixture,
692                         gconstpointer  user_data)
693 {
694   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "2");
695   set_path_visibility (fixture, "2", FALSE);
696   check_filter_model (fixture);
697   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
698 
699   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
700   set_path_visibility (fixture, "0", FALSE);
701   check_filter_model (fixture);
702   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
703 
704   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "2");
705   set_path_visibility (fixture, "4", FALSE);
706   check_filter_model (fixture);
707   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 3);
708 
709 
710   /* Hide remaining */
711   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
712   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
713 
714   set_path_visibility (fixture, "1", FALSE);
715   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
716 
717   set_path_visibility (fixture, "3", FALSE);
718   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 5);
719 
720   check_filter_model (fixture);
721 
722   /* Show some */
723   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
724   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
725   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "1");
726   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "1");
727 
728   set_path_visibility (fixture, "1", TRUE);
729   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
730 
731   set_path_visibility (fixture, "3", TRUE);
732   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 3);
733 
734   check_filter_model (fixture);
735 }
736 
737 static void
filled_hide_child_levels(FilterTest * fixture,gconstpointer user_data)738 filled_hide_child_levels (FilterTest    *fixture,
739                           gconstpointer  user_data)
740 {
741   set_path_visibility (fixture, "0:2", FALSE);
742   check_filter_model (fixture);
743   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
744   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 1);
745 
746   set_path_visibility (fixture, "0:4", FALSE);
747   check_filter_model (fixture);
748   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
749   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
750 
751   set_path_visibility (fixture, "0:4:3", FALSE);
752   check_filter_model (fixture);
753   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
754   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
755 
756   set_path_visibility (fixture, "0:4:0", FALSE);
757   set_path_visibility (fixture, "0:4:1", FALSE);
758   set_path_visibility (fixture, "0:4:2", FALSE);
759   set_path_visibility (fixture, "0:4:4", FALSE);
760   check_filter_model (fixture);
761   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
762   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
763 
764   /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
765   set_path_visibility (fixture, "0:4", TRUE);
766   check_filter_model (fixture);
767   check_level_length (fixture->filter, "0:3", 0);
768 
769   set_path_visibility (fixture, "0:2", TRUE);
770   check_filter_model (fixture);
771   check_level_length (fixture->filter, "0:2", LEVEL_LENGTH);
772   check_level_length (fixture->filter, "0:3", LEVEL_LENGTH);
773   check_level_length (fixture->filter, "0:4", 0);
774 
775   /* Once 0:4:0 got inserted, 0:4 became a parent.  Because 0:4 is
776    * not visible, not signals are emitted.
777    */
778   set_path_visibility (fixture, "0:4:2", TRUE);
779   set_path_visibility (fixture, "0:4:4", TRUE);
780   signal_monitor_assert_is_empty (fixture->monitor);
781   check_level_length (fixture->filter, "0:4", 2);
782 }
783 
784 static void
filled_hide_child_levels_root_expanded(FilterTest * fixture,gconstpointer user_data)785 filled_hide_child_levels_root_expanded (FilterTest    *fixture,
786                                         gconstpointer  user_data)
787 {
788   GtkTreePath *path;
789 
790   path = gtk_tree_path_new_from_indices (0, -1);
791   gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), path, FALSE);
792   gtk_tree_path_free (path);
793 
794   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0:2");
795   set_path_visibility (fixture, "0:2", FALSE);
796   check_filter_model (fixture);
797   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
798   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 1);
799 
800   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0:3");
801   set_path_visibility (fixture, "0:4", FALSE);
802   check_filter_model (fixture);
803   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
804   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
805 
806   set_path_visibility (fixture, "0:4:3", FALSE);
807   check_filter_model (fixture);
808   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
809   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
810 
811   set_path_visibility (fixture, "0:4:0", FALSE);
812   set_path_visibility (fixture, "0:4:1", FALSE);
813   set_path_visibility (fixture, "0:4:2", FALSE);
814   set_path_visibility (fixture, "0:4:4", FALSE);
815   check_filter_model (fixture);
816   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
817   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
818 
819   /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
820   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:3");
821   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:3");
822   set_path_visibility (fixture, "0:4", TRUE);
823   check_filter_model (fixture);
824   check_level_length (fixture->filter, "0:3", 0);
825 
826   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:2");
827   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:2");
828   set_path_visibility (fixture, "0:2", TRUE);
829   check_filter_model (fixture);
830   check_level_length (fixture->filter, "0:2", LEVEL_LENGTH);
831   check_level_length (fixture->filter, "0:3", LEVEL_LENGTH);
832   check_level_length (fixture->filter, "0:4", 0);
833 
834   /* has-child-toggled for 0:4 is required.  */
835   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:4");
836   set_path_visibility (fixture, "0:4:2", TRUE);
837   set_path_visibility (fixture, "0:4:4", TRUE);
838   signal_monitor_assert_is_empty (fixture->monitor);
839   check_level_length (fixture->filter, "0:4", 2);
840 }
841 
842 
843 static void
filled_vroot_hide_root_level(FilterTest * fixture,gconstpointer user_data)844 filled_vroot_hide_root_level (FilterTest    *fixture,
845                               gconstpointer  user_data)
846 {
847   GtkTreePath *path = (GtkTreePath *)user_data;
848 
849   /* These changes do not affect the filter's root level */
850   set_path_visibility (fixture, "0", FALSE);
851   check_filter_model_with_root (fixture, path);
852   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
853   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
854 
855   set_path_visibility (fixture, "4", FALSE);
856   check_filter_model_with_root (fixture, path);
857   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
858   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
859 
860   /* Even though we set the virtual root parent node to FALSE,
861    * the virtual root contents remain.
862    */
863   set_path_visibility (fixture, "2", FALSE);
864   check_filter_model_with_root (fixture, path);
865   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
866   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
867 
868   /* No change */
869   set_path_visibility (fixture, "1", FALSE);
870   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
871   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
872 
873   set_path_visibility (fixture, "3", FALSE);
874   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
875   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
876 
877   check_filter_model_with_root (fixture, path);
878 
879   /* Show some */
880   set_path_visibility (fixture, "2", TRUE);
881   check_filter_model_with_root (fixture, path);
882   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
883   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
884 
885   set_path_visibility (fixture, "1", TRUE);
886   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
887   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
888 
889   set_path_visibility (fixture, "3", TRUE);
890   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
891   check_level_length (fixture->filter, "0", LEVEL_LENGTH);
892 
893   check_filter_model_with_root (fixture, path);
894 
895   /* Now test changes in the virtual root level */
896   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "2");
897   set_path_visibility (fixture, "2:2", FALSE);
898   check_filter_model_with_root (fixture, path);
899   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
900 
901   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "3");
902   set_path_visibility (fixture, "2:4", FALSE);
903   check_filter_model_with_root (fixture, path);
904   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
905 
906   set_path_visibility (fixture, "1:4", FALSE);
907   check_filter_model_with_root (fixture, path);
908   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
909 
910   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "3");
911   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "3");
912   set_path_visibility (fixture, "2:4", TRUE);
913   check_filter_model_with_root (fixture, path);
914   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
915 
916   set_path_visibility (fixture, "2", FALSE);
917   check_filter_model_with_root (fixture, path);
918   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
919 
920   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
921   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
922   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
923   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
924   set_path_visibility (fixture, "2:0", FALSE);
925   set_path_visibility (fixture, "2:1", FALSE);
926   set_path_visibility (fixture, "2:2", FALSE);
927   set_path_visibility (fixture, "2:3", FALSE);
928   set_path_visibility (fixture, "2:4", FALSE);
929   check_filter_model_with_root (fixture, path);
930   check_level_length (fixture->filter, NULL, 0);
931 
932   set_path_visibility (fixture, "2", TRUE);
933   check_filter_model_with_root (fixture, path);
934   check_level_length (fixture->filter, NULL, 0);
935 
936   set_path_visibility (fixture, "1:4", FALSE);
937   check_filter_model_with_root (fixture, path);
938   check_level_length (fixture->filter, NULL, 0);
939 
940   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
941   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
942   set_path_visibility (fixture, "2:4", TRUE);
943   check_filter_model_with_root (fixture, path);
944   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 4);
945 
946   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
947   set_path_visibility (fixture, "2:4", FALSE);
948   check_filter_model_with_root (fixture, path);
949   check_level_length (fixture->filter, NULL, 0);
950 
951   set_path_visibility (fixture, "2", FALSE);
952   check_filter_model_with_root (fixture, path);
953   check_level_length (fixture->filter, NULL, 0);
954 
955   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
956   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
957   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "1");
958   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "1");
959   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "2");
960   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
961   set_path_visibility (fixture, "2:0", TRUE);
962   set_path_visibility (fixture, "2:1", TRUE);
963   set_path_visibility (fixture, "2:2", TRUE);
964   check_filter_model_with_root (fixture, path);
965   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
966 
967   set_path_visibility (fixture, "2", TRUE);
968   check_filter_model_with_root (fixture, path);
969   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 2);
970 }
971 
972 static void
filled_vroot_hide_child_levels(FilterTest * fixture,gconstpointer user_data)973 filled_vroot_hide_child_levels (FilterTest    *fixture,
974                                 gconstpointer  user_data)
975 {
976   GtkTreePath *path = (GtkTreePath *)user_data;
977 
978   set_path_visibility (fixture, "2:0:2", FALSE);
979   check_filter_model_with_root (fixture, path);
980   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
981   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 1);
982 
983   set_path_visibility (fixture, "2:0:4", FALSE);
984   check_filter_model_with_root (fixture, path);
985   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
986   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
987 
988   set_path_visibility (fixture, "2:0:4:3", FALSE);
989   check_filter_model_with_root (fixture, path);
990   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
991   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
992 
993   set_path_visibility (fixture, "2:0:4:0", FALSE);
994   set_path_visibility (fixture, "2:0:4:1", FALSE);
995   set_path_visibility (fixture, "2:0:4:2", FALSE);
996   set_path_visibility (fixture, "2:0:4:4", FALSE);
997   check_filter_model_with_root (fixture, path);
998   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
999   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1000 
1001   /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
1002   set_path_visibility (fixture, "2:0:4", TRUE);
1003   check_filter_model_with_root (fixture, path);
1004   check_level_length (fixture->filter, "0:3", 0);
1005 
1006   set_path_visibility (fixture, "2:0:2", TRUE);
1007   check_filter_model_with_root (fixture, path);
1008   check_level_length (fixture->filter, "0:2", LEVEL_LENGTH);
1009   check_level_length (fixture->filter, "0:3", LEVEL_LENGTH);
1010   check_level_length (fixture->filter, "0:4", 0);
1011 
1012   /* Once 0:4:0 got inserted, 0:4 became a parent. However, 0:4 is not
1013    * visible, so no signal should be emitted.
1014    */
1015   set_path_visibility (fixture, "2:0:4:2", TRUE);
1016   set_path_visibility (fixture, "2:0:4:4", TRUE);
1017   check_level_length (fixture->filter, "0:4", 2);
1018   signal_monitor_assert_is_empty (fixture->monitor);
1019 }
1020 
1021 static void
filled_vroot_hide_child_levels_root_expanded(FilterTest * fixture,gconstpointer user_data)1022 filled_vroot_hide_child_levels_root_expanded (FilterTest    *fixture,
1023                                               gconstpointer  user_data)
1024 {
1025   GtkTreePath *path = (GtkTreePath *)user_data;
1026   GtkTreePath *tmp_path;
1027 
1028   tmp_path = gtk_tree_path_new_from_indices (0, -1);
1029   gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), tmp_path, FALSE);
1030   gtk_tree_path_free (tmp_path);
1031 
1032   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0:2");
1033   set_path_visibility (fixture, "2:0:2", FALSE);
1034   check_filter_model_with_root (fixture, path);
1035   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1036   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 1);
1037 
1038   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0:3");
1039   set_path_visibility (fixture, "2:0:4", FALSE);
1040   check_filter_model_with_root (fixture, path);
1041   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1042   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1043 
1044   set_path_visibility (fixture, "2:0:4:3", FALSE);
1045   check_filter_model_with_root (fixture, path);
1046   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1047   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1048 
1049   set_path_visibility (fixture, "2:0:4:0", FALSE);
1050   set_path_visibility (fixture, "2:0:4:1", FALSE);
1051   set_path_visibility (fixture, "2:0:4:2", FALSE);
1052   set_path_visibility (fixture, "2:0:4:4", FALSE);
1053   check_filter_model_with_root (fixture, path);
1054   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1055   check_level_length (fixture->filter, "0", LEVEL_LENGTH - 2);
1056 
1057   /* Since "0:2" is hidden, "0:4" must be "0:3" in the filter model */
1058   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:3");
1059   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:3");
1060   set_path_visibility (fixture, "2:0:4", TRUE);
1061   check_filter_model_with_root (fixture, path);
1062   check_level_length (fixture->filter, "0:3", 0);
1063 
1064   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0:2");
1065   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:2");
1066   set_path_visibility (fixture, "2:0:2", TRUE);
1067   check_filter_model_with_root (fixture, path);
1068   check_level_length (fixture->filter, "0:2", LEVEL_LENGTH);
1069   check_level_length (fixture->filter, "0:3", LEVEL_LENGTH);
1070   check_level_length (fixture->filter, "0:4", 0);
1071 
1072   /* Once 0:4:0 got inserted, 0:4 became a parent */
1073   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0:4");
1074   set_path_visibility (fixture, "2:0:4:2", TRUE);
1075   set_path_visibility (fixture, "2:0:4:4", TRUE);
1076   check_level_length (fixture->filter, "0:4", 2);
1077   signal_monitor_assert_is_empty (fixture->monitor);
1078 }
1079 
1080 static void
empty_show_nodes(FilterTest * fixture,gconstpointer user_data)1081 empty_show_nodes (FilterTest    *fixture,
1082                   gconstpointer  user_data)
1083 {
1084   check_filter_model (fixture);
1085   check_level_length (fixture->filter, NULL, 0);
1086 
1087   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1088   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1089   set_path_visibility (fixture, "3", TRUE);
1090   check_filter_model (fixture);
1091   check_level_length (fixture->filter, NULL, 1);
1092   check_level_length (fixture->filter, "0", 0);
1093 
1094   set_path_visibility (fixture, "3:2:2", TRUE);
1095   check_filter_model (fixture);
1096   check_level_length (fixture->filter, NULL, 1);
1097   check_level_length (fixture->filter, "0", 0);
1098 
1099   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1100   set_path_visibility (fixture, "3:2", TRUE);
1101   check_filter_model (fixture);
1102   check_level_length (fixture->filter, NULL, 1);
1103   check_level_length (fixture->filter, "0", 1);
1104   check_level_length (fixture->filter, "0:0", 1);
1105   check_level_length (fixture->filter, "0:0:0", 0);
1106 
1107   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1108   set_path_visibility (fixture, "3", FALSE);
1109   check_filter_model (fixture);
1110   check_level_length (fixture->filter, NULL, 0);
1111 
1112   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1113   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1114   set_path_visibility (fixture, "3:2:1", TRUE);
1115   set_path_visibility (fixture, "3", TRUE);
1116   check_filter_model (fixture);
1117   check_level_length (fixture->filter, NULL, 1);
1118   check_level_length (fixture->filter, "0", 1);
1119   check_level_length (fixture->filter, "0:0", 2);
1120   check_level_length (fixture->filter, "0:0:0", 0);
1121 }
1122 
1123 static void
empty_show_multiple_nodes(FilterTest * fixture,gconstpointer user_data)1124 empty_show_multiple_nodes (FilterTest    *fixture,
1125                            gconstpointer  user_data)
1126 {
1127   GtkTreeIter iter;
1128   GtkTreePath *changed_path;
1129 
1130   check_filter_model (fixture);
1131   check_level_length (fixture->filter, NULL, 0);
1132 
1133   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1134   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1135   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "1");
1136   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "1");
1137 
1138   /* We simulate a change in visible func condition with this.  The
1139    * visibility state of multiple nodes changes at once, we emit row-changed
1140    * for these nodes (and others) after that.
1141    */
1142   filter_test_block_signals (fixture);
1143   set_path_visibility (fixture, "3", TRUE);
1144   set_path_visibility (fixture, "4", TRUE);
1145   filter_test_unblock_signals (fixture);
1146 
1147   changed_path = gtk_tree_path_new ();
1148   gtk_tree_path_append_index (changed_path, 2);
1149   gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
1150                            &iter, changed_path);
1151   /* Invisible node - so no signals expected */
1152   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1153                               changed_path, &iter);
1154 
1155   gtk_tree_path_next (changed_path);
1156   gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1157   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1158                               changed_path, &iter);
1159 
1160   gtk_tree_path_next (changed_path);
1161   gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1162   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1163                               changed_path, &iter);
1164 
1165   gtk_tree_path_free (changed_path);
1166 
1167   check_filter_model (fixture);
1168   check_level_length (fixture->filter, NULL, 2);
1169   check_level_length (fixture->filter, "0", 0);
1170 
1171   set_path_visibility (fixture, "3:2:2", TRUE);
1172   check_filter_model (fixture);
1173   check_level_length (fixture->filter, NULL, 2);
1174   check_level_length (fixture->filter, "0", 0);
1175 
1176   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1177   set_path_visibility (fixture, "3:2", TRUE);
1178   check_filter_model (fixture);
1179   check_level_length (fixture->filter, NULL, 2);
1180   check_level_length (fixture->filter, "0", 1);
1181   check_level_length (fixture->filter, "0:0", 1);
1182   check_level_length (fixture->filter, "0:0:0", 0);
1183 
1184   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1185   set_path_visibility (fixture, "3", FALSE);
1186   check_filter_model (fixture);
1187   check_level_length (fixture->filter, NULL, 1);
1188 
1189   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1190   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1191   set_path_visibility (fixture, "3:2:1", TRUE);
1192   set_path_visibility (fixture, "3", TRUE);
1193   check_filter_model (fixture);
1194   check_level_length (fixture->filter, NULL, 2);
1195   check_level_length (fixture->filter, "0", 1);
1196   check_level_length (fixture->filter, "0:0", 2);
1197   check_level_length (fixture->filter, "0:0:0", 0);
1198 }
1199 
1200 static void
empty_vroot_show_nodes(FilterTest * fixture,gconstpointer user_data)1201 empty_vroot_show_nodes (FilterTest    *fixture,
1202                         gconstpointer  user_data)
1203 {
1204   GtkTreePath *path = (GtkTreePath *)user_data;
1205 
1206   check_filter_model_with_root (fixture, path);
1207   check_level_length (fixture->filter, NULL, 0);
1208 
1209   set_path_visibility (fixture, "2", TRUE);
1210   check_filter_model_with_root (fixture, path);
1211   check_level_length (fixture->filter, NULL, 0);
1212 
1213   set_path_visibility (fixture, "2:2:2", TRUE);
1214   check_filter_model_with_root (fixture, path);
1215   check_level_length (fixture->filter, NULL, 0);
1216 
1217   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1218   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1219   set_path_visibility (fixture, "2:2", TRUE);
1220   check_filter_model_with_root (fixture, path);
1221   check_level_length (fixture->filter, NULL, 1);
1222   check_level_length (fixture->filter, "0", 1);
1223   check_level_length (fixture->filter, "0:0", 0);
1224 
1225   set_path_visibility (fixture, "3", TRUE);
1226   check_filter_model_with_root (fixture, path);
1227   check_level_length (fixture->filter, NULL, 1);
1228 
1229   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1230   set_path_visibility (fixture, "2:2", FALSE);
1231   check_filter_model_with_root (fixture, path);
1232   check_level_length (fixture->filter, NULL, 0);
1233 
1234   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1235   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1236   set_path_visibility (fixture, "2:2:1", TRUE);
1237   set_path_visibility (fixture, "2:2", TRUE);
1238   check_filter_model_with_root (fixture, path);
1239   check_level_length (fixture->filter, NULL, 1);
1240   check_level_length (fixture->filter, "0", 2);
1241   check_level_length (fixture->filter, "0:1", 0);
1242 }
1243 
1244 static void
empty_vroot_show_multiple_nodes(FilterTest * fixture,gconstpointer user_data)1245 empty_vroot_show_multiple_nodes (FilterTest    *fixture,
1246                                  gconstpointer  user_data)
1247 {
1248   GtkTreeIter iter;
1249   GtkTreePath *changed_path;
1250   GtkTreePath *path = (GtkTreePath *)user_data;
1251 
1252   check_filter_model_with_root (fixture, path);
1253   check_level_length (fixture->filter, NULL, 0);
1254 
1255   /* We simulate a change in visible func condition with this.  The
1256    * visibility state of multiple nodes changes at once, we emit row-changed
1257    * for these nodes (and others) after that.
1258    */
1259   filter_test_block_signals (fixture);
1260   set_path_visibility (fixture, "2", TRUE);
1261   set_path_visibility (fixture, "3", TRUE);
1262   filter_test_unblock_signals (fixture);
1263 
1264   changed_path = gtk_tree_path_new ();
1265   gtk_tree_path_append_index (changed_path, 1);
1266   gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
1267                            &iter, changed_path);
1268   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1269                               changed_path, &iter);
1270 
1271   gtk_tree_path_next (changed_path);
1272   gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1273   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1274                               changed_path, &iter);
1275 
1276   gtk_tree_path_next (changed_path);
1277   gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1278   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1279                               changed_path, &iter);
1280 
1281   gtk_tree_path_next (changed_path);
1282   gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1283   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1284                               changed_path, &iter);
1285 
1286   gtk_tree_path_free (changed_path);
1287 
1288   check_filter_model_with_root (fixture, path);
1289   check_level_length (fixture->filter, NULL, 0);
1290 
1291   set_path_visibility (fixture, "2:2:2", TRUE);
1292   check_filter_model_with_root (fixture, path);
1293   check_level_length (fixture->filter, NULL, 0);
1294 
1295   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1296   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1297   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "1");
1298   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "1");
1299 
1300   /* Again, we simulate a call to refilter */
1301   filter_test_block_signals (fixture);
1302   set_path_visibility (fixture, "2:2", TRUE);
1303   set_path_visibility (fixture, "2:3", TRUE);
1304   filter_test_unblock_signals (fixture);
1305 
1306   changed_path = gtk_tree_path_new ();
1307   gtk_tree_path_append_index (changed_path, 2);
1308   gtk_tree_path_append_index (changed_path, 1);
1309   gtk_tree_model_get_iter (GTK_TREE_MODEL (fixture->store),
1310                            &iter, changed_path);
1311   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1312                               changed_path, &iter);
1313 
1314   gtk_tree_path_next (changed_path);
1315   gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1316   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1317                               changed_path, &iter);
1318 
1319   gtk_tree_path_next (changed_path);
1320   gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1321   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1322                               changed_path, &iter);
1323 
1324   gtk_tree_path_next (changed_path);
1325   gtk_tree_model_iter_next (GTK_TREE_MODEL (fixture->store), &iter);
1326   gtk_tree_model_row_changed (GTK_TREE_MODEL (fixture->store),
1327                               changed_path, &iter);
1328 
1329   gtk_tree_path_free (changed_path);
1330 
1331   check_filter_model_with_root (fixture, path);
1332   check_level_length (fixture->filter, NULL, 2);
1333   check_level_length (fixture->filter, "0", 1);
1334   check_level_length (fixture->filter, "0:0", 0);
1335 
1336   set_path_visibility (fixture, "3", TRUE);
1337   check_filter_model_with_root (fixture, path);
1338   check_level_length (fixture->filter, NULL, 2);
1339 
1340   signal_monitor_append_signal (fixture->monitor, ROW_DELETED, "0");
1341   set_path_visibility (fixture, "2:2", FALSE);
1342   check_filter_model_with_root (fixture, path);
1343   check_level_length (fixture->filter, NULL, 1);
1344 
1345   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1346   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1347   set_path_visibility (fixture, "2:2:1", TRUE);
1348   set_path_visibility (fixture, "2:2", TRUE);
1349   check_filter_model_with_root (fixture, path);
1350   check_level_length (fixture->filter, NULL, 2);
1351   check_level_length (fixture->filter, "0", 2);
1352   check_level_length (fixture->filter, "0:1", 0);
1353 }
1354 
1355 
1356 static void
unfiltered_hide_single(FilterTest * fixture,gconstpointer user_data)1357 unfiltered_hide_single (FilterTest    *fixture,
1358                         gconstpointer  user_data)
1359 
1360 {
1361   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
1362   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
1363   set_path_visibility (fixture, "2", FALSE);
1364 
1365   signal_monitor_assert_is_empty (fixture->monitor);
1366   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1367 
1368   /* The view only shows the root level, so we only expect signals
1369    * for the root level.
1370    */
1371   filter_test_append_refilter_signals (fixture, 1);
1372   filter_test_enable_filter (fixture);
1373 
1374   check_filter_model (fixture);
1375   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
1376 }
1377 
1378 static void
unfiltered_hide_single_root_expanded(FilterTest * fixture,gconstpointer user_data)1379 unfiltered_hide_single_root_expanded (FilterTest    *fixture,
1380                                       gconstpointer  user_data)
1381 
1382 {
1383   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
1384   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
1385   set_path_visibility (fixture, "2", FALSE);
1386 
1387   signal_monitor_assert_is_empty (fixture->monitor);
1388   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1389 
1390   filter_test_append_refilter_signals (fixture, 2);
1391   filter_test_enable_filter (fixture);
1392 
1393   check_filter_model (fixture);
1394   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
1395 }
1396 
1397 static void
unfiltered_hide_single_child(FilterTest * fixture,gconstpointer user_data)1398 unfiltered_hide_single_child (FilterTest    *fixture,
1399                               gconstpointer  user_data)
1400 
1401 {
1402   /* This row is not shown, so its signal is not propagated */
1403   set_path_visibility (fixture, "2:2", FALSE);
1404 
1405   signal_monitor_assert_is_empty (fixture->monitor);
1406   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1407   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1408 
1409   /* The view only shows the root level, so we only expect signals
1410    * for the root level.
1411    */
1412   filter_test_append_refilter_signals (fixture, 0);
1413   filter_test_enable_filter (fixture);
1414 
1415   check_filter_model (fixture);
1416   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1417   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1418 }
1419 
1420 static void
unfiltered_hide_single_child_root_expanded(FilterTest * fixture,gconstpointer user_data)1421 unfiltered_hide_single_child_root_expanded (FilterTest    *fixture,
1422                                             gconstpointer  user_data)
1423 
1424 {
1425   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1426   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1427   set_path_visibility (fixture, "2:2", FALSE);
1428 
1429   signal_monitor_assert_is_empty (fixture->monitor);
1430   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1431   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1432 
1433   filter_test_append_refilter_signals (fixture, 2);
1434   filter_test_enable_filter (fixture);
1435 
1436   check_filter_model (fixture);
1437   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1438   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1439 }
1440 
1441 static void
unfiltered_hide_single_multi_level(FilterTest * fixture,gconstpointer user_data)1442 unfiltered_hide_single_multi_level (FilterTest    *fixture,
1443                                     gconstpointer  user_data)
1444 
1445 {
1446   /* This row is not shown, so its signal is not propagated */
1447   set_path_visibility (fixture, "2:2:2", FALSE);
1448 
1449   /* This row is not shown, so its signal is not propagated */
1450   set_path_visibility (fixture, "2:2", FALSE);
1451 
1452   signal_monitor_assert_is_empty (fixture->monitor);
1453   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1454   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1455   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1456 
1457   /* The view only shows the root level, so we only expect signals
1458    * for the root level.
1459    */
1460   filter_test_append_refilter_signals (fixture, 1);
1461   filter_test_enable_filter (fixture);
1462 
1463   check_filter_model (fixture);
1464   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1465   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1466 
1467   set_path_visibility (fixture, "2:2", TRUE);
1468 
1469   check_filter_model (fixture);
1470   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1471   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1472   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH - 1);
1473 }
1474 
1475 static void
unfiltered_hide_single_multi_level_root_expanded(FilterTest * fixture,gconstpointer user_data)1476 unfiltered_hide_single_multi_level_root_expanded (FilterTest    *fixture,
1477                                                   gconstpointer  user_data)
1478 
1479 {
1480   /* This row is not shown, so its signal is not propagated */
1481   set_path_visibility (fixture, "2:2:2", FALSE);
1482 
1483   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1484   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1485   set_path_visibility (fixture, "2:2", FALSE);
1486 
1487   signal_monitor_assert_is_empty (fixture->monitor);
1488   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1489   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1490   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1491 
1492   filter_test_append_refilter_signals (fixture, 2);
1493   filter_test_enable_filter (fixture);
1494 
1495   check_filter_model (fixture);
1496   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1497   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1498 
1499   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "2:2");
1500   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1501   set_path_visibility (fixture, "2:2", TRUE);
1502 
1503   check_filter_model (fixture);
1504   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1505   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1506   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH - 1);
1507 }
1508 
1509 
1510 
1511 static void
unfiltered_vroot_hide_single(FilterTest * fixture,gconstpointer user_data)1512 unfiltered_vroot_hide_single (FilterTest    *fixture,
1513                               gconstpointer  user_data)
1514 
1515 {
1516   GtkTreePath *path = (GtkTreePath *)user_data;
1517 
1518   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
1519   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
1520   set_path_visibility (fixture, "2:2", FALSE);
1521 
1522   signal_monitor_assert_is_empty (fixture->monitor);
1523   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1524 
1525   /* The view only shows the root level, so we only expect signals
1526    * for the root level.  (Though for the depth argument, we have to
1527    * take the virtual root into account).
1528    */
1529   filter_test_append_refilter_signals_with_vroot (fixture, 2, path);
1530   filter_test_enable_filter (fixture);
1531 
1532   check_filter_model_with_root (fixture, path);
1533   check_level_length (fixture->filter, NULL, LEVEL_LENGTH - 1);
1534 }
1535 
1536 static void
unfiltered_vroot_hide_single_child(FilterTest * fixture,gconstpointer user_data)1537 unfiltered_vroot_hide_single_child (FilterTest    *fixture,
1538                                     gconstpointer  user_data)
1539 
1540 {
1541   GtkTreePath *path = (GtkTreePath *)user_data;
1542 
1543   /* Not visible, so no signal will be received. */
1544   set_path_visibility (fixture, "2:2:2", FALSE);
1545 
1546   signal_monitor_assert_is_empty (fixture->monitor);
1547   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1548   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1549 
1550   /* The view only shows the root level, so we only expect signals
1551    * for the root level.  (Though for the depth argument, we have to
1552    * take the virtual root into account).
1553    */
1554   filter_test_append_refilter_signals_with_vroot (fixture, 2, path);
1555   filter_test_enable_filter (fixture);
1556 
1557   check_filter_model_with_root (fixture, path);
1558   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1559   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1560 }
1561 
1562 static void
unfiltered_vroot_hide_single_child_root_expanded(FilterTest * fixture,gconstpointer user_data)1563 unfiltered_vroot_hide_single_child_root_expanded (FilterTest    *fixture,
1564                                                   gconstpointer  user_data)
1565 
1566 {
1567   GtkTreePath *path = (GtkTreePath *)user_data;
1568 
1569   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1570   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1571   set_path_visibility (fixture, "2:2:2", FALSE);
1572 
1573   signal_monitor_assert_is_empty (fixture->monitor);
1574   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1575   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1576 
1577   filter_test_append_refilter_signals_with_vroot (fixture, 3, path);
1578   filter_test_enable_filter (fixture);
1579 
1580   check_filter_model_with_root (fixture, path);
1581   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1582   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1583 }
1584 
1585 static void
unfiltered_vroot_hide_single_multi_level(FilterTest * fixture,gconstpointer user_data)1586 unfiltered_vroot_hide_single_multi_level (FilterTest    *fixture,
1587                                           gconstpointer  user_data)
1588 
1589 {
1590   GtkTreePath *path = (GtkTreePath *)user_data;
1591 
1592   /* This row is not shown, so its signal is not propagated */
1593   set_path_visibility (fixture, "2:2:2:2", FALSE);
1594 
1595   /* Not shown, so no signal */
1596   set_path_visibility (fixture, "2:2:2", FALSE);
1597 
1598   signal_monitor_assert_is_empty (fixture->monitor);
1599   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1600   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1601   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1602 
1603   /* We only expect signals for the root level.  The depth is 2
1604    * because we have to take the virtual root into account.
1605    */
1606   filter_test_append_refilter_signals_with_vroot (fixture, 2, path);
1607   filter_test_enable_filter (fixture);
1608 
1609   check_filter_model_with_root (fixture, path);
1610   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1611   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1612 
1613   /* Not shown, so no signal */
1614   set_path_visibility (fixture, "2:2:2", TRUE);
1615 
1616   check_filter_model_with_root (fixture, path);
1617   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1618   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1619   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH - 1);
1620 }
1621 
1622 static void
unfiltered_vroot_hide_single_multi_level_root_expanded(FilterTest * fixture,gconstpointer user_data)1623 unfiltered_vroot_hide_single_multi_level_root_expanded (FilterTest    *fixture,
1624                                                         gconstpointer  user_data)
1625 
1626 {
1627   GtkTreePath *path = (GtkTreePath *)user_data;
1628 
1629   /* This row is not shown, so its signal is not propagated */
1630   set_path_visibility (fixture, "2:2:2:2", FALSE);
1631 
1632   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1633   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1634   set_path_visibility (fixture, "2:2:2", FALSE);
1635 
1636   signal_monitor_assert_is_empty (fixture->monitor);
1637   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1638   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1639   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1640 
1641   filter_test_append_refilter_signals_with_vroot (fixture, 3, path);
1642   filter_test_enable_filter (fixture);
1643 
1644   check_filter_model_with_root (fixture, path);
1645   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1646   check_level_length (fixture->filter, "2", LEVEL_LENGTH - 1);
1647 
1648   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "2:2");
1649   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1650   set_path_visibility (fixture, "2:2:2", TRUE);
1651 
1652   check_filter_model_with_root (fixture, path);
1653   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1654   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1655   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH - 1);
1656 }
1657 
1658 static void
unfiltered_show_single(FilterTest * fixture,gconstpointer user_data)1659 unfiltered_show_single (FilterTest    *fixture,
1660                         gconstpointer  user_data)
1661 
1662 {
1663   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
1664   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
1665   set_path_visibility (fixture, "2", TRUE);
1666 
1667   signal_monitor_assert_is_empty (fixture->monitor);
1668   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1669 
1670   /* We only expect signals for the root level */
1671   filter_test_append_refilter_signals (fixture, 1);
1672   filter_test_enable_filter (fixture);
1673 
1674   check_filter_model (fixture);
1675   check_level_length (fixture->filter, NULL, 1);
1676 }
1677 
1678 static void
unfiltered_show_single_child(FilterTest * fixture,gconstpointer user_data)1679 unfiltered_show_single_child (FilterTest    *fixture,
1680                               gconstpointer  user_data)
1681 
1682 {
1683   set_path_visibility (fixture, "2:2", TRUE);
1684 
1685   signal_monitor_assert_is_empty (fixture->monitor);
1686   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1687   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1688 
1689   /* We only expect signals for the root level */
1690   filter_test_append_refilter_signals (fixture, 1);
1691   filter_test_enable_filter (fixture);
1692 
1693   check_filter_model (fixture);
1694   check_level_length (fixture->filter, NULL, 0);
1695 
1696   /* From here we are filtered, "2" in the real model is "0" in the filter
1697    * model.
1698    */
1699   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1700   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1701   set_path_visibility (fixture, "2", TRUE);
1702   signal_monitor_assert_is_empty (fixture->monitor);
1703   check_level_length (fixture->filter, NULL, 1);
1704   check_level_length (fixture->filter, "0", 1);
1705 }
1706 
1707 static void
unfiltered_show_single_child_root_expanded(FilterTest * fixture,gconstpointer user_data)1708 unfiltered_show_single_child_root_expanded (FilterTest    *fixture,
1709                                             gconstpointer  user_data)
1710 
1711 {
1712   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1713   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1714   set_path_visibility (fixture, "2:2", TRUE);
1715 
1716   signal_monitor_assert_is_empty (fixture->monitor);
1717   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1718   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1719 
1720   filter_test_append_refilter_signals (fixture, 2);
1721   filter_test_enable_filter (fixture);
1722 
1723   check_filter_model (fixture);
1724   check_level_length (fixture->filter, NULL, 0);
1725 
1726   /* From here we are filtered, "2" in the real model is "0" in the filter
1727    * model.
1728    */
1729   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1730   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1731   set_path_visibility (fixture, "2", TRUE);
1732   signal_monitor_assert_is_empty (fixture->monitor);
1733   check_level_length (fixture->filter, NULL, 1);
1734   check_level_length (fixture->filter, "0", 1);
1735 }
1736 
1737 static void
unfiltered_show_single_multi_level(FilterTest * fixture,gconstpointer user_data)1738 unfiltered_show_single_multi_level (FilterTest    *fixture,
1739                                     gconstpointer  user_data)
1740 
1741 {
1742   /* The view is not showing these rows (collapsed state), so it is not
1743    * referenced.  The signal should not go through.
1744    */
1745   set_path_visibility (fixture, "2:2:2", TRUE);
1746   set_path_visibility (fixture, "2:2", TRUE);
1747 
1748   signal_monitor_assert_is_empty (fixture->monitor);
1749   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1750   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1751   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1752 
1753   /* We only expect signals for the first level */
1754   filter_test_append_refilter_signals (fixture, 1);
1755   filter_test_enable_filter (fixture);
1756 
1757   check_filter_model (fixture);
1758   check_level_length (fixture->filter, NULL, 0);
1759 
1760   /* From here we are filtered, "2" in the real model is "0" in the filter
1761    * model.
1762    */
1763   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1764   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1765   set_path_visibility (fixture, "2", TRUE);
1766   check_filter_model (fixture);
1767   check_level_length (fixture->filter, NULL, 1);
1768   check_level_length (fixture->filter, "0", 1);
1769   check_level_length (fixture->filter, "0:0", 1);
1770 }
1771 
1772 static void
unfiltered_show_single_multi_level_root_expanded(FilterTest * fixture,gconstpointer user_data)1773 unfiltered_show_single_multi_level_root_expanded (FilterTest    *fixture,
1774                                                   gconstpointer  user_data)
1775 
1776 {
1777   /* The view is not showing this row (collapsed state), so it is not
1778    * referenced.  The signal should not go through.
1779    */
1780   set_path_visibility (fixture, "2:2:2", TRUE);
1781 
1782   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1783   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1784   set_path_visibility (fixture, "2:2", TRUE);
1785 
1786   signal_monitor_assert_is_empty (fixture->monitor);
1787   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1788   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1789   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1790 
1791   filter_test_append_refilter_signals (fixture, 2);
1792   filter_test_enable_filter (fixture);
1793 
1794   check_filter_model (fixture);
1795   check_level_length (fixture->filter, NULL, 0);
1796 
1797   /* From here we are filtered, "2" in the real model is "0" in the filter
1798    * model.
1799    */
1800   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1801   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1802   set_path_visibility (fixture, "2", TRUE);
1803   check_filter_model (fixture);
1804   check_level_length (fixture->filter, NULL, 1);
1805   check_level_length (fixture->filter, "0", 1);
1806   check_level_length (fixture->filter, "0:0", 1);
1807 }
1808 
1809 static void
unfiltered_vroot_show_single(FilterTest * fixture,gconstpointer user_data)1810 unfiltered_vroot_show_single (FilterTest    *fixture,
1811                               gconstpointer  user_data)
1812 
1813 {
1814   GtkTreePath *path = (GtkTreePath *)user_data;
1815 
1816   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2");
1817   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2");
1818   set_path_visibility (fixture, "2:2", TRUE);
1819 
1820   signal_monitor_assert_is_empty (fixture->monitor);
1821   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1822 
1823   /* The view only shows the root level, so the filter model only has
1824    * the first two levels cached.
1825    */
1826   filter_test_append_refilter_signals_with_vroot (fixture, 2, path);
1827   filter_test_enable_filter (fixture);
1828 
1829   check_filter_model_with_root (fixture, path);
1830   check_level_length (fixture->filter, NULL, 1);
1831 }
1832 
1833 static void
unfiltered_vroot_show_single_child(FilterTest * fixture,gconstpointer user_data)1834 unfiltered_vroot_show_single_child (FilterTest    *fixture,
1835                                     gconstpointer  user_data)
1836 
1837 {
1838   GtkTreePath *path = (GtkTreePath *)user_data;
1839 
1840   set_path_visibility (fixture, "2:2:2", TRUE);
1841 
1842   signal_monitor_assert_is_empty (fixture->monitor);
1843   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1844   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1845 
1846   /* The view only shows the root level, so the filter model only has
1847    * the first two levels cached.
1848    */
1849   filter_test_append_refilter_signals_with_vroot (fixture, 2, path);
1850   filter_test_enable_filter (fixture);
1851 
1852   check_filter_model_with_root (fixture, path);
1853   check_level_length (fixture->filter, NULL, 0);
1854 
1855   /* From here we are filtered, "2" in the real model is "0" in the filter
1856    * model.
1857    */
1858   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1859   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1860   set_path_visibility (fixture, "2:2", TRUE);
1861   signal_monitor_assert_is_empty (fixture->monitor);
1862   check_level_length (fixture->filter, NULL, 1);
1863   check_level_length (fixture->filter, "0", 1);
1864 }
1865 
1866 static void
unfiltered_vroot_show_single_child_root_expanded(FilterTest * fixture,gconstpointer user_data)1867 unfiltered_vroot_show_single_child_root_expanded (FilterTest    *fixture,
1868                                                   gconstpointer  user_data)
1869 
1870 {
1871   GtkTreePath *path = (GtkTreePath *)user_data;
1872 
1873   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1874   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1875   set_path_visibility (fixture, "2:2:2", TRUE);
1876 
1877   signal_monitor_assert_is_empty (fixture->monitor);
1878   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1879   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1880 
1881   filter_test_append_refilter_signals_with_vroot (fixture, 3, path);
1882   filter_test_enable_filter (fixture);
1883 
1884   check_filter_model_with_root (fixture, path);
1885   check_level_length (fixture->filter, NULL, 0);
1886 
1887   /* From here we are filtered, "2" in the real model is "0" in the filter
1888    * model.
1889    */
1890   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1891   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1892   set_path_visibility (fixture, "2:2", TRUE);
1893   signal_monitor_assert_is_empty (fixture->monitor);
1894   check_level_length (fixture->filter, NULL, 1);
1895   check_level_length (fixture->filter, "0", 1);
1896 }
1897 
1898 
1899 static void
unfiltered_vroot_show_single_multi_level(FilterTest * fixture,gconstpointer user_data)1900 unfiltered_vroot_show_single_multi_level (FilterTest    *fixture,
1901                                           gconstpointer  user_data)
1902 
1903 {
1904   GtkTreePath *path = (GtkTreePath *)user_data;
1905 
1906   /* The view is not showing this row (collapsed state), so it is not
1907    * referenced.  The signal should not go through.
1908    */
1909   set_path_visibility (fixture, "2:2:2:2", TRUE);
1910 
1911   set_path_visibility (fixture, "2:2:2", TRUE);
1912 
1913   signal_monitor_assert_is_empty (fixture->monitor);
1914   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1915   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1916   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1917 
1918   /* We only expect signals for the root level */
1919   filter_test_append_refilter_signals_with_vroot (fixture, 2, path);
1920   filter_test_enable_filter (fixture);
1921 
1922   check_filter_model_with_root (fixture, path);
1923   check_level_length (fixture->filter, NULL, 0);
1924 
1925   /* From here we are filtered, "2" in the real model is "0" in the filter
1926    * model.
1927    */
1928   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1929   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1930   set_path_visibility (fixture, "2:2", TRUE);
1931   check_filter_model_with_root (fixture, path);
1932   check_level_length (fixture->filter, NULL, 1);
1933   check_level_length (fixture->filter, "0", 1);
1934   check_level_length (fixture->filter, "0:0", 1);
1935 }
1936 
1937 static void
unfiltered_vroot_show_single_multi_level_root_expanded(FilterTest * fixture,gconstpointer user_data)1938 unfiltered_vroot_show_single_multi_level_root_expanded (FilterTest    *fixture,
1939                                                         gconstpointer  user_data)
1940 
1941 {
1942   GtkTreePath *path = (GtkTreePath *)user_data;
1943 
1944   /* The view is not showing this row (collapsed state), so it is not
1945    * referenced.  The signal should not go through.
1946    */
1947   set_path_visibility (fixture, "2:2:2:2", TRUE);
1948 
1949   signal_monitor_append_signal (fixture->monitor, ROW_CHANGED, "2:2");
1950   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "2:2");
1951   set_path_visibility (fixture, "2:2:2", TRUE);
1952 
1953   signal_monitor_assert_is_empty (fixture->monitor);
1954   check_level_length (fixture->filter, NULL, LEVEL_LENGTH);
1955   check_level_length (fixture->filter, "2", LEVEL_LENGTH);
1956   check_level_length (fixture->filter, "2:2", LEVEL_LENGTH);
1957 
1958   filter_test_append_refilter_signals_with_vroot (fixture, 3, path);
1959   filter_test_enable_filter (fixture);
1960 
1961   check_filter_model_with_root (fixture, path);
1962   check_level_length (fixture->filter, NULL, 0);
1963 
1964   /* From here we are filtered, "2" in the real model is "0" in the filter
1965    * model.
1966    */
1967   signal_monitor_append_signal (fixture->monitor, ROW_INSERTED, "0");
1968   signal_monitor_append_signal (fixture->monitor, ROW_HAS_CHILD_TOGGLED, "0");
1969   set_path_visibility (fixture, "2:2", TRUE);
1970   check_filter_model_with_root (fixture, path);
1971   check_level_length (fixture->filter, NULL, 1);
1972   check_level_length (fixture->filter, "0", 1);
1973   check_level_length (fixture->filter, "0:0", 1);
1974 }
1975 
1976 static void
unfiltered_rows_reordered_root_level(FilterTest * fixture,gconstpointer user_data)1977 unfiltered_rows_reordered_root_level (FilterTest    *fixture,
1978                                       gconstpointer  user_data)
1979 {
1980   int order0[] = { 1, 2, 3, 4, 0 };
1981   int order1[] = { 0, 2, 1, 3, 4 };
1982   int order2[] = { 4, 0, 1, 2, 3 };
1983   GtkTreeIter iter0, iter1, iter2, iter3, iter4;
1984   GtkTreePath *path;
1985 
1986   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
1987                                        &iter0, "0");
1988   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
1989                                        &iter1, "1");
1990   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
1991                                        &iter2, "2");
1992   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
1993                                        &iter3, "3");
1994   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
1995                                        &iter4, "4");
1996 
1997   path = gtk_tree_path_new ();
1998   signal_monitor_append_signal_reordered (fixture->monitor,
1999                                           ROWS_REORDERED,
2000                                           path, order0, 5);
2001   gtk_tree_store_move_after (fixture->store, &iter0, &iter4);
2002   signal_monitor_assert_is_empty (fixture->monitor);
2003 
2004   signal_monitor_append_signal_reordered (fixture->monitor,
2005                                           ROWS_REORDERED,
2006                                           path, order1, 5);
2007   gtk_tree_store_move_after (fixture->store, &iter2, &iter3);
2008   signal_monitor_assert_is_empty (fixture->monitor);
2009 
2010   signal_monitor_append_signal_reordered (fixture->monitor,
2011                                           ROWS_REORDERED,
2012                                           path, order2, 5);
2013   gtk_tree_store_move_before (fixture->store, &iter0, &iter1);
2014   signal_monitor_assert_is_empty (fixture->monitor);
2015 
2016   gtk_tree_path_free (path);
2017 }
2018 
2019 static void
unfiltered_rows_reordered_child_level(FilterTest * fixture,gconstpointer user_data)2020 unfiltered_rows_reordered_child_level (FilterTest    *fixture,
2021                                        gconstpointer  user_data)
2022 {
2023   int order0[] = { 1, 2, 3, 4, 0 };
2024   int order1[] = { 0, 2, 1, 3, 4 };
2025   int order2[] = { 4, 0, 1, 2, 3 };
2026   GtkTreeIter iter0, iter1, iter2, iter3, iter4;
2027   GtkTreePath *path;
2028 
2029   /* Expand row 0 */
2030   path = gtk_tree_path_new_from_indices (0, -1);
2031   gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), path, FALSE);
2032 
2033   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2034                                        &iter0, "0:0");
2035   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2036                                        &iter1, "0:1");
2037   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2038                                        &iter2, "0:2");
2039   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2040                                        &iter3, "0:3");
2041   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2042                                        &iter4, "0:4");
2043 
2044   signal_monitor_append_signal_reordered (fixture->monitor,
2045                                           ROWS_REORDERED,
2046                                           path, order0, 5);
2047   gtk_tree_store_move_after (fixture->store, &iter0, &iter4);
2048   signal_monitor_assert_is_empty (fixture->monitor);
2049 
2050   signal_monitor_append_signal_reordered (fixture->monitor,
2051                                           ROWS_REORDERED,
2052                                           path, order1, 5);
2053   gtk_tree_store_move_after (fixture->store, &iter2, &iter3);
2054   signal_monitor_assert_is_empty (fixture->monitor);
2055 
2056   signal_monitor_append_signal_reordered (fixture->monitor,
2057                                           ROWS_REORDERED,
2058                                           path, order2, 5);
2059   gtk_tree_store_move_before (fixture->store, &iter0, &iter1);
2060   signal_monitor_assert_is_empty (fixture->monitor);
2061 
2062   gtk_tree_path_free (path);
2063 }
2064 
2065 static void
filtered_rows_reordered_root_level_first_hidden(FilterTest * fixture,gconstpointer user_data)2066 filtered_rows_reordered_root_level_first_hidden (FilterTest    *fixture,
2067                                                  gconstpointer  user_data)
2068 {
2069   int order0[] = { 1, 2, 3, 0 };
2070   int order1[] = { 0, 2, 1, 3 };
2071   int order2[] = { 3, 0, 1, 2 };
2072   GtkTreeIter iter1, iter2, iter3, iter4;
2073   GtkTreePath *path;
2074 
2075   /* Hide middle path */
2076   signal_monitor_append_signal (fixture->monitor,
2077                                 ROW_DELETED, "0");
2078   set_path_visibility (fixture, "0", FALSE);
2079   signal_monitor_assert_is_empty (fixture->monitor);
2080 
2081   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2082                                        &iter1, "1");
2083   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2084                                        &iter2, "2");
2085   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2086                                        &iter3, "3");
2087   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2088                                        &iter4, "4");
2089 
2090   path = gtk_tree_path_new ();
2091   signal_monitor_append_signal_reordered (fixture->monitor,
2092                                           ROWS_REORDERED,
2093                                           path, order0, 4);
2094   gtk_tree_store_move_after (fixture->store, &iter1, &iter4);
2095   signal_monitor_assert_is_empty (fixture->monitor);
2096 
2097   signal_monitor_append_signal_reordered (fixture->monitor,
2098                                           ROWS_REORDERED,
2099                                           path, order1, 4);
2100   gtk_tree_store_move_after (fixture->store, &iter3, &iter4);
2101   signal_monitor_assert_is_empty (fixture->monitor);
2102 
2103   signal_monitor_append_signal_reordered (fixture->monitor,
2104                                           ROWS_REORDERED,
2105                                           path, order2, 4);
2106   gtk_tree_store_move_before (fixture->store, &iter1, &iter2);
2107   signal_monitor_assert_is_empty (fixture->monitor);
2108 
2109   gtk_tree_path_free (path);
2110 }
2111 
2112 static void
filtered_rows_reordered_root_level_middle_hidden(FilterTest * fixture,gconstpointer user_data)2113 filtered_rows_reordered_root_level_middle_hidden (FilterTest    *fixture,
2114                                                   gconstpointer  user_data)
2115 {
2116   int order0[] = { 1, 2, 3, 0 };
2117   int order1[] = { 0, 2, 1, 3 };
2118   int order2[] = { 3, 0, 1, 2 };
2119   GtkTreeIter iter0, iter1, iter3, iter4;
2120   GtkTreePath *path;
2121 
2122   /* Hide middle path */
2123   signal_monitor_append_signal (fixture->monitor,
2124                                 ROW_DELETED, "2");
2125   set_path_visibility (fixture, "2", FALSE);
2126   signal_monitor_assert_is_empty (fixture->monitor);
2127 
2128   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2129                                        &iter0, "0");
2130   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2131                                        &iter1, "1");
2132   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2133                                        &iter3, "3");
2134   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2135                                        &iter4, "4");
2136 
2137   path = gtk_tree_path_new ();
2138   signal_monitor_append_signal_reordered (fixture->monitor,
2139                                           ROWS_REORDERED,
2140                                           path, order0, 4);
2141   gtk_tree_store_move_after (fixture->store, &iter0, &iter4);
2142   signal_monitor_assert_is_empty (fixture->monitor);
2143 
2144   signal_monitor_append_signal_reordered (fixture->monitor,
2145                                           ROWS_REORDERED,
2146                                           path, order1, 4);
2147   gtk_tree_store_move_after (fixture->store, &iter3, &iter4);
2148   signal_monitor_assert_is_empty (fixture->monitor);
2149 
2150   signal_monitor_append_signal_reordered (fixture->monitor,
2151                                           ROWS_REORDERED,
2152                                           path, order2, 4);
2153   gtk_tree_store_move_before (fixture->store, &iter0, &iter1);
2154   signal_monitor_assert_is_empty (fixture->monitor);
2155 
2156   gtk_tree_path_free (path);
2157 }
2158 
2159 static void
filtered_rows_reordered_child_level_first_hidden(FilterTest * fixture,gconstpointer user_data)2160 filtered_rows_reordered_child_level_first_hidden (FilterTest    *fixture,
2161                                                   gconstpointer  user_data)
2162 {
2163   int order0[] = { 1, 2, 3, 0 };
2164   int order1[] = { 0, 2, 1, 3 };
2165   int order2[] = { 3, 0, 1, 2 };
2166   GtkTreeIter iter1, iter2, iter3, iter4;
2167   GtkTreePath *path;
2168 
2169   /* Expand row 0 */
2170   path = gtk_tree_path_new_from_indices (0, -1);
2171   gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), path, TRUE);
2172 
2173   /* Hide middle path */
2174   signal_monitor_append_signal (fixture->monitor,
2175                                 ROW_DELETED, "0:0");
2176   set_path_visibility (fixture, "0:0", FALSE);
2177   signal_monitor_assert_is_empty (fixture->monitor);
2178 
2179   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2180                                        &iter1, "0:1");
2181   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2182                                        &iter2, "0:2");
2183   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2184                                        &iter3, "0:3");
2185   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2186                                        &iter4, "0:4");
2187 
2188   signal_monitor_append_signal_reordered (fixture->monitor,
2189                                           ROWS_REORDERED,
2190                                           path, order0, 4);
2191   gtk_tree_store_move_after (fixture->store, &iter1, &iter4);
2192   signal_monitor_assert_is_empty (fixture->monitor);
2193 
2194   signal_monitor_append_signal_reordered (fixture->monitor,
2195                                           ROWS_REORDERED,
2196                                           path, order1, 4);
2197   gtk_tree_store_move_after (fixture->store, &iter3, &iter4);
2198   signal_monitor_assert_is_empty (fixture->monitor);
2199 
2200   signal_monitor_append_signal_reordered (fixture->monitor,
2201                                           ROWS_REORDERED,
2202                                           path, order2, 4);
2203   gtk_tree_store_move_before (fixture->store, &iter1, &iter2);
2204   signal_monitor_assert_is_empty (fixture->monitor);
2205 
2206   gtk_tree_path_free (path);
2207 }
2208 
2209 static void
filtered_rows_reordered_child_level_middle_hidden(FilterTest * fixture,gconstpointer user_data)2210 filtered_rows_reordered_child_level_middle_hidden (FilterTest    *fixture,
2211                                                    gconstpointer  user_data)
2212 {
2213   int order0[] = { 1, 2, 3, 0 };
2214   int order1[] = { 0, 2, 1, 3 };
2215   int order2[] = { 3, 0, 1, 2 };
2216   GtkTreeIter iter0, iter1, iter3, iter4;
2217   GtkTreePath *path;
2218 
2219   /* Expand row 0 */
2220   path = gtk_tree_path_new_from_indices (0, -1);
2221   gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), path, FALSE);
2222 
2223   /* Hide middle path */
2224   signal_monitor_append_signal (fixture->monitor,
2225                                 ROW_DELETED, "0:2");
2226   set_path_visibility (fixture, "0:2", FALSE);
2227   signal_monitor_assert_is_empty (fixture->monitor);
2228 
2229   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2230                                        &iter0, "0:0");
2231   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2232                                        &iter1, "0:1");
2233   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2234                                        &iter3, "0:3");
2235   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2236                                        &iter4, "0:4");
2237 
2238   signal_monitor_append_signal_reordered (fixture->monitor,
2239                                           ROWS_REORDERED,
2240                                           path, order0, 4);
2241   gtk_tree_store_move_after (fixture->store, &iter0, &iter4);
2242   signal_monitor_assert_is_empty (fixture->monitor);
2243 
2244   signal_monitor_append_signal_reordered (fixture->monitor,
2245                                           ROWS_REORDERED,
2246                                           path, order1, 4);
2247   gtk_tree_store_move_after (fixture->store, &iter3, &iter4);
2248   signal_monitor_assert_is_empty (fixture->monitor);
2249 
2250   signal_monitor_append_signal_reordered (fixture->monitor,
2251                                           ROWS_REORDERED,
2252                                           path, order2, 4);
2253   gtk_tree_store_move_before (fixture->store, &iter0, &iter1);
2254   signal_monitor_assert_is_empty (fixture->monitor);
2255 
2256   gtk_tree_path_free (path);
2257 }
2258 
2259 static void
filtered_rows_reordered_child_level_4_hidden(FilterTest * fixture,gconstpointer user_data)2260 filtered_rows_reordered_child_level_4_hidden (FilterTest    *fixture,
2261                                               gconstpointer  user_data)
2262 {
2263   int order0[] = { 0 };
2264   GtkTreeIter iter1, iter4;
2265   GtkTreePath *path;
2266 
2267   /* Expand row 0 */
2268   path = gtk_tree_path_new_from_indices (0, -1);
2269   gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), path, FALSE);
2270 
2271   /* Hide last 4 paths */
2272   signal_monitor_append_signal (fixture->monitor,
2273                                 ROW_DELETED, "0:4");
2274   signal_monitor_append_signal (fixture->monitor,
2275                                 ROW_DELETED, "0:3");
2276   signal_monitor_append_signal (fixture->monitor,
2277                                 ROW_DELETED, "0:2");
2278   signal_monitor_append_signal (fixture->monitor,
2279                                 ROW_DELETED, "0:0");
2280   set_path_visibility (fixture, "0:4", FALSE);
2281   set_path_visibility (fixture, "0:3", FALSE);
2282   set_path_visibility (fixture, "0:2", FALSE);
2283   set_path_visibility (fixture, "0:0", FALSE);
2284   signal_monitor_assert_is_empty (fixture->monitor);
2285 
2286   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2287                                        &iter1, "0:1");
2288   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2289                                        &iter4, "0:4");
2290 
2291   signal_monitor_append_signal_reordered (fixture->monitor,
2292                                           ROWS_REORDERED,
2293                                           path, order0, 1);
2294   gtk_tree_store_move_after (fixture->store, &iter1, &iter4);
2295   signal_monitor_assert_is_empty (fixture->monitor);
2296 
2297   gtk_tree_path_free (path);
2298 }
2299 
2300 static void
filtered_rows_reordered_child_level_all_hidden(FilterTest * fixture,gconstpointer user_data)2301 filtered_rows_reordered_child_level_all_hidden (FilterTest    *fixture,
2302                                                 gconstpointer  user_data)
2303 {
2304   GtkTreeIter iter1, iter4;
2305   GtkTreePath *path;
2306 
2307   /* Expand row 0 */
2308   path = gtk_tree_path_new_from_indices (0, -1);
2309   gtk_tree_view_expand_row (GTK_TREE_VIEW (fixture->tree_view), path, FALSE);
2310   gtk_tree_path_free (path);
2311 
2312   /* Hide last 4 paths */
2313   signal_monitor_append_signal (fixture->monitor,
2314                                 ROW_DELETED, "0:4");
2315   signal_monitor_append_signal (fixture->monitor,
2316                                 ROW_DELETED, "0:3");
2317   signal_monitor_append_signal (fixture->monitor,
2318                                 ROW_DELETED, "0:2");
2319   signal_monitor_append_signal (fixture->monitor,
2320                                 ROW_DELETED, "0:1");
2321   signal_monitor_append_signal (fixture->monitor,
2322                                 ROW_DELETED, "0:0");
2323   signal_monitor_append_signal (fixture->monitor,
2324                                 ROW_HAS_CHILD_TOGGLED, "0");
2325   set_path_visibility (fixture, "0:4", FALSE);
2326   set_path_visibility (fixture, "0:3", FALSE);
2327   set_path_visibility (fixture, "0:2", FALSE);
2328   set_path_visibility (fixture, "0:1", FALSE);
2329   set_path_visibility (fixture, "0:0", FALSE);
2330   signal_monitor_assert_is_empty (fixture->monitor);
2331 
2332   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2333                                        &iter1, "0:1");
2334   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture->store),
2335                                        &iter4, "0:4");
2336 
2337   gtk_tree_store_move_after (fixture->store, &iter1, &iter4);
2338   signal_monitor_assert_is_empty (fixture->monitor);
2339 }
2340 
2341 static void
insert_before(void)2342 insert_before (void)
2343 {
2344   GtkTreeStore *store;
2345   GtkTreeModel *filter;
2346   GtkWidget *tree_view;
2347   SignalMonitor *monitor;
2348   GtkTreeIter iter;
2349   GtkTreeIter last_iter;
2350   GtkTreePath *path;
2351 
2352   /* This tests two aspects of the row-inserted handling:
2353    *   1) If the newly inserted node was already handled by building
2354    *      the root level, don't handle it a second time.
2355    *   2) Offsets of existing nodes must be updated when a new
2356    *      node is inserted.
2357    */
2358 
2359   store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
2360   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
2361   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter),
2362                                             1);
2363 
2364   tree_view = gtk_tree_view_new_with_model (filter);
2365   monitor = signal_monitor_new (filter);
2366 
2367   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 0);
2368 
2369   /* Insert 0 */
2370   path = gtk_tree_path_new_from_indices (0, -1);
2371   signal_monitor_append_signal_path (monitor, ROW_INSERTED, path);
2372   gtk_tree_path_free (path);
2373 
2374   gtk_tree_store_insert_with_values (store, &iter, NULL, 0,
2375                                      0, "Foo", 1, TRUE, -1);
2376 
2377   signal_monitor_assert_is_empty (monitor);
2378   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 1);
2379 
2380   /* Insert 1 */
2381   path = gtk_tree_path_new_from_indices (1, -1);
2382   signal_monitor_append_signal_path (monitor, ROW_INSERTED, path);
2383   gtk_tree_path_free (path);
2384 
2385   gtk_tree_store_insert_with_values (store, &iter, NULL, 1,
2386                                      0, "Foo", 1, TRUE, -1);
2387   last_iter = iter;
2388 
2389   signal_monitor_assert_is_empty (monitor);
2390   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 2);
2391 
2392   /* Insert on 1 again -- invisible */
2393   gtk_tree_store_insert_with_values (store, &iter, NULL, 1,
2394                                      0, "Foo", 1, FALSE, -1);
2395 
2396   signal_monitor_assert_is_empty (monitor);
2397   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 2);
2398 
2399   /* Insert on 1 again -- visible */
2400   path = gtk_tree_path_new_from_indices (1, -1);
2401   signal_monitor_append_signal_path (monitor, ROW_INSERTED, path);
2402   gtk_tree_path_free (path);
2403 
2404   gtk_tree_store_insert_with_values (store, &iter, NULL, 1,
2405                                      0, "Foo", 1, TRUE, -1);
2406 
2407   signal_monitor_assert_is_empty (monitor);
2408   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 3);
2409 
2410   /* Modify the iter that should be at the last position and check the
2411    * signal we get.
2412    */
2413   path = gtk_tree_path_new_from_indices (2, -1);
2414   signal_monitor_append_signal_path (monitor, ROW_CHANGED, path);
2415   gtk_tree_path_free (path);
2416 
2417   gtk_tree_store_set (store, &last_iter, 0, "Foo changed", -1);
2418 
2419   signal_monitor_assert_is_empty (monitor);
2420   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 3);
2421 
2422   g_object_unref (filter);
2423   g_object_unref (store);
2424   g_object_unref (g_object_ref_sink (tree_view));
2425 }
2426 
2427 static void
insert_child(void)2428 insert_child (void)
2429 {
2430   GtkTreeStore *store;
2431   GtkTreeModel *filter;
2432   GtkWidget *tree_view;
2433   SignalMonitor *monitor;
2434   GtkTreeIter parent, iter;
2435   GtkTreePath *path;
2436 
2437   store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
2438 
2439   gtk_tree_store_insert_with_values (store, &parent, NULL, 0,
2440                                      0, "Parent", 1, TRUE, -1);
2441 
2442 
2443   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
2444   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter),
2445                                             1);
2446 
2447   tree_view = gtk_tree_view_new_with_model (filter);
2448   monitor = signal_monitor_new (filter);
2449 
2450   /* Insert child -- invisible */
2451   path = gtk_tree_path_new_from_indices (0, -1);
2452   signal_monitor_append_signal_path (monitor, ROW_HAS_CHILD_TOGGLED, path);
2453   /* The signal is received twice, once a pass through from GtkTreeStore
2454    * and one generated by GtkTreeModelFilter.  Not accurate, but cannot
2455    * hurt.
2456    */
2457   signal_monitor_append_signal_path (monitor, ROW_HAS_CHILD_TOGGLED, path);
2458   gtk_tree_path_free (path);
2459 
2460   gtk_tree_store_insert_with_values (store, &iter, &parent, 1,
2461                                      0, "Child", 1, FALSE, -1);
2462 
2463   signal_monitor_assert_is_empty (monitor);
2464   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 1);
2465 
2466   /* Insert child */
2467   path = gtk_tree_path_new_from_indices (0, 0, -1);
2468   gtk_tree_path_up (path); /* 0 */
2469   signal_monitor_append_signal_path (monitor, ROW_HAS_CHILD_TOGGLED, path);
2470   gtk_tree_path_free (path);
2471 
2472   gtk_tree_store_insert_with_values (store, &iter, &parent, 0,
2473                                      0, "Child", 1, TRUE, -1);
2474 
2475   signal_monitor_assert_is_empty (monitor);
2476   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 1);
2477 
2478   /* Insert child -- invisible */
2479   gtk_tree_store_insert_with_values (store, &iter, &parent, 1,
2480                                      0, "Child", 1, FALSE, -1);
2481 
2482   signal_monitor_assert_is_empty (monitor);
2483   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 1);
2484 
2485   g_object_unref (filter);
2486   g_object_unref (store);
2487   g_object_unref (g_object_ref_sink (tree_view));
2488 }
2489 
2490 
2491 
2492 static void
remove_node(void)2493 remove_node (void)
2494 {
2495   GtkTreeIter iter, iter1, iter2, iter3;
2496   GtkListStore *list;
2497   GtkTreeModel *filter;
2498   GtkWidget *view G_GNUC_UNUSED;
2499 
2500   list = gtk_list_store_new (1, G_TYPE_INT);
2501   gtk_list_store_insert_with_values (list, &iter1, 0, 0, 1, -1);
2502   gtk_list_store_insert_with_values (list, &iter, 1, 0, 2, -1);
2503   gtk_list_store_insert_with_values (list, &iter, 2, 0, 3, -1);
2504   gtk_list_store_insert_with_values (list, &iter, 3, 0, 4, -1);
2505   gtk_list_store_insert_with_values (list, &iter, 4, 0, 5, -1);
2506   gtk_list_store_insert_with_values (list, &iter, 5, 0, 6, -1);
2507   gtk_list_store_insert_with_values (list, &iter2, 6, 0, 7, -1);
2508   gtk_list_store_insert_with_values (list, &iter3, 7, 0, 8, -1);
2509 
2510   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (list), NULL);
2511   view = gtk_tree_view_new_with_model (filter);
2512 
2513   gtk_list_store_remove (list, &iter1);
2514   gtk_list_store_remove (list, &iter3);
2515   gtk_list_store_remove (list, &iter2);
2516 
2517   g_object_unref (g_object_ref_sink (view));
2518   g_object_unref (filter);
2519   g_object_unref (list);
2520 }
2521 
2522 static void
remove_node_vroot(void)2523 remove_node_vroot (void)
2524 {
2525   GtkTreeIter parent, root;
2526   GtkTreeIter iter, iter1, iter2, iter3;
2527   GtkTreeStore *tree;
2528   GtkTreeModel *filter;
2529   GtkTreePath *path;
2530   GtkWidget *view G_GNUC_UNUSED;
2531 
2532   tree = gtk_tree_store_new (1, G_TYPE_INT);
2533   gtk_tree_store_insert_with_values (tree, &parent, NULL, 0, 0, 0, -1);
2534   gtk_tree_store_insert_with_values (tree, &root, &parent, 0, 0, 0, -1);
2535 
2536   gtk_tree_store_insert_with_values (tree, &iter1, &root, 0, 0, 1, -1);
2537   gtk_tree_store_insert_with_values (tree, &iter, &root, 1, 0, 2, -1);
2538   gtk_tree_store_insert_with_values (tree, &iter, &root, 2, 0, 3, -1);
2539   gtk_tree_store_insert_with_values (tree, &iter, &root, 3, 0, 4, -1);
2540   gtk_tree_store_insert_with_values (tree, &iter, &root, 4, 0, 5, -1);
2541   gtk_tree_store_insert_with_values (tree, &iter, &root, 5, 0, 6, -1);
2542   gtk_tree_store_insert_with_values (tree, &iter2, &root, 6, 0, 7, -1);
2543   gtk_tree_store_insert_with_values (tree, &iter3, &root, 7, 0, 8, -1);
2544 
2545   path = gtk_tree_path_new_from_indices (0, 0, -1);
2546   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), path);
2547   gtk_tree_path_free (path);
2548 
2549   view = gtk_tree_view_new_with_model (filter);
2550 
2551   gtk_tree_store_remove (tree, &iter1);
2552   gtk_tree_store_remove (tree, &iter3);
2553   gtk_tree_store_remove (tree, &iter2);
2554 
2555   g_object_unref (g_object_ref_sink (view));
2556   g_object_unref (filter);
2557   g_object_unref (tree);
2558 }
2559 
2560 static void
remove_vroot_ancestor(void)2561 remove_vroot_ancestor (void)
2562 {
2563   GtkTreeIter parent, root;
2564   GtkTreeIter iter, iter1, iter2, iter3;
2565   GtkTreeStore *tree;
2566   GtkTreeModel *filter;
2567   GtkTreePath *path;
2568   GtkWidget *view G_GNUC_UNUSED;
2569 
2570   tree = gtk_tree_store_new (1, G_TYPE_INT);
2571   gtk_tree_store_insert_with_values (tree, &parent, NULL, 0, 0, 0, -1);
2572   gtk_tree_store_insert_with_values (tree, &root, &parent, 0, 0, 0, -1);
2573 
2574   gtk_tree_store_insert_with_values (tree, &iter1, &root, 0, 0, 1, -1);
2575   gtk_tree_store_insert_with_values (tree, &iter, &root, 1, 0, 2, -1);
2576   gtk_tree_store_insert_with_values (tree, &iter, &root, 2, 0, 3, -1);
2577   gtk_tree_store_insert_with_values (tree, &iter, &root, 3, 0, 4, -1);
2578   gtk_tree_store_insert_with_values (tree, &iter, &root, 4, 0, 5, -1);
2579   gtk_tree_store_insert_with_values (tree, &iter, &root, 5, 0, 6, -1);
2580   gtk_tree_store_insert_with_values (tree, &iter2, &root, 6, 0, 7, -1);
2581   gtk_tree_store_insert_with_values (tree, &iter3, &root, 7, 0, 8, -1);
2582 
2583   path = gtk_tree_path_new_from_indices (0, 0, -1);
2584   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), path);
2585   gtk_tree_path_free (path);
2586 
2587   view = gtk_tree_view_new_with_model (filter);
2588 
2589   gtk_tree_store_remove (tree, &parent);
2590 
2591   g_object_unref (g_object_ref_sink (view));
2592   g_object_unref (filter);
2593   g_object_unref (tree);
2594 }
2595 
2596 static void
ref_count_single_level(void)2597 ref_count_single_level (void)
2598 {
2599   GtkTreeIter iter[5];
2600   GtkTreeModel *model;
2601   GtkTreeModelRefCount *ref_model;
2602   GtkTreeModel *filter_model;
2603   GtkWidget *tree_view;
2604 
2605   model = gtk_tree_model_ref_count_new ();
2606   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
2607 
2608   gtk_tree_store_append (GTK_TREE_STORE (model), &iter[0], NULL);
2609   gtk_tree_store_append (GTK_TREE_STORE (model), &iter[1], NULL);
2610   gtk_tree_store_append (GTK_TREE_STORE (model), &iter[2], NULL);
2611   gtk_tree_store_append (GTK_TREE_STORE (model), &iter[3], NULL);
2612   gtk_tree_store_append (GTK_TREE_STORE (model), &iter[4], NULL);
2613 
2614   assert_root_level_unreferenced (ref_model);
2615 
2616   filter_model = gtk_tree_model_filter_new (model, NULL);
2617   tree_view = gtk_tree_view_new_with_model (filter_model);
2618 
2619   assert_node_ref_count (ref_model, &iter[0], 2);
2620   assert_node_ref_count (ref_model, &iter[1], 1);
2621   assert_node_ref_count (ref_model, &iter[2], 1);
2622   assert_node_ref_count (ref_model, &iter[3], 1);
2623   assert_node_ref_count (ref_model, &iter[4], 1);
2624 
2625   g_object_unref (g_object_ref_sink (tree_view));
2626 
2627   assert_node_ref_count (ref_model, &iter[0], 1);
2628   assert_node_ref_count (ref_model, &iter[1], 0);
2629   assert_node_ref_count (ref_model, &iter[2], 0);
2630   assert_node_ref_count (ref_model, &iter[3], 0);
2631   assert_node_ref_count (ref_model, &iter[4], 0);
2632 
2633   g_object_unref (filter_model);
2634 
2635   assert_node_ref_count (ref_model, &iter[0], 0);
2636 
2637   g_object_unref (ref_model);
2638 }
2639 
2640 static void
ref_count_two_levels(void)2641 ref_count_two_levels (void)
2642 {
2643   GtkTreeIter parent1, parent2, iter, iter_first;
2644   GtkTreeModel *model;
2645   GtkTreeModelRefCount *ref_model;
2646   GtkTreeModel *filter_model;
2647   GtkWidget *tree_view;
2648 
2649   model = gtk_tree_model_ref_count_new ();
2650   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
2651 
2652   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, NULL);
2653   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, NULL);
2654   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_first, &parent2);
2655   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, &parent2);
2656   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, &parent2);
2657 
2658   assert_entire_model_unreferenced (ref_model);
2659 
2660   filter_model = gtk_tree_model_filter_new (model, NULL);
2661   tree_view = gtk_tree_view_new_with_model (filter_model);
2662 
2663   /* This is quite confusing:
2664    *  - node 0 has a ref count of 2 because it is referenced as the
2665    *    first node in a level and by the tree view.
2666    *  - node 1 has a ref count of 2 because it is referenced by its
2667    *    child level and by the tree view.
2668    */
2669   assert_root_level_referenced (ref_model, 2);
2670   assert_node_ref_count (ref_model, &iter_first, 1);
2671   assert_node_ref_count (ref_model, &iter, 0);
2672 
2673   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
2674 
2675   assert_node_ref_count (ref_model, &parent1, 2);
2676   assert_node_ref_count (ref_model, &parent2, 2);
2677   assert_node_ref_count (ref_model, &iter_first, 2);
2678   assert_node_ref_count (ref_model, &iter, 1);
2679 
2680   gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view));
2681 
2682   /* The child level is not destroyed because its parent is visible */
2683   assert_node_ref_count (ref_model, &parent1, 2);
2684   assert_node_ref_count (ref_model, &parent2, 2);
2685   assert_node_ref_count (ref_model, &iter_first, 1);
2686   assert_node_ref_count (ref_model, &iter, 0);
2687 
2688   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2689 
2690   assert_node_ref_count (ref_model, &parent1, 2);
2691   assert_node_ref_count (ref_model, &parent2, 2);
2692   assert_node_ref_count (ref_model, &iter_first, 1);
2693   assert_node_ref_count (ref_model, &iter, 0);
2694 
2695   g_object_unref (g_object_ref_sink (tree_view));
2696 
2697   assert_root_level_referenced (ref_model, 1);
2698   assert_node_ref_count (ref_model, &iter_first, 1);
2699   assert_node_ref_count (ref_model, &iter, 0);
2700 
2701   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2702 
2703   /* The root level and first level remain cached, only the references on the
2704    * first nodes of these levels are kept.
2705    */
2706   assert_node_ref_count (ref_model, &parent1, 1);
2707   assert_node_ref_count (ref_model, &parent2, 1);
2708   assert_node_ref_count (ref_model, &iter_first, 1);
2709   assert_node_ref_count (ref_model, &iter, 0);
2710 
2711   g_object_unref (filter_model);
2712   g_object_unref (ref_model);
2713 }
2714 
2715 static void
ref_count_three_levels(void)2716 ref_count_three_levels (void)
2717 {
2718   GtkTreeIter grandparent1, grandparent2, parent1, parent2;
2719   GtkTreeIter iter_parent1, iter_parent2, iter_parent2_first;
2720   GtkTreeModel *model;
2721   GtkTreeModelRefCount *ref_model;
2722   GtkTreeModel *filter_model;
2723   GtkTreePath *path;
2724   GtkWidget *tree_view;
2725 
2726   model = gtk_tree_model_ref_count_new ();
2727   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
2728 
2729   /* + grandparent1
2730    * + grandparent2
2731    *   + parent1
2732    *     + iter_parent1
2733    *   + parent2
2734    *     + iter_parent2_first
2735    *     + iter_parent2
2736    */
2737 
2738   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
2739   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
2740   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent2);
2741   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent1, &parent1);
2742   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent2);
2743   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent2_first, &parent2);
2744   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent2, &parent2);
2745 
2746   assert_entire_model_unreferenced (ref_model);
2747 
2748   filter_model = gtk_tree_model_filter_new (model, NULL);
2749   tree_view = gtk_tree_view_new_with_model (filter_model);
2750 
2751   /* This is quite confusing:
2752    *  - node 0 has a ref count of 2 because it is referenced as the
2753    *    first node in a level and by the tree view.
2754    *  - node 1 has a ref count of 2 because it is referenced by its
2755    *    child level and by the tree view.
2756    */
2757   assert_root_level_referenced (ref_model, 2);
2758   assert_node_ref_count (ref_model, &parent1, 1);
2759   assert_node_ref_count (ref_model, &parent2, 0);
2760   assert_level_unreferenced (ref_model, &parent1);
2761   assert_level_unreferenced (ref_model, &parent2);
2762 
2763   path = gtk_tree_path_new_from_indices (1, -1);
2764   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
2765 
2766   assert_node_ref_count (ref_model, &grandparent1, 2);
2767   assert_node_ref_count (ref_model, &grandparent2, 2);
2768   assert_node_ref_count (ref_model, &parent1, 3);
2769   assert_node_ref_count (ref_model, &parent2, 2);
2770   assert_node_ref_count (ref_model, &iter_parent1, 1);
2771   assert_node_ref_count (ref_model, &iter_parent2_first, 1);
2772   assert_node_ref_count (ref_model, &iter_parent2, 0);
2773 
2774   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, TRUE);
2775 
2776   assert_node_ref_count (ref_model, &grandparent1, 2);
2777   assert_node_ref_count (ref_model, &grandparent2, 2);
2778   assert_node_ref_count (ref_model, &parent1, 3);
2779   assert_node_ref_count (ref_model, &parent2, 2);
2780   assert_node_ref_count (ref_model, &iter_parent1, 2);
2781   assert_node_ref_count (ref_model, &iter_parent2_first, 2);
2782   assert_node_ref_count (ref_model, &iter_parent2, 1);
2783 
2784   gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view));
2785 
2786   assert_node_ref_count (ref_model, &grandparent1, 2);
2787   assert_node_ref_count (ref_model, &grandparent2, 2);
2788   assert_node_ref_count (ref_model, &parent1, 2);
2789   assert_node_ref_count (ref_model, &parent2, 1);
2790   assert_node_ref_count (ref_model, &iter_parent1, 1);
2791   assert_node_ref_count (ref_model, &iter_parent2_first, 1);
2792   assert_node_ref_count (ref_model, &iter_parent2, 0);
2793 
2794   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2795 
2796   assert_node_ref_count (ref_model, &grandparent1, 2);
2797   assert_node_ref_count (ref_model, &grandparent2, 2);
2798   assert_node_ref_count (ref_model, &parent1, 1);
2799   assert_node_ref_count (ref_model, &parent2, 0);
2800   assert_node_ref_count (ref_model, &iter_parent1, 0);
2801   assert_node_ref_count (ref_model, &iter_parent2_first, 0);
2802   assert_node_ref_count (ref_model, &iter_parent2, 0);
2803 
2804   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
2805 
2806   assert_node_ref_count (ref_model, &grandparent1, 2);
2807   assert_node_ref_count (ref_model, &grandparent2, 2);
2808   assert_node_ref_count (ref_model, &parent1, 3);
2809   assert_node_ref_count (ref_model, &parent2, 2);
2810   assert_node_ref_count (ref_model, &iter_parent1, 1);
2811   assert_node_ref_count (ref_model, &iter_parent2_first, 1);
2812   assert_node_ref_count (ref_model, &iter_parent2, 0);
2813 
2814   gtk_tree_path_append_index (path, 1);
2815   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
2816 
2817   assert_node_ref_count (ref_model, &grandparent1, 2);
2818   assert_node_ref_count (ref_model, &grandparent2, 2);
2819   assert_node_ref_count (ref_model, &parent1, 3);
2820   assert_node_ref_count (ref_model, &parent2, 2);
2821   assert_node_ref_count (ref_model, &iter_parent1, 1);
2822   assert_node_ref_count (ref_model, &iter_parent2_first, 2);
2823   assert_node_ref_count (ref_model, &iter_parent2, 1);
2824 
2825   gtk_tree_view_collapse_row (GTK_TREE_VIEW (tree_view), path);
2826 
2827   assert_node_ref_count (ref_model, &grandparent1, 2);
2828   assert_node_ref_count (ref_model, &grandparent2, 2);
2829   assert_node_ref_count (ref_model, &parent1, 3);
2830   assert_node_ref_count (ref_model, &parent2, 2);
2831   assert_node_ref_count (ref_model, &iter_parent1, 1);
2832   assert_node_ref_count (ref_model, &iter_parent2_first, 1);
2833   assert_node_ref_count (ref_model, &iter_parent2, 0);
2834 
2835   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2836 
2837   assert_node_ref_count (ref_model, &grandparent1, 2);
2838   assert_node_ref_count (ref_model, &grandparent2, 2);
2839   assert_node_ref_count (ref_model, &parent1, 3);
2840   assert_node_ref_count (ref_model, &parent2, 2);
2841   assert_node_ref_count (ref_model, &iter_parent1, 1);
2842   assert_node_ref_count (ref_model, &iter_parent2_first, 1);
2843   assert_node_ref_count (ref_model, &iter_parent2, 0);
2844 
2845   gtk_tree_path_up (path);
2846   gtk_tree_view_collapse_row (GTK_TREE_VIEW (tree_view), path);
2847   gtk_tree_path_free (path);
2848 
2849   assert_node_ref_count (ref_model, &grandparent1, 2);
2850   assert_node_ref_count (ref_model, &grandparent2, 2);
2851   assert_node_ref_count (ref_model, &parent1, 2);
2852   assert_node_ref_count (ref_model, &parent2, 1);
2853   assert_node_ref_count (ref_model, &iter_parent1, 1);
2854   assert_node_ref_count (ref_model, &iter_parent2_first, 1);
2855   assert_node_ref_count (ref_model, &iter_parent2, 0);
2856 
2857   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2858 
2859   assert_node_ref_count (ref_model, &grandparent1, 2);
2860   assert_node_ref_count (ref_model, &grandparent2, 2);
2861   assert_node_ref_count (ref_model, &parent1, 1);
2862   assert_node_ref_count (ref_model, &parent2, 0);
2863   assert_node_ref_count (ref_model, &iter_parent1, 0);
2864   assert_node_ref_count (ref_model, &iter_parent2_first, 0);
2865   assert_node_ref_count (ref_model, &iter_parent2, 0);
2866 
2867   g_object_unref (g_object_ref_sink (tree_view));
2868 
2869   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2870 
2871   /* The root level and first level remain cached, only the references on the
2872    * first nodes of these levels are kept.  Grandparent2 is the parent
2873    * of the first level with parent1, so grandparent2 keeps a reference
2874    * as well.
2875    */
2876   assert_node_ref_count (ref_model, &grandparent1, 1);
2877   assert_node_ref_count (ref_model, &grandparent2, 1);
2878   assert_node_ref_count (ref_model, &parent1, 1);
2879   assert_node_ref_count (ref_model, &parent2, 0);
2880   assert_node_ref_count (ref_model, &iter_parent1, 0);
2881   assert_node_ref_count (ref_model, &iter_parent2_first, 0);
2882   assert_node_ref_count (ref_model, &iter_parent2, 0);
2883 
2884   g_object_unref (filter_model);
2885   g_object_unref (ref_model);
2886 }
2887 
2888 static void
ref_count_delete_row(void)2889 ref_count_delete_row (void)
2890 {
2891   GtkTreeIter grandparent1, grandparent2, parent1, parent2;
2892   GtkTreeIter iter_parent1, iter_parent2, iter_parent2_first;
2893   GtkTreeModel *model;
2894   GtkTreeModelRefCount *ref_model;
2895   GtkTreeModel *filter_model;
2896   GtkTreePath *path;
2897   GtkWidget *tree_view;
2898 
2899   model = gtk_tree_model_ref_count_new ();
2900   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
2901 
2902   /* + grandparent1
2903    * + grandparent2
2904    *   + parent1
2905    *     + iter_parent1
2906    *   + parent2
2907    *     + iter_parent2_first
2908    *     + iter_parent2
2909    */
2910 
2911   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
2912   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
2913   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent2);
2914   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent1, &parent1);
2915   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent2);
2916   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent2_first, &parent2);
2917   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent2, &parent2);
2918 
2919   assert_entire_model_unreferenced (ref_model);
2920 
2921   filter_model = gtk_tree_model_filter_new (model, NULL);
2922   tree_view = gtk_tree_view_new_with_model (filter_model);
2923 
2924   assert_root_level_referenced (ref_model, 2);
2925   assert_node_ref_count (ref_model, &parent1, 1);
2926   assert_node_ref_count (ref_model, &parent2, 0);
2927   assert_level_unreferenced (ref_model, &parent1);
2928   assert_level_unreferenced (ref_model, &parent2);
2929 
2930   path = gtk_tree_path_new_from_indices (1, -1);
2931   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, TRUE);
2932   gtk_tree_path_free (path);
2933 
2934   assert_node_ref_count (ref_model, &grandparent1, 2);
2935   assert_node_ref_count (ref_model, &grandparent2, 2);
2936   assert_node_ref_count (ref_model, &parent1, 3);
2937   assert_node_ref_count (ref_model, &parent2, 2);
2938   assert_node_ref_count (ref_model, &iter_parent1, 2);
2939   assert_node_ref_count (ref_model, &iter_parent2_first, 2);
2940   assert_node_ref_count (ref_model, &iter_parent2, 1);
2941 
2942   gtk_tree_store_remove (GTK_TREE_STORE (model), &iter_parent2);
2943 
2944   assert_node_ref_count (ref_model, &grandparent1, 2);
2945   assert_node_ref_count (ref_model, &grandparent2, 2);
2946   assert_node_ref_count (ref_model, &parent1, 3);
2947   assert_node_ref_count (ref_model, &parent2, 2);
2948   assert_node_ref_count (ref_model, &iter_parent1, 2);
2949   assert_node_ref_count (ref_model, &iter_parent2_first, 2);
2950 
2951   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent1);
2952 
2953   assert_node_ref_count (ref_model, &grandparent1, 2);
2954   assert_node_ref_count (ref_model, &grandparent2, 2);
2955   assert_node_ref_count (ref_model, &parent2, 3);
2956   assert_level_referenced (ref_model, 2, &parent2);
2957 
2958   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent2);
2959 
2960   assert_node_ref_count (ref_model, &grandparent1, 2);
2961 
2962   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2963 
2964   assert_node_ref_count (ref_model, &grandparent1, 2);
2965 
2966   g_object_unref (g_object_ref_sink (tree_view));
2967   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
2968 
2969   assert_node_ref_count (ref_model, &grandparent1, 1);
2970 
2971   g_object_unref (filter_model);
2972 
2973   assert_node_ref_count (ref_model, &grandparent1, 0);
2974 
2975   g_object_unref (ref_model);
2976 }
2977 
2978 static void
ref_count_filter_row_length_1(void)2979 ref_count_filter_row_length_1 (void)
2980 {
2981   GtkTreeIter level1_1;
2982   GtkTreeIter level2_1;
2983   GtkTreeIter level3_1;
2984   GtkTreeIter level4_1;
2985   GtkTreeModel *model;
2986   GtkTreeModelRefCount *ref_model;
2987   GtkTreeModel *filter_model;
2988   GtkTreePath *path;
2989   GtkWidget *tree_view;
2990   GType column_types[] = { G_TYPE_BOOLEAN };
2991 
2992   model = gtk_tree_model_ref_count_new ();
2993   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
2994 
2995   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
2996                                    column_types);
2997 
2998 
2999   /* + level1_1
3000    *   + level2_1
3001    *     + level3_1
3002    *       + level4_1
3003    *
3004    * Node level1_1 is expanded.  This makes that levels 1 and 2 are
3005    * visible.  Level 3 is cached because its parent is visible.  Level 4
3006    * is not cached.
3007    */
3008 
3009   gtk_tree_store_append (GTK_TREE_STORE (model), &level1_1, NULL);
3010   gtk_tree_store_append (GTK_TREE_STORE (model), &level2_1, &level1_1);
3011   gtk_tree_store_append (GTK_TREE_STORE (model), &level3_1, &level2_1);
3012   gtk_tree_store_append (GTK_TREE_STORE (model), &level4_1, &level3_1);
3013 
3014   gtk_tree_store_set (GTK_TREE_STORE (model), &level1_1, 0, TRUE, -1);
3015   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_1, 0, TRUE, -1);
3016   gtk_tree_store_set (GTK_TREE_STORE (model), &level3_1, 0, TRUE, -1);
3017   gtk_tree_store_set (GTK_TREE_STORE (model), &level4_1, 0, TRUE, -1);
3018 
3019   assert_entire_model_unreferenced (ref_model);
3020 
3021   filter_model = gtk_tree_model_filter_new (model, NULL);
3022   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
3023   tree_view = gtk_tree_view_new_with_model (filter_model);
3024 
3025   assert_node_ref_count (ref_model, &level1_1, 3);
3026   assert_node_ref_count (ref_model, &level2_1, 1);
3027   assert_node_ref_count (ref_model, &level3_1, 0);
3028   assert_node_ref_count (ref_model, &level4_1, 0);
3029 
3030   path = gtk_tree_path_new_from_indices (0, -1);
3031   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
3032   gtk_tree_path_free (path);
3033 
3034   assert_node_ref_count (ref_model, &level1_1, 3);
3035   assert_node_ref_count (ref_model, &level2_1, 3);
3036   assert_node_ref_count (ref_model, &level3_1, 1);
3037   assert_node_ref_count (ref_model, &level4_1, 0);
3038 
3039   gtk_tree_store_set (GTK_TREE_STORE (model), &level4_1, 0, FALSE, -1);
3040 
3041   assert_node_ref_count (ref_model, &level1_1, 3);
3042   assert_node_ref_count (ref_model, &level2_1, 3);
3043   assert_node_ref_count (ref_model, &level3_1, 1);
3044   assert_node_ref_count (ref_model, &level4_1, 0);
3045 
3046   /* level3_1 has a visible parent, so the node is kept in the cache. */
3047   gtk_tree_store_set (GTK_TREE_STORE (model), &level3_1, 0, FALSE, -1);
3048 
3049   assert_node_ref_count (ref_model, &level1_1, 3);
3050   assert_node_ref_count (ref_model, &level2_1, 3);
3051   assert_node_ref_count (ref_model, &level3_1, 1);
3052   assert_node_ref_count (ref_model, &level4_1, 0);
3053 
3054   /* level2_1 has a visible parent, so is kept in the cache.  However,
3055    * the external reference should be released.
3056    */
3057   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_1, 0, FALSE, -1);
3058 
3059   assert_node_ref_count (ref_model, &level1_1, 3);
3060   assert_node_ref_count (ref_model, &level2_1, 1);
3061   assert_node_ref_count (ref_model, &level3_1, 0);
3062   assert_node_ref_count (ref_model, &level4_1, 0);
3063 
3064   gtk_tree_store_set (GTK_TREE_STORE (model), &level1_1, 0, FALSE, -1);
3065 
3066   assert_node_ref_count (ref_model, &level1_1, 2);
3067   assert_node_ref_count (ref_model, &level2_1, 1);
3068   assert_node_ref_count (ref_model, &level3_1, 0);
3069   assert_node_ref_count (ref_model, &level4_1, 0);
3070 
3071   g_object_unref (g_object_ref_sink (tree_view));
3072   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
3073 
3074   assert_node_ref_count (ref_model, &level1_1, 2);
3075   assert_node_ref_count (ref_model, &level2_1, 1);
3076 
3077   g_object_unref (filter_model);
3078 
3079   assert_node_ref_count (ref_model, &level1_1, 0);
3080 
3081   g_object_unref (ref_model);
3082 }
3083 
3084 static void
ref_count_filter_row_length_1_remove_in_root_level(void)3085 ref_count_filter_row_length_1_remove_in_root_level (void)
3086 {
3087   GtkTreeIter level1_1;
3088   GtkTreeIter level2_1;
3089   GtkTreeIter level3_1;
3090   GtkTreeIter level4_1;
3091   GtkTreeModel *model;
3092   GtkTreeModelRefCount *ref_model;
3093   GtkTreeModel *filter_model;
3094   GtkTreePath *path;
3095   GtkWidget *tree_view;
3096   GType column_types[] = { G_TYPE_BOOLEAN };
3097 
3098   model = gtk_tree_model_ref_count_new ();
3099   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3100 
3101   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
3102                                    column_types);
3103 
3104 
3105   /* + level1_1
3106    *   + level2_1
3107    *     + level3_1
3108    *       + level4_1
3109    */
3110 
3111   gtk_tree_store_append (GTK_TREE_STORE (model), &level1_1, NULL);
3112   gtk_tree_store_append (GTK_TREE_STORE (model), &level2_1, &level1_1);
3113   gtk_tree_store_append (GTK_TREE_STORE (model), &level3_1, &level2_1);
3114   gtk_tree_store_append (GTK_TREE_STORE (model), &level4_1, &level3_1);
3115 
3116   gtk_tree_store_set (GTK_TREE_STORE (model), &level1_1, 0, TRUE, -1);
3117   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_1, 0, TRUE, -1);
3118   gtk_tree_store_set (GTK_TREE_STORE (model), &level3_1, 0, TRUE, -1);
3119   gtk_tree_store_set (GTK_TREE_STORE (model), &level4_1, 0, TRUE, -1);
3120 
3121   assert_entire_model_unreferenced (ref_model);
3122 
3123   filter_model = gtk_tree_model_filter_new (model, NULL);
3124   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
3125   tree_view = gtk_tree_view_new_with_model (filter_model);
3126 
3127   assert_node_ref_count (ref_model, &level1_1, 3);
3128   assert_node_ref_count (ref_model, &level2_1, 1);
3129   assert_node_ref_count (ref_model, &level3_1, 0);
3130   assert_node_ref_count (ref_model, &level4_1, 0);
3131 
3132   path = gtk_tree_path_new_from_indices (0, -1);
3133   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, TRUE);
3134   gtk_tree_path_free (path);
3135 
3136   assert_node_ref_count (ref_model, &level1_1, 3);
3137   assert_node_ref_count (ref_model, &level2_1, 3);
3138   assert_node_ref_count (ref_model, &level3_1, 3);
3139   assert_node_ref_count (ref_model, &level4_1, 2);
3140 
3141   gtk_tree_store_set (GTK_TREE_STORE (model), &level1_1, 0, FALSE, -1);
3142 
3143   assert_node_ref_count (ref_model, &level1_1, 2);
3144   assert_node_ref_count (ref_model, &level2_1, 1);
3145   assert_node_ref_count (ref_model, &level3_1, 0);
3146   assert_node_ref_count (ref_model, &level4_1, 0);
3147 
3148   g_object_unref (g_object_ref_sink (tree_view));
3149   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
3150 
3151   assert_node_ref_count (ref_model, &level1_1, 2);
3152   assert_node_ref_count (ref_model, &level2_1, 1);
3153   assert_node_ref_count (ref_model, &level3_1, 0);
3154   assert_node_ref_count (ref_model, &level4_1, 0);
3155 
3156   g_object_unref (filter_model);
3157 
3158   assert_node_ref_count (ref_model, &level1_1, 0);
3159   assert_node_ref_count (ref_model, &level2_1, 0);
3160   assert_node_ref_count (ref_model, &level3_1, 0);
3161   assert_node_ref_count (ref_model, &level4_1, 0);
3162 
3163   g_object_unref (ref_model);
3164 }
3165 
3166 static void
ref_count_filter_row_length_1_remove_in_child_level(void)3167 ref_count_filter_row_length_1_remove_in_child_level (void)
3168 {
3169   GtkTreeIter level1_1;
3170   GtkTreeIter level2_1;
3171   GtkTreeIter level3_1;
3172   GtkTreeIter level4_1;
3173   GtkTreeModel *model;
3174   GtkTreeModelRefCount *ref_model;
3175   GtkTreeModel *filter_model;
3176   GtkTreePath *path;
3177   GtkWidget *tree_view;
3178   GType column_types[] = { G_TYPE_BOOLEAN };
3179 
3180   model = gtk_tree_model_ref_count_new ();
3181   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3182 
3183   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
3184                                    column_types);
3185 
3186 
3187   /* + level1_1
3188    *   + level2_1
3189    *     + level3_1
3190    *       + level4_1
3191    */
3192 
3193   gtk_tree_store_append (GTK_TREE_STORE (model), &level1_1, NULL);
3194   gtk_tree_store_append (GTK_TREE_STORE (model), &level2_1, &level1_1);
3195   gtk_tree_store_append (GTK_TREE_STORE (model), &level3_1, &level2_1);
3196   gtk_tree_store_append (GTK_TREE_STORE (model), &level4_1, &level3_1);
3197 
3198   gtk_tree_store_set (GTK_TREE_STORE (model), &level1_1, 0, TRUE, -1);
3199   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_1, 0, TRUE, -1);
3200   gtk_tree_store_set (GTK_TREE_STORE (model), &level3_1, 0, TRUE, -1);
3201   gtk_tree_store_set (GTK_TREE_STORE (model), &level4_1, 0, TRUE, -1);
3202 
3203   assert_entire_model_unreferenced (ref_model);
3204 
3205   filter_model = gtk_tree_model_filter_new (model, NULL);
3206   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
3207   tree_view = gtk_tree_view_new_with_model (filter_model);
3208 
3209   assert_node_ref_count (ref_model, &level1_1, 3);
3210   assert_node_ref_count (ref_model, &level2_1, 1);
3211   assert_node_ref_count (ref_model, &level3_1, 0);
3212   assert_node_ref_count (ref_model, &level4_1, 0);
3213 
3214   path = gtk_tree_path_new_from_indices (0, -1);
3215   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, TRUE);
3216   gtk_tree_path_free (path);
3217 
3218   assert_node_ref_count (ref_model, &level1_1, 3);
3219   assert_node_ref_count (ref_model, &level2_1, 3);
3220   assert_node_ref_count (ref_model, &level3_1, 3);
3221   assert_node_ref_count (ref_model, &level4_1, 2);
3222 
3223   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_1, 0, FALSE, -1);
3224 
3225   assert_node_ref_count (ref_model, &level1_1, 3);
3226   assert_node_ref_count (ref_model, &level2_1, 1);
3227   assert_node_ref_count (ref_model, &level3_1, 0);
3228   assert_node_ref_count (ref_model, &level4_1, 0);
3229 
3230   g_object_unref (g_object_ref_sink (tree_view));
3231   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
3232 
3233   assert_node_ref_count (ref_model, &level1_1, 2);
3234   assert_node_ref_count (ref_model, &level2_1, 1);
3235   assert_node_ref_count (ref_model, &level3_1, 0);
3236   assert_node_ref_count (ref_model, &level4_1, 0);
3237 
3238   g_object_unref (filter_model);
3239 
3240   assert_node_ref_count (ref_model, &level1_1, 0);
3241   assert_node_ref_count (ref_model, &level2_1, 0);
3242   assert_node_ref_count (ref_model, &level3_1, 0);
3243   assert_node_ref_count (ref_model, &level4_1, 0);
3244 
3245   g_object_unref (ref_model);
3246 }
3247 
3248 static void
ref_count_filter_row_length_gt_1(void)3249 ref_count_filter_row_length_gt_1 (void)
3250 {
3251   GtkTreeIter level1_1, level1_2;
3252   GtkTreeIter level2_1, level2_2;
3253   GtkTreeIter level3_1, level3_2;
3254   GtkTreeIter level4_1, level4_2;
3255   GtkTreeModel *model;
3256   GtkTreeModelRefCount *ref_model;
3257   GtkTreeModel *filter_model;
3258   GtkTreePath *path;
3259   GtkWidget *tree_view;
3260   GType column_types[] = { G_TYPE_BOOLEAN };
3261 
3262   model = gtk_tree_model_ref_count_new ();
3263   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3264 
3265   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
3266                                    column_types);
3267 
3268 
3269   /* + level1_1
3270    * + level1_2
3271    *   + level2_1
3272    *   + level2_2
3273    *     + level3_1
3274    *     + level3_2
3275    *       + level4_1
3276    *       + level4_2
3277    *
3278    * Node level1_2 is expanded.  This makes that levels 1 and 2 are
3279    * visible.  Level 3 is cached because its parent is visible.  Level 4
3280    * is not cached.
3281    */
3282 
3283   gtk_tree_store_append (GTK_TREE_STORE (model), &level1_1, NULL);
3284   gtk_tree_store_append (GTK_TREE_STORE (model), &level1_2, NULL);
3285   gtk_tree_store_append (GTK_TREE_STORE (model), &level2_1, &level1_2);
3286   gtk_tree_store_append (GTK_TREE_STORE (model), &level2_2, &level1_2);
3287   gtk_tree_store_append (GTK_TREE_STORE (model), &level3_1, &level2_2);
3288   gtk_tree_store_append (GTK_TREE_STORE (model), &level3_2, &level2_2);
3289   gtk_tree_store_append (GTK_TREE_STORE (model), &level4_1, &level3_2);
3290   gtk_tree_store_append (GTK_TREE_STORE (model), &level4_2, &level3_2);
3291 
3292   gtk_tree_store_set (GTK_TREE_STORE (model), &level1_1, 0, TRUE, -1);
3293   gtk_tree_store_set (GTK_TREE_STORE (model), &level1_2, 0, TRUE, -1);
3294   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_1, 0, TRUE, -1);
3295   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_2, 0, TRUE, -1);
3296   gtk_tree_store_set (GTK_TREE_STORE (model), &level3_1, 0, TRUE, -1);
3297   gtk_tree_store_set (GTK_TREE_STORE (model), &level3_2, 0, TRUE, -1);
3298   gtk_tree_store_set (GTK_TREE_STORE (model), &level4_1, 0, TRUE, -1);
3299   gtk_tree_store_set (GTK_TREE_STORE (model), &level4_2, 0, TRUE, -1);
3300 
3301   assert_entire_model_unreferenced (ref_model);
3302 
3303   filter_model = gtk_tree_model_filter_new (model, NULL);
3304   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
3305   tree_view = gtk_tree_view_new_with_model (filter_model);
3306 
3307   assert_node_ref_count (ref_model, &level1_1, 2);
3308   assert_node_ref_count (ref_model, &level1_2, 2);
3309   assert_node_ref_count (ref_model, &level2_1, 1);
3310   assert_node_ref_count (ref_model, &level2_2, 0);
3311   assert_node_ref_count (ref_model, &level3_1, 0);
3312   assert_node_ref_count (ref_model, &level3_2, 0);
3313   assert_node_ref_count (ref_model, &level4_1, 0);
3314   assert_node_ref_count (ref_model, &level4_2, 0);
3315 
3316   path = gtk_tree_path_new_from_indices (1, -1);
3317   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
3318   gtk_tree_path_free (path);
3319 
3320   assert_node_ref_count (ref_model, &level1_1, 2);
3321   assert_node_ref_count (ref_model, &level1_2, 2);
3322   assert_node_ref_count (ref_model, &level2_1, 2);
3323   assert_node_ref_count (ref_model, &level2_2, 2);
3324   assert_node_ref_count (ref_model, &level3_1, 1);
3325   assert_node_ref_count (ref_model, &level3_2, 0);
3326   assert_node_ref_count (ref_model, &level4_1, 0);
3327   assert_node_ref_count (ref_model, &level4_2, 0);
3328 
3329   gtk_tree_store_set (GTK_TREE_STORE (model), &level4_1, 0, FALSE, -1);
3330 
3331   assert_node_ref_count (ref_model, &level1_1, 2);
3332   assert_node_ref_count (ref_model, &level1_2, 2);
3333   assert_node_ref_count (ref_model, &level2_1, 2);
3334   assert_node_ref_count (ref_model, &level2_2, 2);
3335   assert_node_ref_count (ref_model, &level3_1, 1);
3336   assert_node_ref_count (ref_model, &level3_2, 0);
3337   assert_node_ref_count (ref_model, &level4_1, 0);
3338   assert_node_ref_count (ref_model, &level4_2, 0);
3339 
3340   gtk_tree_store_set (GTK_TREE_STORE (model), &level3_1, 0, FALSE, -1);
3341 
3342   assert_node_ref_count (ref_model, &level1_1, 2);
3343   assert_node_ref_count (ref_model, &level1_2, 2);
3344   assert_node_ref_count (ref_model, &level2_1, 2);
3345   assert_node_ref_count (ref_model, &level2_2, 2);
3346   assert_node_ref_count (ref_model, &level3_1, 0);
3347   assert_node_ref_count (ref_model, &level3_2, 1);
3348   assert_node_ref_count (ref_model, &level4_1, 0);
3349   assert_node_ref_count (ref_model, &level4_2, 0);
3350 
3351   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_2, 0, FALSE, -1);
3352 
3353   assert_node_ref_count (ref_model, &level1_1, 2);
3354   assert_node_ref_count (ref_model, &level1_2, 2);
3355   assert_node_ref_count (ref_model, &level2_1, 2);
3356   assert_node_ref_count (ref_model, &level2_2, 0);
3357   assert_node_ref_count (ref_model, &level3_1, 0);
3358   assert_node_ref_count (ref_model, &level3_2, 0);
3359   assert_node_ref_count (ref_model, &level4_1, 0);
3360   assert_node_ref_count (ref_model, &level4_2, 0);
3361 
3362   gtk_tree_store_set (GTK_TREE_STORE (model), &level1_2, 0, FALSE, -1);
3363 
3364   assert_node_ref_count (ref_model, &level1_1, 2);
3365   assert_node_ref_count (ref_model, &level1_2, 0);
3366   assert_node_ref_count (ref_model, &level2_1, 0);
3367   assert_node_ref_count (ref_model, &level2_2, 0);
3368   assert_node_ref_count (ref_model, &level3_1, 0);
3369   assert_node_ref_count (ref_model, &level3_2, 0);
3370   assert_node_ref_count (ref_model, &level4_1, 0);
3371   assert_node_ref_count (ref_model, &level4_2, 0);
3372 
3373   g_object_unref (g_object_ref_sink (tree_view));
3374   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
3375 
3376   assert_node_ref_count (ref_model, &level1_1, 1);
3377 
3378   g_object_unref (filter_model);
3379 
3380   assert_node_ref_count (ref_model, &level1_1, 0);
3381 
3382   g_object_unref (ref_model);
3383 }
3384 
3385 static void
ref_count_filter_row_length_gt_1_visible_children(void)3386 ref_count_filter_row_length_gt_1_visible_children (void)
3387 {
3388   GtkTreeIter level1_1, level1_2;
3389   GtkTreeIter level2_1, level2_2;
3390   GtkTreeIter level3_1, level3_2;
3391   GtkTreeIter level4_1, level4_2;
3392   GtkTreeModel *model;
3393   GtkTreeModelRefCount *ref_model;
3394   GtkTreeModel *filter_model;
3395   GtkTreePath *path;
3396   GtkWidget *tree_view;
3397   GType column_types[] = { G_TYPE_BOOLEAN };
3398 
3399   model = gtk_tree_model_ref_count_new ();
3400   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3401 
3402   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
3403                                    column_types);
3404 
3405 
3406   /* + level1_1
3407    * + level1_2
3408    *   + level2_1
3409    *   + level2_2
3410    *     + level3_1
3411    *     + level3_2
3412    *       + level4_1
3413    *       + level4_2
3414    */
3415 
3416   gtk_tree_store_append (GTK_TREE_STORE (model), &level1_1, NULL);
3417   gtk_tree_store_append (GTK_TREE_STORE (model), &level1_2, NULL);
3418   gtk_tree_store_append (GTK_TREE_STORE (model), &level2_1, &level1_2);
3419   gtk_tree_store_append (GTK_TREE_STORE (model), &level2_2, &level1_2);
3420   gtk_tree_store_append (GTK_TREE_STORE (model), &level3_1, &level2_2);
3421   gtk_tree_store_append (GTK_TREE_STORE (model), &level3_2, &level2_2);
3422   gtk_tree_store_append (GTK_TREE_STORE (model), &level4_1, &level3_2);
3423   gtk_tree_store_append (GTK_TREE_STORE (model), &level4_2, &level3_2);
3424 
3425   gtk_tree_store_set (GTK_TREE_STORE (model), &level1_1, 0, TRUE, -1);
3426   gtk_tree_store_set (GTK_TREE_STORE (model), &level1_2, 0, TRUE, -1);
3427   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_1, 0, TRUE, -1);
3428   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_2, 0, TRUE, -1);
3429   gtk_tree_store_set (GTK_TREE_STORE (model), &level3_1, 0, TRUE, -1);
3430   gtk_tree_store_set (GTK_TREE_STORE (model), &level3_2, 0, TRUE, -1);
3431   gtk_tree_store_set (GTK_TREE_STORE (model), &level4_1, 0, TRUE, -1);
3432   gtk_tree_store_set (GTK_TREE_STORE (model), &level4_2, 0, TRUE, -1);
3433 
3434   assert_entire_model_unreferenced (ref_model);
3435 
3436   filter_model = gtk_tree_model_filter_new (model, NULL);
3437   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
3438   tree_view = gtk_tree_view_new_with_model (filter_model);
3439 
3440   assert_node_ref_count (ref_model, &level1_1, 2);
3441   assert_node_ref_count (ref_model, &level1_2, 2);
3442   assert_node_ref_count (ref_model, &level2_1, 1);
3443   assert_node_ref_count (ref_model, &level2_2, 0);
3444   assert_node_ref_count (ref_model, &level3_1, 0);
3445   assert_node_ref_count (ref_model, &level3_2, 0);
3446   assert_node_ref_count (ref_model, &level4_1, 0);
3447   assert_node_ref_count (ref_model, &level4_2, 0);
3448 
3449   path = gtk_tree_path_new_from_indices (1, -1);
3450   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, TRUE);
3451   gtk_tree_path_free (path);
3452 
3453   assert_node_ref_count (ref_model, &level1_1, 2);
3454   assert_node_ref_count (ref_model, &level1_2, 2);
3455   assert_node_ref_count (ref_model, &level2_1, 2);
3456   assert_node_ref_count (ref_model, &level2_2, 2);
3457   assert_node_ref_count (ref_model, &level3_1, 2);
3458   assert_node_ref_count (ref_model, &level3_2, 2);
3459   assert_node_ref_count (ref_model, &level4_1, 2);
3460   assert_node_ref_count (ref_model, &level4_2, 1);
3461 
3462   gtk_tree_store_set (GTK_TREE_STORE (model), &level2_2, 0, FALSE, -1);
3463 
3464   assert_node_ref_count (ref_model, &level1_1, 2);
3465   assert_node_ref_count (ref_model, &level1_2, 2);
3466   assert_node_ref_count (ref_model, &level2_1, 2);
3467   assert_node_ref_count (ref_model, &level2_2, 0);
3468   assert_node_ref_count (ref_model, &level3_1, 0);
3469   assert_node_ref_count (ref_model, &level3_2, 0);
3470   assert_node_ref_count (ref_model, &level4_1, 0);
3471   assert_node_ref_count (ref_model, &level4_2, 0);
3472 
3473   g_object_unref (g_object_ref_sink (tree_view));
3474   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
3475 
3476   assert_node_ref_count (ref_model, &level1_1, 1);
3477   assert_node_ref_count (ref_model, &level1_2, 1);
3478   assert_node_ref_count (ref_model, &level2_1, 1);
3479   assert_node_ref_count (ref_model, &level2_2, 0);
3480   assert_node_ref_count (ref_model, &level3_1, 0);
3481   assert_node_ref_count (ref_model, &level3_2, 0);
3482   assert_node_ref_count (ref_model, &level4_1, 0);
3483   assert_node_ref_count (ref_model, &level4_2, 0);
3484 
3485   g_object_unref (filter_model);
3486 
3487   assert_node_ref_count (ref_model, &level1_1, 0);
3488   assert_node_ref_count (ref_model, &level1_2, 0);
3489   assert_node_ref_count (ref_model, &level2_1, 0);
3490   assert_node_ref_count (ref_model, &level2_2, 0);
3491   assert_node_ref_count (ref_model, &level3_1, 0);
3492   assert_node_ref_count (ref_model, &level3_2, 0);
3493   assert_node_ref_count (ref_model, &level4_1, 0);
3494   assert_node_ref_count (ref_model, &level4_2, 0);
3495 
3496   g_object_unref (ref_model);
3497 }
3498 
3499 static void
ref_count_cleanup(void)3500 ref_count_cleanup (void)
3501 {
3502   GtkTreeIter grandparent1, grandparent2, parent1, parent2;
3503   GtkTreeIter iter_parent1, iter_parent2, iter_parent2_first;
3504   GtkTreeModel *model;
3505   GtkTreeModelRefCount *ref_model;
3506   GtkTreeModel *filter_model;
3507   GtkWidget *tree_view;
3508 
3509   model = gtk_tree_model_ref_count_new ();
3510   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3511 
3512   /* + grandparent1
3513    * + grandparent2
3514    *   + parent1
3515    *     + iter_parent1
3516    *   + parent2
3517    *     + iter_parent2_first
3518    *     + iter_parent2
3519    */
3520 
3521   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
3522   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3523   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent2);
3524   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent1, &parent1);
3525   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent2);
3526   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent2_first, &parent2);
3527   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent2, &parent2);
3528 
3529   filter_model = gtk_tree_model_filter_new (model, NULL);
3530   tree_view = gtk_tree_view_new_with_model (filter_model);
3531 
3532   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
3533 
3534   assert_node_ref_count (ref_model, &grandparent1, 2);
3535   assert_node_ref_count (ref_model, &grandparent2, 2);
3536   assert_node_ref_count (ref_model, &parent1, 3);
3537   assert_node_ref_count (ref_model, &parent2, 2);
3538   assert_node_ref_count (ref_model, &iter_parent1, 2);
3539   assert_node_ref_count (ref_model, &iter_parent2_first, 2);
3540   assert_node_ref_count (ref_model, &iter_parent2, 1);
3541 
3542   g_object_unref (g_object_ref_sink (tree_view));
3543 
3544   assert_node_ref_count (ref_model, &grandparent1, 1);
3545   assert_node_ref_count (ref_model, &grandparent2, 1);
3546   assert_node_ref_count (ref_model, &parent1, 2);
3547   assert_node_ref_count (ref_model, &parent2, 1);
3548   assert_node_ref_count (ref_model, &iter_parent1, 1);
3549   assert_node_ref_count (ref_model, &iter_parent2_first, 1);
3550   assert_node_ref_count (ref_model, &iter_parent2, 0);
3551 
3552   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
3553 
3554   /* The root level and first level remain cached, only the references on the
3555    * first nodes of these levels are kept.  Grandparent2 is the parent
3556    * of the first level with parent1, so grandparent2 keeps a reference
3557    * as well.
3558    */
3559   assert_node_ref_count (ref_model, &grandparent1, 1);
3560   assert_node_ref_count (ref_model, &grandparent2, 1);
3561   assert_node_ref_count (ref_model, &parent1, 1);
3562   assert_node_ref_count (ref_model, &parent2, 0);
3563   assert_node_ref_count (ref_model, &iter_parent1, 0);
3564   assert_node_ref_count (ref_model, &iter_parent2_first, 0);
3565   assert_node_ref_count (ref_model, &iter_parent2, 0);
3566 
3567   g_object_unref (filter_model);
3568   g_object_unref (ref_model);
3569 }
3570 
3571 static void
ref_count_row_ref(void)3572 ref_count_row_ref (void)
3573 {
3574   GtkTreeIter grandparent1, grandparent2, parent1, parent2;
3575   GtkTreeIter iter_parent1, iter_parent2, iter_parent2_first;
3576   GtkTreeModel *model;
3577   GtkTreeModelRefCount *ref_model;
3578   GtkTreeModel *filter_model;
3579   GtkWidget *tree_view;
3580   GtkTreePath *path;
3581   GtkTreeRowReference *row_ref;
3582 
3583   model = gtk_tree_model_ref_count_new ();
3584   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3585 
3586   /* + grandparent1
3587    * + grandparent2
3588    *   + parent1
3589    *     + iter_parent1
3590    *   + parent2
3591    *     + iter_parent2
3592    *     + iter_parent2
3593    */
3594 
3595   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
3596   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3597   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent2);
3598   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent1, &parent1);
3599   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent2);
3600   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent2_first, &parent2);
3601   gtk_tree_store_append (GTK_TREE_STORE (model), &iter_parent2, &parent2);
3602 
3603   filter_model = gtk_tree_model_filter_new (model, NULL);
3604   tree_view = gtk_tree_view_new_with_model (filter_model);
3605 
3606   path = gtk_tree_path_new_from_indices (1, 1, 1, -1);
3607   row_ref = gtk_tree_row_reference_new (filter_model, path);
3608   gtk_tree_path_free (path);
3609 
3610   assert_node_ref_count (ref_model, &grandparent1, 2);
3611   assert_node_ref_count (ref_model, &grandparent2, 3);
3612   assert_node_ref_count (ref_model, &parent1, 1);
3613   assert_node_ref_count (ref_model, &parent2, 2);
3614   assert_node_ref_count (ref_model, &iter_parent1, 0);
3615   assert_node_ref_count (ref_model, &iter_parent2_first, 1);
3616   assert_node_ref_count (ref_model, &iter_parent2, 1);
3617 
3618   gtk_tree_row_reference_free (row_ref);
3619 
3620   assert_node_ref_count (ref_model, &grandparent1, 2);
3621   assert_node_ref_count (ref_model, &grandparent2, 2);
3622   assert_node_ref_count (ref_model, &parent1, 1);
3623   assert_node_ref_count (ref_model, &parent2, 1);
3624   assert_node_ref_count (ref_model, &iter_parent1, 0);
3625   assert_node_ref_count (ref_model, &iter_parent2_first, 1);
3626   assert_node_ref_count (ref_model, &iter_parent2, 0);
3627 
3628   path = gtk_tree_path_new_from_indices (1, 1, 1, -1);
3629   row_ref = gtk_tree_row_reference_new (filter_model, path);
3630   gtk_tree_path_free (path);
3631 
3632   assert_node_ref_count (ref_model, &grandparent1, 2);
3633   assert_node_ref_count (ref_model, &grandparent2, 3);
3634   assert_node_ref_count (ref_model, &parent1, 1);
3635   assert_node_ref_count (ref_model, &parent2, 2);
3636   assert_node_ref_count (ref_model, &iter_parent1, 0);
3637   assert_node_ref_count (ref_model, &iter_parent2_first, 1);
3638   assert_node_ref_count (ref_model, &iter_parent2, 1);
3639 
3640   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent2);
3641 
3642   assert_node_ref_count (ref_model, &grandparent1, 2);
3643   assert_node_ref_count (ref_model, &grandparent2, 2);
3644   assert_node_ref_count (ref_model, &parent1, 1);
3645   assert_node_ref_count (ref_model, &iter_parent1, 0);
3646 
3647   gtk_tree_row_reference_free (row_ref);
3648 
3649   assert_node_ref_count (ref_model, &grandparent1, 2);
3650   assert_node_ref_count (ref_model, &grandparent2, 2);
3651   assert_node_ref_count (ref_model, &parent1, 1);
3652   assert_node_ref_count (ref_model, &iter_parent1, 0);
3653 
3654   g_object_unref (g_object_ref_sink (tree_view));
3655 
3656   gtk_tree_model_filter_clear_cache (GTK_TREE_MODEL_FILTER (filter_model));
3657 
3658   /* The root level and first level remain cached, only the references on the
3659    * first nodes of these levels are kept.  Grandparent2 is the parent
3660    * of the first level with parent1, so grandparent2 keeps a reference
3661    * as well.
3662    */
3663   assert_node_ref_count (ref_model, &grandparent1, 1);
3664   assert_node_ref_count (ref_model, &grandparent2, 1);
3665   assert_node_ref_count (ref_model, &parent1, 1);
3666 
3667   g_object_unref (filter_model);
3668   g_object_unref (ref_model);
3669 }
3670 
3671 static void
ref_count_transfer_root_level_insert(void)3672 ref_count_transfer_root_level_insert (void)
3673 {
3674   GtkTreeIter grandparent1, grandparent2, grandparent3;
3675   GtkTreeIter new_node;
3676   GtkTreeModel *model;
3677   GtkTreeModelRefCount *ref_model;
3678   GtkTreeModel *filter_model;
3679   GtkWidget *tree_view;
3680 
3681   model = gtk_tree_model_ref_count_new ();
3682   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3683 
3684   /* + grandparent1
3685    * + grandparent2
3686    * + grandparent3
3687    */
3688 
3689   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
3690   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3691   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, NULL);
3692 
3693   filter_model = gtk_tree_model_filter_new (model, NULL);
3694   tree_view = gtk_tree_view_new_with_model (filter_model);
3695 
3696   assert_node_ref_count (ref_model, &grandparent1, 2);
3697   assert_node_ref_count (ref_model, &grandparent2, 1);
3698   assert_node_ref_count (ref_model, &grandparent3, 1);
3699 
3700   gtk_tree_store_prepend (GTK_TREE_STORE (model), &new_node, NULL);
3701 
3702   assert_node_ref_count (ref_model, &new_node, 2);
3703   assert_node_ref_count (ref_model, &grandparent1, 1);
3704   assert_node_ref_count (ref_model, &grandparent2, 1);
3705   assert_node_ref_count (ref_model, &grandparent3, 1);
3706 
3707   g_object_unref (g_object_ref_sink (tree_view));
3708   g_object_unref (filter_model);
3709   g_object_unref (ref_model);
3710 }
3711 
3712 static void
ref_count_transfer_root_level_remove(void)3713 ref_count_transfer_root_level_remove (void)
3714 {
3715   GtkTreeIter grandparent1, grandparent2, grandparent3;
3716   GtkTreeModel *model;
3717   GtkTreeModelRefCount *ref_model;
3718   GtkTreeModel *filter_model;
3719   GtkWidget *tree_view;
3720 
3721   model = gtk_tree_model_ref_count_new ();
3722   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3723 
3724   /* + grandparent1
3725    * + grandparent2
3726    * + grandparent3
3727    */
3728 
3729   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
3730   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3731   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, NULL);
3732 
3733   filter_model = gtk_tree_model_filter_new (model, NULL);
3734   tree_view = gtk_tree_view_new_with_model (filter_model);
3735 
3736   assert_node_ref_count (ref_model, &grandparent1, 2);
3737   assert_node_ref_count (ref_model, &grandparent2, 1);
3738   assert_node_ref_count (ref_model, &grandparent3, 1);
3739 
3740   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent1);
3741 
3742   assert_node_ref_count (ref_model, &grandparent2, 2);
3743   assert_node_ref_count (ref_model, &grandparent3, 1);
3744 
3745   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent2);
3746 
3747   assert_node_ref_count (ref_model, &grandparent3, 2);
3748 
3749   g_object_unref (g_object_ref_sink (tree_view));
3750   g_object_unref (filter_model);
3751   g_object_unref (ref_model);
3752 }
3753 
3754 static void
ref_count_transfer_root_level_remove_filtered(void)3755 ref_count_transfer_root_level_remove_filtered (void)
3756 {
3757   GtkTreeIter grandparent1, grandparent2, grandparent3, grandparent4;
3758   GtkTreeModel *model;
3759   GtkTreeModelRefCount *ref_model;
3760   GtkTreeModel *filter_model;
3761   GtkWidget *tree_view;
3762   GType column_types[] = { G_TYPE_BOOLEAN };
3763 
3764   model = gtk_tree_model_ref_count_new ();
3765   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3766 
3767   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
3768                                    column_types);
3769 
3770   /* + grandparent1
3771    * + grandparent2
3772    * + grandparent3
3773    * + grandparent4
3774    */
3775 
3776   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
3777   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3778   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, NULL);
3779   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent4, NULL);
3780 
3781   /* Filter first node */
3782   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
3783   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
3784   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, TRUE, -1);
3785   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, TRUE, -1);
3786 
3787   filter_model = gtk_tree_model_filter_new (model, NULL);
3788   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
3789   tree_view = gtk_tree_view_new_with_model (filter_model);
3790 
3791   assert_node_ref_count (ref_model, &grandparent1, 0);
3792   assert_node_ref_count (ref_model, &grandparent2, 2);
3793   assert_node_ref_count (ref_model, &grandparent3, 1);
3794   assert_node_ref_count (ref_model, &grandparent4, 1);
3795 
3796   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent2);
3797 
3798   assert_node_ref_count (ref_model, &grandparent1, 0);
3799   assert_node_ref_count (ref_model, &grandparent3, 2);
3800   assert_node_ref_count (ref_model, &grandparent4, 1);
3801 
3802   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent3);
3803 
3804   assert_node_ref_count (ref_model, &grandparent1, 0);
3805   assert_node_ref_count (ref_model, &grandparent4, 2);
3806 
3807   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent4);
3808 
3809   /* Check level length to get root level cached again */
3810   check_level_length (GTK_TREE_MODEL_FILTER (filter_model), NULL, 0);
3811 
3812   assert_node_ref_count (ref_model, &grandparent1, 1);
3813 
3814   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3815 
3816   assert_node_ref_count (ref_model, &grandparent1, 1);
3817   assert_node_ref_count (ref_model, &grandparent2, 0);
3818 
3819   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
3820 
3821   assert_node_ref_count (ref_model, &grandparent1, 1);
3822   assert_node_ref_count (ref_model, &grandparent2, 1);
3823 
3824   check_level_length (GTK_TREE_MODEL_FILTER (filter_model), NULL, 1);
3825 
3826   g_object_unref (g_object_ref_sink (tree_view));
3827   g_object_unref (filter_model);
3828   g_object_unref (ref_model);
3829 }
3830 
3831 static void
ref_count_transfer_root_level_reordered(void)3832 ref_count_transfer_root_level_reordered (void)
3833 {
3834   GtkTreeIter grandparent1, grandparent2, grandparent3;
3835   GtkTreeModel *model;
3836   GtkTreeModelRefCount *ref_model;
3837   GtkTreeModel *filter_model;
3838   GtkWidget *tree_view;
3839 
3840   model = gtk_tree_model_ref_count_new ();
3841   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3842 
3843   /* + grandparent1
3844    * + grandparent2
3845    * + grandparent3
3846    */
3847 
3848   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
3849   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3850   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, NULL);
3851 
3852   filter_model = gtk_tree_model_filter_new (model, NULL);
3853   tree_view = gtk_tree_view_new_with_model (filter_model);
3854 
3855   assert_node_ref_count (ref_model, &grandparent1, 2);
3856   assert_node_ref_count (ref_model, &grandparent2, 1);
3857   assert_node_ref_count (ref_model, &grandparent3, 1);
3858 
3859   /* gtk_tree_store_move() will emit rows-reordered */
3860   gtk_tree_store_move_after (GTK_TREE_STORE (model),
3861                              &grandparent1, &grandparent3);
3862 
3863   assert_node_ref_count (ref_model, &grandparent2, 2);
3864   assert_node_ref_count (ref_model, &grandparent3, 1);
3865   assert_node_ref_count (ref_model, &grandparent1, 1);
3866 
3867   g_object_unref (g_object_ref_sink (tree_view));
3868   g_object_unref (filter_model);
3869   g_object_unref (ref_model);
3870 }
3871 
3872 static void
ref_count_transfer_root_level_reordered_filtered(void)3873 ref_count_transfer_root_level_reordered_filtered (void)
3874 {
3875   GtkTreeIter grandparent1, grandparent2, grandparent3;
3876   GtkTreeModel *model;
3877   GtkTreeModelRefCount *ref_model;
3878   GtkTreeModel *filter_model;
3879   GtkWidget *tree_view;
3880   GType column_types[] = { G_TYPE_BOOLEAN };
3881 
3882   model = gtk_tree_model_ref_count_new ();
3883   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3884 
3885   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
3886                                    column_types);
3887 
3888   /* + grandparent1
3889    * + grandparent2
3890    * + grandparent3
3891    */
3892 
3893   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
3894   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3895   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, NULL);
3896 
3897   /* Test with 1 node filtered */
3898   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
3899   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, TRUE, -1);
3900 
3901   filter_model = gtk_tree_model_filter_new (model, NULL);
3902   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
3903   tree_view = gtk_tree_view_new_with_model (filter_model);
3904 
3905   assert_node_ref_count (ref_model, &grandparent1, 0);
3906   assert_node_ref_count (ref_model, &grandparent2, 2);
3907   assert_node_ref_count (ref_model, &grandparent3, 1);
3908 
3909   /* Move the invisible node grandparent1 */
3910 
3911   /* gtk_tree_store_move() will emit rows-reordered */
3912   gtk_tree_store_move_after (GTK_TREE_STORE (model),
3913                              &grandparent1, &grandparent3);
3914 
3915   assert_node_ref_count (ref_model, &grandparent2, 2);
3916   assert_node_ref_count (ref_model, &grandparent3, 1);
3917   assert_node_ref_count (ref_model, &grandparent1, 0);
3918 
3919   /* Move the invisible node grandparent1 */
3920 
3921   /* gtk_tree_store_move() will emit rows-reordered */
3922   gtk_tree_store_move_before (GTK_TREE_STORE (model),
3923                               &grandparent1, &grandparent2);
3924 
3925   assert_node_ref_count (ref_model, &grandparent1, 0);
3926   assert_node_ref_count (ref_model, &grandparent2, 2);
3927   assert_node_ref_count (ref_model, &grandparent3, 1);
3928 
3929   /* Now swap grandparent2 and grandparent3, first reference must transfer */
3930   /* gtk_tree_store_swap() will emit rows-reordered */
3931   gtk_tree_store_swap (GTK_TREE_STORE (model),
3932                        &grandparent2, &grandparent3);
3933 
3934   assert_node_ref_count (ref_model, &grandparent1, 0);
3935   assert_node_ref_count (ref_model, &grandparent3, 2);
3936   assert_node_ref_count (ref_model, &grandparent2, 1);
3937 
3938   /* Swap back */
3939   gtk_tree_store_swap (GTK_TREE_STORE (model),
3940                        &grandparent2, &grandparent3);
3941 
3942   assert_node_ref_count (ref_model, &grandparent1, 0);
3943   assert_node_ref_count (ref_model, &grandparent2, 2);
3944   assert_node_ref_count (ref_model, &grandparent3, 1);
3945 
3946   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, TRUE, -1);
3947 
3948   assert_node_ref_count (ref_model, &grandparent1, 2);
3949   assert_node_ref_count (ref_model, &grandparent2, 1);
3950   assert_node_ref_count (ref_model, &grandparent3, 1);
3951 
3952   /* Test with two nodes filtered */
3953   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
3954   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, FALSE, -1);
3955 
3956   assert_node_ref_count (ref_model, &grandparent1, 0);
3957   assert_node_ref_count (ref_model, &grandparent2, 0);
3958   assert_node_ref_count (ref_model, &grandparent3, 2);
3959 
3960   /* gtk_tree_store_move() will emit rows-reordered */
3961   gtk_tree_store_move_before (GTK_TREE_STORE (model),
3962                              &grandparent3, &grandparent1);
3963 
3964   assert_node_ref_count (ref_model, &grandparent3, 2);
3965   assert_node_ref_count (ref_model, &grandparent2, 0);
3966   assert_node_ref_count (ref_model, &grandparent1, 0);
3967 
3968   g_object_unref (g_object_ref_sink (tree_view));
3969   g_object_unref (filter_model);
3970   g_object_unref (ref_model);
3971 }
3972 
3973 static void
ref_count_transfer_root_level_filter(void)3974 ref_count_transfer_root_level_filter (void)
3975 {
3976   GtkTreeIter grandparent1, grandparent2, grandparent3, grandparent4;
3977   GtkTreeIter new_node;
3978   GtkTreeModel *model;
3979   GtkTreeModelRefCount *ref_model;
3980   GtkTreeModel *filter_model;
3981   GtkWidget *tree_view;
3982   GType column_types[] = { G_TYPE_BOOLEAN };
3983 
3984   model = gtk_tree_model_ref_count_new ();
3985   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
3986 
3987   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
3988                                    column_types);
3989 
3990   /* + grandparent1
3991    * + grandparent2
3992    * + grandparent3
3993    * + grandparent4
3994    */
3995 
3996   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
3997   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, NULL);
3998   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, NULL);
3999   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent4, NULL);
4000 
4001   /* Filter first node */
4002   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
4003   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
4004   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, TRUE, -1);
4005   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, TRUE, -1);
4006 
4007   filter_model = gtk_tree_model_filter_new (model, NULL);
4008   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
4009   tree_view = gtk_tree_view_new_with_model (filter_model);
4010 
4011   assert_node_ref_count (ref_model, &grandparent1, 0);
4012   assert_node_ref_count (ref_model, &grandparent2, 2);
4013   assert_node_ref_count (ref_model, &grandparent3, 1);
4014   assert_node_ref_count (ref_model, &grandparent4, 1);
4015 
4016   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, FALSE, -1);
4017 
4018   assert_node_ref_count (ref_model, &grandparent1, 0);
4019   assert_node_ref_count (ref_model, &grandparent2, 0);
4020   assert_node_ref_count (ref_model, &grandparent3, 2);
4021   assert_node_ref_count (ref_model, &grandparent4, 1);
4022 
4023   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, FALSE, -1);
4024 
4025   assert_node_ref_count (ref_model, &grandparent1, 0);
4026   assert_node_ref_count (ref_model, &grandparent2, 0);
4027   assert_node_ref_count (ref_model, &grandparent3, 0);
4028   assert_node_ref_count (ref_model, &grandparent4, 2);
4029 
4030   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, FALSE, -1);
4031 
4032   assert_node_ref_count (ref_model, &grandparent1, 0);
4033   assert_node_ref_count (ref_model, &grandparent2, 0);
4034   assert_node_ref_count (ref_model, &grandparent3, 0);
4035   assert_node_ref_count (ref_model, &grandparent4, 1);
4036 
4037   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
4038 
4039   assert_node_ref_count (ref_model, &grandparent1, 0);
4040   assert_node_ref_count (ref_model, &grandparent2, 2);
4041   assert_node_ref_count (ref_model, &grandparent3, 0);
4042   assert_node_ref_count (ref_model, &grandparent4, 0);
4043 
4044   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, FALSE, -1);
4045 
4046   assert_node_ref_count (ref_model, &grandparent1, 0);
4047   assert_node_ref_count (ref_model, &grandparent2, 0);
4048   assert_node_ref_count (ref_model, &grandparent3, 0);
4049   assert_node_ref_count (ref_model, &grandparent4, 1);
4050 
4051   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, TRUE, -1);
4052 
4053   assert_node_ref_count (ref_model, &grandparent1, 2);
4054   assert_node_ref_count (ref_model, &grandparent2, 0);
4055   assert_node_ref_count (ref_model, &grandparent3, 0);
4056   assert_node_ref_count (ref_model, &grandparent4, 0);
4057 
4058   gtk_tree_store_prepend (GTK_TREE_STORE (model), &new_node, NULL);
4059 
4060   assert_node_ref_count (ref_model, &new_node, 0);
4061   assert_node_ref_count (ref_model, &grandparent1, 2);
4062   assert_node_ref_count (ref_model, &grandparent2, 0);
4063   assert_node_ref_count (ref_model, &grandparent3, 0);
4064   assert_node_ref_count (ref_model, &grandparent4, 0);
4065 
4066   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
4067 
4068   assert_node_ref_count (ref_model, &new_node, 0);
4069   assert_node_ref_count (ref_model, &grandparent1, 0);
4070   assert_node_ref_count (ref_model, &grandparent2, 0);
4071   assert_node_ref_count (ref_model, &grandparent3, 0);
4072   assert_node_ref_count (ref_model, &grandparent4, 1);
4073 
4074   gtk_tree_store_remove (GTK_TREE_STORE (model), &new_node);
4075   gtk_tree_store_prepend (GTK_TREE_STORE (model), &new_node, NULL);
4076 
4077   assert_node_ref_count (ref_model, &new_node, 0);
4078   assert_node_ref_count (ref_model, &grandparent1, 0);
4079   assert_node_ref_count (ref_model, &grandparent2, 0);
4080   assert_node_ref_count (ref_model, &grandparent3, 0);
4081   assert_node_ref_count (ref_model, &grandparent4, 1);
4082 
4083   gtk_tree_store_set (GTK_TREE_STORE (model), &new_node, 0, TRUE, -1);
4084 
4085   assert_node_ref_count (ref_model, &new_node, 2);
4086   assert_node_ref_count (ref_model, &grandparent1, 0);
4087   assert_node_ref_count (ref_model, &grandparent2, 0);
4088   assert_node_ref_count (ref_model, &grandparent3, 0);
4089   assert_node_ref_count (ref_model, &grandparent4, 0);
4090 
4091   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
4092   gtk_tree_store_remove (GTK_TREE_STORE (model), &new_node);
4093 
4094   assert_node_ref_count (ref_model, &grandparent1, 0);
4095   assert_node_ref_count (ref_model, &grandparent2, 2);
4096   assert_node_ref_count (ref_model, &grandparent3, 0);
4097   assert_node_ref_count (ref_model, &grandparent4, 0);
4098 
4099   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, TRUE, -1);
4100   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent2);
4101 
4102   g_object_unref (g_object_ref_sink (tree_view));
4103   g_object_unref (filter_model);
4104   g_object_unref (ref_model);
4105 }
4106 
4107 static void
ref_count_transfer_child_level_insert(void)4108 ref_count_transfer_child_level_insert (void)
4109 {
4110   GtkTreeIter grandparent1;
4111   GtkTreeIter parent1, parent2, parent3;
4112   GtkTreeIter new_node;
4113   GtkTreeModel *model;
4114   GtkTreeModelRefCount *ref_model;
4115   GtkTreeModel *filter_model;
4116   GtkWidget *tree_view;
4117 
4118   model = gtk_tree_model_ref_count_new ();
4119   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4120 
4121   /* + grandparent1
4122    *   + parent1
4123    *   + parent2
4124    *   + parent3
4125    */
4126 
4127   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
4128   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
4129   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
4130   gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
4131 
4132   filter_model = gtk_tree_model_filter_new (model, NULL);
4133   tree_view = gtk_tree_view_new_with_model (filter_model);
4134 
4135   assert_node_ref_count (ref_model, &grandparent1, 3);
4136   assert_node_ref_count (ref_model, &parent1, 1);
4137   assert_node_ref_count (ref_model, &parent2, 0);
4138   assert_node_ref_count (ref_model, &parent3, 0);
4139 
4140   gtk_tree_store_prepend (GTK_TREE_STORE (model), &new_node, &grandparent1);
4141 
4142   assert_node_ref_count (ref_model, &grandparent1, 3);
4143   assert_node_ref_count (ref_model, &new_node, 1);
4144   assert_node_ref_count (ref_model, &parent1, 0);
4145   assert_node_ref_count (ref_model, &parent2, 0);
4146   assert_node_ref_count (ref_model, &parent3, 0);
4147 
4148   g_object_unref (g_object_ref_sink (tree_view));
4149   g_object_unref (filter_model);
4150   g_object_unref (ref_model);
4151 }
4152 
4153 static void
ref_count_transfer_child_level_remove(void)4154 ref_count_transfer_child_level_remove (void)
4155 {
4156   GtkTreeIter grandparent1;
4157   GtkTreeIter parent1, parent2, parent3;
4158   GtkTreeModel *model;
4159   GtkTreeModelRefCount *ref_model;
4160   GtkTreeModel *filter_model;
4161   GtkWidget *tree_view;
4162 
4163   model = gtk_tree_model_ref_count_new ();
4164   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4165 
4166   /* + grandparent1
4167    *   + parent1
4168    *   + parent2
4169    *   + parent3
4170    */
4171 
4172   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
4173   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
4174   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
4175   gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
4176 
4177   filter_model = gtk_tree_model_filter_new (model, NULL);
4178   tree_view = gtk_tree_view_new_with_model (filter_model);
4179 
4180   assert_node_ref_count (ref_model, &grandparent1, 3);
4181   assert_node_ref_count (ref_model, &parent1, 1);
4182   assert_node_ref_count (ref_model, &parent2, 0);
4183   assert_node_ref_count (ref_model, &parent3, 0);
4184 
4185   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent1);
4186 
4187   assert_node_ref_count (ref_model, &grandparent1, 3);
4188   assert_node_ref_count (ref_model, &parent2, 1);
4189   assert_node_ref_count (ref_model, &parent3, 0);
4190 
4191   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent2);
4192 
4193   assert_node_ref_count (ref_model, &grandparent1, 3);
4194   assert_node_ref_count (ref_model, &parent3, 1);
4195 
4196   g_object_unref (g_object_ref_sink (tree_view));
4197   g_object_unref (filter_model);
4198   g_object_unref (ref_model);
4199 }
4200 
4201 static void
ref_count_transfer_child_level_remove_filtered(void)4202 ref_count_transfer_child_level_remove_filtered (void)
4203 {
4204   GtkTreeIter grandparent1;
4205   GtkTreeIter parent1, parent2, parent3, parent4;
4206   GtkTreeModel *model;
4207   GtkTreeModelRefCount *ref_model;
4208   GtkTreeModel *filter_model;
4209   GtkWidget *tree_view;
4210   GType column_types[] = { G_TYPE_BOOLEAN };
4211 
4212   model = gtk_tree_model_ref_count_new ();
4213   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4214 
4215   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
4216                                    column_types);
4217 
4218   /* + grandparent1
4219    *   + parent1
4220    *   + parent2
4221    *   + parent3
4222    *   + parent4
4223    */
4224 
4225   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
4226   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
4227   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
4228   gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
4229   gtk_tree_store_append (GTK_TREE_STORE (model), &parent4, &grandparent1);
4230 
4231   /* Filter first node */
4232   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, TRUE, -1);
4233   gtk_tree_store_set (GTK_TREE_STORE (model), &parent1, 0, FALSE, -1);
4234   gtk_tree_store_set (GTK_TREE_STORE (model), &parent2, 0, TRUE, -1);
4235   gtk_tree_store_set (GTK_TREE_STORE (model), &parent3, 0, TRUE, -1);
4236   gtk_tree_store_set (GTK_TREE_STORE (model), &parent4, 0, TRUE, -1);
4237 
4238   filter_model = gtk_tree_model_filter_new (model, NULL);
4239   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
4240   tree_view = gtk_tree_view_new_with_model (filter_model);
4241 
4242   assert_node_ref_count (ref_model, &grandparent1, 3);
4243   assert_node_ref_count (ref_model, &parent1, 0);
4244   assert_node_ref_count (ref_model, &parent2, 1);
4245   assert_node_ref_count (ref_model, &parent3, 0);
4246   assert_node_ref_count (ref_model, &parent4, 0);
4247 
4248   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent2);
4249 
4250   assert_node_ref_count (ref_model, &grandparent1, 3);
4251   assert_node_ref_count (ref_model, &parent1, 0);
4252   assert_node_ref_count (ref_model, &parent3, 1);
4253   assert_node_ref_count (ref_model, &parent4, 0);
4254 
4255   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent3);
4256 
4257   assert_node_ref_count (ref_model, &grandparent1, 3);
4258   assert_node_ref_count (ref_model, &parent1, 0);
4259   assert_node_ref_count (ref_model, &parent4, 1);
4260 
4261   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent4);
4262 
4263   /* Check level length to get level cached again */
4264   check_level_length (GTK_TREE_MODEL_FILTER (filter_model), "0", 0);
4265 
4266   assert_node_ref_count (ref_model, &grandparent1, 3);
4267   assert_node_ref_count (ref_model, &parent1, 1);
4268 
4269   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
4270 
4271   assert_node_ref_count (ref_model, &grandparent1, 3);
4272   assert_node_ref_count (ref_model, &parent1, 1);
4273   assert_node_ref_count (ref_model, &parent2, 0);
4274 
4275   gtk_tree_store_set (GTK_TREE_STORE (model), &parent2, 0, TRUE, -1);
4276 
4277   assert_node_ref_count (ref_model, &grandparent1, 3);
4278   assert_node_ref_count (ref_model, &parent1, 1);
4279   assert_node_ref_count (ref_model, &parent2, 0);
4280 
4281   check_level_length (GTK_TREE_MODEL_FILTER (filter_model), "0", 1);
4282 
4283   g_object_unref (g_object_ref_sink (tree_view));
4284   g_object_unref (filter_model);
4285   g_object_unref (ref_model);
4286 }
4287 
4288 static void
ref_count_transfer_child_level_reordered(void)4289 ref_count_transfer_child_level_reordered (void)
4290 {
4291   GtkTreeIter grandparent1;
4292   GtkTreeIter parent1, parent2, parent3;
4293   GtkTreeModel *model;
4294   GtkTreeModelRefCount *ref_model;
4295   GtkTreeModel *filter_model;
4296   GtkWidget *tree_view;
4297 
4298   model = gtk_tree_model_ref_count_new ();
4299   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4300 
4301   /* + grandparent1
4302    *   + parent1
4303    *   + parent2
4304    *   + parent3
4305    */
4306 
4307   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
4308   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
4309   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
4310   gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
4311 
4312   filter_model = gtk_tree_model_filter_new (model, NULL);
4313   tree_view = gtk_tree_view_new_with_model (filter_model);
4314 
4315   assert_node_ref_count (ref_model, &grandparent1, 3);
4316   assert_node_ref_count (ref_model, &parent1, 1);
4317   assert_node_ref_count (ref_model, &parent2, 0);
4318   assert_node_ref_count (ref_model, &parent3, 0);
4319 
4320   /* gtk_tree_store_move() will emit rows-reordered */
4321   gtk_tree_store_move_after (GTK_TREE_STORE (model),
4322                              &parent1, &parent3);
4323 
4324   assert_node_ref_count (ref_model, &grandparent1, 3);
4325   assert_node_ref_count (ref_model, &parent2, 1);
4326   assert_node_ref_count (ref_model, &parent3, 0);
4327   assert_node_ref_count (ref_model, &parent1, 0);
4328 
4329   g_object_unref (g_object_ref_sink (tree_view));
4330   g_object_unref (filter_model);
4331   g_object_unref (ref_model);
4332 }
4333 
4334 static void
ref_count_transfer_child_level_reordered_filtered(void)4335 ref_count_transfer_child_level_reordered_filtered (void)
4336 {
4337   GtkTreeIter grandparent1;
4338   GtkTreeIter parent1, parent2, parent3;
4339   GtkTreeModel *model;
4340   GtkTreeModelRefCount *ref_model;
4341   GtkTreeModel *filter_model;
4342   GtkWidget *tree_view;
4343   GType column_types[] = { G_TYPE_BOOLEAN };
4344 
4345   model = gtk_tree_model_ref_count_new ();
4346   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4347 
4348   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
4349                                    column_types);
4350 
4351   /* + grandparent1
4352    *   + parent1
4353    *   + parent2
4354    *   + parent3
4355    */
4356 
4357   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, NULL);
4358   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, &grandparent1);
4359   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, &grandparent1);
4360   gtk_tree_store_append (GTK_TREE_STORE (model), &parent3, &grandparent1);
4361 
4362   /* Test with 1 node filtered (parent1) */
4363   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, TRUE, -1);
4364   gtk_tree_store_set (GTK_TREE_STORE (model), &parent2, 0, TRUE, -1);
4365   gtk_tree_store_set (GTK_TREE_STORE (model), &parent3, 0, TRUE, -1);
4366 
4367   filter_model = gtk_tree_model_filter_new (model, NULL);
4368   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
4369   tree_view = gtk_tree_view_new_with_model (filter_model);
4370 
4371   assert_node_ref_count (ref_model, &grandparent1, 3);
4372   assert_node_ref_count (ref_model, &parent1, 0);
4373   assert_node_ref_count (ref_model, &parent2, 1);
4374   assert_node_ref_count (ref_model, &parent3, 0);
4375 
4376   /* Move invisible node parent 1 */
4377 
4378   /* gtk_tree_store_move() will emit rows-reordered */
4379   gtk_tree_store_move_after (GTK_TREE_STORE (model),
4380                              &parent1, &parent3);
4381 
4382   assert_node_ref_count (ref_model, &grandparent1, 3);
4383   assert_node_ref_count (ref_model, &parent2, 1);
4384   assert_node_ref_count (ref_model, &parent3, 0);
4385   assert_node_ref_count (ref_model, &parent1, 0);
4386 
4387   /* Move invisible node parent 1 */
4388 
4389   /* gtk_tree_store_move() will emit rows-reordered */
4390   gtk_tree_store_move_before (GTK_TREE_STORE (model),
4391                               &parent1, &parent2);
4392 
4393   assert_node_ref_count (ref_model, &grandparent1, 3);
4394   assert_node_ref_count (ref_model, &parent1, 0);
4395   assert_node_ref_count (ref_model, &parent2, 1);
4396   assert_node_ref_count (ref_model, &parent3, 0);
4397 
4398   /* Now swap parent2 and parent2, first reference must transfer */
4399   /* gtk_tree_store_swap() will emit rows-reordered */
4400   gtk_tree_store_swap (GTK_TREE_STORE (model),
4401                        &parent2, &parent3);
4402 
4403   assert_node_ref_count (ref_model, &grandparent1, 3);
4404   assert_node_ref_count (ref_model, &parent1, 0);
4405   assert_node_ref_count (ref_model, &parent3, 1);
4406   assert_node_ref_count (ref_model, &parent2, 0);
4407 
4408   /* Swap back */
4409   gtk_tree_store_swap (GTK_TREE_STORE (model),
4410                        &parent2, &parent3);
4411 
4412   assert_node_ref_count (ref_model, &grandparent1, 3);
4413   assert_node_ref_count (ref_model, &parent1, 0);
4414   assert_node_ref_count (ref_model, &parent2, 1);
4415   assert_node_ref_count (ref_model, &parent3, 0);
4416 
4417   gtk_tree_store_set (GTK_TREE_STORE (model), &parent1, 0, TRUE, -1);
4418 
4419   assert_node_ref_count (ref_model, &parent1, 1);
4420   assert_node_ref_count (ref_model, &parent2, 0);
4421   assert_node_ref_count (ref_model, &parent3, 0);
4422 
4423   /* Test with two nodes filtered */
4424   gtk_tree_store_set (GTK_TREE_STORE (model), &parent1, 0, FALSE, -1);
4425   gtk_tree_store_set (GTK_TREE_STORE (model), &parent2, 0, FALSE, -1);
4426 
4427   assert_node_ref_count (ref_model, &parent1, 0);
4428   assert_node_ref_count (ref_model, &parent2, 0);
4429   assert_node_ref_count (ref_model, &parent3, 1);
4430 
4431   /* gtk_tree_store_move() will emit rows-reordered */
4432   gtk_tree_store_move_before (GTK_TREE_STORE (model),
4433                              &parent3, &parent1);
4434 
4435   assert_node_ref_count (ref_model, &parent3, 1);
4436   assert_node_ref_count (ref_model, &parent2, 0);
4437   assert_node_ref_count (ref_model, &parent1, 0);
4438 
4439   g_object_unref (g_object_ref_sink (tree_view));
4440   g_object_unref (filter_model);
4441   g_object_unref (ref_model);
4442 }
4443 
4444 static void
ref_count_transfer_child_level_filter(void)4445 ref_count_transfer_child_level_filter (void)
4446 {
4447   GtkTreeIter root;
4448   GtkTreeIter grandparent1, grandparent2, grandparent3, grandparent4;
4449   GtkTreeIter new_node;
4450   GtkTreeModel *model;
4451   GtkTreeModelRefCount *ref_model;
4452   GtkTreeModel *filter_model;
4453   GtkWidget *tree_view;
4454   GType column_types[] = { G_TYPE_BOOLEAN };
4455 
4456   model = gtk_tree_model_ref_count_new ();
4457   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
4458 
4459   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
4460                                    column_types);
4461 
4462   /* + root
4463    *    + grandparent1
4464    *    + grandparent2
4465    *    + grandparent3
4466    *    + grandparent4
4467    */
4468 
4469   gtk_tree_store_append (GTK_TREE_STORE (model), &root, NULL);
4470   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent1, &root);
4471   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent2, &root);
4472   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent3, &root);
4473   gtk_tree_store_append (GTK_TREE_STORE (model), &grandparent4, &root);
4474 
4475   /* Filter first node */
4476   gtk_tree_store_set (GTK_TREE_STORE (model), &root, 0, TRUE, -1);
4477   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
4478   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
4479   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, TRUE, -1);
4480   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, TRUE, -1);
4481 
4482   filter_model = gtk_tree_model_filter_new (model, NULL);
4483   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
4484   tree_view = gtk_tree_view_new_with_model (filter_model);
4485 
4486   assert_node_ref_count (ref_model, &grandparent1, 0);
4487   assert_node_ref_count (ref_model, &grandparent2, 1);
4488   assert_node_ref_count (ref_model, &grandparent3, 0);
4489   assert_node_ref_count (ref_model, &grandparent4, 0);
4490 
4491   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, FALSE, -1);
4492 
4493   assert_node_ref_count (ref_model, &grandparent1, 0);
4494   assert_node_ref_count (ref_model, &grandparent2, 0);
4495   assert_node_ref_count (ref_model, &grandparent3, 1);
4496   assert_node_ref_count (ref_model, &grandparent4, 0);
4497 
4498   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent3, 0, FALSE, -1);
4499 
4500   assert_node_ref_count (ref_model, &grandparent1, 0);
4501   assert_node_ref_count (ref_model, &grandparent2, 0);
4502   assert_node_ref_count (ref_model, &grandparent3, 0);
4503   assert_node_ref_count (ref_model, &grandparent4, 1);
4504 
4505   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, FALSE, -1);
4506 
4507   assert_node_ref_count (ref_model, &grandparent1, 0);
4508   assert_node_ref_count (ref_model, &grandparent2, 0);
4509   assert_node_ref_count (ref_model, &grandparent3, 0);
4510   assert_node_ref_count (ref_model, &grandparent4, 1);
4511 
4512   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
4513 
4514   assert_node_ref_count (ref_model, &grandparent1, 0);
4515   assert_node_ref_count (ref_model, &grandparent2, 1);
4516   assert_node_ref_count (ref_model, &grandparent3, 0);
4517   assert_node_ref_count (ref_model, &grandparent4, 0);
4518 
4519   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, FALSE, -1);
4520 
4521   assert_node_ref_count (ref_model, &grandparent1, 0);
4522   assert_node_ref_count (ref_model, &grandparent2, 0);
4523   assert_node_ref_count (ref_model, &grandparent3, 0);
4524   assert_node_ref_count (ref_model, &grandparent4, 1);
4525 
4526   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, TRUE, -1);
4527 
4528   assert_node_ref_count (ref_model, &grandparent1, 1);
4529   assert_node_ref_count (ref_model, &grandparent2, 0);
4530   assert_node_ref_count (ref_model, &grandparent3, 0);
4531   assert_node_ref_count (ref_model, &grandparent4, 0);
4532 
4533   gtk_tree_store_prepend (GTK_TREE_STORE (model), &new_node, &root);
4534 
4535   assert_node_ref_count (ref_model, &new_node, 0);
4536   assert_node_ref_count (ref_model, &grandparent1, 1);
4537   assert_node_ref_count (ref_model, &grandparent2, 0);
4538   assert_node_ref_count (ref_model, &grandparent3, 0);
4539   assert_node_ref_count (ref_model, &grandparent4, 0);
4540 
4541   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent1, 0, FALSE, -1);
4542 
4543   assert_node_ref_count (ref_model, &new_node, 0);
4544   assert_node_ref_count (ref_model, &grandparent1, 0);
4545   assert_node_ref_count (ref_model, &grandparent2, 0);
4546   assert_node_ref_count (ref_model, &grandparent3, 0);
4547   assert_node_ref_count (ref_model, &grandparent4, 1);
4548 
4549   gtk_tree_store_remove (GTK_TREE_STORE (model), &new_node);
4550   gtk_tree_store_prepend (GTK_TREE_STORE (model), &new_node, &root);
4551 
4552   assert_node_ref_count (ref_model, &new_node, 0);
4553   assert_node_ref_count (ref_model, &grandparent1, 0);
4554   assert_node_ref_count (ref_model, &grandparent2, 0);
4555   assert_node_ref_count (ref_model, &grandparent3, 0);
4556   assert_node_ref_count (ref_model, &grandparent4, 1);
4557 
4558   gtk_tree_store_set (GTK_TREE_STORE (model), &new_node, 0, TRUE, -1);
4559 
4560   assert_node_ref_count (ref_model, &new_node, 1);
4561   assert_node_ref_count (ref_model, &grandparent1, 0);
4562   assert_node_ref_count (ref_model, &grandparent2, 0);
4563   assert_node_ref_count (ref_model, &grandparent3, 0);
4564   assert_node_ref_count (ref_model, &grandparent4, 0);
4565 
4566   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent2, 0, TRUE, -1);
4567   gtk_tree_store_remove (GTK_TREE_STORE (model), &new_node);
4568 
4569   assert_node_ref_count (ref_model, &grandparent1, 0);
4570   assert_node_ref_count (ref_model, &grandparent2, 1);
4571   assert_node_ref_count (ref_model, &grandparent3, 0);
4572   assert_node_ref_count (ref_model, &grandparent4, 0);
4573 
4574   gtk_tree_store_set (GTK_TREE_STORE (model), &grandparent4, 0, TRUE, -1);
4575   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandparent2);
4576 
4577   g_object_unref (g_object_ref_sink (tree_view));
4578   g_object_unref (filter_model);
4579   g_object_unref (ref_model);
4580 }
4581 
4582 
4583 static gboolean
specific_path_dependent_filter_func(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)4584 specific_path_dependent_filter_func (GtkTreeModel *model,
4585                                      GtkTreeIter  *iter,
4586                                      gpointer      data)
4587 {
4588   GtkTreePath *path;
4589 
4590   path = gtk_tree_model_get_path (model, iter);
4591   if (gtk_tree_path_get_indices (path)[0] < 4)
4592     return FALSE;
4593 
4594   return TRUE;
4595 }
4596 
4597 static void
specific_path_dependent_filter(void)4598 specific_path_dependent_filter (void)
4599 {
4600   int i;
4601   GtkTreeIter iter;
4602   GtkListStore *list;
4603   GtkTreeModel *sort;
4604   GtkTreeModel *filter;
4605 
4606   list = gtk_list_store_new (1, G_TYPE_INT);
4607   gtk_list_store_insert_with_values (list, &iter, 0, 0, 1, -1);
4608   gtk_list_store_insert_with_values (list, &iter, 1, 0, 2, -1);
4609   gtk_list_store_insert_with_values (list, &iter, 2, 0, 3, -1);
4610   gtk_list_store_insert_with_values (list, &iter, 3, 0, 4, -1);
4611   gtk_list_store_insert_with_values (list, &iter, 4, 0, 5, -1);
4612   gtk_list_store_insert_with_values (list, &iter, 5, 0, 6, -1);
4613   gtk_list_store_insert_with_values (list, &iter, 6, 0, 7, -1);
4614   gtk_list_store_insert_with_values (list, &iter, 7, 0, 8, -1);
4615 
4616   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (list));
4617   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (sort), NULL);
4618   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
4619                                           specific_path_dependent_filter_func,
4620                                           NULL, NULL);
4621 
4622   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort), 0,
4623                                         GTK_SORT_DESCENDING);
4624 
4625   for (i = 0; i < 4; i++)
4626     {
4627       if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (list), &iter,
4628                                          NULL, 1))
4629         gtk_list_store_remove (list, &iter);
4630 
4631       if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (list), &iter,
4632                                          NULL, 2))
4633         gtk_list_store_remove (list, &iter);
4634     }
4635 
4636   g_object_unref (filter);
4637   g_object_unref (sort);
4638   g_object_unref (list);
4639 }
4640 
4641 
4642 static gboolean
specific_append_after_collapse_visible_func(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)4643 specific_append_after_collapse_visible_func (GtkTreeModel *model,
4644                                              GtkTreeIter  *iter,
4645                                              gpointer      data)
4646 {
4647   int number;
4648   gboolean hide_negative_numbers;
4649 
4650   gtk_tree_model_get (model, iter, 1, &number, -1);
4651   hide_negative_numbers = GPOINTER_TO_INT (g_object_get_data (data, "private-hide-negative-numbers"));
4652 
4653   return (number >= 0 || !hide_negative_numbers);
4654 }
4655 
4656 static void
specific_append_after_collapse(void)4657 specific_append_after_collapse (void)
4658 {
4659   /* This test is based on one of the test cases I found in my
4660    * old test cases directory.  I unfortunately do not have a record
4661    * from who this test case originated.  -Kris.
4662    *
4663    * General idea:
4664    * - Construct tree.
4665    * - Show tree, expand, collapse.
4666    * - Add a row.
4667    */
4668 
4669   GtkTreeIter iter;
4670   GtkTreeIter child_iter;
4671   GtkTreeIter child_iter2;
4672   GtkTreePath *append_path;
4673   GtkTreeStore *store;
4674   GtkTreeModel *filter;
4675   GtkTreeModel *sort;
4676 
4677   GtkWidget *window;
4678   GtkWidget *tree_view;
4679 
4680   store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_INT);
4681 
4682   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
4683   g_object_set_data (G_OBJECT (filter), "private-hide-negative-numbers",
4684                      GINT_TO_POINTER (FALSE));
4685   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
4686                                           specific_append_after_collapse_visible_func,
4687                                           filter, NULL);
4688 
4689   sort = gtk_tree_model_sort_new_with_model (filter);
4690 
4691   window = gtk_window_new ();
4692   tree_view = gtk_tree_view_new_with_model (sort);
4693   gtk_window_set_child (GTK_WINDOW (window), tree_view);
4694 
4695   while (g_main_context_pending (NULL))
4696     g_main_context_iteration (NULL, TRUE);
4697 
4698   gtk_tree_store_prepend (store, &iter, NULL);
4699   gtk_tree_store_set (store, &iter,
4700                       0, "hallo", 1, 1, -1);
4701 
4702   gtk_tree_store_append (store, &child_iter, &iter);
4703   gtk_tree_store_set (store, &child_iter,
4704                       0, "toemaar", 1, 1, -1);
4705 
4706   gtk_tree_store_append (store, &child_iter2, &child_iter);
4707   gtk_tree_store_set (store, &child_iter2,
4708                       0, "very deep", 1, 1, -1);
4709 
4710   append_path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &child_iter2);
4711 
4712   gtk_tree_store_append (store, &child_iter, &iter);
4713   gtk_tree_store_set (store, &child_iter,
4714                       0, "sja", 1, 1, -1);
4715 
4716   gtk_tree_store_append (store, &child_iter, &iter);
4717   gtk_tree_store_set (store, &child_iter,
4718                       0, "some word", 1, -1, -1);
4719 
4720   /* Expand and collapse the tree */
4721   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
4722   while (g_main_context_pending (NULL))
4723     g_main_context_iteration (NULL, TRUE);
4724 
4725   gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view));
4726   while (g_main_context_pending (NULL))
4727     g_main_context_iteration (NULL, TRUE);
4728 
4729   /* Add another it */
4730   g_object_set_data (G_OBJECT (filter), "private-hide-negative-numbers",
4731                      GINT_TO_POINTER (TRUE));
4732 
4733   if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, append_path))
4734     {
4735       gtk_tree_store_append (store, &child_iter, &iter);
4736       gtk_tree_store_set (store, &child_iter,
4737                           0, "new new new !!", 1, 1, -1);
4738     }
4739   gtk_tree_path_free (append_path);
4740 
4741   /* Expand */
4742   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
4743   while (g_main_context_pending (NULL))
4744     g_main_context_iteration (NULL, TRUE);
4745 }
4746 
4747 
4748 static int
specific_sort_filter_remove_node_compare_func(GtkTreeModel * model,GtkTreeIter * iter1,GtkTreeIter * iter2,gpointer data)4749 specific_sort_filter_remove_node_compare_func (GtkTreeModel  *model,
4750                                                GtkTreeIter   *iter1,
4751                                                GtkTreeIter   *iter2,
4752                                                gpointer       data)
4753 {
4754   return -1;
4755 }
4756 
4757 static gboolean
specific_sort_filter_remove_node_visible_func(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)4758 specific_sort_filter_remove_node_visible_func (GtkTreeModel  *model,
4759                                                GtkTreeIter   *iter,
4760                                                gpointer       data)
4761 {
4762   char *item = NULL;
4763 
4764   /* Do reference the model */
4765   gtk_tree_model_get (model, iter, 0, &item, -1);
4766   g_free (item);
4767 
4768   return FALSE;
4769 }
4770 
4771 static void
specific_sort_filter_remove_node(void)4772 specific_sort_filter_remove_node (void)
4773 {
4774   /* This test is based on one of the test cases I found in my
4775    * old test cases directory.  I unfortunately do not have a record
4776    * from who this test case originated.  -Kris.
4777    *
4778    * General idea:
4779    *  - Create tree store, sort, filter models.  The sort model has
4780    *    a default sort func that is enabled, filter model a visible func
4781    *    that defaults to returning FALSE.
4782    *  - Remove a node from the tree store.
4783    */
4784 
4785   GtkTreeIter iter;
4786   GtkTreeStore *store;
4787   GtkTreeModel *filter;
4788   GtkTreeModel *sort;
4789 
4790   GtkWidget *window;
4791   GtkWidget *tree_view;
4792 
4793   store = gtk_tree_store_new (1, G_TYPE_STRING);
4794   gtk_tree_store_append (store, &iter, NULL);
4795   gtk_tree_store_set (store, &iter, 0, "Hello1", -1);
4796 
4797   gtk_tree_store_append (store, &iter, NULL);
4798   gtk_tree_store_set (store, &iter, 0, "Hello2", -1);
4799 
4800   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
4801   gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sort),
4802                                            specific_sort_filter_remove_node_compare_func, NULL, NULL);
4803 
4804   filter = gtk_tree_model_filter_new (sort, NULL);
4805   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
4806                                           specific_sort_filter_remove_node_visible_func,
4807                                           filter, NULL);
4808 
4809 
4810   window = gtk_window_new ();
4811   tree_view = gtk_tree_view_new_with_model (filter);
4812   gtk_window_set_child (GTK_WINDOW (window), tree_view);
4813 
4814   while (g_main_context_pending (NULL))
4815     g_main_context_iteration (NULL, TRUE);
4816 
4817   /* Remove a node */
4818   gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
4819   gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
4820   gtk_tree_store_remove (store, &iter);
4821 
4822   while (g_main_context_pending (NULL))
4823     g_main_context_iteration (NULL, TRUE);
4824 }
4825 
4826 
4827 static void
specific_sort_filter_remove_root(void)4828 specific_sort_filter_remove_root (void)
4829 {
4830   /* This test is based on one of the test cases I found in my
4831    * old test cases directory.  I unfortunately do not have a record
4832    * from who this test case originated.  -Kris.
4833    */
4834 
4835   GtkTreeModel *model, *sort, *filter;
4836   GtkTreeIter root, mid, leaf;
4837   GtkTreePath *path;
4838 
4839   model = GTK_TREE_MODEL (gtk_tree_store_new (1, G_TYPE_INT));
4840   gtk_tree_store_append (GTK_TREE_STORE (model), &root, NULL);
4841   gtk_tree_store_append (GTK_TREE_STORE (model), &mid, &root);
4842   gtk_tree_store_append (GTK_TREE_STORE (model), &leaf, &mid);
4843 
4844   path = gtk_tree_model_get_path (model, &mid);
4845 
4846   sort = gtk_tree_model_sort_new_with_model (model);
4847   filter = gtk_tree_model_filter_new (sort, path);
4848 
4849   gtk_tree_path_free (path);
4850 
4851   gtk_tree_store_remove (GTK_TREE_STORE (model), &root);
4852 
4853   g_object_unref (filter);
4854   g_object_unref (sort);
4855   g_object_unref (model);
4856 }
4857 
4858 
4859 static void
specific_root_mixed_visibility(void)4860 specific_root_mixed_visibility (void)
4861 {
4862   int i;
4863   GtkTreeModel *filter;
4864   /* A bit nasty, apologies */
4865   FilterTest fixture;
4866 
4867   fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
4868 
4869   for (i = 0; i < LEVEL_LENGTH; i++)
4870     {
4871       GtkTreeIter iter;
4872 
4873       gtk_tree_store_insert (fixture.store, &iter, NULL, i);
4874       if (i % 2 == 0)
4875         create_tree_store_set_values (fixture.store, &iter, TRUE);
4876       else
4877         create_tree_store_set_values (fixture.store, &iter, FALSE);
4878     }
4879 
4880   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
4881   fixture.filter = GTK_TREE_MODEL_FILTER (filter);
4882   fixture.monitor = NULL;
4883 
4884   gtk_tree_model_filter_set_visible_column (fixture.filter, 1);
4885 
4886   /* In order to trigger the potential bug, we should not access
4887    * the filter model here (so don't call the check functions).
4888    */
4889 
4890   /* Change visibility of an odd row to TRUE */
4891   set_path_visibility (&fixture, "3", TRUE);
4892   check_filter_model (&fixture);
4893   check_level_length (fixture.filter, NULL, 4);
4894 }
4895 
4896 
4897 
4898 static gboolean
specific_has_child_filter_filter_func(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)4899 specific_has_child_filter_filter_func (GtkTreeModel *model,
4900                                        GtkTreeIter  *iter,
4901                                        gpointer      data)
4902 {
4903   return gtk_tree_model_iter_has_child (model, iter);
4904 }
4905 
4906 static void
specific_has_child_filter(void)4907 specific_has_child_filter (void)
4908 {
4909   GtkTreeModel *filter;
4910   GtkTreeIter iter, root;
4911   FilterTest fixture; /* This is not how it should be done */
4912   GtkWidget *tree_view;
4913 
4914   fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
4915   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
4916   fixture.filter = GTK_TREE_MODEL_FILTER (filter);
4917   fixture.monitor = signal_monitor_new (filter);
4918 
4919   tree_view = gtk_tree_view_new_with_model (filter);
4920 
4921   /* We will filter on parent state using a filter function.  We will
4922    * manually keep the boolean column in sync, so that we can use
4923    * check_filter_model() to check the consistency of the model.
4924    */
4925   /* FIXME: We need a check_filter_model() that is not tied to LEVEL_LENGTH
4926    * to be able to check the structure here.  We keep the calls to
4927    * check_filter_model() commented out until then.
4928    */
4929   gtk_tree_model_filter_set_visible_func (fixture.filter,
4930                                           specific_has_child_filter_filter_func,
4931                                           NULL, NULL);
4932 
4933   /* The first node will be initially invisible: no signals */
4934   gtk_tree_store_append (fixture.store, &root, NULL);
4935   create_tree_store_set_values (fixture.store, &root, FALSE);
4936 
4937   /* check_filter_model (&fixture); */
4938   check_level_length (fixture.filter, NULL, 0);
4939   signal_monitor_assert_is_empty (fixture.monitor);
4940 
4941   /* Insert a child node. This will cause the parent to become visible
4942    * since there is a child now.
4943    */
4944   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
4945   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
4946   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
4947 
4948   gtk_tree_store_append (fixture.store, &iter, &root);
4949   create_tree_store_set_values (fixture.store, &iter, TRUE);
4950 
4951   /* Parent must now be visible.  Do the level length check first,
4952    * to avoid modifying the child model triggering a row-changed to
4953    * the filter model.
4954    */
4955   check_level_length (fixture.filter, NULL, 1);
4956   check_level_length (fixture.filter, "0", 0);
4957   signal_monitor_assert_is_empty (fixture.monitor);
4958 
4959   /* This should propagate row-changed */
4960   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
4961   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
4962 
4963   set_path_visibility (&fixture, "0", TRUE);
4964   /* check_filter_model (&fixture); */
4965   signal_monitor_assert_is_empty (fixture.monitor);
4966 
4967   /* New root node, no child, so no signal */
4968   gtk_tree_store_append (fixture.store, &root, NULL);
4969   check_level_length (fixture.filter, NULL, 1);
4970   signal_monitor_assert_is_empty (fixture.monitor);
4971 
4972   /* When the child comes in, this node will become visible */
4973   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "1");
4974   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
4975   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
4976   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "1");
4977   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
4978 
4979   gtk_tree_store_append (fixture.store, &iter, &root);
4980   check_level_length (fixture.filter, NULL, 2);
4981   check_level_length (fixture.filter, "1", 0);
4982 
4983   create_tree_store_set_values (fixture.store, &root, TRUE);
4984   create_tree_store_set_values (fixture.store, &iter, TRUE);
4985 
4986   /* check_filter_model (&fixture); */
4987   signal_monitor_assert_is_empty (fixture.monitor);
4988 
4989   /* Add another child for 1 */
4990   gtk_tree_store_append (fixture.store, &iter, &root);
4991   create_tree_store_set_values (fixture.store, &iter, TRUE);
4992   check_level_length (fixture.filter, NULL, 2);
4993   check_level_length (fixture.filter, "0", 0);
4994   check_level_length (fixture.filter, "1", 0);
4995   signal_monitor_assert_is_empty (fixture.monitor);
4996 
4997   /* Now remove one of the remaining child rows */
4998   signal_monitor_append_signal (fixture.monitor, ROW_DELETED, "0");
4999 
5000   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
5001                                        &iter, "0:0");
5002   gtk_tree_store_remove (fixture.store, &iter);
5003 
5004   check_level_length (fixture.filter, NULL, 1);
5005   check_level_length (fixture.filter, "0", 0);
5006 
5007   set_path_visibility (&fixture, "0", FALSE);
5008   /* check_filter_model (&fixture); */
5009   signal_monitor_assert_is_empty (fixture.monitor);
5010 
5011   g_object_unref (fixture.filter);
5012   g_object_unref (fixture.store);
5013   g_object_unref (g_object_ref_sink (tree_view));
5014 }
5015 
5016 
5017 static gboolean
specific_root_has_child_filter_filter_func(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)5018 specific_root_has_child_filter_filter_func (GtkTreeModel *model,
5019                                             GtkTreeIter  *iter,
5020                                             gpointer      data)
5021 {
5022   int depth;
5023   GtkTreePath *path;
5024 
5025   path = gtk_tree_model_get_path (model, iter);
5026   depth = gtk_tree_path_get_depth (path);
5027   gtk_tree_path_free (path);
5028 
5029   if (depth > 1)
5030     return TRUE;
5031   /* else */
5032   return gtk_tree_model_iter_has_child (model, iter);
5033 }
5034 
5035 static void
specific_root_has_child_filter(void)5036 specific_root_has_child_filter (void)
5037 {
5038   GtkTreeModel *filter;
5039   GtkTreeIter iter, root;
5040   FilterTest fixture; /* This is not how it should be done ... */
5041   GtkWidget *tree_view;
5042 
5043   /* This is a variation on the above test case, specific has-child-filter,
5044    * herein the has-child check for visibility only applies to root level
5045    * nodes.  In this test, children are always visible because we
5046    * only filter based on the "has child" criterion.
5047    */
5048 
5049   fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
5050   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
5051   fixture.filter = GTK_TREE_MODEL_FILTER (filter);
5052   fixture.monitor = signal_monitor_new (filter);
5053 
5054   tree_view = gtk_tree_view_new_with_model (filter);
5055 
5056   /* We will filter on parent state using a filter function.  We will
5057    * manually keep the boolean column in sync, so that we can use
5058    * check_filter_model() to check the consistency of the model.
5059    */
5060   /* FIXME: We need a check_filter_model() that is not tied to LEVEL_LENGTH
5061    * to be able to check the structure here.  We keep the calls to
5062    * check_filter_model() commented out until then.
5063    */
5064   gtk_tree_model_filter_set_visible_func (fixture.filter,
5065                                           specific_root_has_child_filter_filter_func,
5066                                           NULL, NULL);
5067 
5068   /* Add a first node, this will be invisible initially, so no signal
5069    * should be emitted.
5070    */
5071   gtk_tree_store_append (fixture.store, &root, NULL);
5072   create_tree_store_set_values (fixture.store, &root, FALSE);
5073 
5074   signal_monitor_assert_is_empty (fixture.monitor);
5075   /* check_filter_model (&fixture); */
5076   check_level_length (fixture.filter, NULL, 0);
5077 
5078   /* Add a child node.  This will cause the parent to become visible,
5079    * so we expect row-inserted signals for both.
5080    */
5081   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
5082   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5083   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5084 
5085   gtk_tree_store_append (fixture.store, &iter, &root);
5086   signal_monitor_assert_is_empty (fixture.monitor);
5087 
5088   check_level_length (fixture.filter, NULL, 1);
5089   check_level_length (fixture.filter, "0", 1);
5090 
5091   /* Modify the content of iter, no signals because the parent is not
5092    * expanded.
5093    */
5094   create_tree_store_set_values (fixture.store, &iter, TRUE);
5095   signal_monitor_assert_is_empty (fixture.monitor);
5096 
5097   /* Parent must now be visible.  Do the level length check first,
5098    * to avoid modifying the child model triggering a row-changed to
5099    * the filter model.
5100    */
5101   check_level_length (fixture.filter, NULL, 1);
5102   check_level_length (fixture.filter, "0", 1);
5103 
5104   /* Modify path 0 */
5105   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
5106   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5107 
5108   set_path_visibility (&fixture, "0", TRUE);
5109   /* check_filter_model (&fixture); */
5110 
5111   signal_monitor_assert_is_empty (fixture.monitor);
5112 
5113   /* Insert another node in the root level.  Initially invisible, so
5114    * not expecting any signal.
5115    */
5116   gtk_tree_store_append (fixture.store, &root, NULL);
5117   check_level_length (fixture.filter, NULL, 1);
5118 
5119   signal_monitor_assert_is_empty (fixture.monitor);
5120 
5121   /* Adding a child node which also makes parent at path 1 visible. */
5122   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "1");
5123   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
5124   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
5125 
5126   gtk_tree_store_append (fixture.store, &iter, &root);
5127   check_level_length (fixture.filter, NULL, 2);
5128   check_level_length (fixture.filter, "1", 1);
5129 
5130   signal_monitor_assert_is_empty (fixture.monitor);
5131 
5132   /* Check if row-changed is propagated */
5133   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "1");
5134   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
5135 
5136   create_tree_store_set_values (fixture.store, &root, TRUE);
5137   create_tree_store_set_values (fixture.store, &iter, TRUE);
5138   /* check_filter_model (&fixture); */
5139   signal_monitor_assert_is_empty (fixture.monitor);
5140 
5141   /* Insert another child under node 1 */
5142   gtk_tree_store_append (fixture.store, &iter, &root);
5143   create_tree_store_set_values (fixture.store, &iter, TRUE);
5144   check_level_length (fixture.filter, NULL, 2);
5145   check_level_length (fixture.filter, "0", 1);
5146   check_level_length (fixture.filter, "1", 2);
5147   signal_monitor_assert_is_empty (fixture.monitor);
5148 
5149   /* Set a child node to invisible.  This should not yield any
5150    * change, because filtering is only done on whether the root
5151    * node has a child, which it still has.
5152    */
5153   set_path_visibility (&fixture, "0:0", FALSE);
5154   signal_monitor_assert_is_empty (fixture.monitor);
5155 
5156   /* Now remove one of the remaining child rows */
5157   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5158   signal_monitor_append_signal (fixture.monitor, ROW_DELETED, "0");
5159 
5160   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
5161                                        &iter, "0:0");
5162   gtk_tree_store_remove (fixture.store, &iter);
5163 
5164   check_level_length (fixture.filter, NULL, 1);
5165   check_level_length (fixture.filter, "0", 2);
5166   signal_monitor_assert_is_empty (fixture.monitor);
5167 
5168   /* Set visibility of 0 to FALSE, no-op for filter model since
5169    * the child 0:0 is already gone
5170    */
5171   set_path_visibility (&fixture, "0", FALSE);
5172   /* check_filter_model (&fixture); */
5173   signal_monitor_assert_is_empty (fixture.monitor);
5174 
5175   g_object_unref (fixture.filter);
5176   g_object_unref (fixture.store);
5177   g_object_unref (g_object_ref_sink (tree_view));
5178 }
5179 
5180 static void
specific_has_child_filter_on_sort_model(void)5181 specific_has_child_filter_on_sort_model (void)
5182 {
5183   GtkTreeModel *filter;
5184   GtkTreeModel *sort_model;
5185   GtkTreeIter iter, root;
5186   FilterTest fixture; /* This is not how it should be done */
5187   GtkWidget *tree_view;
5188 
5189   fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
5190   sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (fixture.store));
5191   filter = gtk_tree_model_filter_new (sort_model, NULL);
5192   fixture.filter = GTK_TREE_MODEL_FILTER (filter);
5193   fixture.monitor = signal_monitor_new (filter);
5194 
5195   tree_view = gtk_tree_view_new_with_model (filter);
5196 
5197   /* We will filter on parent state using a filter function.  We will
5198    * manually keep the boolean column in sync, so that we can use
5199    * check_filter_model() to check the consistency of the model.
5200    */
5201   /* FIXME: We need a check_filter_model() that is not tied to LEVEL_LENGTH
5202    * to be able to check the structure here.  We keep the calls to
5203    * check_filter_model() commented out until then.
5204    */
5205   gtk_tree_model_filter_set_visible_func (fixture.filter,
5206                                           specific_has_child_filter_filter_func,
5207                                           NULL, NULL);
5208 
5209   /* The first node will be initially invisible: no signals */
5210   gtk_tree_store_append (fixture.store, &root, NULL);
5211   create_tree_store_set_values (fixture.store, &root, FALSE);
5212 
5213   /* check_filter_model (&fixture); */
5214   check_level_length (fixture.filter, NULL, 0);
5215   signal_monitor_assert_is_empty (fixture.monitor);
5216 
5217   /* Insert a child node. This will cause the parent to become visible
5218    * since there is a child now.
5219    */
5220   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
5221   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5222 
5223   gtk_tree_store_append (fixture.store, &iter, &root);
5224   create_tree_store_set_values (fixture.store, &iter, TRUE);
5225 
5226   /* Parent must now be visible.  Do the level length check first,
5227    * to avoid modifying the child model triggering a row-changed to
5228    * the filter model.
5229    */
5230   check_level_length (fixture.filter, NULL, 1);
5231   check_level_length (fixture.filter, "0", 0);
5232   signal_monitor_assert_is_empty (fixture.monitor);
5233 
5234   /* This should propagate row-changed */
5235   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
5236   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5237 
5238   set_path_visibility (&fixture, "0", TRUE);
5239   /* check_filter_model (&fixture); */
5240   signal_monitor_assert_is_empty (fixture.monitor);
5241 
5242   /* New root node, no child, so no signal */
5243   gtk_tree_store_append (fixture.store, &root, NULL);
5244   check_level_length (fixture.filter, NULL, 1);
5245   signal_monitor_assert_is_empty (fixture.monitor);
5246 
5247   /* When the child comes in, this node will become visible */
5248   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "1");
5249   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
5250   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "1");
5251   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
5252 
5253   gtk_tree_store_append (fixture.store, &iter, &root);
5254   check_level_length (fixture.filter, NULL, 2);
5255   check_level_length (fixture.filter, "1", 0);
5256 
5257   create_tree_store_set_values (fixture.store, &root, TRUE);
5258   create_tree_store_set_values (fixture.store, &iter, TRUE);
5259 
5260   /* check_filter_model (&fixture); */
5261   signal_monitor_assert_is_empty (fixture.monitor);
5262 
5263   /* Add another child for 1 */
5264   gtk_tree_store_append (fixture.store, &iter, &root);
5265   create_tree_store_set_values (fixture.store, &iter, TRUE);
5266   check_level_length (fixture.filter, NULL, 2);
5267   check_level_length (fixture.filter, "0", 0);
5268   check_level_length (fixture.filter, "1", 0);
5269   signal_monitor_assert_is_empty (fixture.monitor);
5270 
5271   /* Now remove one of the remaining child rows */
5272   signal_monitor_append_signal (fixture.monitor, ROW_DELETED, "0");
5273 
5274   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
5275                                        &iter, "0:0");
5276   gtk_tree_store_remove (fixture.store, &iter);
5277 
5278   check_level_length (fixture.filter, NULL, 1);
5279   check_level_length (fixture.filter, "0", 0);
5280 
5281   set_path_visibility (&fixture, "0", FALSE);
5282   /* check_filter_model (&fixture); */
5283   signal_monitor_assert_is_empty (fixture.monitor);
5284 
5285   g_object_unref (fixture.filter);
5286   g_object_unref (fixture.store);
5287   g_object_unref (g_object_ref_sink (tree_view));
5288 }
5289 
5290 static gboolean
specific_at_least_2_children_filter_filter_func(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)5291 specific_at_least_2_children_filter_filter_func (GtkTreeModel *model,
5292                                                  GtkTreeIter  *iter,
5293                                                  gpointer      data)
5294 {
5295   return gtk_tree_model_iter_n_children (model, iter) >= 2;
5296 }
5297 
5298 static void
specific_at_least_2_children_filter(void)5299 specific_at_least_2_children_filter (void)
5300 {
5301   GtkTreeModel *filter;
5302   GtkTreeIter iter, root;
5303   FilterTest fixture; /* This is not how it should be done */
5304   GtkWidget *tree_view;
5305 
5306   fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
5307   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (fixture.store), NULL);
5308   fixture.filter = GTK_TREE_MODEL_FILTER (filter);
5309   fixture.monitor = signal_monitor_new (filter);
5310 
5311   tree_view = gtk_tree_view_new_with_model (filter);
5312 
5313   gtk_tree_model_filter_set_visible_func (fixture.filter,
5314                                           specific_at_least_2_children_filter_filter_func,
5315                                           NULL, NULL);
5316 
5317   /* The first node will be initially invisible: no signals */
5318   gtk_tree_store_append (fixture.store, &root, NULL);
5319   create_tree_store_set_values (fixture.store, &root, FALSE);
5320 
5321   /* check_filter_model (&fixture); */
5322   check_level_length (fixture.filter, NULL, 0);
5323   signal_monitor_assert_is_empty (fixture.monitor);
5324 
5325   /* Insert a child node.  Nothing should happen.
5326    */
5327   gtk_tree_store_append (fixture.store, &iter, &root);
5328   create_tree_store_set_values (fixture.store, &iter, TRUE);
5329 
5330   check_level_length (fixture.filter, NULL, 0);
5331   signal_monitor_assert_is_empty (fixture.monitor);
5332 
5333   /* Insert a second child node.  This will cause the parent to become
5334    * visible.
5335    */
5336   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
5337   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5338 
5339   gtk_tree_store_append (fixture.store, &iter, &root);
5340   create_tree_store_set_values (fixture.store, &iter, TRUE);
5341 
5342   /* Parent must now be visible.  Do the level length check first,
5343    * to avoid modifying the child model triggering a row-changed to
5344    * the filter model.
5345    */
5346   check_level_length (fixture.filter, NULL, 1);
5347   check_level_length (fixture.filter, "0", 0);
5348   signal_monitor_assert_is_empty (fixture.monitor);
5349 
5350   /* This should propagate row-changed */
5351   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
5352   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5353 
5354   set_path_visibility (&fixture, "0", TRUE);
5355   /* check_filter_model (&fixture); */
5356   signal_monitor_assert_is_empty (fixture.monitor);
5357 
5358   /* New root node, no child, so no signal */
5359   gtk_tree_store_append (fixture.store, &root, NULL);
5360   check_level_length (fixture.filter, NULL, 1);
5361   signal_monitor_assert_is_empty (fixture.monitor);
5362 
5363   /* First child, no signal, no change */
5364   gtk_tree_store_append (fixture.store, &iter, &root);
5365   check_level_length (fixture.filter, NULL, 1);
5366   signal_monitor_assert_is_empty (fixture.monitor);
5367 
5368   /* When the second child comes in, this node will become visible */
5369   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "1");
5370   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
5371   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "1");
5372   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "1");
5373 
5374   gtk_tree_store_append (fixture.store, &iter, &root);
5375   check_level_length (fixture.filter, NULL, 2);
5376   check_level_length (fixture.filter, "1", 0);
5377 
5378   create_tree_store_set_values (fixture.store, &root, TRUE);
5379   create_tree_store_set_values (fixture.store, &iter, TRUE);
5380 
5381   /* check_filter_model (&fixture); */
5382   signal_monitor_assert_is_empty (fixture.monitor);
5383 
5384   /* Add another child for 1 */
5385   gtk_tree_store_append (fixture.store, &iter, &root);
5386   create_tree_store_set_values (fixture.store, &iter, TRUE);
5387   check_level_length (fixture.filter, NULL, 2);
5388   check_level_length (fixture.filter, "0", 0);
5389   check_level_length (fixture.filter, "1", 0);
5390   signal_monitor_assert_is_empty (fixture.monitor);
5391 
5392   /* Now remove one of the remaining child rows */
5393   signal_monitor_append_signal (fixture.monitor, ROW_DELETED, "0");
5394 
5395   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (fixture.store),
5396                                        &iter, "0:0");
5397   gtk_tree_store_remove (fixture.store, &iter);
5398 
5399   check_level_length (fixture.filter, NULL, 1);
5400   check_level_length (fixture.filter, "0", 0);
5401 
5402   set_path_visibility (&fixture, "0", FALSE);
5403   /* check_filter_model (&fixture); */
5404   signal_monitor_assert_is_empty (fixture.monitor);
5405 
5406   g_object_unref (fixture.filter);
5407   g_object_unref (fixture.store);
5408   g_object_unref (g_object_ref_sink (tree_view));
5409 }
5410 
5411 static void
specific_at_least_2_children_filter_on_sort_model(void)5412 specific_at_least_2_children_filter_on_sort_model (void)
5413 {
5414   GtkTreeRowReference *ref;
5415   GtkTreeModel *filter;
5416   GtkTreeModel *sort_model;
5417   GtkTreeIter iter, root;
5418   FilterTest fixture; /* This is not how it should be done */
5419   GtkWidget *tree_view;
5420 
5421   fixture.store = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN);
5422   sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (fixture.store));
5423   filter = gtk_tree_model_filter_new (sort_model, NULL);
5424   fixture.filter = GTK_TREE_MODEL_FILTER (filter);
5425   fixture.monitor = signal_monitor_new (filter);
5426 
5427   tree_view = gtk_tree_view_new_with_model (filter);
5428 
5429   gtk_tree_model_filter_set_visible_func (fixture.filter,
5430                                           specific_at_least_2_children_filter_filter_func,
5431                                           NULL, NULL);
5432 
5433   /* The first node will be initially invisible: no signals */
5434   gtk_tree_store_append (fixture.store, &root, NULL);
5435   create_tree_store_set_values (fixture.store, &root, FALSE);
5436 
5437   /* check_filter_model (&fixture); */
5438   check_level_length (fixture.filter, NULL, 0);
5439   signal_monitor_assert_is_empty (fixture.monitor);
5440 
5441   /* Insert a child node.  Nothing should happen.
5442    */
5443   gtk_tree_store_append (fixture.store, &iter, &root);
5444   create_tree_store_set_values (fixture.store, &iter, TRUE);
5445 
5446   check_level_length (fixture.filter, NULL, 0);
5447   signal_monitor_assert_is_empty (fixture.monitor);
5448 
5449     {
5450       GtkTreePath *path = gtk_tree_path_new_from_indices (0, 0, -1);
5451 
5452       ref = gtk_tree_row_reference_new (sort_model, path);
5453       gtk_tree_path_free (path);
5454     }
5455 
5456   /* Insert a second child node.  This will cause the parent to become
5457    * visible.
5458    */
5459   signal_monitor_append_signal (fixture.monitor, ROW_INSERTED, "0");
5460   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5461 
5462   gtk_tree_store_append (fixture.store, &iter, &root);
5463   create_tree_store_set_values (fixture.store, &iter, TRUE);
5464 
5465   /* Parent must now be visible.  Do the level length check first,
5466    * to avoid modifying the child model triggering a row-changed to
5467    * the filter model.
5468    */
5469   check_level_length (fixture.filter, NULL, 1);
5470   check_level_length (fixture.filter, "0", 0);
5471   signal_monitor_assert_is_empty (fixture.monitor);
5472 
5473   /* This should propagate row-changed */
5474   signal_monitor_append_signal (fixture.monitor, ROW_CHANGED, "0");
5475   signal_monitor_append_signal (fixture.monitor, ROW_HAS_CHILD_TOGGLED, "0");
5476 
5477   set_path_visibility (&fixture, "0", TRUE);
5478   /* check_filter_model (&fixture); */
5479   signal_monitor_assert_is_empty (fixture.monitor);
5480 
5481   /* New root node, no child, so no signal */
5482   gtk_tree_store_append (fixture.store, &root, NULL);
5483   check_level_length (fixture.filter, NULL, 1);
5484   signal_monitor_assert_is_empty (fixture.monitor);
5485 
5486   gtk_tree_row_reference_free (ref);
5487   g_object_unref (fixture.filter);
5488   g_object_unref (fixture.store);
5489   g_object_unref (g_object_ref_sink (tree_view));
5490 }
5491 
5492 
5493 static void
specific_filter_add_child(void)5494 specific_filter_add_child (void)
5495 {
5496   /* This test is based on one of the test cases I found in my
5497    * old test cases directory.  I unfortunately do not have a record
5498    * from who this test case originated.  -Kris.
5499    */
5500 
5501   GtkTreeIter iter;
5502   GtkTreeIter iter_first;
5503   GtkTreeIter child;
5504   GtkTreeStore *store;
5505   GtkTreeModel *filter G_GNUC_UNUSED;
5506 
5507   store = gtk_tree_store_new (1, G_TYPE_STRING);
5508 
5509   gtk_tree_store_append (store, &iter_first, NULL);
5510   gtk_tree_store_set (store, &iter_first, 0, "Hello", -1);
5511 
5512   gtk_tree_store_append (store, &iter, NULL);
5513   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
5514 
5515   gtk_tree_store_append (store, &iter, NULL);
5516   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
5517 
5518   gtk_tree_store_append (store, &iter, NULL);
5519   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
5520 
5521   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
5522 
5523   gtk_tree_store_set (store, &iter, 0, "Hello", -1);
5524   gtk_tree_store_append (store, &child, &iter_first);
5525   gtk_tree_store_set (store, &child, 0, "Hello", -1);
5526 }
5527 
5528 static void
specific_list_store_clear(void)5529 specific_list_store_clear (void)
5530 {
5531   GtkTreeIter iter;
5532   GtkListStore *list;
5533   GtkTreeModel *filter;
5534   GtkWidget *view G_GNUC_UNUSED;
5535 
5536   list = gtk_list_store_new (1, G_TYPE_INT);
5537   gtk_list_store_insert_with_values (list, &iter, 0, 0, 1, -1);
5538   gtk_list_store_insert_with_values (list, &iter, 1, 0, 2, -1);
5539   gtk_list_store_insert_with_values (list, &iter, 2, 0, 3, -1);
5540   gtk_list_store_insert_with_values (list, &iter, 3, 0, 4, -1);
5541   gtk_list_store_insert_with_values (list, &iter, 4, 0, 5, -1);
5542   gtk_list_store_insert_with_values (list, &iter, 5, 0, 6, -1);
5543   gtk_list_store_insert_with_values (list, &iter, 6, 0, 7, -1);
5544   gtk_list_store_insert_with_values (list, &iter, 7, 0, 8, -1);
5545 
5546   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (list), NULL);
5547   view = gtk_tree_view_new_with_model (filter);
5548 
5549   gtk_list_store_clear (list);
5550 }
5551 
5552 static void
specific_sort_ref_leaf_and_remove_ancestor(void)5553 specific_sort_ref_leaf_and_remove_ancestor (void)
5554 {
5555   GtkTreeIter iter, child, child2, child3;
5556   GtkTreeStore *tree;
5557   GtkTreeModel *sort;
5558   GtkTreePath *path;
5559   GtkTreeRowReference *rowref;
5560   GtkWidget *view G_GNUC_UNUSED;
5561 
5562   tree = gtk_tree_store_new (1, G_TYPE_INT);
5563   gtk_tree_store_insert_with_values (tree, &iter, NULL, 0, 0, 1, -1);
5564   gtk_tree_store_insert_with_values (tree, &iter, NULL, 1, 0, 2, -1);
5565   gtk_tree_store_insert_with_values (tree, &iter, NULL, 2, 0, 3, -1);
5566   gtk_tree_store_insert_with_values (tree, &iter, NULL, 3, 0, 4, -1);
5567 
5568   gtk_tree_store_insert_with_values (tree, &child, &iter, 0, 0, 50, -1);
5569   gtk_tree_store_insert_with_values (tree, &child2, &child, 0, 0, 6, -1);
5570   gtk_tree_store_insert_with_values (tree, &child3, &child2, 0, 0, 7, -1);
5571 
5572   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree));
5573   view = gtk_tree_view_new_with_model (sort);
5574   gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
5575 
5576   path = gtk_tree_path_new_from_indices (3, 0, 0, 0, -1);
5577   rowref = gtk_tree_row_reference_new (sort, path);
5578   gtk_tree_path_free (path);
5579 
5580   path = gtk_tree_path_new_from_indices (3, 0, 0, 0, -1);
5581   rowref = gtk_tree_row_reference_new (sort, path);
5582   gtk_tree_path_free (path);
5583 
5584   path = gtk_tree_path_new_from_indices (3, 0, -1);
5585   rowref = gtk_tree_row_reference_new (sort, path);
5586   gtk_tree_path_free (path);
5587 
5588   path = gtk_tree_path_new_from_indices (3, -1);
5589   rowref = gtk_tree_row_reference_new (sort, path);
5590   gtk_tree_path_free (path);
5591 
5592   /* Deleting a parent */
5593   path = gtk_tree_path_new_from_indices (3, 0, -1);
5594   gtk_tree_model_get_iter (GTK_TREE_MODEL (tree), &iter, path);
5595   gtk_tree_store_remove (tree, &iter);
5596   gtk_tree_path_free (path);
5597 
5598   gtk_tree_row_reference_free (rowref);
5599 }
5600 
5601 static void
specific_ref_leaf_and_remove_ancestor(void)5602 specific_ref_leaf_and_remove_ancestor (void)
5603 {
5604   GtkTreeIter iter, child, child2, child3;
5605   GtkTreeStore *tree;
5606   GtkTreeModel *filter;
5607   GtkTreePath *path;
5608   GtkTreeRowReference *rowref;
5609   GtkWidget *view G_GNUC_UNUSED;
5610 
5611   tree = gtk_tree_store_new (1, G_TYPE_INT);
5612   gtk_tree_store_insert_with_values (tree, &iter, NULL, 0, 0, 1, -1);
5613   gtk_tree_store_insert_with_values (tree, &iter, NULL, 1, 0, 2, -1);
5614   gtk_tree_store_insert_with_values (tree, &iter, NULL, 2, 0, 3, -1);
5615   gtk_tree_store_insert_with_values (tree, &iter, NULL, 3, 0, 4, -1);
5616 
5617   gtk_tree_store_insert_with_values (tree, &child, &iter, 0, 0, 50, -1);
5618   gtk_tree_store_insert_with_values (tree, &child2, &child, 0, 0, 6, -1);
5619   gtk_tree_store_insert_with_values (tree, &child3, &child2, 0, 0, 7, -1);
5620 
5621   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), NULL);
5622   view = gtk_tree_view_new_with_model (filter);
5623   gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
5624 
5625   path = gtk_tree_path_new_from_indices (3, 0, 0, 0, -1);
5626   rowref = gtk_tree_row_reference_new (filter, path);
5627   gtk_tree_path_free (path);
5628 
5629   path = gtk_tree_path_new_from_indices (3, 0, 0, 0, -1);
5630   rowref = gtk_tree_row_reference_new (filter, path);
5631   gtk_tree_path_free (path);
5632 
5633   path = gtk_tree_path_new_from_indices (3, 0, -1);
5634   rowref = gtk_tree_row_reference_new (filter, path);
5635   gtk_tree_path_free (path);
5636 
5637   path = gtk_tree_path_new_from_indices (3, -1);
5638   rowref = gtk_tree_row_reference_new (filter, path);
5639   gtk_tree_path_free (path);
5640 
5641   /* Deleting a parent */
5642   path = gtk_tree_path_new_from_indices (3, 0, -1);
5643   gtk_tree_model_get_iter (GTK_TREE_MODEL (tree), &iter, path);
5644   gtk_tree_store_remove (tree, &iter);
5645   gtk_tree_path_free (path);
5646 
5647   gtk_tree_row_reference_free (rowref);
5648 }
5649 
5650 static void
specific_virtual_ref_leaf_and_remove_ancestor(void)5651 specific_virtual_ref_leaf_and_remove_ancestor (void)
5652 {
5653   GtkTreeIter iter, child, child2, child3;
5654   GtkTreeStore *tree;
5655   GtkTreeModel *filter;
5656   GtkTreePath *path;
5657   GtkTreeRowReference *rowref;
5658   GtkWidget *view G_GNUC_UNUSED;
5659 
5660   tree = gtk_tree_store_new (1, G_TYPE_INT);
5661   gtk_tree_store_insert_with_values (tree, &iter, NULL, 0, 0, 1, -1);
5662   gtk_tree_store_insert_with_values (tree, &iter, NULL, 1, 0, 2, -1);
5663   gtk_tree_store_insert_with_values (tree, &iter, NULL, 2, 0, 3, -1);
5664   gtk_tree_store_insert_with_values (tree, &iter, NULL, 3, 0, 4, -1);
5665 
5666   gtk_tree_store_insert_with_values (tree, &child, &iter, 0, 0, 50, -1);
5667   gtk_tree_store_insert_with_values (tree, &child2, &child, 0, 0, 6, -1);
5668   gtk_tree_store_insert_with_values (tree, &child3, &child2, 0, 0, 7, -1);
5669 
5670   /* Set a virtual root of 3:0 */
5671   path = gtk_tree_path_new_from_indices (3, 0, -1);
5672   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (tree), path);
5673   gtk_tree_path_free (path);
5674 
5675   view = gtk_tree_view_new_with_model (filter);
5676   gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
5677 
5678   path = gtk_tree_path_new_from_indices (0, 0, -1);
5679   rowref = gtk_tree_row_reference_new (filter, path);
5680   gtk_tree_path_free (path);
5681 
5682   path = gtk_tree_path_new_from_indices (0, 0, -1);
5683   rowref = gtk_tree_row_reference_new (filter, path);
5684   gtk_tree_path_free (path);
5685 
5686   path = gtk_tree_path_new_from_indices (0, -1);
5687   rowref = gtk_tree_row_reference_new (filter, path);
5688   gtk_tree_path_free (path);
5689 
5690   /* Deleting the virtual root */
5691   path = gtk_tree_path_new_from_indices (3, 0, -1);
5692   gtk_tree_model_get_iter (GTK_TREE_MODEL (tree), &iter, path);
5693   gtk_tree_store_remove (tree, &iter);
5694   gtk_tree_path_free (path);
5695 
5696   gtk_tree_row_reference_free (rowref);
5697 }
5698 
5699 
5700 static int
specific_bug_301558_sort_func(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,gpointer data)5701 specific_bug_301558_sort_func (GtkTreeModel *model,
5702                                GtkTreeIter  *a,
5703                                GtkTreeIter  *b,
5704                                gpointer      data)
5705 {
5706   int i, j;
5707 
5708   gtk_tree_model_get (model, a, 0, &i, -1);
5709   gtk_tree_model_get (model, b, 0, &j, -1);
5710 
5711   return j - i;
5712 }
5713 
5714 static void
specific_bug_301558(void)5715 specific_bug_301558 (void)
5716 {
5717   /* Test case for GNOME Bugzilla bug 301558 provided by
5718    * Markku Vire.
5719    */
5720   GtkTreeStore *tree;
5721   GtkTreeModel *filter;
5722   GtkTreeModel *sort;
5723   GtkTreeIter root, iter, iter2;
5724   GtkWidget *view G_GNUC_UNUSED;
5725   int i;
5726   gboolean add;
5727 
5728   /*http://bugzilla.gnome.org/show_bug.cgi?id=301558 */
5729 
5730   tree = gtk_tree_store_new (2, G_TYPE_INT, G_TYPE_BOOLEAN);
5731   gtk_tree_store_append (tree, &iter, NULL);
5732   gtk_tree_store_set (tree, &iter, 0, 123, 1, TRUE, -1);
5733   gtk_tree_store_append (tree, &iter2, &iter);
5734   gtk_tree_store_set (tree, &iter2, 0, 73, 1, TRUE, -1);
5735 
5736   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (tree));
5737   gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (sort),
5738                                            specific_bug_301558_sort_func,
5739                                            NULL, NULL);
5740 
5741   filter = gtk_tree_model_filter_new (sort, NULL);
5742   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter), 1);
5743 
5744   view = gtk_tree_view_new_with_model (filter);
5745 
5746   while (g_main_context_pending (NULL))
5747     g_main_context_iteration (NULL, TRUE);
5748 
5749   add = TRUE;
5750 
5751   for (i = 0; i < 10; i++)
5752     {
5753       if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (tree), &root))
5754         g_assert_not_reached ();
5755 
5756       if (add)
5757         {
5758           gtk_tree_store_append (tree, &iter, &root);
5759           gtk_tree_store_set (tree, &iter, 0, 456, 1, TRUE, -1);
5760         }
5761       else
5762         {
5763           int n;
5764           n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (tree), &root);
5765           gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (tree), &iter,
5766                                          &root, n - 1);
5767           gtk_tree_store_remove (tree, &iter);
5768         }
5769 
5770       add = !add;
5771     }
5772 }
5773 
5774 
5775 static gboolean
specific_bug_311955_filter_func(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)5776 specific_bug_311955_filter_func (GtkTreeModel *model,
5777                                  GtkTreeIter  *iter,
5778                                  gpointer      data)
5779 {
5780   int value;
5781 
5782   gtk_tree_model_get (model, iter, 0, &value, -1);
5783 
5784   return (value != 0);
5785 }
5786 
5787 static void
specific_bug_311955(void)5788 specific_bug_311955 (void)
5789 {
5790   /* This is a test case for GNOME Bugzilla bug 311955.  It was written
5791    * by Markku Vire.
5792    */
5793   GtkTreeIter iter, child, root;
5794   GtkTreeStore *store;
5795   GtkTreeModel *sort;
5796   GtkTreeModel *filter;
5797 
5798   GtkWidget *window G_GNUC_UNUSED;
5799   GtkWidget *tree_view;
5800   int i;
5801   int n;
5802   GtkTreePath *path;
5803 
5804   /*http://bugzilla.gnome.org/show_bug.cgi?id=311955 */
5805 
5806   store = gtk_tree_store_new (1, G_TYPE_INT);
5807 
5808   gtk_tree_store_append (store, &root, NULL);
5809   gtk_tree_store_set (store, &root, 0, 33, -1);
5810 
5811   gtk_tree_store_append (store, &iter, &root);
5812   gtk_tree_store_set (store, &iter, 0, 50, -1);
5813 
5814   gtk_tree_store_append (store, &iter, NULL);
5815   gtk_tree_store_set (store, &iter, 0, 22, -1);
5816 
5817   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
5818   filter = gtk_tree_model_filter_new (sort, NULL);
5819 
5820   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
5821                                           specific_bug_311955_filter_func,
5822                                           NULL, NULL);
5823 
5824   window = gtk_window_new ();
5825   tree_view = gtk_tree_view_new_with_model (filter);
5826   g_object_unref (store);
5827 
5828   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
5829 
5830   while (g_main_context_pending (NULL))
5831     g_main_context_iteration (NULL, TRUE);
5832 
5833   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 2);
5834   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0", 1);
5835 
5836   /* Fill model */
5837   for (i = 0; i < 4; i++)
5838     {
5839       gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &root);
5840 
5841       gtk_tree_store_append (store, &iter, &root);
5842 
5843       if (i < 3)
5844         gtk_tree_store_set (store, &iter, 0, i, -1);
5845 
5846       if (i % 2 == 0)
5847         {
5848           gtk_tree_store_append (store, &child, &iter);
5849           gtk_tree_store_set (store, &child, 0, 10, -1);
5850         }
5851     }
5852 
5853   while (g_main_context_pending (NULL))
5854     g_main_context_iteration (NULL, TRUE);
5855 
5856   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0", 3);
5857   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0:2", 1);
5858 
5859   /* Remove bottommost child from the tree. */
5860   gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &root);
5861   n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), &root);
5862 
5863   if (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store), &iter, &root, n - 2))
5864     {
5865       if (gtk_tree_model_iter_children (GTK_TREE_MODEL (store), &child, &iter))
5866         gtk_tree_store_remove (store, &child);
5867     }
5868   else
5869     g_assert_not_reached ();
5870 
5871   path = gtk_tree_path_new_from_indices (0, 2, -1);
5872   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
5873   gtk_tree_path_free (path);
5874 
5875   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0", 3);
5876   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0:2", 0);
5877 }
5878 
5879 static void
specific_bug_311955_clean(void)5880 specific_bug_311955_clean (void)
5881 {
5882   /* Cleaned up version of the test case for GNOME Bugzilla bug 311955,
5883    * which is easier to understand.
5884    */
5885   GtkTreeIter iter, child, grandchild;
5886   GtkTreeStore *store;
5887   GtkTreeModel *sort;
5888   GtkTreeModel *filter;
5889 
5890   GtkWidget *tree_view;
5891   GtkTreePath *path;
5892 
5893   store = gtk_tree_store_new (1, G_TYPE_INT);
5894 
5895   gtk_tree_store_append (store, &iter, NULL);
5896   gtk_tree_store_set (store, &iter, 0, 1, -1);
5897 
5898   gtk_tree_store_append (store, &child, &iter);
5899   gtk_tree_store_set (store, &child, 0, 1, -1);
5900 
5901   sort = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
5902   filter = gtk_tree_model_filter_new (sort, NULL);
5903 
5904   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
5905                                           specific_bug_311955_filter_func,
5906                                           NULL, NULL);
5907 
5908   tree_view = gtk_tree_view_new_with_model (filter);
5909   g_object_unref (store);
5910 
5911   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
5912 
5913   while (g_main_context_pending (NULL))
5914     g_main_context_iteration (NULL, TRUE);
5915 
5916   check_level_length (GTK_TREE_MODEL_FILTER (filter), NULL, 1);
5917   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0", 1);
5918 
5919   gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter);
5920 
5921   gtk_tree_store_append (store, &child, &iter);
5922   gtk_tree_store_set (store, &child, 0, 0, -1);
5923 
5924   gtk_tree_store_append (store, &child, &iter);
5925   gtk_tree_store_set (store, &child, 0, 1, -1);
5926 
5927   gtk_tree_store_append (store, &child, &iter);
5928   gtk_tree_store_set (store, &child, 0, 1, -1);
5929 
5930   gtk_tree_store_append (store, &grandchild, &child);
5931   gtk_tree_store_set (store, &grandchild, 0, 1, -1);
5932 
5933   gtk_tree_store_append (store, &child, &iter);
5934   /* Don't set a value: assume 0 */
5935 
5936   /* Remove leaf node, check trigger row-has-child-toggled */
5937   path = gtk_tree_path_new_from_indices (0, 3, 0, -1);
5938   gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, path);
5939   gtk_tree_path_free (path);
5940   gtk_tree_store_remove (store, &iter);
5941 
5942   path = gtk_tree_path_new_from_indices (0, 2, -1);
5943   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path, FALSE);
5944   gtk_tree_path_free (path);
5945 
5946   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0", 3);
5947   check_level_length (GTK_TREE_MODEL_FILTER (filter), "0:2", 0);
5948 
5949   g_object_unref (g_object_ref_sink (tree_view));
5950 }
5951 
5952 static void
specific_bug_346800(void)5953 specific_bug_346800 (void)
5954 {
5955   /* This is a test case for GNOME Bugzilla bug 346800.  It was written
5956    * by Jonathan Matthew.
5957    */
5958 
5959   GtkTreeIter node_iters[50];
5960   GtkTreeIter child_iters[50];
5961   GtkTreeModel *model;
5962   GtkTreeModelFilter *filter;
5963   GtkTreeStore *store;
5964   GType *columns;
5965   int i;
5966   int items = 50;
5967   columns = g_new (GType, 2);
5968   columns[0] = G_TYPE_STRING;
5969   columns[1] = G_TYPE_BOOLEAN;
5970   store = gtk_tree_store_newv (2, columns);
5971   model = GTK_TREE_MODEL (store);
5972   GList *junk = NULL;
5973 
5974   /*http://bugzilla.gnome.org/show_bug.cgi?id=346800 */
5975 
5976   filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (model, NULL));
5977   gtk_tree_model_filter_set_visible_column (filter, 1);
5978 
5979   for (i=0; i<items; i++)
5980     {
5981       /* allocate random amounts of junk, otherwise the filter model's arrays can expand without moving */
5982 
5983       junk = g_list_append (junk, g_malloc (138));
5984       gtk_tree_store_append (store, &node_iters[i], NULL);
5985       gtk_tree_store_set (store, &node_iters[i],
5986                           0, "something",
5987                           1, ((i%6) == 0) ? FALSE : TRUE,
5988                           -1);
5989 
5990       junk = g_list_append (junk, g_malloc (47));
5991       gtk_tree_store_append (store, &child_iters[i], &node_iters[i]);
5992       gtk_tree_store_set (store, &child_iters[i],
5993                           0, "something else",
5994                           1, FALSE,
5995                           -1);
5996       gtk_tree_model_filter_refilter (filter);
5997 
5998       if (i > 6)
5999         {
6000           gtk_tree_store_set (GTK_TREE_STORE (model), &child_iters[i-1], 1,
6001                               (i & 1) ? TRUE : FALSE, -1);
6002           gtk_tree_model_filter_refilter (filter);
6003 
6004           gtk_tree_store_set (GTK_TREE_STORE (model), &child_iters[i-2], 1,
6005                               (i & 1) ? FALSE: TRUE, -1);
6006           gtk_tree_model_filter_refilter (filter);
6007         }
6008     }
6009 
6010   g_list_free_full (junk, g_free);
6011 }
6012 
6013 static gboolean
specific_bug_464173_visible_func(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)6014 specific_bug_464173_visible_func (GtkTreeModel *model,
6015                                   GtkTreeIter  *iter,
6016                                   gpointer      data)
6017 {
6018   gboolean *visible = (gboolean *)data;
6019 
6020   return *visible;
6021 }
6022 
6023 static void
specific_bug_464173(void)6024 specific_bug_464173 (void)
6025 {
6026   /* Test case for GNOME Bugzilla bug 464173, test case written
6027    * by Andreas Koehler.
6028    */
6029   GtkTreeStore *model;
6030   GtkTreeModelFilter *f_model;
6031   GtkTreeIter iter1, iter2;
6032   GtkWidget *view G_GNUC_UNUSED;
6033   gboolean visible = TRUE;
6034 
6035   /*http://bugzilla.gnome.org/show_bug.cgi?id=464173 */
6036 
6037   model = gtk_tree_store_new (1, G_TYPE_STRING);
6038   gtk_tree_store_append (model, &iter1, NULL);
6039   gtk_tree_store_set (model, &iter1, 0, "Foo", -1);
6040   gtk_tree_store_append (model, &iter2, &iter1);
6041   gtk_tree_store_set (model, &iter2, 0, "Bar", -1);
6042 
6043   f_model = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL(model), NULL));
6044   gtk_tree_model_filter_set_visible_func (f_model,
6045                                           specific_bug_464173_visible_func,
6046                                           &visible, NULL);
6047 
6048   view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (f_model));
6049 
6050   visible = FALSE;
6051   gtk_tree_model_filter_refilter (f_model);
6052 }
6053 
6054 
6055 static gboolean
specific_bug_540201_filter_func(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)6056 specific_bug_540201_filter_func (GtkTreeModel *model,
6057                                  GtkTreeIter  *iter,
6058                                  gpointer      data)
6059 {
6060   gboolean has_children;
6061 
6062   has_children = gtk_tree_model_iter_has_child (model, iter);
6063 
6064   return has_children;
6065 }
6066 
6067 static void
specific_bug_540201(void)6068 specific_bug_540201 (void)
6069 {
6070   /* Test case for GNOME Bugzilla bug 540201, steps provided by
6071    * Charles Day.
6072    */
6073   GtkTreeIter iter, root;
6074   GtkTreeStore *store;
6075   GtkTreeModel *filter;
6076 
6077   GtkWidget *tree_view G_GNUC_UNUSED;
6078 
6079   /*http://bugzilla.gnome.org/show_bug.cgi?id=540201 */
6080 
6081   store = gtk_tree_store_new (1, G_TYPE_INT);
6082 
6083   gtk_tree_store_append (store, &root, NULL);
6084   gtk_tree_store_set (store, &root, 0, 33, -1);
6085 
6086   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
6087   tree_view = gtk_tree_view_new_with_model (filter);
6088 
6089   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
6090                                           specific_bug_540201_filter_func,
6091                                           NULL, NULL);
6092 
6093   gtk_tree_store_append (store, &iter, &root);
6094   gtk_tree_store_set (store, &iter, 0, 50, -1);
6095 
6096   gtk_tree_store_append (store, &iter, &root);
6097   gtk_tree_store_set (store, &iter, 0, 22, -1);
6098 
6099 
6100   gtk_tree_store_append (store, &root, NULL);
6101   gtk_tree_store_set (store, &root, 0, 33, -1);
6102 
6103   gtk_tree_store_append (store, &iter, &root);
6104   gtk_tree_store_set (store, &iter, 0, 22, -1);
6105 }
6106 
6107 
6108 static gboolean
specific_bug_549287_visible_func(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)6109 specific_bug_549287_visible_func (GtkTreeModel *model,
6110                                   GtkTreeIter  *iter,
6111                                   gpointer      data)
6112 {
6113   gboolean result = FALSE;
6114 
6115   result = gtk_tree_model_iter_has_child (model, iter);
6116 
6117   return result;
6118 }
6119 
6120 static void
specific_bug_549287(void)6121 specific_bug_549287 (void)
6122 {
6123   /* Test case for GNOME Bugzilla bug 529287, provided by Julient Puydt */
6124 
6125   int i;
6126   GtkTreeStore *store;
6127   GtkTreeModel *filtered;
6128   GtkWidget *view G_GNUC_UNUSED;
6129   GtkTreeIter iter;
6130   GtkTreeIter *swap, *parent, *child;
6131 
6132   /*http://bugzilla.gnome.org/show_bug.cgi?id=529287 */
6133 
6134   store = gtk_tree_store_new (1, G_TYPE_STRING);
6135   filtered = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
6136   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filtered),
6137                                           specific_bug_549287_visible_func,
6138                                           NULL, NULL);
6139 
6140   view = gtk_tree_view_new_with_model (filtered);
6141 
6142   for (i = 0; i < 4; i++)
6143     {
6144       if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter))
6145         {
6146           parent = gtk_tree_iter_copy (&iter);
6147           child = gtk_tree_iter_copy (&iter);
6148 
6149           while (gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (store),
6150                                                 child, parent, 0))
6151             {
6152 
6153               swap = parent;
6154               parent = child;
6155               child = swap;
6156             }
6157 
6158           gtk_tree_store_append (store, child, parent);
6159           gtk_tree_store_set (store, child,
6160                               0, "Something",
6161                               -1);
6162 
6163           gtk_tree_iter_free (parent);
6164           gtk_tree_iter_free (child);
6165         }
6166       else
6167         {
6168           gtk_tree_store_append (store, &iter, NULL);
6169           gtk_tree_store_set (store, &iter,
6170                               0, "Something",
6171                               -1);
6172         }
6173 
6174       /* since we inserted something, we changed the visibility conditions: */
6175       gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filtered));
6176     }
6177 }
6178 
6179 static gboolean
specific_bug_621076_visible_func(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)6180 specific_bug_621076_visible_func (GtkTreeModel *model,
6181                                   GtkTreeIter  *iter,
6182                                   gpointer      data)
6183 {
6184   gboolean visible = FALSE;
6185   char *str = NULL;
6186 
6187   gtk_tree_model_get (model, iter, 0, &str, -1);
6188   if (str != NULL && g_str_has_prefix (str, "visible"))
6189     {
6190       visible = TRUE;
6191     }
6192   else
6193     {
6194       GtkTreeIter child_iter;
6195       gboolean valid;
6196 
6197       /* Recursively check if we have a visible child */
6198       for (valid = gtk_tree_model_iter_children (model, &child_iter, iter);
6199            valid; valid = gtk_tree_model_iter_next (model, &child_iter))
6200         {
6201           if (specific_bug_621076_visible_func (model, &child_iter, data))
6202             {
6203               visible = TRUE;
6204               break;
6205             }
6206         }
6207     }
6208 
6209   g_free (str);
6210 
6211   return visible;
6212 }
6213 
6214 static void
specific_bug_621076(void)6215 specific_bug_621076 (void)
6216 {
6217   /* Test case for GNOME Bugzilla bug 621076, provided by Xavier Claessens */
6218 
6219   /* This test case differs from has-child-filter and root-has-child-filter
6220    * in that the visible function both filters on content and model
6221    * structure.  Also, it is recursive.
6222    */
6223 
6224   GtkTreeStore *store;
6225   GtkTreeModel *filter;
6226   GtkWidget *view;
6227   GtkTreeIter group_iter;
6228   GtkTreeIter item_iter;
6229   SignalMonitor *monitor;
6230 
6231   /*http://bugzilla.gnome.org/show_bug.cgi?id=621076 */
6232 
6233   store = gtk_tree_store_new (1, G_TYPE_STRING);
6234   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
6235   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
6236                                           specific_bug_621076_visible_func,
6237                                           NULL, NULL);
6238 
6239   view = gtk_tree_view_new_with_model (filter);
6240   g_object_ref_sink (view);
6241 
6242   monitor = signal_monitor_new (filter);
6243 
6244   signal_monitor_append_signal (monitor, ROW_INSERTED, "0");
6245   gtk_tree_store_insert_with_values (store, &item_iter, NULL, -1,
6246                                      0, "visible-group-0",
6247                                      -1);
6248   signal_monitor_assert_is_empty (monitor);
6249 
6250   /* visible-group-0 is not expanded, so ROW_INSERTED should not be emitted
6251    * for its children. However, ROW_HAS_CHILD_TOGGLED should be emitted on
6252    * visible-group-0 to tell the view that row can be expanded. */
6253   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "0");
6254   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "0");
6255   group_iter = item_iter;
6256   gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
6257                                      0, "visible-0:0",
6258                                      -1);
6259   signal_monitor_assert_is_empty (monitor);
6260 
6261   signal_monitor_append_signal (monitor, ROW_INSERTED, "1");
6262   gtk_tree_store_insert_with_values (store, &item_iter, NULL, -1,
6263                                      0, "visible-group-1",
6264                                      -1);
6265   signal_monitor_assert_is_empty (monitor);
6266 
6267   /* We are adding an hidden item inside visible-group-1, so
6268    * ROW_HAS_CHILD_TOGGLED should not be emitted.  It is emitted though,
6269    * because the signal originating at TreeStore will be propagated,
6270    * as well a generated signal because the state of the parent *could*
6271    * change by a change in the model.
6272    */
6273   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1");
6274   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1");
6275   group_iter = item_iter;
6276   gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
6277                                      0, "group-1:0",
6278                                      -1);
6279   signal_monitor_assert_is_empty (monitor);
6280 
6281   /* This group is invisible and its parent too. Nothing should be emitted */
6282   group_iter = item_iter;
6283   gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
6284                                      0, "group-1:0:0",
6285                                      -1);
6286   signal_monitor_assert_is_empty (monitor);
6287 
6288   /* Adding a visible item in this group hierarchy will make all nodes
6289    * in this path visible.  The first level should simply tell the view
6290    * that it now has a child, and the view will load the tree if needed
6291    * (depends on the expanded state).
6292    */
6293   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1");
6294   group_iter = item_iter;
6295   gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
6296                                      0, "visible-1:0:0:0",
6297                                      -1);
6298   signal_monitor_assert_is_empty (monitor);
6299 
6300   check_level_length (GTK_TREE_MODEL_FILTER (filter), "1", 1);
6301 
6302   gtk_tree_store_insert_with_values (store, &item_iter, NULL, -1,
6303                                      0, "group-2",
6304                                      -1);
6305   signal_monitor_assert_is_empty (monitor);
6306 
6307   /* Parent is invisible, and adding this invisible item won't change that,
6308    * so no signal should be emitted. */
6309   group_iter = item_iter;
6310   gtk_tree_store_insert_with_values (store, NULL, &group_iter, -1,
6311                                      0, "invisible-2:0",
6312                                      -1);
6313   signal_monitor_assert_is_empty (monitor);
6314 
6315   /* This makes group-2 visible, so it gets inserted and tells it has
6316    * children.
6317    */
6318   signal_monitor_append_signal (monitor, ROW_INSERTED, "2");
6319   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "2");
6320   gtk_tree_store_insert_with_values (store, NULL, &group_iter, -1,
6321                                      0, "visible-2:1",
6322                                      -1);
6323   signal_monitor_assert_is_empty (monitor);
6324 
6325   /* group-2 is already visible, so this time it is a normal insertion */
6326   gtk_tree_store_insert_with_values (store, NULL, &group_iter, -1,
6327                                      0, "visible-2:2",
6328                                      -1);
6329   signal_monitor_assert_is_empty (monitor);
6330 
6331 
6332   gtk_tree_store_insert_with_values (store, &item_iter, NULL, -1,
6333                                      0, "group-3",
6334                                      -1);
6335   signal_monitor_assert_is_empty (monitor);
6336 
6337   /* Parent is invisible, and adding this invisible item won't change that,
6338    * so no signal should be emitted. */
6339   group_iter = item_iter;
6340   gtk_tree_store_insert_with_values (store, NULL, &group_iter, -1,
6341                                      0, "invisible-3:0",
6342                                      -1);
6343   signal_monitor_assert_is_empty (monitor);
6344 
6345   gtk_tree_store_insert_with_values (store, &item_iter, &group_iter, -1,
6346                                      0, "invisible-3:1",
6347                                      -1);
6348   signal_monitor_assert_is_empty (monitor);
6349 
6350   /* This will make group 3 visible. */
6351   signal_monitor_append_signal (monitor, ROW_INSERTED, "3");
6352   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "3");
6353   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "3");
6354   gtk_tree_store_set (store, &item_iter, 0, "visible-3:1", -1);
6355   signal_monitor_assert_is_empty (monitor);
6356 
6357   /* Make sure all groups are expanded, so the filter has the tree cached */
6358   gtk_tree_view_expand_all (GTK_TREE_VIEW (view));
6359   while (g_main_context_pending (NULL))
6360     g_main_context_iteration (NULL, TRUE);
6361 
6362   /* Should only yield a row-changed */
6363   signal_monitor_append_signal (monitor, ROW_CHANGED, "3:0");
6364   gtk_tree_store_set (store, &item_iter, 0, "visible-3:1", -1);
6365   signal_monitor_assert_is_empty (monitor);
6366 
6367   /* Now remove/hide some items. If a group loses its last item, the group
6368    * should be deleted instead of the item.
6369    */
6370 
6371   signal_monitor_append_signal (monitor, ROW_DELETED, "2:1");
6372   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &item_iter, "2:2");
6373   gtk_tree_store_remove (store, &item_iter);
6374   signal_monitor_assert_is_empty (monitor);
6375 
6376   signal_monitor_append_signal (monitor, ROW_DELETED, "2:0");
6377   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "2");
6378   signal_monitor_append_signal (monitor, ROW_DELETED, "2");
6379   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &item_iter, "2:1");
6380   gtk_tree_store_set (store, &item_iter, 0, "invisible-2:1", -1);
6381   signal_monitor_assert_is_empty (monitor);
6382 
6383   signal_monitor_append_signal (monitor, ROW_DELETED, "1:0:0:0");
6384   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1:0:0");
6385   signal_monitor_append_signal (monitor, ROW_DELETED, "1:0");
6386   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "1");
6387   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &item_iter, "1:0:0:0");
6388   gtk_tree_store_remove (store, &item_iter);
6389   signal_monitor_assert_is_empty (monitor);
6390 
6391   /* Hide a group using row-changed instead of row-deleted */
6392   /* Caution: group 2 is gone, so offsets of the signals have moved. */
6393   signal_monitor_append_signal (monitor, ROW_DELETED, "2:0");
6394   signal_monitor_append_signal (monitor, ROW_HAS_CHILD_TOGGLED, "2");
6395   signal_monitor_append_signal (monitor, ROW_DELETED, "2");
6396   gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store), &item_iter,
6397                                        "3:1");
6398   gtk_tree_store_set (store, &item_iter, 0, "invisible-3:1", -1);
6399   signal_monitor_assert_is_empty (monitor);
6400 
6401   /* Cleanup */
6402   signal_monitor_free (monitor);
6403   g_object_unref (view);
6404   g_object_unref (store);
6405   g_object_unref (filter);
6406 }
6407 
6408 static void
specific_bug_657353_related(void)6409 specific_bug_657353_related (void)
6410 {
6411   GtkTreeIter node1, node2, node3, node4;
6412   GtkTreeModel *model;
6413   GtkTreeModelRefCount *ref_model;
6414   GtkTreeModel *filter_model;
6415   GtkWidget *tree_view;
6416   GType column_types[] = { G_TYPE_BOOLEAN };
6417 
6418   /* gtk_tree_model_filter_rows_reordered() used to have a problem to
6419    * not properly transfer the first ref count when the first node in
6420    * the level does not have elt->offset == 0.  This test checks for
6421    * that.  This bug could cause the faulty condition
6422    *   elt->ext_ref_count > elt->ref_count
6423    * to raise.
6424    */
6425 
6426   model = gtk_tree_model_ref_count_new ();
6427   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
6428 
6429   gtk_tree_store_set_column_types (GTK_TREE_STORE (model), 1,
6430                                    column_types);
6431 
6432   gtk_tree_store_append (GTK_TREE_STORE (model), &node1, NULL);
6433   gtk_tree_store_append (GTK_TREE_STORE (model), &node2, NULL);
6434   gtk_tree_store_append (GTK_TREE_STORE (model), &node3, NULL);
6435   gtk_tree_store_append (GTK_TREE_STORE (model), &node4, NULL);
6436 
6437   /* Hide the first node */
6438   gtk_tree_store_set (GTK_TREE_STORE (model), &node1, 0, FALSE, -1);
6439   gtk_tree_store_set (GTK_TREE_STORE (model), &node2, 0, TRUE, -1);
6440   gtk_tree_store_set (GTK_TREE_STORE (model), &node3, 0, TRUE, -1);
6441   gtk_tree_store_set (GTK_TREE_STORE (model), &node4, 0, TRUE, -1);
6442 
6443   filter_model = gtk_tree_model_filter_new (model, NULL);
6444   gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (filter_model), 0);
6445   tree_view = gtk_tree_view_new_with_model (filter_model);
6446 
6447   assert_node_ref_count (ref_model, &node1, 0);
6448   assert_node_ref_count (ref_model, &node2, 2);
6449   assert_node_ref_count (ref_model, &node3, 1);
6450   assert_node_ref_count (ref_model, &node4, 1);
6451 
6452   /* Swap nodes 2 and 3 */
6453 
6454   /* gtk_tree_store_swap() will emit rows-reordered */
6455   gtk_tree_store_swap (GTK_TREE_STORE (model),
6456                        &node2, &node3);
6457 
6458   assert_node_ref_count (ref_model, &node1, 0);
6459   assert_node_ref_count (ref_model, &node3, 2);
6460   assert_node_ref_count (ref_model, &node2, 1);
6461   assert_node_ref_count (ref_model, &node4, 1);
6462 
6463   /* Hide node 3 */
6464   gtk_tree_store_set (GTK_TREE_STORE (model), &node3, 0, FALSE, -1);
6465 
6466   assert_node_ref_count (ref_model, &node1, 0);
6467   assert_node_ref_count (ref_model, &node3, 0);
6468   assert_node_ref_count (ref_model, &node2, 2);
6469   assert_node_ref_count (ref_model, &node4, 1);
6470 
6471   g_object_unref (g_object_ref_sink (tree_view));
6472   g_object_unref (filter_model);
6473   g_object_unref (ref_model);
6474 }
6475 
6476 static gboolean
specific_bug_657353_visible_func(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)6477 specific_bug_657353_visible_func (GtkTreeModel *model,
6478                                   GtkTreeIter  *iter,
6479                                   gpointer      data)
6480 {
6481   char *str;
6482   gboolean ret = FALSE;
6483 
6484   gtk_tree_model_get (model, iter, 0, &str, -1);
6485   ret = strstr (str, "hidden") ? FALSE : TRUE;
6486   g_free (str);
6487 
6488   return ret;
6489 }
6490 
6491 static void
specific_bug_657353(void)6492 specific_bug_657353 (void)
6493 {
6494   GtkListStore *store;
6495   GtkTreeModel *sort_model;
6496   GtkTreeModel *filter_model;
6497   GtkTreeIter iter, iter_a, iter_b, iter_c;
6498   GtkWidget *tree_view;
6499 
6500   /* This is a very carefully crafted test case that is triggering the
6501    * situation described in bug 657353.
6502    *
6503    *   GtkListStore acts like EphyCompletionModel
6504    *   GtkTreeModelSort acts like the sort model added in
6505    *                      ephy_location_entry_set_completion.
6506    *   GtkTreeModelFilter acts like the filter model in
6507    *                      GtkEntryCompletion.
6508    */
6509 
6510   /* Set up a model that's wrapped in a GtkTreeModelSort.  The first item
6511    * will be hidden.
6512    */
6513   store = gtk_list_store_new (1, G_TYPE_STRING);
6514   gtk_list_store_insert_with_values (store, &iter_b, 0, 0, "BBB hidden", -1);
6515   gtk_list_store_insert_with_values (store, &iter, 1, 0, "EEE", -1);
6516   gtk_list_store_insert_with_values (store, &iter, 2, 0, "DDD", -1);
6517   gtk_list_store_insert_with_values (store, &iter_c, 3, 0, "CCC", -1);
6518 
6519   sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (store));
6520 
6521   filter_model = gtk_tree_model_filter_new (sort_model, NULL);
6522   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter_model),
6523                                           specific_bug_657353_visible_func,
6524                                           filter_model, NULL);
6525 
6526   tree_view = gtk_tree_view_new_with_model (filter_model);
6527 
6528   /* This triggers emission of rows-reordered.  The elt with offset == 0
6529    * is hidden, which used to cause misbehavior.  (The first reference should
6530    * have moved to CCC, which did not happen).
6531    */
6532   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model),
6533                                         0, GTK_SORT_ASCENDING);
6534 
6535   /* By inserting another item that will appear at the first position, a
6536    * reference transfer is done from CCC (which failed to get this reference
6537    * earlier) to AAA.  At this point, the rule
6538    * elt->ref_count >= elt->ext_ref_count is broken for CCC.
6539    */
6540   gtk_list_store_insert_with_values (store, &iter_a, 6, 0, "AAA", -1);
6541 
6542   /* When we hide CCC, the references cannot be correctly released, because
6543    * CCC failed to get a reference during rows-reordered.  The faulty condition
6544    * only manifests itself here with MODEL_FILTER_DEBUG disabled (as is usual
6545    * in production).
6546    */
6547   gtk_list_store_set (store, &iter_c, 0, "CCC hidden", -1);
6548 
6549   g_object_unref (g_object_ref_sink (tree_view));
6550   g_object_unref (filter_model);
6551   g_object_unref (sort_model);
6552   g_object_unref (store);
6553 }
6554 
6555 static void
specific_bug_658696(void)6556 specific_bug_658696 (void)
6557 {
6558   GtkTreeStore *store;
6559   GtkTreeModel *filter;
6560   GtkTreePath *vroot;
6561   GtkTreeIter iter;
6562 
6563   store = create_tree_store (4, TRUE);
6564 
6565   vroot = gtk_tree_path_new_from_indices (0, 0, -1);
6566   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), vroot);
6567   gtk_tree_path_free (vroot);
6568 
6569   /* This used to cause a crash in gtk_tree_model_filter_check_ancestors() */
6570   gtk_tree_store_append (store, &iter, NULL);
6571 
6572   g_object_unref (store);
6573   g_object_unref (filter);
6574 }
6575 
6576 static gboolean
specific_bug_659022_visible_func(GtkTreeModel * model,GtkTreeIter * iter,gpointer data)6577 specific_bug_659022_visible_func (GtkTreeModel *model,
6578                                   GtkTreeIter  *iter,
6579                                   gpointer      data)
6580 {
6581   GtkTreeIter tmp;
6582 
6583   if (!gtk_tree_model_iter_parent (model, &tmp, iter))
6584     {
6585       if (gtk_tree_model_iter_n_children (model, iter) >= 2)
6586         return TRUE;
6587       else
6588         return FALSE;
6589     }
6590 
6591   return TRUE;
6592 }
6593 
6594 static void
specific_bug_659022_row_changed_emission(void)6595 specific_bug_659022_row_changed_emission (void)
6596 {
6597   GtkTreeModel *filter;
6598   GtkTreeModel *model;
6599   GtkTreeIter parent, child, child2;
6600   GtkTreePath *path;
6601   GtkWidget *tree_view;
6602 
6603   model = gtk_tree_model_ref_count_new ();
6604 
6605   filter = gtk_tree_model_filter_new (model, NULL);
6606   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
6607                                           specific_bug_659022_visible_func,
6608                                           NULL, NULL);
6609 
6610   tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (filter));
6611 
6612   gtk_tree_store_insert (GTK_TREE_STORE (model), &parent, NULL, 0);
6613   gtk_tree_store_insert (GTK_TREE_STORE (model), &child, &parent, 0);
6614   gtk_tree_store_insert (GTK_TREE_STORE (model), &child2, &parent, 0);
6615 
6616   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
6617 
6618   gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filter));
6619 
6620   gtk_tree_store_remove (GTK_TREE_STORE (model), &child2);
6621 
6622   gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filter));
6623 
6624   path = gtk_tree_model_get_path (model, &child);
6625   gtk_tree_model_row_changed (model, path, &child);
6626   gtk_tree_path_free (path);
6627 
6628   g_object_unref (g_object_ref_sink (tree_view));
6629   g_object_unref (filter);
6630   g_object_unref (model);
6631 }
6632 
6633 static void
specific_bug_659022_row_deleted_node_invisible(void)6634 specific_bug_659022_row_deleted_node_invisible (void)
6635 {
6636   GtkTreeModel *filter;
6637   GtkTreeModel *model;
6638   GtkTreeIter parent, child;
6639   GtkTreeIter parent2, child2, child3;
6640   GtkWidget *tree_view;
6641 
6642   model = gtk_tree_model_ref_count_new ();
6643 
6644   filter = gtk_tree_model_filter_new (model, NULL);
6645   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
6646                                           specific_bug_659022_visible_func,
6647                                           NULL, NULL);
6648 
6649   tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (filter));
6650 
6651   gtk_tree_store_insert (GTK_TREE_STORE (model), &parent, NULL, 0);
6652   gtk_tree_store_insert (GTK_TREE_STORE (model), &child, &parent, 0);
6653 
6654   gtk_tree_store_insert (GTK_TREE_STORE (model), &parent2, NULL, 0);
6655   gtk_tree_store_insert (GTK_TREE_STORE (model), &child2, &parent2, 0);
6656   gtk_tree_store_insert (GTK_TREE_STORE (model), &child3, &parent2, 0);
6657 
6658   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
6659 
6660   gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (filter));
6661 
6662   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent);
6663 
6664   g_object_unref (g_object_ref_sink (tree_view));
6665   g_object_unref (filter);
6666   g_object_unref (model);
6667 }
6668 
6669 static void
specific_bug_659022_row_deleted_free_level(void)6670 specific_bug_659022_row_deleted_free_level (void)
6671 {
6672   GtkTreeModel *filter;
6673   GtkTreeModel *model;
6674   GtkTreeModelRefCount *ref_model;
6675   GtkTreeIter parent, child;
6676   GtkTreeIter parent2, child2, child3;
6677   GtkWidget *tree_view;
6678 
6679   model = gtk_tree_model_ref_count_new ();
6680   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
6681 
6682   filter = gtk_tree_model_filter_new (model, NULL);
6683   gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
6684                                           specific_bug_659022_visible_func,
6685                                           NULL, NULL);
6686 
6687   tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (filter));
6688 
6689   /* Carefully construct a model */
6690   gtk_tree_store_insert (GTK_TREE_STORE (model), &parent, NULL, 0);
6691   gtk_tree_store_insert (GTK_TREE_STORE (model), &child, &parent, 0);
6692 
6693   gtk_tree_store_insert (GTK_TREE_STORE (model), &parent2, NULL, 0);
6694   gtk_tree_store_insert (GTK_TREE_STORE (model), &child2, &parent2, 0);
6695   gtk_tree_store_insert (GTK_TREE_STORE (model), &child3, &parent2, 0);
6696 
6697   /* Only parent2 is visible, child3 holds first ref count for that level
6698    * (Note that above, both child2 as child3 are inserted at position 0).
6699    */
6700   assert_node_ref_count (ref_model, &parent, 0);
6701   assert_node_ref_count (ref_model, &child, 0);
6702   assert_node_ref_count (ref_model, &parent2, 3);
6703   assert_node_ref_count (ref_model, &child3, 1);
6704   assert_node_ref_count (ref_model, &child2, 0);
6705 
6706   /* Make sure child level is cached */
6707   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
6708 
6709   assert_node_ref_count (ref_model, &parent, 0);
6710   assert_node_ref_count (ref_model, &child, 0);
6711   assert_node_ref_count (ref_model, &parent2, 3);
6712   assert_node_ref_count (ref_model, &child3, 2);
6713   assert_node_ref_count (ref_model, &child2, 1);
6714 
6715   gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view));
6716 
6717   assert_node_ref_count (ref_model, &parent, 0);
6718   assert_node_ref_count (ref_model, &child, 0);
6719   assert_node_ref_count (ref_model, &parent2, 3);
6720   assert_node_ref_count (ref_model, &child3, 1);
6721   assert_node_ref_count (ref_model, &child2, 0);
6722 
6723   /* Remove node with longer child level first */
6724   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent2);
6725   gtk_tree_store_remove (GTK_TREE_STORE (model), &parent);
6726 
6727   g_object_unref (g_object_ref_sink (tree_view));
6728   g_object_unref (filter);
6729   g_object_unref (model);
6730 }
6731 
6732 static void
specific_bug_679910(void)6733 specific_bug_679910 (void)
6734 {
6735   GtkTreeModel *filter;
6736   GtkListStore *store;
6737   GtkTreeIter iter, nil_iter;
6738   GtkTreeIter filter_iter;
6739 
6740   store = gtk_list_store_new (1, G_TYPE_POINTER);
6741   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
6742 
6743   gtk_list_store_append (store, &nil_iter);
6744   gtk_list_store_append (store, &iter);
6745   gtk_list_store_append (store, &nil_iter);
6746 
6747   gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (filter),
6748                                                     &filter_iter,
6749                                                     &iter);
6750   iter = filter_iter;
6751   g_assert_true (gtk_tree_model_iter_next (filter, &iter));
6752   iter = filter_iter;
6753   g_assert_true (gtk_tree_model_iter_previous (filter, &iter));
6754 
6755   g_object_unref (filter);
6756   g_object_unref (store);
6757 }
6758 
6759 static int row_changed_count;
6760 static int filter_row_changed_count;
6761 
6762 static void
row_changed(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gpointer data)6763 row_changed (GtkTreeModel *model,
6764              GtkTreePath  *path,
6765              GtkTreeIter  *iter,
6766              gpointer data)
6767 {
6768   int *count = data;
6769 
6770   (*count)++;
6771 }
6772 
6773 static void
test_row_changed(void)6774 test_row_changed (void)
6775 {
6776   GtkTreeModel *filter;
6777   GtkListStore *store;
6778   GtkTreeIter iter1, iter2, iter3;
6779   GtkTreeIter fiter1, fiter2, fiter3;
6780 
6781   store = gtk_list_store_new (1, G_TYPE_INT);
6782   filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
6783 
6784   gtk_list_store_append (store, &iter1);
6785   gtk_list_store_append (store, &iter2);
6786   gtk_list_store_append (store, &iter3);
6787 
6788   gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (filter), &fiter1, &iter1);
6789   gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (filter), &fiter2, &iter2);
6790   gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (filter), &fiter3, &iter3);
6791 
6792   g_signal_connect (store, "row-changed", G_CALLBACK (row_changed), &row_changed_count);
6793   g_signal_connect (filter, "row-changed", G_CALLBACK (row_changed), &filter_row_changed_count);
6794 
6795   row_changed_count = 0;
6796   filter_row_changed_count = 0;
6797 
6798   gtk_list_store_set (store, &iter1, 0, 1, -1);
6799   gtk_list_store_set (store, &iter2, 0, 1, -1);
6800   gtk_list_store_set (store, &iter3, 0, 1, -1);
6801 
6802   g_assert_cmpint (row_changed_count, ==, 3);
6803   g_assert_cmpint (filter_row_changed_count, ==, 0);
6804 
6805   row_changed_count = 0;
6806   filter_row_changed_count = 0;
6807 
6808   gtk_tree_model_ref_node (filter, &fiter1);
6809   gtk_tree_model_ref_node (filter, &fiter2);
6810   gtk_tree_model_ref_node (filter, &fiter3);
6811 
6812   gtk_list_store_set (store, &iter1, 0, 2, -1);
6813   gtk_list_store_set (store, &iter2, 0, 2, -1);
6814   gtk_list_store_set (store, &iter3, 0, 2, -1);
6815 
6816   g_assert_cmpint (row_changed_count, ==, 3);
6817   g_assert_cmpint (filter_row_changed_count, ==, 3);
6818 
6819   gtk_tree_model_unref_node (filter, &fiter1);
6820   gtk_tree_model_unref_node (filter, &fiter2);
6821   gtk_tree_model_unref_node (filter, &fiter3);
6822 
6823   g_object_unref (filter);
6824   g_object_unref (store);
6825 }
6826 
6827 
6828 /* main */
6829 
6830 void
register_filter_model_tests(void)6831 register_filter_model_tests (void)
6832 {
6833   g_test_add ("/TreeModelFilter/self/verify-test-suite",
6834               FilterTest, NULL,
6835               filter_test_setup,
6836               verify_test_suite,
6837               filter_test_teardown);
6838 
6839   g_test_add ("/TreeModelFilter/self/verify-test-suite/vroot/depth-1",
6840               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6841               filter_test_setup,
6842               verify_test_suite_vroot,
6843               filter_test_teardown);
6844   g_test_add ("/TreeModelFilter/self/verify-test-suite/vroot/depth-2",
6845               FilterTest, gtk_tree_path_new_from_indices (2, 3, -1),
6846               filter_test_setup,
6847               verify_test_suite_vroot,
6848               filter_test_teardown);
6849 
6850 
6851   g_test_add ("/TreeModelFilter/filled/hide-root-level",
6852               FilterTest, NULL,
6853               filter_test_setup,
6854               filled_hide_root_level,
6855               filter_test_teardown);
6856   g_test_add ("/TreeModelFilter/filled/hide-child-levels",
6857               FilterTest, NULL,
6858               filter_test_setup,
6859               filled_hide_child_levels,
6860               filter_test_teardown);
6861   g_test_add ("/TreeModelFilter/filled/hide-child-levels/root-expanded",
6862               FilterTest, NULL,
6863               filter_test_setup,
6864               filled_hide_child_levels_root_expanded,
6865               filter_test_teardown);
6866 
6867   g_test_add ("/TreeModelFilter/filled/hide-root-level/vroot",
6868               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6869               filter_test_setup,
6870               filled_vroot_hide_root_level,
6871               filter_test_teardown);
6872   g_test_add ("/TreeModelFilter/filled/hide-child-levels/vroot",
6873               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6874               filter_test_setup,
6875               filled_vroot_hide_child_levels,
6876               filter_test_teardown);
6877   g_test_add ("/TreeModelFilter/filled/hide-child-levels/vroot-root-expanded",
6878               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6879               filter_test_setup,
6880               filled_vroot_hide_child_levels_root_expanded,
6881               filter_test_teardown);
6882 
6883 
6884   g_test_add ("/TreeModelFilter/empty/show-nodes",
6885               FilterTest, NULL,
6886               filter_test_setup_empty,
6887               empty_show_nodes,
6888               filter_test_teardown);
6889   g_test_add ("/TreeModelFilter/empty/show-multiple-nodes",
6890               FilterTest, NULL,
6891               filter_test_setup_empty,
6892               empty_show_multiple_nodes,
6893               filter_test_teardown);
6894 
6895   g_test_add ("/TreeModelFilter/empty/show-nodes/vroot",
6896               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6897               filter_test_setup_empty,
6898               empty_vroot_show_nodes,
6899               filter_test_teardown);
6900   g_test_add ("/TreeModelFilter/empty/show-multiple-nodes/vroot",
6901               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6902               filter_test_setup_empty,
6903               empty_vroot_show_multiple_nodes,
6904               filter_test_teardown);
6905 
6906 
6907   g_test_add ("/TreeModelFilter/unfiltered/hide-single",
6908               FilterTest, NULL,
6909               filter_test_setup_unfiltered,
6910               unfiltered_hide_single,
6911               filter_test_teardown);
6912   g_test_add ("/TreeModelFilter/unfiltered/hide-single/root-expanded",
6913               FilterTest, NULL,
6914               filter_test_setup_unfiltered_root_expanded,
6915               unfiltered_hide_single_root_expanded,
6916               filter_test_teardown);
6917   g_test_add ("/TreeModelFilter/unfiltered/hide-single-child",
6918               FilterTest, NULL,
6919               filter_test_setup_unfiltered,
6920               unfiltered_hide_single_child,
6921               filter_test_teardown);
6922   g_test_add ("/TreeModelFilter/unfiltered/hide-single-child/root-expanded",
6923               FilterTest, NULL,
6924               filter_test_setup_unfiltered_root_expanded,
6925               unfiltered_hide_single_child_root_expanded,
6926               filter_test_teardown);
6927   g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level",
6928               FilterTest, NULL,
6929               filter_test_setup_unfiltered,
6930               unfiltered_hide_single_multi_level,
6931               filter_test_teardown);
6932   g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level/root-expanded",
6933               FilterTest, NULL,
6934               filter_test_setup_unfiltered_root_expanded,
6935               unfiltered_hide_single_multi_level_root_expanded,
6936               filter_test_teardown);
6937 
6938   g_test_add ("/TreeModelFilter/unfiltered/hide-single/vroot",
6939               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6940               filter_test_setup_unfiltered,
6941               unfiltered_vroot_hide_single,
6942               filter_test_teardown);
6943   g_test_add ("/TreeModelFilter/unfiltered/hide-single-child/vroot",
6944               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6945               filter_test_setup_unfiltered,
6946               unfiltered_vroot_hide_single_child,
6947               filter_test_teardown);
6948   g_test_add ("/TreeModelFilter/unfiltered/hide-single-child/vroot/root-expanded",
6949               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6950               filter_test_setup_unfiltered_root_expanded,
6951               unfiltered_vroot_hide_single_child_root_expanded,
6952               filter_test_teardown);
6953   g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level/vroot",
6954               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6955               filter_test_setup_unfiltered,
6956               unfiltered_vroot_hide_single_multi_level,
6957               filter_test_teardown);
6958   g_test_add ("/TreeModelFilter/unfiltered/hide-single-multi-level/vroot/root-expanded",
6959               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6960               filter_test_setup_unfiltered_root_expanded,
6961               unfiltered_vroot_hide_single_multi_level_root_expanded,
6962               filter_test_teardown);
6963 
6964 
6965 
6966   g_test_add ("/TreeModelFilter/unfiltered/show-single",
6967               FilterTest, NULL,
6968               filter_test_setup_empty_unfiltered,
6969               unfiltered_show_single,
6970               filter_test_teardown);
6971   g_test_add ("/TreeModelFilter/unfiltered/show-single-child",
6972               FilterTest, NULL,
6973               filter_test_setup_empty_unfiltered,
6974               unfiltered_show_single_child,
6975               filter_test_teardown);
6976   g_test_add ("/TreeModelFilter/unfiltered/show-single-child/root-expanded",
6977               FilterTest, NULL,
6978               filter_test_setup_empty_unfiltered_root_expanded,
6979               unfiltered_show_single_child_root_expanded,
6980               filter_test_teardown);
6981   g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level",
6982               FilterTest, NULL,
6983               filter_test_setup_empty_unfiltered,
6984               unfiltered_show_single_multi_level,
6985               filter_test_teardown);
6986   g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level/root-expanded",
6987               FilterTest, NULL,
6988               filter_test_setup_empty_unfiltered_root_expanded,
6989               unfiltered_show_single_multi_level_root_expanded,
6990               filter_test_teardown);
6991 
6992   g_test_add ("/TreeModelFilter/unfiltered/show-single/vroot",
6993               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6994               filter_test_setup_empty_unfiltered,
6995               unfiltered_vroot_show_single,
6996               filter_test_teardown);
6997   g_test_add ("/TreeModelFilter/unfiltered/show-single-child/vroot",
6998               FilterTest, gtk_tree_path_new_from_indices (2, -1),
6999               filter_test_setup_empty_unfiltered,
7000               unfiltered_vroot_show_single_child,
7001               filter_test_teardown);
7002   g_test_add ("/TreeModelFilter/unfiltered/show-single-child/vroot/root-expanded",
7003               FilterTest, gtk_tree_path_new_from_indices (2, -1),
7004               filter_test_setup_empty_unfiltered_root_expanded,
7005               unfiltered_vroot_show_single_child_root_expanded,
7006               filter_test_teardown);
7007   g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level/vroot",
7008               FilterTest, gtk_tree_path_new_from_indices (2, -1),
7009               filter_test_setup_empty_unfiltered,
7010               unfiltered_vroot_show_single_multi_level,
7011               filter_test_teardown);
7012   g_test_add ("/TreeModelFilter/unfiltered/show-single-multi-level/vroot/root-expanded",
7013               FilterTest, gtk_tree_path_new_from_indices (2, -1),
7014               filter_test_setup_empty_unfiltered_root_expanded,
7015               unfiltered_vroot_show_single_multi_level_root_expanded,
7016               filter_test_teardown);
7017 
7018 
7019   g_test_add ("/TreeModelFilter/unfiltered/rows-reordered/root-level",
7020               FilterTest, NULL,
7021               filter_test_setup_unfiltered,
7022               unfiltered_rows_reordered_root_level,
7023               filter_test_teardown);
7024   g_test_add ("/TreeModelFilter/unfiltered/rows-reordered/child-level",
7025               FilterTest, NULL,
7026               filter_test_setup_unfiltered,
7027               unfiltered_rows_reordered_child_level,
7028               filter_test_teardown);
7029 
7030   g_test_add ("/TreeModelFilter/filtered/rows-reordered/root-level/first-hidden",
7031               FilterTest, NULL,
7032               filter_test_setup,
7033               filtered_rows_reordered_root_level_first_hidden,
7034               filter_test_teardown);
7035   g_test_add ("/TreeModelFilter/filtered/rows-reordered/root-level/middle-hidden",
7036               FilterTest, NULL,
7037               filter_test_setup,
7038               filtered_rows_reordered_root_level_middle_hidden,
7039               filter_test_teardown);
7040   g_test_add ("/TreeModelFilter/filtered/rows-reordered/child-level/first-hidden",
7041               FilterTest, NULL,
7042               filter_test_setup,
7043               filtered_rows_reordered_child_level_first_hidden,
7044               filter_test_teardown);
7045   g_test_add ("/TreeModelFilter/filtered/rows-reordered/child-level/middle-hidden",
7046               FilterTest, NULL,
7047               filter_test_setup,
7048               filtered_rows_reordered_child_level_middle_hidden,
7049               filter_test_teardown);
7050   g_test_add ("/TreeModelFilter/filtered/rows-reordered/child-level/4-hidden",
7051               FilterTest, NULL,
7052               filter_test_setup,
7053               filtered_rows_reordered_child_level_4_hidden,
7054               filter_test_teardown);
7055   g_test_add ("/TreeModelFilter/filtered/rows-reordered/child-level/all-hidden",
7056               FilterTest, NULL,
7057               filter_test_setup,
7058               filtered_rows_reordered_child_level_all_hidden,
7059               filter_test_teardown);
7060 
7061   /* Inserts in child models after creation of filter model */
7062   g_test_add_func ("/TreeModelFilter/insert/before",
7063                    insert_before);
7064   g_test_add_func ("/TreeModelFilter/insert/child",
7065                    insert_child);
7066 
7067   /* Removals from child model after creating of filter model */
7068   g_test_add_func ("/TreeModelFilter/remove/node",
7069                    remove_node);
7070   g_test_add_func ("/TreeModelFilter/remove/node-vroot",
7071                    remove_node_vroot);
7072   g_test_add_func ("/TreeModelFilter/remove/vroot-ancestor",
7073                    remove_vroot_ancestor);
7074 
7075   /* Reference counting */
7076   g_test_add_func ("/TreeModelFilter/ref-count/single-level",
7077                    ref_count_single_level);
7078   g_test_add_func ("/TreeModelFilter/ref-count/two-levels",
7079                    ref_count_two_levels);
7080   g_test_add_func ("/TreeModelFilter/ref-count/three-levels",
7081                    ref_count_three_levels);
7082   g_test_add_func ("/TreeModelFilter/ref-count/delete-row",
7083                    ref_count_delete_row);
7084   g_test_add_func ("/TreeModelFilter/ref-count/filter-row/length-1",
7085                    ref_count_filter_row_length_1);
7086   g_test_add_func ("/TreeModelFilter/ref-count/filter-row/length-1-remove-in-root-level",
7087                    ref_count_filter_row_length_1_remove_in_root_level);
7088   g_test_add_func ("/TreeModelFilter/ref-count/filter-row/length-1-remove-in-child-level",
7089                    ref_count_filter_row_length_1_remove_in_child_level);
7090   g_test_add_func ("/TreeModelFilter/ref-count/filter-row/length-gt-1",
7091                    ref_count_filter_row_length_gt_1);
7092   g_test_add_func ("/TreeModelFilter/ref-count/filter-row/length-gt-1-visible-children",
7093                    ref_count_filter_row_length_gt_1_visible_children);
7094   g_test_add_func ("/TreeModelFilter/ref-count/cleanup",
7095                    ref_count_cleanup);
7096   g_test_add_func ("/TreeModelFilter/ref-count/row-ref",
7097                    ref_count_row_ref);
7098 
7099   /* Reference counting, transfer of first reference on
7100    * first node in level.  This is a GtkTreeModelFilter-specific
7101    * feature.
7102    */
7103   g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/insert",
7104                    ref_count_transfer_root_level_insert);
7105   g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/remove",
7106                    ref_count_transfer_root_level_remove);
7107   g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/remove/filtered",
7108                    ref_count_transfer_root_level_remove_filtered);
7109   g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/reordered",
7110                    ref_count_transfer_root_level_reordered);
7111   g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/reordered/filtered",
7112                    ref_count_transfer_root_level_reordered_filtered);
7113   g_test_add_func ("/TreeModelFilter/ref-count/transfer/root-level/filter",
7114                    ref_count_transfer_root_level_filter);
7115   g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/insert",
7116                    ref_count_transfer_child_level_insert);
7117   g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/remove",
7118                    ref_count_transfer_child_level_remove);
7119   g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/remove/filtered",
7120                    ref_count_transfer_child_level_remove_filtered);
7121   g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/reordered",
7122                    ref_count_transfer_child_level_reordered);
7123   g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/reordered/filtered",
7124                    ref_count_transfer_child_level_reordered_filtered);
7125   g_test_add_func ("/TreeModelFilter/ref-count/transfer/child-level/filter",
7126                    ref_count_transfer_child_level_filter);
7127 
7128   g_test_add_func ("/TreeModelFilter/specific/path-dependent-filter",
7129                    specific_path_dependent_filter);
7130   g_test_add_func ("/TreeModelFilter/specific/append-after-collapse",
7131                    specific_append_after_collapse);
7132   g_test_add_func ("/TreeModelFilter/specific/sort-filter-remove-node",
7133                    specific_sort_filter_remove_node);
7134   g_test_add_func ("/TreeModelFilter/specific/sort-filter-remove-root",
7135                    specific_sort_filter_remove_root);
7136   g_test_add_func ("/TreeModelFilter/specific/root-mixed-visibility",
7137                    specific_root_mixed_visibility);
7138   g_test_add_func ("/TreeModelFilter/specific/has-child-filter",
7139                    specific_has_child_filter);
7140   g_test_add_func ("/TreeModelFilter/specific/has-child-filter-on-sort-model",
7141                    specific_has_child_filter_on_sort_model);
7142   g_test_add_func ("/TreeModelFilter/specific/at-least-2-children-filter",
7143                    specific_at_least_2_children_filter);
7144   g_test_add_func ("/TreeModelFilter/specific/at-least-2-children-filter-on-sort-model",
7145                    specific_at_least_2_children_filter_on_sort_model);
7146   g_test_add_func ("/TreeModelFilter/specific/root-has-child-filter",
7147                    specific_root_has_child_filter);
7148   g_test_add_func ("/TreeModelFilter/specific/filter-add-child",
7149                    specific_filter_add_child);
7150   g_test_add_func ("/TreeModelFilter/specific/list-store-clear",
7151                    specific_list_store_clear);
7152   g_test_add_func ("/TreeModelFilter/specific/sort-ref-leaf-and-remove-ancestor",
7153                    specific_sort_ref_leaf_and_remove_ancestor);
7154   g_test_add_func ("/TreeModelFilter/specific/ref-leaf-and-remove-ancestor",
7155                    specific_ref_leaf_and_remove_ancestor);
7156   g_test_add_func ("/TreeModelFilter/specific/virtual-ref-leaf-and-remove-ancestor",
7157                    specific_virtual_ref_leaf_and_remove_ancestor);
7158 
7159   g_test_add_func ("/TreeModelFilter/specific/bug-301558",
7160                    specific_bug_301558);
7161   g_test_add_func ("/TreeModelFilter/specific/bug-311955",
7162                    specific_bug_311955);
7163   g_test_add_func ("/TreeModelFilter/specific/bug-311955-clean",
7164                    specific_bug_311955_clean);
7165   g_test_add_func ("/TreeModelFilter/specific/bug-346800",
7166                    specific_bug_346800);
7167   g_test_add_func ("/TreeModelFilter/specific/bug-464173",
7168                    specific_bug_464173);
7169   g_test_add_func ("/TreeModelFilter/specific/bug-540201",
7170                    specific_bug_540201);
7171   g_test_add_func ("/TreeModelFilter/specific/bug-549287",
7172                    specific_bug_549287);
7173   g_test_add_func ("/TreeModelFilter/specific/bug-621076",
7174                    specific_bug_621076);
7175   g_test_add_func ("/TreeModelFilter/specific/bug-657353-related",
7176                    specific_bug_657353_related);
7177   g_test_add_func ("/TreeModelFilter/specific/bug-657353",
7178                    specific_bug_657353);
7179   g_test_add_func ("/TreeModelFilter/specific/bug-658696",
7180                    specific_bug_658696);
7181   g_test_add_func ("/TreeModelFilter/specific/bug-659022/row-changed-emission",
7182                    specific_bug_659022_row_changed_emission);
7183   g_test_add_func ("/TreeModelFilter/specific/bug-659022/row-deleted-node-invisible",
7184                    specific_bug_659022_row_deleted_node_invisible);
7185   g_test_add_func ("/TreeModelFilter/specific/bug-659022/row-deleted-free-level",
7186                    specific_bug_659022_row_deleted_free_level);
7187   g_test_add_func ("/TreeModelFilter/specific/bug-679910",
7188                    specific_bug_679910);
7189 
7190   g_test_add_func ("/TreeModelFilter/signal/row-changed", test_row_changed);
7191 }
7192