#ifdef HAVE_CONFIG_H # include #endif #include #include #include #include "eo_cxx_suite.h" START_TEST(eo_cxx_future_construct_and_destroy) { Efl_Promise *p; Efl_Future *f; ecore_init(); { p = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p); f = efl_promise_future_get(p); fail_if(!f); efl::shared_future future(efl_ref(f)); } ecore_shutdown(); } END_TEST START_TEST(eo_cxx_future_wait) { Efl_Promise *p; Efl_Future *f; ecore_init(); p = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p); f = efl_promise_future_get(p); fail_if(!f); { efl::shared_future future(efl_ref(f)); std::thread thread([&] { efl::ecore::main_loop_thread_safe_call_sync([]{}); // wait for ecore_main_loop_begin() call to start efl::ecore::main_loop_thread_safe_call_async ([&] { int* i = static_cast(malloc(sizeof(int))); *i = 5; efl_promise_value_set(p, i, & ::free); }); future.wait(); efl::ecore::main_loop_thread_safe_call_sync([] { ecore_main_loop_quit(); }); }); ecore_main_loop_begin(); thread.join(); } ecore_shutdown(); } END_TEST START_TEST(eo_cxx_future_get) { Efl_Promise *p; Efl_Future *f; ecore_init(); p = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p); f = efl_promise_future_get(p); fail_if(!f); { efl::shared_future future(efl_ref(f)); std::thread thread([&] { efl::ecore::main_loop_thread_safe_call_sync([]{}); // wait for ecore_main_loop_begin() call to start efl::ecore::main_loop_thread_safe_call_async ([&] { int* i = static_cast(malloc(sizeof(int))); *i = 5; efl_promise_value_set(p, i, & ::free); }); int i = future.get(); ck_assert_int_eq(i, 5); efl::ecore::main_loop_thread_safe_call_sync([] { ecore_main_loop_quit(); }); }); ecore_main_loop_begin(); thread.join(); } ecore_shutdown(); } END_TEST START_TEST(eo_cxx_future_get_error) { Efl_Promise *p; Efl_Future *f; ecore_init(); p = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p); f = efl_promise_future_get(p); fail_if(!f); { efl::shared_future future(efl_ref(f)); std::thread thread([&] { efl::ecore::main_loop_thread_safe_call_sync([]{}); // wait for ecore_main_loop_begin() call to start efl::ecore::main_loop_thread_safe_call_async ([&] { efl_promise_failed_set(p, ENOMEM); }); try { future.get(); ck_abort_msg("Execution should not have continued, exception expected"); } catch(std::system_error const& e) { } efl::ecore::main_loop_thread_safe_call_sync([] { ecore_main_loop_quit(); }); }); ecore_main_loop_begin(); thread.join(); } ecore_shutdown(); } END_TEST START_TEST(eo_cxx_future_then_value) { Efl_Promise *promise; Efl_Future *f; ecore_init(); promise = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!promise); f = efl_promise_future_get(promise); fail_if(!f); { efl::shared_future future(efl_ref(f)), rfuture; std::thread thread ([&] { efl::ecore::main_loop_thread_safe_call_sync ([&] { rfuture = then (future, [] (int i) -> int { ck_assert_int_eq(i, 5); return 42; }, [] (std::error_code) { throw std::bad_alloc(); }); }); efl::ecore::main_loop_thread_safe_call_async ([&] { int* i = static_cast(malloc(sizeof(int))); *i = 5; efl_promise_value_set(promise, i, &::free); }); int i = rfuture.get(); ck_assert_int_eq(i, 42); efl::ecore::main_loop_thread_safe_call_sync([] { ecore_main_loop_quit(); }); }); ecore_main_loop_begin(); thread.join(); } ecore_shutdown(); } END_TEST START_TEST(eo_cxx_future_composite_construct_and_destroy) { ecore_init(); { Efl_Promise *p1 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p1); Efl_Future *f1 = efl_promise_future_get(p1); fail_if(!f1); Efl_Promise *p2 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p1); Efl_Future *f2 = efl_promise_future_get(p2); fail_if(!f2); Efl_Future *f3 = efl_future_all(f1, f2); fail_if(!f3); efl::shared_future future1(efl_ref(f1)) , future2(efl_ref(f2)); efl::shared_future future3(efl_ref(f3)); } ecore_shutdown(); } END_TEST START_TEST(eo_cxx_future_composite_wait) { ecore_init(); { Efl_Promise *p1 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p1); Efl_Future* f1 = efl_promise_future_get(p1); fail_if(!f1); Efl_Promise *p2 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p2); Efl_Future* f2 = efl_promise_future_get(p2); fail_if(!f2); Efl_Future *f3 = efl_future_all(f1, f2); fail_if(!f3); efl::shared_future future1(efl_ref(f1)) , future2(efl_ref(f2)); efl::shared_future future3(efl_ref(f3)); std::thread thread([&] { efl::ecore::main_loop_thread_safe_call_sync([]{}); // wait for ecore_main_loop_begin() call to start efl::ecore::main_loop_thread_safe_call_async ([&] { int* i1 = static_cast(malloc(sizeof(int))); *i1 = 5; efl_promise_value_set(p1, i1, & ::free); int* i2 = static_cast(malloc(sizeof(int))); *i2 = 42; efl_promise_value_set(p2, i2, & ::free); }); future3.wait(); efl::ecore::main_loop_thread_safe_call_sync([] { ecore_main_loop_quit(); }); }); ecore_main_loop_begin(); thread.join(); } ecore_shutdown(); } END_TEST START_TEST(eo_cxx_future_composite_get) { ecore_init(); { Efl_Promise *p1 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p1); Efl_Future *f1 = efl_promise_future_get(p1); fail_if(!f1); Efl_Promise *p2 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p2); Efl_Future *f2 = efl_promise_future_get(p2); fail_if(!f2); Efl_Future *f3 = efl_future_all(f1, f2); fail_if(!f3); efl::shared_future future1(efl_ref(f1)) , future2(efl_ref(f2)); efl::shared_future future3(efl_ref(f3)); std::thread thread([&] { efl::ecore::main_loop_thread_safe_call_sync([]{}); // wait for ecore_main_loop_begin() call to start efl::ecore::main_loop_thread_safe_call_async ([&] { int* i1 = static_cast(malloc(sizeof(int))); *i1 = 5; efl_promise_value_set(p1, i1, & ::free); int* i2 = static_cast(malloc(sizeof(int))); *i2 = 42; efl_promise_value_set(p2, i2, & ::free); }); std::tuple tuple = future3.get(); ck_assert_int_eq(std::get<0>(tuple), 5); ck_assert_int_eq(std::get<1>(tuple), 42); efl::ecore::main_loop_thread_safe_call_sync([] { ecore_main_loop_quit(); }); }); ecore_main_loop_begin(); thread.join(); } ecore_shutdown(); } END_TEST START_TEST(eo_cxx_future_composite_then_value) { ecore_init(); { Efl_Promise *p1 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p1); Efl_Future *f1 = efl_promise_future_get(p1); fail_if(!f1); Efl_Promise *p2 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p2); Efl_Future *f2 = efl_promise_future_get(p2); fail_if(!f2); Efl_Future *f3 = efl_future_all(f1, f2); fail_if(!f3); efl::shared_future future(efl_ref(f3)); efl::shared_future rfuture; std::thread thread ([&] { efl::ecore::main_loop_thread_safe_call_sync ([&] { rfuture = then (future, [] (int i1, int i2) -> int { ck_assert_int_eq(i1, 5); ck_assert_int_eq(i2, 42); return 42; }, [] (std::error_code) { throw std::bad_alloc(); }); }); efl::ecore::main_loop_thread_safe_call_async ([&] { int* i1 = static_cast(malloc(sizeof(int))); *i1 = 5; efl_promise_value_set(p1, i1, &::free); int* i2 = static_cast(malloc(sizeof(int))); *i2 = 42; efl_promise_value_set(p2, i2, &::free); }); int i; i = rfuture.get(); ck_assert_int_eq(i, 42); efl::ecore::main_loop_thread_safe_call_sync([] { ecore_main_loop_quit(); }); }); ecore_main_loop_begin(); thread.join(); } ecore_shutdown(); } END_TEST START_TEST(eo_cxx_future_all_construct_and_destroy) { ecore_init(); { Efl_Promise *p1 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p1); Efl_Future *f1 = efl_promise_future_get(p1); fail_if(!f1); Efl_Promise *p2 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p1); Efl_Future *f2 = efl_promise_future_get(p2); fail_if(!f2); Efl_Future *f3 = efl_future_all(f1, f2); fail_if(!f3); efl::shared_future future1(efl_ref(f1)) , future2(efl_ref(f2)); efl::shared_future future3 = all(future1, future2); } ecore_shutdown(); } END_TEST START_TEST(eo_cxx_future_all_wait) { ecore_init(); { Efl_Promise *p1 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p1); Efl_Future* f1 = efl_promise_future_get(p1); fail_if(!f1); Efl_Promise *p2 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p2); Efl_Future* f2 = efl_promise_future_get(p2); fail_if(!f2); efl::shared_future future1(efl_ref(f1)) , future2(efl_ref(f2)); efl::shared_future future3 = all(future1, future2); std::thread thread([&] { efl::ecore::main_loop_thread_safe_call_sync([]{}); // wait for ecore_main_loop_begin() call to start efl::ecore::main_loop_thread_safe_call_async ([&] { int* i1 = static_cast(malloc(sizeof(int))); *i1 = 5; efl_promise_value_set(p1, i1, & ::free); int* i2 = static_cast(malloc(sizeof(int))); *i2 = 42; efl_promise_value_set(p2, i2, & ::free); }); future3.wait(); efl::ecore::main_loop_thread_safe_call_sync([] { ecore_main_loop_quit(); }); }); ecore_main_loop_begin(); thread.join(); } ecore_shutdown(); } END_TEST START_TEST(eo_cxx_future_all_get) { ecore_init(); { Efl_Promise *p1 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p1); Efl_Future *f1 = efl_promise_future_get(p1); fail_if(!f1); Efl_Promise *p2 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p2); Efl_Future *f2 = efl_promise_future_get(p2); fail_if(!f2); efl::shared_future future1(efl_ref(f1)) , future2(efl_ref(f2)); efl::shared_future future3 = all(future1, future2); std::thread thread([&] { efl::ecore::main_loop_thread_safe_call_sync([]{}); // wait for ecore_main_loop_begin() call to start efl::ecore::main_loop_thread_safe_call_async ([&] { int* i1 = static_cast(malloc(sizeof(int))); *i1 = 5; efl_promise_value_set(p1, i1, & ::free); int* i2 = static_cast(malloc(sizeof(int))); *i2 = 42; efl_promise_value_set(p2, i2, & ::free); }); std::tuple tuple = future3.get(); ck_assert_int_eq(std::get<0>(tuple), 5); ck_assert_int_eq(std::get<1>(tuple), 42); efl::ecore::main_loop_thread_safe_call_sync([] { ecore_main_loop_quit(); }); }); ecore_main_loop_begin(); thread.join(); } ecore_shutdown(); } END_TEST START_TEST(eo_cxx_future_all_then_value) { ecore_init(); { Efl_Promise *p1 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p1); Efl_Future *f1 = efl_promise_future_get(p1); fail_if(!f1); Efl_Promise *p2 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p2); Efl_Future *f2 = efl_promise_future_get(p2); fail_if(!f2); efl::shared_future future1(efl_ref(f1)), future2(efl_ref(f2)); efl::shared_future future = all(future1, future2); efl::shared_future rfuture; std::thread thread ([&] { efl::ecore::main_loop_thread_safe_call_sync ([&] { rfuture = then (future, [] (int i1, int i2) -> int { ck_assert_int_eq(i1, 5); ck_assert_int_eq(i2, 42); return 42; }, [] (std::error_code) { throw std::bad_alloc(); }); }); efl::ecore::main_loop_thread_safe_call_async ([&] { int* i1 = static_cast(malloc(sizeof(int))); *i1 = 5; efl_promise_value_set(p1, i1, &::free); int* i2 = static_cast(malloc(sizeof(int))); *i2 = 42; efl_promise_value_set(p2, i2, &::free); }); int i; i = rfuture.get(); ck_assert_int_eq(i, 42); efl::ecore::main_loop_thread_safe_call_sync([] { ecore_main_loop_quit(); }); }); ecore_main_loop_begin(); thread.join(); } ecore_shutdown(); } END_TEST // race START_TEST(eo_cxx_future_race_construct_and_destroy) { ecore_init(); { Efl_Promise *p1 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p1); Efl_Future *f1 = efl_promise_future_get(p1); fail_if(!f1); Efl_Promise *p2 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p1); Efl_Future *f2 = efl_promise_future_get(p2); fail_if(!f2); efl::shared_future future1(efl_ref(f1)), future2(efl_ref(f2)); efl::shared_future future3(efl_ref(f2)); efl::shared_race_future race1 = race(future1, future2); efl::shared_race_future> race2 = race(future1, future3); } ecore_shutdown(); } END_TEST START_TEST(eo_cxx_future_race_wait) { ecore_init(); { Efl_Promise *p1 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p1); Efl_Future* f1 = efl_promise_future_get(p1); fail_if(!f1); Efl_Promise *p2 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p2); Efl_Future* f2 = efl_promise_future_get(p2); fail_if(!f2); efl::shared_future future1(efl_ref(f1)) , future2(efl_ref(f2)); efl::shared_race_future future3 = race(future1, future2); std::thread thread([&] { efl::ecore::main_loop_thread_safe_call_sync([]{}); // wait for ecore_main_loop_begin() call to start efl::ecore::main_loop_thread_safe_call_async ([&] { int* i1 = static_cast(malloc(sizeof(int))); *i1 = 5; efl_promise_value_set(p1, i1, & ::free); }); future3.wait(); efl::ecore::main_loop_thread_safe_call_sync([] { ecore_main_loop_quit(); }); }); ecore_main_loop_begin(); thread.join(); } ecore_shutdown(); } END_TEST START_TEST(eo_cxx_future_race_get) { ecore_init(); { Efl_Promise *p1 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p1); Efl_Future *f1 = efl_promise_future_get(p1); fail_if(!f1); Efl_Promise *p2 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p2); Efl_Future *f2 = efl_promise_future_get(p2); fail_if(!f2); efl::shared_future future1(efl_ref(f1)) , future2(efl_ref(f2)); efl::shared_race_future future3 = race(future1, future2); std::thread thread([&] { efl::ecore::main_loop_thread_safe_call_sync([]{}); // wait for ecore_main_loop_begin() call to start efl::ecore::main_loop_thread_safe_call_async ([&] { int* i1 = static_cast(malloc(sizeof(int))); *i1 = 5; efl_promise_value_set(p1, i1, & ::free); }); int value = future3.get(); ck_assert_int_eq(value, 5); efl::ecore::main_loop_thread_safe_call_sync([] { ecore_main_loop_quit(); }); }); ecore_main_loop_begin(); thread.join(); } ecore_shutdown(); } END_TEST START_TEST(eo_cxx_future_race_then_value) { ecore_init(); { Efl_Promise *p1 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p1); Efl_Future *f1 = efl_promise_future_get(p1); fail_if(!f1); Efl_Promise *p2 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p2); Efl_Future *f2 = efl_promise_future_get(p2); fail_if(!f2); efl::shared_future future1(efl_ref(f1)), future2(efl_ref(f2)); efl::shared_race_future future = race(future1, future2); efl::shared_future rfuture; std::thread thread ([&] { efl::ecore::main_loop_thread_safe_call_sync ([&] { rfuture = then (future, [] (int i) -> int { ck_assert_int_eq(i, 5); return 42; }, [] (std::error_code) { throw std::bad_alloc(); }); }); efl::ecore::main_loop_thread_safe_call_async ([&] { int* i1 = static_cast(malloc(sizeof(int))); *i1 = 5; efl_promise_value_set(p1, i1, &::free); }); int i; i = rfuture.get(); ck_assert_int_eq(i, 42); efl::ecore::main_loop_thread_safe_call_sync([] { ecore_main_loop_quit(); }); }); ecore_main_loop_begin(); thread.join(); } ecore_shutdown(); } END_TEST START_TEST(eo_cxx_future_race_variant_get) { ecore_init(); { Efl_Promise *p1 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p1); Efl_Future *f1 = efl_promise_future_get(p1); fail_if(!f1); Efl_Promise *p2 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p2); Efl_Future *f2 = efl_promise_future_get(p2); fail_if(!f2); efl::shared_future future1(efl_ref(f1)); efl::shared_future future2(efl_ref(f2)); efl::shared_race_future> future3 = race(future1, future2); std::thread thread([&] { efl::ecore::main_loop_thread_safe_call_sync([]{}); // wait for ecore_main_loop_begin() call to start efl::ecore::main_loop_thread_safe_call_async ([&] { int* i1 = static_cast(malloc(sizeof(int))); *i1 = 5; efl_promise_value_set(p1, i1, & ::free); }); efl::eina::variant value = future3.get(); ck_assert(efl::eina::get(&value) != nullptr); ck_assert_int_eq(efl::eina::get(value), 5); efl::ecore::main_loop_thread_safe_call_sync([] { ecore_main_loop_quit(); }); }); ecore_main_loop_begin(); thread.join(); } ecore_shutdown(); } END_TEST START_TEST(eo_cxx_future_race_variant_then_value) { ecore_init(); { Efl_Promise *p1 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p1); Efl_Future *f1 = efl_promise_future_get(p1); fail_if(!f1); Efl_Promise *p2 = efl_add(EFL_PROMISE_CLASS, ecore_main_loop_get()); fail_if(!p2); Efl_Future *f2 = efl_promise_future_get(p2); fail_if(!f2); efl::shared_future future1(efl_ref(f1)); efl::shared_future future2(efl_ref(f2)); efl::shared_race_future> future = race(future1, future2); efl::shared_future rfuture; std::thread thread ([&] { efl::ecore::main_loop_thread_safe_call_sync ([&] { rfuture = then (future, [] (efl::eina::variant v) -> int { ck_assert(efl::eina::get(&v) != nullptr); ck_assert_int_eq(efl::eina::get(v), 5); return 42; }, [] (std::error_code) { throw std::bad_alloc(); }); }); efl::ecore::main_loop_thread_safe_call_async ([&] { int* i1 = static_cast(malloc(sizeof(int))); *i1 = 5; efl_promise_value_set(p1, i1, &::free); }); int i; i = rfuture.get(); ck_assert_int_eq(i, 42); efl::ecore::main_loop_thread_safe_call_sync([] { ecore_main_loop_quit(); }); }); ecore_main_loop_begin(); thread.join(); } ecore_shutdown(); } END_TEST template void eo_cxx_promise_construct_and_destroy_impl() { ecore_init(); { efl::promise promise; efl::shared_future f = promise.get_future(); } ecore_shutdown(); } START_TEST(eo_cxx_promise_construct_and_destroy) { eo_cxx_promise_construct_and_destroy_impl(); } END_TEST template struct test_value_get; template <> struct test_value_get { static int get() { return 5; } }; template void eo_cxx_promise_value_set_impl() { ecore_init(); { efl::promise promise; efl::shared_future f = promise.get_future(); std::thread thread ([&] { efl::ecore::main_loop_thread_safe_call_sync([]{}); // wait for ecore_main_loop_begin() call to start efl::ecore::main_loop_thread_safe_call_async ([&] { promise.set_value(test_value_get::get()); }); T value = f.get(); ck_assert_int_eq(value, test_value_get::get()); efl::ecore::main_loop_thread_safe_call_sync([] { ecore_main_loop_quit(); }); }); ecore_main_loop_begin(); thread.join(); } ecore_shutdown(); } START_TEST(eo_cxx_promise_value_set) { eo_cxx_promise_value_set_impl(); } END_TEST void eo_cxx_test_promise(TCase* tc) { tcase_add_test(tc, eo_cxx_future_construct_and_destroy); tcase_add_test(tc, eo_cxx_future_wait); tcase_add_test(tc, eo_cxx_future_get); tcase_add_test(tc, eo_cxx_future_get_error); tcase_add_test(tc, eo_cxx_future_then_value); tcase_add_test(tc, eo_cxx_future_composite_construct_and_destroy); tcase_add_test(tc, eo_cxx_future_composite_wait); tcase_add_test(tc, eo_cxx_future_composite_get); tcase_add_test(tc, eo_cxx_future_composite_then_value); tcase_add_test(tc, eo_cxx_future_all_construct_and_destroy); tcase_add_test(tc, eo_cxx_future_all_wait); tcase_add_test(tc, eo_cxx_future_all_get); tcase_add_test(tc, eo_cxx_future_all_then_value); tcase_add_test(tc, eo_cxx_future_race_construct_and_destroy); tcase_add_test(tc, eo_cxx_future_race_wait); tcase_add_test(tc, eo_cxx_future_race_get); tcase_add_test(tc, eo_cxx_future_race_then_value); tcase_add_test(tc, eo_cxx_future_race_variant_get); tcase_add_test(tc, eo_cxx_future_race_variant_then_value); tcase_add_test(tc, eo_cxx_promise_construct_and_destroy); tcase_add_test(tc, eo_cxx_promise_value_set); }