summaryrefslogtreecommitdiff
path: root/tests/glibmm_refptr/main.cc
diff options
context:
space:
mode:
Diffstat (limited to 'tests/glibmm_refptr/main.cc')
-rw-r--r--tests/glibmm_refptr/main.cc275
1 files changed, 275 insertions, 0 deletions
diff --git a/tests/glibmm_refptr/main.cc b/tests/glibmm_refptr/main.cc
new file mode 100644
index 00000000..d03b2249
--- /dev/null
+++ b/tests/glibmm_refptr/main.cc
@@ -0,0 +1,275 @@
+// Bug 564005 - Valgrind errors and crash on exit with Gtk::UIManager
+// Bug 154498 - Unnecessary warning on console: signalproxy_connectionnode.cc
+
+
+#include <glibmm.h>
+#include <sigc++/sigc++.h>
+#include <iostream>
+#include <stdlib.h>
+
+#define ACTIVATE_BUG 1
+
+// A class with its own reference-count, for use with RefPtr.
+class Something
+{
+public:
+ Something()
+ : ref_count_(1),
+ max_ref_count_(ref_count_)
+ {}
+
+ void reference()
+ {
+ ++ref_count_;
+
+ //Track the highest-ever max count.
+ if(max_ref_count_ < ref_count_)
+ max_ref_count_ = ref_count_;
+ }
+
+ void unreference()
+ {
+ if (--ref_count_ <= 0)
+ delete this;
+ }
+
+ //Just so we can check it in our test.
+ int ref_count()
+ {
+ return ref_count_;
+ }
+
+ //Just so we can check it in our test.
+ int max_ref_count()
+ {
+ return max_ref_count_;
+ }
+
+
+private:
+ int ref_count_;
+ int max_ref_count_;
+};
+
+class SomethingDerived : public Something
+{
+};
+
+class Parent
+{
+public:
+ explicit Parent(const Glib::RefPtr<Something>& something)
+ : something_(something),
+ was_constructed_via_copy_constructor_(true),
+ was_constructed_via_move_constructor_(false)
+ {
+ }
+
+ explicit Parent(Glib::RefPtr<Something>&& something)
+ : something_(std::move(something)),
+ was_constructed_via_copy_constructor_(false),
+ was_constructed_via_move_constructor_(true)
+ {
+ }
+
+ //Non copyable
+ Parent(const Parent& src) = delete;
+ Parent& operator=(const Parent& src) = delete;
+
+ bool was_constructed_via_copy_constructor() const
+ {
+ return was_constructed_via_copy_constructor_;
+ }
+
+ bool was_constructed_via_move_constructor() const
+ {
+ return was_constructed_via_move_constructor_;
+ }
+
+ int something_ref_count() const
+ {
+ return something_->ref_count();
+ }
+
+ int something_max_ref_count() const
+ {
+ return something_->max_ref_count();
+ }
+
+private:
+ Glib::RefPtr<Something> something_;
+ bool was_constructed_via_copy_constructor_;
+ bool was_constructed_via_move_constructor_;
+
+};
+
+static
+void test_initial_refcount()
+{
+ Glib::RefPtr<Something> refSomething (new Something());
+ g_assert_cmpint(refSomething->ref_count(), ==, 1);
+ g_assert_cmpint(refSomething->max_ref_count(), ==, 1);
+}
+
+static
+void test_refptr_copy_constructor()
+{
+ Glib::RefPtr<Something> refSomething (new Something());
+ g_assert_cmpint(refSomething->ref_count(), ==, 1);
+ g_assert_cmpint(refSomething->max_ref_count(), ==, 1);
+
+ {
+ Glib::RefPtr<Something> refSomething2(refSomething);
+ g_assert_cmpint(refSomething->ref_count(), ==, 2);
+ g_assert_cmpint(refSomething2->ref_count(), ==, 2);
+ g_assert_cmpint(refSomething->max_ref_count(), ==, 2);
+ }
+
+ //Test the refcount after other references should have been released
+ //when other RefPtrs went out of scope:
+ g_assert_cmpint(refSomething->ref_count(), ==, 1);
+ g_assert_cmpint(refSomething->max_ref_count(), ==, 2);
+}
+
+static
+void test_refptr_assignment_operator()
+{
+ Glib::RefPtr<Something> refSomething (new Something());
+ g_assert_cmpint(refSomething->ref_count(), ==, 1);
+ g_assert_cmpint(refSomething->max_ref_count(), ==, 1);
+
+ {
+ Glib::RefPtr<Something> refSomething2 = refSomething;
+ g_assert_cmpint(refSomething->ref_count(), ==, 2);
+ g_assert_cmpint(refSomething2->ref_count(), ==, 2);
+ g_assert_cmpint(refSomething->max_ref_count(), ==, 2);
+ }
+
+ //Test the refcount after other references should have been released
+ //when other RefPtrs went out of scope:
+ g_assert_cmpint(refSomething->ref_count(), ==, 1);
+ g_assert_cmpint(refSomething->max_ref_count(), ==, 2);
+}
+
+
+
+static
+Glib::RefPtr<Something> get_something()
+{
+ static Glib::RefPtr<Something> something_to_get;
+
+ //Reinitialize it each time:
+ something_to_get = Glib::RefPtr<Something>(new Something());
+
+ return something_to_get;
+}
+
+static
+void test_refptr_with_parent_copy_constructor()
+{
+ //We use get_something() because test_refptr_with_parent_move_constructor() does.
+ Glib::RefPtr<Something> refSomething = get_something();
+ g_assert_cmpint(refSomething->ref_count(), ==, 2); //1 here and 1 inside get_something()
+ g_assert_cmpint(refSomething->max_ref_count(), ==, 2);
+
+ {
+ Parent parent(refSomething);
+ g_assert(!parent.was_constructed_via_move_constructor());
+ g_assert(parent.was_constructed_via_copy_constructor());
+ g_assert_cmpint(parent.something_ref_count(), ==, 3); //1 here, 1 in parent, and 1 inside get_something()
+ g_assert_cmpint(parent.something_max_ref_count(), ==, 3);
+ }
+
+ //Test the refcount after other references should have been released
+ //when other RefPtrs went out of scope:
+ g_assert_cmpint(refSomething->ref_count(), ==, 2); //1 here and 1 inside get_something()
+ g_assert_cmpint(refSomething->max_ref_count(), ==, 3);
+}
+
+static
+void test_refptr_with_parent_move_constructor()
+{
+ Parent parent(get_something());
+ g_assert(parent.was_constructed_via_move_constructor());
+ g_assert(!parent.was_constructed_via_copy_constructor());
+ g_assert_cmpint(parent.something_ref_count(), ==, 2); //1 in parent and 1 inside get_something()
+ g_assert_cmpint(parent.something_max_ref_count(), ==, 2);
+}
+
+static
+void test_refptr_move_constructor()
+{
+ Glib::RefPtr<Something> refSomething(new Something());
+ Glib::RefPtr<Something> refSomething2(std::move(refSomething));
+ g_assert_cmpint(refSomething2->ref_count(), ==, 1);
+ g_assert(!refSomething);
+ g_assert_cmpint(refSomething2->max_ref_count(), ==, 1);
+}
+
+static
+void test_refptr_move_assignment_operator()
+{
+ Glib::RefPtr<Something> refSomething(new Something());
+ Glib::RefPtr<Something> refSomething2;
+ refSomething2 = std::move(refSomething);
+ g_assert_cmpint(refSomething2->ref_count(), ==, 1);
+ g_assert(!refSomething);
+ g_assert_cmpint(refSomething2->max_ref_count(), ==, 1);
+}
+
+static
+void test_refptr_universal_reference_move_constructor()
+{
+ Glib::RefPtr<SomethingDerived> refSomethingDerived(new SomethingDerived());
+ Glib::RefPtr<Something> refSomething(std::move(refSomethingDerived));
+ g_assert_cmpint(refSomething->ref_count(), ==, 1);
+ g_assert(!refSomethingDerived);
+ g_assert_cmpint(refSomething->max_ref_count(), ==, 1);
+}
+
+static
+void test_refptr_universal_reference_asignment_operator()
+{
+ Glib::RefPtr<SomethingDerived> refSomethingDerived(new SomethingDerived());
+ Glib::RefPtr<Something> refSomething;
+ refSomething = std::move(refSomethingDerived);
+ g_assert_cmpint(refSomething->ref_count(), ==, 1);
+ g_assert(!refSomethingDerived);
+ g_assert_cmpint(refSomething->max_ref_count(), ==, 1);
+}
+
+int main(int, char**)
+{
+ //Test initial refcount:
+ test_initial_refcount();
+
+ //Test refcount when using the RefPtr copy constructor:
+ test_refptr_copy_constructor();
+
+ //Test refcount when using the RefPtr assignment operator (operator=):
+ test_refptr_assignment_operator();
+
+ //Test the refcount when using the RefPtr move constuctor:
+ test_refptr_move_constructor();
+
+ //Test the refcount when using the RefPtr move asignment operator (operator=):
+ test_refptr_move_assignment_operator();
+
+ //Test the refcount when another class makes a copy via its constructor:
+ test_refptr_with_parent_copy_constructor();
+
+ //Test the refcount when another class makes a copy via its
+ //(perfect-forwarding) move constructor, which should not involve a temporary
+ //instance:
+ test_refptr_with_parent_move_constructor();
+
+ //Test the refcount when using the RefPtr move constructor with derived class
+ //as an argument.
+ test_refptr_universal_reference_move_constructor();
+
+ //Test the refcount when using the RefPtr assignment operator (operator=)
+ //with derived class as an argument.
+ test_refptr_universal_reference_asignment_operator();
+
+ return EXIT_SUCCESS;
+}