From b02b64fba74477bedf4c52e5833a8ede137f712b Mon Sep 17 00:00:00 2001 From: Lauro Moura Date: Fri, 31 May 2019 17:34:59 -0300 Subject: [PATCH] csharp: Add some tests Summary: - Wrappers losing C# ref while alive in Eo - Inherited instances being collected Also cleanup GC and loop queue before each test Reviewers: vitor.sousa Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D9063 --- src/Makefile_Efl_Mono.am | 10 ++++- src/tests/efl_mono/Eo.cs | 14 +++++++ src/tests/efl_mono/Events.cs | 53 +++++++++++++++++++++++++++ src/tests/efl_mono/Main.cs | 3 ++ src/tests/efl_mono/TestUtils.cs | 14 +++++++ src/tests/efl_mono/dummy_event_manager.c | 55 ++++++++++++++++++++++++++++ src/tests/efl_mono/dummy_event_manager.eo | 29 +++++++++++++++ src/tests/efl_mono/libefl_mono_native_test.h | 1 + src/tests/efl_mono/meson.build | 12 +++++- 9 files changed, 189 insertions(+), 2 deletions(-) create mode 100644 src/tests/efl_mono/dummy_event_manager.c create mode 100644 src/tests/efl_mono/dummy_event_manager.eo diff --git a/src/Makefile_Efl_Mono.am b/src/Makefile_Efl_Mono.am index 94e38fe..b85d23f 100644 --- a/src/Makefile_Efl_Mono.am +++ b/src/Makefile_Efl_Mono.am @@ -69,7 +69,8 @@ efl_mono_test_eolian_files = \ tests/efl_mono/dummy_inherit_helper.eo \ tests/efl_mono/dummy_child.eo \ tests/efl_mono/dummy_part_holder.eo \ - tests/efl_mono/dummy_numberwrapper.eo + tests/efl_mono/dummy_numberwrapper.eo \ + tests/efl_mono/dummy_event_manager.eo efl_mono_test_files = \ $(efl_mono_test_eolian_files) \ @@ -416,6 +417,7 @@ check_LTLIBRARIES += tests/efl_mono/libefl_mono_native_test.la tests_efl_mono_libefl_mono_native_test_la_SOURCES = \ tests/efl_mono/dummy_child.c \ + tests/efl_mono/dummy_event_manager.c \ tests/efl_mono/dummy_inherit_helper.c \ tests/efl_mono/dummy_interfaces.c \ tests/efl_mono/dummy_numberwrapper.c \ @@ -439,6 +441,11 @@ tests/efl_mono/dummy_child.c: \ $(efl_mono_test_eolian_h) \ tests/efl_mono/libefl_mono_native_test.h +tests/efl_mono/dummy_event_manager.c: \ + $(efl_mono_test_eolian_c) \ + $(efl_mono_test_eolian_h) \ + tests/efl_mono/libefl_mono_native_test.h + tests/efl_mono/dummy_inherit_helper.c: \ $(efl_mono_test_eolian_c) \ $(efl_mono_test_eolian_h) \ @@ -468,6 +475,7 @@ tests/efl_mono/dummy_test_object.c: \ efl_mono_test_eolian_mono_files = tests/efl_mono/dummy_test_object.eo.cs \ tests/efl_mono/dummy_test_iface.eo.cs \ tests/efl_mono/dummy_child.eo.cs \ +tests/efl_mono/dummy_event_manager.eo.cs \ tests/efl_mono/dummy_part_holder.eo.cs \ tests/efl_mono/dummy_numberwrapper.eo.cs \ tests/efl_mono/dummy_inherit_iface.eo.cs \ diff --git a/src/tests/efl_mono/Eo.cs b/src/tests/efl_mono/Eo.cs index e77fd7b..95b6b63 100644 --- a/src/tests/efl_mono/Eo.cs +++ b/src/tests/efl_mono/Eo.cs @@ -110,6 +110,20 @@ class TestEoInherit Efl.Object loop = new MyObject(); Test.Assert(loop.NativeHandle != System.IntPtr.Zero); } + + private static WeakReference CreateCollectableInherited() + { + var obj = new MyObject(); + return new WeakReference(obj); + } + + public static void inherited_collected() + { + var wref = CreateCollectableInherited(); + Test.CollectAndIterate(); + + Test.AssertNull(wref.Target); + } } class TestEoNames diff --git a/src/tests/efl_mono/Events.cs b/src/tests/efl_mono/Events.cs index 70a49bf..b664e2b 100644 --- a/src/tests/efl_mono/Events.cs +++ b/src/tests/efl_mono/Events.cs @@ -274,4 +274,57 @@ class TestEventNaming } } + +class TestEventWithDeadWrappers +{ + + private static WeakReference AttachToManager(Dummy.EventManager manager, + EventHandler cb) + { + var obj = new Dummy.TestObject(); + manager.Emitter = obj; + + obj.EvtWithIntEvt += cb; + return new WeakReference(obj); + } + + public static void test_event_from_c_owned_wrapper() + { + // Set upon object instantiation + WeakReference wref = null; + + // Checks in the callback called + bool callbackCalled = false; + int received = -1; + + // attach to evt with int + EventHandler cb = (object sender, Dummy.TestObjectEvtWithIntEvt_Args args) => { + callbackCalled = true; + received = args.arg; + Test.Assert(Object.ReferenceEquals(sender, wref.Target)); + }; + + Dummy.EventManager manager = new Dummy.EventManager(); + wref = AttachToManager(manager, cb); + + Test.CollectAndIterate(); + + manager.EmitWithInt(42); + + Test.CollectAndIterate(); + + Test.Assert(callbackCalled, "Callback must have been called."); + Test.AssertEquals(42, received, "Wrong value received."); + + // Cleanup checks + manager.Release(); + + // Make sure the released wrapper is collected and release the Eo object + Test.CollectAndIterate(); + + Test.AssertNull(wref.Target); + } + +} + } diff --git a/src/tests/efl_mono/Main.cs b/src/tests/efl_mono/Main.cs index a5700ff..f154f93 100644 --- a/src/tests/efl_mono/Main.cs +++ b/src/tests/efl_mono/Main.cs @@ -42,6 +42,9 @@ class TestMain if (localTestCase == setUp || localTestCase == tearDown) continue; + // Cleanup garbage collector and job queue + Test.CollectAndIterate(1); + Console.WriteLine("[ RUN ] " + testCase.Name + "." + localTestCase.Name); bool caseResult = true; diff --git a/src/tests/efl_mono/TestUtils.cs b/src/tests/efl_mono/TestUtils.cs index e7daf05..657bdb0 100644 --- a/src/tests/efl_mono/TestUtils.cs +++ b/src/tests/efl_mono/TestUtils.cs @@ -196,6 +196,20 @@ public static class Test if (reference == null) throw new AssertionException($"Assertion failed: {file}:{line} ({member}) {msg}"); } + + /// Runs a number of garbage collections and iterate the main loop. + /// The iteration is needed to make sure objects collected in the GC thread + /// are efl_unref'd in the main thread. + public static void CollectAndIterate(int iterations=1000) + { + for (int i = 0; i < iterations; i++) + { + System.GC.Collect(); + } + System.GC.WaitForPendingFinalizers(); + Efl.App.AppMain.Iterate(); + } + } diff --git a/src/tests/efl_mono/dummy_event_manager.c b/src/tests/efl_mono/dummy_event_manager.c new file mode 100644 index 0000000..416877d --- /dev/null +++ b/src/tests/efl_mono/dummy_event_manager.c @@ -0,0 +1,55 @@ +#include "libefl_mono_native_test.h" + +typedef struct Dummy_Event_Manager_Data +{ + Eo* emitter; +} Dummy_Event_Manager_Data; + +static Efl_Object* +_dummy_event_manager_efl_object_constructor(Eo *obj, EINA_UNUSED Dummy_Event_Manager_Data *pd) +{ + efl_constructor(efl_super(obj, DUMMY_EVENT_MANAGER_CLASS)); + + return obj; +} + +static void +_dummy_event_manager_efl_object_destructor(Eo *obj, Dummy_Event_Manager_Data *pd) +{ + if (pd->emitter != 0) + efl_unref(pd->emitter); + + efl_destructor(efl_super(obj, DUMMY_EVENT_MANAGER_CLASS)); +} + +static void +_dummy_event_manager_emitter_set(EINA_UNUSED Eo *obj, Dummy_Event_Manager_Data *pd, Eo *emitter) +{ + pd->emitter = emitter; +} + +static Eina_Bool +_dummy_event_manager_emit_with_int(EINA_UNUSED Eo *obj, Dummy_Event_Manager_Data *pd, int data) +{ + if (pd->emitter) + efl_event_callback_call(pd->emitter, DUMMY_TEST_OBJECT_EVENT_EVT_WITH_INT, &data); + else + { + EINA_LOG_ERR("Trying to emit event without an emitter."); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static void +_dummy_event_manager_release(EINA_UNUSED Eo *obj, Dummy_Event_Manager_Data *pd) +{ + if (!pd->emitter) + return; + + efl_unref(pd->emitter); +} + + +#include "dummy_event_manager.eo.c" diff --git a/src/tests/efl_mono/dummy_event_manager.eo b/src/tests/efl_mono/dummy_event_manager.eo new file mode 100644 index 0000000..78b9dec --- /dev/null +++ b/src/tests/efl_mono/dummy_event_manager.eo @@ -0,0 +1,29 @@ +import eina_types; + +class @beta Dummy.Event_Manager extends Efl.Object { + + methods { + @property emitter { + set { + } + values { + emitter: Efl.Object @owned; + } + } + + emit_with_int { + params { + data: int; + } + return: bool; + } + + release { + } + } + + implements { + Efl.Object.constructor; + Efl.Object.destructor; + } +} diff --git a/src/tests/efl_mono/libefl_mono_native_test.h b/src/tests/efl_mono/libefl_mono_native_test.h index 672f249..9251118 100644 --- a/src/tests/efl_mono/libefl_mono_native_test.h +++ b/src/tests/efl_mono/libefl_mono_native_test.h @@ -54,6 +54,7 @@ #include "dummy_child.eo.h" #include "dummy_inherit_helper.eo.h" #include "dummy_part_holder.eo.h" +#include "dummy_event_manager.eo.h" #include diff --git a/src/tests/efl_mono/meson.build b/src/tests/efl_mono/meson.build index 84a0c22..f75a5b8 100644 --- a/src/tests/efl_mono/meson.build +++ b/src/tests/efl_mono/meson.build @@ -1,4 +1,13 @@ -eo_files = ['dummy_child.eo', 'dummy_numberwrapper.eo', 'dummy_test_object.eo', 'dummy_test_iface.eo', 'dummy_inherit_helper.eo', 'dummy_inherit_iface.eo', 'dummy_part_holder.eo'] +eo_files = [ + 'dummy_child.eo', + 'dummy_numberwrapper.eo', + 'dummy_test_object.eo', + 'dummy_test_iface.eo', + 'dummy_inherit_helper.eo', + 'dummy_inherit_iface.eo', + 'dummy_part_holder.eo', + 'dummy_event_manager.eo', +] eo_file_targets = [] @@ -23,6 +32,7 @@ efl_mono_native_test = library('efl_mono_native_test', 'dummy_numberwrapper.c', 'dummy_part_holder.c', 'dummy_test_object.c', + 'dummy_event_manager.c', ], dependencies : [ecore, eo, efl], ) -- 2.7.4