Eo: Fix singleton pattern and add a test to make sure it works.
authorTom Hacohen <tom@stosb.com>
Wed, 18 May 2016 12:29:45 +0000 (13:29 +0100)
committerTom Hacohen <tom@stosb.com>
Wed, 18 May 2016 12:31:30 +0000 (13:31 +0100)
src/Makefile_Eo.am
src/lib/eo/eo.c
src/tests/eo/suite/eo_test_class_singleton.c [new file with mode: 0644]
src/tests/eo/suite/eo_test_class_singleton.h [new file with mode: 0644]
src/tests/eo/suite/eo_test_general.c

index 2626f3f..69c4466 100644 (file)
@@ -122,6 +122,8 @@ TESTS += tests/eo/test_constructors
 tests_eo_eo_suite_SOURCES = \
 tests/eo/suite/eo_test_class_simple.c \
 tests/eo/suite/eo_test_class_simple.h \
+tests/eo/suite/eo_test_class_singleton.c \
+tests/eo/suite/eo_test_class_singleton.h \
 tests/eo/suite/eo_suite.c \
 tests/eo/suite/eo_suite.h \
 tests/eo/suite/eo_error_msgs.h \
index 88e22db..c8039f4 100644 (file)
@@ -683,10 +683,20 @@ _eo_add_internal_start(const char *file, int line, const Eo_Class *klass_id, Eo
      {
         ERR("Object of class '%s' - Error while constructing object",
             klass->desc->name);
+
+        /* We have two refs at this point. */
         _eo_unref(obj);
         _eo_unref(obj);
         return NULL;
      }
+   else if (eo_id != _eo_obj_id_get(obj))
+     {
+        /* We have two refs at this point. */
+        _eo_unref(obj);
+        _eo_unref(obj);
+
+        eo_ref(eo_id);
+     }
 
    if (is_fallback)
      {
diff --git a/src/tests/eo/suite/eo_test_class_singleton.c b/src/tests/eo/suite/eo_test_class_singleton.c
new file mode 100644 (file)
index 0000000..4898abc
--- /dev/null
@@ -0,0 +1,43 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "Eo.h"
+#include "eo_test_class_singleton.h"
+#include "eo_test_class_simple.h"
+
+#define MY_CLASS SINGLETON_CLASS
+
+static Eo *singleton_obj = NULL;
+
+static Eo *
+_singleton_eo_constructor(Eo *eo_obj EINA_UNUSED, void *_pd EINA_UNUSED)
+{
+   if (!singleton_obj)
+     {
+        singleton_obj = eo_add(SIMPLE_CLASS, NULL);
+     }
+   else
+     {
+        eo_ref(singleton_obj);
+     }
+
+   return singleton_obj;
+}
+
+static Eo_Op_Description op_descs[] = {
+     EO_OP_FUNC_OVERRIDE(eo_constructor, _singleton_eo_constructor),
+};
+
+static const Eo_Class_Description class_desc = {
+     EO_VERSION,
+     "Singleton",
+     EO_CLASS_TYPE_REGULAR,
+     EO_CLASS_DESCRIPTION_OPS(op_descs),
+     NULL,
+     0,
+     NULL,
+     NULL
+};
+
+EO_DEFINE_CLASS(singleton_class_get, &class_desc, EO_CLASS, NULL)
diff --git a/src/tests/eo/suite/eo_test_class_singleton.h b/src/tests/eo/suite/eo_test_class_singleton.h
new file mode 100644 (file)
index 0000000..7aafb35
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef SINGLETON_H
+#define SINGLETON_H
+
+#define SINGLETON_CLASS singleton_class_get()
+const Eo_Class *singleton_class_get(void);
+
+#endif
index a26c0d6..959247d 100644 (file)
@@ -10,6 +10,7 @@
 
 #include "eo_suite.h"
 #include "eo_test_class_simple.h"
+#include "eo_test_class_singleton.h"
 
 /* Loading this internal header for testing purposes. */
 #include "eo_ptr_indirection.h"
@@ -30,6 +31,25 @@ START_TEST(eo_simple)
 }
 END_TEST
 
+START_TEST(eo_singleton)
+{
+   eo_init();
+
+   Eo *obj = eo_add(SINGLETON_CLASS, NULL);
+   fail_if(!obj);
+
+   Eo *obj2 = eo_add(SINGLETON_CLASS, NULL);
+   fail_if(!obj2);
+
+   ck_assert_ptr_eq(obj, obj2);
+
+   eo_unref(obj);
+   eo_unref(obj2);
+
+   eo_shutdown();
+}
+END_TEST
+
 START_TEST(eo_stack)
 {
    eo_init();
@@ -1171,6 +1191,7 @@ END_TEST
 void eo_test_general(TCase *tc)
 {
    tcase_add_test(tc, eo_simple);
+   tcase_add_test(tc, eo_singleton);
    tcase_add_test(tc, eo_stack);
    tcase_add_test(tc, eo_signals);
    tcase_add_test(tc, eo_data_fetch);