From: Kristian Rietveld Date: Sat, 28 May 2011 14:48:15 +0000 (+0200) Subject: Add generic GtkTreeModel reference counting unit tests X-Git-Url: http://pileus.org/git/?a=commitdiff_plain;h=bda09159c378c87008beee624c2d64f06a852b88;p=~andy%2Fgtk Add generic GtkTreeModel reference counting unit tests --- diff --git a/gtk/tests/Makefile.am b/gtk/tests/Makefile.am index d1c87a7a1..e28898ed2 100644 --- a/gtk/tests/Makefile.am +++ b/gtk/tests/Makefile.am @@ -28,7 +28,7 @@ testing_SOURCES = testing.c testing_LDADD = $(progs_ldadd) TEST_PROGS += treemodel -treemodel_SOURCES = treemodel.c liststore.c treestore.c filtermodel.c sortmodel.c +treemodel_SOURCES = treemodel.c liststore.c treestore.c filtermodel.c sortmodel.c modelrefcount.c gtktreemodelrefcount.c treemodel_LDADD = $(progs_ldadd) TEST_PROGS += treeview diff --git a/gtk/tests/modelrefcount.c b/gtk/tests/modelrefcount.c new file mode 100644 index 000000000..c94d60f7e --- /dev/null +++ b/gtk/tests/modelrefcount.c @@ -0,0 +1,965 @@ +/* GtkTreeModel ref counting tests + * Copyright (C) 2011 Kristian Rietveld + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "gtktreemodelrefcount.h" +#include "treemodel.h" + +/* A couple of helpers for the tests */ + +static inline void +assert_entire_model_unreferenced (GtkTreeModelRefCount *ref_model) +{ + g_assert_cmpint (gtk_tree_model_ref_count_check_level (ref_model, NULL, 0, + TRUE), + ==, TRUE); +} + +static inline void +assert_root_level_unreferenced (GtkTreeModelRefCount *ref_model) +{ + g_assert_cmpint (gtk_tree_model_ref_count_check_level (ref_model, NULL, 0, + FALSE), + ==, TRUE); +} + +static inline void +assert_level_unreferenced (GtkTreeModelRefCount *ref_model, + GtkTreeIter *iter) +{ + g_assert_cmpint (gtk_tree_model_ref_count_check_level (ref_model, iter, + 0, FALSE), + ==, TRUE); +} + +static inline void +assert_entire_model_referenced (GtkTreeModelRefCount *ref_model, + gint ref_count) +{ + g_assert_cmpint (gtk_tree_model_ref_count_check_level (ref_model, NULL, + ref_count, TRUE), + ==, TRUE); +} + + static inline void +assert_not_entire_model_referenced (GtkTreeModelRefCount *ref_model, + gint ref_count) +{ + g_assert_cmpint (gtk_tree_model_ref_count_check_level (ref_model, NULL, + ref_count, TRUE), + ==, FALSE); +} + +static inline void +assert_root_level_referenced (GtkTreeModelRefCount *ref_model, + gint ref_count) +{ + g_assert_cmpint (gtk_tree_model_ref_count_check_level (ref_model, NULL, + ref_count, FALSE), + ==, TRUE); +} + +static inline void +assert_level_referenced (GtkTreeModelRefCount *ref_model, + gint ref_count, + GtkTreeIter *iter) +{ + g_assert_cmpint (gtk_tree_model_ref_count_check_level (ref_model, iter, + ref_count, FALSE), + ==, TRUE); +} + +static inline void +assert_node_ref_count (GtkTreeModelRefCount *ref_model, + GtkTreeIter *iter, + gint ref_count) +{ + g_assert_cmpint (gtk_tree_model_ref_count_check_node (ref_model, iter, + ref_count), + ==, TRUE); +} + +/* And the tests themselves */ + +static void +test_list_no_reference (void) +{ + GtkTreeIter iter; + GtkTreeModel *model; + GtkTreeModelRefCount *ref_model; + + model = gtk_tree_model_ref_count_new (); + ref_model = GTK_TREE_MODEL_REF_COUNT (model); + + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + + assert_root_level_unreferenced (ref_model); + + g_object_unref (ref_model); +} + +static void +test_list_reference_during_creation (void) +{ + GtkTreeIter iter; + GtkTreeModel *model; + GtkTreeModelRefCount *ref_model; + GtkWidget *tree_view; + + model = gtk_tree_model_ref_count_new (); + ref_model = GTK_TREE_MODEL_REF_COUNT (model); + tree_view = gtk_tree_view_new_with_model (model); + + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + + assert_root_level_referenced (ref_model, 1); + + gtk_widget_destroy (tree_view); + + assert_root_level_unreferenced (ref_model); + + g_object_unref (ref_model); +} + +static void +test_list_reference_after_creation (void) +{ + GtkTreeIter iter; + GtkTreeModel *model; + GtkTreeModelRefCount *ref_model; + GtkWidget *tree_view; + + model = gtk_tree_model_ref_count_new (); + ref_model = GTK_TREE_MODEL_REF_COUNT (model); + + assert_root_level_unreferenced (ref_model); + + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + + tree_view = gtk_tree_view_new_with_model (model); + + assert_root_level_referenced (ref_model, 1); + + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + + assert_root_level_referenced (ref_model, 1); + + gtk_widget_destroy (tree_view); + + assert_root_level_unreferenced (ref_model); + + g_object_unref (ref_model); +} + + +static void +test_tree_no_reference (void) +{ + GtkTreeIter iter, child; + GtkTreeModel *model; + GtkTreeModelRefCount *ref_model; + + model = gtk_tree_model_ref_count_new (); + ref_model = GTK_TREE_MODEL_REF_COUNT (model); + + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + + assert_entire_model_unreferenced (ref_model); + + g_object_unref (ref_model); +} + +static void +test_tree_reference_during_creation (void) +{ + GtkTreeIter iter, child; + GtkTreeModel *model; + GtkTreeModelRefCount *ref_model; + GtkWidget *tree_view; + + model = gtk_tree_model_ref_count_new (); + ref_model = GTK_TREE_MODEL_REF_COUNT (model); + tree_view = gtk_tree_view_new_with_model (model); + + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + + assert_root_level_referenced (ref_model, 1); + assert_not_entire_model_referenced (ref_model, 1); + assert_level_unreferenced (ref_model, &child); + + gtk_widget_destroy (tree_view); + + assert_entire_model_unreferenced (ref_model); + + g_object_unref (ref_model); +} + +static void +test_tree_reference_after_creation (void) +{ + GtkTreeIter iter, child; + GtkTreeModel *model; + GtkTreeModelRefCount *ref_model; + GtkWidget *tree_view; + + model = gtk_tree_model_ref_count_new (); + ref_model = GTK_TREE_MODEL_REF_COUNT (model); + + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + + assert_entire_model_unreferenced (ref_model); + + tree_view = gtk_tree_view_new_with_model (model); + + assert_root_level_referenced (ref_model, 1); + assert_not_entire_model_referenced (ref_model, 1); + assert_level_unreferenced (ref_model, &child); + + gtk_widget_destroy (tree_view); + + assert_entire_model_unreferenced (ref_model); + + g_object_unref (ref_model); +} + +static void +test_tree_reference_expand_all (void) +{ + GtkTreeIter iter, child; + GtkTreeModel *model; + GtkTreeModelRefCount *ref_model; + GtkWidget *tree_view; + + model = gtk_tree_model_ref_count_new (); + ref_model = GTK_TREE_MODEL_REF_COUNT (model); + + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + + assert_entire_model_unreferenced (ref_model); + + tree_view = gtk_tree_view_new_with_model (model); + + assert_root_level_referenced (ref_model, 1); + assert_not_entire_model_referenced (ref_model, 1); + assert_level_unreferenced (ref_model, &child); + + gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view)); + + assert_entire_model_referenced (ref_model, 1); + + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + + assert_root_level_referenced (ref_model, 1); + assert_not_entire_model_referenced (ref_model, 1); + assert_level_unreferenced (ref_model, &child); + + gtk_widget_destroy (tree_view); + + assert_entire_model_unreferenced (ref_model); + + g_object_unref (ref_model); +} + +static void +test_tree_reference_collapse_all (void) +{ + GtkTreeIter iter, child; + GtkTreeModel *model; + GtkTreeModelRefCount *ref_model; + GtkWidget *tree_view; + + model = gtk_tree_model_ref_count_new (); + ref_model = GTK_TREE_MODEL_REF_COUNT (model); + + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &iter); + + assert_entire_model_unreferenced (ref_model); + + tree_view = gtk_tree_view_new_with_model (model); + gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view)); + + assert_entire_model_referenced (ref_model, 1); + + gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view)); + + assert_root_level_referenced (ref_model, 1); + assert_not_entire_model_referenced (ref_model, 1); + assert_level_unreferenced (ref_model, &child); + + gtk_widget_destroy (tree_view); + + assert_entire_model_unreferenced (ref_model); + + g_object_unref (ref_model); +} + +static void +test_tree_reference_expand_collapse (void) +{ + GtkTreeIter parent1, parent2, child; + GtkTreePath *path1, *path2; + GtkTreeModel *model; + GtkTreeModelRefCount *ref_model; + GtkWidget *tree_view; + + model = gtk_tree_model_ref_count_new (); + ref_model = GTK_TREE_MODEL_REF_COUNT (model); + tree_view = gtk_tree_view_new_with_model (model); + + gtk_tree_store_append (GTK_TREE_STORE (model), &parent1, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &parent1); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &parent1); + gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &parent2, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &parent2); + gtk_tree_store_append (GTK_TREE_STORE (model), &child, &parent2); + + path1 = gtk_tree_model_get_path (model, &parent1); + path2 = gtk_tree_model_get_path (model, &parent2); + + assert_level_unreferenced (ref_model, &parent1); + assert_level_unreferenced (ref_model, &parent2); + + gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path1, FALSE); + + assert_level_referenced (ref_model, 1, &parent1); + assert_level_unreferenced (ref_model, &parent2); + + gtk_tree_view_collapse_row (GTK_TREE_VIEW (tree_view), path1); + + assert_level_unreferenced (ref_model, &parent1); + assert_level_unreferenced (ref_model, &parent2); + + gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path2, FALSE); + + assert_level_unreferenced (ref_model, &parent1); + assert_level_referenced (ref_model, 1, &parent2); + + gtk_tree_view_collapse_row (GTK_TREE_VIEW (tree_view), path2); + + assert_level_unreferenced (ref_model, &parent1); + assert_level_unreferenced (ref_model, &parent2); + + gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path2, FALSE); + + assert_level_unreferenced (ref_model, &parent1); + assert_level_referenced (ref_model, 1, &parent2); + + gtk_tree_view_expand_row (GTK_TREE_VIEW (tree_view), path1, FALSE); + + assert_level_referenced (ref_model, 1, &parent1); + assert_level_referenced (ref_model, 1, &parent2); + + gtk_tree_path_free (path1); + gtk_tree_path_free (path2); + + gtk_widget_destroy (tree_view); + g_object_unref (ref_model); +} + +static void +test_row_reference_list (void) +{ + GtkTreeIter iter0, iter1, iter2; + GtkTreePath *path; + GtkTreeModel *model; + GtkTreeModelRefCount *ref_model; + GtkTreeRowReference *row_ref; + GtkWidget *tree_view; + + model = gtk_tree_model_ref_count_new (); + ref_model = GTK_TREE_MODEL_REF_COUNT (model); + + gtk_tree_store_append (GTK_TREE_STORE (model), &iter0, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter1, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter2, NULL); + + assert_root_level_unreferenced (ref_model); + + /* create and remove a row ref and check reference counts */ + path = gtk_tree_path_new_from_indices (1, -1); + row_ref = gtk_tree_row_reference_new (model, path); + + assert_node_ref_count (ref_model, &iter0, 0); + assert_node_ref_count (ref_model, &iter1, 1); + assert_node_ref_count (ref_model, &iter2, 0); + + gtk_tree_row_reference_free (row_ref); + + assert_root_level_unreferenced (ref_model); + + /* the same, but then also with a tree view monitoring the model */ + tree_view = gtk_tree_view_new_with_model (model); + + assert_root_level_referenced (ref_model, 1); + + row_ref = gtk_tree_row_reference_new (model, path); + + assert_node_ref_count (ref_model, &iter0, 1); + assert_node_ref_count (ref_model, &iter1, 2); + assert_node_ref_count (ref_model, &iter2, 1); + + gtk_widget_destroy (tree_view); + + assert_node_ref_count (ref_model, &iter0, 0); + assert_node_ref_count (ref_model, &iter1, 1); + assert_node_ref_count (ref_model, &iter2, 0); + + gtk_tree_row_reference_free (row_ref); + + assert_root_level_unreferenced (ref_model); + + gtk_tree_path_free (path); + + g_object_unref (ref_model); +} + +static void +test_row_reference_list_remove (void) +{ + GtkTreeIter iter0, iter1, iter2; + GtkTreePath *path; + GtkTreeModel *model; + GtkTreeModelRefCount *ref_model; + GtkTreeRowReference *row_ref; + + model = gtk_tree_model_ref_count_new (); + ref_model = GTK_TREE_MODEL_REF_COUNT (model); + + gtk_tree_store_append (GTK_TREE_STORE (model), &iter0, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter1, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter2, NULL); + + assert_root_level_unreferenced (ref_model); + + /* test creating the row reference and then removing the node */ + path = gtk_tree_path_new_from_indices (1, -1); + row_ref = gtk_tree_row_reference_new (model, path); + + assert_node_ref_count (ref_model, &iter0, 0); + assert_node_ref_count (ref_model, &iter1, 1); + assert_node_ref_count (ref_model, &iter2, 0); + + gtk_tree_store_remove (GTK_TREE_STORE (model), &iter1); + + assert_root_level_unreferenced (ref_model); + + gtk_tree_row_reference_free (row_ref); + + assert_root_level_unreferenced (ref_model); + + /* test creating a row ref, removing another node and then removing + * the row ref node. + */ + row_ref = gtk_tree_row_reference_new (model, path); + + assert_node_ref_count (ref_model, &iter0, 0); + assert_node_ref_count (ref_model, &iter2, 1); + + gtk_tree_store_remove (GTK_TREE_STORE (model), &iter0); + + assert_root_level_referenced (ref_model, 1); + + gtk_tree_store_remove (GTK_TREE_STORE (model), &iter2); + + g_assert (!gtk_tree_model_get_iter_first (model, &iter0)); + + gtk_tree_row_reference_free (row_ref); + + gtk_tree_path_free (path); + + g_object_unref (ref_model); +} + +static void +test_row_reference_tree (void) +{ + GtkTreeIter iter0, iter1, iter2; + GtkTreeIter child0, child1, child2; + GtkTreeIter grandchild0, grandchild1, grandchild2; + GtkTreePath *path; + GtkTreeModel *model; + GtkTreeModelRefCount *ref_model; + GtkTreeRowReference *row_ref, *row_ref1; + GtkWidget *tree_view; + + model = gtk_tree_model_ref_count_new (); + ref_model = GTK_TREE_MODEL_REF_COUNT (model); + + gtk_tree_store_append (GTK_TREE_STORE (model), &iter0, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child0, &iter0); + gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild0, &child0); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter1, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child1, &iter1); + gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild1, &child1); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter2, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child2, &iter2); + gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild2, &child2); + + assert_entire_model_unreferenced (ref_model); + + /* create and remove a row ref and check reference counts */ + path = gtk_tree_path_new_from_indices (1, 0, 0, -1); + row_ref = gtk_tree_row_reference_new (model, path); + gtk_tree_path_free (path); + + assert_node_ref_count (ref_model, &iter0, 0); + assert_node_ref_count (ref_model, &child0, 0); + assert_node_ref_count (ref_model, &grandchild0, 0); + assert_node_ref_count (ref_model, &iter1, 1); + assert_node_ref_count (ref_model, &child1, 1); + assert_node_ref_count (ref_model, &grandchild1, 1); + assert_node_ref_count (ref_model, &iter2, 0); + assert_node_ref_count (ref_model, &child2, 0); + assert_node_ref_count (ref_model, &grandchild2, 0); + + gtk_tree_row_reference_free (row_ref); + + assert_entire_model_unreferenced (ref_model); + + /* again, with path 1:1 */ + path = gtk_tree_path_new_from_indices (1, 0, -1); + row_ref = gtk_tree_row_reference_new (model, path); + gtk_tree_path_free (path); + + assert_node_ref_count (ref_model, &iter0, 0); + assert_node_ref_count (ref_model, &child0, 0); + assert_node_ref_count (ref_model, &grandchild0, 0); + assert_node_ref_count (ref_model, &iter1, 1); + assert_node_ref_count (ref_model, &child1, 1); + assert_node_ref_count (ref_model, &grandchild1, 0); + assert_node_ref_count (ref_model, &iter2, 0); + assert_node_ref_count (ref_model, &child2, 0); + assert_node_ref_count (ref_model, &grandchild2, 0); + + gtk_tree_row_reference_free (row_ref); + + assert_entire_model_unreferenced (ref_model); + + /* both row refs existent at once and also with a tree view monitoring + * the model + */ + tree_view = gtk_tree_view_new_with_model (model); + + assert_root_level_referenced (ref_model, 1); + + path = gtk_tree_path_new_from_indices (1, 0, 0, -1); + row_ref = gtk_tree_row_reference_new (model, path); + gtk_tree_path_free (path); + + assert_node_ref_count (ref_model, &iter0, 1); + assert_node_ref_count (ref_model, &child0, 0); + assert_node_ref_count (ref_model, &grandchild0, 0); + assert_node_ref_count (ref_model, &iter1, 2); + assert_node_ref_count (ref_model, &child1, 1); + assert_node_ref_count (ref_model, &grandchild1, 1); + assert_node_ref_count (ref_model, &iter2, 1); + assert_node_ref_count (ref_model, &child2, 0); + assert_node_ref_count (ref_model, &grandchild2, 0); + + path = gtk_tree_path_new_from_indices (1, 0, -1); + row_ref1 = gtk_tree_row_reference_new (model, path); + gtk_tree_path_free (path); + + assert_node_ref_count (ref_model, &iter0, 1); + assert_node_ref_count (ref_model, &child0, 0); + assert_node_ref_count (ref_model, &grandchild0, 0); + assert_node_ref_count (ref_model, &iter1, 3); + assert_node_ref_count (ref_model, &child1, 2); + assert_node_ref_count (ref_model, &grandchild1, 1); + assert_node_ref_count (ref_model, &iter2, 1); + assert_node_ref_count (ref_model, &child2, 0); + assert_node_ref_count (ref_model, &grandchild2, 0); + + gtk_tree_row_reference_free (row_ref); + + assert_node_ref_count (ref_model, &iter0, 1); + assert_node_ref_count (ref_model, &child0, 0); + assert_node_ref_count (ref_model, &grandchild0, 0); + assert_node_ref_count (ref_model, &iter1, 2); + assert_node_ref_count (ref_model, &child1, 1); + assert_node_ref_count (ref_model, &grandchild1, 0); + assert_node_ref_count (ref_model, &iter2, 1); + assert_node_ref_count (ref_model, &child2, 0); + assert_node_ref_count (ref_model, &grandchild2, 0); + + gtk_widget_destroy (tree_view); + + assert_node_ref_count (ref_model, &iter0, 0); + assert_node_ref_count (ref_model, &child0, 0); + assert_node_ref_count (ref_model, &grandchild0, 0); + assert_node_ref_count (ref_model, &iter1, 1); + assert_node_ref_count (ref_model, &child1, 1); + assert_node_ref_count (ref_model, &grandchild1, 0); + assert_node_ref_count (ref_model, &iter2, 0); + assert_node_ref_count (ref_model, &child2, 0); + assert_node_ref_count (ref_model, &grandchild2, 0); + + gtk_tree_row_reference_free (row_ref1); + + assert_root_level_unreferenced (ref_model); + + g_object_unref (ref_model); +} + +static void +test_row_reference_tree_remove (void) +{ + GtkTreeIter iter0, iter1, iter2; + GtkTreeIter child0, child1, child2; + GtkTreeIter grandchild0, grandchild1, grandchild2; + GtkTreePath *path; + GtkTreeModel *model; + GtkTreeModelRefCount *ref_model; + GtkTreeRowReference *row_ref, *row_ref1, *row_ref2; + + model = gtk_tree_model_ref_count_new (); + ref_model = GTK_TREE_MODEL_REF_COUNT (model); + + gtk_tree_store_append (GTK_TREE_STORE (model), &iter0, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child0, &iter0); + gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild0, &child0); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter1, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child1, &iter1); + gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild1, &child1); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter2, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child2, &iter2); + gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild2, &child2); + + assert_entire_model_unreferenced (ref_model); + + path = gtk_tree_path_new_from_indices (1, 0, 0, -1); + row_ref = gtk_tree_row_reference_new (model, path); + gtk_tree_path_free (path); + + path = gtk_tree_path_new_from_indices (2, 0, -1); + row_ref1 = gtk_tree_row_reference_new (model, path); + gtk_tree_path_free (path); + + path = gtk_tree_path_new_from_indices (2, -1); + row_ref2 = gtk_tree_row_reference_new (model, path); + gtk_tree_path_free (path); + + assert_node_ref_count (ref_model, &iter0, 0); + assert_node_ref_count (ref_model, &child0, 0); + assert_node_ref_count (ref_model, &grandchild0, 0); + assert_node_ref_count (ref_model, &iter1, 1); + assert_node_ref_count (ref_model, &child1, 1); + assert_node_ref_count (ref_model, &grandchild1, 1); + assert_node_ref_count (ref_model, &iter2, 2); + assert_node_ref_count (ref_model, &child2, 1); + assert_node_ref_count (ref_model, &grandchild2, 0); + + gtk_tree_store_remove (GTK_TREE_STORE (model), &grandchild1); + + assert_node_ref_count (ref_model, &iter0, 0); + assert_node_ref_count (ref_model, &child0, 0); + assert_node_ref_count (ref_model, &grandchild0, 0); + assert_node_ref_count (ref_model, &iter1, 0); + assert_node_ref_count (ref_model, &child1, 0); + assert_node_ref_count (ref_model, &iter2, 2); + assert_node_ref_count (ref_model, &child2, 1); + assert_node_ref_count (ref_model, &grandchild2, 0); + + gtk_tree_store_remove (GTK_TREE_STORE (model), &child2); + + assert_node_ref_count (ref_model, &iter0, 0); + assert_node_ref_count (ref_model, &child0, 0); + assert_node_ref_count (ref_model, &grandchild0, 0); + assert_node_ref_count (ref_model, &iter1, 0); + assert_node_ref_count (ref_model, &child1, 0); + assert_node_ref_count (ref_model, &iter2, 1); + + gtk_tree_store_remove (GTK_TREE_STORE (model), &iter2); + + assert_entire_model_unreferenced (ref_model); + + gtk_tree_row_reference_free (row_ref); + gtk_tree_row_reference_free (row_ref1); + gtk_tree_row_reference_free (row_ref2); + + g_object_unref (ref_model); +} + +static void +test_row_reference_tree_remove_ancestor (void) +{ + GtkTreeIter iter0, iter1, iter2; + GtkTreeIter child0, child1, child2; + GtkTreeIter grandchild0, grandchild1, grandchild2; + GtkTreePath *path; + GtkTreeModel *model; + GtkTreeModelRefCount *ref_model; + GtkTreeRowReference *row_ref, *row_ref1; + + model = gtk_tree_model_ref_count_new (); + ref_model = GTK_TREE_MODEL_REF_COUNT (model); + + gtk_tree_store_append (GTK_TREE_STORE (model), &iter0, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child0, &iter0); + gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild0, &child0); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter1, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child1, &iter1); + gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild1, &child1); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter2, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child2, &iter2); + gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild2, &child2); + + assert_entire_model_unreferenced (ref_model); + + path = gtk_tree_path_new_from_indices (1, 0, 0, -1); + row_ref = gtk_tree_row_reference_new (model, path); + gtk_tree_path_free (path); + + path = gtk_tree_path_new_from_indices (2, 0, -1); + row_ref1 = gtk_tree_row_reference_new (model, path); + gtk_tree_path_free (path); + + assert_node_ref_count (ref_model, &iter0, 0); + assert_node_ref_count (ref_model, &child0, 0); + assert_node_ref_count (ref_model, &grandchild0, 0); + assert_node_ref_count (ref_model, &iter1, 1); + assert_node_ref_count (ref_model, &child1, 1); + assert_node_ref_count (ref_model, &grandchild1, 1); + assert_node_ref_count (ref_model, &iter2, 1); + assert_node_ref_count (ref_model, &child2, 1); + assert_node_ref_count (ref_model, &grandchild2, 0); + + gtk_tree_store_remove (GTK_TREE_STORE (model), &child1); + + assert_node_ref_count (ref_model, &iter0, 0); + assert_node_ref_count (ref_model, &child0, 0); + assert_node_ref_count (ref_model, &grandchild0, 0); + assert_node_ref_count (ref_model, &iter1, 0); + assert_node_ref_count (ref_model, &iter2, 1); + assert_node_ref_count (ref_model, &child2, 1); + assert_node_ref_count (ref_model, &grandchild2, 0); + + gtk_tree_store_remove (GTK_TREE_STORE (model), &iter2); + + assert_entire_model_unreferenced (ref_model); + + gtk_tree_row_reference_free (row_ref); + gtk_tree_row_reference_free (row_ref1); + + g_object_unref (ref_model); +} + +static void +test_row_reference_tree_expand (void) +{ + GtkTreeIter iter0, iter1, iter2; + GtkTreeIter child0, child1, child2; + GtkTreeIter grandchild0, grandchild1, grandchild2; + GtkTreePath *path; + GtkTreeModel *model; + GtkTreeModelRefCount *ref_model; + GtkTreeRowReference *row_ref, *row_ref1, *row_ref2; + GtkWidget *tree_view; + + model = gtk_tree_model_ref_count_new (); + ref_model = GTK_TREE_MODEL_REF_COUNT (model); + tree_view = gtk_tree_view_new_with_model (model); + + gtk_tree_store_append (GTK_TREE_STORE (model), &iter0, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child0, &iter0); + gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild0, &child0); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter1, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child1, &iter1); + gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild1, &child1); + gtk_tree_store_append (GTK_TREE_STORE (model), &iter2, NULL); + gtk_tree_store_append (GTK_TREE_STORE (model), &child2, &iter2); + gtk_tree_store_append (GTK_TREE_STORE (model), &grandchild2, &child2); + + assert_root_level_referenced (ref_model, 1); + + gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view)); + + assert_entire_model_referenced (ref_model, 1); + + path = gtk_tree_path_new_from_indices (1, 0, 0, -1); + row_ref = gtk_tree_row_reference_new (model, path); + gtk_tree_path_free (path); + + path = gtk_tree_path_new_from_indices (2, 0, -1); + row_ref1 = gtk_tree_row_reference_new (model, path); + gtk_tree_path_free (path); + + path = gtk_tree_path_new_from_indices (2, -1); + row_ref2 = gtk_tree_row_reference_new (model, path); + gtk_tree_path_free (path); + + assert_node_ref_count (ref_model, &iter0, 1); + assert_node_ref_count (ref_model, &child0, 1); + assert_node_ref_count (ref_model, &grandchild0, 1); + assert_node_ref_count (ref_model, &iter1, 2); + assert_node_ref_count (ref_model, &child1, 2); + assert_node_ref_count (ref_model, &grandchild1, 2); + assert_node_ref_count (ref_model, &iter2, 3); + assert_node_ref_count (ref_model, &child2, 2); + assert_node_ref_count (ref_model, &grandchild2, 1); + + gtk_tree_store_remove (GTK_TREE_STORE (model), &grandchild1); + + assert_node_ref_count (ref_model, &iter0, 1); + assert_node_ref_count (ref_model, &child0, 1); + assert_node_ref_count (ref_model, &grandchild0, 1); + assert_node_ref_count (ref_model, &iter1, 1); + assert_node_ref_count (ref_model, &child1, 1); + assert_node_ref_count (ref_model, &iter2, 3); + assert_node_ref_count (ref_model, &child2, 2); + assert_node_ref_count (ref_model, &grandchild2, 1); + + gtk_tree_store_remove (GTK_TREE_STORE (model), &child2); + + assert_node_ref_count (ref_model, &iter0, 1); + assert_node_ref_count (ref_model, &child0, 1); + assert_node_ref_count (ref_model, &grandchild0, 1); + assert_node_ref_count (ref_model, &iter1, 1); + assert_node_ref_count (ref_model, &child1, 1); + assert_node_ref_count (ref_model, &iter2, 2); + + gtk_tree_view_collapse_all (GTK_TREE_VIEW (tree_view)); + + assert_node_ref_count (ref_model, &iter0, 1); + assert_node_ref_count (ref_model, &child0, 0); + assert_node_ref_count (ref_model, &grandchild0, 0); + assert_node_ref_count (ref_model, &iter1, 1); + assert_node_ref_count (ref_model, &child1, 0); + assert_node_ref_count (ref_model, &iter2, 2); + + gtk_tree_store_remove (GTK_TREE_STORE (model), &iter2); + + assert_node_ref_count (ref_model, &iter0, 1); + assert_node_ref_count (ref_model, &child0, 0); + assert_node_ref_count (ref_model, &grandchild0, 0); + assert_node_ref_count (ref_model, &iter1, 1); + assert_node_ref_count (ref_model, &child1, 0); + + gtk_tree_row_reference_free (row_ref); + gtk_tree_row_reference_free (row_ref1); + gtk_tree_row_reference_free (row_ref2); + + gtk_widget_destroy (tree_view); + g_object_unref (ref_model); +} + +void +register_model_ref_count_tests (void) +{ + /* lists (though based on GtkTreeStore) */ + g_test_add_func ("/TreeModel/ref-count/list/no-reference", + test_list_no_reference); + g_test_add_func ("/TreeModel/ref-count/list/reference-during-creation", + test_list_reference_during_creation); + g_test_add_func ("/TreeModel/ref-count/list/reference-after-creation", + test_list_reference_after_creation); + + /* trees */ + g_test_add_func ("/TreeModel/ref-count/tree/no-reference", + test_tree_no_reference); + g_test_add_func ("/TreeModel/ref-count/tree/reference-during-creation", + test_tree_reference_during_creation); + g_test_add_func ("/TreeModel/ref-count/tree/reference-after-creation", + test_tree_reference_after_creation); + g_test_add_func ("/TreeModel/ref-count/tree/expand-all", + test_tree_reference_expand_all); + g_test_add_func ("/TreeModel/ref-count/tree/collapse-all", + test_tree_reference_collapse_all); + g_test_add_func ("/TreeModel/ref-count/tree/expand-collapse", + test_tree_reference_expand_collapse); + + /* row references */ + g_test_add_func ("/TreeModel/ref-count/row-reference/list", + test_row_reference_list); + g_test_add_func ("/TreeModel/ref-count/row-reference/list-remove", + test_row_reference_list_remove); + g_test_add_func ("/TreeModel/ref-count/row-reference/tree", + test_row_reference_tree); + g_test_add_func ("/TreeModel/ref-count/row-reference/tree-remove", + test_row_reference_tree_remove); + g_test_add_func ("/TreeModel/ref-count/row-reference/tree-remove-ancestor", + test_row_reference_tree_remove_ancestor); + g_test_add_func ("/TreeModel/ref-count/row-reference/tree-expand", + test_row_reference_tree_expand); +} diff --git a/gtk/tests/treemodel.c b/gtk/tests/treemodel.c index 7791403ef..d91471fd0 100644 --- a/gtk/tests/treemodel.c +++ b/gtk/tests/treemodel.c @@ -33,6 +33,7 @@ main (int argc, register_tree_store_tests (); register_sort_model_tests (); register_filter_model_tests (); + register_model_ref_count_tests (); return g_test_run (); } diff --git a/gtk/tests/treemodel.h b/gtk/tests/treemodel.h index 4a46ebabb..d63afd7ef 100644 --- a/gtk/tests/treemodel.h +++ b/gtk/tests/treemodel.h @@ -21,3 +21,4 @@ void register_list_store_tests (); void register_tree_store_tests (); void register_sort_model_tests (); void register_filter_model_tests (); +void register_model_ref_count_tests ();