felipealmeida pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=3b090b808bf668f393d01c87dbfe5071615a7a72

commit 3b090b808bf668f393d01c87dbfe5071615a7a72
Author: Lauro Moura <[email protected]>
Date:   Tue Jun 7 14:05:15 2016 -0300

    eina: Fixes on promises behavior when cancelling
    
    - Free the cancel callbacks on promise delete
    - Cancelling an ended promise should be a nop
    - More tests to increase coverage
---
 src/lib/eina/eina_promise.c        |  12 +-
 src/tests/eina/eina_test_promise.c | 241 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 251 insertions(+), 2 deletions(-)

diff --git a/src/lib/eina/eina_promise.c b/src/lib/eina/eina_promise.c
index 7ce0112..eac1517 100644
--- a/src/lib/eina/eina_promise.c
+++ b/src/lib/eina/eina_promise.c
@@ -147,6 +147,14 @@ static void 
_eina_promise_free_progress_notify_callback_node(void* node)
    free(progress_notify_cb);
 }
 
+static void _eina_promise_free_cancel_callback_node(void *node)
+{
+    _Eina_Promise_Cancel_Cb *cancel_cb = node;
+    if (cancel_cb->free)
+      cancel_cb->free(cancel_cb->data);
+    free(cancel_cb);
+}
+
 static void _eina_promise_finish(_Eina_Promise_Default_Owner* promise);
 static void _eina_promise_ref(_Eina_Promise_Default* promise);
 static void _eina_promise_unref(_Eina_Promise_Default* promise);
@@ -249,6 +257,8 @@ _eina_promise_del(_Eina_Promise_Default_Owner* promise)
                                     
&_eina_promise_free_progress_callback_node);
    
_eina_promise_free_callback_list(&promise->promise.progress_notify_callbacks,
                                     
&_eina_promise_free_progress_notify_callback_node);
+   _eina_promise_free_callback_list(&promise->promise.cancel_callbacks,
+                                    &_eina_promise_free_cancel_callback_node);
    free(promise);
 }
 
@@ -437,7 +447,7 @@ _eina_promise_cancel(_Eina_Promise_Default* promise)
 {
    _Eina_Promise_Default_Owner* owner = EINA_PROMISE_GET_OWNER(promise);
 
-   if (!owner->promise.is_cancelled)
+   if (!owner->promise.is_cancelled && !owner->promise.has_finished)
      {
         owner->promise.is_cancelled = EINA_TRUE;
         owner->promise.has_finished = EINA_TRUE;
diff --git a/src/tests/eina/eina_test_promise.c 
b/src/tests/eina/eina_test_promise.c
index 4629869..086b6d5 100644
--- a/src/tests/eina/eina_test_promise.c
+++ b/src/tests/eina/eina_test_promise.c
@@ -80,6 +80,42 @@ START_TEST(eina_test_promise_normal_lifetime_all)
 }
 END_TEST
 
+static void
+_eina_test_error_cb(void *data, Eina_Error error)
+{
+    *(int *)data = error;
+}
+
+START_TEST(eina_test_promise_error_set)
+{
+   Eina_Promise_Owner* promise_owner;
+   Eina_Promise* promise;
+   int ran = 0;
+   int error = 0xdeadbeef;
+
+   eina_init();
+
+   promise_owner = eina_promise_value_add(0);
+
+   promise = eina_promise_owner_promise_get(promise_owner);
+
+   eina_promise_ref(promise);
+
+   eina_promise_then(promise, NULL, &_eina_test_error_cb, &ran);
+
+   eina_promise_owner_error_set(promise_owner, error);
+
+   ck_assert(ran == error);
+   ck_assert_int_eq(error, eina_promise_error_get(promise));
+   ck_assert(!eina_promise_pending_is(promise));
+   ck_assert(!eina_promise_owner_cancelled_is(promise_owner));
+
+   eina_promise_unref(promise);
+
+   eina_shutdown();
+}
+END_TEST
+
 START_TEST(eina_test_promise_immediate_set_lifetime)
 {
    Eina_Promise_Owner* owner;
@@ -208,7 +244,95 @@ START_TEST(eina_test_promise_cancel_promise)
    // Finally free the owner
    eina_promise_owner_value_set(owner, NULL, NULL);
 
-   ck_assert(ran);
+   eina_shutdown();
+}
+END_TEST
+
+static void
+_cancel_then_callback(void *data, void *value EINA_UNUSED)
+{
+   *(int*)data = 1;
+}
+
+static void
+_cancel_error_callback(void *data, Eina_Error error EINA_UNUSED)
+{
+   *(int*)data = -1;
+}
+
+START_TEST(eina_test_promise_cancel_finished_promise)
+{
+   Eina_Bool cancel_ran = EINA_FALSE;
+   int ran = 0;
+   Eina_Promise_Owner* owner;
+   Eina_Promise* promise;
+
+   eina_init();
+
+   owner = eina_promise_value_add(0);
+   eina_promise_owner_default_cancel_cb_add(owner, &cancel_callback, 
&cancel_ran, NULL);
+
+   promise = eina_promise_owner_promise_get(owner);
+
+   eina_promise_then(promise, &_cancel_then_callback, &_cancel_error_callback, 
&ran);
+
+   eina_promise_ref(promise);
+   eina_promise_owner_value_set(owner, NULL, NULL);
+
+   ck_assert(!cancel_ran);
+   ck_assert_int_eq(1, ran);
+   ck_assert(!eina_promise_owner_cancelled_is(owner));
+   ck_assert(!eina_promise_pending_is(promise));
+   ck_assert_int_eq(0, eina_promise_error_get(promise));
+
+   eina_promise_cancel(promise);
+
+   // The conditions should not have been changed.
+   ck_assert(!cancel_ran);
+   ck_assert_int_eq(1, ran);
+   ck_assert(!eina_promise_owner_cancelled_is(owner));
+   ck_assert(!eina_promise_pending_is(promise));
+   ck_assert_int_eq(0, eina_promise_error_get(promise));
+
+   eina_promise_unref(promise);
+
+   eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_test_promise_double_cancel_promise)
+{
+   Eina_Bool ran = EINA_FALSE, cancel_ran = EINA_FALSE;
+   Eina_Promise_Owner* owner;
+   Eina_Promise* promise;
+
+   eina_init();
+
+   owner = eina_promise_value_add(0);
+   eina_promise_owner_default_cancel_cb_add(owner, &cancel_callback, 
&cancel_ran, NULL);
+
+   promise = eina_promise_owner_promise_get(owner);
+
+   eina_promise_then(promise, NULL, &_cancel_promise_callback, &ran);
+
+   eina_promise_cancel(promise);
+
+   ck_assert(cancel_ran && ran);
+   ck_assert(eina_promise_owner_cancelled_is(owner));
+   ck_assert(!eina_promise_pending_is(promise));
+   ck_assert_int_eq(EINA_ERROR_PROMISE_CANCEL, 
eina_promise_error_get(promise));
+
+   cancel_ran = EINA_FALSE;
+   ran = EINA_FALSE;
+
+   eina_promise_cancel(promise);
+
+   ck_assert(!cancel_ran && !ran);
+   ck_assert(eina_promise_owner_cancelled_is(owner));
+   ck_assert(!eina_promise_pending_is(promise));
+
+   // Finally free the owner
+   eina_promise_owner_value_set(owner, NULL, NULL);
 
    eina_shutdown();
 }
@@ -420,6 +544,36 @@ START_TEST(eina_test_pointer_promise_normal_lifetime_all)
 }
 END_TEST
 
+START_TEST(eina_test_pointer_promise_error_set)
+{
+   Eina_Promise_Owner* promise_owner;
+   Eina_Promise* promise;
+   int ran = 0;
+   int error = 0xdeadbeef;
+
+   eina_init();
+
+   promise_owner = eina_promise_add();
+
+   promise = eina_promise_owner_promise_get(promise_owner);
+
+   eina_promise_ref(promise);
+
+   eina_promise_then(promise, NULL, &_eina_test_error_cb, &ran);
+
+   eina_promise_owner_error_set(promise_owner, error);
+
+   ck_assert(ran == error);
+   ck_assert_int_eq(error, eina_promise_error_get(promise));
+   ck_assert(!eina_promise_pending_is(promise));
+   ck_assert(!eina_promise_owner_cancelled_is(promise_owner));
+
+   eina_promise_unref(promise);
+
+   eina_shutdown();
+}
+END_TEST
+
 START_TEST(eina_test_pointer_promise_immediate_set_lifetime)
 {
    Eina_Promise_Owner* owner;
@@ -526,6 +680,84 @@ START_TEST(eina_test_pointer_promise_cancel_promise)
 }
 END_TEST
 
+START_TEST(eina_test_pointer_promise_cancel_finished_promise)
+{
+   Eina_Bool cancel_ran = EINA_FALSE;
+   int ran = 0;
+   Eina_Promise_Owner* owner;
+   Eina_Promise* promise;
+
+   eina_init();
+
+   owner = eina_promise_add();
+   eina_promise_owner_default_cancel_cb_add(owner, &cancel_callback, 
&cancel_ran, NULL);
+
+   promise = eina_promise_owner_promise_get(owner);
+
+   eina_promise_then(promise, &_cancel_then_callback, &_cancel_error_callback, 
&ran);
+
+   eina_promise_ref(promise);
+   eina_promise_owner_value_set(owner, NULL, NULL);
+
+   ck_assert(!cancel_ran);
+   ck_assert_int_eq(1, ran);
+   ck_assert(!eina_promise_owner_cancelled_is(owner));
+   ck_assert(!eina_promise_pending_is(promise));
+   ck_assert_int_eq(0, eina_promise_error_get(promise));
+
+   eina_promise_cancel(promise);
+
+   // The conditions should not have been changed.
+   ck_assert(!cancel_ran);
+   ck_assert_int_eq(1, ran);
+   ck_assert(!eina_promise_owner_cancelled_is(owner));
+   ck_assert(!eina_promise_pending_is(promise));
+   ck_assert_int_eq(0, eina_promise_error_get(promise));
+
+   eina_promise_unref(promise);
+
+   eina_shutdown();
+}
+END_TEST
+
+START_TEST(eina_test_pointer_promise_double_cancel_promise)
+{
+   Eina_Bool ran = EINA_FALSE, cancel_ran = EINA_FALSE;
+   Eina_Promise_Owner* owner;
+   Eina_Promise* promise;
+
+   eina_init();
+
+   owner = eina_promise_add();
+   eina_promise_owner_default_cancel_cb_add(owner, &cancel_callback, 
&cancel_ran, NULL);
+
+   promise = eina_promise_owner_promise_get(owner);
+
+   eina_promise_then(promise, NULL, &_cancel_promise_callback, &ran);
+
+   eina_promise_cancel(promise);
+
+   ck_assert(cancel_ran && ran);
+   ck_assert(eina_promise_owner_cancelled_is(owner));
+   ck_assert(!eina_promise_pending_is(promise));
+   ck_assert_int_eq(EINA_ERROR_PROMISE_CANCEL, 
eina_promise_error_get(promise));
+
+   cancel_ran = EINA_FALSE;
+   ran = EINA_FALSE;
+
+   eina_promise_cancel(promise);
+
+   ck_assert(!cancel_ran && !ran);
+   ck_assert(eina_promise_owner_cancelled_is(owner));
+   ck_assert(!eina_promise_pending_is(promise));
+
+   // Finally free the owner
+   eina_promise_owner_value_set(owner, NULL, NULL);
+
+   eina_shutdown();
+}
+END_TEST 
+
 START_TEST(eina_test_pointer_promise_progress)
 {
    Eina_Bool progress_ran = EINA_FALSE;
@@ -668,10 +900,14 @@ eina_test_promise(TCase *tc)
 {
    tcase_add_test(tc, eina_test_promise_normal_lifetime);
    tcase_add_test(tc, eina_test_promise_normal_lifetime_all);
+   tcase_add_test(tc, eina_test_promise_error_set);
+   /* tcase_add_test(tc, eina_test_promise_error_set_all); */
    tcase_add_test(tc, eina_test_promise_immediate_set_lifetime);
    tcase_add_test(tc, eina_test_promise_immediate_set_lifetime_all);
    tcase_add_test(tc, eina_test_promise_values_all);
    tcase_add_test(tc, eina_test_promise_cancel_promise);
+   tcase_add_test(tc, eina_test_promise_cancel_finished_promise);
+   tcase_add_test(tc, eina_test_promise_double_cancel_promise);
    tcase_add_test(tc, eina_test_promise_progress);
    tcase_add_test(tc, eina_test_promise_progress_notify1);
    tcase_add_test(tc, eina_test_promise_progress_notify2);
@@ -681,10 +917,13 @@ eina_test_promise(TCase *tc)
    // pointer
    tcase_add_test(tc, eina_test_pointer_promise_normal_lifetime);
    tcase_add_test(tc, eina_test_pointer_promise_normal_lifetime_all);
+   tcase_add_test(tc, eina_test_pointer_promise_error_set);
    tcase_add_test(tc, eina_test_pointer_promise_immediate_set_lifetime);
    tcase_add_test(tc, eina_test_pointer_promise_immediate_set_lifetime_all);
    tcase_add_test(tc, eina_test_pointer_promise_values_all);
    tcase_add_test(tc, eina_test_pointer_promise_cancel_promise);
+   tcase_add_test(tc, eina_test_pointer_promise_cancel_finished_promise);
+   tcase_add_test(tc, eina_test_pointer_promise_double_cancel_promise);
    tcase_add_test(tc, eina_test_pointer_promise_progress);
    tcase_add_test(tc, eina_test_pointer_promise_progress_notify1);
    tcase_add_test(tc, eina_test_pointer_promise_progress_notify2);

-- 


Reply via email to