[pygobject] Add tests for refcount of a GObject owned by a library
- From: Tomeu Vizoso <tomeuv src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] Add tests for refcount of a GObject owned by a library
- Date: Thu, 20 Jan 2011 13:52:01 +0000 (UTC)
commit cae2cf3d4fb049c94389bf8f84d7d97a544d7a3f
Author: Steve Frécinaux <code istique net>
Date: Wed Jan 19 16:57:57 2011 +0100
Add tests for refcount of a GObject owned by a library
When the object is constructed, its refcount is 2 because the library
refs it once. It should remain around until we ask the library to
release its reference.
https://bugzilla.gnome.org/show_bug.cgi?id=639949
tests/test-floating.c | 30 ++++++++++++++++++++++
tests/test-floating.h | 20 +++++++++++++++
tests/test_gobject.py | 62 ++++++++++++++++++++++++++++++++++++++++++++++
tests/testhelpermodule.c | 51 +++++++++++++++++++++++++++++++++++++
4 files changed, 163 insertions(+), 0 deletions(-)
---
diff --git a/tests/test-floating.c b/tests/test-floating.c
index 918a42d..393784e 100644
--- a/tests/test-floating.c
+++ b/tests/test-floating.c
@@ -93,3 +93,33 @@ test_floating_without_sink_func_init (TestFloatingWithoutSinkFunc *self)
{
}
+/* TestOwnedByLibrary */
+
+G_DEFINE_TYPE(TestOwnedByLibrary, test_owned_by_library, G_TYPE_OBJECT)
+
+static GSList *obl_instance_list = NULL;
+
+static void
+test_owned_by_library_class_init (TestOwnedByLibraryClass *klass)
+{
+}
+
+static void
+test_owned_by_library_init (TestOwnedByLibrary *self)
+{
+ g_object_ref (self);
+ obl_instance_list = g_slist_prepend (obl_instance_list, self);
+}
+
+void
+test_owned_by_library_release (TestOwnedByLibrary *self)
+{
+ obl_instance_list = g_slist_remove (obl_instance_list, self);
+ g_object_unref (self);
+}
+
+GSList *
+test_owned_by_library_get_instance_list (void)
+{
+ return obl_instance_list;
+}
diff --git a/tests/test-floating.h b/tests/test-floating.h
index e53df32..05cd394 100644
--- a/tests/test-floating.h
+++ b/tests/test-floating.h
@@ -58,3 +58,23 @@ typedef struct {
GType test_floating_without_sink_func_get_type (void);
+/* TestOwnedByLibrary */
+
+typedef struct {
+ GObject parent;
+} TestOwnedByLibrary;
+
+typedef struct {
+ GObjectClass parent_class;
+} TestOwnedByLibraryClass;
+
+#define TEST_TYPE_OWNED_BY_LIBRARY (test_owned_by_library_get_type())
+#define TEST_OWNED_BY_LIBRARY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_OWNED_BY_LIBRARY, TestOwnedByLibrary))
+#define TEST_OWNED_BY_LIBRARY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_OWNED_BY_LIBRARY, TestOwnedByLibraryClass))
+#define TEST_IS_OWNED_BY_LIBRARY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_OWNED_BY_LIBRARY))
+#define TEST_IS_OWNED_BY_LIBRARY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), TEST_TYPE_OWNED_BY_LIBRARY))
+#define TEST_OWNED_BY_LIBRARY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TEST_TYPE_OWNED_BY_LIBRARY, TestOwnedByLibraryClass))
+
+GType test_owned_by_library_get_type (void);
+void test_owned_by_library_release (TestOwnedByLibrary *self);
+GSList *test_owned_by_library_get_instance_list (void);
diff --git a/tests/test_gobject.py b/tests/test_gobject.py
index b445be9..cfcebfd 100644
--- a/tests/test_gobject.py
+++ b/tests/test_gobject.py
@@ -34,3 +34,65 @@ class TestReferenceCounting(unittest.TestCase):
obj = gobject.new(testhelper.FloatingWithoutSinkFunc)
self.assertEquals(obj.__grefcount__, 1)
+
+ def testOwnedByLibrary(self):
+ # Upon creation, the refcount of the object should be 2:
+ # - someone already has a reference on the new object.
+ # - the python wrapper should hold its own reference.
+ obj = testhelper.OwnedByLibrary()
+ self.assertEquals(obj.__grefcount__, 2)
+
+ # We ask the library to release its reference, so the only
+ # remaining ref should be our wrapper's. Once the wrapper
+ # will run out of scope, the object will get finalized.
+ obj.release()
+ self.assertEquals(obj.__grefcount__, 1)
+
+ def testOwnedByLibraryOutOfScope(self):
+ obj = testhelper.OwnedByLibrary()
+ self.assertEquals(obj.__grefcount__, 2)
+
+ # We are manually taking the object out of scope. This means
+ # that our wrapper has been freed, and its reference dropped. We
+ # cannot check it but the refcount should now be 1 (the ref held
+ # by the library is still there, we didn't call release()
+ obj = None
+
+ # When we get the object back from the lib, the wrapper is
+ # re-created, so our refcount will be 2 once again.
+ obj = testhelper.owned_by_library_get_instance_list()[0]
+ self.assertEquals(obj.__grefcount__, 2)
+
+ obj.release()
+ self.assertEquals(obj.__grefcount__, 1)
+
+ def testOwnedByLibraryUsingGObjectNew(self):
+ # Upon creation, the refcount of the object should be 2:
+ # - someone already has a reference on the new object.
+ # - the python wrapper should hold its own reference.
+ obj = gobject.new(testhelper.OwnedByLibrary)
+ self.assertEquals(obj.__grefcount__, 2)
+
+ # We ask the library to release its reference, so the only
+ # remaining ref should be our wrapper's. Once the wrapper
+ # will run out of scope, the object will get finalized.
+ obj.release()
+ self.assertEquals(obj.__grefcount__, 1)
+
+ def testOwnedByLibraryOutOfScopeUsingGobjectNew(self):
+ obj = gobject.new(testhelper.OwnedByLibrary)
+ self.assertEquals(obj.__grefcount__, 2)
+
+ # We are manually taking the object out of scope. This means
+ # that our wrapper has been freed, and its reference dropped. We
+ # cannot check it but the refcount should now be 1 (the ref held
+ # by the library is still there, we didn't call release()
+ obj = None
+
+ # When we get the object back from the lib, the wrapper is
+ # re-created, so our refcount will be 2 once again.
+ obj = testhelper.owned_by_library_get_instance_list()[0]
+ self.assertEquals(obj.__grefcount__, 2)
+
+ obj.release()
+ self.assertEquals(obj.__grefcount__, 1)
diff --git a/tests/testhelpermodule.c b/tests/testhelpermodule.c
index 5610a5d..9a0be36 100644
--- a/tests/testhelpermodule.c
+++ b/tests/testhelpermodule.c
@@ -230,6 +230,22 @@ PYGLIB_DEFINE_TYPE("testhelper.FloatingWithSinkFunc", PyTestFloatingWithSinkFunc
/* TestFloatingWithoutSinkFunc */
PYGLIB_DEFINE_TYPE("testhelper.FloatingWithoutSinkFunc", PyTestFloatingWithoutSinkFunc_Type, PyGObject);
+/* TestOwnedByLibrary */
+PYGLIB_DEFINE_TYPE("testhelper.OwnedByLibrary", PyTestOwnedByLibrary_Type, PyGObject);
+
+static PyObject *
+_wrap_test_owned_by_library_release (PyGObject *self)
+{
+ test_owned_by_library_release (TEST_OWNED_BY_LIBRARY (self->obj));
+ return Py_None;
+}
+
+static const PyMethodDef _PyTestOwnedByLibrary_methods[] = {
+ { "release", (PyCFunction)_wrap_test_owned_by_library_release, METH_NOARGS, NULL },
+ { NULL, NULL, 0, NULL }
+};
+
+
#include <string.h>
#include <glib-object.h>
@@ -431,6 +447,29 @@ _wrap_test_gerror_exception(PyObject *self, PyObject *args)
return Py_None;
}
+static PyObject *
+_wrap_test_owned_by_library_get_instance_list (PyObject *self)
+{
+ PyObject *py_list, *py_obj;
+ GSList *list, *tmp;
+
+ list = test_owned_by_library_get_instance_list ();
+
+ if ((py_list = PyList_New (0)) == NULL) {
+ return NULL;
+ }
+ for (tmp = list; tmp != NULL; tmp = tmp->next) {
+ py_obj = pygobject_new (G_OBJECT (tmp->data));
+ if (py_obj == NULL) {
+ Py_DECREF (py_list);
+ return NULL;
+ }
+ PyList_Append (py_list, py_obj);
+ Py_DECREF (py_obj);
+ }
+ return py_list;
+}
+
static PyMethodDef testhelper_functions[] = {
{ "get_test_thread", (PyCFunction)_wrap_get_test_thread, METH_NOARGS },
{ "get_unknown", (PyCFunction)_wrap_get_unknown, METH_NOARGS },
@@ -440,6 +479,7 @@ static PyMethodDef testhelper_functions[] = {
{ "test_value", (PyCFunction)_wrap_test_value, METH_VARARGS },
{ "test_value_array", (PyCFunction)_wrap_test_value_array, METH_VARARGS },
{ "test_gerror_exception", (PyCFunction)_wrap_test_gerror_exception, METH_VARARGS },
+ { "owned_by_library_get_instance_list", (PyCFunction)_wrap_test_owned_by_library_get_instance_list, METH_NOARGS },
{ NULL, NULL }
};
@@ -507,6 +547,17 @@ PYGLIB_MODULE_START(testhelper, "testhelper")
Py_BuildValue("(O)",
&PyGObject_Type));
pyg_set_object_has_new_constructor(TEST_TYPE_FLOATING_WITHOUT_SINK_FUNC);
+
+ /* TestOwnedByLibrary */
+ PyTestOwnedByLibrary_Type.tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE);
+ PyTestOwnedByLibrary_Type.tp_methods = (struct PyMethodDef*)_PyTestOwnedByLibrary_methods;
+ PyTestOwnedByLibrary_Type.tp_weaklistoffset = offsetof(PyGObject, weakreflist);
+ PyTestOwnedByLibrary_Type.tp_dictoffset = offsetof(PyGObject, inst_dict);
+ pygobject_register_class(d, "OwnedByLibrary", TEST_TYPE_OWNED_BY_LIBRARY,
+ &PyTestOwnedByLibrary_Type,
+ Py_BuildValue("(O)",
+ &PyGObject_Type));
+ pyg_set_object_has_new_constructor(TEST_TYPE_OWNED_BY_LIBRARY);
}
PYGLIB_MODULE_END
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]