1 /* GtkTreeModel ref counting tests
2  * Copyright (C) 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 "gtktreemodelrefcount.h"
19 #include "treemodel.h"
20 
21 /* And the tests themselves */
22 
23 static void
test_list_no_reference(void)24 test_list_no_reference (void)
25 {
26   GtkTreeIter iter;
27   GtkTreeModel *model;
28   GtkTreeModelRefCount *ref_model;
29 
30   model = gtk_tree_model_ref_count_new ();
31   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
32 
33   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
34   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
35   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
36   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
37   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
38 
39   assert_root_level_unreferenced (ref_model);
40 
41   g_object_unref (ref_model);
42 }
43 
44 static void
test_list_reference_during_creation(void)45 test_list_reference_during_creation (void)
46 {
47   GtkTreeIter iter;
48   GtkTreeModel *model;
49   GtkTreeModelRefCount *ref_model;
50   GtkWidget *tree_view;
51 
52   model = gtk_tree_model_ref_count_new ();
53   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
54   tree_view = gtk_tree_view_new_with_model (model);
55 
56   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
57   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
58   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
59   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
60   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
61 
62   assert_root_level_referenced (ref_model, 1);
63 
64   g_object_unref (g_object_ref_sink (tree_view));
65 
66   assert_root_level_unreferenced (ref_model);
67 
68   g_object_unref (ref_model);
69 }
70 
71 static void
test_list_reference_after_creation(void)72 test_list_reference_after_creation (void)
73 {
74   GtkTreeIter iter;
75   GtkTreeModel *model;
76   GtkTreeModelRefCount *ref_model;
77   GtkWidget *tree_view;
78 
79   model = gtk_tree_model_ref_count_new ();
80   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
81 
82   assert_root_level_unreferenced (ref_model);
83 
84   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
85   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
86   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
87   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
88   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
89 
90   tree_view = gtk_tree_view_new_with_model (model);
91 
92   assert_root_level_referenced (ref_model, 1);
93 
94   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
95   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
96 
97   assert_root_level_referenced (ref_model, 1);
98 
99   g_object_unref (g_object_ref_sink (tree_view));
100 
101   assert_root_level_unreferenced (ref_model);
102 
103   g_object_unref (ref_model);
104 }
105 
106 static void
test_list_reference_reordered(void)107 test_list_reference_reordered (void)
108 {
109   GtkTreeIter iter1, iter2, iter3, iter4, iter5;
110   GtkTreeModel *model;
111   GtkTreeModelRefCount *ref_model;
112   GtkWidget *tree_view;
113 
114   model = gtk_tree_model_ref_count_new ();
115   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
116 
117   assert_root_level_unreferenced (ref_model);
118 
119   gtk_tree_store_append (GTK_TREE_STORE (model), &iter1, NULL);
120   gtk_tree_store_append (GTK_TREE_STORE (model), &iter2, NULL);
121   gtk_tree_store_append (GTK_TREE_STORE (model), &iter3, NULL);
122   gtk_tree_store_append (GTK_TREE_STORE (model), &iter4, NULL);
123   gtk_tree_store_append (GTK_TREE_STORE (model), &iter5, NULL);
124 
125   tree_view = gtk_tree_view_new_with_model (model);
126 
127   assert_root_level_referenced (ref_model, 1);
128 
129   gtk_tree_store_move_after (GTK_TREE_STORE (model),
130                              &iter1, &iter5);
131 
132   assert_root_level_referenced (ref_model, 1);
133 
134   gtk_tree_store_move_after (GTK_TREE_STORE (model),
135                              &iter3, &iter4);
136 
137   assert_root_level_referenced (ref_model, 1);
138 
139   g_object_unref (g_object_ref_sink (tree_view));
140 
141   assert_root_level_unreferenced (ref_model);
142 
143   g_object_unref (ref_model);
144 }
145 
146 
147 static void
test_tree_no_reference(void)148 test_tree_no_reference (void)
149 {
150   GtkTreeIter iter, child;
151   GtkTreeModel *model;
152   GtkTreeModelRefCount *ref_model;
153 
154   model = gtk_tree_model_ref_count_new ();
155   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
156 
157   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
158   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
159   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
160   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
161   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
162   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
163   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
164   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
165   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
166   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
167   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
168 
169   assert_entire_model_unreferenced (ref_model);
170 
171   g_object_unref (ref_model);
172 }
173 
174 static void
test_tree_reference_during_creation(void)175 test_tree_reference_during_creation (void)
176 {
177   GtkTreeIter iter, child;
178   GtkTreeModel *model;
179   GtkTreeModelRefCount *ref_model;
180   GtkWidget *tree_view;
181 
182   model = gtk_tree_model_ref_count_new ();
183   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
184   tree_view = gtk_tree_view_new_with_model (model);
185 
186   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
187   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
188   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
189   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
190   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
191   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
192   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
193   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
194   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
195   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
196   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
197 
198   assert_root_level_referenced (ref_model, 1);
199   assert_not_entire_model_referenced (ref_model, 1);
200   assert_level_unreferenced (ref_model, &child);
201 
202   g_object_unref (g_object_ref_sink (tree_view));
203 
204   assert_entire_model_unreferenced (ref_model);
205 
206   g_object_unref (ref_model);
207 }
208 
209 static void
test_tree_reference_after_creation(void)210 test_tree_reference_after_creation (void)
211 {
212   GtkTreeIter iter, child;
213   GtkTreeModel *model;
214   GtkTreeModelRefCount *ref_model;
215   GtkWidget *tree_view;
216 
217   model = gtk_tree_model_ref_count_new ();
218   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
219 
220   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
221   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
222   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
223   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
224   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
225   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
226   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
227   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
228   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
229   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
230   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
231 
232   assert_entire_model_unreferenced (ref_model);
233 
234   tree_view = gtk_tree_view_new_with_model (model);
235 
236   assert_root_level_referenced (ref_model, 1);
237   assert_not_entire_model_referenced (ref_model, 1);
238   assert_level_unreferenced (ref_model, &child);
239 
240   g_object_unref (g_object_ref_sink (tree_view));
241 
242   assert_entire_model_unreferenced (ref_model);
243 
244   g_object_unref (ref_model);
245 }
246 
247 static void
test_tree_reference_reordered(void)248 test_tree_reference_reordered (void)
249 {
250   GtkTreeIter parent;
251   GtkTreeIter iter1, iter2, iter3, iter4, iter5;
252   GtkTreeModel *model;
253   GtkTreeModelRefCount *ref_model;
254   GtkWidget *tree_view;
255 
256   model = gtk_tree_model_ref_count_new ();
257   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
258 
259   assert_root_level_unreferenced (ref_model);
260 
261   gtk_tree_store_append (GTK_TREE_STORE (model), &parent, NULL);
262   gtk_tree_store_append (GTK_TREE_STORE (model), &iter1, &parent);
263   gtk_tree_store_append (GTK_TREE_STORE (model), &iter2, &parent);
264   gtk_tree_store_append (GTK_TREE_STORE (model), &iter3, &parent);
265   gtk_tree_store_append (GTK_TREE_STORE (model), &iter4, &parent);
266   gtk_tree_store_append (GTK_TREE_STORE (model), &iter5, &parent);
267 
268   tree_view = gtk_tree_view_new_with_model (model);
269   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
270 
271   assert_entire_model_referenced (ref_model, 1);
272 
273   gtk_tree_store_move_after (GTK_TREE_STORE (model),
274                              &iter1, &iter5);
275 
276   assert_entire_model_referenced (ref_model, 1);
277 
278   gtk_tree_store_move_after (GTK_TREE_STORE (model),
279                              &iter3, &iter4);
280 
281   assert_entire_model_referenced (ref_model, 1);
282 
283   g_object_unref (g_object_ref_sink (tree_view));
284 
285   assert_entire_model_unreferenced (ref_model);
286 
287   g_object_unref (ref_model);
288 }
289 
290 static void
test_tree_reference_expand_all(void)291 test_tree_reference_expand_all (void)
292 {
293   GtkTreeIter iter, child;
294   GtkTreeModel *model;
295   GtkTreeModelRefCount *ref_model;
296   GtkWidget *tree_view;
297 
298   model = gtk_tree_model_ref_count_new ();
299   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
300 
301   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
302   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
303   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
304   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
305   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
306   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
307   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
308   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
309   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
310   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
311   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
312 
313   assert_entire_model_unreferenced (ref_model);
314 
315   tree_view = gtk_tree_view_new_with_model (model);
316 
317   assert_root_level_referenced (ref_model, 1);
318   assert_not_entire_model_referenced (ref_model, 1);
319   assert_level_unreferenced (ref_model, &child);
320 
321   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
322 
323   assert_entire_model_referenced (ref_model, 1);
324 
325   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
326   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
327   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
328 
329   assert_root_level_referenced (ref_model, 1);
330   assert_not_entire_model_referenced (ref_model, 1);
331   assert_level_unreferenced (ref_model, &child);
332 
333   g_object_unref (g_object_ref_sink (tree_view));
334 
335   assert_entire_model_unreferenced (ref_model);
336 
337   g_object_unref (ref_model);
338 }
339 
340 static void
test_tree_reference_collapse_all(void)341 test_tree_reference_collapse_all (void)
342 {
343   GtkTreeIter iter, child;
344   GtkTreeModel *model;
345   GtkTreeModelRefCount *ref_model;
346   GtkWidget *tree_view;
347 
348   model = gtk_tree_model_ref_count_new ();
349   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
350 
351   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
352   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
353   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
354   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
355   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
356   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
357   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
358   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
359   gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
360   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
361   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter);
362 
363   assert_entire_model_unreferenced (ref_model);
364 
365   tree_view = gtk_tree_view_new_with_model (model);
366   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
367 
368   assert_entire_model_referenced (ref_model, 1);
369 
370   gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view));
371 
372   assert_root_level_referenced (ref_model, 1);
373   assert_not_entire_model_referenced (ref_model, 1);
374   assert_level_unreferenced (ref_model, &child);
375 
376   g_object_unref (g_object_ref_sink (tree_view));
377 
378   assert_entire_model_unreferenced (ref_model);
379 
380   g_object_unref (ref_model);
381 }
382 
383 static void
test_tree_reference_expand_collapse(void)384 test_tree_reference_expand_collapse (void)
385 {
386   GtkTreeIter parent1, parent2, child;
387   GtkTreePath *path1, *path2;
388   GtkTreeModel *model;
389   GtkTreeModelRefCount *ref_model;
390   GtkWidget *tree_view;
391 
392   model = gtk_tree_model_ref_count_new ();
393   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
394   tree_view = gtk_tree_view_new_with_model (model);
395 
396   gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, NULL);
397   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &parent1);
398   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &parent1);
399   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, NULL);
400   gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, NULL);
401   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &parent2);
402   gtk_tree_store_append (GTK_TREE_STORE (model), &child, &parent2);
403 
404   path1 = gtk_tree_model_get_path (model, &parent1);
405   path2 = gtk_tree_model_get_path (model, &parent2);
406 
407   assert_level_unreferenced (ref_model, &parent1);
408   assert_level_unreferenced (ref_model, &parent2);
409 
410   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path1, FALSE);
411 
412   assert_level_referenced (ref_model, 1, &parent1);
413   assert_level_unreferenced (ref_model, &parent2);
414 
415   gtk_tree_view_collapse_row (GTK_TREE_VIEW (tree_view), path1);
416 
417   assert_level_unreferenced (ref_model, &parent1);
418   assert_level_unreferenced (ref_model, &parent2);
419 
420   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path2, FALSE);
421 
422   assert_level_unreferenced (ref_model, &parent1);
423   assert_level_referenced (ref_model, 1, &parent2);
424 
425   gtk_tree_view_collapse_row (GTK_TREE_VIEW (tree_view), path2);
426 
427   assert_level_unreferenced (ref_model, &parent1);
428   assert_level_unreferenced (ref_model, &parent2);
429 
430   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path2, FALSE);
431 
432   assert_level_unreferenced (ref_model, &parent1);
433   assert_level_referenced (ref_model, 1, &parent2);
434 
435   gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path1, FALSE);
436 
437   assert_level_referenced (ref_model, 1, &parent1);
438   assert_level_referenced (ref_model, 1, &parent2);
439 
440   gtk_tree_path_free (path1);
441   gtk_tree_path_free (path2);
442 
443   g_object_unref (g_object_ref_sink (tree_view));
444   g_object_unref (ref_model);
445 }
446 
447 static void
test_row_reference_list(void)448 test_row_reference_list (void)
449 {
450   GtkTreeIter iter0, iter1, iter2;
451   GtkTreePath *path;
452   GtkTreeModel *model;
453   GtkTreeModelRefCount *ref_model;
454   GtkTreeRowReference *row_ref;
455   GtkWidget *tree_view;
456 
457   model = gtk_tree_model_ref_count_new ();
458   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
459 
460   gtk_tree_store_append (GTK_TREE_STORE (model), &iter0, NULL);
461   gtk_tree_store_append (GTK_TREE_STORE (model), &iter1, NULL);
462   gtk_tree_store_append (GTK_TREE_STORE (model), &iter2, NULL);
463 
464   assert_root_level_unreferenced (ref_model);
465 
466   /* create and remove a row ref and check reference counts */
467   path = gtk_tree_path_new_from_indices (1, -1);
468   row_ref = gtk_tree_row_reference_new (model, path);
469 
470   assert_node_ref_count (ref_model, &iter0, 0);
471   assert_node_ref_count (ref_model, &iter1, 1);
472   assert_node_ref_count (ref_model, &iter2, 0);
473 
474   gtk_tree_row_reference_free (row_ref);
475 
476   assert_root_level_unreferenced (ref_model);
477 
478   /* the same, but then also with a tree view monitoring the model */
479   tree_view = gtk_tree_view_new_with_model (model);
480 
481   assert_root_level_referenced (ref_model, 1);
482 
483   row_ref = gtk_tree_row_reference_new (model, path);
484 
485   assert_node_ref_count (ref_model, &iter0, 1);
486   assert_node_ref_count (ref_model, &iter1, 2);
487   assert_node_ref_count (ref_model, &iter2, 1);
488 
489   g_object_unref (g_object_ref_sink (tree_view));
490 
491   assert_node_ref_count (ref_model, &iter0, 0);
492   assert_node_ref_count (ref_model, &iter1, 1);
493   assert_node_ref_count (ref_model, &iter2, 0);
494 
495   gtk_tree_row_reference_free (row_ref);
496 
497   assert_root_level_unreferenced (ref_model);
498 
499   gtk_tree_path_free (path);
500 
501   g_object_unref (ref_model);
502 }
503 
504 static void
test_row_reference_list_remove(void)505 test_row_reference_list_remove (void)
506 {
507   GtkTreeIter iter0, iter1, iter2;
508   GtkTreePath *path;
509   GtkTreeModel *model;
510   GtkTreeModelRefCount *ref_model;
511   GtkTreeRowReference *row_ref;
512 
513   model = gtk_tree_model_ref_count_new ();
514   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
515 
516   gtk_tree_store_append (GTK_TREE_STORE (model), &iter0, NULL);
517   gtk_tree_store_append (GTK_TREE_STORE (model), &iter1, NULL);
518   gtk_tree_store_append (GTK_TREE_STORE (model), &iter2, NULL);
519 
520   assert_root_level_unreferenced (ref_model);
521 
522   /* test creating the row reference and then removing the node */
523   path = gtk_tree_path_new_from_indices (1, -1);
524   row_ref = gtk_tree_row_reference_new (model, path);
525 
526   assert_node_ref_count (ref_model, &iter0, 0);
527   assert_node_ref_count (ref_model, &iter1, 1);
528   assert_node_ref_count (ref_model, &iter2, 0);
529 
530   gtk_tree_store_remove (GTK_TREE_STORE (model), &iter1);
531 
532   assert_root_level_unreferenced (ref_model);
533 
534   gtk_tree_row_reference_free (row_ref);
535 
536   assert_root_level_unreferenced (ref_model);
537 
538   /* test creating a row ref, removing another node and then removing
539    * the row ref node.
540    */
541   row_ref = gtk_tree_row_reference_new (model, path);
542 
543   assert_node_ref_count (ref_model, &iter0, 0);
544   assert_node_ref_count (ref_model, &iter2, 1);
545 
546   gtk_tree_store_remove (GTK_TREE_STORE (model), &iter0);
547 
548   assert_root_level_referenced (ref_model, 1);
549 
550   gtk_tree_store_remove (GTK_TREE_STORE (model), &iter2);
551 
552   g_assert_false (gtk_tree_model_get_iter_first (model, &iter0));
553 
554   gtk_tree_row_reference_free (row_ref);
555 
556   gtk_tree_path_free (path);
557 
558   g_object_unref (ref_model);
559 }
560 
561 static void
test_row_reference_tree(void)562 test_row_reference_tree (void)
563 {
564   GtkTreeIter iter0, iter1, iter2;
565   GtkTreeIter child0, child1, child2;
566   GtkTreeIter grandchild0, grandchild1, grandchild2;
567   GtkTreePath *path;
568   GtkTreeModel *model;
569   GtkTreeModelRefCount *ref_model;
570   GtkTreeRowReference *row_ref, *row_ref1;
571   GtkWidget *tree_view;
572 
573   model = gtk_tree_model_ref_count_new ();
574   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
575 
576   gtk_tree_store_append (GTK_TREE_STORE (model), &iter0, NULL);
577   gtk_tree_store_append (GTK_TREE_STORE (model), &child0, &iter0);
578   gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild0, &child0);
579   gtk_tree_store_append (GTK_TREE_STORE (model), &iter1, NULL);
580   gtk_tree_store_append (GTK_TREE_STORE (model), &child1, &iter1);
581   gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild1, &child1);
582   gtk_tree_store_append (GTK_TREE_STORE (model), &iter2, NULL);
583   gtk_tree_store_append (GTK_TREE_STORE (model), &child2, &iter2);
584   gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild2, &child2);
585 
586   assert_entire_model_unreferenced (ref_model);
587 
588   /* create and remove a row ref and check reference counts */
589   path = gtk_tree_path_new_from_indices (1, 0, 0, -1);
590   row_ref = gtk_tree_row_reference_new (model, path);
591   gtk_tree_path_free (path);
592 
593   assert_node_ref_count (ref_model, &iter0, 0);
594   assert_node_ref_count (ref_model, &child0, 0);
595   assert_node_ref_count (ref_model, &grandchild0, 0);
596   assert_node_ref_count (ref_model, &iter1, 1);
597   assert_node_ref_count (ref_model, &child1, 1);
598   assert_node_ref_count (ref_model, &grandchild1, 1);
599   assert_node_ref_count (ref_model, &iter2, 0);
600   assert_node_ref_count (ref_model, &child2, 0);
601   assert_node_ref_count (ref_model, &grandchild2, 0);
602 
603   gtk_tree_row_reference_free (row_ref);
604 
605   assert_entire_model_unreferenced (ref_model);
606 
607   /* again, with path 1:1 */
608   path = gtk_tree_path_new_from_indices (1, 0, -1);
609   row_ref = gtk_tree_row_reference_new (model, path);
610   gtk_tree_path_free (path);
611 
612   assert_node_ref_count (ref_model, &iter0, 0);
613   assert_node_ref_count (ref_model, &child0, 0);
614   assert_node_ref_count (ref_model, &grandchild0, 0);
615   assert_node_ref_count (ref_model, &iter1, 1);
616   assert_node_ref_count (ref_model, &child1, 1);
617   assert_node_ref_count (ref_model, &grandchild1, 0);
618   assert_node_ref_count (ref_model, &iter2, 0);
619   assert_node_ref_count (ref_model, &child2, 0);
620   assert_node_ref_count (ref_model, &grandchild2, 0);
621 
622   gtk_tree_row_reference_free (row_ref);
623 
624   assert_entire_model_unreferenced (ref_model);
625 
626   /* both row refs existent at once and also with a tree view monitoring
627    * the model
628    */
629   tree_view = gtk_tree_view_new_with_model (model);
630 
631   assert_root_level_referenced (ref_model, 1);
632 
633   path = gtk_tree_path_new_from_indices (1, 0, 0, -1);
634   row_ref = gtk_tree_row_reference_new (model, path);
635   gtk_tree_path_free (path);
636 
637   assert_node_ref_count (ref_model, &iter0, 1);
638   assert_node_ref_count (ref_model, &child0, 0);
639   assert_node_ref_count (ref_model, &grandchild0, 0);
640   assert_node_ref_count (ref_model, &iter1, 2);
641   assert_node_ref_count (ref_model, &child1, 1);
642   assert_node_ref_count (ref_model, &grandchild1, 1);
643   assert_node_ref_count (ref_model, &iter2, 1);
644   assert_node_ref_count (ref_model, &child2, 0);
645   assert_node_ref_count (ref_model, &grandchild2, 0);
646 
647   path = gtk_tree_path_new_from_indices (1, 0, -1);
648   row_ref1 = gtk_tree_row_reference_new (model, path);
649   gtk_tree_path_free (path);
650 
651   assert_node_ref_count (ref_model, &iter0, 1);
652   assert_node_ref_count (ref_model, &child0, 0);
653   assert_node_ref_count (ref_model, &grandchild0, 0);
654   assert_node_ref_count (ref_model, &iter1, 3);
655   assert_node_ref_count (ref_model, &child1, 2);
656   assert_node_ref_count (ref_model, &grandchild1, 1);
657   assert_node_ref_count (ref_model, &iter2, 1);
658   assert_node_ref_count (ref_model, &child2, 0);
659   assert_node_ref_count (ref_model, &grandchild2, 0);
660 
661   gtk_tree_row_reference_free (row_ref);
662 
663   assert_node_ref_count (ref_model, &iter0, 1);
664   assert_node_ref_count (ref_model, &child0, 0);
665   assert_node_ref_count (ref_model, &grandchild0, 0);
666   assert_node_ref_count (ref_model, &iter1, 2);
667   assert_node_ref_count (ref_model, &child1, 1);
668   assert_node_ref_count (ref_model, &grandchild1, 0);
669   assert_node_ref_count (ref_model, &iter2, 1);
670   assert_node_ref_count (ref_model, &child2, 0);
671   assert_node_ref_count (ref_model, &grandchild2, 0);
672 
673   g_object_unref (g_object_ref_sink (tree_view));
674 
675   assert_node_ref_count (ref_model, &iter0, 0);
676   assert_node_ref_count (ref_model, &child0, 0);
677   assert_node_ref_count (ref_model, &grandchild0, 0);
678   assert_node_ref_count (ref_model, &iter1, 1);
679   assert_node_ref_count (ref_model, &child1, 1);
680   assert_node_ref_count (ref_model, &grandchild1, 0);
681   assert_node_ref_count (ref_model, &iter2, 0);
682   assert_node_ref_count (ref_model, &child2, 0);
683   assert_node_ref_count (ref_model, &grandchild2, 0);
684 
685   gtk_tree_row_reference_free (row_ref1);
686 
687   assert_root_level_unreferenced (ref_model);
688 
689   g_object_unref (ref_model);
690 }
691 
692 static void
test_row_reference_tree_remove(void)693 test_row_reference_tree_remove (void)
694 {
695   GtkTreeIter iter0, iter1, iter2;
696   GtkTreeIter child0, child1, child2;
697   GtkTreeIter grandchild0, grandchild1, grandchild2;
698   GtkTreePath *path;
699   GtkTreeModel *model;
700   GtkTreeModelRefCount *ref_model;
701   GtkTreeRowReference *row_ref, *row_ref1, *row_ref2;
702 
703   model = gtk_tree_model_ref_count_new ();
704   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
705 
706   gtk_tree_store_append (GTK_TREE_STORE (model), &iter0, NULL);
707   gtk_tree_store_append (GTK_TREE_STORE (model), &child0, &iter0);
708   gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild0, &child0);
709   gtk_tree_store_append (GTK_TREE_STORE (model), &iter1, NULL);
710   gtk_tree_store_append (GTK_TREE_STORE (model), &child1, &iter1);
711   gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild1, &child1);
712   gtk_tree_store_append (GTK_TREE_STORE (model), &iter2, NULL);
713   gtk_tree_store_append (GTK_TREE_STORE (model), &child2, &iter2);
714   gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild2, &child2);
715 
716   assert_entire_model_unreferenced (ref_model);
717 
718   path = gtk_tree_path_new_from_indices (1, 0, 0, -1);
719   row_ref = gtk_tree_row_reference_new (model, path);
720   gtk_tree_path_free (path);
721 
722   path = gtk_tree_path_new_from_indices (2, 0, -1);
723   row_ref1 = gtk_tree_row_reference_new (model, path);
724   gtk_tree_path_free (path);
725 
726   path = gtk_tree_path_new_from_indices (2, -1);
727   row_ref2 = gtk_tree_row_reference_new (model, path);
728   gtk_tree_path_free (path);
729 
730   assert_node_ref_count (ref_model, &iter0, 0);
731   assert_node_ref_count (ref_model, &child0, 0);
732   assert_node_ref_count (ref_model, &grandchild0, 0);
733   assert_node_ref_count (ref_model, &iter1, 1);
734   assert_node_ref_count (ref_model, &child1, 1);
735   assert_node_ref_count (ref_model, &grandchild1, 1);
736   assert_node_ref_count (ref_model, &iter2, 2);
737   assert_node_ref_count (ref_model, &child2, 1);
738   assert_node_ref_count (ref_model, &grandchild2, 0);
739 
740   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandchild1);
741 
742   assert_node_ref_count (ref_model, &iter0, 0);
743   assert_node_ref_count (ref_model, &child0, 0);
744   assert_node_ref_count (ref_model, &grandchild0, 0);
745   assert_node_ref_count (ref_model, &iter1, 0);
746   assert_node_ref_count (ref_model, &child1, 0);
747   assert_node_ref_count (ref_model, &iter2, 2);
748   assert_node_ref_count (ref_model, &child2, 1);
749   assert_node_ref_count (ref_model, &grandchild2, 0);
750 
751   gtk_tree_store_remove (GTK_TREE_STORE (model), &child2);
752 
753   assert_node_ref_count (ref_model, &iter0, 0);
754   assert_node_ref_count (ref_model, &child0, 0);
755   assert_node_ref_count (ref_model, &grandchild0, 0);
756   assert_node_ref_count (ref_model, &iter1, 0);
757   assert_node_ref_count (ref_model, &child1, 0);
758   assert_node_ref_count (ref_model, &iter2, 1);
759 
760   gtk_tree_store_remove (GTK_TREE_STORE (model), &iter2);
761 
762   assert_entire_model_unreferenced (ref_model);
763 
764   gtk_tree_row_reference_free (row_ref);
765   gtk_tree_row_reference_free (row_ref1);
766   gtk_tree_row_reference_free (row_ref2);
767 
768   g_object_unref (ref_model);
769 }
770 
771 static void
test_row_reference_tree_remove_ancestor(void)772 test_row_reference_tree_remove_ancestor (void)
773 {
774   GtkTreeIter iter0, iter1, iter2;
775   GtkTreeIter child0, child1, child2;
776   GtkTreeIter grandchild0, grandchild1, grandchild2;
777   GtkTreePath *path;
778   GtkTreeModel *model;
779   GtkTreeModelRefCount *ref_model;
780   GtkTreeRowReference *row_ref, *row_ref1;
781 
782   model = gtk_tree_model_ref_count_new ();
783   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
784 
785   gtk_tree_store_append (GTK_TREE_STORE (model), &iter0, NULL);
786   gtk_tree_store_append (GTK_TREE_STORE (model), &child0, &iter0);
787   gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild0, &child0);
788   gtk_tree_store_append (GTK_TREE_STORE (model), &iter1, NULL);
789   gtk_tree_store_append (GTK_TREE_STORE (model), &child1, &iter1);
790   gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild1, &child1);
791   gtk_tree_store_append (GTK_TREE_STORE (model), &iter2, NULL);
792   gtk_tree_store_append (GTK_TREE_STORE (model), &child2, &iter2);
793   gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild2, &child2);
794 
795   assert_entire_model_unreferenced (ref_model);
796 
797   path = gtk_tree_path_new_from_indices (1, 0, 0, -1);
798   row_ref = gtk_tree_row_reference_new (model, path);
799   gtk_tree_path_free (path);
800 
801   path = gtk_tree_path_new_from_indices (2, 0, -1);
802   row_ref1 = gtk_tree_row_reference_new (model, path);
803   gtk_tree_path_free (path);
804 
805   assert_node_ref_count (ref_model, &iter0, 0);
806   assert_node_ref_count (ref_model, &child0, 0);
807   assert_node_ref_count (ref_model, &grandchild0, 0);
808   assert_node_ref_count (ref_model, &iter1, 1);
809   assert_node_ref_count (ref_model, &child1, 1);
810   assert_node_ref_count (ref_model, &grandchild1, 1);
811   assert_node_ref_count (ref_model, &iter2, 1);
812   assert_node_ref_count (ref_model, &child2, 1);
813   assert_node_ref_count (ref_model, &grandchild2, 0);
814 
815   gtk_tree_store_remove (GTK_TREE_STORE (model), &child1);
816 
817   assert_node_ref_count (ref_model, &iter0, 0);
818   assert_node_ref_count (ref_model, &child0, 0);
819   assert_node_ref_count (ref_model, &grandchild0, 0);
820   assert_node_ref_count (ref_model, &iter1, 0);
821   assert_node_ref_count (ref_model, &iter2, 1);
822   assert_node_ref_count (ref_model, &child2, 1);
823   assert_node_ref_count (ref_model, &grandchild2, 0);
824 
825   gtk_tree_store_remove (GTK_TREE_STORE (model), &iter2);
826 
827   assert_entire_model_unreferenced (ref_model);
828 
829   gtk_tree_row_reference_free (row_ref);
830   gtk_tree_row_reference_free (row_ref1);
831 
832   g_object_unref (ref_model);
833 }
834 
835 static void
test_row_reference_tree_expand(void)836 test_row_reference_tree_expand (void)
837 {
838   GtkTreeIter iter0, iter1, iter2;
839   GtkTreeIter child0, child1, child2;
840   GtkTreeIter grandchild0, grandchild1, grandchild2;
841   GtkTreePath *path;
842   GtkTreeModel *model;
843   GtkTreeModelRefCount *ref_model;
844   GtkTreeRowReference *row_ref, *row_ref1, *row_ref2;
845   GtkWidget *tree_view;
846 
847   model = gtk_tree_model_ref_count_new ();
848   ref_model = GTK_TREE_MODEL_REF_COUNT (model);
849   tree_view = gtk_tree_view_new_with_model (model);
850 
851   gtk_tree_store_append (GTK_TREE_STORE (model), &iter0, NULL);
852   gtk_tree_store_append (GTK_TREE_STORE (model), &child0, &iter0);
853   gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild0, &child0);
854   gtk_tree_store_append (GTK_TREE_STORE (model), &iter1, NULL);
855   gtk_tree_store_append (GTK_TREE_STORE (model), &child1, &iter1);
856   gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild1, &child1);
857   gtk_tree_store_append (GTK_TREE_STORE (model), &iter2, NULL);
858   gtk_tree_store_append (GTK_TREE_STORE (model), &child2, &iter2);
859   gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild2, &child2);
860 
861   assert_root_level_referenced (ref_model, 1);
862 
863   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
864 
865   assert_entire_model_referenced (ref_model, 1);
866 
867   path = gtk_tree_path_new_from_indices (1, 0, 0, -1);
868   row_ref = gtk_tree_row_reference_new (model, path);
869   gtk_tree_path_free (path);
870 
871   path = gtk_tree_path_new_from_indices (2, 0, -1);
872   row_ref1 = gtk_tree_row_reference_new (model, path);
873   gtk_tree_path_free (path);
874 
875   path = gtk_tree_path_new_from_indices (2, -1);
876   row_ref2 = gtk_tree_row_reference_new (model, path);
877   gtk_tree_path_free (path);
878 
879   assert_node_ref_count (ref_model, &iter0, 1);
880   assert_node_ref_count (ref_model, &child0, 1);
881   assert_node_ref_count (ref_model, &grandchild0, 1);
882   assert_node_ref_count (ref_model, &iter1, 2);
883   assert_node_ref_count (ref_model, &child1, 2);
884   assert_node_ref_count (ref_model, &grandchild1, 2);
885   assert_node_ref_count (ref_model, &iter2, 3);
886   assert_node_ref_count (ref_model, &child2, 2);
887   assert_node_ref_count (ref_model, &grandchild2, 1);
888 
889   gtk_tree_store_remove (GTK_TREE_STORE (model), &grandchild1);
890 
891   assert_node_ref_count (ref_model, &iter0, 1);
892   assert_node_ref_count (ref_model, &child0, 1);
893   assert_node_ref_count (ref_model, &grandchild0, 1);
894   assert_node_ref_count (ref_model, &iter1, 1);
895   assert_node_ref_count (ref_model, &child1, 1);
896   assert_node_ref_count (ref_model, &iter2, 3);
897   assert_node_ref_count (ref_model, &child2, 2);
898   assert_node_ref_count (ref_model, &grandchild2, 1);
899 
900   gtk_tree_store_remove (GTK_TREE_STORE (model), &child2);
901 
902   assert_node_ref_count (ref_model, &iter0, 1);
903   assert_node_ref_count (ref_model, &child0, 1);
904   assert_node_ref_count (ref_model, &grandchild0, 1);
905   assert_node_ref_count (ref_model, &iter1, 1);
906   assert_node_ref_count (ref_model, &child1, 1);
907   assert_node_ref_count (ref_model, &iter2, 2);
908 
909   gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view));
910 
911   assert_node_ref_count (ref_model, &iter0, 1);
912   assert_node_ref_count (ref_model, &child0, 0);
913   assert_node_ref_count (ref_model, &grandchild0, 0);
914   assert_node_ref_count (ref_model, &iter1, 1);
915   assert_node_ref_count (ref_model, &child1, 0);
916   assert_node_ref_count (ref_model, &iter2, 2);
917 
918   gtk_tree_store_remove (GTK_TREE_STORE (model), &iter2);
919 
920   assert_node_ref_count (ref_model, &iter0, 1);
921   assert_node_ref_count (ref_model, &child0, 0);
922   assert_node_ref_count (ref_model, &grandchild0, 0);
923   assert_node_ref_count (ref_model, &iter1, 1);
924   assert_node_ref_count (ref_model, &child1, 0);
925 
926   gtk_tree_row_reference_free (row_ref);
927   gtk_tree_row_reference_free (row_ref1);
928   gtk_tree_row_reference_free (row_ref2);
929 
930   g_object_unref (g_object_ref_sink (tree_view));
931   g_object_unref (ref_model);
932 }
933 
934 void
register_model_ref_count_tests(void)935 register_model_ref_count_tests (void)
936 {
937   /* lists (though based on GtkTreeStore) */
938   g_test_add_func ("/TreeModel/ref-count/list/no-reference",
939                    test_list_no_reference);
940   g_test_add_func ("/TreeModel/ref-count/list/reference-during-creation",
941                    test_list_reference_during_creation);
942   g_test_add_func ("/TreeModel/ref-count/list/reference-after-creation",
943                    test_list_reference_after_creation);
944   g_test_add_func ("/TreeModel/ref-count/list/reference-reordered",
945                    test_list_reference_reordered);
946 
947   /* trees */
948   g_test_add_func ("/TreeModel/ref-count/tree/no-reference",
949                    test_tree_no_reference);
950   g_test_add_func ("/TreeModel/ref-count/tree/reference-during-creation",
951                    test_tree_reference_during_creation);
952   g_test_add_func ("/TreeModel/ref-count/tree/reference-after-creation",
953                    test_tree_reference_after_creation);
954   g_test_add_func ("/TreeModel/ref-count/tree/expand-all",
955                    test_tree_reference_expand_all);
956   g_test_add_func ("/TreeModel/ref-count/tree/collapse-all",
957                    test_tree_reference_collapse_all);
958   g_test_add_func ("/TreeModel/ref-count/tree/expand-collapse",
959                    test_tree_reference_expand_collapse);
960   g_test_add_func ("/TreeModel/ref-count/tree/reference-reordered",
961                    test_tree_reference_reordered);
962 
963   /* row references */
964   g_test_add_func ("/TreeModel/ref-count/row-reference/list",
965                    test_row_reference_list);
966   g_test_add_func ("/TreeModel/ref-count/row-reference/list-remove",
967                    test_row_reference_list_remove);
968   g_test_add_func ("/TreeModel/ref-count/row-reference/tree",
969                    test_row_reference_tree);
970   g_test_add_func ("/TreeModel/ref-count/row-reference/tree-remove",
971                    test_row_reference_tree_remove);
972   g_test_add_func ("/TreeModel/ref-count/row-reference/tree-remove-ancestor",
973                    test_row_reference_tree_remove_ancestor);
974   g_test_add_func ("/TreeModel/ref-count/row-reference/tree-expand",
975                    test_row_reference_tree_expand);
976 }
977