From 8f7fc2e6579e305872588ecf4f84026fedf7f05b Mon Sep 17 00:00:00 2001 From: Roman Marchenko Date: Thu, 23 Nov 2017 19:04:23 +0200 Subject: [PATCH 01/16] add excluding coverage comments for tdm_helper.c add excluding coverage comments for tdm_helper.c for folowing code: - inner function; - deprecated function; Change-Id: I9b4fb790bd3576fc0bc6a5e76579f74fbb817105 Signed-off-by: Roman Marchenko --- src/tdm_helper.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/tdm_helper.c b/src/tdm_helper.c index bcd7aec..74d8bb5 100644 --- a/src/tdm_helper.c +++ b/src/tdm_helper.c @@ -207,6 +207,7 @@ _tdm_helper_dump_png(const char *file, const void *data, int width, fclose(fp); } +/* LCOV_EXCL_START */ INTERN char * tdm_helper_dump_make_directory(const char *path, char *reply, int *len) { @@ -272,6 +273,7 @@ tdm_helper_dump_buffer_str(tbm_surface_h buffer, char *dir, char *str) tdm_helper_dump_buffer(buffer, file); } +/* LCOV_EXCL_STOP */ EXTERN void tdm_helper_dump_buffer(tbm_surface_h buffer, const char *file) @@ -578,6 +580,7 @@ unmap_srcbuf: return ret; } +/* LCOV_EXCL_START */ EXTERN int tdm_helper_get_fd(const char *env) { @@ -599,6 +602,7 @@ tdm_helper_set_fd(const char *env, int fd) tbm_drm_helper_set_tbm_master_fd(fd); } +/* LCOV_EXCL_STOP */ EXTERN void tdm_helper_dump_start(char *dumppath, int *count) @@ -621,6 +625,7 @@ tdm_helper_dump_stop(void) TDM_DBG("tdm_helper_dump stop."); } +/* LCOV_EXCL_START */ static tdm_error _tdm_helper_buffer_convert(tbm_surface_h srcbuf, tbm_surface_h dstbuf, int dx, int dy, int dw, int dh, int count) @@ -708,6 +713,8 @@ cant_convert: return TDM_ERROR_OPERATION_FAILED; } +/* LCOV_EXCL_STOP */ + EXTERN tdm_error tdm_helper_capture_output(tdm_output *output, tbm_surface_h dst_buffer, @@ -1061,6 +1068,7 @@ tdm_helper_get_display_information(tdm_display *dpy, char *reply, int *len) TDM_SNPRINTF(reply, len, "\n"); } +/* LCOV_EXCL_START */ EXTERN int tdm_helper_commit_per_vblank_enabled(tdm_display *dpy) { @@ -1068,6 +1076,7 @@ tdm_helper_commit_per_vblank_enabled(tdm_display *dpy) return 0; } +/* LCOV_EXCL_STOP */ EXTERN int tdm_helper_output_commit_per_vblank_enabled(tdm_output *output) -- 2.7.4 From a2e571d41a5c41c16165ca4b0bab9139d5c2e39a Mon Sep 17 00:00:00 2001 From: Andrii Sokolenko Date: Fri, 24 Nov 2017 10:45:59 +0200 Subject: [PATCH 02/16] utest: Fix warning of incorrect 64bits type casting Change-Id: Ic0ab8db296a8295425da1ffc44d1bced023daea1 Signed-off-by: Andrii Sokolenko --- utests/src/ut_tdm_output.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/utests/src/ut_tdm_output.cpp b/utests/src/ut_tdm_output.cpp index effb32f..be7d0b3 100644 --- a/utests/src/ut_tdm_output.cpp +++ b/utests/src/ut_tdm_output.cpp @@ -49,7 +49,7 @@ protected: tdm_value value, void *u_data) { - if ( ((int) u_data) < -100) { + if ( ((intptr_t) u_data) < -100) { TDMOutput::handle_call++; } } @@ -375,7 +375,7 @@ TEST_F(TDMOutput, OutputAddChangeHandlerSuccessfulFewFuncs) if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) continue; checked = true; - for (int k = 0; k < 20; k++) { + for (intptr_t k = 0; k < 20; k++) { ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_add_change_handler(output, tdm_output_change_handler_test_func, (void *) (-101-k))); @@ -463,7 +463,7 @@ TEST_F(TDMOutput, OutputRemoveChangeHandlerSuccessfulFewFuncs) if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) continue; checked = true; - for (int k = 0; k < 20; k++) { + for (intptr_t k = 0; k < 20; k++) { ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_add_change_handler(output, tdm_output_change_handler_test_func, (void *) (-101-k))); @@ -472,7 +472,7 @@ TEST_F(TDMOutput, OutputRemoveChangeHandlerSuccessfulFewFuncs) ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_OFF)); ASSERT_GT(handle_call, 20); handle_call = 0; - for (int k = 0; k < 20; k++) { + for (intptr_t k = 0; k < 20; k++) { tdm_output_remove_change_handler(output, tdm_output_change_handler_test_func, (void *) (-101-k)); } ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_ON)); -- 2.7.4 From 6fc6a8ec3d14782e56dfbdf6b96acdf909fe4732 Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Sun, 26 Nov 2017 13:43:10 +0900 Subject: [PATCH 03/16] package version up to 1.9.0 Change-Id: Iaa50a2ba6a8a4fc5b45ea920be480ed7d1a4a657 --- packaging/libtdm.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index f83d628..d68ef56 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -1,7 +1,7 @@ %define UTEST_PACKAGE 1 Name: libtdm -Version: 1.8.4 +Version: 1.9.0 Release: 0 Summary: User Library of Tizen Display Manager Group: Development/Libraries -- 2.7.4 From bed36e3c270d7b5610425283d1eee779072b8ca9 Mon Sep 17 00:00:00 2001 From: Konstantin Drabeniuk Date: Fri, 24 Nov 2017 12:44:14 +0200 Subject: [PATCH 04/16] add excluding coverage comments for tdm_monitor_server.c and tdm_output.c add excluding coverage comments for tdm_monitor_server.c for all file. add excluding coverage comments for tdm_output.c for folowing code: - dump; - calloc fail; - fail if the backend's function don't exist; - fail in the backend's function - tdm_output_set_dpms_async() - fail if there is not capability; Change-Id: I7541c992ddc2f9ea5bb18ab77e97de2a3ed2cf28 Signed-off-by: Konstantin Drabeniuk --- src/tdm_monitor_server.c | 2 ++ src/tdm_output.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/src/tdm_monitor_server.c b/src/tdm_monitor_server.c index 0d92cef..ea56a8b 100644 --- a/src/tdm_monitor_server.c +++ b/src/tdm_monitor_server.c @@ -45,6 +45,7 @@ #define TDM_DBG_SERVER_ARGS_MAX 32 +/* LCOV_EXCL_START */ static void _tdm_monitor_server_usage(char *app_name, char *reply, int *len); static void @@ -702,3 +703,4 @@ tdm_monitor_server_command(tdm_display *dpy, const char *options, char *reply, i _tdm_monitor_server_command(pid, cwd, dpy, argc, argv, reply, len); } +/* LCOV_EXCL_STOP */ diff --git a/src/tdm_output.c b/src/tdm_output.c index 078946a..855c352 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -127,6 +127,7 @@ tdm_output_get_conn_status(tdm_output *output, tdm_output_conn_status *status) return ret; } +/* LCOV_EXCL_START */ static void _tdm_output_update(tdm_output *output_backend, void *user_data) { @@ -192,6 +193,7 @@ tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status, TDM_OUTPUT_CHANGE_CONNECTION, value, 0); } +/* LCOV_EXCL_STOP */ EXTERN tdm_error tdm_output_add_change_handler(tdm_output *output, @@ -207,9 +209,11 @@ tdm_output_add_change_handler(tdm_output *output, change_handler = calloc(1, sizeof(tdm_private_change_handler)); if (!change_handler) { + /* LCOV_EXCL_START */ TDM_ERR("failed: alloc memory"); _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_OUT_OF_MEMORY; + /* LCOV_EXCL_STOP */ } change_handler->private_output = private_output; @@ -536,9 +540,11 @@ tdm_output_set_property(tdm_output *output, unsigned int id, tdm_value value) func_output = &private_display->func_output; if (!func_output->output_set_property) { + /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; + /* LCOV_EXCL_STOP */ } ret = func_output->output_set_property(private_output->output_backend, id, @@ -562,9 +568,11 @@ tdm_output_get_property(tdm_output *output, unsigned int id, tdm_value *value) func_output = &private_display->func_output; if (!func_output->output_get_property) { + /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; + /* LCOV_EXCL_STOP */ } ret = func_output->output_get_property(private_output->output_backend, id, @@ -734,8 +742,10 @@ _tdm_output_wait_vblank(tdm_output *output, int interval, int sync, interval = 1; if (!func_output->output_wait_vblank) { + /* LCOV_EXCL_START */ TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; + /* LCOV_EXCL_STOP */ } if (!private_output->regist_vblank_cb) { @@ -746,8 +756,10 @@ _tdm_output_wait_vblank(tdm_output *output, int interval, int sync, vblank_handler = calloc(1, sizeof(tdm_private_vblank_handler)); if (!vblank_handler) { + /* LCOV_EXCL_START */ TDM_ERR("failed: alloc memory"); return TDM_ERROR_OUT_OF_MEMORY; + /* LCOV_EXCL_STOP */ } if (tdm_debug_module & TDM_DEBUG_COMMIT) @@ -785,11 +797,13 @@ _tdm_output_wait_vblank(tdm_output *output, int interval, int sync, return ret; wait_failed: + /* LCOV_EXCL_START */ if (vblank_handler) { LIST_DEL(&vblank_handler->link); free(vblank_handler); } return ret; + /* LCOV_EXCL_STOP */ } EXTERN tdm_error @@ -814,6 +828,7 @@ tdm_output_wait_vblank(tdm_output *output, int interval, int sync, return ret; } +/* LCOV_EXCL_START */ EXTERN tdm_error tdm_output_wait_vblank_add_front(tdm_output *output, int interval, int sync, tdm_output_vblank_handler func, void *user_data) @@ -835,6 +850,7 @@ tdm_output_wait_vblank_add_front(tdm_output *output, int interval, int sync, return ret; } +/* LCOV_EXCL_STOP */ INTERN void tdm_output_remove_vblank_handler_internal(tdm_output *output, tdm_output_vblank_handler func, void *user_data) @@ -915,8 +931,10 @@ tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handl func_output = &private_display->func_output; if (!func_output->output_commit) { + /* LCOV_EXCL_START */ TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; + /* LCOV_EXCL_STOP */ } ret = tdm_output_get_dpms_internal(output, &dpms_value); @@ -933,8 +951,10 @@ tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handl output_commit_handler = calloc(1, sizeof(tdm_private_output_commit_handler)); if (!output_commit_handler) { + /* LCOV_EXCL_START */ TDM_ERR("failed: alloc memory"); return TDM_ERROR_OUT_OF_MEMORY; + /* LCOV_EXCL_STOP */ } LIST_ADDTAIL(&output_commit_handler->link, &private_output->output_commit_handler_list); @@ -977,11 +997,13 @@ tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handl return ret; commit_failed: + /* LCOV_EXCL_START */ if (output_commit_handler) { LIST_DEL(&output_commit_handler->link); free(output_commit_handler); } return ret; + /* LCOV_EXCL_STOP */ } EXTERN tdm_error @@ -1043,9 +1065,11 @@ tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode) func_output = &private_display->func_output; if (!func_output->output_set_mode) { + /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; + /* LCOV_EXCL_STOP */ } ret = func_output->output_set_mode(private_output->output_backend, mode); @@ -1087,6 +1111,7 @@ _tdm_output_dpms_changed_timeout(void *user_data) return TDM_ERROR_NONE; } +/* LCOV_EXCL_START */ INTERN void tdm_output_cb_dpms(tdm_output *output_backend, tdm_output_dpms dpms, void *user_data) { @@ -1134,6 +1159,7 @@ tdm_output_cb_dpms(tdm_output *output_backend, tdm_output_dpms dpms, void *user_ TDM_OUTPUT_CHANGE_DPMS, value, 0); } +/* LCOV_EXCL_STOP */ EXTERN tdm_error tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value) @@ -1168,9 +1194,11 @@ tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value) tdm_event_loop_add_timer_handler(private_output->private_display, _tdm_output_dpms_changed_timeout, private_output, NULL); if (!private_output->dpms_changed_timer) { + /* LCOV_EXCL_START */ TDM_ERR("can't create dpms timer!!"); _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_OUT_OF_MEMORY; + /* LCOV_EXCL_STOP */ } } @@ -1181,9 +1209,11 @@ tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value) if (func_output->output_set_dpms) ret = func_output->output_set_dpms(private_output->output_backend, dpms_value); else { + /* LCOV_EXCL_START */ ret = TDM_ERROR_NONE; TDM_WRN("not implemented!!"); goto done; + /* LCOV_EXCL_STOP */ } done: @@ -1211,6 +1241,7 @@ done: return ret; } +/* LCOV_EXCL_START */ EXTERN tdm_error tdm_output_set_dpms_async(tdm_output *output, tdm_output_dpms dpms_value) { @@ -1275,6 +1306,7 @@ tdm_output_set_dpms_async(tdm_output *output, tdm_output_dpms dpms_value) return ret; } +/* LCOV_EXCL_STOP */ INTERN tdm_error tdm_output_get_dpms_internal(tdm_output *output, tdm_output_dpms *dpms_value) @@ -1297,15 +1329,19 @@ tdm_output_get_dpms_internal(tdm_output *output, tdm_output_dpms *dpms_value) func_output = &private_display->func_output; if (!func_output->output_get_dpms) { + /* LCOV_EXCL_START */ *dpms_value = private_output->current_dpms_value; TDM_WRN("not implemented!!"); return TDM_ERROR_NONE; + /* LCOV_EXCL_STOP */ } ret = func_output->output_get_dpms(private_output->output_backend, dpms_value); if (ret != TDM_ERROR_NONE) { + /* LCOV_EXCL_START */ TDM_ERR("output_get_dpms failed"); *dpms_value = TDM_OUTPUT_DPMS_OFF; + /* LCOV_EXCL_STOP */ } /* TODO: this is ugly. But we have to check if all backends's DPMS operation has no problem. */ @@ -1363,9 +1399,11 @@ tdm_output_hwc_create_window(tdm_output *output, tdm_error *error) if (private_output->caps.capabilities & TDM_OUTPUT_CAPABILITY_HWC) hwc_window = (tdm_hwc_window *)tdm_hwc_window_create_internal(private_output, error); else { + /* LCOV_EXCL_START */ TDM_ERR("output(%p) not support HWC", private_output); if (error) *error = TDM_ERROR_BAD_REQUEST; + /* LCOV_EXCL_STOP */ } _pthread_mutex_unlock(&private_display->lock); @@ -1409,9 +1447,11 @@ tdm_output_hwc_validate(tdm_output *output, uint32_t *num_types) func_output = &private_display->func_output; if (!func_output->output_hwc_validate) { + /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; + /* LCOV_EXCL_STOP */ } ret = func_output->output_hwc_validate(private_output->output_backend, num_types); @@ -1476,16 +1516,20 @@ tdm_output_hwc_get_changed_composition_types(tdm_output *output, func_output = &private_display->func_output; if (!func_output->output_hwc_get_changed_composition_types) { + /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; + /* LCOV_EXCL_STOP */ } ret = func_output->output_hwc_get_changed_composition_types(private_output->output_backend, num_elements, hwc_window, composition_types); if (ret != TDM_ERROR_NONE) { + /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); return ret; + /* LCOV_EXCL_STOP */ } if (hwc_window == NULL || composition_types == NULL) { @@ -1498,11 +1542,13 @@ tdm_output_hwc_get_changed_composition_types(tdm_output *output, private_hwc_window = _tdm_output_find_private_hwc_window(private_output, hwc_window[i]); if (private_hwc_window == NULL) { + /* LCOV_EXCL_START */ TDM_ERR("failed! This should never happen!"); func_output->output_hwc_destroy_window(private_output->output_backend, hwc_window[i]); *num_elements = 0; _pthread_mutex_unlock(&private_display->lock); return TDM_ERROR_OPERATION_FAILED; + /* LCOV_EXCL_STOP */ } hwc_window[i] = (tdm_hwc_window*)private_hwc_window; @@ -1531,9 +1577,11 @@ tdm_output_hwc_accept_changes(tdm_output *output) func_output = &private_display->func_output; if (!func_output->output_hwc_validate) { + /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; + /* LCOV_EXCL_STOP */ } ret = func_output->output_hwc_accept_changes(private_output->output_backend); @@ -1564,9 +1612,11 @@ tdm_output_hwc_get_target_buffer_queue(tdm_output *output, tdm_error *error) func_output = &private_display->func_output; if (!func_output->output_hwc_get_target_buffer_queue) { + /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); TDM_ERR("not implemented!!"); return NULL; + /* LCOV_EXCL_STOP */ } queue = func_output->output_hwc_get_target_buffer_queue(private_output->output_backend, error); @@ -1576,6 +1626,7 @@ tdm_output_hwc_get_target_buffer_queue(tdm_output *output, tdm_error *error) return queue; } +/* LCOV_EXCL_START */ static void _tdm_target_window_dump_buffer(tdm_private_output *private_output, tbm_surface_h buffer) { @@ -1591,6 +1642,7 @@ _tdm_target_window_dump_buffer(tdm_private_output *private_output, tbm_surface_h return; } +/* LCOV_EXCL_STOP */ EXTERN tdm_error tdm_output_hwc_set_client_target_buffer(tdm_output *output, tbm_surface_h target_buffer, @@ -1609,24 +1661,30 @@ tdm_output_hwc_set_client_target_buffer(tdm_output *output, tbm_surface_h target } if (tdm_debug_dump & TDM_DUMP_FLAG_WINDOW) { + /* LCOV_EXCL_START */ char str[TDM_PATH_LEN]; static int i; snprintf(str, TDM_PATH_LEN, "target_window_%d_%03d", private_output->index, i++); tdm_helper_dump_buffer_str(target_buffer, tdm_debug_dump_dir, str); + /* LCOV_EXCL_STOP */ } func_output = &private_display->func_output; if (!func_output->output_hwc_set_client_target_buffer) { + /* LCOV_EXCL_START */ _pthread_mutex_unlock(&private_display->lock); TDM_ERR("not implemented!!"); return TDM_ERROR_NOT_IMPLEMENTED; + /* LCOV_EXCL_STOP */ } /* dump buffer */ if (tdm_dump_enable) + /* LCOV_EXCL_START */ _tdm_target_window_dump_buffer((tdm_private_output *)output, target_buffer); + /* LCOV_EXCL_STOP */ ret = func_output->output_hwc_set_client_target_buffer(private_output->output_backend, target_buffer, damage); -- 2.7.4 From 05519c6c5265c19f1970480a9db50e7850753596 Mon Sep 17 00:00:00 2001 From: Konstantin Drabeniuk Date: Fri, 24 Nov 2017 13:28:27 +0200 Subject: [PATCH 05/16] utest: improve the test coverage for tdm_output.c Change-Id: I71c9e30c79e5f1d98065f13149dbd1b1c3c4826a Signed-off-by: Konstantin Drabeniuk --- utests/src/ut_tdm_hwc_window.cpp | 115 +++++++- utests/src/ut_tdm_output.cpp | 576 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 675 insertions(+), 16 deletions(-) diff --git a/utests/src/ut_tdm_hwc_window.cpp b/utests/src/ut_tdm_hwc_window.cpp index d6fb90c..f4c33a5 100644 --- a/utests/src/ut_tdm_hwc_window.cpp +++ b/utests/src/ut_tdm_hwc_window.cpp @@ -32,8 +32,9 @@ #include "ut_common.h" #include "stdint.h" -extern "C" { #include "tdm.h" +#include "tdm_backend.h" +extern "C" { #include "tbm_bufmgr.h" #include "tbm_drm_helper.h" } @@ -52,7 +53,7 @@ protected: { setenv("TDM_DEBUG_MODULE", "all", 1); setenv("TDM_DEBUG", "1", 1); - setenv("TDM_THREAD", "0", 1); + setenv("TDM_THREAD", "1", 1); setenv("TDM_COMMIT_PER_VBLANK", "1", 1); setenv("TDM_DLOG", "1", 1); setenv("TDM_HWC", "1", 1); @@ -177,7 +178,14 @@ protected: UnsetEnv(); } +}; +class TDMOutputHwcWithoutHwcCap : public TDMOutputHwc { + void SetEnv() + { + TDMOutputHwc::SetEnv(); + setenv("TDM_HWC", "0", 1); + } }; #define HWC_WIN_NUM 5 @@ -284,6 +292,19 @@ TEST_F(TDMOutputHwc, SetClientTargetBufferFailNullOutput) ASSERT_NE(TDM_ERROR_NONE, error); } +TEST_F(TDMOutputHwcWithoutHwcCap, SetClientTargetBufferFailNoHwc) +{ + tdm_hwc_region damage; + + for (int i = 0; i < output_count; i++) { + tbm_surface_h target_buff = CreateBufferForOutput(i); + ASSERT_NE(NULL, target_buff); + error = tdm_output_hwc_set_client_target_buffer(outputs[i], target_buff, damage); + tbm_surface_internal_destroy(target_buff); + ASSERT_NE(TDM_ERROR_NONE, error); + } +} + TEST_F(TDMOutputHwc, SetClientTargetBufferSuccessfulSetBuff) { tdm_hwc_region damage; @@ -331,6 +352,17 @@ TEST_F(TDMOutputHwc, GetTargetBufferQueueFailNullOutput) ASSERT_EQ(NULL, queue); } +TEST_F(TDMOutputHwcWithoutHwcCap, GetTargetBufferQueueFainNoHwc) +{ + tbm_surface_queue_h queue = NULL; + + for (int i = 0; i < output_count; i++) { + queue = tdm_output_hwc_get_target_buffer_queue(outputs[i], &error); + ASSERT_NE(TDM_ERROR_NONE, error); + ASSERT_EQ(NULL, queue); + } +} + TEST_F(TDMOutputHwc, GetTargetBufferQueueSuccessful) { tbm_surface_queue_h queue = NULL; @@ -639,6 +671,16 @@ TEST_F(TDMOutputHwc, ValidateFailNull) } } +TEST_F(TDMOutputHwcWithoutHwcCap, ValidateFailNoHwc) +{ + uint32_t num_types; + + for (int i = 0; i < output_count; i++) { + error = tdm_output_hwc_validate(outputs[i], &num_types); + ASSERT_NE(TDM_ERROR_NONE, error); + } +} + TEST_F(TDMOutputHwc, ValidateSuccessful) { uint32_t num_types; @@ -657,7 +699,6 @@ TEST_F(TDMOutputHwc, ValidateSuccessful) uint32_t *num_elements, tdm_hwc_window **hwc_window, tdm_hwc_window_composition *composition_types); */ -/* tdm_error tdm_output_hwc_accept_changes(tdm_output *output); */ TEST_F(TDMOutputHwc, GetChangedCompositionTypesFailNull) { uint32_t num_elements; @@ -671,6 +712,16 @@ TEST_F(TDMOutputHwc, GetChangedCompositionTypesFailNull) } } +TEST_F(TDMOutputHwcWithoutHwcCap, GetChangedCompositionTypesFailNoHwc) +{ + uint32_t get_num = 10; + + for (int i = 0; i < output_count; i++) { + error = tdm_output_hwc_get_changed_composition_types(outputs[i], &get_num, NULL, NULL); + ASSERT_NE(TDM_ERROR_NONE, error); + } +} + TEST_F(TDMHwcWindow, GetChangedCompositionTypesSuccessful) { uint32_t validate_num; @@ -701,6 +752,7 @@ TEST_F(TDMHwcWindow, GetChangedCompositionTypesSuccessful) free(hwc_wnds); free(composition_types); + ASSERT_EQ(TDM_ERROR_NONE, error); } else { error = tdm_output_hwc_get_changed_composition_types(outputs[i], &get_num, NULL, NULL); @@ -709,8 +761,48 @@ TEST_F(TDMHwcWindow, GetChangedCompositionTypesSuccessful) } } +/* tdm_error tdm_output_hwc_accept_changes(tdm_output *output); */ + +TEST_F(TDMOutputHwc, AcceptChangesFailNull) +{ + error = tdm_output_hwc_accept_changes(NULL); + ASSERT_NE(TDM_ERROR_NONE, error); +} + +TEST_F(TDMOutputHwcWithoutHwcCap, AcceptChangesFailNoHwc) +{ + for (int i = 0; i < output_count; i++) { + error = tdm_output_hwc_accept_changes(outputs[i]); + ASSERT_NE(TDM_ERROR_NONE, error); + } +} + +TEST_F(TDMHwcWindow, AcceptChangesSuccessful) +{ + uint32_t validate_num; + + for (int i = 0; i < hwc_count; i++) { + error = tdm_hwc_window_set_composition_type(hwc_wins[i], TDM_COMPOSITION_DEVICE); + ASSERT_EQ(TDM_ERROR_NONE, error); + } + + for (int i = 0; i < output_count; i++) { + if (IsHwcEnable(i)) { + error = tdm_output_hwc_validate(outputs[i], &validate_num); + ASSERT_EQ(TDM_ERROR_NONE, error); + + if (validate_num > 0) { + error = tdm_output_hwc_accept_changes(outputs[i]); + ASSERT_EQ(TDM_ERROR_NONE, error); + } + } + } +} + +static int need_validate_handler_is_called = 0; static void need_validate_handler(tdm_output *output) { + need_validate_handler_is_called = 1; } /* tdm_error tdm_output_hwc_set_need_validate_handler(tdm_output *output, tdm_output_need_validate_handler hndl); */ @@ -723,6 +815,15 @@ TEST_F(TDMOutputHwc, SetNeedValidateHandlerFailNull) ASSERT_NE(TDM_ERROR_NONE, error); } + +TEST_F(TDMOutputHwcWithoutHwcCap, SetNeedValidateHandlerFailNoHwc) +{ + for (int i = 0; i < output_count; i++) { + error = tdm_output_hwc_set_need_validate_handler(outputs[i], &need_validate_handler); + ASSERT_NE(TDM_ERROR_NONE, error); + } +} + TEST_F(TDMOutputHwc, SetNeedValidateHandlerSuccessful) { for (int i = 0; i < output_count; i++) { @@ -731,6 +832,14 @@ TEST_F(TDMOutputHwc, SetNeedValidateHandlerSuccessful) error = tdm_output_hwc_set_need_validate_handler(outputs[i], &need_validate_handler); ASSERT_EQ(TDM_ERROR_NONE, error); + error = tdm_backend_trigger_need_validate_event(outputs[i]); + ASSERT_EQ(TDM_ERROR_NONE, error); + + error = tdm_display_handle_events(dpy); + ASSERT_EQ(TDM_ERROR_NONE, error); + + ASSERT_EQ(1, need_validate_handler_is_called); + /* test: second isn't allowed*/ error = tdm_output_hwc_set_need_validate_handler(outputs[i], &need_validate_handler); ASSERT_NE(TDM_ERROR_NONE, error); diff --git a/utests/src/ut_tdm_output.cpp b/utests/src/ut_tdm_output.cpp index be7d0b3..71c7b55 100644 --- a/utests/src/ut_tdm_output.cpp +++ b/utests/src/ut_tdm_output.cpp @@ -31,11 +31,15 @@ #include "gtest/gtest.h" #include "ut_common.h" #include -extern "C" { #include "tdm.h" +extern "C" { #include "tbm_bufmgr.h" #include "tbm_drm_helper.h" } +#include +#include +#include +#include class TDMOutput : public ::testing::Test { protected: @@ -53,13 +57,31 @@ protected: TDMOutput::handle_call++; } } - void SetUp(void) + virtual void SetEnvs() { + setenv("TDM_DEBUG_MODULE", "all", 1); + setenv("TDM_DEBUG", "1", 1); setenv("TDM_DLOG", "1", 1); setenv("XDG_RUNTIME_DIR", ".", 1); setenv("TBM_DLOG", "1", 1); setenv("TBM_DISPLAY_SERVER", "1", 1); setenv("TDM_COMMIT_PER_VBLANK", "0", 1); + } + + virtual void UnsetEnvs() + { + unsetenv("TDM_DEBUG_MODULE"); + unsetenv("TDM_DEBUG"); + unsetenv("TDM_DLOG"); + unsetenv("XDG_RUNTIME_DIR"); + unsetenv("TBM_DLOG"); + unsetenv("TBM_DISPLAY_SERVER"); + unsetenv("TDM_COMMIT_PER_VBLANK"); + } + + void SetUp(void) + { + SetEnvs(); tdm_error error = TDM_ERROR_NONE; dpy = tdm_display_init(&error); @@ -97,22 +119,76 @@ protected: exit(1); close(tbm_fd); } - unsetenv("TDM_DLOG"); - unsetenv("XDG_RUNTIME_DIR"); - unsetenv("TBM_DLOG"); - unsetenv("TBM_DISPLAY_SERVER"); - unsetenv("TDM_COMMIT_PER_VBLANK"); + + UnsetEnvs(); + } +}; + +class TDMOutputHWC : public TDMOutput { + void SetEnvs(void) + { + TDMOutput::SetEnvs(); + setenv("TDM_HWC", "1", 1); + } + void UnsetEnvs(void) + { + TDMOutput::UnsetEnvs(); + unsetenv("TDM_HWC"); + } +}; + +class TDMOutputThread : public TDMOutput { + void SetEnvs(void) + { + + TDMOutput::SetEnvs(); + setenv("TDM_THREAD", "1", 1); + } + void UnsetEnvs(void) + { + TDMOutput::UnsetEnvs(); + unsetenv("TDM_THREAD"); } }; class TDMOutputCommit : public TDMOutput { +private: + int epFd = -1; + int timerFd = -1; + int tdmFd = -1; + static const int timeLimitSec = 1; + static const int timeLimitNsec = 0; protected: int conn_output_count = 0; tdm_output ** connected_output_array = NULL; const tdm_output_mode** preferred_mode = NULL; bool has_output = false; + std::vector> layers_array; + std::vector buffers; + static unsigned int utOutputCommitHandlerCounter; + static void UtOutputCommitHandler(tdm_output *output, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, + void *user_data) + { + utOutputCommitHandlerCounter++; + } + + static unsigned int utOutputVblankHandlerCounter; + static void UtOutputVblankHandler(tdm_output *output, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, + void *user_data) + { + utOutputVblankHandlerCounter++; + } + friend void *UtOutputRemoveChangeHandlerSuccessfulThread(void *ptr); + void SetUp(void) { + struct epoll_event ep; + + utOutputCommitHandlerCounter = 0; + utOutputVblankHandlerCounter = 0; + ASSERT_NO_FATAL_FAILURE(TDMOutput::SetUp()); if (TDMOutput::output_count > 0) { connected_output_array = (tdm_output **) calloc(TDMOutput::output_count, sizeof(tdm_output *)); @@ -124,8 +200,10 @@ protected: for (int i = 0; i < TDMOutput::output_count; i++) { tdm_error error = TDM_ERROR_NONE; int output_modes_cnt = 0; + int layer_count = 0; const tdm_output_mode* output_modes = NULL; tdm_output * output = tdm_display_get_output(TDMOutput::dpy, i, &error); + std::vector layers; if (TDM_ERROR_NONE != error || NULL == output) continue; tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED; @@ -147,7 +225,21 @@ protected: } if (NULL == preferred_mode[conn_output_count]) continue; + + if (TDM_ERROR_NONE != tdm_output_get_layer_count(output, &layer_count)) + continue; + if (0 == layer_count) + continue; + + for (int i = 0; i < layer_count; ++i) { + tdm_layer *layer; + layer = tdm_output_get_layer(output, i, &error); + if (layer == nullptr) + continue; + layers.push_back(layer); + } connected_output_array[conn_output_count++] = output; + layers_array.push_back(layers); } #ifdef FAIL_ON_UNSUPPORTED ASSERT_GT(conn_output_count, 0); @@ -155,9 +247,37 @@ protected: if (conn_output_count > 0) has_output = true; + + epFd = epoll_create1(0); + ASSERT_TRUE(epFd != -1); + + timerFd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); + ASSERT_TRUE(timerFd != -1); + + memset(&ep, 0, sizeof ep); + ep.events |= EPOLLIN; + ep.data.fd = timerFd; + ASSERT_TRUE(epoll_ctl(epFd, EPOLL_CTL_ADD, timerFd, &ep) == 0); + + ASSERT_TRUE(tdm_display_get_fd(dpy, &tdmFd) == TDM_ERROR_NONE); + + memset(&ep, 0, sizeof ep); + ep.events |= EPOLLIN; + ep.data.fd = tdmFd; + ASSERT_TRUE(epoll_ctl(epFd, EPOLL_CTL_ADD, tdmFd, &ep) == 0); } void TearDown(void) { + for (size_t i = 0; i < layers_array.size(); ++i) { + for (tdm_layer *layer : layers_array[i]) { + tdm_layer_unset_buffer(layer); + } + } + + for (tbm_surface_h buffer : buffers) { + tbm_surface_destroy(buffer); + } + for (int i = 0; i < conn_output_count; i++) { EXPECT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(connected_output_array[i], TDM_OUTPUT_DPMS_OFF)); @@ -168,10 +288,141 @@ protected: free(preferred_mode); ASSERT_NO_FATAL_FAILURE(TDMOutput::TearDown()); } + + tbm_surface_h UtCreateBuffer(int width, int height, tbm_format format) + { + tbm_surface_h buffer; + + buffer = tbm_surface_internal_create_with_flags(width, height, format, TBM_BO_SCANOUT); + + if (buffer) + buffers.push_back(buffer); + + return buffer; + } + + void UtPrepareToCommit() + { + for (size_t i = 0; i < layers_array.size(); ++i) { + for (tdm_layer *layer : layers_array[i]) { + int w, h; + tdm_error error; + tdm_layer_capability lcapabilities; + tbm_surface_h buffer; + tdm_info_layer layer_info = {0}; + + w = preferred_mode[i]->hdisplay; + h = preferred_mode[i]->vdisplay; + + error = tdm_output_set_mode(connected_output_array[i], preferred_mode[i]); + ASSERT_EQ(TDM_ERROR_NONE, error); + + error = tdm_layer_get_capabilities(layer, &lcapabilities); + ASSERT_EQ(TDM_ERROR_NONE, error); + if (!(lcapabilities & TDM_LAYER_CAPABILITY_PRIMARY)) { + w = w / 2; + h = h / 2; + } + + buffer = UtCreateBuffer(w, h, TBM_FORMAT_ARGB8888); + ASSERT_NE(nullptr, buffer); + + layer_info.src_config.size.h = w; + layer_info.src_config.size.v = h; + layer_info.src_config.pos.x = 0; + layer_info.src_config.pos.y = 0; + layer_info.src_config.pos.w = w; + layer_info.src_config.pos.h = h; + layer_info.src_config.format = TBM_FORMAT_ARGB8888; + layer_info.dst_pos.x = 0; + layer_info.dst_pos.y = 0; + layer_info.dst_pos.w = w; + layer_info.dst_pos.h = h; + layer_info.transform = TDM_TRANSFORM_NORMAL; + + error = tdm_layer_set_info(layer, &layer_info); + ASSERT_EQ(TDM_ERROR_NONE, error); + + error = tdm_layer_set_buffer(layer, buffer); + ASSERT_EQ(TDM_ERROR_NONE, error); + } + } + } + + void UtHandleEvent(unsigned int & wait_var, unsigned int num) + { + struct itimerspec its; + int count; + struct epoll_event ep_event[2]; + + if (wait_var == num) + return; + + its.it_interval.tv_sec = 0; + its.it_interval.tv_nsec = 0; + its.it_value.tv_sec = timeLimitSec; + its.it_value.tv_nsec = timeLimitNsec; + + ASSERT_TRUE(timerfd_settime(timerFd, 0, &its, NULL) == 0); + + while (1) { + count = epoll_wait(epFd, ep_event, sizeof(ep_event), -1); + ASSERT_TRUE(count >= 0); + + for (int i = 0; i < count; i++) { + if (ep_event[i].data.fd == timerFd) { + return; + } else { + ASSERT_TRUE(tdm_display_handle_events(dpy) == TDM_ERROR_NONE); + if (wait_var == num) + return; + } + } + } + } + + void UtHandleCommitEvent() + { + UtHandleEvent(utOutputCommitHandlerCounter, (unsigned int)conn_output_count); + } + + void UtHandleVblankEvent() + { + UtHandleEvent(utOutputVblankHandlerCounter, conn_output_count); + } +}; + +class TDMOutputCommitPerVblankEnabled : public TDMOutputCommit { + void SetEnvs(void) + { + + TDMOutputCommit::SetEnvs(); + setenv("TDM_COMMIT_PER_VBLANK", "1", 1); + } + void UnsetEnvs(void) + { + TDMOutputCommit::UnsetEnvs(); + unsetenv("TDM_COMMIT_PER_VBLANK"); + } }; +class TDMOutputCommitThread : public TDMOutputCommit { + void SetEnvs(void) + { + TDMOutputCommit::SetEnvs(); + setenv("TDM_THREAD", "1", 1); + } + + void UnsetEnvs(void) + { + TDMOutputCommit::UnsetEnvs(); + unsetenv("TDM_THREAD"); + } +}; unsigned int TDMOutput::handle_call = 0; +unsigned int TDMOutputCommit::utOutputCommitHandlerCounter = 0; +unsigned int TDMOutputCommit::utOutputVblankHandlerCounter = 0; TEST_F(TDMOutput, DisplayGetOutputSuccessful) { @@ -449,6 +700,69 @@ TEST_F(TDMOutput, OutputRemoveChangeHandlerSuccessful) } } +void *UtOutputRemoveChangeHandlerSuccessfulThread(void *ptr) +{ + TDMOutputCommitThread *FTDMOutput = (TDMOutputCommitThread *)ptr; + + bool checked = false; + for (int i = 0; i < FTDMOutput->output_count; i++) { + tdm_error error = TDM_ERROR_NONE; + tdm_output * output = tdm_display_get_output(FTDMOutput->dpy, i, &error); + if (NULL == output || TDM_ERROR_NONE != error) + return (void *)1; + tdm_output_conn_status status; + error = tdm_output_get_conn_status(output, &status); + if (TDM_ERROR_NONE != error) + return (void *)2; + if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) + continue; + checked = true; + error = tdm_output_add_change_handler(output, + FTDMOutput->tdm_output_change_handler_test_func, + (void *) -101); + if (TDM_ERROR_NONE != error) + return (void *)3; + error = tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_ON); + if (TDM_ERROR_NONE != error) + return (void *)4; + error = tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_OFF); + if (TDM_ERROR_NONE != error) + return (void *)5; + FTDMOutput->UtHandleEvent(FTDMOutput->handle_call, 1); + if (FTDMOutput->handle_call <= 0) + return (void *)6; + FTDMOutput->handle_call = 0; + tdm_output_remove_change_handler(output, FTDMOutput->tdm_output_change_handler_test_func, (void *) -101); + error = tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_ON); + if (TDM_ERROR_NONE != error) + return (void *)7; + error = tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_OFF); + if (TDM_ERROR_NONE != error) + return (void *)8; + FTDMOutput->UtHandleEvent(FTDMOutput->handle_call, 1); + if (FTDMOutput->handle_call != 0) + return (void *)9; + } + if (false == checked) { + return (void *)10; + } + + return nullptr; +} + +TEST_F(TDMOutputCommitThread, OutputRemoveChangeHandlerSuccessfulThread) +{ + SKIP_FLAG(has_output); + pthread_t thread = 0; + int *status = nullptr; + + ASSERT_FALSE(pthread_create(&thread, NULL, UtOutputRemoveChangeHandlerSuccessfulThread, this)); + + ASSERT_FALSE(pthread_join(thread, (void **)&status)); + + ASSERT_EQ(nullptr, status); +} + TEST_F(TDMOutput, OutputRemoveChangeHandlerSuccessfulFewFuncs) { SKIP_FLAG(has_output); @@ -561,6 +875,33 @@ TEST_F(TDMOutput, OutputGetLayerCountSuccessful) } } +TEST_F(TDMOutputHWC, OutputGetLayerCountFailHWC) +{ + SKIP_FLAG(has_output); + for (int i = 0; i < output_count; i++) { + tdm_error error = TDM_ERROR_NONE; + int count = -42; + tdm_output * output = tdm_display_get_output(dpy, i, &error); + ASSERT_FALSE(NULL == output); + ASSERT_TRUE(TDM_ERROR_NONE == error); + ASSERT_TRUE(TDM_ERROR_NONE != tdm_output_get_layer_count(output, &count)); + } +} + +TEST_F(TDMOutputHWC, OutputGetLayerFailHWC) +{ + SKIP_FLAG(has_output); + + for (int i = 0; i < output_count; i++) { + tdm_error error = TDM_ERROR_NONE; + tdm_output * output = tdm_display_get_output(dpy, i, &error); + ASSERT_FALSE(NULL == output); + ASSERT_TRUE(TDM_ERROR_NONE == error); + ASSERT_TRUE(nullptr == tdm_output_get_layer(output, 0, &error)); + ASSERT_TRUE(TDM_ERROR_NONE != error); + } +} + TEST_F(TDMOutput, OutputGetLayerCountFailNullAll) { SKIP_FLAG(has_output); @@ -906,6 +1247,40 @@ TEST_F(TDMOutput, OutputGetPipeFailOnlyOutput) exit(0);}, ::testing::ExitedWithCode(0), ""); } +TEST_F(TDMOutput, OutputGetPrimaryIndexSuccessful) +{ + SKIP_FLAG(has_output); + for (int i = 0; i < output_count; i++) { + tdm_error error = TDM_ERROR_NONE; + int primary_index = INT_MAX; + tdm_output * output = tdm_display_get_output(dpy, i, &error); + ASSERT_FALSE(NULL == output); + ASSERT_TRUE(TDM_ERROR_NONE == error); + ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_get_primary_index(output, &primary_index)); + ASSERT_NE(primary_index, INT_MAX); + } +} + +TEST_F(TDMOutput, OutputGetPrimaryIndexFailNullAll) +{ + SKIP_FLAG(has_output); + ASSERT_EXIT({if (tdm_output_get_primary_index(NULL, NULL) == TDM_ERROR_NONE) exit(1); + exit(0);}, ::testing::ExitedWithCode(0), ""); +} + +TEST_F(TDMOutput, OutputGetPrimaryIndexFailOnlyOutput) +{ + SKIP_FLAG(has_output); + ASSERT_EXIT({for (int i = 0; i < output_count; i++) { + tdm_error error = TDM_ERROR_NONE; + tdm_output * output = tdm_display_get_output(dpy, i, &error); + if (NULL == output) exit(1); + if (TDM_ERROR_NONE != error) exit(1); + if (tdm_output_get_primary_index(output, NULL) == TDM_ERROR_NONE) exit(1); + } + exit(0);}, ::testing::ExitedWithCode(0), ""); +} + TEST_F(TDMOutput, OutputSetPropertySuccessful) { SKIP_FLAG(has_output); @@ -955,19 +1330,194 @@ TEST_F(TDMOutput, OutputGetPropertyFailNullAll) exit(0);}, ::testing::ExitedWithCode(0), ""); } +TEST_F(TDMOutputCommit, OutputCommitFailNullAll) +{ + SKIP_FLAG(has_output); + + ASSERT_TRUE(TDM_ERROR_NONE != tdm_output_commit(NULL, 0, NULL, NULL)); +} + TEST_F(TDMOutputCommit, OutputCommit) { SKIP_FLAG(has_output); + + ASSERT_NO_FATAL_FAILURE(UtPrepareToCommit()); + + for (int i = 0; i < conn_output_count; i++) + ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_commit(connected_output_array[i], 0, UtOutputCommitHandler, NULL)); + + UtHandleCommitEvent(); + + ASSERT_EQ(conn_output_count, utOutputCommitHandlerCounter); +} + +TEST_F(TDMOutputCommitThread, OutputCommit) +{ + SKIP_FLAG(has_output); + + ASSERT_NO_FATAL_FAILURE(UtPrepareToCommit()); + + for (int i = 0; i < conn_output_count; i++) + ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_commit(connected_output_array[i], 0, UtOutputCommitHandler, NULL)); + + UtHandleCommitEvent(); + + ASSERT_EQ(conn_output_count, utOutputCommitHandlerCounter); +} + +TEST_F(TDMOutputCommitPerVblankEnabled, OutputCommitFailLayerCommit) +{ + SKIP_FLAG(has_output); + + ASSERT_NO_FATAL_FAILURE(UtPrepareToCommit()); + + for (size_t i = 0; i < layers_array.size(); ++i) { + for (tdm_layer *layer : layers_array[i]) { + tdm_layer_commit(layer, NULL, NULL); + } + } + + for (int i = 0; i < conn_output_count; i++) + ASSERT_TRUE(TDM_ERROR_NONE != tdm_output_commit(connected_output_array[i], 0, UtOutputCommitHandler, NULL)); +} + +TEST_F(TDMOutputCommitPerVblankEnabled, OutputCommitFailCommitPerVblankEnabled) +{ + SKIP_FLAG(has_output); + + ASSERT_NO_FATAL_FAILURE(UtPrepareToCommit()); + + for (int i = 0; i < conn_output_count; i++) + ASSERT_TRUE(TDM_ERROR_NONE != tdm_output_commit(connected_output_array[i], 0, UtOutputCommitHandler, NULL)); +} + +TEST_F(TDMOutputCommit, OutputCommitFailDpmsOff) +{ + SKIP_FLAG(has_output); + + ASSERT_NO_FATAL_FAILURE(UtPrepareToCommit()); + for (int i = 0; i < conn_output_count; i++) { - ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_mode(connected_output_array[i], preferred_mode[i])); - ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_commit(connected_output_array[i], 0, NULL, NULL)); - /* TODO: use a commit handler instead of an usleep to wait when - * commit will be applied */ - usleep(20000); + ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(connected_output_array[i], TDM_OUTPUT_DPMS_OFF)); + + ASSERT_TRUE(TDM_ERROR_NONE != tdm_output_commit(connected_output_array[i], 0, UtOutputCommitHandler, NULL)); } } -TEST_F(TDMOutputCommit, DISABLED_OutputWaitVBlank) +TEST_F(TDMOutputCommit, OutputWaitVBlankFailNullAll) +{ + SKIP_FLAG(has_output); + + ASSERT_TRUE(TDM_ERROR_NONE != tdm_output_wait_vblank(nullptr, 1, 0, nullptr, nullptr)); +} + +TEST_F(TDMOutputCommit, OutputWaitVBlankFailDpmsOff) +{ + SKIP_FLAG(has_output); + + ASSERT_NO_FATAL_FAILURE(UtPrepareToCommit()); + + for (int i = 0; i < conn_output_count; i++) { + ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_set_dpms(connected_output_array[i], TDM_OUTPUT_DPMS_OFF)); + + for (int i = 0; i < conn_output_count; i++) + ASSERT_TRUE(TDM_ERROR_NONE != tdm_output_wait_vblank(connected_output_array[i], 1, 0, UtOutputVblankHandler, nullptr)); + } +} + +TEST_F(TDMOutputCommit, OutputWaitVBlank) +{ + SKIP_FLAG(has_output); + + ASSERT_NO_FATAL_FAILURE(UtPrepareToCommit()); + + for (int i = 0; i < conn_output_count; i++) + ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_commit(connected_output_array[i], 0, UtOutputCommitHandler, nullptr)); + + UtHandleCommitEvent(); + + ASSERT_EQ(conn_output_count, utOutputCommitHandlerCounter); + + for (int i = 0; i < conn_output_count; i++) + ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_wait_vblank(connected_output_array[i], 1, 0, UtOutputVblankHandler, nullptr)); + + UtHandleVblankEvent(); + + ASSERT_EQ(conn_output_count, utOutputVblankHandlerCounter); +} + +TEST_F(TDMOutputCommitThread, OutputWaitVBlank) { SKIP_FLAG(has_output); + + ASSERT_NO_FATAL_FAILURE(UtPrepareToCommit()); + + for (int i = 0; i < conn_output_count; i++) + ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_commit(connected_output_array[i], 0, UtOutputCommitHandler, NULL)); + + UtHandleCommitEvent(); + + ASSERT_EQ(conn_output_count, utOutputCommitHandlerCounter); + + for (int i = 0; i < conn_output_count; i++) + ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_wait_vblank(connected_output_array[i], 1, 0, UtOutputVblankHandler, NULL)); + + UtHandleVblankEvent(); + + ASSERT_EQ(conn_output_count, utOutputVblankHandlerCounter); +} + +TEST_F(TDMOutputCommit, OutputRemoveVblankHandlerFailNullAll) +{ + SKIP_FLAG(has_output); + + ASSERT_TRUE(TDM_ERROR_NONE != tdm_output_remove_vblank_handler(nullptr, nullptr, nullptr)); +} + +TEST_F(TDMOutputCommitThread, OutputRemoveVblankHandlerSuccess) +{ + SKIP_FLAG(has_output); + + ASSERT_NO_FATAL_FAILURE(UtPrepareToCommit()); + + for (int i = 0; i < conn_output_count; i++) + ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_commit(connected_output_array[i], 0, UtOutputCommitHandler, NULL)); + + UtHandleCommitEvent(); + + ASSERT_EQ(conn_output_count, utOutputCommitHandlerCounter); + + for (int i = 0; i < conn_output_count; i++) + ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_wait_vblank(connected_output_array[i], 2, 0, UtOutputVblankHandler, NULL)); + + for (int i = 0; i < conn_output_count; i++) { + ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_remove_vblank_handler(connected_output_array[i], UtOutputVblankHandler, NULL)); + } + + UtHandleVblankEvent(); + + ASSERT_EQ(0, utOutputVblankHandlerCounter); +} + +TEST_F(TDMOutputCommit, OutputRemoveCommitHandlerFailNullAll) +{ + SKIP_FLAG(has_output); + + ASSERT_TRUE(TDM_ERROR_NONE != tdm_output_remove_commit_handler(nullptr, nullptr, nullptr)); +} + +TEST_F(TDMOutputCommitThread, OutputRemoveCommitHandlerSuccess) +{ + SKIP_FLAG(has_output); + + ASSERT_NO_FATAL_FAILURE(UtPrepareToCommit()); + + for (int i = 0; i < conn_output_count; i++) + ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_commit(connected_output_array[i], 0, UtOutputCommitHandler, NULL)); + + for (int i = 0; i < conn_output_count; i++) { + ASSERT_TRUE(TDM_ERROR_NONE == tdm_output_remove_commit_handler(connected_output_array[i], UtOutputCommitHandler, NULL)); + } + + UtHandleCommitEvent(); } -- 2.7.4 From a542ccbcbbee734a35d5de1cd3feae2493097dda Mon Sep 17 00:00:00 2001 From: Konstantin Drabeniuk Date: Fri, 24 Nov 2017 14:43:42 +0200 Subject: [PATCH 06/16] add excluding coverage comments for tdm.c and tdm_thread.c As we test only API's funcs add excluding coverage comments for all static func in the tdm.c file. Add excluding coverage comments for tdm_thread.c for the folowing code: - TDM_THREAD_CB_OUTPUT_STATUS(it is not supported by all targets) - TDM_THREAD_CB_OUTPUT_DPMS(it is not supported by all targets) Change-Id: I8f404184774589c27f8c0dfe21574755434a75c8 Signed-off-by: Konstantin Drabeniuk --- src/tdm.c | 12 ++++++++++++ src/tdm_thread.c | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/src/tdm.c b/src/tdm.c index 7c36041..418010c 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -50,6 +50,7 @@ int tdm_mutex_lock_line; const char *tdm_mutex_unlock_func; int tdm_mutex_unlock_line; +/* LCOV_EXCL_START */ static tdm_private_layer * _tdm_display_find_private_layer(tdm_private_output *private_output, tdm_layer *layer_backend) @@ -652,6 +653,7 @@ failed_update: _tdm_display_destroy_private_display(private_display); return ret; } +/* LCOV_EXCL_STOP */ EXTERN tdm_error tdm_display_update(tdm_display *dpy) @@ -681,6 +683,7 @@ int tdm_debug_dump; static tdm_private_display *g_private_display; static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER; +/* LCOV_EXCL_START */ static tdm_error _tdm_display_check_module(tdm_backend_module *module) { @@ -909,6 +912,7 @@ _tdm_display_unload_module(tdm_private_display *private_display) private_display->module_data = NULL; private_display->module = NULL; } +/* LCOV_EXCL_STOP */ EXTERN tdm_display * tdm_display_init(tdm_error *error) @@ -932,9 +936,11 @@ tdm_display_init(tdm_error *error) private_display = calloc(1, sizeof(tdm_private_display)); if (!private_display) { + /* LCOV_EXCL_START */ ret = TDM_ERROR_OUT_OF_MEMORY; TDM_ERR("'private_display != NULL' failed"); goto failed_alloc; + /* LCOV_EXCL_STOP */ } str = getenv("TDM_DEBUG_MODULE"); @@ -950,9 +956,11 @@ tdm_display_init(tdm_error *error) tdm_display_enable_path(str); if (pthread_mutex_init(&private_display->lock, NULL)) { + /* LCOV_EXCL_START */ ret = TDM_ERROR_OPERATION_FAILED; TDM_ERR("mutex init failed: %m"); goto failed_mutex_init; + /* LCOV_EXCL_STOP */ } _pthread_mutex_lock(&private_display->lock); @@ -1043,6 +1051,7 @@ tdm_display_init(tdm_error *error) return (tdm_display *)private_display; +/* LCOV_EXCL_START */ failed_update: _tdm_display_unload_module(private_display); failed_load: @@ -1058,6 +1067,7 @@ failed_alloc: *error = ret; pthread_mutex_unlock(&gLock); return NULL; +/* LCOV_EXCL_STOP */ } EXTERN void @@ -1109,6 +1119,7 @@ tdm_display_deinit(tdm_display *dpy) TDM_INFO("done"); } +/* LCOV_EXCL_START */ INTERN int tdm_display_check_module_abi(tdm_private_display *private_display, int abimaj, int abimin) { @@ -1359,3 +1370,4 @@ tdm_display_enable_fps(tdm_private_display *private_display, int enable) return TDM_ERROR_NONE; } +/* LCOV_EXCL_STOP */ diff --git a/src/tdm_thread.c b/src/tdm_thread.c index 8f624e1..ed5d049 100644 --- a/src/tdm_thread.c +++ b/src/tdm_thread.c @@ -307,6 +307,7 @@ tdm_thread_handle_cb(tdm_private_loop *private_loop) break; } case TDM_THREAD_CB_OUTPUT_STATUS: { + /* LCOV_EXCL_START */ tdm_thread_cb_output_status *output_status = (tdm_thread_cb_output_status*)base; tdm_output *output_backend = tdm_display_find_output_stamp(private_loop->dpy, output_status->output_stamp); @@ -317,8 +318,10 @@ tdm_thread_handle_cb(tdm_private_loop *private_loop) tdm_output_cb_status(output_backend, output_status->status, output_status->user_data); break; + /* LCOV_EXCL_STOP */ } case TDM_THREAD_CB_OUTPUT_DPMS: { + /* LCOV_EXCL_START */ tdm_thread_cb_output_dpms *output_dpms = (tdm_thread_cb_output_dpms*)base; tdm_output *output_backend = tdm_display_find_output_stamp(private_loop->dpy, output_dpms->output_stamp); @@ -328,6 +331,7 @@ tdm_thread_handle_cb(tdm_private_loop *private_loop) } tdm_output_cb_dpms(output_backend, output_dpms->dpms, output_dpms->user_data); break; + /* LCOV_EXCL_STOP */ } case TDM_THREAD_CB_PP_DONE: { tdm_thread_cb_pp_done *pp_done = (tdm_thread_cb_pp_done*)base; -- 2.7.4 From c82ff146433678e371da26fcf96ab8b613f1a7a1 Mon Sep 17 00:00:00 2001 From: Konstantin Drabeniuk Date: Fri, 24 Nov 2017 15:19:45 +0200 Subject: [PATCH 07/16] add excluding coverage comments for tdm_vblank.c add excluding coverage comments for tdm_vblank.c for the folowing code: - _tdm_vblank_cb_output_change; - pthread's fail; - calloc's fail; - tdm_event_loop_source_timer_update() func's fail; - _tdm_vblank_sw_timer_update() func's fail; - funcs for tdm_monitor. Change-Id: I67a22c38fd1ed19fde6ebf12a08681c60554f16c Signed-off-by: Konstantin Drabeniuk --- src/tdm_vblank.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/tdm_vblank.c b/src/tdm_vblank.c index 462eaf5..39eeca6 100644 --- a/src/tdm_vblank.c +++ b/src/tdm_vblank.c @@ -352,6 +352,7 @@ _tdm_vblank_update_output_info(tdm_private_vblank *private_vblank) private_vblank->vrefresh, private_vblank->fps, private_vblank->fps_changeable); } +/* LCOV_EXCL_START */ static void _tdm_vblank_cb_output_change(tdm_output *output, tdm_output_change_type type, tdm_value value, void *user_data) @@ -388,6 +389,7 @@ _tdm_vblank_cb_output_change(tdm_output *output, tdm_output_change_type type, break; } } +/* LCOV_EXCL_STOP */ EXTERN tdm_error tdm_vblank_set_client_vblank_fps(unsigned int pid, const char *name, unsigned int fps) @@ -470,10 +472,12 @@ tdm_vblank_create(tdm_display *dpy, tdm_output *output, tdm_error *error) if (!vblank_list_inited) { if (pthread_mutex_init(&valid_list_lock, NULL)) { + /* LCOV_EXCL_START */ TDM_ERR("mutex init failed: %m"); if (error) *error = TDM_ERROR_OPERATION_FAILED; return NULL; + /* LCOV_EXCL_STOP */ } LIST_INITHEAD(&valid_vblank_list); LIST_INITHEAD(&valid_wait_list); @@ -482,10 +486,12 @@ tdm_vblank_create(tdm_display *dpy, tdm_output *output, tdm_error *error) private_vblank = calloc(1, sizeof * private_vblank); if (!private_vblank) { + /* LCOV_EXCL_START */ if (error) *error = TDM_ERROR_OUT_OF_MEMORY; VER("alloc failed"); return NULL; + /* LCOV_EXCL_STOP */ } tdm_output_add_change_handler(output, _tdm_vblank_cb_output_change, private_vblank); @@ -740,9 +746,11 @@ _tdm_vblank_sw_timer_update(tdm_private_vblank *private_vblank) ret = tdm_event_loop_source_timer_update(private_vblank->SW_timer, ms_delay); if (ret != TDM_ERROR_NONE) { + /* LCOV_EXCL_START */ tdm_display_unlock(private_vblank->dpy); VER("couldn't update timer"); return ret; + /* LCOV_EXCL_STOP */ } tdm_display_unlock(private_vblank->dpy); @@ -1038,9 +1046,11 @@ _tdm_vblank_wait_SW(tdm_vblank_wait_info *wait_info) ret = _tdm_vblank_sw_timer_update(private_vblank); if (ret != TDM_ERROR_NONE) { + /* LCOV_EXCL_START */ LIST_DEL(&wait_info->link); VER("couldn't update sw timer"); return ret; + /* LCOV_EXCL_STOP */ } return TDM_ERROR_NONE; @@ -1079,8 +1089,10 @@ tdm_vblank_wait(tdm_vblank *vblank, unsigned int req_sec, unsigned int req_usec, wait_info = calloc(1, sizeof * wait_info); if (!wait_info) { + /* LCOV_EXCL_START */ VER("alloc failed"); return TDM_ERROR_OUT_OF_MEMORY; + /* LCOV_EXCL_STOP */ } /* set request time to current time if 0. This function seems to be called in server side. */ @@ -1139,6 +1151,7 @@ tdm_vblank_wait(tdm_vblank *vblank, unsigned int req_sec, unsigned int req_usec, } if (ret != TDM_ERROR_NONE) { + /* LCOV_EXCL_START */ LIST_DEL(&wait_info->link); _tdm_vblank_valid_list_del(&wait_info->valid_link); @@ -1148,6 +1161,7 @@ tdm_vblank_wait(tdm_vblank *vblank, unsigned int req_sec, unsigned int req_usec, free(wait_info); return ret; + /* LCOV_EXCL_STOP */ } return TDM_ERROR_NONE; @@ -1204,6 +1218,7 @@ tdm_vblank_wait_seq(tdm_vblank *vblank, unsigned int req_sec, unsigned int req_u return tdm_vblank_wait(vblank, req_sec, req_usec, interval, func, user_data); } +/* LCOV_EXCL_START */ INTERN tdm_error tdm_vblank_set_add_front(tdm_vblank *vblank, unsigned int add_front) { @@ -1220,6 +1235,7 @@ tdm_vblank_set_add_front(tdm_vblank *vblank, unsigned int add_front) return TDM_ERROR_NONE; } +/* LCOV_EXCL_STOP */ INTERN tdm_error tdm_vblank_set_resource(tdm_vblank *vblank, struct wl_resource *resource) @@ -1244,6 +1260,7 @@ tdm_vblank_get_stamp(tdm_vblank *vblank) return private_vblank->stamp; } +/* LCOV_EXCL_START */ INTERN void tdm_vblank_get_vblank_list_information(tdm_display *dpy, char *reply, int *len) { @@ -1276,4 +1293,5 @@ tdm_vblank_get_vblank_list_information(tdm_display *dpy, char *reply, int *len) TDM_SNPRINTF(reply, len, "\n"); } +/* LCOV_EXCL_STOP */ -- 2.7.4 From e4f0f3446d7beefed462cdc445e655b418907df5 Mon Sep 17 00:00:00 2001 From: Roman Marchenko Date: Fri, 24 Nov 2017 16:28:41 +0200 Subject: [PATCH 08/16] utest: Add 10 test cases for tdm_event_loop.c Change-Id: If7286f39557388dd2fedd8f11d32fa015cb23338 Signed-off-by: Roman Marchenko --- utests/Makefile.am | 1 + utests/src/ut_tdm_event_loop.cpp | 198 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 199 insertions(+) create mode 100644 utests/src/ut_tdm_event_loop.cpp diff --git a/utests/Makefile.am b/utests/Makefile.am index eee9511..eab6e26 100644 --- a/utests/Makefile.am +++ b/utests/Makefile.am @@ -10,6 +10,7 @@ tdm_utests_SOURCES = \ src/ut_tdm_buffer.cpp \ src/ut_tdm_helper.cpp \ src/ut_tdm_layer.cpp \ + src/ut_tdm_event_loop.cpp \ src/ut_tdm_vblank.cpp tdm_utests_CXXFLAGS = \ diff --git a/utests/src/ut_tdm_event_loop.cpp b/utests/src/ut_tdm_event_loop.cpp new file mode 100644 index 0000000..62b9165 --- /dev/null +++ b/utests/src/ut_tdm_event_loop.cpp @@ -0,0 +1,198 @@ +#include "gtest/gtest.h" +#include "ut_common.h" +#include "stdint.h" +#include "fcntl.h" + +extern "C" { +#include "tdm.h" +#include "tdm_backend.h" +#include "tbm_bufmgr.h" +#include "tbm_surface.h" +#include "tbm_surface_internal.h" +#include "tbm_drm_helper.h" +} + +class TDMEventLoop: public ::testing::Test +{ +protected: + static tdm_display *dpy; + tdm_error error; + tdm_event_loop_source *loop_src; + int fd; + + static void SetEnv(void) + { + setenv("TDM_DEBUG_MODULE", "all", 1); + setenv("TDM_DEBUG", "1", 1); + setenv("TDM_THREAD", "0", 1); + setenv("XDG_RUNTIME_DIR", "/run", 1); + setenv("TBM_DISPLAY_SERVER", "1", 1); + } + + static void UnsetEnv(void) + { + unsetenv("TDM_DEBUG_MODULE"); + unsetenv("TDM_DEBUG"); + unsetenv("TDM_THREAD"); + unsetenv("XDG_RUNTIME_DIR"); + unsetenv("TBM_DISPLAY_SERVER"); + } + + static void SetUpTestCase() + { + tdm_error error; + SetEnv(); + dpy = tdm_display_init(&error); + ASSERT_NE(NULL, dpy); + ASSERT_EQ(TDM_ERROR_NONE, error); + } + + static void TearDownTestCase() + { + tdm_display_deinit(dpy); + UnsetEnv(); + } + + int GetFd() + { + if (fd == -1) + fd = tbm_drm_helper_get_master_fd(); + return fd; + } + + void SetUp() + { + loop_src = NULL; + fd = -1; + } + + void TearDown() + { + if (loop_src) + tdm_event_loop_source_remove(loop_src); + if (fd >= 0) + close(fd); + } +}; + +tdm_display *TDMEventLoop::dpy = NULL; + +static int handler_is_called = 0; +static tdm_error timer_handler(void *user_data) +{ + if (user_data == &handler_is_called) + handler_is_called = 1; + return TDM_ERROR_NONE; +} + +static tdm_error fd_handler(int fd, tdm_event_loop_mask mask, void *user_data) +{ + if (user_data == &handler_is_called) + handler_is_called = 1; + return TDM_ERROR_NONE; +} + +/*void tdm_event_loop_source_remove(tdm_event_loop_source *source); */ +TEST_F(TDMEventLoop, SourceRemoveFailNULL) +{ + tdm_event_loop_source_remove(NULL); +} + +/* tdm_event_loop_source* tdm_event_loop_add_timer_handler(tdm_display *dpy, + tdm_event_loop_timer_handler func, + void *user_data, tdm_error *error); */ +TEST_F(TDMEventLoop, AddTimerHandlerFailNULL) +{ + loop_src = tdm_event_loop_add_timer_handler(NULL, timer_handler, &handler_is_called, &error); + ASSERT_NE(TDM_ERROR_NONE, error); + ASSERT_EQ(NULL, loop_src); + + loop_src = tdm_event_loop_add_timer_handler(dpy, NULL, &handler_is_called, &error); + ASSERT_NE(TDM_ERROR_NONE, error); + ASSERT_EQ(NULL, loop_src); + + loop_src = tdm_event_loop_add_timer_handler(dpy, NULL, &handler_is_called, NULL); + ASSERT_EQ(NULL, loop_src); +} + +TEST_F(TDMEventLoop, AddTimerHandlerSuccessful) +{ + loop_src = tdm_event_loop_add_timer_handler(dpy, timer_handler, &handler_is_called, &error); + ASSERT_EQ(TDM_ERROR_NONE, error); + ASSERT_NE(NULL, loop_src); +} + +/* tdm_error tdm_event_loop_source_timer_update(tdm_event_loop_source *source, unsigned int ms_delay); */ +TEST_F(TDMEventLoop, SourceTimerUpdateFailNULL) +{ + error = tdm_event_loop_source_timer_update(NULL, 0); + ASSERT_NE(TDM_ERROR_NONE, error); +} +TEST_F(TDMEventLoop, SourceTimerUpdateSuccessful) +{ + loop_src = tdm_event_loop_add_timer_handler(dpy, timer_handler, &handler_is_called, &error); + ASSERT_EQ(TDM_ERROR_NONE, error); + ASSERT_NE(NULL, loop_src); + + error = tdm_event_loop_source_timer_update(loop_src, 10); + ASSERT_EQ(TDM_ERROR_NONE, error); +} + +/* tdm_event_loop_source* tdm_event_loop_add_fd_handler(tdm_display *dpy, int fd, tdm_event_loop_mask mask, + tdm_event_loop_fd_handler func, void *user_data, + tdm_error *error); */ +TEST_F(TDMEventLoop, AddFdHandlerFailNULL) +{ + loop_src = tdm_event_loop_add_fd_handler(NULL, 0, TDM_EVENT_LOOP_READABLE, + fd_handler, &handler_is_called, &error); + ASSERT_EQ(NULL, loop_src); + ASSERT_NE(TDM_ERROR_NONE, error); + + loop_src = tdm_event_loop_add_fd_handler(dpy, 0, TDM_EVENT_LOOP_READABLE, + NULL, &handler_is_called, &error); + ASSERT_NE(TDM_ERROR_NONE, error); + ASSERT_EQ(NULL, loop_src); +} + +TEST_F(TDMEventLoop, AddFdHandlerFailInvalidFd) +{ + loop_src = tdm_event_loop_add_fd_handler(dpy, -1, TDM_EVENT_LOOP_READABLE, + fd_handler, &handler_is_called, &error); + ASSERT_NE(TDM_ERROR_NONE, error); + ASSERT_EQ(NULL, loop_src); +} + +TEST_F(TDMEventLoop, AddFdHandlerSuccessful) +{ + int fd = GetFd(); + ASSERT_NE(-1, fd); + + loop_src = tdm_event_loop_add_fd_handler(dpy, fd, TDM_EVENT_LOOP_READABLE, + fd_handler, &handler_is_called, &error); + ASSERT_EQ(TDM_ERROR_NONE, error); + ASSERT_NE(NULL, loop_src); +} + +/* tdm_error tdm_event_loop_source_fd_update(tdm_event_loop_source *source, tdm_event_loop_mask mask); */ +TEST_F(TDMEventLoop, SourceFdUpdateFailNULL) +{ + error = tdm_event_loop_source_fd_update(NULL, TDM_EVENT_LOOP_READABLE); +} + +TEST_F(TDMEventLoop, SourceFdUpdateSuccessful) +{ + int fd; + tdm_event_loop_mask flag = TDM_EVENT_LOOP_WRITABLE; + + fd = GetFd(); + ASSERT_NE(-1, fd); + + loop_src = tdm_event_loop_add_fd_handler(dpy, fd, flag, + fd_handler, &handler_is_called, &error); + ASSERT_EQ(TDM_ERROR_NONE, error); + ASSERT_NE(NULL, loop_src); + + error = tdm_event_loop_source_fd_update(loop_src, TDM_EVENT_LOOP_READABLE); + ASSERT_EQ(TDM_ERROR_NONE, error); +} + -- 2.7.4 From 802f43a791f330e67fad0873b3efcd022e01dfd8 Mon Sep 17 00:00:00 2001 From: Roman Marchenko Date: Fri, 24 Nov 2017 18:00:41 +0200 Subject: [PATCH 09/16] add excluding coverage comments for tdm_event_loop.c for folowing code: - inner functions Change-Id: Ic3065fa1a0f3e81bff1332b7721d4866a2635286 Signed-off-by: Roman Marchenko --- src/tdm_event_loop.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tdm_event_loop.c b/src/tdm_event_loop.c index 1c88685..bb0ed57 100644 --- a/src/tdm_event_loop.c +++ b/src/tdm_event_loop.c @@ -472,6 +472,7 @@ tdm_event_loop_source_remove(tdm_event_loop_source *source) free(source); } +/* LCOV_EXCL_START */ static void _trace_cb_client_destroy(struct wl_listener *listener, void *data) { @@ -658,3 +659,4 @@ tdm_event_loop_trace_enable(tdm_private_display * private_display, return TDM_ERROR_NONE; } +/* LCOV_EXCL_STOP */ -- 2.7.4 From 6beeb1293d6ed6d6680e956849dd025c00e35379 Mon Sep 17 00:00:00 2001 From: Sergey Sizonov Date: Fri, 24 Nov 2017 15:40:16 +0300 Subject: [PATCH 10/16] utest: Add 62 tests cases for tdm_client Change-Id: If704891c1c2754baacfafdd6f327a94bb5fdc937 Signed-off-by: Sergey Sizonov --- utests/Makefile.am | 5 +- utests/src/ut_tdm_client.cpp | 1097 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1101 insertions(+), 1 deletion(-) create mode 100644 utests/src/ut_tdm_client.cpp diff --git a/utests/Makefile.am b/utests/Makefile.am index eab6e26..fe1e8b5 100644 --- a/utests/Makefile.am +++ b/utests/Makefile.am @@ -11,13 +11,15 @@ tdm_utests_SOURCES = \ src/ut_tdm_helper.cpp \ src/ut_tdm_layer.cpp \ src/ut_tdm_event_loop.cpp \ - src/ut_tdm_vblank.cpp + src/ut_tdm_vblank.cpp \ + src/ut_tdm_client.cpp tdm_utests_CXXFLAGS = \ $(CXXFLAGS) \ $(TDM_CFLAGS) \ -I../src \ -I../include \ + -I../client \ -I./src \ -I$(includedir)/gtest \ -fpermissive \ @@ -31,6 +33,7 @@ tdm_utests_LDFLAGS = \ ${LDFLAGS} \ $(TDM_LIBS) \ $(top_builddir)/src/libtdm.la \ + $(top_builddir)/client/libtdm-client.la \ -lgtest check: diff --git a/utests/src/ut_tdm_client.cpp b/utests/src/ut_tdm_client.cpp new file mode 100644 index 0000000..a8e695e --- /dev/null +++ b/utests/src/ut_tdm_client.cpp @@ -0,0 +1,1097 @@ +/************************************************************************** + * + * Copyright 2017 Samsung Electronics co., Ltd. All Rights Reserved. + * + * Contact: Konstantin Drabeniuk + * Contact: Andrii Sokolenko + * Contact: Roman Marchenko + * Contact: Sergey Sizonov + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * +**************************************************************************/ + +#include "gtest/gtest.h" +#include "ut_common.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" +{ +#include "tdm.h" +#include "tdm_client.h" + +#include "tbm_surface.h" + +#include "wayland-client.h" +} + +class tdm_client_test_prepare +{ +public: + tdm_client_test_prepare() + { + /* we have to deal with a named semaphore to protect an access to tdm across several instances + * of servers */ + semaphore = sem_open(semaphore_name.c_str(), O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR, 1); + if (semaphore == SEM_FAILED) + { + if (errno == EEXIST) + sem_unlink(semaphore_name.c_str()); + else + { + std::cout << "can't create semaphore(1): " << semaphore_name << ", errno: " << errno << ".\n"; + exit(EXIT_FAILURE); + } + } else { + return; + } + + semaphore = sem_open(semaphore_name.c_str(), O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR, 1); + if (semaphore == SEM_FAILED) + { + std::cout << "can't create semaphore(2): " << semaphore_name << ", errno: " << errno << ".\n"; + exit(EXIT_FAILURE); + } + } + + ~tdm_client_test_prepare() + { + sem_close(semaphore); + sem_unlink(semaphore_name.c_str()); + } + + static sem_t *semaphore; + + /* /dev/shm/sem.tdm-client-utests */ + static const std::string semaphore_name; +}; + +sem_t *tdm_client_test_prepare::semaphore; +const std::string tdm_client_test_prepare::semaphore_name = "/tdm-client-utests"; + +/* global object is created before main() */ +tdm_client_test_prepare dont_use_it; + +/* real mess, sorry... */ +class TDMClientTest : public ::testing::Test +{ +protected: + TDMClientTest() : error(TDM_ERROR_NONE), server_pid(0), cl_serv_lock_fd(-1), + dsp(nullptr), output(nullptr), layer(nullptr), buffer(nullptr), is_server_stopped(false) + { + set_env_vars(); + start_server(); /* as a separate process */ + wait_till_server_ready(); + } + + ~TDMClientTest() + { + _stop_server(); + unset_env_vars(); + } + + void send_request_to_server(int req) + { + switch(req) + { + case ChangeDPMS: + send_request(ChangeDPMS); + break; + + default: + break; + } + } + + /* to stop server by user demand */ + void stop_server(void) + { + _stop_server(); + wait_till_serv_is_over(); + + /* TODO: maybe it makes a sense to use this approach in the dtor too */ + } + + enum + { + ChangeDPMS, + }; + +private: + void set_env_vars(void) + { + setenv("XDG_RUNTIME_DIR", "/run", 1); + setenv("TBM_DISPLAY_SERVER", "1", 1); + } + + void unset_env_vars(void) + { + unsetenv("TBM_DISPLAY_SERVER"); + unsetenv("XDG_RUNTIME_DIR"); + } + + void start_server(void) + { + cl_serv_lock_fd = eventfd(0, 0); + socketpair(AF_UNIX, SOCK_STREAM, 0, reinterpret_cast(&socks_pair)); + + server_pid = fork(); + + if (server_pid) + { + close(socks_pair.server_socket); + return; + } + + close(socks_pair.client_socket); + + wait_till_serv_resources_available(); + run_server(); + } + + void _stop_server(void) + { + if (is_server_stopped) return; + + close(socks_pair.client_socket); + close(cl_serv_lock_fd); + kill(server_pid, SIGINT); + + is_server_stopped = true; + } + + void wait_till_server_ready(void) + { + uint64_t val; + + if (read(cl_serv_lock_fd, &val, sizeof val) < 0) + std::cout << "error while trying to read from cl_serv_lock_fd eventfd object.\n"; + } + + void notify_server_ready(void) + { + uint64_t val; + + val = 1; + + if (write(cl_serv_lock_fd, &val, sizeof val) < 0) + std::cout << "error while trying to write to cl_serv_lock_fd evenfd object.\n"; + } + + void wait_till_serv_resources_available(void) + { + while (1) + { + int ret; + + ret = sem_wait(tdm_client_test_prepare::semaphore); + if (ret < 0 && errno == EINTR) + continue; + else + break; + } + } + + void notify_serv_resources_available(void) + { + sem_post(tdm_client_test_prepare::semaphore); + + sem_close(tdm_client_test_prepare::semaphore); + sem_unlink(tdm_client_test_prepare::semaphore_name.c_str()); + } + + void wait_till_serv_is_over(void) + { + wait_till_serv_resources_available(); + sem_post(tdm_client_test_prepare::semaphore); + } + + void send_request(int req) + { + send(socks_pair.client_socket, &req, sizeof req, 0); + } + + void handle_client_request() + { + int req; + + recv(socks_pair.server_socket, &req, sizeof req, 0); + + switch(req) + { + case ChangeDPMS: + change_dpms_request_handler(); + break; + + default: + break; + } + } + + void run_server(void) + { + sigset_t mask; + int signal_fd; + int tdm_fd; + pollfd work_fds[3]; + + /* ask kernel to notify us about parent's die via SIGHUP signal */ + prctl(PR_SET_PDEATHSIG, SIGHUP); + + sigemptyset(&mask); + sigaddset(&mask, SIGINT); + sigaddset(&mask, SIGHUP); + + sigprocmask(SIG_BLOCK, &mask, NULL); + + signal_fd = signalfd(-1, &mask, 0); + + init_tdm(); + tdm_display_get_fd(dsp, &tdm_fd); + + std::memset(&work_fds, 0, sizeof work_fds); + + work_fds[0].fd = signal_fd; + work_fds[0].events = POLLIN; + + work_fds[1].fd = tdm_fd; + work_fds[1].events = POLLIN; + + work_fds[2].fd = socks_pair.server_socket; + work_fds[2].events = POLLIN; + + notify_server_ready(); + + while (1) + { + int ret; + + ret = poll(work_fds, 3, -1); + if (ret < 0 && errno == EINTR) continue; + + if (work_fds[0].revents == POLLIN) + { + signal_hndl(); + exit(EXIT_SUCCESS); + } + + if(work_fds[1].revents == POLLIN) + tdm_display_handle_events(dsp); + + if(work_fds[2].revents == POLLIN) + handle_client_request(); + } + } + + void signal_hndl(void) + { + close(socks_pair.server_socket); + close(cl_serv_lock_fd); + + deinit_tdm(); + notify_serv_resources_available(); + } + + void init_tdm(void); + void deinit_tdm(void); + + void set_layer_geometry(int w, int h); + void set_image_on_screen(int w, int h); + + void change_dpms_request_handler(void); + + struct sockets_pair + { + sockets_pair() : server_socket(0), client_socket(0) {} + int server_socket; + int client_socket; + }; + +protected: + tdm_error error; + +private: + pid_t server_pid; + int cl_serv_lock_fd; + sockets_pair socks_pair; + + tdm_display *dsp; + tdm_output *output; + tdm_layer *layer; + + tbm_surface_h buffer; + + bool is_server_stopped; +}; + +class TDMClientTestClient : public TDMClientTest +{ +protected: + TDMClientTestClient() : TDMClientTest() + { + tdm_cl = tdm_client_create(nullptr); + } + ~TDMClientTestClient() + { + tdm_client_destroy(tdm_cl); + } + +protected: + tdm_client *tdm_cl; +}; + +class TDMClientTestClientOutput : public TDMClientTestClient +{ +protected: + TDMClientTestClientOutput() : TDMClientTestClient() + { + cl_output = tdm_client_get_output(tdm_cl, const_cast("primary"), nullptr); + } + ~TDMClientTestClientOutput() + { + } + +protected: + tdm_client_output* cl_output; +}; + +class TDMClientTestVblank : public TDMClientTestClientOutput +{ +protected: + TDMClientTestVblank() : TDMClientTestClientOutput() + { + cl_vblank = tdm_client_output_create_vblank(cl_output, nullptr); + } + ~TDMClientTestVblank() + { + tdm_client_vblank_destroy(cl_vblank); + } + +protected: + tdm_client_vblank* cl_vblank; +}; + +typedef TDMClientTest TDMClientTestDeathTest; +typedef TDMClientTestClient TDMClientTestClientDeathTest; +typedef TDMClientTestClientOutput TDMClientTestClientOutputDeathTest; +typedef TDMClientTestVblank TDMClientTestVblankDeathTest; + + +void TDMClientTest::set_layer_geometry(int w, int h) +{ + tdm_info_layer layer_info; + + std::memset(&layer_info, 0, sizeof(tdm_info_layer)); + + layer_info.src_config.size.h = w; + layer_info.src_config.size.v = h; + layer_info.src_config.pos.x = 0; + layer_info.src_config.pos.y = 0; + layer_info.src_config.pos.w = w; + layer_info.src_config.pos.h = h; + layer_info.src_config.format = TBM_FORMAT_ARGB8888; + layer_info.dst_pos.x = 0; + layer_info.dst_pos.y = 0; + layer_info.dst_pos.w = w; + layer_info.dst_pos.h = h; + layer_info.transform = TDM_TRANSFORM_NORMAL; + + tdm_layer_set_info(layer, &layer_info); +} + +void TDMClientTest::set_image_on_screen(int w, int h) +{ + tbm_surface_info_s tbm_surface_info; + + /* to have a hw vblank we have to make at least one tdm_commit */ + buffer = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888); + + std::memset(&tbm_surface_info, 0, sizeof(tbm_surface_info_s)); + + tbm_surface_map(buffer, TBM_SURF_OPTION_WRITE, &tbm_surface_info); + + int *img = (int *)tbm_surface_info.planes[0].ptr; + + for (uint32_t i = 0; i < tbm_surface_info.height; i++) + for (uint32_t j = 0; j < tbm_surface_info.planes[0].stride / 4; j++) + *img++ = 0x0000000; + + tbm_surface_unmap(buffer); + + set_layer_geometry(w, h); + tdm_layer_set_buffer(layer, buffer); + tdm_output_commit(output, 0, nullptr, nullptr); +} + +void TDMClientTest::init_tdm(void) +{ + int outputs_cnt = 0; + tdm_output_type tdm_output_type; + + int output_modes_cnt = 0; + const tdm_output_mode* output_modes; + const tdm_output_mode* preferred_mode = NULL; + + int layers_cnt = 0; + tdm_layer_capability tdm_layer_capability; + + dsp = tdm_display_init(nullptr); + + tdm_display_get_output_count(dsp, &outputs_cnt); + + /* this part is hardware dependent, how to resolve this issue ? */ + for (int i = 0; i < outputs_cnt; i++) + { + output = tdm_display_get_output(dsp, i, nullptr); + tdm_output_get_output_type(output, &tdm_output_type); + + /* we're not interesting about other outputs */ + if (tdm_output_type != TDM_OUTPUT_TYPE_VIRTUAL && + tdm_output_type != TDM_OUTPUT_TYPE_HDMIA) + break; + } + + /* get output's preferred mode to obtain width & height we'll use later to create surface */ + tdm_output_get_available_modes(output, &output_modes, &output_modes_cnt); + + /* look for output's preferred mode */ + for (int i = 0; i < output_modes_cnt; i++) + { + if (output_modes[i].type & TDM_OUTPUT_MODE_TYPE_PREFERRED) + { + preferred_mode = &output_modes[i]; + break; + } + } + + tdm_output_set_mode(output, preferred_mode); + + tdm_output_get_layer_count(output, &layers_cnt); + + /* it supposed that output always has primary & graphic layer */ + for (int i = 0; i < layers_cnt; i++) + { + layer = tdm_output_get_layer(output, i, nullptr); + tdm_layer_get_capabilities(layer, &tdm_layer_capability); + + if ((tdm_layer_capability & TDM_LAYER_CAPABILITY_PRIMARY) && + (tdm_layer_capability & TDM_LAYER_CAPABILITY_GRAPHIC)) + break; + } + + tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_ON); + + set_image_on_screen(preferred_mode->hdisplay, preferred_mode->vdisplay); +} + +void TDMClientTest::deinit_tdm(void) +{ + if (layer) + { + tdm_layer_unset_buffer(layer); + tdm_output_commit(output, 1, nullptr, nullptr); + } + + if (buffer) + tbm_surface_internal_unref(buffer); + + if (dsp) + tdm_display_deinit(dsp); +} + +void TDMClientTest::change_dpms_request_handler(void) +{ + std::cout << "tdm_output_set_dpms.\n"; + tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_OFF); +} + +TEST_F(TDMClientTest, TdmClientCreateSuccessfulCheckClient) +{ + tdm_client *tdm_cl = tdm_client_create(nullptr); + ASSERT_TRUE(nullptr != tdm_cl); + + tdm_client_destroy(tdm_cl); +} + +TEST_F(TDMClientTest, TdmClientCreateSuccessfulCheckError) +{ + tdm_client* tdm_cl = tdm_client_create(&error); + ASSERT_TRUE(TDM_ERROR_NONE == error); + + tdm_client_destroy(tdm_cl); +} + +TEST_F(TDMClientTest, TdmClientCreateFailServerStoppedCheckError) +{ + stop_server(); + + tdm_client_create(&error); + ASSERT_TRUE(TDM_ERROR_OPERATION_FAILED == error); +} + +TEST_F(TDMClientTest, TdmClientCreateFailServerStopped) +{ + stop_server(); + + tdm_client *tdm_cl = tdm_client_create(nullptr); + ASSERT_TRUE(nullptr == tdm_cl); +} + +TEST_F(TDMClientTestDeathTest, TdmClientDestroySuccessful) +{ + ASSERT_EXIT( + { + tdm_client_destroy(nullptr); + + exit(EXIT_SUCCESS); + }, + ::testing::ExitedWithCode(EXIT_SUCCESS), ""); +} + +TEST_F(TDMClientTestDeathTest, TdmClientDestroySuccessfulServerStopped) +{ + ASSERT_EXIT( + { + tdm_client *tdm_cl = tdm_client_create(nullptr); + + stop_server(); + + tdm_client_destroy(tdm_cl); + + exit(EXIT_SUCCESS); + }, + ::testing::ExitedWithCode(EXIT_SUCCESS), ""); +} + +TEST_F(TDMClientTestClient, TdmClientGetFdSuccessful) +{ + int fd; + + tdm_client_get_fd(tdm_cl, &fd); + ASSERT_TRUE(0 < fd); +} + +TEST_F(TDMClientTestClient, TdmClientGetFdSuccessfulCheckError) +{ + int fd; + + error = tdm_client_get_fd(tdm_cl, &fd); + ASSERT_TRUE(TDM_ERROR_NONE == error); +} + +TEST_F(TDMClientTestClient, TdmClientGetFdFailNullTdmClient) +{ + int fd; + + error = tdm_client_get_fd(nullptr, &fd); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestClient, TdmClientGetFdFailNullFd) +{ + error = tdm_client_get_fd(nullptr, nullptr); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestClient, DISABLED_TdmClientHandleEventsSuccessful) +{ + ASSERT_EXIT( + { + pollfd work_fds[2]; + itimerspec times_up; + + std::memset(&work_fds, 0, sizeof work_fds); + std::memset(×_up, 0, sizeof times_up); + + tdm_client_get_fd(tdm_cl, &work_fds[0].fd); + work_fds[0].events = POLLIN; + + work_fds[1].fd = timerfd_create(CLOCK_MONOTONIC, 0); + work_fds[1].events = POLLIN; + + times_up.it_value.tv_nsec = 100000000; /* 100ms */ + timerfd_settime(work_fds[1].fd, 0, ×_up, nullptr); + + while (1) + { + int ret; + + ret = poll(work_fds, 2, -1); + if (ret < 0 && errno == EINTR) continue; + + if (work_fds[0].revents == POLLIN) + { + tdm_client_handle_events(tdm_cl); + std::cout << "ha.\n"; + } + + if(work_fds[1].revents == POLLIN) + exit(EXIT_SUCCESS); + } + }, + ::testing::ExitedWithCode(EXIT_SUCCESS), ""); +} + +TEST_F(TDMClientTestClient, TdmClientHandleEventsFailNullTDMClient) +{ + error = tdm_client_handle_events(nullptr); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestClient, TdmClientGetOutputSuccessful) +{ + tdm_client_output* cl_output; + + cl_output = tdm_client_get_output(tdm_cl, const_cast("primary"), nullptr); + ASSERT_TRUE(nullptr != cl_output); +} + +TEST_F(TDMClientTestClient, TdmClientGetOutputSuccessfulCallTwice) +{ + tdm_client_output* cl_output_1, *cl_output_2; + + cl_output_1 = tdm_client_get_output(tdm_cl, const_cast("primary"), nullptr); + cl_output_2 = tdm_client_get_output(tdm_cl, const_cast("primary"), nullptr); + ASSERT_TRUE(cl_output_1 == cl_output_2); +} + +TEST_F(TDMClientTestClient, TdmClientGetOutputSuccessfulCheckError) +{ + tdm_client_get_output(tdm_cl, const_cast("primary"), &error); + ASSERT_TRUE(TDM_ERROR_NONE == error); +} + +TEST_F(TDMClientTestClient, TdmClientGetOutputSuccessfulNullName) +{ + tdm_client_output* cl_output; + + cl_output = tdm_client_get_output(tdm_cl, nullptr, nullptr); + ASSERT_TRUE(nullptr != cl_output); +} + +TEST_F(TDMClientTestClient, TdmClientGetOutputSuccessfulNullNameCheckError) +{ + tdm_client_get_output(tdm_cl, nullptr, &error); + ASSERT_TRUE(TDM_ERROR_NONE == error); +} + +TEST_F(TDMClientTestClient, TdmClientGetOutputFailNullTdmClient) +{ + tdm_client_output* cl_output; + + cl_output = tdm_client_get_output(nullptr, const_cast("primary"), nullptr); + ASSERT_TRUE(nullptr == cl_output); +} + +TEST_F(TDMClientTestClient, TdmClientGetOutputFailNullTdmClientCheckError) +{ + tdm_client_get_output(nullptr, const_cast("primary"), &error); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestClientOutput, DISABLED_TdmClientOutputAddChangeHandlerSuccessful) +{ + static bool got_an_event = false; + wl_display *wl_dsp; + + /* is this function implemented fully? */ + tdm_client_output_add_change_handler(cl_output, [] (tdm_client_output *output, + tdm_output_change_type type, + tdm_value value, + void *user_data) { got_an_event = true; }, nullptr); + + /* force a requests flush */ + wl_dsp = wl_display_connect("tdm-socket"); + wl_display_flush(wl_dsp); + wl_display_roundtrip(wl_dsp); + wl_display_disconnect(wl_dsp); + + send_request_to_server(TDMClientTest::ChangeDPMS); + tdm_client_handle_events(tdm_cl); + + ASSERT_TRUE(true == got_an_event); +} + +TEST_F(TDMClientTestClientOutput, TdmClientOutputAddChangeHandlerFailNullOutput) +{ + error = tdm_client_output_add_change_handler(nullptr, [] (tdm_client_output *output, + tdm_output_change_type type, + tdm_value value, + void *user_data) {}, nullptr); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestClientOutput, TdmClientOutputAddChangeHandlerFailNullHandler) +{ + error = tdm_client_output_add_change_handler(cl_output, nullptr, nullptr); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestClientOutputDeathTest, TdmClientOutputRemoveChangeHandlerSuccessful) +{ + ASSERT_EXIT( + { + auto func = [] (tdm_client_output *output, tdm_output_change_type type, tdm_value value, + void *user_data) {}; + + tdm_client_output_add_change_handler(cl_output, func, nullptr); + + tdm_client_output_remove_change_handler(cl_output, func, nullptr); + + exit(EXIT_SUCCESS); + }, + ::testing::ExitedWithCode(EXIT_SUCCESS), ""); +} + +TEST_F(TDMClientTestClientOutputDeathTest, TdmClientOutputRemoveChangeHandlerSuccessfulInvalidHandler) +{ + ASSERT_EXIT( + { + auto func = [] (tdm_client_output *output, tdm_output_change_type type, tdm_value value, + void *user_data) {}; + + tdm_client_output_remove_change_handler(cl_output, func, nullptr); + + exit(EXIT_SUCCESS); + }, + ::testing::ExitedWithCode(EXIT_SUCCESS), ""); +} + +TEST_F(TDMClientTestClientOutputDeathTest, TdmClientOutputRemoveChangeHandlerFailNullOutput) +{ + ASSERT_EXIT( + { + auto func = [] (tdm_client_output *output, tdm_output_change_type type, tdm_value value, + void *user_data) {}; + + tdm_client_output_remove_change_handler(nullptr, func, nullptr); + + exit(EXIT_SUCCESS); + }, + ::testing::ExitedWithCode(EXIT_SUCCESS), ""); +} + +TEST_F(TDMClientTestClientOutputDeathTest, TdmClientOutputRemoveChangeHandlerFailNullHandler) +{ + ASSERT_EXIT( + { + tdm_client_output_remove_change_handler(cl_output, nullptr, nullptr); + + exit(EXIT_SUCCESS); + }, + ::testing::ExitedWithCode(EXIT_SUCCESS), ""); +} + +TEST_F(TDMClientTestClientOutput, TdmClientOutputGetRefreshRateSuccessful) +{ + uint32_t refresh_rate; + + error = tdm_client_output_get_refresh_rate(cl_output, &refresh_rate); + ASSERT_TRUE(TDM_ERROR_NONE == error); +} + +TEST_F(TDMClientTestClientOutput, TdmClientOutputGetRefreshRateFailNullOutput) +{ + uint32_t refresh_rate; + + error = tdm_client_output_get_refresh_rate(nullptr, &refresh_rate); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestClientOutput, TdmClientOutputGetRefreshRateFailNullRefreshRate) +{ + error = tdm_client_output_get_refresh_rate(cl_output, nullptr); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestClientOutput, TdmClientOutputGetConnectionStatusSuccessful) +{ + tdm_output_conn_status conn_status; + + error = tdm_client_output_get_conn_status(cl_output, &conn_status); + ASSERT_TRUE(TDM_ERROR_NONE == error); +} + +TEST_F(TDMClientTestClientOutput, TdmClientOutputGetConnectionStatusFailNullOutput) +{ + tdm_output_conn_status conn_status; + + error = tdm_client_output_get_conn_status(nullptr, &conn_status); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestClientOutput, TTdmClientOutputGetConnectionStatusFailNullConnState) +{ + error = tdm_client_output_get_conn_status(cl_output, nullptr); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestClientOutput, TdmClientOutputGetDpmsSuccessful) +{ + tdm_output_dpms dpms_val; + + error = tdm_client_output_get_dpms(cl_output, &dpms_val); + ASSERT_TRUE(TDM_ERROR_NONE == error); +} + +TEST_F(TDMClientTestClientOutput, TdmClientOutputGetDpmsFailNullOutput) +{ + tdm_output_dpms dpms_val; + + error = tdm_client_output_get_dpms(nullptr, &dpms_val); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestClientOutput, TdmClientOutputGetDpmsFailNullDpmsArg) +{ + error = tdm_client_output_get_dpms(cl_output, nullptr); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestClientOutput, TdmClientOutputCreateVblankSuccessful) +{ + tdm_client_vblank* cl_vblank; + + cl_vblank = tdm_client_output_create_vblank(cl_output, nullptr); + ASSERT_TRUE(nullptr != cl_vblank); + + tdm_client_vblank_destroy(cl_vblank); +} + +TEST_F(TDMClientTestClientOutput, TdmClientOutputCreateVblankSuccessfulCheckError) +{ + tdm_client_vblank* cl_vblank; + + cl_vblank = tdm_client_output_create_vblank(cl_output, &error); + ASSERT_TRUE(TDM_ERROR_NONE == error); + + tdm_client_vblank_destroy(cl_vblank); +} + +TEST_F(TDMClientTestClientOutput, TdmClientOutputCreateVblankFailNullOutput) +{ + tdm_client_vblank* cl_vblank; + + cl_vblank = tdm_client_output_create_vblank(nullptr, nullptr); + ASSERT_TRUE(nullptr == cl_vblank); +} + +TEST_F(TDMClientTestClientOutput, TdmClientOutputCreateVblankFailNullOutputCheckError) +{ + tdm_client_output_create_vblank(nullptr, &error); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestClientOutputDeathTest, TdmClientDestroyVblankSuccessful) +{ + ASSERT_EXIT( + { + tdm_client_vblank *cl_vblank = tdm_client_output_create_vblank(cl_output, nullptr); + + tdm_client_vblank_destroy(cl_vblank); + exit(EXIT_SUCCESS); + }, + ::testing::ExitedWithCode(EXIT_SUCCESS), ""); +} + +TEST_F(TDMClientTestClientOutputDeathTest, TdmClientDestroyVblankFailNoClientVblankArg) +{ + ASSERT_EXIT( + { + tdm_client_vblank_destroy(nullptr); + exit(EXIT_SUCCESS); + }, + ::testing::ExitedWithCode(EXIT_SUCCESS), ""); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankSetNameSuccessful) +{ + error = tdm_client_vblank_set_name(cl_vblank, "wassup"); + ASSERT_TRUE(TDM_ERROR_NONE == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankSetNameSuccessfulNoExplicitName) +{ + error = tdm_client_vblank_set_name(cl_vblank, nullptr); + ASSERT_TRUE(TDM_ERROR_NONE == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankSetNameFailNullClientVblank) +{ + error = tdm_client_vblank_set_name(nullptr, "wassup"); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankSetSyncSuccessful) +{ + error = tdm_client_vblank_set_sync(cl_vblank, 0); + ASSERT_TRUE(TDM_ERROR_NONE == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankSetSyncFailNullClientVblank) +{ + error = tdm_client_vblank_set_sync(nullptr, 0); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankSetFpsSuccessful) +{ + error = tdm_client_vblank_set_fps(cl_vblank, 60); + ASSERT_TRUE(TDM_ERROR_NONE == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankSetFpsSuccessfulSetTwice) +{ + tdm_client_vblank_set_fps(cl_vblank, 60); + error = tdm_client_vblank_set_fps(cl_vblank, 60); + ASSERT_TRUE(TDM_ERROR_NONE == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankSetFpsFailNullClientVblank) +{ + error = tdm_client_vblank_set_fps(nullptr, 60); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankSetFpsFailInvalidFpsArg) +{ + error = tdm_client_vblank_set_fps(cl_vblank, 0); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankSetOffsetSuccessful) +{ + error = tdm_client_vblank_set_offset(cl_vblank, 10); + ASSERT_TRUE(TDM_ERROR_NONE == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankSetOffsetSuccessfulSetTwice) +{ + tdm_client_vblank_set_offset(cl_vblank, 10); + error = tdm_client_vblank_set_offset(cl_vblank, 10); + ASSERT_TRUE(TDM_ERROR_NONE == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankSetOffsetFailNullClientVblank) +{ + error = tdm_client_vblank_set_offset(nullptr, 10); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankSetFakeSuccessfulEnableFake) +{ + error = tdm_client_vblank_set_enable_fake(cl_vblank, 1); + ASSERT_TRUE(TDM_ERROR_NONE == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankSetFakeSuccessfulDisableFake) +{ + error = tdm_client_vblank_set_enable_fake(cl_vblank, 0); + ASSERT_TRUE(TDM_ERROR_NONE == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankSetFakeSuccessfulSetTwice) +{ + tdm_client_vblank_set_enable_fake(cl_vblank, 0); + error = tdm_client_vblank_set_enable_fake(cl_vblank, 0); + ASSERT_TRUE(TDM_ERROR_NONE == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankSetFakeFailNullClientVblank) +{ + error = tdm_client_vblank_set_enable_fake(nullptr, 0); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankWaitSuccessful) +{ + auto func = [](tdm_client_vblank *vblank, tdm_error error, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, void *user_data) {}; + + tdm_client_vblank_set_sync(cl_vblank, 0); + tdm_client_vblank_set_enable_fake(cl_vblank, 1); + + error = tdm_client_vblank_wait(cl_vblank, 1, func, nullptr); + ASSERT_TRUE(TDM_ERROR_NONE == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankWaitFailNullClientVblank) +{ + auto func = [](tdm_client_vblank *vblank, tdm_error error, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, void *user_data) {}; + + error = tdm_client_vblank_wait(nullptr, 1, func, nullptr); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankWaitFailNullHandler) +{ + error = tdm_client_vblank_wait(cl_vblank, 1, nullptr, nullptr); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankWaitFailInvalidInterval) +{ + auto func = [](tdm_client_vblank *vblank, tdm_error error, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, void *user_data) {}; + + error = tdm_client_vblank_wait(cl_vblank, 0, func, nullptr); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankWaitSequencySuccessful) +{ + auto func = [](tdm_client_vblank *vblank, tdm_error error, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, void *user_data) {}; + + tdm_client_vblank_set_sync(cl_vblank, 0); + tdm_client_vblank_set_enable_fake(cl_vblank, 1); + + error = tdm_client_vblank_wait_seq(cl_vblank, 100, func, nullptr); + ASSERT_TRUE(TDM_ERROR_NONE == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankWaitSequencyFailNullClientVblank) +{ + auto func = [](tdm_client_vblank *vblank, tdm_error error, unsigned int sequence, + unsigned int tv_sec, unsigned int tv_usec, void *user_data) {}; + + error = tdm_client_vblank_wait_seq(nullptr, 1, func, nullptr); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + +TEST_F(TDMClientTestVblank, TdmClientVblankWaitSequencyFailNullHandler) +{ + error = tdm_client_vblank_wait_seq(cl_vblank, 1, nullptr, nullptr); + ASSERT_TRUE(TDM_ERROR_INVALID_PARAMETER == error); +} + -- 2.7.4 From ee372d00fb3da283d88a8d1b25b12ce87c31bf04 Mon Sep 17 00:00:00 2001 From: Sergey Sizonov Date: Mon, 27 Nov 2017 12:35:10 +0300 Subject: [PATCH 11/16] fix svace warnings Change-Id: I4835f45443a7c38353cfc01f0fa3c897cc6d5f04 Signed-off-by: Sergey Sizonov --- utests/src/ut_tdm_client.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/utests/src/ut_tdm_client.cpp b/utests/src/ut_tdm_client.cpp index a8e695e..3c88875 100644 --- a/utests/src/ut_tdm_client.cpp +++ b/utests/src/ut_tdm_client.cpp @@ -493,6 +493,14 @@ void TDMClientTest::init_tdm(void) } } + if (!preferred_mode) + { + std::cout << "no preferred mode, server's gonna be stopped.\n"; + + deinit_tdm(); + exit(EXIT_FAILURE); + } + tdm_output_set_mode(output, preferred_mode); tdm_output_get_layer_count(output, &layers_cnt); -- 2.7.4 From d39a0db0af66d6ca74734df9ddcbe892b5a5398e Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 27 Nov 2017 17:44:18 +0900 Subject: [PATCH 12/16] output: add debug log Change-Id: I36f24f5c2e53f56c8568888bd6e305a62dd6eb1b --- src/tdm_output.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tdm_output.c b/src/tdm_output.c index 855c352..7449637 100644 --- a/src/tdm_output.c +++ b/src/tdm_output.c @@ -1073,8 +1073,11 @@ tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode) } ret = func_output->output_set_mode(private_output->output_backend, mode); - if (ret == TDM_ERROR_NONE) + if (ret == TDM_ERROR_NONE) { private_output->current_mode = mode; + TDM_INFO("mode: %dx%d %dhz", mode->hdisplay, mode->vdisplay, mode->vrefresh); + } + _pthread_mutex_unlock(&private_display->lock); return ret; -- 2.7.4 From 8494d02d00769b90a00a38dc4049bbbf891895c9 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 27 Nov 2017 17:44:40 +0900 Subject: [PATCH 13/16] tools: fix syntax error Change-Id: I0d857f566ed34dcd415939b7b2fe4b4062320f7f --- tools/tdm_test_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/tdm_test_server.c b/tools/tdm_test_server.c index ff7b542..af3c303 100644 --- a/tools/tdm_test_server.c +++ b/tools/tdm_test_server.c @@ -930,7 +930,7 @@ output_setup(tdm_test_server_output *o) } if (!best) best = &modes[i]; - if (modes[i].flags & TDM_OUTPUT_MODE_TYPE_PREFERRED) + if (modes[i].type & TDM_OUTPUT_MODE_TYPE_PREFERRED) prefer = &modes[i]; } if (!found && prefer) { -- 2.7.4 From 4be48914071e24d20b0b26598012239f79504055 Mon Sep 17 00:00:00 2001 From: Sergey Sizonov Date: Wed, 29 Nov 2017 09:07:50 +0300 Subject: [PATCH 14/16] add excluding coverage comments for tdm_client.c/tdm_server.c Change-Id: I02a2e61c0a944879a6936d784545f731b161e23e Signed-off-by: Sergey Sizonov --- client/tdm_client.c | 48 ++++++++++++++++++++++++ src/tdm_server.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) diff --git a/client/tdm_client.c b/client/tdm_client.c index e576c3d..3e9176a 100644 --- a/client/tdm_client.c +++ b/client/tdm_client.c @@ -135,6 +135,7 @@ _tdm_client_vblank_cb_stamp(void *data, struct wl_tdm_vblank *wl_tdm_vblank, uin private_vblank->stamp = stamp; } +/* LCOV_EXCL_START */ static void _tdm_client_vblank_cb_done(void *data, struct wl_tdm_vblank *wl_tdm_vblank, uint32_t req_id, uint32_t sequence, uint32_t tv_sec, @@ -171,7 +172,9 @@ _tdm_client_vblank_cb_done(void *data, struct wl_tdm_vblank *wl_tdm_vblank, return; } } +/* LCOV_EXCL_STOP */ +/* LCOV_EXCL_START */ static void _tdm_client_vblank_cb_ttrace(void *data, struct wl_tdm_vblank *wl_tdm_vblank, uint32_t enable) { @@ -181,6 +184,7 @@ _tdm_client_vblank_cb_ttrace(void *data, struct wl_tdm_vblank *wl_tdm_vblank, ui private_vblank->enable_ttrace = enable; } +/* LCOV_EXCL_STOP */ static const struct wl_tdm_vblank_listener tdm_client_vblank_listener = { _tdm_client_vblank_cb_stamp, @@ -312,10 +316,12 @@ _tdm_client_cb_global(void *data, struct wl_registry *registry, } } +/* LCOV_EXCL_START */ static void _tdm_client_cb_global_remove(void *data, struct wl_registry *registry, uint32_t name) { } +/* LCOV_EXCL_STOP */ static const struct wl_registry_listener tdm_client_registry_listener = { _tdm_client_cb_global, @@ -329,10 +335,14 @@ tdm_client_create(tdm_error *error) private_client = calloc(1, sizeof *private_client); if (!private_client) { + /* LCOV_EXCL_START */ + TDM_ERR("alloc failed"); if (error) *error = TDM_ERROR_OUT_OF_MEMORY; return NULL; + + /* LCOV_EXCL_STOP */ } LIST_INITHEAD(&private_client->output_list); @@ -411,11 +421,13 @@ tdm_client_handle_events(tdm_client *client) TDM_RETURN_VAL_IF_FAIL(client != NULL, TDM_ERROR_INVALID_PARAMETER); + /* LCOV_EXCL_START */ private_client = (tdm_private_client*)client; wl_display_dispatch(private_client->display); return TDM_ERROR_NONE; + /* LCOV_EXCL_STOP */ } typedef struct _tdm_client_vblank_temp { @@ -423,6 +435,7 @@ typedef struct _tdm_client_vblank_temp { void *user_data; } tdm_client_vblank_temp; +/* LCOV_EXCL_START */ static void _tdm_client_vblank_handler_temp(tdm_client_vblank *vblank, tdm_error error, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) @@ -436,7 +449,9 @@ _tdm_client_vblank_handler_temp(tdm_client_vblank *vblank, tdm_error error, unsi free(vblank_temp); } +/* LCOV_EXCL_STOP */ +/* LCOV_EXCL_START */ /* deprecated */ tdm_error tdm_client_wait_vblank(tdm_client *client, char *name, int sw_timer, int interval, int sync, @@ -470,6 +485,7 @@ tdm_client_wait_vblank(tdm_client *client, char *name, return tdm_client_vblank_wait(private_client->temp_vblank, interval, _tdm_client_vblank_handler_temp, vblank_temp); } +/* LCOV_EXCL_STOP */ tdm_client_output* tdm_client_get_output(tdm_client *client, char *name, tdm_error *error) @@ -499,10 +515,14 @@ tdm_client_get_output(tdm_client *client, char *name, tdm_error *error) private_output = calloc(1, sizeof *private_output); if (!private_output) { + /* LCOV_EXCL_START */ + TDM_ERR("alloc failed"); if (error) *error = TDM_ERROR_OUT_OF_MEMORY; return NULL; + + /* LCOV_EXCL_STOP */ } private_output->private_client = private_client; @@ -510,11 +530,15 @@ tdm_client_get_output(tdm_client *client, char *name, tdm_error *error) snprintf(private_output->name, TDM_NAME_LEN, "%s", name); private_output->output = wl_tdm_create_output(private_client->tdm, private_output->name); if (!private_output->output) { + /* LCOV_EXCL_START */ + TDM_ERR("couldn't create output resource"); free(private_output); if (error) *error = TDM_ERROR_OUT_OF_MEMORY; return NULL; + + /* LCOV_EXCL_STOP */ } LIST_INITHEAD(&private_output->vblank_list); @@ -701,21 +725,29 @@ tdm_client_output_create_vblank(tdm_client_output *output, tdm_error *error) private_vblank = calloc(1, sizeof *private_vblank); if (!private_vblank) { + /* LCOV_EXCL_START */ + TDM_ERR("alloc failed"); if (error) *error = TDM_ERROR_OUT_OF_MEMORY; return NULL; + + /* LCOV_EXCL_STOP */ } private_vblank->private_output = private_output; private_vblank->vblank = wl_tdm_output_create_vblank(private_output->output); if (!private_vblank->vblank) { + /* LCOV_EXCL_START */ + TDM_ERR("couldn't create vblank resource"); free(private_vblank); if (error) *error = TDM_ERROR_OUT_OF_MEMORY; return NULL; + + /* LCOV_EXCL_STOP */ } /* initial value */ @@ -882,8 +914,12 @@ tdm_client_vblank_wait(tdm_client_vblank *vblank, unsigned int interval, tdm_cli w = calloc(1, sizeof *w); if (!w) { + /* LCOV_EXCL_START */ + TDM_ERR("alloc failed"); return TDM_ERROR_OUT_OF_MEMORY; + + /* LCOV_EXCL_STOP */ } w->private_vblank = private_vblank; @@ -918,6 +954,8 @@ tdm_client_vblank_wait(tdm_client_vblank *vblank, unsigned int interval, tdm_cli return TDM_ERROR_NONE; } + /* LCOV_EXCL_START */ + while (ret != -1 && !w->need_free) ret = wl_display_dispatch(private_client->display); @@ -930,6 +968,8 @@ tdm_client_vblank_wait(tdm_client_vblank *vblank, unsigned int interval, tdm_cli free(w); return TDM_ERROR_NONE; + + /* LCOV_EXCL_STOP */ } tdm_error @@ -967,8 +1007,12 @@ tdm_client_vblank_wait_seq(tdm_client_vblank *vblank, unsigned int sequence, w = calloc(1, sizeof *w); if (!w) { + /* LCOV_EXCL_START */ + TDM_ERR("alloc failed"); return TDM_ERROR_OUT_OF_MEMORY; + + /* LCOV_EXCL_STOP */ } w->private_vblank = private_vblank; @@ -1003,6 +1047,8 @@ tdm_client_vblank_wait_seq(tdm_client_vblank *vblank, unsigned int sequence, return TDM_ERROR_NONE; } + /* LCOV_EXCL_START */ + while (ret != -1 && !w->need_free) ret = wl_display_dispatch(private_client->display); @@ -1015,4 +1061,6 @@ tdm_client_vblank_wait_seq(tdm_client_vblank *vblank, unsigned int sequence, free(w); return TDM_ERROR_NONE; + + /* LCOV_EXCL_STOP */ } diff --git a/src/tdm_server.c b/src/tdm_server.c index f56b1ad..3932819 100644 --- a/src/tdm_server.c +++ b/src/tdm_server.c @@ -162,6 +162,7 @@ _tdm_server_find_output(tdm_private_server *private_server, const char *name) return found; } +/* LCOV_EXCL_START */ static void _tdm_server_send_done(tdm_server_wait_info *wait_info, tdm_error error, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec) @@ -193,14 +194,18 @@ _tdm_server_send_done(tdm_server_wait_info *wait_info, tdm_error error, destroy_wait(wait_info); } +/* LCOV_EXCL_STOP */ +/* LCOV_EXCL_START */ static void _tdm_server_cb_vblank(tdm_vblank *vblank, tdm_error error, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) { _tdm_server_send_done((tdm_server_wait_info*)user_data, error, sequence, tv_sec, tv_usec); } +/* LCOV_EXCL_STOP */ +/* LCOV_EXCL_START */ static void _tdm_server_cb_output_change(tdm_output *output, tdm_output_change_type type, tdm_value value, void *user_data) @@ -234,6 +239,7 @@ _tdm_server_cb_output_change(tdm_output *output, tdm_output_change_type type, break; } } +/* LCOV_EXCL_STOP */ static void destroy_wait(tdm_server_wait_info *wait_info) @@ -263,12 +269,15 @@ destroy_vblank_callback(struct wl_resource *resource) free(vblank_info); } +/* LCOV_EXCL_START */ static void _tdm_server_vblank_cb_destroy(struct wl_client *client, struct wl_resource *resource) { wl_resource_destroy(resource); } +/* LCOV_EXCL_STOP */ +/* LCOV_EXCL_START */ static void _tdm_server_vblank_cb_set_name(struct wl_client *client, struct wl_resource *resource, const char *name) { @@ -276,7 +285,9 @@ _tdm_server_vblank_cb_set_name(struct wl_client *client, struct wl_resource *res tdm_vblank_set_name(vblank_info->vblank, name); } +/* LCOV_EXCL_STOP */ +/* LCOV_EXCL_START */ static void _tdm_server_vblank_cb_set_fps(struct wl_client *client, struct wl_resource *resource, uint32_t fps) { @@ -284,7 +295,9 @@ _tdm_server_vblank_cb_set_fps(struct wl_client *client, struct wl_resource *reso tdm_vblank_set_fps(vblank_info->vblank, fps); } +/* LCOV_EXCL_STOP */ +/* LCOV_EXCL_START */ static void _tdm_server_vblank_cb_set_offset(struct wl_client *client, struct wl_resource *resource, int32_t offset) { @@ -292,6 +305,7 @@ _tdm_server_vblank_cb_set_offset(struct wl_client *client, struct wl_resource *r tdm_vblank_set_offset(vblank_info->vblank, offset); } +/* LCOV_EXCL_STOP */ static void _tdm_server_vblank_cb_set_enable_fake(struct wl_client *client, struct wl_resource *resource, uint32_t enable_fake) @@ -315,9 +329,13 @@ _tdm_server_vblank_cb_wait_vblank(struct wl_client *client, struct wl_resource * wait_info = calloc(1, sizeof * wait_info); if (!wait_info) { + /* LCOV_EXCL_START */ + TDM_ERR("alloc failed"); ret = TDM_ERROR_OUT_OF_MEMORY; goto wait_failed; + + /* LCOV_EXCL_STOP */ } LIST_ADDTAIL(&wait_info->link, &private_server->wait_list); @@ -342,9 +360,13 @@ _tdm_server_vblank_cb_wait_vblank(struct wl_client *client, struct wl_resource * return; wait_failed: + /* LCOV_EXCL_START */ + wl_tdm_vblank_send_done(vblank_info->resource, req_id, 0, 0, 0, ret); if (wait_info) destroy_wait(wait_info); + + /* LCOV_EXCL_STOP */ } static void @@ -361,9 +383,13 @@ _tdm_server_vblank_cb_wait_vblank_seq(struct wl_client *client, struct wl_resour wait_info = calloc(1, sizeof * wait_info); if (!wait_info) { + /* LCOV_EXCL_START */ + TDM_ERR("alloc failed"); ret = TDM_ERROR_OUT_OF_MEMORY; goto wait_failed; + + /* LCOV_EXCL_STOP */ } LIST_ADDTAIL(&wait_info->link, &private_server->wait_list); @@ -388,9 +414,13 @@ _tdm_server_vblank_cb_wait_vblank_seq(struct wl_client *client, struct wl_resour return; wait_failed: + /* LCOV_EXCL_START */ + wl_tdm_vblank_send_done(vblank_info->resource, req_id, 0, 0, 0, ret); if (wait_info) destroy_wait(wait_info); + + /* LCOV_EXCL_STOP */ } static const struct wl_tdm_vblank_interface tdm_vblank_implementation = { @@ -403,11 +433,13 @@ static const struct wl_tdm_vblank_interface tdm_vblank_implementation = { _tdm_server_vblank_cb_wait_vblank_seq, }; +/* LCOV_EXCL_START */ static void _tdm_server_output_cb_destroy(struct wl_client *client, struct wl_resource *resource) { wl_resource_destroy(resource); } +/* LCOV_EXCL_STOP */ static void _tdm_server_output_cb_create_vblank(struct wl_client *client, struct wl_resource *resource, uint32_t id) @@ -423,26 +455,38 @@ _tdm_server_output_cb_create_vblank(struct wl_client *client, struct wl_resource wl_resource_create(client, &wl_tdm_vblank_interface, wl_resource_get_version(resource), id); if (!vblank_resource) { + /* LCOV_EXCL_START */ + wl_resource_post_no_memory(resource); TDM_ERR("wl_resource_create failed"); return; + + /* LCOV_EXCL_STOP */ } vblank = tdm_vblank_create(private_loop->dpy, output_info->output, NULL); if (!vblank) { + /* LCOV_EXCL_START */ + wl_resource_post_no_memory(resource); wl_resource_destroy(vblank_resource); TDM_ERR("tdm_vblank_create failed"); return; + + /* LCOV_EXCL_STOP */ } vblank_info = calloc(1, sizeof * vblank_info); if (!vblank_info) { + /* LCOV_EXCL_START */ + wl_resource_post_no_memory(resource); wl_resource_destroy(vblank_resource); tdm_vblank_destroy(vblank); TDM_ERR("alloc failed"); return; + + /* LCOV_EXCL_STOP */ } LIST_ADDTAIL(&vblank_info->link, &output_info->vblank_list); @@ -461,6 +505,7 @@ _tdm_server_output_cb_create_vblank(struct wl_client *client, struct wl_resource return; } +/* LCOV_EXCL_START */ static void _tdm_server_output_cb_watch_output_changes(struct wl_client *client, struct wl_resource *resource, unsigned int enable) { @@ -470,6 +515,7 @@ _tdm_server_output_cb_watch_output_changes(struct wl_client *client, struct wl_r output_info->watch_output_changes = enable; } +/* LCOV_EXCL_STOP */ static void _tdm_server_output_cb_get_connection(struct wl_client *client, struct wl_resource *resource) @@ -594,27 +640,39 @@ _tdm_server_cb_create_output(struct wl_client *client, struct wl_resource *resou output = _tdm_server_find_output(private_server, name); if (!output) { + /* LCOV_EXCL_START */ + TDM_ERR("There is no '%s' output", name); wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "There is no '%s' output", name); return; + + /* LCOV_EXCL_STOP */ } output_resource = wl_resource_create(client, &wl_tdm_output_interface, wl_resource_get_version(resource), id); if (!output_resource) { + /* LCOV_EXCL_START */ + wl_resource_post_no_memory(resource); TDM_ERR("wl_resource_create failed"); return; + + /* LCOV_EXCL_STOP */ } output_info = calloc(1, sizeof * output_info); if (!output_info) { + /* LCOV_EXCL_START */ + wl_resource_post_no_memory(resource); wl_resource_destroy(output_resource); TDM_ERR("alloc failed"); return; + + /* LCOV_EXCL_STOP */ } LIST_ADDTAIL(&output_info->link, &private_server->output_list); @@ -650,6 +708,7 @@ _tdm_server_cb_create_output(struct wl_client *client, struct wl_resource *resou } } +/* LCOV_EXCL_START */ static void _tdm_server_cb_debug(struct wl_client *client, struct wl_resource *resource, const char *options) { @@ -689,7 +748,9 @@ _tdm_server_cb_debug(struct wl_client *client, struct wl_resource *resource, con wl_tdm_send_debug_done(resource); } +/* LCOV_EXCL_STOP */ +/* LCOV_EXCL_START */ static void _tdm_server_cb_set_client_vblank_fps(struct wl_client *client, struct wl_resource *resource, unsigned int pid, const char *name, unsigned int fps) @@ -699,6 +760,7 @@ _tdm_server_cb_set_client_vblank_fps(struct wl_client *client, struct wl_resourc TDM_INFO("'%s' vblank fps(PID: '%u'): %u", name, pid, fps); } +/* LCOV_EXCL_STOP */ static const struct wl_tdm_interface tdm_implementation = { _tdm_server_cb_debug, @@ -733,15 +795,23 @@ _tdm_server_bind(struct wl_client *client, void *data, resource = wl_resource_create(client, &wl_tdm_interface, version, id); if (!resource) { + /* LCOV_EXCL_START */ + wl_client_post_no_memory(client); return; + + /* LCOV_EXCL_STOP */ } cinfo = calloc(1, sizeof(tdm_server_client_info)); if (!cinfo) { + /* LCOV_EXCL_START */ + wl_client_post_no_memory(client); wl_resource_destroy(resource); return; + + /* LCOV_EXCL_STOP */ } cinfo->resource = resource; @@ -798,12 +868,16 @@ _tdm_getgrnam_r(const char *name) return id; failed: + /* LCOV_EXCL_START */ + if (buf) free(buf); if (grp) free(grp); return -1; + + /* LCOV_EXCL_STOP */ } static void @@ -817,8 +891,12 @@ _tdm_socket_init(tdm_private_loop *private_loop) dir = getenv("XDG_RUNTIME_DIR"); if (!dir) { + /* LCOV_EXCL_START */ + TDM_WRN("getting XDG_RUNTIME_DIR failed"); return; + + /* LCOV_EXCL_STOP */ } strncpy(socket_path, dir, TDM_NAME_LEN - 1); @@ -829,28 +907,44 @@ _tdm_socket_init(tdm_private_loop *private_loop) ret = chmod(socket_path, 509); if (ret < 0) { + /* LCOV_EXCL_START */ + TDM_WRN("changing modes of socket file failed:%s (%m)", socket_path); return; + + /* LCOV_EXCL_STOP */ } ret = _tdm_getgrnam_r("root"); if (ret < 0) { + /* LCOV_EXCL_START */ + TDM_WRN("getting uid failed"); return; + + /* LCOV_EXCL_STOP */ } uid = ret; ret = _tdm_getgrnam_r("display"); if (ret < 0) { + /* LCOV_EXCL_START */ + TDM_WRN("getting gid failed"); return; + + /* LCOV_EXCL_STOP */ } gid = ret; ret = chown(socket_path, uid, gid); if (ret < 0) { + /* LCOV_EXCL_START */ + TDM_WRN("changing owner of socket file failed:%s (%m)", socket_path); return; + + /* LCOV_EXCL_STOP */ } } @@ -866,8 +960,12 @@ tdm_server_init(tdm_private_loop *private_loop) return TDM_ERROR_NONE; if (wl_display_add_socket(private_loop->wl_display, "tdm-socket")) { + /* LCOV_EXCL_START */ + TDM_ERR("createing a tdm-socket failed"); return TDM_ERROR_OPERATION_FAILED; + + /* LCOV_EXCL_STOP */ } _tdm_socket_init(private_loop); @@ -883,9 +981,13 @@ tdm_server_init(tdm_private_loop *private_loop) if (!wl_global_create(private_loop->wl_display, &wl_tdm_interface, 1, private_server, _tdm_server_bind)) { + /* LCOV_EXCL_START */ + TDM_ERR("creating a global resource failed"); free(private_server); return TDM_ERROR_OUT_OF_MEMORY; + + /* LCOV_EXCL_STOP */ } private_server->private_loop = private_loop; @@ -927,6 +1029,7 @@ tdm_server_deinit(tdm_private_loop *private_loop) keep_private_server = NULL; } +/* LCOV_EXCL_START */ INTERN const char* tdm_server_get_client_name(pid_t pid) { @@ -939,7 +1042,9 @@ tdm_server_get_client_name(pid_t pid) return NULL; } +/* LCOV_EXCL_STOP */ +/* LCOV_EXCL_START */ INTERN tdm_error tdm_server_enable_ttrace_vblank(tdm_display *dpy, tdm_output *output, int enable) { @@ -966,3 +1071,4 @@ tdm_server_enable_ttrace_vblank(tdm_display *dpy, tdm_output *output, int enable return TDM_ERROR_NONE; } +/* LCOV_EXCL_STOP */ -- 2.7.4 From f7547c59e1cb13eff9445f91b132e354d88b7de2 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Tue, 28 Nov 2017 17:13:27 +0900 Subject: [PATCH 15/16] output: add debug logs Change-Id: I70c3bce41875176fb01c741e3b8b470dafb128c3 --- src/tdm_vblank.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/tdm_vblank.c b/src/tdm_vblank.c index 39eeca6..2701456 100644 --- a/src/tdm_vblank.c +++ b/src/tdm_vblank.c @@ -1142,12 +1142,20 @@ tdm_vblank_wait(tdm_vblank *vblank, unsigned int req_sec, unsigned int req_usec, else wait_info->type = VBLANK_TYPE_HW_SW; - if (wait_info->type == VBLANK_TYPE_SW || wait_info->type == VBLANK_TYPE_SW_FAKE) + if (wait_info->type == VBLANK_TYPE_SW || wait_info->type == VBLANK_TYPE_SW_FAKE) { ret = _tdm_vblank_wait_SW(wait_info); - else { + if (ret != TDM_ERROR_NONE) + TDM_ERR("_tdm_vblank_wait_SW failed: ret(%d)", ret); + } else { ret = _tdm_vblank_wait_HW(wait_info); - if (ret == TDM_ERROR_OUTPUT_DISCONNECTED || ret == TDM_ERROR_DPMS_OFF) + if (ret != TDM_ERROR_NONE) + TDM_ERR("_tdm_vblank_wait_HW failed: ret(%d)", ret); + + if (ret == TDM_ERROR_OUTPUT_DISCONNECTED || ret == TDM_ERROR_DPMS_OFF) { ret = _tdm_vblank_wait_SW(wait_info); + if (ret != TDM_ERROR_NONE) + TDM_ERR("_tdm_vblank_wait_SW failed: ret(%d)", ret); + } } if (ret != TDM_ERROR_NONE) { -- 2.7.4 From c2c4980b27f69239b3e7af5aa7102d652223a4f5 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Tue, 28 Nov 2017 11:08:49 +0900 Subject: [PATCH 16/16] dpms: add more description Change-Id: Ic8f325d92cdf57cac88f11e0436a378d238fb9c9 --- include/tdm_common.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/tdm_common.h b/include/tdm_common.h index 637d883..f353216 100644 --- a/include/tdm_common.h +++ b/include/tdm_common.h @@ -214,10 +214,10 @@ typedef enum { * @details bit compatible with the libdrm definitions. */ typedef enum { - TDM_OUTPUT_DPMS_ON, /**< On */ - TDM_OUTPUT_DPMS_STANDBY, /**< StandBy */ - TDM_OUTPUT_DPMS_SUSPEND, /**< Suspend */ - TDM_OUTPUT_DPMS_OFF, /**< Off */ + TDM_OUTPUT_DPMS_ON, /**< On, Vsync On */ + TDM_OUTPUT_DPMS_STANDBY, /**< StandBy, Vsync On */ + TDM_OUTPUT_DPMS_SUSPEND, /**< Suspend, Vsync Off */ + TDM_OUTPUT_DPMS_OFF, /**< Off, Vsync Off */ } tdm_output_dpms; /** -- 2.7.4