From 2ac98deee151aa56de5025dac8f5d2230095bda7 Mon Sep 17 00:00:00 2001 From: Vo Trung Chi Date: Mon, 2 Sep 2019 12:31:36 +0700 Subject: libdlt: truncate the log message if it is too long (#156) (#157) Change the behavior of dlt_user_log_write_string, dlt_user_log_write_constant_string and dlt_user_log_write_utf8_string so that they truncate the incoming message if it is too big and add "Message truncated, too long" at the end of it. These function should anyway still return an DLT_RETURN_USER_BUFFER_FULL error in this case. Signed-off-by: Nguyen Dinh Thi (RBVH/ENG2) Signed-off-by: Vo Trung Chi --- src/lib/dlt_user.c | 237 +++++---- tests/gtest_dlt_user.cpp | 1319 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 1461 insertions(+), 95 deletions(-) diff --git a/src/lib/dlt_user.c b/src/lib/dlt_user.c index 4ae1fde..55e57bf 100644 --- a/src/lib/dlt_user.c +++ b/src/lib/dlt_user.c @@ -93,6 +93,15 @@ static int atexit_registered = 0; /* used to disallow DLT usage in fork() child */ static int g_dlt_is_child = 0; +/* String truncate message */ +static const char *STR_TRUNCATED_MESSAGE = "... <>"; + +/* Enum for type of string */ +enum StringType +{ + ASCII_STRING = 0, + UTF8_STRING = 1 +}; /*Max DLT message size is 1390 bytes plus some extra header space to accomidate the resend buffer*/ #define DLT_USER_EXTRA_BUFF_SIZE 100 @@ -112,12 +121,10 @@ void dlt_lock_mutex(pthread_mutex_t *mutex) { int32_t lock_mutex_result = pthread_mutex_lock(mutex); - if ( lock_mutex_result != 0 ) - { + if (lock_mutex_result != 0) dlt_vlog(LOG_ERR, "Mutex lock failed unexpected pid=%i with result %i!\n", getpid(), lock_mutex_result); - } } void dlt_unlock_mutex(pthread_mutex_t *mutex) @@ -169,6 +176,8 @@ static int dlt_start_threads(); static void dlt_stop_threads(); static void dlt_fork_child_fork_handler(); +static DltReturnValue dlt_user_log_write_string_utils(DltContextData *log, const char *text, + const enum StringType type); DltReturnValue dlt_user_check_library_version(const char *user_major_version, const char *user_minor_version) { @@ -300,7 +309,6 @@ static DltReturnValue dlt_initialize_fifo_connection(void) if (ret == -1) dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "Loging disabled, FIFO user %s cannot be created!\n", filename); - /* return DLT_RETURN_OK; */ /* removed to prevent error, when FIFO already exists */ /* S_IWGRP cannot be set by mkfifo (???), let's reassign right bits */ ret = chmod(filename, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP); @@ -321,13 +329,12 @@ static DltReturnValue dlt_initialize_fifo_connection(void) /* open DLT output FIFO */ dlt_user.dlt_log_handle = open(dlt_daemon_fifo, O_WRONLY | O_NONBLOCK | O_CLOEXEC); - if (dlt_user.dlt_log_handle == -1) { + if (dlt_user.dlt_log_handle == -1) /* This is a normal usecase. It is OK that the daemon (and thus the FIFO /tmp/dlt) * starts later and some DLT users have already been started before. * Thus it is OK if the FIFO can't be opened. */ dlt_vnlog(LOG_INFO, DLT_USER_BUFFER_LENGTH, "FIFO %s cannot be opened. Retrying later...\n", dlt_daemon_fifo); - } return DLT_RETURN_OK; } @@ -367,10 +374,12 @@ DltReturnValue dlt_init(void) /* init shared memory */ if (dlt_shm_init_client(&(dlt_user.dlt_shm), dltShmName) < DLT_RETURN_OK) dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "Logging disabled," - " Shared memory %s cannot be created!\n", dltShmName); + " Shared memory %s cannot be created!\n", dltShmName); + #endif #ifdef DLT_USE_UNIX_SOCKET_IPC + if (dlt_initialize_socket_connection() != DLT_RETURN_OK) /* We could connect to the pipe, but not to the socket, which is normally */ /* open before by the DLT daemon => bad failure => return error code */ @@ -378,6 +387,7 @@ DltReturnValue dlt_init(void) return DLT_RETURN_ERROR; #else /* FIFO connection */ + if (dlt_initialize_fifo_connection() != DLT_RETURN_OK) return DLT_RETURN_ERROR; @@ -386,6 +396,7 @@ DltReturnValue dlt_init(void) dlt_user_initialised = false; return DLT_RETURN_ERROR; } + #endif /* These will be lazy initialized only when needed */ @@ -563,11 +574,10 @@ DltReturnValue dlt_init_common(void) env_initial_log_level = getenv("DLT_INITIAL_LOG_LEVEL"); if (env_initial_log_level != NULL) { - if (dlt_env_extract_ll_set(&env_initial_log_level, &dlt_user.initial_ll_set) != 0) { + if (dlt_env_extract_ll_set(&env_initial_log_level, &dlt_user.initial_ll_set) != 0) dlt_vlog(LOG_WARNING, "Unable to parse initial set of log-levels from environment! Env:\n%s\n", getenv("DLT_INITIAL_LOG_LEVEL")); - } } /* Initialize LogLevel/TraceStatus field */ @@ -675,9 +685,8 @@ DltReturnValue dlt_init_common(void) void dlt_user_atexit_handler(void) { /* parent will do clean-up */ - if (g_dlt_is_child) { + if (g_dlt_is_child) return; - } if (!dlt_user_initialised) { dlt_vlog(LOG_WARNING, "%s dlt_user_initialised false\n", __FUNCTION__); @@ -847,6 +856,7 @@ DltReturnValue dlt_free(void) /* Ignore return value */ DLT_SEM_LOCK(); + dlt_user_free_buffer(&(dlt_user.resend_buffer)); dlt_buffer_free_dynamic(&(dlt_user.startup_buffer)); DLT_SEM_FREE(); @@ -965,7 +975,9 @@ DltReturnValue dlt_register_app(const char *apid, const char *description) (apid[1] == dlt_user.appID[1]) && (apid[2] == dlt_user.appID[2]) && (apid[3] == dlt_user.appID[3])) + { return DLT_RETURN_OK; + } DLT_SEM_LOCK(); @@ -1103,7 +1115,8 @@ DltReturnValue dlt_register_context_ll_ts_llccb(DltContext *handle, dlt_user.dlt_ll_ts[i].log_level_changed_callback = 0; } } - else if ((dlt_user.dlt_ll_ts_num_entries % DLT_USER_CONTEXT_ALLOC_SIZE) == 0) { + else if ((dlt_user.dlt_ll_ts_num_entries % DLT_USER_CONTEXT_ALLOC_SIZE) == 0) + { /* allocate memory in steps of DLT_USER_CONTEXT_ALLOC_SIZE, e.g. 500 */ dlt_ll_ts_type *old_ll_ts; uint32_t old_max_entries; @@ -1467,10 +1480,9 @@ int dlt_set_resend_timeout_atexit(uint32_t timeout_in_milliseconds) if (g_dlt_is_child) return DLT_RETURN_ERROR; - if (dlt_user_initialised == 0) { + if (dlt_user_initialised == 0) if (dlt_init() < 0) return -1; - } dlt_user.timeout_at_exit_handler = timeout_in_milliseconds * 10; return 0; @@ -2282,10 +2294,30 @@ DltReturnValue dlt_user_log_write_bool(DltContextData *log, uint8_t data) } DltReturnValue dlt_user_log_write_string(DltContextData *log, const char *text) +{ + return dlt_user_log_write_string_utils(log, text, ASCII_STRING); +} + +DltReturnValue dlt_user_log_write_constant_string(DltContextData *log, const char *text) +{ + /* Send parameter only in verbose mode */ + return dlt_user.verbose_mode ? dlt_user_log_write_string(log, text) : DLT_RETURN_OK; +} + +DltReturnValue dlt_user_log_write_utf8_string(DltContextData *log, const char *text) +{ + return dlt_user_log_write_string_utils(log, text, UTF8_STRING); +} + +DltReturnValue dlt_user_log_write_string_utils(DltContextData *log, const char *text, const enum StringType type) { uint16_t arg_size = 0; uint32_t type_info = 0; size_t new_log_size = 0; + DltReturnValue ret = DLT_RETURN_OK; + + size_t str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; + size_t max_payload_str_msg; if ((log == NULL) || (text == NULL)) return DLT_RETURN_WRONG_PARAMETER; @@ -2299,65 +2331,76 @@ DltReturnValue dlt_user_log_write_string(DltContextData *log, const char *text) new_log_size = log->size + arg_size + sizeof(uint16_t); - if (new_log_size > dlt_user.log_buf_len) - return DLT_RETURN_USER_BUFFER_FULL; - - if (dlt_user.verbose_mode) { - new_log_size = log->size + arg_size + sizeof(uint32_t) + sizeof(uint16_t); - - if (new_log_size > dlt_user.log_buf_len) - return DLT_RETURN_USER_BUFFER_FULL; - - type_info = DLT_TYPE_INFO_STRG | DLT_SCOD_ASCII; + if (dlt_user.verbose_mode) + new_log_size += sizeof(uint32_t); - memcpy((log->buffer) + log->size, &(type_info), sizeof(uint32_t)); - log->size += sizeof(uint32_t); - } + /* Check log size condition */ + if (new_log_size > dlt_user.log_buf_len) { + ret = DLT_RETURN_USER_BUFFER_FULL; - memcpy((log->buffer) + log->size, &(arg_size), sizeof(uint16_t)); - log->size += sizeof(uint16_t); + /* Re-calculate arg_size */ + arg_size = dlt_user.log_buf_len - log->size - sizeof(uint16_t); - memcpy((log->buffer) + log->size, text, arg_size); - log->size += arg_size; + size_t min_payload_str_truncate_msg = log->size + str_truncate_message_length + sizeof(uint16_t); - log->args_num++; - - return DLT_RETURN_OK; -} + if (dlt_user.verbose_mode) { + min_payload_str_truncate_msg += sizeof(uint32_t); + arg_size -= sizeof(uint32_t); + } -DltReturnValue dlt_user_log_write_constant_string(DltContextData *log, const char *text) -{ - /* Send parameter only in verbose mode */ - return dlt_user.verbose_mode ? dlt_user_log_write_string(log, text) : DLT_RETURN_OK; -} + /* Return when dlt_user.log_buf_len does not have enough space for min_payload_str_truncate_msg */ + if (min_payload_str_truncate_msg > dlt_user.log_buf_len) { + dlt_vlog(LOG_WARNING, "%s not enough minimum space to store data\n", __FUNCTION__); + return ret; + } -DltReturnValue dlt_user_log_write_utf8_string(DltContextData *log, const char *text) -{ - uint16_t arg_size; - uint32_t type_info; - size_t new_log_size = 0; + /* Calculate the maximum size of string will be copied after truncate */ + max_payload_str_msg = dlt_user.log_buf_len - min_payload_str_truncate_msg; - if ((log == NULL) || (text == NULL)) - return DLT_RETURN_WRONG_PARAMETER; + if (type == UTF8_STRING) { + /** + * Adjust the lengh to truncate one utf8 character corectly + * refer: https://en.wikipedia.org/wiki/UTF-8 + * one utf8 character will have maximum 4 bytes then maximum bytes will be truncate additional is 3 + */ + const char *tmp = (text + max_payload_str_msg - 3); + uint16_t reduce_size = 0; + + if (tmp[2] & 0x80) { + /* Is the last byte of truncated text is the first byte in multi-byte sequence (utf8 2 bytes) */ + if (tmp[2] & 0x40) + reduce_size = 1; + /* Is the next to last byte of truncated text is the first byte in multi-byte sequence (utf8 3 bytes) */ + else if ((tmp[1] & 0xe0) == 0xe0) + reduce_size = 2; + /* utf8 4 bytes */ + else if ((tmp[0] & 0xf0) == 0xf0) + reduce_size = 3; + } - if (!dlt_user_initialised) { - dlt_vlog(LOG_WARNING, "%s dlt_user_initialised false\n", __FUNCTION__); - return DLT_RETURN_ERROR; + max_payload_str_msg -= reduce_size; + arg_size -= reduce_size; + } } - arg_size = strlen(text) + 1; - new_log_size = log->size + arg_size + sizeof(uint16_t); - - if (new_log_size > dlt_user.log_buf_len) - return DLT_RETURN_USER_BUFFER_FULL; - if (dlt_user.verbose_mode) { - new_log_size = log->size + arg_size + sizeof(uint32_t) + sizeof(uint16_t); - - if (new_log_size > dlt_user.log_buf_len) - return DLT_RETURN_USER_BUFFER_FULL; - - type_info = DLT_TYPE_INFO_STRG | DLT_SCOD_UTF8; + switch (type) { + case ASCII_STRING: + { + type_info = DLT_TYPE_INFO_STRG | DLT_SCOD_ASCII; + break; + } + case UTF8_STRING: + { + type_info = DLT_TYPE_INFO_STRG | DLT_SCOD_UTF8; + break; + } + default: + { + /* Do nothing */ + break; + } + } memcpy((log->buffer) + log->size, &(type_info), sizeof(uint32_t)); log->size += sizeof(uint32_t); @@ -2366,12 +2409,35 @@ DltReturnValue dlt_user_log_write_utf8_string(DltContextData *log, const char *t memcpy((log->buffer) + log->size, &(arg_size), sizeof(uint16_t)); log->size += sizeof(uint16_t); - memcpy((log->buffer) + log->size, text, arg_size); - log->size += arg_size; + switch (ret) { + case DLT_RETURN_OK: + { + /* Whole string will be copied */ + memcpy((log->buffer) + log->size, text, arg_size); + log->size += arg_size; + break; + } + case DLT_RETURN_USER_BUFFER_FULL: + { + /* Only copy partial string */ + memcpy((log->buffer) + log->size, text, max_payload_str_msg); + log->size += max_payload_str_msg; + + /* Append string truncate the input string */ + memcpy((log->buffer) + log->size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); + log->size += str_truncate_message_length; + break; + } + default: + { + /* Do nothing */ + break; + } + } log->args_num++; - return DLT_RETURN_OK; + return ret; } DltReturnValue dlt_register_injection_callback_with_id(DltContext *handle, uint32_t service_id, @@ -2412,8 +2478,6 @@ DltReturnValue dlt_register_injection_callback_with_id(DltContext *handle, uint3 break; } - - if (found) { j = k; } @@ -2645,7 +2709,7 @@ DltReturnValue dlt_user_trace_network_segmented_segment(uint32_t id, while (check_buffer() < 0) { /* Wait 50ms */ ts.tv_sec = 0; - ts.tv_nsec = 1000000*50; + ts.tv_nsec = 1000000 * 50; nanosleep(&ts, NULL); dlt_user_log_resend_buffer(); } @@ -2813,7 +2877,7 @@ void dlt_user_trace_network_segmented_thread(void *unused) /* Indicator just to try to flush the buffer */ /* DLT_NW_TRACE_RESEND custom type is used to mark a resend */ - if(data->nw_trace_type == DLT_NW_TRACE_RESEND) { + if (data->nw_trace_type == DLT_NW_TRACE_RESEND) { struct timespec req; /* Sleep 100ms, to allow other process to read FIFO */ req.tv_sec = 0; @@ -3386,12 +3450,11 @@ DltReturnValue dlt_user_log_init(DltContext *handle, DltContextData *log) if (!dlt_user_initialised) { ret = dlt_init(); - if (ret < DLT_RETURN_OK) - { + + if (ret < DLT_RETURN_OK) { if (ret != DLT_RETURN_LOGGING_DISABLED) - { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); - } + return ret; } } @@ -3513,7 +3576,6 @@ DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype) if (dlt_user.use_extende_header_for_non_verbose) msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH); - #if (BYTE_ORDER == BIG_ENDIAN) msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_MSBF); #endif @@ -3539,13 +3601,13 @@ DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype) case DLT_TYPE_LOG: { msg.extendedheader->msin = (DLT_TYPE_LOG << DLT_MSIN_MSTP_SHIFT) | - ((log->log_level << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN); /* messsage info */ + ((log->log_level << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN); break; } case DLT_TYPE_NW_TRACE: { msg.extendedheader->msin = (DLT_TYPE_NW_TRACE << DLT_MSIN_MSTP_SHIFT) | - ((log->trace_status << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN); /* messsage info */ + ((log->trace_status << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN); break; } default: @@ -3585,10 +3647,9 @@ DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype) /* print to std out, if enabled */ if ((dlt_user.local_print_mode != DLT_PM_FORCE_OFF) && (dlt_user.local_print_mode != DLT_PM_AUTOMATIC)) { - if ((dlt_user.enable_local_print) || (dlt_user.local_print_mode == DLT_PM_FORCE_ON)) { + if ((dlt_user.enable_local_print) || (dlt_user.local_print_mode == DLT_PM_FORCE_ON)) if (dlt_user_print_msg(&msg, log) == DLT_RETURN_ERROR) return DLT_RETURN_ERROR; - } } if (dlt_user.dlt_is_file) { @@ -4167,7 +4228,7 @@ DltReturnValue dlt_user_log_check_user_message(void) DLT_RETURN_ERROR) return DLT_RETURN_ERROR; } - break; + break; case DLT_USER_MESSAGE_INJECTION: { /* At least, user header, user context, and service id and data_length of injected message is available */ @@ -4191,7 +4252,7 @@ DltReturnValue dlt_user_log_check_user_message(void) DLT_SEM_LOCK(); - if ((usercontextinj->data_length_inject > 0) && (dlt_user.dlt_ll_ts)) { + if ((usercontextinj->data_length_inject > 0) && (dlt_user.dlt_ll_ts)) /* Check if injection callback is registered for this context */ for (i = 0; i < dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].nrcallbacks; i++) if ((dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table) && @@ -4229,7 +4290,6 @@ DltReturnValue dlt_user_log_check_user_message(void) break; } - } DLT_SEM_FREE(); @@ -4280,7 +4340,7 @@ DltReturnValue dlt_user_log_check_user_message(void) DLT_RETURN_ERROR) return DLT_RETURN_ERROR; } - break; + break; default: { dlt_log(LOG_WARNING, "Invalid user message type received!\n"); @@ -4436,6 +4496,7 @@ void dlt_user_log_reattach_to_daemon(void) if (dlt_shm_init_client(&dlt_user.dlt_shm, dltShmName) < DLT_RETURN_OK) dlt_vnlog(LOG_WARNING, DLT_USER_BUFFER_LENGTH, "Logging disabled," " Shared memory %s cannot be created!\n", dltShmName); + #endif dlt_log(LOG_NOTICE, "Logging (re-)enabled!\n"); @@ -4563,11 +4624,10 @@ void dlt_stop_threads() /* do not ignore return value */ dlt_receiverthread_result = pthread_cancel(dlt_receiverthread_handle); - if (dlt_receiverthread_result != 0) { + if (dlt_receiverthread_result != 0) dlt_vlog(LOG_ERR, "ERROR pthread_cancel(dlt_receiverthread_handle): %s\n", strerror(errno)); - } } if (dlt_user.dlt_segmented_nwt_handle) { @@ -4577,22 +4637,20 @@ void dlt_stop_threads() dlt_segmented_nwt_result = pthread_cancel(dlt_user.dlt_segmented_nwt_handle); - if (dlt_segmented_nwt_result != 0) { + if (dlt_segmented_nwt_result != 0) dlt_vlog(LOG_ERR, "ERROR pthread_cancel(dlt_user.dlt_segmented_nwt_handle): %s\n", strerror(errno)); - } } /* make sure that the threads really finished working */ if ((dlt_receiverthread_result == 0) && dlt_receiverthread_handle) { int joined = pthread_join(dlt_receiverthread_handle, NULL); - if (joined < 0) { + if (joined < 0) dlt_vlog(LOG_ERR, "ERROR pthread_join(dlt_receiverthread_handle, NULL): %s\n", strerror(errno)); - } dlt_receiverthread_handle = 0; /* set to invalid */ } @@ -4600,11 +4658,10 @@ void dlt_stop_threads() if ((dlt_segmented_nwt_result == 0) && dlt_user.dlt_segmented_nwt_handle) { int joined = pthread_join(dlt_user.dlt_segmented_nwt_handle, NULL); - if (joined < 0) { + if (joined < 0) dlt_vlog(LOG_ERR, "ERROR pthread_join(dlt_user.dlt_segmented_nwt_handle, NULL): %s\n", strerror(errno)); - } dlt_user.dlt_segmented_nwt_handle = 0; /* set to invalid */ } diff --git a/tests/gtest_dlt_user.cpp b/tests/gtest_dlt_user.cpp index a910f01..777e459 100644 --- a/tests/gtest_dlt_user.cpp +++ b/tests/gtest_dlt_user.cpp @@ -26,13 +26,13 @@ #include #include "gtest/gtest.h" #include +#include extern "C" { #include "dlt_user.h" +#include "dlt_user_cfg.h" } - - /* TEST COMMENTED OUT WITH */ /* TODO: */ /* DO FAIL! */ @@ -188,10 +188,17 @@ extern "C" { # define INT_MAX INT32_MAX #endif +static const char *STR_TRUNCATED_MESSAGE = "... <>"; + /*/////////////////////////////////////// */ /* start initial dlt */ TEST(t_dlt_init, onetime) { + /** + * Unset DLT_USER_ENV_LOG_MSG_BUF_LEN environment variable + * to make sure the dlt user buffer initialized with default value + */ + unsetenv(DLT_USER_ENV_LOG_MSG_BUF_LEN); EXPECT_EQ(DLT_RETURN_OK, dlt_init()); } @@ -1525,12 +1532,311 @@ TEST(t_dlt_user_log_write_string, normal) EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } -TEST(t_dlt_user_log_write_string, nullpointer) +/** + * Send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN + * Expectation: dlt_user_log_write_string() will be returned DLT_RETURN_USER_BUFFER_FULL and + * message will be truncated and appended STR_TRUNCATED_MESSAGE at + * the end of received message. + */ +TEST(t_dlt_user_log_write_string, normal_dlt_log_msg_truncated_because_exceed_the_buffer_length_in_verbose_mode) +{ + DltContext context; + DltContextData contextData; + uint16_t index = 0; + uint16_t package_description_size = 0; + uint16_t user_message_after_truncated_size = 0; + uint16_t send_message_length = 0; + uint16_t str_truncate_message_length = 0; + uint16_t expected_message_length = 0; + char *message = NULL; + char *expected_message = NULL; + + EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); + EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_string normal_dlt_log_msg_truncated_because_exceed_the_buffer_length_in_verbose_mode")); + + /* Normal values */ + EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); + + /* Create the message exceed buffer length 10 bytes */ + send_message_length = DLT_USER_BUF_MAX_SIZE + 10; + message = (char *)(malloc(send_message_length)); + ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; + + for (index = 0; index < send_message_length; index++) + { + message[index] = '#'; + } + message[send_message_length - 1] = '\0'; + + /** + * In Verbose Mode: + * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) + */ + package_description_size = sizeof(uint32_t) + sizeof(uint16_t); + str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; + + /* Create the expected message */ + expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; + expected_message = (char *)(malloc(expected_message_length)); + ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; + user_message_after_truncated_size = expected_message_length - str_truncate_message_length; + + for (index = 0; index < user_message_after_truncated_size; index++) + { + expected_message[index] = '#'; + } + strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); + + EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_string(&contextData, message)); + ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); + + free(message); + message = NULL; + free(expected_message); + expected_message = NULL; + + EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); +} + +/** + * In Non-Verbose mode, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN + * Expectation: dlt_user_log_write_string() will be returned DLT_RETURN_USER_BUFFER_FULL and + * message will be truncated and appended STR_TRUNCATED_MESSAGE at + * the end of received message. + */ +TEST(t_dlt_user_log_write_string, normal_dlt_log_msg_truncated_because_exceed_the_buffer_length_in_non_verbose_mode) +{ + DltContext context; + DltContextData contextData; + uint16_t index = 0; + uint16_t package_description_size = 0; + uint16_t user_message_after_truncated_size = 0; + uint16_t send_message_length = 0; + uint16_t str_truncate_message_length = 0; + uint16_t expected_message_length = 0; + char *message = NULL; + char *expected_message = NULL; + + dlt_nonverbose_mode(); + + EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); + EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_string normal_dlt_log_msg_truncated_because_exceed_the_buffer_length_in_non_verbose_mode")); + + /* Normal values */ + EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); + + /* Create the message exceed buffer length 10 bytes */ + send_message_length = DLT_USER_BUF_MAX_SIZE + 10; + message = (char *)(malloc(send_message_length)); + ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; + + for (index = 0; index < send_message_length; index++) + { + message[index] = '#'; + } + message[send_message_length - 1] = '\0'; + + /** + * In Non-Verbose Mode: + * package_description_size = Message ID (32 bits) + Description of data payload of type string (16 bits) + */ + package_description_size = sizeof(uint32_t) + sizeof(uint16_t); + str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; + + /* Create the expected message */ + expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; + expected_message = (char *)(malloc(expected_message_length)); + ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; + user_message_after_truncated_size = expected_message_length - str_truncate_message_length; + + for (index = 0; index < user_message_after_truncated_size; index++) + { + expected_message[index] = '#'; + } + strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); + + EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_string(&contextData, message)); + ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); + + free(message); + message = NULL; + free(expected_message); + expected_message = NULL; + + EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); + + /* Restore verbose mode */ + dlt_verbose_mode(); +} + +/** + * Set the DLT_USER_ENV_LOG_MSG_BUF_LEN to 46, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN + * Expectation: dlt_user_log_write_string() will be returned DLT_RETURN_USER_BUFFER_FULL and + * message will be truncated and appended STR_TRUNCATED_MESSAGE at + * the end of received message. + * Note: dlt_init() will be called after testcase is finished to restore environment for other test cases + */ +TEST(t_dlt_user_log_write_string, normal_message_truncated_because_exceed_buffer_length_and_reduce_msg_buf_len_by_env_variable) +{ + DltContext context; + DltContextData contextData; + uint16_t index = 0; + uint16_t package_description_size = 0; + uint16_t str_truncate_message_length = 0; + uint16_t expected_message_length = 0; + uint16_t user_message_after_truncated_size = 0; + const char *message = "$$$$###############################################"; + char *expected_message = NULL; + + /** + * Re-initialize the dlt with dlt user buffer size from DLT_USER_ENV_LOG_MSG_BUF_LEN environment variable + * to simulate use case the dlt user buffer size only available 4 bytes for store user message. + * Note: 46 bytes = package_description_size (6 bytes) + str_truncated_message_length (35 bytes) + 4 bytes user message + 1 byte NULL terminator. + */ + user_message_after_truncated_size = 4; + EXPECT_EQ(DLT_RETURN_OK, dlt_free()); + setenv(DLT_USER_ENV_LOG_MSG_BUF_LEN, "46", 1); + EXPECT_EQ(DLT_RETURN_OK, dlt_init()); + + EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); + EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_string normal_message_truncated_because_exceed_buffer_length_and_reduce_msg_buf_len_by_env_variable")); + + /* Normal values */ + EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); + + EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_string(&contextData, message)); + + /** + * In Verbose Mode: + * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) + */ + package_description_size = sizeof(uint32_t) + sizeof(uint16_t); + str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; + + /* Create the expected message */ + expected_message_length = user_message_after_truncated_size + str_truncate_message_length; + expected_message = (char *)(malloc(expected_message_length)); + ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; + + for (index = 0; index < user_message_after_truncated_size; index++) + { + expected_message[index] = '$'; + } + strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); + + ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); + EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); + + /* Restore the dlt with dlt user buffer size as default */ + EXPECT_EQ(DLT_RETURN_OK, dlt_free()); + unsetenv(DLT_USER_ENV_LOG_MSG_BUF_LEN); + EXPECT_EQ(DLT_RETURN_OK, dlt_init()); +} + +/** + * Set DLT_USER_ENV_LOG_MSG_BUF_LEN to 35 bytes and send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN + * Expectation: dlt_user_log_write_string() will be returned DLT_RETURN_USER_BUFFER_FULL because the DLT_USER_ENV_LOG_MSG_BUF_LEN + * does not have enough space to store truncate message STR_TRUNCATED_MESSAGE + * Note: dlt_init() will be called after testcase is finished to restore environment for other test cases + */ +TEST(t_dlt_user_log_write_string, normal_DLT_USER_ENV_LOG_MSG_BUF_LEN_does_not_enough_space_for_truncated_message) { DltContext context; DltContextData contextData; + uint16_t package_description_size = 0; + const char *message = "################################################################################"; + + /** + * Re-initialize the dlt with dlt user buffer size from DLT_USER_ENV_LOG_MSG_BUF_LEN environment variable + * to simulate use case the dlt user buffer size not enough minimum space to store data even the truncate notice message. + * Note: The minimum buffer to store the truncate notice message is 42 bytes. + */ + EXPECT_EQ(DLT_RETURN_OK, dlt_free()); + setenv(DLT_USER_ENV_LOG_MSG_BUF_LEN, "35", 1); + EXPECT_EQ(DLT_RETURN_OK, dlt_init()); + + EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); + EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_string normal_DLT_USER_ENV_LOG_MSG_BUF_LEN_does_not_enough_space_for_truncated_message")); + + /* Normal values */ + EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); + + EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_string(&contextData, message)); + + /** + * In Verbose Mode: + * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) + */ + package_description_size = sizeof(uint32_t) + sizeof(uint16_t); + ASSERT_STREQ("", (char *)(contextData.buffer + package_description_size)); + + EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); + + /* Restore the dlt with dlt user buffer size as default */ + EXPECT_EQ(DLT_RETURN_OK, dlt_free()); + unsetenv(DLT_USER_ENV_LOG_MSG_BUF_LEN); + EXPECT_EQ(DLT_RETURN_OK, dlt_init()); +} + +/** + * Set DLT_USER_ENV_LOG_MSG_BUF_LEN to 42 bytes and send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN + * Expectation: dlt_user_log_write_string() will be returned DLT_RETURN_USER_BUFFER_FULL and + * receive message will be STR_TRUNCATED_MESSAGE + * Note: dlt_init() will be called after testcase is finished to restore environment for other test cases + */ +TEST(t_dlt_user_log_write_string, normal_DLT_USER_ENV_LOG_MSG_BUF_LEN_fix_truncate_message) +{ + DltContext context; + DltContextData contextData; + uint16_t package_description_size = 0; + const char *message = "################################################################################"; + + /** + * Re-initialize the dlt with dlt user buffer size from DLT_USER_ENV_LOG_MSG_BUF_LEN environment variable + * to simulate use case the dlt user buffer size just fixed to truncate message STR_TRUNCATED_MESSAGE + * Note: 42 bytes = package_description_size (6 bytes) + str_truncated_message_length (35 bytes) + 1 byte NULL terminator. + */ + EXPECT_EQ(DLT_RETURN_OK, dlt_free()); + setenv(DLT_USER_ENV_LOG_MSG_BUF_LEN, "42", 1); + EXPECT_EQ(DLT_RETURN_OK, dlt_init()); + + EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); + EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c normal_DLT_USER_ENV_LOG_MSG_BUF_LEN_fix_truncate_message")); + + /* Normal values */ + EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); + + EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_string(&contextData, message)); + + /** + * In Verbose Mode: + * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) + */ + package_description_size = sizeof(uint32_t) + sizeof(uint16_t); + ASSERT_STREQ(STR_TRUNCATED_MESSAGE, (char *)(contextData.buffer + package_description_size)); + EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); + + /* Restore the dlt with dlt user buffer size as default */ + EXPECT_EQ(DLT_RETURN_OK, dlt_free()); + unsetenv(DLT_USER_ENV_LOG_MSG_BUF_LEN); + EXPECT_EQ(DLT_RETURN_OK, dlt_init()); +} +TEST(t_dlt_user_log_write_string, nullpointer) +{ + DltContext context; + DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, @@ -1573,12 +1879,105 @@ TEST(t_dlt_user_log_write_constant_string, normal) EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } -TEST(t_dlt_user_log_write_constant_string, nullpointer) +/** + * Send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN + * Expectation: dlt_user_log_write_constant_string() will be returned DLT_RETURN_USER_BUFFER_FULL and + * message will be truncated and appended STR_TRUNCATED_MESSAGE at + * the end of received message. + */ +TEST(t_dlt_user_log_write_constant_string, normal_too_long_message_is_truncated_and_appended_notice_message_in_verbose_mode) { DltContext context; DltContextData contextData; + uint16_t index = 0; + uint16_t package_description_size = 0; + uint16_t user_message_after_truncated_size = 0; + uint16_t send_message_length = 0; + uint16_t str_truncate_message_length = 0; + uint16_t expected_message_length = 0; + char *message = NULL; + char *expected_message = NULL; + EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); + EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_constant_string normal_too_long_message_is_truncated_and_appended_notice_message_in_verbose_mode")); + + /* Normal values */ + EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); + + /** + * In Verbose Mode: + * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) + */ + package_description_size = sizeof(uint32_t) + sizeof(uint16_t); + str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; + + /* Create the message exceed DLT_USER_ENV_LOG_MSG_BUF_LEN 10 bytes */ + send_message_length = DLT_USER_BUF_MAX_SIZE + 10; + message = (char *)(malloc(send_message_length)); + ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; + + for (index = 0; index < send_message_length; index++) + { + message[index] = '#'; + } + message[send_message_length - 1] = '\0'; + + /* Create the expected message */ + expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; + expected_message = (char *)(malloc(expected_message_length)); + ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; + user_message_after_truncated_size = expected_message_length - str_truncate_message_length; + + for (index = 0; index < user_message_after_truncated_size; index++) + { + expected_message[index] = '#'; + } + strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); + + EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_constant_string(&contextData, message)); + ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); + + free(message); + message = NULL; + free(expected_message); + expected_message = NULL; + + EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); +} + +/** + * In Non-Verbose Mode + * Expectation: dlt_user_log_write_constant_string() will not package and send message. Return DLT_RETURN_OK + */ +TEST(t_dlt_user_log_write_constant_string, normal_do_nothing_in_non_verbose_mode) +{ + DltContext context; + DltContextData contextData; + const char *message = "message"; + + dlt_nonverbose_mode(); + + EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); + EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_constant_string normal_do_nothing_in_non_verbose_mode")); + + /* Normal values */ + EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); + + EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_constant_string(&contextData, message)); + EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); + + /* Restore verbose mode */ + dlt_verbose_mode(); +} +TEST(t_dlt_user_log_write_constant_string, nullpointer) +{ + DltContext context; + DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, @@ -1621,12 +2020,922 @@ TEST(t_dlt_user_log_write_utf8_string, normal) EXPECT_LE(DLT_RETURN_OK, dlt_unregister_app()); } -TEST(t_dlt_user_log_write_utf8_string, nullpointer) +/** + * Send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN + * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and + * message will be truncated at one byte utf-8 and appended STR_TRUNCATED_MESSAGE at + * the end of received message. + */ +TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_1byte_in_verbose_mode) +{ + DltContext context; + DltContextData contextData; + uint16_t index = 0; + uint16_t package_description_size = 0; + uint16_t user_message_after_truncated_size = 0; + uint16_t send_message_length = 0; + uint16_t str_truncate_message_length = 0; + uint16_t expected_message_length = 0; + char *message = NULL; + char *expected_message = NULL; + + EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); + EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_1byte_in_verbose_mode")); + + /* Normal values */ + EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); + + /* Create the message exceed buffer length 10 bytes which have '$' character (utf-8 1 byte) right before truncate position */ + send_message_length = DLT_USER_BUF_MAX_SIZE + 10; + message = (char *)(malloc(send_message_length)); + ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; + + for (index = 0; index < send_message_length; index++) + { + message[index] = '#'; + } + message[send_message_length - 1] = '\0'; + + /** + * In Verbose Mode: + * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) + */ + package_description_size = sizeof(uint32_t) + sizeof(uint16_t); + + /* Fill '$' before truncate position */ + str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; + index = (DLT_USER_BUF_MAX_SIZE - package_description_size - str_truncate_message_length - 1); + message[index] = '$'; + + /* Create the expected message */ + expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; + expected_message = (char *)(malloc(expected_message_length)); + ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; + user_message_after_truncated_size = expected_message_length - str_truncate_message_length; + + for (index = 0; index < (user_message_after_truncated_size - 1); index++) + { + expected_message[index] = '#'; + } + expected_message[user_message_after_truncated_size - 1] = '$'; + strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); + + EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); + ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); + + free(message); + message = NULL; + free(expected_message); + message = NULL; + + EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); +} + +/** + * In Non-Verbose Mode, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN + * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and + * message will be truncated at one byte utf-8 and appended STR_TRUNCATED_MESSAGE at + * the end of received message. + */ +TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_1byte_in_non_verbose_mode) { DltContext context; DltContextData contextData; + uint16_t index = 0; + uint16_t package_description_size = 0; + uint16_t user_message_after_truncated_size = 0; + uint16_t send_message_length = 0; + uint16_t str_truncate_message_length = 0; + uint16_t expected_message_length = 0; + char *message = NULL; + char *expected_message = NULL; + + dlt_nonverbose_mode(); + EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); + EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_1byte_in_non_verbose_mode")); + + /* Normal values */ + EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); + + /* Create the message exceed buffer length 10 bytes which have '$' character (utf-8 1 byte) right before truncate position */ + send_message_length = DLT_USER_BUF_MAX_SIZE + 10; + message = (char *)(malloc(send_message_length)); + ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; + + for (index = 0; index < send_message_length; index++) + { + message[index] = '#'; + } + message[send_message_length - 1] = '\0'; + + str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; + + /** + * In Non-Verbose Mode: + * package_description_size = Message ID (32 bits) + Description of data payload of type string (16 bits) + */ + package_description_size = sizeof(uint32_t) + sizeof(uint16_t); + + /* Fill '$' before truncate position */ + index = (DLT_USER_BUF_MAX_SIZE - package_description_size - str_truncate_message_length - 1); + message[index] = '$'; + + /* Create the expected message */ + expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; + expected_message = (char *)(malloc(expected_message_length)); + ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; + user_message_after_truncated_size = expected_message_length - str_truncate_message_length; + + for (index = 0; index < (user_message_after_truncated_size - 1); index++) + { + expected_message[index] = '#'; + } + expected_message[user_message_after_truncated_size - 1] = '$'; + strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); + + EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); + ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); + + free(message); + message = NULL; + free(expected_message); + message = NULL; + + EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); + + /* Restore verbose mode */ + dlt_verbose_mode(); +} + +/** + * Set the DLT_USER_ENV_LOG_MSG_BUF_LEN to 46, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN + * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and + * message will be truncated at the whole utf-8 1 bytes and appended + * STR_TRUNCATED_MESSAGE at the end of received message. + * Note: dlt_init() will be called after testcase is finished to restore environment for other testcases + */ +TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_1bytes_and_reduce_msg_buf_len_by_env_variable) +{ + DltContext context; + DltContextData contextData; + uint16_t index = 0; + uint16_t package_description_size = 0; + uint16_t expected_message_length = 0; + uint16_t str_truncate_message_length = 0; + uint16_t user_message_after_truncated_size = 0; + const char *message = "$$$$###############################################"; + char *expected_message = NULL; + + /** + * Re-initialize the dlt with dlt user buffer size from DLT_USER_ENV_LOG_MSG_BUF_LEN environment variable + * to simulate use case the dlt user buffer size only available 4 bytes for store user message. + * Note: 46 bytes = package_description_size (6 bytes) + str_truncated_message_length (35 bytes) + 4 bytes user message + 1 byte NULL terminator. + */ + user_message_after_truncated_size = 4; + EXPECT_EQ(DLT_RETURN_OK, dlt_free()); + setenv(DLT_USER_ENV_LOG_MSG_BUF_LEN, "46", 1); + EXPECT_EQ(DLT_RETURN_OK, dlt_init()); + + EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); + EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_1bytes_and_reduce_msg_buf_len_by_env_variable")); + + /* Normal values */ + EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); + EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); + + /** + * In Verbose Mode: + * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) + */ + package_description_size = sizeof(uint32_t) + sizeof(uint16_t); + str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; + + /* Create the expected message */ + expected_message_length = user_message_after_truncated_size + str_truncate_message_length; + expected_message = (char *)(malloc(expected_message_length)); + ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; + + for (index = 0; index < user_message_after_truncated_size; index++) + { + expected_message[index] = '$'; + } + strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); + + ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); + EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); + + /* Restore the dlt with dlt user buffer size as default */ + EXPECT_EQ(DLT_RETURN_OK, dlt_free()); + unsetenv(DLT_USER_ENV_LOG_MSG_BUF_LEN); + EXPECT_EQ(DLT_RETURN_OK, dlt_init()); +} + +/** + * In Non-Verbose Mode, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN + * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and + * message will be truncated at the middle of utf-8 2 bytes, the rest of this utf-8 character will + * be removed completely, after that appended STR_TRUNCATED_MESSAGE at + * the end of received message. + */ +TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_2bytes_in_verbose_mode) +{ + DltContext context; + DltContextData contextData; + uint16_t index = 0; + uint16_t package_description_size = 0; + uint16_t user_message_after_truncated_size = 0; + uint16_t send_message_length = 0; + uint16_t str_truncate_message_length = 0; + uint16_t expected_message_length = 0; + uint16_t remaining_byte_truncated_utf8_character = 0; + const char *utf8_2byte_character = "¢"; + char *message = NULL; + char *expected_message = NULL; + + EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); + EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_2bytes_in_verbose_mode")); + + /* Normal values */ + EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); + + /* Create the message contain the '¢' (2 bytes utf-8 character) and last byte of this character is exceed buffer length */ + send_message_length = DLT_USER_BUF_MAX_SIZE + 10; + message = (char *)(malloc(send_message_length)); + ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; + + for (index = 0; index < send_message_length; index++) + { + message[index] = '#'; + } + message[send_message_length - 1] = '\0'; + + /** + * In Verbose Mode: + * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) + */ + package_description_size = sizeof(uint32_t) + sizeof(uint16_t); + + /** + * Fill the "¢" character at the position which the last byte of this character is exceed the buffer length and + * expectation is it will be truncated 1 more bytes in the character sequence + */ + str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; + remaining_byte_truncated_utf8_character = 1; + index = (DLT_USER_BUF_MAX_SIZE - package_description_size - str_truncate_message_length - remaining_byte_truncated_utf8_character); + strncpy(message + index, utf8_2byte_character, strlen(utf8_2byte_character)); + + /* Create the expected message */ + expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; + expected_message = (char *)(malloc(expected_message_length)); + ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; + user_message_after_truncated_size = expected_message_length - str_truncate_message_length - remaining_byte_truncated_utf8_character; + + for (index = 0; index < user_message_after_truncated_size; index++) + { + expected_message[index] = '#'; + } + strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); + + EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); + ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); + + free(message); + message = NULL; + free(expected_message); + expected_message = NULL; + + EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); +} + +/** + * In Non-Verbose Mode, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN + * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and + * message will be truncated at the middle of utf-8 2 bytes, the rest of this utf-8 character will + * be removed completely, after that appended STR_TRUNCATED_MESSAGE at + * the end of received message. + */ +TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_2bytes_in_non_verbose_mode) +{ + DltContext context; + DltContextData contextData; + uint16_t index = 0; + uint16_t package_description_size = 0; + uint16_t user_message_after_truncated_size = 0; + uint16_t send_message_length = 0; + uint16_t str_truncate_message_length = 0; + uint16_t expected_message_length = 0; + uint16_t remaining_byte_truncated_utf8_character = 0; + const char *utf8_2byte_character = "¢"; + char *message = NULL; + char *expected_message = NULL; + + dlt_nonverbose_mode(); + + EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); + EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_2bytes_in_non_verbose_mode")); + + /* Normal values */ + EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); + + /* Create the message contain the '¢' (2 bytes utf-8 character) and last byte of this character is exceed buffer length */ + send_message_length = DLT_USER_BUF_MAX_SIZE + 10; + message = (char *)(malloc(send_message_length)); + ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; + + for (index = 0; index < send_message_length; index++) + { + message[index] = '#'; + } + message[send_message_length - 1] = '\0'; + + /** + * In Non-Verbose Mode: + * package_description_size = Message ID (32 bits) + Description of data payload of type string (16 bits) + */ + package_description_size = sizeof(uint32_t) + sizeof(uint16_t); + + /** + * Fill the "¢" character at the position which the last byte of this character is exceed the buffer length and + * expectation is it will be truncated 1 more bytes in the character sequence + */ + str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; + remaining_byte_truncated_utf8_character = 1; + index = (DLT_USER_BUF_MAX_SIZE - package_description_size - str_truncate_message_length - remaining_byte_truncated_utf8_character); + strncpy(message + index, utf8_2byte_character, strlen(utf8_2byte_character)); + + /* Create the expected message */ + expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; + expected_message = (char *)(malloc(DLT_USER_BUF_MAX_SIZE)); + ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; + user_message_after_truncated_size = expected_message_length - str_truncate_message_length - remaining_byte_truncated_utf8_character; + + for (index = 0; index < user_message_after_truncated_size; index++) + { + expected_message[index] = '#'; + } + strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); + + EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); + ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); + + free(message); + message = NULL; + free(expected_message); + expected_message = NULL; + + EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); + + /* Restore verbose mode */ + dlt_verbose_mode(); +} + +/** + * Set the DLT_USER_ENV_LOG_MSG_BUF_LEN to 46, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN + * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and + * message will be truncated at the middle of utf-8 2 bytes, the rest of this utf-8 character will + * be removed completely, after that appended STR_TRUNCATED_MESSAGE at + * the end of received message. + * Note: dlt_init() will be called after testcase is finished to restore environment for other testcases + */ +TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_2bytes_and_reduce_msg_buf_len_by_env_variable) +{ + DltContext context; + DltContextData contextData; + uint16_t index = 0; + uint16_t str_truncate_message_length = 0; + uint16_t expected_message_length = 0; + uint16_t package_description_size = 0; + uint16_t user_message_after_truncated_size = 0; + uint16_t remaining_byte_truncated_utf8_character = 0; + const char *message = "$$$¢###############################################"; + char *expected_message = NULL; + + /** + * Re-initialize the dlt with dlt user buffer size from DLT_USER_ENV_LOG_MSG_BUF_LEN environment variable + * to simulate use case the dlt user buffer size only available 4 bytes for store user message. + * Note: 46 bytes = package_description_size (6 bytes) + str_truncated_message_length (35 bytes) + 4 bytes user message + 1 byte NULL terminator. + */ + user_message_after_truncated_size = 4; + EXPECT_EQ(DLT_RETURN_OK, dlt_free()); + setenv(DLT_USER_ENV_LOG_MSG_BUF_LEN, "46", 1); + EXPECT_EQ(DLT_RETURN_OK, dlt_init()); + + EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); + EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_2bytes_and_reduce_msg_buf_len_by_env_variable")); + + /* Normal values */ + EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); + + EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); + + /** + * In Verbose Mode: + * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) + */ + package_description_size = sizeof(uint32_t) + sizeof(uint16_t); + str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; + + /* Create the expected message */ + remaining_byte_truncated_utf8_character = 1; + expected_message_length = user_message_after_truncated_size - remaining_byte_truncated_utf8_character + str_truncate_message_length; + expected_message = (char *)(malloc(expected_message_length)); + ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; + user_message_after_truncated_size -= remaining_byte_truncated_utf8_character; + + for (index = 0; index < user_message_after_truncated_size; index++) + { + expected_message[index] = '$'; + } + strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); + + ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); + EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); + + /* Restore the dlt with dlt user buffer size as default */ + EXPECT_EQ(DLT_RETURN_OK, dlt_free()); + unsetenv(DLT_USER_ENV_LOG_MSG_BUF_LEN); + EXPECT_EQ(DLT_RETURN_OK, dlt_init()); +} + +/** + * In Non-Verbose Mode, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN + * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and + * message will be truncated at the middle of utf-8 3 bytes, the rest of this utf-8 character will + * be removed completely, after that appended STR_TRUNCATED_MESSAGE at + * the end of received message. + */ +TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_3bytes_in_verbose_mode) +{ + DltContext context; + DltContextData contextData; + uint16_t index = 0; + uint16_t package_description_size = 0; + uint16_t user_message_after_truncated_size = 0; + uint16_t send_message_length = 0; + uint16_t str_truncate_message_length = 0; + uint16_t expected_message_length = 0; + uint16_t remaining_byte_truncated_utf8_character = 0; + const char *utf8_3byte_character = "€"; + char *message = NULL; + char *expected_message = NULL; + + EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); + EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_3bytes_in_verbose_mode")); + + /* normal values */ + EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); + + /* Create the message contain the '€' (3 bytes utf-8 character) and last byte of this character is exceed buffer length */ + send_message_length = DLT_USER_BUF_MAX_SIZE + 10; + message = (char *)(malloc(send_message_length)); + ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; + + for (index = 0; index < send_message_length; index++) + { + message[index] = '#'; + } + message[send_message_length - 1] = '\0'; + + /** + * In Verbose Mode: + * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) + */ + package_description_size = sizeof(uint32_t) + sizeof(uint16_t); + + /** + * Fill the "€" character at the position which the last byte of this character is exceed the buffer length and + * expectation is it will be truncated 2 more bytes in the character sequence + */ + str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; + remaining_byte_truncated_utf8_character = 2; + index = (DLT_USER_BUF_MAX_SIZE - package_description_size - str_truncate_message_length - remaining_byte_truncated_utf8_character); + strncpy(message + index, utf8_3byte_character, strlen(utf8_3byte_character)); + + /* Create the expected message */ + expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; + expected_message = (char *)(malloc(expected_message_length)); + ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; + user_message_after_truncated_size = expected_message_length - str_truncate_message_length - remaining_byte_truncated_utf8_character; + + for (index = 0; index < user_message_after_truncated_size; index++) + { + expected_message[index] = '#'; + } + strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); + + EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); + ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); + + free(message); + message = NULL; + free(expected_message); + expected_message = NULL; + + EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); +} + +/** + * In Non-Verbose Mode, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN + * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and + * message will be truncated at the middle of utf-8 3 bytes, the rest of this utf-8 character will + * be removed completely, after that appended STR_TRUNCATED_MESSAGE at + * the end of received message. + */ +TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_3bytes_in_non_verbose_mode) +{ + DltContext context; + DltContextData contextData; + uint16_t index = 0; + uint16_t package_description_size = 0; + uint16_t user_message_after_truncated_size = 0; + uint16_t send_message_length = 0; + uint16_t str_truncate_message_length = 0; + uint16_t expected_message_length = 0; + uint16_t remaining_byte_truncated_utf8_character = 0; + const char *utf8_3byte_character = "€"; + char *message = NULL; + char *expected_message = NULL; + + dlt_nonverbose_mode(); + + EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); + EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_3bytes_in_non_verbose_mode")); + + /* Normal values */ + EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); + + /* Create the message contain the '€' (3 bytes utf-8 character) and last byte of this character is exceed buffer length */ + send_message_length = DLT_USER_BUF_MAX_SIZE + 10; + message = (char *)(malloc(send_message_length)); + ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; + + for (index = 0; index < send_message_length; index++) + { + message[index] = '#'; + } + message[send_message_length - 1] = '\0'; + + /** + * In Verbose Mode: + * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) + */ + package_description_size = sizeof(uint32_t) + sizeof(uint16_t); + + /** + * Fill the "€" character at the position which the last byte of this character is exceed the buffer length and + * expectation is it will be truncated 2 more bytes in the character sequence + */ + str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; + remaining_byte_truncated_utf8_character = 2; + index = (DLT_USER_BUF_MAX_SIZE - package_description_size - str_truncate_message_length - remaining_byte_truncated_utf8_character); + strncpy(message + index, utf8_3byte_character, strlen(utf8_3byte_character)); + + /* Create the expected message */ + expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; + expected_message = (char *)(malloc(expected_message_length)); + ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; + user_message_after_truncated_size = expected_message_length - str_truncate_message_length - remaining_byte_truncated_utf8_character; + + for (index = 0; index < user_message_after_truncated_size; index++) + { + expected_message[index] = '#'; + } + strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); + + EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); + ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); + + free(message); + message = NULL; + free(expected_message); + expected_message = NULL; + + EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); + + /* Restore verbose mode */ + dlt_verbose_mode(); +} + +/** + * Set the DLT_USER_ENV_LOG_MSG_BUF_LEN to 46, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN + * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and + * message will be truncated at the middle of utf-8 3 bytes, the rest of this utf-8 character will + * be removed completely, after that appended STR_TRUNCATED_MESSAGE at + * the end of received message. + * Note: dlt_init() will be called after testcase is finished to restore environment for other testcases + */ +TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_3bytes_and_reduce_msg_buf_len_by_env_variable) +{ + DltContext context; + DltContextData contextData; + uint16_t index = 0; + uint16_t str_truncate_message_length = 0; + uint16_t expected_message_length = 0; + uint16_t package_description_size = 0; + uint16_t user_message_after_truncated_size = 0; + uint16_t remaining_byte_truncated_utf8_character = 0; + const char *message = "$$€###############################################"; + char *expected_message = NULL; + + /** + * Re-initialize the dlt with dlt user buffer size from DLT_USER_ENV_LOG_MSG_BUF_LEN environment variable + * to simulate use case the dlt user buffer size only available 4 bytes for store user message. + * Note: 46 bytes = package_description_size (6 bytes) + str_truncated_message_length (35 bytes) + 4 bytes user message + 1 byte NULL terminator. + */ + user_message_after_truncated_size = 4; + EXPECT_EQ(DLT_RETURN_OK, dlt_free()); + setenv(DLT_USER_ENV_LOG_MSG_BUF_LEN, "46", 1); + EXPECT_EQ(DLT_RETURN_OK, dlt_init()); + + EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); + EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_3bytes_and_reduce_msg_buf_len_by_env_variable")); + + /* Normal values */ + EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); + + EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); + + /** + * In Verbose Mode: + * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) + */ + package_description_size = sizeof(uint32_t) + sizeof(uint16_t); + str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; + + /* Create the expected message */ + remaining_byte_truncated_utf8_character = 2; + expected_message_length = user_message_after_truncated_size - remaining_byte_truncated_utf8_character + str_truncate_message_length; + expected_message = (char *)(malloc(expected_message_length)); + ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; + user_message_after_truncated_size -= remaining_byte_truncated_utf8_character; + + for (index = 0; index < user_message_after_truncated_size; index++) + { + expected_message[index] = '$'; + } + strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); + + ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); + EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); + + /* Restore the dlt with dlt user buffer size as default */ + EXPECT_EQ(DLT_RETURN_OK, dlt_free()); + unsetenv(DLT_USER_ENV_LOG_MSG_BUF_LEN); + EXPECT_EQ(DLT_RETURN_OK, dlt_init()); +} + +/** + * In Non-Verbose Mode, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN + * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and + * message will be truncated at the middle of utf-8 4 bytes, the rest of this utf-8 character will + * be removed completely, after that appended STR_TRUNCATED_MESSAGE at + * the end of received message. + */ +TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_4bytes_in_verbose_mode) +{ + DltContext context; + DltContextData contextData; + uint16_t index = 0; + uint16_t package_description_size = 0; + uint16_t user_message_after_truncated_size = 0; + uint16_t send_message_length = 0; + uint16_t str_truncate_message_length = 0; + uint16_t expected_message_length = 0; + uint16_t remaining_byte_truncated_utf8_character = 0; + const char *utf8_4byte_character = "𐍈"; + char *message = NULL; + char *expected_message = NULL; + + EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); + EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_4bytes_in_verbose_mode")); + + /* Normal values */ + EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); + + /* Create the message contain the '𐍈' (4 bytes utf-8 character) and last byte of this character is exceed buffer length */ + send_message_length = DLT_USER_BUF_MAX_SIZE + 10; + message = (char *)(malloc(send_message_length)); + ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; + + for (index = 0; index < send_message_length; index++) + { + message[index] = '#'; + } + message[send_message_length - 1] = '\0'; + + /** + * In Verbose Mode: + * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) + */ + package_description_size = sizeof(uint32_t) + sizeof(uint16_t); + + /** + * Fill the "𐍈" character at the position which the last byte of this character is exceed the buffer length and + * expectation is it will be truncated 3 more bytes in the character sequence + */ + str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; + remaining_byte_truncated_utf8_character = 3; + index = (DLT_USER_BUF_MAX_SIZE - package_description_size - str_truncate_message_length - remaining_byte_truncated_utf8_character); + strncpy(message + index, utf8_4byte_character, strlen(utf8_4byte_character)); + + /* Create the expected message */ + expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; + expected_message = (char *)(malloc(expected_message_length)); + ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; + user_message_after_truncated_size = expected_message_length - str_truncate_message_length - remaining_byte_truncated_utf8_character; + + for (index = 0; index < user_message_after_truncated_size; index++) + { + expected_message[index] = '#'; + } + strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); + + EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); + ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); + + free(message); + message = NULL; + free(expected_message); + expected_message = NULL; + + EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); +} + +/** + * In Non-Verbose Mode, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN + * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and + * message will be truncated at the middle of utf-8 4 bytes, the rest of this utf-8 character will + * be removed completely, after that appended STR_TRUNCATED_MESSAGE at + * the end of received message. + */ +TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_4bytes_in_non_verbose_mode) +{ + DltContext context; + DltContextData contextData; + uint16_t index = 0; + uint16_t package_description_size = 0; + uint16_t user_message_after_truncated_size = 0; + uint16_t send_message_length = 0; + uint16_t str_truncate_message_length = 0; + uint16_t expected_message_length = 0; + uint16_t remaining_byte_truncated_utf8_character = 0; + const char *utf8_4byte_character = "𐍈"; + char *message = NULL; + char *expected_message = NULL; + + dlt_nonverbose_mode(); + + EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); + EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_4bytes_in_non_verbose_mode")); + + /* Normal values */ + EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); + + /* Create the message contain the '𐍈' (4 bytes utf-8 character) and last byte of this character is exceed buffer length */ + send_message_length = DLT_USER_BUF_MAX_SIZE + 10; + message = (char *)(malloc(send_message_length)); + ASSERT_TRUE(message != NULL) << "Failed to allocate memory."; + + for (index = 0; index < send_message_length; index++) + { + message[index] = '#'; + } + message[send_message_length - 1] = '\0'; + + /** + * In Non-Verbose Mode: + * package_description_size = Message ID (32 bits) + Description of data payload of type string (16 bits) + */ + package_description_size = sizeof(uint32_t) + sizeof(uint16_t); + + /** + * Fill the "𐍈" character at the position which the last byte of this character is exceed the buffer length and + * expectation is it will be truncated 3 more bytes in the character sequence + */ + str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; + remaining_byte_truncated_utf8_character = 3; + index = (DLT_USER_BUF_MAX_SIZE - package_description_size - str_truncate_message_length - remaining_byte_truncated_utf8_character); + strncpy(message + index, utf8_4byte_character, strlen(utf8_4byte_character)); + + /* Create the expected message */ + expected_message_length = DLT_USER_BUF_MAX_SIZE - package_description_size; + expected_message = (char *)(malloc(expected_message_length)); + ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; + user_message_after_truncated_size = expected_message_length - str_truncate_message_length - remaining_byte_truncated_utf8_character; + + for (index = 0; index < user_message_after_truncated_size; index++) + { + expected_message[index] = '#'; + } + strncpy(expected_message + user_message_after_truncated_size, STR_TRUNCATED_MESSAGE, str_truncate_message_length); + + EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); + ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); + + free(message); + message = NULL; + free(expected_message); + expected_message = NULL; + + EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); + + /* Restore verbose mode */ + dlt_verbose_mode(); +} + +/** + * Set the DLT_USER_ENV_LOG_MSG_BUF_LEN to 46, send a message which has the length exceed DLT_USER_ENV_LOG_MSG_BUF_LEN + * Expectation: dlt_user_log_write_utf8_string() will be returned DLT_RETURN_USER_BUFFER_FULL and + * message will be truncated at the middle of utf-8 4 bytes, the rest of this utf-8 character will + * be removed completely, after that appended STR_TRUNCATED_MESSAGE at + * the end of received message. + * Note: dlt_init() will be called after testcase is finished to restore environment for other testcases + */ +TEST(t_dlt_user_log_write_utf8_string, normal_message_truncated_at_utf8_4bytes_and_reduce_msg_buf_len_by_env_variable) +{ + DltContext context; + DltContextData contextData; + uint16_t str_truncate_message_length = 0; + uint16_t expected_message_length = 0; + uint16_t package_description_size = 0; + uint16_t user_message_after_truncated_size = 0; + uint16_t remaining_byte_truncated_utf8_character = 0; + const char *message = "$𐍈###############################################"; + char *expected_message = NULL; + + /** + * Re-initialize the dlt with dlt user buffer size from DLT_USER_ENV_LOG_MSG_BUF_LEN environment variable + * to simulate use case the dlt user buffer size only available 4 bytes for store user message. + * Note: 46 bytes = package_description_size (6 bytes) + str_truncated_message_length (35 bytes) + 4 bytes user message + 1 byte NULL terminator. + */ + user_message_after_truncated_size = 4; + EXPECT_EQ(DLT_RETURN_OK, dlt_free()); + setenv(DLT_USER_ENV_LOG_MSG_BUF_LEN, "46", 1); + EXPECT_EQ(DLT_RETURN_OK, dlt_init()); + + EXPECT_EQ(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); + EXPECT_EQ(DLT_RETURN_OK, dlt_register_context(&context, "TEST", "dlt_user.c t_dlt_user_log_write_utf8_string normal_message_truncated_at_utf8_4bytes_and_reduce_msg_buf_len_by_env_variable")); + + /* Normal values */ + EXPECT_LE(DLT_RETURN_OK, dlt_user_log_write_start(&context, &contextData, DLT_LOG_DEFAULT)); + + EXPECT_EQ(DLT_RETURN_USER_BUFFER_FULL, dlt_user_log_write_utf8_string(&contextData, message)); + + /** + * In Verbose Mode: + * package_description_size = Type info (32 bits) + Description of data payload of type string (16 bits) + */ + package_description_size = sizeof(uint32_t) + sizeof(uint16_t); + str_truncate_message_length = strlen(STR_TRUNCATED_MESSAGE) + 1; + + /* Create the expected message */ + remaining_byte_truncated_utf8_character = 3; + expected_message_length = user_message_after_truncated_size - remaining_byte_truncated_utf8_character + str_truncate_message_length; + expected_message = (char *)(malloc(expected_message_length)); + ASSERT_TRUE(expected_message != NULL) << "Failed to allocate memory."; + + expected_message[0] = '$'; + strncpy(expected_message + 1, STR_TRUNCATED_MESSAGE, str_truncate_message_length); + + ASSERT_STREQ(expected_message, (char *)(contextData.buffer + package_description_size)); + EXPECT_EQ(DLT_RETURN_OK, dlt_user_log_write_finish(&contextData)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_context(&context)); + EXPECT_EQ(DLT_RETURN_OK, dlt_unregister_app()); + + /* Restore the dlt with dlt user buffer size as default */ + EXPECT_EQ(DLT_RETURN_OK, dlt_free()); + unsetenv(DLT_USER_ENV_LOG_MSG_BUF_LEN); + EXPECT_EQ(DLT_RETURN_OK, dlt_init()); +} + +TEST(t_dlt_user_log_write_utf8_string, nullpointer) +{ + DltContext context; + DltContextData contextData; EXPECT_LE(DLT_RETURN_OK, dlt_register_app("TUSR", "dlt_user.c tests")); EXPECT_LE(DLT_RETURN_OK, -- cgit v1.2.1