summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjell Ahlstedt <kjell.ahlstedt@bredband.net>2016-04-27 09:27:40 +0200
committerKjell Ahlstedt <kjell.ahlstedt@bredband.net>2016-04-27 09:27:40 +0200
commit60bc4839dd957cd3ce4688cab4a4d189233b7ba8 (patch)
treef1ad27d14bedcfd1947170fb1034e08acdda9d85
parent84e597dd50d513ee24235bdfe0ffc79d1a26ea67 (diff)
downloadglibmm-60bc4839dd957cd3ce4688cab4a4d189233b7ba8.tar.gz
Add tests/giomm_listmodel
Similar to glib/gio/tests/glistmodel.c Bug #755307
-rw-r--r--tests/Makefile.am4
-rw-r--r--tests/giomm_listmodel/main.cc349
2 files changed, 353 insertions, 0 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b2dddc32..2cb35abb 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -24,6 +24,7 @@ check_PROGRAMS = \
giomm_simple/test \
giomm_asyncresult_sourceobject/test \
giomm_tls_client/test \
+ giomm_listmodel/test \
glibmm_btree/test \
glibmm_base64/test \
glibmm_date/test \
@@ -83,6 +84,9 @@ giomm_asyncresult_sourceobject_test_LDADD = $(giomm_ldadd)
giomm_tls_client_test_SOURCES = giomm_tls_client/main.cc
giomm_tls_client_test_LDADD = $(giomm_ldadd)
+giomm_listmodel_test_SOURCES = giomm_listmodel/main.cc
+giomm_listmodel_test_LDADD = $(giomm_ldadd)
+
glibmm_base64_test_SOURCES = glibmm_base64/main.cc
glibmm_btree_test_SOURCES = glibmm_btree/main.cc
glibmm_buildfilename_test_SOURCES = glibmm_buildfilename/main.cc
diff --git a/tests/giomm_listmodel/main.cc b/tests/giomm_listmodel/main.cc
new file mode 100644
index 00000000..f40a9430
--- /dev/null
+++ b/tests/giomm_listmodel/main.cc
@@ -0,0 +1,349 @@
+/* Copyright (C) 2016 The giomm Development Team
+ *
+ * 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.1 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, see <http://www.gnu.org/licenses/>.
+ */
+
+// This test is similar to glib/gio/tests/glistmodel.c.
+
+#include <giomm.h>
+#include <cstdlib>
+#include <iostream>
+
+namespace
+{
+int result = EXIT_SUCCESS;
+
+void check_store_boundaries_n_items(int icall,
+ const Glib::RefPtr<const Gio::ListStoreBase>& store, unsigned int expected)
+{
+ if (store->get_n_items() != expected)
+ {
+ result = EXIT_FAILURE;
+ std::cerr << "test_store_boundaries(), " << icall << ": get_n_items()="
+ << store->get_n_items() << std::endl;
+ }
+}
+
+void test_store_boundaries()
+{
+ auto store = Gio::ListStore<Gio::MenuItem>::create();
+ auto item = Gio::MenuItem::create("", "");
+ auto weakref_item = Glib::WeakRef<Gio::MenuItem>(item);
+
+ // Remove an item from an empty list.
+ store->remove(0);
+ check_store_boundaries_n_items(1, store, 0);
+
+ // Don't allow inserting an item past the end ...
+ store->insert(1, item);
+ check_store_boundaries_n_items(2, store, 0);
+
+ // ... except exactly at the end.
+ store->insert(0, item);
+ check_store_boundaries_n_items(3, store, 1);
+
+ // Remove a non-existing item at exactly the end of the list.
+ store->remove(1);
+ check_store_boundaries_n_items(4, store, 1);
+
+ // Remove an existing item.
+ store->remove(0);
+ check_store_boundaries_n_items(5, store, 0);
+
+ // Splice beyond the end of the list.
+ store->splice(1, 0, std::vector<Glib::RefPtr<Gio::MenuItem>>());
+ check_store_boundaries_n_items(6, store, 0);
+
+ // Remove items from an empty list.
+ store->splice(0, 1, std::vector<Glib::RefPtr<Gio::MenuItem>>());
+ check_store_boundaries_n_items(7, store, 0);
+
+ // Append an item, remove it, and insert it by splicing.
+ store->append(item);
+ {
+ std::vector<Glib::RefPtr<Gio::MenuItem>> v;
+ v.push_back(item);
+ store->splice(0, 1, v);
+ }
+ check_store_boundaries_n_items(8, store, 1);
+
+ // Remove more items than exist.
+ store->splice(0, 5, std::vector<Glib::RefPtr<Gio::MenuItem>>());
+ check_store_boundaries_n_items(9, store, 1);
+
+ store.reset();
+ item.reset();
+ if (weakref_item)
+ {
+ result = EXIT_FAILURE;
+ std::cerr << "test_store_boundaries(), 10: weakref_item is not null" << std::endl;
+ }
+} // end test_store_boundaries()
+
+void check_store_refcounts_n_items(int icall,
+ const Glib::RefPtr<const Gio::ListStoreBase>& store, unsigned int expected)
+{
+ if (store->get_n_items() != expected)
+ {
+ result = EXIT_FAILURE;
+ std::cerr << "test_store_refcounts(), " << icall << ": get_n_items()="
+ << store->get_n_items() << std::endl;
+ }
+ if (store->get_object(expected))
+ {
+ result = EXIT_FAILURE;
+ std::cerr << "test_store_refcounts(), " << icall << ": get_object("
+ << expected << ") is not null" << std::endl;
+ }
+}
+
+void test_store_refcounts()
+{
+ auto store = Gio::ListStore<Gio::MenuItem>::create();
+
+ check_store_refcounts_n_items(1, store, 0);
+
+ const std::size_t n_items = 10;
+ std::vector<Glib::RefPtr<Gio::MenuItem>> items;
+ std::vector<Glib::WeakRef<Gio::MenuItem>> weakref_items;
+ for (std::size_t i = 0; i < n_items; ++i)
+ {
+ items.push_back(Gio::MenuItem::create("", ""));
+ weakref_items.push_back(Glib::WeakRef<Gio::MenuItem>(items[i]));
+ store->append(items[i]);
+ }
+ check_store_refcounts_n_items(2, store, n_items);
+
+ if (store->get_item(3).operator->() != items[3].operator->())
+ {
+ result = EXIT_FAILURE;
+ std::cerr << "test_store_refcounts(), 3: get_item(3) != items[3]" << std::endl;
+ }
+
+ for (std::size_t i = 0; i < n_items; ++i)
+ {
+ items[i].reset();
+ if (!weakref_items[i])
+ {
+ result = EXIT_FAILURE;
+ std::cerr << "test_store_refcounts(), 4: weakref_items[" << i << "] is null" << std::endl;
+ }
+ }
+
+ store->remove(4);
+ if (weakref_items[4])
+ {
+ result = EXIT_FAILURE;
+ std::cerr << "test_store_refcounts(), 5: weakref_items[4] is not null" << std::endl;
+ }
+ check_store_refcounts_n_items(6, store, n_items-1);
+
+ store.reset();
+ for (std::size_t i = 0; i < n_items; ++i)
+ {
+ if (weakref_items[i])
+ {
+ result = EXIT_FAILURE;
+ std::cerr << "test_store_refcounts(), 7: weakref_items[" << i << "] is not null" << std::endl;
+ }
+ }
+} // end test_store_refcounts()
+
+// All returned numbers are different as long as the number of calls are < 15000.
+gint32 get_next_number()
+{
+ static gint32 n_calls = 0;
+
+ ++n_calls;
+ const gint32 n1 = n_calls;
+ const gint32 n2 = 30000 - n_calls;
+ gint32 res = (n2 << 16) | n1;
+ if (n_calls & 1)
+ res = (n1 << 16) | n2;
+
+ return res;
+}
+
+int compare_items1(const Glib::RefPtr<const Glib::Object>& a,
+ const Glib::RefPtr<const Glib::Object>& b)
+{
+ const auto action_a = Glib::RefPtr<const Gio::SimpleAction>::cast_dynamic(a);
+ const auto action_b = Glib::RefPtr<const Gio::SimpleAction>::cast_dynamic(b);
+ if (!action_a || !action_b)
+ {
+ result = EXIT_FAILURE;
+ std::cerr << "compare_items1(): cast_dynamic() failed" << std::endl;
+ return 0;
+ }
+ gint32 value_a = 0;
+ gint32 value_b = 0;
+ action_a->get_state(value_a);
+ action_b->get_state(value_b);
+ return value_a - value_b;
+}
+
+void insert_item_sorted1(const Glib::RefPtr<Gio::ListStore<Glib::Object>>& store, gint32 n)
+{
+ auto obj = Gio::SimpleAction::create_radio_integer("dummy", n);
+ store->insert_sorted(obj, sigc::ptr_fun(compare_items1));
+}
+
+void test_store_sorted1()
+{
+ // Test that a subclass of Glib::Object can be stored in and retrieved from
+ // a Gio::ListStore<Glib::Object>.
+ auto store = Gio::ListStore<Glib::Object>::create();
+
+ const std::size_t n_items2 = 100; // n_items2*2 items are stored.
+ for (std::size_t i = 0; i < n_items2; ++i)
+ {
+ const auto n = get_next_number();
+ insert_item_sorted1(store, n);
+ insert_item_sorted1(store, n); // Multiple copies of the same are OK
+ }
+ if (store->get_n_items() != n_items2*2)
+ {
+ result = EXIT_FAILURE;
+ std::cerr << "test_store_sorted1(), 1: get_n_items()=" << store->get_n_items() << std::endl;
+ }
+
+ for (std::size_t i = 0; i < n_items2; ++i)
+ {
+ // Should see our two copies.
+ auto a = store->get_item(i * 2);
+ auto b = store->get_item(i * 2 + 1);
+ if (compare_items1(a, b) != 0)
+ {
+ result = EXIT_FAILURE;
+ std::cerr << "test_store_sorted1(), 2: i=" << i << ", items are not equal" << std::endl;
+ }
+ if (a.operator->() == b.operator->())
+ {
+ result = EXIT_FAILURE;
+ std::cerr << "test_store_sorted1(), 3: i=" << i << ", items are the same" << std::endl;
+ }
+
+ if (i > 0)
+ {
+ auto c = store->get_item(i * 2 - 1);
+ if (c.operator->() == a.operator->() || c.operator->() == b.operator->())
+ {
+ result = EXIT_FAILURE;
+ std::cerr << "test_store_sorted1(), 4: i=" << i << ", items are the same" << std::endl;
+ }
+ if (!(compare_items1(a, c) > 0 && compare_items1(b, c) > 0))
+ {
+ result = EXIT_FAILURE;
+ std::cerr << "test_store_sorted1(), 5: i=" << i << ", c is not less than a and b" << std::endl;
+ }
+ }
+ }
+} // end test_store_sorted1()
+
+// User-defined class
+class MyObject : public Glib::Object
+{
+protected:
+ MyObject(int id) : m_id(id) {}
+
+public:
+ static Glib::RefPtr<MyObject> create(int id)
+ {
+ return Glib::RefPtr<MyObject>(new MyObject(id));
+ }
+
+ int get_id() const { return m_id; }
+
+ static int compare(const Glib::RefPtr<const MyObject>& a,
+ const Glib::RefPtr<const MyObject>& b)
+ {
+ if (!a || !b)
+ {
+ result = EXIT_FAILURE;
+ std::cerr << "MyObject::compare(): Empty RefPtr" << std::endl;
+ return 0;
+ }
+ return a->get_id() - b->get_id();
+ }
+
+private:
+ int m_id;
+};
+
+void test_store_sorted2()
+{
+ // Test that a user-defined class, derived from Glib::Object, can be stored in
+ // and retrieved from a Gio::ListStore<>.
+ auto store = Gio::ListStore<MyObject>::create();
+
+ const std::size_t n_items2 = 100; // n_items2*2 items are stored.
+ for (std::size_t i = 0; i < n_items2; ++i)
+ {
+ const auto n = get_next_number();
+ // Multiple copies of the same are OK
+ store->insert_sorted(MyObject::create(n), sigc::ptr_fun(&MyObject::compare));
+ store->insert_sorted(MyObject::create(n), sigc::ptr_fun(&MyObject::compare));
+ }
+ if (store->get_n_items() != n_items2*2)
+ {
+ result = EXIT_FAILURE;
+ std::cerr << "test_store_sorted2(), 1: get_n_items()=" << store->get_n_items() << std::endl;
+ }
+
+ for (std::size_t i = 0; i < n_items2; ++i)
+ {
+ // Should see our two copies.
+ auto a = store->get_item(i * 2);
+ auto b = store->get_item(i * 2 + 1);
+ if (MyObject::compare(a, b) != 0)
+ {
+ result = EXIT_FAILURE;
+ std::cerr << "test_store_sorted2(), 2: i=" << i << ", items are not equal" << std::endl;
+ }
+ if (a.operator->() == b.operator->())
+ {
+ result = EXIT_FAILURE;
+ std::cerr << "test_store_sorted2(), 3: i=" << i << ", items are the same" << std::endl;
+ }
+
+ if (i > 0)
+ {
+ auto c = store->get_item(i * 2 - 1);
+ if (c.operator->() == a.operator->() || c.operator->() == b.operator->())
+ {
+ result = EXIT_FAILURE;
+ std::cerr << "test_store_sorted2(), 4: i=" << i << ", items are the same" << std::endl;
+ }
+ if (!(MyObject::compare(a, c) > 0 && MyObject::compare(b, c) > 0))
+ {
+ result = EXIT_FAILURE;
+ std::cerr << "test_store_sorted2(), 5: i=" << i << ", c is not less than a and b" << std::endl;
+ }
+ }
+ }
+} // end test_store_sorted2()
+
+} // anonymous namespace
+
+int main(int, char**)
+{
+ Gio::init();
+
+ test_store_boundaries();
+ test_store_refcounts();
+ test_store_sorted1();
+ test_store_sorted2();
+
+ return result;
+}