#ifdef HAVE_CONFIG_H # include "elementary_config.h" #endif #include "efl_ui_suite.h" #include "efl_ui_homogeneous_model.eo.h" #include "efl_ui_exact_model.eo.h" #include "efl_ui_average_model.eo.h" static const int child_number = 3; static const int base_ints[] = { 41, 42, 43 }; static int expected_average[] = { 0, 0, 0 }; static Efl_Model * _generate_base_model(void) { Efl_Generic_Model *base_model, *child; Eina_Value v; int i; eina_value_setup(&v, EINA_VALUE_TYPE_INT); base_model = efl_add_ref(EFL_GENERIC_MODEL_CLASS, efl_main_loop_get()); ck_assert(!!base_model); for (i = 0; i < child_number; ++i) { child = efl_model_child_add(base_model); ck_assert(!!child); ck_assert(eina_value_set(&v, base_ints[i])); efl_model_property_set(child, "test_p_int", &v); } eina_value_flush(&v); return base_model; } static Eina_Error _property_error_expected(Efl_Model *model, const char *property) { Eina_Value *v; Eina_Error err = 0; v = efl_model_property_get(model, property); ck_assert_ptr_eq(eina_value_type_get(v), EINA_VALUE_TYPE_ERROR); ck_assert(eina_value_error_get(v, &err)); eina_value_free(v); return err; } static unsigned int _property_uint_expected(Efl_Model *model, const char *property) { Eina_Value *v; unsigned int r = 0; v = efl_model_property_get(model, property); ck_assert_ptr_eq(eina_value_type_get(v), EINA_VALUE_TYPE_UINT); ck_assert(eina_value_uint_get(v, &r)); eina_value_free(v); return r; } static Eina_Value _child_should_succeed(Efl_Model *model EINA_UNUSED, void *data EINA_UNUSED, const Eina_Value v) { ck_assert_ptr_eq(eina_value_type_get(&v), EINA_VALUE_TYPE_ARRAY); return v; } static Eina_Value _child_should_fail(Efl_Model *model EINA_UNUSED, void *data, const Eina_Value v) { unsigned int i, len; Eina_Value c = EINA_VALUE_EMPTY; EINA_VALUE_ARRAY_FOREACH(&v, len, i, c) { if (eina_value_type_get(&c) != EINA_VALUE_TYPE_ERROR) { fprintf(stderr, "Request on child %i should have failed but got '%s'\n", (int)(uintptr_t) data, eina_value_to_string(&c)); abort(); } } return eina_value_int_init(0); } static Eina_Value _total_succeed(Efl_Model *model EINA_UNUSED, void *data EINA_UNUSED, const Eina_Value v) { efl_loop_quit(efl_loop_get(model), eina_value_string_init("BOOM")); return v; } static Eina_Value _total_failed(Efl_Model *model EINA_UNUSED, void *data EINA_UNUSED, Eina_Error err) { fprintf(stderr, "Shouldn't have failed: '%s'\n", eina_error_msg_get(err)); efl_loop_quit(efl_loop_get(model), eina_value_int_init(42)); return eina_value_error_init(err); } static Eina_Value _children_homogeneous_slice_get_then(Efl_Model *model, void *data EINA_UNUSED, const Eina_Value v) { unsigned int i, len; Efl_Model *child = NULL; Eina_Future *all[4] = { NULL, NULL, NULL, EINA_FUTURE_SENTINEL }; Eina_Future *f; fail_if(eina_value_type_get(&v) != EINA_VALUE_TYPE_ARRAY); EINA_VALUE_ARRAY_FOREACH(&v, len, i, child) { ck_assert_int_eq(_property_error_expected(child, "self.width"), EAGAIN); ck_assert_int_eq(_property_error_expected(child, "self.height"), EAGAIN); } EINA_VALUE_ARRAY_FOREACH(&v, len, i, child) { Eina_Value *v; unsigned int w, h; v = efl_model_property_get(child, "test_p_int"); eina_value_uint_convert(v, &w); eina_value_uint_convert(v, &h); eina_value_free(v); w *= 2; h *= 3; all[i] = eina_future_all(efl_model_property_set(child, "self.width", eina_value_uint_new(w)), efl_model_property_set(child, "self.height", eina_value_uint_new(h))); if (i == 0) all[i] = efl_future_then(model, all[i], .success = _child_should_succeed); else all[i] = efl_future_then(model, all[i], .success = _child_should_fail, .success_type = EINA_VALUE_TYPE_ARRAY, .data = (void*)(uintptr_t) i); } f = eina_future_all_array(all); f = efl_future_then(model, f, .success = _total_succeed, .error = _total_failed); return eina_future_as_value(f); } EFL_START_TEST(efl_ui_homogeneous_model_test) { Efl_Generic_Model *base_model, *model; Eina_Value *ret__; Eina_Future *future; int real__; base_model = _generate_base_model(); model = efl_add_ref(EFL_UI_HOMOGENEOUS_MODEL_CLASS, efl_main_loop_get(), efl_ui_view_model_set(efl_added, base_model)); ck_assert(!!model); future = efl_model_children_slice_get(model, 0, efl_model_children_count_get(model)); efl_future_then(model, future, .success = _children_homogeneous_slice_get_then); ck_assert_int_eq(_property_error_expected(model, "total.width"), EAGAIN); ck_assert_int_eq(_property_error_expected(model, "total.height"), EAGAIN); ck_assert_int_eq(_property_error_expected(model, "item.width"), EAGAIN); ck_assert_int_eq(_property_error_expected(model, "item.height"), EAGAIN); ret__ = efl_loop_begin(efl_app_main_get()); real__ = efl_loop_exit_code_process(ret__); fail_if(real__ != 0); ck_assert_int_eq(_property_uint_expected(model, "total.width"), base_ints[0] * 2); ck_assert_int_eq(_property_uint_expected(model, "total.height"), base_ints[0] * 3 * 3); ck_assert_int_eq(_property_uint_expected(model, "item.width"), base_ints[0] * 2); ck_assert_int_eq(_property_uint_expected(model, "item.height"), base_ints[0] * 3); } EFL_END_TEST static Eina_Value _children_exact_slice_get_then(Efl_Model *model, void *data EINA_UNUSED, const Eina_Value v) { unsigned int i, len; Efl_Model *child = NULL; Eina_Future *all[4] = { NULL, NULL, NULL, EINA_FUTURE_SENTINEL }; Eina_Future *f; fail_if(eina_value_type_get(&v) != EINA_VALUE_TYPE_ARRAY); EINA_VALUE_ARRAY_FOREACH(&v, len, i, child) { ck_assert_int_eq(_property_uint_expected(child, "self.width"), 0); ck_assert_int_eq(_property_uint_expected(child, "self.height"), 0); } EINA_VALUE_ARRAY_FOREACH(&v, len, i, child) { Eina_Value *v; unsigned int w, h; v = efl_model_property_get(child, "test_p_int"); eina_value_uint_convert(v, &w); eina_value_uint_convert(v, &h); eina_value_free(v); w *= 2; h *= 3; all[i] = eina_future_all(efl_model_property_set(child, "self.width", eina_value_uint_new(w)), efl_model_property_set(child, "self.height", eina_value_uint_new(h))); all[i] = efl_future_then(model, all[i], .success = _child_should_succeed); } f = eina_future_all_array(all); f = efl_future_then(model, f, .success = _total_succeed, .error = _total_failed); return eina_future_as_value(f); } EFL_START_TEST(efl_ui_exact_model_test) { Efl_Generic_Model *base_model, *model; Eina_Future *future; Eina_Value *ret__; int real__; base_model = _generate_base_model(); model = efl_add_ref(EFL_UI_EXACT_MODEL_CLASS, efl_main_loop_get(), efl_ui_view_model_set(efl_added, base_model)); ck_assert(!!model); future = efl_model_children_slice_get(model, 0, efl_model_children_count_get(model)); efl_future_then(model, future, .success = _children_exact_slice_get_then); ck_assert_int_eq(_property_uint_expected(model, "total.width"), 0); ck_assert_int_eq(_property_uint_expected(model, "total.height"), 0); ck_assert_int_eq(_property_error_expected(model, "item.width"), EAGAIN); ck_assert_int_eq(_property_error_expected(model, "item.height"), EAGAIN); ret__ = efl_loop_begin(efl_app_main_get()); real__ = efl_loop_exit_code_process(ret__); fail_if(real__ != 0); ck_assert_int_eq(_property_uint_expected(model, "total.width"), base_ints[2] * 2); ck_assert_int_eq(_property_uint_expected(model, "total.height"), base_ints[0] * 3 + base_ints[1] * 3 + base_ints[2] * 3); } EFL_END_TEST static Eina_Value _child_updated_average(Efl_Model *model, void *data, const Eina_Value v) { Eina_Value *r; int *ex = data; int got = 0; r = efl_model_property_get(model, "total.height"); ck_assert(eina_value_int_convert(r, &got)); ck_assert_int_eq(got, *ex); eina_value_free(r); return v; } static Eina_Value _children_average_slice_get_then(Efl_Model *model, void *data EINA_UNUSED, const Eina_Value v) { unsigned int i, len; Efl_Model *child = NULL; Eina_Future *all[4] = { NULL, NULL, NULL, EINA_FUTURE_SENTINEL }; Eina_Future *f; fail_if(eina_value_type_get(&v) != EINA_VALUE_TYPE_ARRAY); EINA_VALUE_ARRAY_FOREACH(&v, len, i, child) { ck_assert_int_eq(_property_uint_expected(child, "self.width"), 0); ck_assert_int_eq(_property_uint_expected(child, "self.height"), 0); } EINA_VALUE_ARRAY_FOREACH(&v, len, i, child) { Eina_Value *v; unsigned int w, h; v = efl_model_property_get(child, "test_p_int"); eina_value_uint_convert(v, &w); eina_value_uint_convert(v, &h); eina_value_free(v); w *= 2; h *= 3; all[i] = eina_future_all(efl_model_property_set(child, "self.width", eina_value_uint_new(w)), efl_model_property_set(child, "self.height", eina_value_uint_new(h))); all[i] = efl_future_then(model, all[i], .success = _child_should_succeed); // The model average is not updated until the property have succeeded, so we have // to wait before we can fetch the property. all[i] = efl_future_then(model, all[i], .success = _child_updated_average, .data = &expected_average[i]); } f = eina_future_all_array(all); f = efl_future_then(model, f, .success = _total_succeed, .error = _total_failed); return eina_future_as_value(f); } EFL_START_TEST(efl_ui_average_model_test) { Efl_Generic_Model *base_model, *model; Eina_Future *future; Eina_Value *ret__; int real__; base_model = _generate_base_model(); model = efl_add_ref(EFL_UI_AVERAGE_MODEL_CLASS, efl_main_loop_get(), efl_ui_view_model_set(efl_added, base_model)); ck_assert(!!model); future = efl_model_children_slice_get(model, 0, efl_model_children_count_get(model)); efl_future_then(model, future, .success = _children_average_slice_get_then); ck_assert_int_eq(_property_uint_expected(model, "total.width"), 0); ck_assert_int_eq(_property_uint_expected(model, "total.height"), 0); ck_assert_int_eq(_property_error_expected(model, "item.width"), EAGAIN); ck_assert_int_eq(_property_error_expected(model, "item.height"), EAGAIN); ret__ = efl_loop_begin(efl_app_main_get()); real__ = efl_loop_exit_code_process(ret__); fail_if(real__ != 0); ck_assert_int_eq(_property_uint_expected(model, "total.width"), base_ints[2] * 2); ck_assert_int_eq(_property_uint_expected(model, "total.height"), base_ints[0] * 3 + base_ints[1] * 3 + base_ints[2] * 3); } EFL_END_TEST void efl_ui_model(TCase *tc) { // This is done here as some system can not initialize computed value from another data at compile time. expected_average[0] = base_ints[0] * 3 * 3; expected_average[1] = ((base_ints[0] * 3 + base_ints[1] * 3) * 3) / 2; expected_average[2] = base_ints[0] * 3 + base_ints[1] * 3 + base_ints[2] * 3; tcase_add_test(tc, efl_ui_homogeneous_model_test); tcase_add_test(tc, efl_ui_average_model_test); tcase_add_test(tc, efl_ui_exact_model_test); }