diff --git a/client/client-multi/client-c/src/kaa/kaa_logging.c b/client/client-multi/client-c/src/kaa/kaa_logging.c index bf25b64af8..2f4f56e82c 100644 --- a/client/client-multi/client-c/src/kaa/kaa_logging.c +++ b/client/client-multi/client-c/src/kaa/kaa_logging.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "platform/stdio.h" #include "platform/sock.h" #include "platform/time.h" @@ -34,45 +35,40 @@ #include "utilities/kaa_log.h" #include "avro_src/avro/io.h" - - #define KAA_LOGGING_RECEIVE_UPDATES_FLAG 0x01 #define KAA_MAX_PADDING_LENGTH (KAA_ALIGNMENT - 1) - - extern kaa_transport_channel_interface_t *kaa_channel_manager_get_transport_channel(kaa_channel_manager_t *self , kaa_service_t service_type); extern bool ext_log_upload_strategy_is_timeout_strategy(void *strategy); - - typedef enum { LOGGING_RESULT_SUCCESS = 0x00, LOGGING_RESULT_FAILURE = 0x01 } logging_sync_result_t; typedef struct { - uint16_t log_bucket_id; - kaa_time_t timeout; + kaa_time_t timeout; /**< Bucket timeout. */ + uint16_t log_bucket_id; /**< ID of bucket present in storage. */ + uint16_t log_count; /**< Current logs count. */ } timeout_info_t; struct kaa_log_collector { - uint16_t log_bucket_id; - void *log_storage_context; - void *log_upload_strategy_context; - kaa_status_t *status; - kaa_channel_manager_t *channel_manager; - kaa_logger_t *logger; - kaa_list_t *timeouts; - bool is_sync_ignored; + kaa_log_bucket_constraints_t bucket_size; + void *log_storage_context; + void *log_upload_strategy_context; + kaa_status_t *status; + kaa_channel_manager_t *channel_manager; + kaa_logger_t *logger; + kaa_list_t *timeouts; + kaa_log_delivery_listener_t log_delivery_listeners; + bool is_sync_ignored; + uint32_t log_last_id; /**< Last log record ID */ + uint16_t log_bucket_id; }; - - -static const kaa_service_t logging_sync_services[1] = {KAA_SERVICE_LOGGING}; - +static const kaa_service_t logging_sync_services[] = {KAA_SERVICE_LOGGING}; kaa_error_t kaa_logging_need_logging_resync(kaa_log_collector_t *self, bool *result) { @@ -85,7 +81,7 @@ kaa_error_t kaa_logging_need_logging_resync(kaa_log_collector_t *self, bool *res return KAA_ERR_NONE; } -static kaa_error_t remember_request(kaa_log_collector_t *self, uint16_t bucket_id) +static kaa_error_t remember_request(kaa_log_collector_t *self, uint16_t bucket_id, uint16_t count) { KAA_RETURN_IF_NIL(self, KAA_ERR_BADPARAM); @@ -94,6 +90,7 @@ static kaa_error_t remember_request(kaa_log_collector_t *self, uint16_t bucket_i info->log_bucket_id = bucket_id; info->timeout = KAA_TIME() + (kaa_time_t)ext_log_upload_strategy_get_timeout(self->log_upload_strategy_context); + info->log_count = count; kaa_list_node_t *it = kaa_list_push_back(self->timeouts, info); if (!it) { @@ -104,24 +101,41 @@ static kaa_error_t remember_request(kaa_log_collector_t *self, uint16_t bucket_i return KAA_ERR_NONE; } - - static bool find_by_bucket_id(void *data, void *context) { KAA_RETURN_IF_NIL2(data, context, false); - return (((timeout_info_t *)data)->log_bucket_id == *((uint16_t *)context)); -} + uint16_t bucket_id = *(uint16_t *) context; + timeout_info_t *timeout_info = data; + if (timeout_info->log_bucket_id == bucket_id) { + return true; + } + + return false; +} -static kaa_error_t remove_request(kaa_log_collector_t *self, uint16_t bucket_id) +/* Returns amount of logs in bucket */ +static size_t remove_request(kaa_log_collector_t *self, uint16_t bucket_id) { - KAA_RETURN_IF_NIL(self, KAA_ERR_BADPARAM); - kaa_list_remove_first(self->timeouts, &find_by_bucket_id, &bucket_id, NULL); - return KAA_ERR_NONE; -} + kaa_list_node_t *node; + timeout_info_t *info; + size_t logs_sent = 0; + + node = kaa_list_find_next(kaa_list_begin(self->timeouts), find_by_bucket_id, &bucket_id); + if (node) { + info = kaa_list_get_data(node); + if (info) { + logs_sent = info->log_count; + } + + kaa_list_remove_at(self->timeouts, node, NULL); + } + + return logs_sent; +} static bool is_timeout(kaa_log_collector_t *self) { @@ -146,6 +160,15 @@ static bool is_timeout(kaa_log_collector_t *self) while (it) { timeout_info_t *info = (timeout_info_t *)kaa_list_get_data(it); ext_log_storage_unmark_by_bucket_id(self->log_storage_context, info->log_bucket_id); + if (self->log_delivery_listeners.on_timeout) { + kaa_log_bucket_info_t log_bucket_info = { + .bucket_id = info->log_bucket_id, + .log_count = info->log_count, + }; + + self->log_delivery_listeners.on_timeout(self->log_delivery_listeners.ctx, + &log_bucket_info); + } it = kaa_list_next(it); } @@ -172,8 +195,6 @@ static bool is_upload_allowed(kaa_log_collector_t *self) return true; } - - void kaa_log_collector_destroy(kaa_log_collector_t *self) { KAA_RETURN_IF_NIL(self, ); @@ -194,13 +215,18 @@ kaa_error_t kaa_log_collector_create(kaa_log_collector_t **log_collector_p kaa_log_collector_t * collector = (kaa_log_collector_t *) KAA_MALLOC(sizeof(kaa_log_collector_t)); KAA_RETURN_IF_NIL(collector, KAA_ERR_NOMEM); - collector->log_bucket_id = 0; - collector->log_storage_context = NULL; - collector->log_upload_strategy_context = NULL; - collector->status = status; - collector->channel_manager = channel_manager; - collector->logger = logger; - collector->is_sync_ignored = false; + collector->log_bucket_id = 0; + collector->log_last_id = 0; + collector->log_storage_context = NULL; + collector->log_upload_strategy_context = NULL; + collector->status = status; + collector->channel_manager = channel_manager; + collector->logger = logger; + collector->is_sync_ignored = false; + + /* Must be overriden in _init() */ + collector->bucket_size.max_bucket_log_count = 0; + collector->bucket_size.max_bucket_size = 0; collector->timeouts = kaa_list_create(); if (!collector->timeouts) { @@ -213,8 +239,7 @@ kaa_error_t kaa_log_collector_create(kaa_log_collector_t **log_collector_p } - -kaa_error_t kaa_logging_init(kaa_log_collector_t *self, void *log_storage_context, void *log_upload_strategy_context) +kaa_error_t kaa_logging_init(kaa_log_collector_t *self, void *log_storage_context, void *log_upload_strategy_context, const kaa_log_bucket_constraints_t *bucket_sizes) { KAA_RETURN_IF_NIL3(self, log_storage_context, log_upload_strategy_context, KAA_ERR_BADPARAM); @@ -223,6 +248,8 @@ kaa_error_t kaa_logging_init(kaa_log_collector_t *self, void *log_storage_contex self->log_storage_context = log_storage_context; self->log_upload_strategy_context = log_upload_strategy_context; + self->log_delivery_listeners = KAA_LOG_EMPTY_LISTENERS; + self->bucket_size = *bucket_sizes; KAA_LOG_DEBUG(self->logger, KAA_ERR_NONE, "Initialized log collector with log storage {%p}, log upload strategy {%p}" , log_storage_context, log_upload_strategy_context); @@ -231,6 +258,29 @@ kaa_error_t kaa_logging_init(kaa_log_collector_t *self, void *log_storage_contex } +kaa_error_t kaa_logging_set_strategy(kaa_log_collector_t *self, void *log_upload_strategy_context) +{ + KAA_RETURN_IF_NIL2(self, log_upload_strategy_context, KAA_ERR_BADPARAM); + + if (self->log_upload_strategy_context) + ext_log_upload_strategy_destroy(self->log_upload_strategy_context); + + self->log_upload_strategy_context = log_upload_strategy_context; + + return KAA_ERR_NONE; +} + +kaa_error_t kaa_logging_set_storage(kaa_log_collector_t *self, void *log_storage_context) +{ + KAA_RETURN_IF_NIL2(self, log_storage_context, KAA_ERR_BADPARAM); + + if (self->log_storage_context) + ext_log_storage_destroy(self->log_storage_context); + + self->log_storage_context = log_storage_context; + + return KAA_ERR_NONE; +} static void do_sync(kaa_log_collector_t *self) { @@ -263,15 +313,16 @@ static void update_storage(kaa_log_collector_t *self) -kaa_error_t kaa_logging_add_record(kaa_log_collector_t *self, kaa_user_log_record_t *entry) +kaa_error_t kaa_logging_add_record(kaa_log_collector_t *self, kaa_user_log_record_t *entry, kaa_log_record_info_t *log_info) { KAA_RETURN_IF_NIL2(self, entry, KAA_ERR_BADPARAM); KAA_RETURN_IF_NIL(self->log_storage_context, KAA_ERR_NOT_INITIALIZED); kaa_log_record_t record = { NULL, entry->get_size(entry) }; if (!record.size) { - KAA_LOG_ERROR(self->logger, KAA_ERR_BADDATA, "Failed to add log record: serialized record size is null." - "Maybe log record schema is empty"); + KAA_LOG_ERROR(self->logger, KAA_ERR_BADDATA, + "Failed to add log record: serialized record size is null. " + "Maybe log record schema is empty"); return KAA_ERR_BADDATA; } @@ -297,14 +348,25 @@ kaa_error_t kaa_logging_add_record(kaa_log_collector_t *self, kaa_user_log_recor ext_log_storage_deallocate_log_record_buffer(self->log_storage_context, &record); return error; } + KAA_LOG_TRACE(self->logger, KAA_ERR_NONE, "Added log record, size %zu", record.size); if (!is_timeout(self)) update_storage(self); + if (log_info) { + log_info->bucket_id = self->log_bucket_id + 1; + log_info->log_id = self->log_last_id++; + } + return KAA_ERR_NONE; } - +kaa_error_t kaa_logging_set_listeners(kaa_log_collector_t *self, const kaa_log_delivery_listener_t *listeners) +{ + KAA_RETURN_IF_NIL2(self, listeners, KAA_ERR_BADPARAM); + self->log_delivery_listeners = *listeners; + return KAA_ERR_NONE; +} kaa_error_t kaa_logging_request_get_size(kaa_log_collector_t *self, size_t *expected_size) { @@ -328,7 +390,7 @@ kaa_error_t kaa_logging_request_get_size(kaa_log_collector_t *self, size_t *expe *expected_size += sizeof(uint32_t); // request id + log records count size_t actual_size = records_count * sizeof(uint32_t) + records_count * KAA_MAX_PADDING_LENGTH + total_size; - size_t bucket_size = ext_log_upload_strategy_get_bucket_size(self->log_upload_strategy_context); + size_t bucket_size = self->bucket_size.max_bucket_size; *expected_size += ((actual_size > bucket_size) ? bucket_size : actual_size); } @@ -360,8 +422,6 @@ kaa_error_t kaa_logging_request_serialize(kaa_log_collector_t *self, kaa_platfor return KAA_ERR_WRITE_FAILED; } - if (!self->log_bucket_id) - self->log_bucket_id = self->status->log_bucket_id; ++self->log_bucket_id; *((uint16_t *) tmp_writer.current) = KAA_HTONS(self->log_bucket_id); @@ -369,7 +429,10 @@ kaa_error_t kaa_logging_request_serialize(kaa_log_collector_t *self, kaa_platfor char *records_count_p = tmp_writer.current; // Pointer to the records count. Will be filled in later. tmp_writer.current += sizeof(uint16_t); - size_t bucket_size = ext_log_upload_strategy_get_bucket_size(self->log_upload_strategy_context); + /* Bucket size constraints */ + + size_t bucket_size = self->bucket_size.max_bucket_size; + size_t max_log_count = self->bucket_size.max_bucket_log_count; size_t actual_size = (tmp_writer.end - tmp_writer.current); bucket_size = (actual_size > bucket_size ? bucket_size : actual_size); @@ -378,7 +441,7 @@ kaa_error_t kaa_logging_request_serialize(kaa_log_collector_t *self, kaa_platfor uint16_t records_count = 0; - while (!error && bucket_size > sizeof(uint32_t)) { + while (!error && bucket_size > sizeof(uint32_t) && records_count < max_log_count) { size_t record_len = 0; error = ext_log_storage_write_next_record(self->log_storage_context , tmp_writer.current + sizeof(uint32_t) @@ -414,7 +477,7 @@ kaa_error_t kaa_logging_request_serialize(kaa_log_collector_t *self, kaa_platfor *((uint16_t *) records_count_p) = KAA_HTONS(records_count); *writer = tmp_writer; - error = remember_request(self, self->log_bucket_id); + error = remember_request(self, self->log_bucket_id, records_count); if (error) { KAA_LOG_WARN(self->logger, error, "Failed to remember request time stamp"); } @@ -455,17 +518,31 @@ kaa_error_t kaa_logging_handle_server_sync(kaa_log_collector_t *self error_code = kaa_platform_message_read(reader, &delivery_error_code, sizeof(int8_t)); KAA_RETURN_IF_ERR(error_code); + if (delivery_result == LOGGING_RESULT_SUCCESS) { KAA_LOG_INFO(self->logger, KAA_ERR_NONE, "Log bucket uploaded successfully, id '%u'", bucket_id); } else { KAA_LOG_WARN(self->logger, KAA_ERR_WRITE_FAILED, "Failed to upload log bucket, id '%u' (delivery error code '%u')", bucket_id, delivery_error_code); } - remove_request(self, bucket_id); + size_t uploaded_count = remove_request(self, bucket_id); + + kaa_log_bucket_info_t log_bucket_info = { + .log_count = uploaded_count, + .bucket_id = bucket_id, + }; if (delivery_result == LOGGING_RESULT_SUCCESS) { + if (self->log_delivery_listeners.on_success) { + self->log_delivery_listeners.on_success(self->log_delivery_listeners.ctx, + &log_bucket_info); + } ext_log_storage_remove_by_bucket_id(self->log_storage_context, bucket_id); } else { + if (self->log_delivery_listeners.on_failed) { + self->log_delivery_listeners.on_failed(self->log_delivery_listeners.ctx, + &log_bucket_info); + } ext_log_storage_unmark_by_bucket_id(self->log_storage_context, bucket_id); ext_log_upload_strategy_on_failure(self->log_upload_strategy_context , (logging_delivery_error_code_t)delivery_error_code); @@ -481,10 +558,10 @@ kaa_error_t kaa_logging_handle_server_sync(kaa_log_collector_t *self extern void ext_log_upload_timeout(kaa_log_collector_t *self) { - if (!is_timeout(self)) - update_storage(self); - else if (ext_log_upload_strategy_is_timeout_strategy(self->log_upload_strategy_context)) + if (!is_timeout(self) + || ext_log_upload_strategy_is_timeout_strategy(self->log_upload_strategy_context)) { update_storage(self); + } } #endif diff --git a/client/client-multi/client-c/src/kaa/kaa_logging.h b/client/client-multi/client-c/src/kaa/kaa_logging.h index cc311c0d42..088d2d48be 100644 --- a/client/client-multi/client-c/src/kaa/kaa_logging.h +++ b/client/client-multi/client-c/src/kaa/kaa_logging.h @@ -28,6 +28,7 @@ #include "gen/kaa_logging_definitions.h" #include "platform/ext_log_storage.h" #include "platform/ext_log_upload_strategy.h" +#include "platform/ext_log_delivery_listener.h" #ifdef __cplusplus extern "C" { @@ -42,6 +43,27 @@ extern "C" { typedef struct kaa_log_collector kaa_log_collector_t; #endif +/** + * @brief Log record info. + * + * Each log is contained in the bucket. Bucket is used to agreggate + * multiple logs into one entity that will be atomically sent to the server. + * Bucket can either be entirely successfully sent or be entirely failed. + * Corresponding events are generated. User may subscribe to them. + * @sa kaa_log_event_fn + * @sa kaa_log_listeners_t + * @sa kaa_logging_set_listeners + */ +typedef struct { + uint32_t log_id; /**< Id of a log record processed by kaa_logging_add_record() */ + uint16_t bucket_id; /**< Id of a bucket where a log record contained */ +} kaa_log_record_info_t; + +/** Constraints applied to log buckets */ +typedef struct { + size_t max_bucket_size; /**< The maximum bucket size in bytes */ + size_t max_bucket_log_count; /**< The maximum log count within a single bucket */ +} kaa_log_bucket_constraints_t; /** * @brief Initializes data collection module with the storage interface, upload strategy, and other settings. @@ -49,21 +71,60 @@ extern "C" { * @param[in] self Pointer to a @link kaa_log_collector_t @endlink instance. * @param[in] log_storage_context Log storage context. * @param[in] log_upload_strategy_context Log upload strategy context. + * @param[in] bucket_sizes Bucket size constraints. + * + * @return Error code. + */ +kaa_error_t kaa_logging_init(kaa_log_collector_t *self, void *log_storage_context, void *log_upload_strategy_context, const kaa_log_bucket_constraints_t *bucket_sizes); + +/** + * @brief Sets custom strategy for given collector. + * + * If a strategy has been assigned to collector previously then it will be + * destroyed and new strategy will be assigned. + * + * @param[in] self Pointer to a @link kaa_log_collector_t @endlink instance. + * @param[in] log_storage_context Log storage context. * * @return Error code. */ -kaa_error_t kaa_logging_init(kaa_log_collector_t *self, void *log_storage_context, void *log_upload_strategy_context); +kaa_error_t kaa_logging_set_strategy(kaa_log_collector_t *self, void *log_upload_strategy_context); +/** + * @brief Sets custom storage for given collector. + * + * If a storage has been assigned to collector previously then it will be + * destroyed and new storage will be assigned. Be aware that all items from + * previous storage will be deleted. + * + * @param[in] self Pointer to a @link kaa_log_collector_t @endlink instance. + * @param[in] log_storage_context Log storage context. + * + * @return Error code. + */ +kaa_error_t kaa_logging_set_storage(kaa_log_collector_t *self, void *log_storage_context); /** * @brief Serializes and adds a log record to the log storage. * - * @param[in] self Pointer to a @link kaa_log_collector_t @endlink instance. - * @param[in] entry Pointer to log entry to be added to the storage. + * @param[in] self Pointer to a @link kaa_log_collector_t @endlink instance. + * @param[in] entry Pointer to log entry to be added to the storage. + * @param[out] bucket Pointer to log bucket info. May be NULL. + * + * @return Error code. + */ +kaa_error_t kaa_logging_add_record(kaa_log_collector_t *self, kaa_user_log_record_t *entry, kaa_log_record_info_t *log_info); + +/** + * @brief Sets listeners of log events. * + * @param[in] self Pointer to a @link kaa_log_collector_t @endlink instance. + * @param[in] listeners Pointer to listeners that will be used to handle + * various log delivery events. @sa KAA_LOG_EMPTY_LISTENERS + * can be used to unsubscribe from log events. * @return Error code. */ -kaa_error_t kaa_logging_add_record(kaa_log_collector_t *self, kaa_user_log_record_t *entry); +kaa_error_t kaa_logging_set_listeners(kaa_log_collector_t *self, const kaa_log_delivery_listener_t *listeners); #ifdef __cplusplus } /* extern "C" */ diff --git a/client/client-multi/client-c/src/kaa/kaa_status.c b/client/client-multi/client-c/src/kaa/kaa_status.c index aa916a28f8..7dfc0f368b 100644 --- a/client/client-multi/client-c/src/kaa/kaa_status.c +++ b/client/client-multi/client-c/src/kaa/kaa_status.c @@ -59,7 +59,6 @@ kaa_error_t kaa_status_create(kaa_status_t ** kaa_status_p) READ_BUFFER(read_buf, &kaa_status->event_seq_n, sizeof(kaa_status->event_seq_n)); READ_BUFFER(read_buf, &kaa_status->config_seq_n, sizeof(kaa_status->config_seq_n)); READ_BUFFER(read_buf, &kaa_status->notification_seq_n, sizeof(kaa_status->notification_seq_n)); - READ_BUFFER(read_buf, &kaa_status->log_bucket_id, sizeof(kaa_status->log_bucket_id)); READ_BUFFER(read_buf, kaa_status->endpoint_public_key_hash, SHA_1_DIGEST_LENGTH); READ_BUFFER(read_buf, kaa_status->profile_hash, SHA_1_DIGEST_LENGTH); @@ -153,7 +152,6 @@ kaa_error_t kaa_status_save(kaa_status_t *self) WRITE_BUFFER(&self->event_seq_n, buffer, sizeof(self->event_seq_n)); WRITE_BUFFER(&self->config_seq_n, buffer, sizeof(self->config_seq_n)); WRITE_BUFFER(&self->notification_seq_n, buffer, sizeof(self->notification_seq_n)); - WRITE_BUFFER(&self->log_bucket_id, buffer, sizeof(self->log_bucket_id)); WRITE_BUFFER(self->endpoint_public_key_hash, buffer, SHA_1_DIGEST_LENGTH); WRITE_BUFFER(self->profile_hash, buffer, SHA_1_DIGEST_LENGTH); WRITE_BUFFER(&endpoint_access_token_length, buffer, sizeof(endpoint_access_token_length)); diff --git a/client/client-multi/client-c/src/kaa/kaa_status.h b/client/client-multi/client-c/src/kaa/kaa_status.h index b9376f23cb..bd0af85f91 100644 --- a/client/client-multi/client-c/src/kaa/kaa_status.h +++ b/client/client-multi/client-c/src/kaa/kaa_status.h @@ -38,7 +38,6 @@ typedef struct uint32_t event_seq_n; uint32_t config_seq_n; uint32_t notification_seq_n; - uint16_t log_bucket_id; bool is_registered; bool is_attached; bool is_updated; diff --git a/client/client-multi/client-c/src/kaa/platform-impl/Econais/EC19D/econais_ec19d_kaa_client.c b/client/client-multi/client-c/src/kaa/platform-impl/Econais/EC19D/econais_ec19d_kaa_client.c index 303adc60b9..dd5f5cd722 100644 --- a/client/client-multi/client-c/src/kaa/platform-impl/Econais/EC19D/econais_ec19d_kaa_client.c +++ b/client/client-multi/client-c/src/kaa/platform-impl/Econais/EC19D/econais_ec19d_kaa_client.c @@ -91,11 +91,14 @@ void print_mem_stat(kaa_client_t *kaa_client); * Strategy-specific configuration parameters used by Kaa log collection feature. */ #define KAA_DEMO_MAX_UPLOAD_THRESHOLD 15 /* Size of collected serialized logs needed to initiate log upload */ -#define KAA_DEMO_MAX_LOG_BUCKET_SIZE 16 /* Max size of a log batch has been sent by SDK during one upload. */ +/* Max size of a log batch has been sent by SDK during one upload. */ +#define KAA_DEMO_MAX_LOG_BUCKET_SIZE (KAA_TCP_CHANNEL_OUT_BUFFER_SIZE >> 3) +#define KAA_DEMO_MAX_LOGS_IN_BUCKET 16 /* Max count of logs in one bucket */ #define KAA_DEMO_MAX_CLEANUP_THRESHOLD 100 /* Max size of an inner log storage. If size is exceeded, elder logs will be removed. */ #define KAA_DEMO_LOG_GENERATION_FREQUENCY 3 /* seconds */ +_Static_assert(KAA_DEMO_MAX_LOG_BUCKET_SIZE, "Maximum bucket size cannot be 0!"); /* * Kaa status and public key storage file names. @@ -737,9 +740,15 @@ kaa_error_t kaa_log_collector_init(kaa_client_t *kaa_client) return error_code; } + kaa_log_bucket_constraints_t bucket_sizes = { + .max_bucket_size = KAA_DEMO_MAX_LOG_BUCKET_SIZE, + .max_bucket_log_count = KAA_DEMO_MAX_LOGS_IN_BUCKET, + }; + error_code = kaa_logging_init(kaa_client->kaa_context->log_collector , kaa_client->log_storage_context - , kaa_client->log_upload_strategy_context); + , kaa_client->log_upload_strategy_context + , &bucket_sizes); if (error_code) { KAA_LOG_ERROR(kaa_client->kaa_context->logger, diff --git a/client/client-multi/client-c/src/kaa/platform-impl/common/ext_log_upload_strategies.c b/client/client-multi/client-c/src/kaa/platform-impl/common/ext_log_upload_strategies.c index deb79e7c00..f3784a3f99 100644 --- a/client/client-multi/client-c/src/kaa/platform-impl/common/ext_log_upload_strategies.c +++ b/client/client-multi/client-c/src/kaa/platform-impl/common/ext_log_upload_strategies.c @@ -43,12 +43,6 @@ */ #define KAA_DEFAULT_UPLOAD_COUNT_THRESHOLD 64 -/** - * @brief The default value (in bytes) for the maximum size of the report pack that - * will be delivered in a single request to the Operaions server. - */ -#define KAA_DEFAULT_BATCH_SIZE 8 * 1024 - /** * @brief The default value for Max amount of log batches allowed to be uploaded parallel. */ @@ -91,7 +85,6 @@ kaa_error_t ext_log_upload_strategy_create(struct kaa_context_s *context, void * KAA_RETURN_IF_ERR( ext_log_upload_strategy_set_threshold_count(strategy, KAA_DEFAULT_UPLOAD_COUNT_THRESHOLD) ); KAA_RETURN_IF_ERR( ext_log_upload_strategy_set_upload_timeout(strategy, KAA_DEFAULT_UPLOAD_TIMEOUT) ); KAA_RETURN_IF_ERR( ext_log_upload_strategy_set_upload_retry_period(strategy, KAA_DEFAULT_RETRY_PERIOD) ); - KAA_RETURN_IF_ERR( ext_log_upload_strategy_set_batch_size(strategy, KAA_DEFAULT_BATCH_SIZE) ); KAA_RETURN_IF_ERR( ext_log_upload_strategy_set_max_parallel_uploads(strategy, KAA_DEFAULT_MAX_PARALLEL_UPLOADS) ); strategy->type = type; @@ -144,16 +137,6 @@ ext_log_upload_decision_t ext_log_upload_strategy_decide(void *context, const vo return decision; } - - -size_t ext_log_upload_strategy_get_bucket_size(void *context) -{ - KAA_RETURN_IF_NIL(context, 0); - return ((ext_log_upload_strategy_t *)context)->log_batch_size; -} - - - size_t ext_log_upload_strategy_get_timeout(void *context) { KAA_RETURN_IF_NIL(context, 0); diff --git a/client/client-multi/client-c/src/kaa/platform-impl/common/ext_log_upload_strategies.h b/client/client-multi/client-c/src/kaa/platform-impl/common/ext_log_upload_strategies.h index 5c5a3158b4..83962e201a 100644 --- a/client/client-multi/client-c/src/kaa/platform-impl/common/ext_log_upload_strategies.h +++ b/client/client-multi/client-c/src/kaa/platform-impl/common/ext_log_upload_strategies.h @@ -60,17 +60,6 @@ kaa_error_t ext_log_upload_strategy_set_threshold_count(void *strategy, size_t t -/** - * @brief Sets the new log batch size to the strategy. - * - * @param strategy The strategy instance. - * @param log_batch_size The new log batch size in bytes. - * @return Error code. - */ -kaa_error_t ext_log_upload_strategy_set_batch_size(void *strategy, size_t log_batch_size); - - - /** * @brief Sets the new upload timeout to the strategy. * diff --git a/client/client-multi/client-c/src/kaa/platform-impl/esp8266/esp8266_kaa_client.c b/client/client-multi/client-c/src/kaa/platform-impl/esp8266/esp8266_kaa_client.c index f9721ee993..6ecc99e3e1 100644 --- a/client/client-multi/client-c/src/kaa/platform-impl/esp8266/esp8266_kaa_client.c +++ b/client/client-multi/client-c/src/kaa/platform-impl/esp8266/esp8266_kaa_client.c @@ -60,6 +60,12 @@ static kaa_service_t OPERATIONS_SERVICES[] = { KAA_SERVICE_PROFILE }; static const int OPERATIONS_SERVICES_COUNT = sizeof(OPERATIONS_SERVICES) / sizeof(kaa_service_t); +/* Logging constraints */ +#define MAX_LOG_COUNT SIZE_MAX +#define MAX_LOG_BUCKET_SIZE (KAA_TCP_CHANNEL_OUT_BUFFER_SIZE >> 3) + +_Static_assert(MAX_LOG_BUCKET_SIZE, "Maximum bucket size cannot be 0!"); + struct kaa_client_t { kaa_context_t *context; bool operate; @@ -447,9 +453,15 @@ kaa_error_t kaa_log_collector_init(kaa_client_t *kaa_client) return error_code; } + kaa_log_bucket_constraints_t bucket_sizes = { + .max_bucket_size = MAX_LOG_BUCKET_SIZE, + .max_bucket_log_count = MAX_LOG_COUNT, + }; + error_code = kaa_logging_init(kaa_client->context->log_collector , kaa_client->log_storage_context - , kaa_client->log_upload_strategy_context); + , kaa_client->log_upload_strategy_context + , &bucket_sizes); if (error_code) { KAA_LOG_ERROR(kaa_client->context->logger, error_code,"Failed to init log collector"); return error_code; diff --git a/client/client-multi/client-c/src/kaa/platform-impl/posix/posix_kaa_client.c b/client/client-multi/client-c/src/kaa/platform-impl/posix/posix_kaa_client.c index ccff7d8b4a..e4817e3d1e 100644 --- a/client/client-multi/client-c/src/kaa/platform-impl/posix/posix_kaa_client.c +++ b/client/client-multi/client-c/src/kaa/platform-impl/posix/posix_kaa_client.c @@ -67,6 +67,11 @@ static kaa_service_t OPERATIONS_SERVICES[] = { KAA_SERVICE_PROFILE static const int OPERATIONS_SERVICES_COUNT = sizeof(OPERATIONS_SERVICES) / sizeof(kaa_service_t); +/* Logging constraints */ +#define MAX_LOG_COUNT SIZE_MAX +#define MAX_LOG_BUCKET_SIZE (KAA_TCP_CHANNEL_OUT_BUFFER_SIZE >> 3) + +_Static_assert(MAX_LOG_BUCKET_SIZE, "Maximum bucket size cannot be 0!"); typedef enum { KAA_CLIENT_CHANNEL_STATE_NOT_CONNECTED = 0, @@ -453,9 +458,15 @@ kaa_error_t kaa_log_collector_init(kaa_client_t *kaa_client) return error_code; } + kaa_log_bucket_constraints_t bucket_sizes = { + .max_bucket_size = MAX_LOG_BUCKET_SIZE, + .max_bucket_log_count = MAX_LOG_COUNT, + }; + error_code = kaa_logging_init(kaa_client->kaa_context->log_collector , kaa_client->log_storage_context - , kaa_client->log_upload_strategy_context); + , kaa_client->log_upload_strategy_context + , &bucket_sizes); if (error_code) { KAA_LOG_ERROR(kaa_client->kaa_context->logger, error_code,"Failed to init log collector"); return error_code; diff --git a/client/client-multi/client-c/src/kaa/platform-impl/stm32/leafMapleMini/esp8266/esp8266_kaa_client.c b/client/client-multi/client-c/src/kaa/platform-impl/stm32/leafMapleMini/esp8266/esp8266_kaa_client.c index cdbc43688e..ef0e602f15 100644 --- a/client/client-multi/client-c/src/kaa/platform-impl/stm32/leafMapleMini/esp8266/esp8266_kaa_client.c +++ b/client/client-multi/client-c/src/kaa/platform-impl/stm32/leafMapleMini/esp8266/esp8266_kaa_client.c @@ -70,7 +70,11 @@ static kaa_service_t OPERATIONS_SERVICES[] = { KAA_SERVICE_PROFILE , KAA_SERVICE_LOGGING}; static const int OPERATIONS_SERVICES_COUNT = sizeof(OPERATIONS_SERVICES) / sizeof(kaa_service_t); +/* Logging constraints */ +#define MAX_LOG_COUNT SIZE_MAX +#define MAX_LOG_BUCKET_SIZE (KAA_TCP_CHANNEL_OUT_BUFFER_SIZE >> 3) +_Static_assert(MAX_LOG_BUCKET_SIZE, "Maximum bucket size cannot be 0!"); typedef enum { KAA_CLIENT_ESP8266_STATE_UNINITED = 0, @@ -681,9 +685,15 @@ kaa_error_t kaa_log_collector_init(kaa_client_t *kaa_client) return error_code; } + kaa_log_bucket_constraints_t bucket_sizes = { + .max_bucket_size = MAX_LOG_BUCKET_SIZE, + .max_bucket_log_count = MAX_LOG_COUNT, + }; + error_code = kaa_logging_init(kaa_client->kaa_context->log_collector , kaa_client->log_storage_context - , kaa_client->log_upload_strategy_context); + , kaa_client->log_upload_strategy_context + , &bucket_sizes); if (error_code) { KAA_LOG_ERROR(kaa_client->kaa_context->logger, error_code,"Failed to logging init"); return error_code; diff --git a/client/client-multi/client-c/src/kaa/platform/ext_log_delivery_listener.h b/client/client-multi/client-c/src/kaa/platform/ext_log_delivery_listener.h new file mode 100644 index 0000000000..2487aefe7a --- /dev/null +++ b/client/client-multi/client-c/src/kaa/platform/ext_log_delivery_listener.h @@ -0,0 +1,71 @@ +/* + * Copyright 2016 CyberVision, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * @brief External log delivery listener interfaces. + * + * Listener callbacks could be used to notify about log-releated events: + * success, fail or timeout. + * + */ + +#ifndef EXT_LOG_DELIVERY_LISTENER_ +#define EXT_LOG_DELIVERY_LISTENER_ + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Log bucket information structure. + * One or more log records are aggregated into the single bucket. + */ +typedef struct { + size_t log_count; /**< Logs left to upload across all buckets. */ + uint16_t bucket_id; /**< ID of bucket present in storage. */ +} kaa_log_bucket_info_t; + +/** + * @brief Event handler type. + * + * Bucket information can be used to retrieve a amount of logs that are + * pending to upload. + * + * @param[in,out] context User-definied context. @sa kaa_logging_add_record + * @param[in] bucket Log bucket for which event was triggered. + */ +typedef void (*kaa_log_event_fn)(void *context, const kaa_log_bucket_info_t *bucket); + +/** Listeners aggreate */ +typedef struct { + kaa_log_event_fn on_success; /**< Handler called upon successfull log delivery. */ + kaa_log_event_fn on_failed; /**< Handler called upon failed delivery. */ + kaa_log_event_fn on_timeout; /**< Handler called upon timeouted delivery. */ + void *ctx; /**< User-defined context. */ +} kaa_log_delivery_listener_t; + +/** Special macro that can be used to disable event handling. */ +#define KAA_LOG_EMPTY_LISTENERS ((kaa_log_delivery_listener_t){NULL, NULL, NULL, NULL}) + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + + +#endif // EXT_LOG_DELIVERY_LISTENER_ diff --git a/client/client-multi/client-c/src/kaa/platform/ext_log_upload_strategy.h b/client/client-multi/client-c/src/kaa/platform/ext_log_upload_strategy.h index 5679bd6ddf..39c98ff621 100644 --- a/client/client-multi/client-c/src/kaa/platform/ext_log_upload_strategy.h +++ b/client/client-multi/client-c/src/kaa/platform/ext_log_upload_strategy.h @@ -71,16 +71,6 @@ kaa_error_t ext_log_upload_strategy_create(struct kaa_context_s *context, void * */ ext_log_upload_decision_t ext_log_upload_strategy_decide(void *context, const void *log_storage_context); -/** - * @brief Retrieves the maximum size of a report pack that will be delivered in a single request to the Operations server. - * - * @param[in] context Log upload strategy context. - * @return The size of a batch in bytes. - */ -size_t ext_log_upload_strategy_get_bucket_size(void *context); - - - /** * @brief The maximum time to wait a log delivery response. * diff --git a/client/client-multi/client-c/test/kaa_test.h b/client/client-multi/client-c/test/kaa_test.h index 80fba57a50..e76be87742 100644 --- a/client/client-multi/client-c/test/kaa_test.h +++ b/client/client-multi/client-c/test/kaa_test.h @@ -43,6 +43,14 @@ #define KAA_RUN_TESTS \ CU_automated_run_tests(); \ +/* Helper macro to control setup and teardown process per each test in group. + * Must be placed in the exact suite. + */ +#define KAA_RUN_TEST(GROUP, NAME) \ + KAA_TEST_CASE(GROUP##_##NAME##_setup, GROUP##_group_setup); \ + KAA_TEST_CASE(GROUP##_##NAME##_test, GROUP##_##NAME##_test) \ + KAA_TEST_CASE(GROUP##_##NAME##_teardown, GROUP##_group_teardown) + #define KAA_END_TEST_SUITE \ unsigned int failed_tests = CU_get_number_of_failure_records(); \ CU_cleanup_registry(); \ @@ -85,6 +93,18 @@ typedef int (*cleanup_fn)(void); if (!init_ret_code) \ TEST_FN(); +/* Helper macro to control setup and teardown process per each test in group. + * Must be placed in the exact suite. + */ +#define KAA_RUN_TEST(GROUP, NAME) \ + do { \ + if (!init_ret_code) { \ + GROUP##_group_setup(); \ + GROUP##_##NAME##_test(); \ + GROUP##_group_teardown(); \ + } \ + } while (0) + #define KAA_RUN_TESTS #define KAA_END_TEST_SUITE \ @@ -93,15 +113,42 @@ typedef int (*cleanup_fn)(void); } \ return (init_ret_code || cleanup_ret_code) ? -1 : 0; \ } - #endif +/* Bunch of macroses that required execute setup() (initialization) + * and teardown() (cleanup) procedures per each test in so called "group". + * + * Group is a set of tests with common setup() and teardown() routines. + * You may have as many groups as you want inside test application. + * This contrasts with suite, which can be only one per each executable. + * + * NOTE: THIS IS INTERMIDIATE SOLUTION THAT WILL BE USED PRIOR TO INTEGRATION + * OF APPROPRIATE TEST FRAMEWORK WHICH SUPPORTS SUCH FEATURES. + */ + +/* Defines test case in the given group */ +#define KAA_TEST_CASE_EX(GROUP, NAME) \ + void GROUP##_##NAME##_test(void) + +/* Defines a setup process for given group. + * It runs before each test to make sure sytem is in predictable state + */ +#define KAA_GROUP_SETUP(GROUP) \ + void GROUP##_group_setup() + +/* Defines a teardown process for given group + * Reverts any changes made by setup routine and makes sure no side effects + * will stay after test + */ +#define KAA_GROUP_TEARDOWN(GROUP) \ + void GROUP##_group_teardown() + + #define KAA_SUITE_MAIN(SUITE_NAME, INIT_FN, CLEANUP_FN, ...) \ KAA_BEGIN_TEST_SUITE(SUITE_NAME, INIT_FN, CLEANUP_FN) \ __VA_ARGS__ \ KAA_RUN_TESTS \ KAA_END_TEST_SUITE \ - #endif /* KAA_TEST_H_ */ diff --git a/client/client-multi/client-c/test/platform-impl/test_ext_log_storage_memory.c b/client/client-multi/client-c/test/platform-impl/test_ext_log_storage_memory.c index c8095377ea..10bb5d1f49 100644 --- a/client/client-multi/client-c/test/platform-impl/test_ext_log_storage_memory.c +++ b/client/client-multi/client-c/test/platform-impl/test_ext_log_storage_memory.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "../kaa_test.h" diff --git a/client/client-multi/client-c/test/platform-impl/test_ext_log_upload_strategies.c b/client/client-multi/client-c/test/platform-impl/test_ext_log_upload_strategies.c index 1bd81114f6..0c9a8e76c1 100644 --- a/client/client-multi/client-c/test/platform-impl/test_ext_log_upload_strategies.c +++ b/client/client-multi/client-c/test/platform-impl/test_ext_log_upload_strategies.c @@ -120,25 +120,6 @@ void test_set_upload_timeout(void) KAA_TRACE_OUT(logger); } -void test_set_batch_size(void) -{ - KAA_TRACE_IN(logger); - - kaa_error_t error_code = KAA_ERR_NONE; - - size_t DEFAULT_BATCH_SIZE = 8 * 1024; - - error_code = ext_log_upload_strategy_change_strategy(strategy, KAA_LOG_UPLOAD_VOLUME_STRATEGY); - ASSERT_EQUAL(error_code, KAA_ERR_NONE); - - error_code = ext_log_upload_strategy_set_batch_size(strategy, DEFAULT_BATCH_SIZE); - ASSERT_EQUAL(error_code, KAA_ERR_NONE); - - ASSERT_EQUAL(ext_log_upload_strategy_get_bucket_size(strategy), DEFAULT_BATCH_SIZE); - - KAA_TRACE_OUT(logger); -} - void test_upload_decision_by_volume(void) { KAA_TRACE_IN(logger); @@ -360,7 +341,6 @@ int test_deinit(void) KAA_SUITE_MAIN(MetaExtension, test_init, test_deinit, KAA_TEST_CASE(create_strategy, test_create_strategy) KAA_TEST_CASE(set_upload_timeout, test_set_upload_timeout) - KAA_TEST_CASE(set_batch_size, test_set_batch_size) KAA_TEST_CASE(upload_decision_by_volume, test_upload_decision_by_volume) KAA_TEST_CASE(upload_decision_by_count, test_upload_decision_by_count) KAA_TEST_CASE(upload_decision_by_timeout, test_upload_decision_by_timeout) diff --git a/client/client-multi/client-c/test/test_kaa_common_schema.c b/client/client-multi/client-c/test/test_kaa_common_schema.c index 7bc2f45c07..faf29c98bc 100644 --- a/client/client-multi/client-c/test/test_kaa_common_schema.c +++ b/client/client-multi/client-c/test/test_kaa_common_schema.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "kaa_test.h" diff --git a/client/client-multi/client-c/test/test_kaa_event.c b/client/client-multi/client-c/test/test_kaa_event.c index 25d0555e06..cb0394f848 100644 --- a/client/client-multi/client-c/test/test_kaa_event.c +++ b/client/client-multi/client-c/test/test_kaa_event.c @@ -521,7 +521,7 @@ void test_event_blocks(void) kaa_event_block_id trx_id = 0; error_code = kaa_event_create_transaction(event_manager, &trx_id); ASSERT_EQUAL(error_code, KAA_ERR_NONE); - ASSERT_NOT_NULL(trx_id); + ASSERT_TRUE(trx_id); const size_t event1_size = 6; char *event1 = (char *) KAA_MALLOC(event1_size + 1); diff --git a/client/client-multi/client-c/test/test_kaa_log.c b/client/client-multi/client-c/test/test_kaa_log.c index 84d1e5f827..39c779109a 100644 --- a/client/client-multi/client-c/test/test_kaa_log.c +++ b/client/client-multi/client-c/test/test_kaa_log.c @@ -82,7 +82,6 @@ static const int OPERATIONS_SERVICES_COUNT = sizeof(OPERATIONS_SERVICES) / sizeo typedef struct { size_t timeout; - size_t batch_size; size_t max_parallel_uploads; bool on_timeout_count; bool on_failure_count; @@ -171,11 +170,6 @@ ext_log_upload_decision_t ext_log_upload_strategy_decide(void *context, const vo return ((mock_strategy_context_t *)context)->decision; } -size_t ext_log_upload_strategy_get_bucket_size(void *context) -{ - return ((mock_strategy_context_t *)context)->batch_size; -} - size_t ext_log_upload_strategy_get_timeout(void *context) { return ((mock_strategy_context_t *)context)->timeout; @@ -328,13 +322,17 @@ void test_create_request(void) mock_strategy_context_t strategy; memset(&strategy, 0, sizeof(mock_strategy_context_t)); strategy.decision = NOOP; - strategy.batch_size = 2 * test_log_record_size; strategy.max_parallel_uploads = UINT32_MAX; - error_code = kaa_logging_init(log_collector, create_mock_storage(), &strategy); + kaa_log_bucket_constraints_t constraints = { + .max_bucket_size = 2 * test_log_record_size, + .max_bucket_log_count = UINT32_MAX, + }; + + error_code = kaa_logging_init(log_collector, create_mock_storage(), &strategy, &constraints); ASSERT_EQUAL(error_code, KAA_ERR_NONE); - error_code = kaa_logging_add_record(log_collector, test_log_record); + error_code = kaa_logging_add_record(log_collector, test_log_record, NULL); ASSERT_EQUAL(error_code, KAA_ERR_NONE); size_t expected_size = 0; @@ -400,7 +398,13 @@ void test_response(void) memset(&strategy, 0, sizeof(mock_strategy_context_t)); mock_storage_context_t *storage = create_mock_storage(); - error_code = kaa_logging_init(log_collector, storage, &strategy); + + kaa_log_bucket_constraints_t constraints = { + .max_bucket_size = 1024, + .max_bucket_log_count = UINT32_MAX, + }; + + error_code = kaa_logging_init(log_collector, storage, &strategy, &constraints); ASSERT_EQUAL(error_code, KAA_ERR_NONE); uint32_t response_count = 2; @@ -435,9 +439,9 @@ void test_response(void) error_code = kaa_logging_handle_server_sync(log_collector, reader, 0, response_buffer_size); ASSERT_EQUAL(error_code, KAA_ERR_NONE); - ASSERT_NOT_NULL(strategy.on_failure_count); - ASSERT_NOT_NULL(storage->on_remove_by_id_count); - ASSERT_NOT_NULL(storage->on_unmark_by_id_count); + ASSERT_TRUE(strategy.on_failure_count); + ASSERT_TRUE(storage->on_remove_by_id_count); + ASSERT_TRUE(storage->on_unmark_by_id_count); kaa_platform_message_reader_destroy(reader); kaa_log_collector_destroy(log_collector); @@ -467,13 +471,17 @@ void test_timeout(void) memset(&strategy, 0, sizeof(mock_strategy_context_t)); strategy.timeout = TEST_TIMEOUT; strategy.decision = NOOP; - strategy.batch_size = 2 * test_log_record_size; strategy.max_parallel_uploads = UINT32_MAX; - error_code = kaa_logging_init(log_collector, create_mock_storage(), &strategy); + kaa_log_bucket_constraints_t constraints = { + .max_bucket_size = 2 * test_log_record_size, + .max_bucket_log_count = UINT32_MAX, + }; + + error_code = kaa_logging_init(log_collector, create_mock_storage(), &strategy, &constraints); ASSERT_EQUAL(error_code, KAA_ERR_NONE); - error_code = kaa_logging_add_record(log_collector, test_log_record); + error_code = kaa_logging_add_record(log_collector, test_log_record, NULL); ASSERT_EQUAL(error_code, KAA_ERR_NONE); size_t request_buffer_size = 256; @@ -487,10 +495,10 @@ void test_timeout(void) sleep(TEST_TIMEOUT + 1); - error_code = kaa_logging_add_record(log_collector, test_log_record); + error_code = kaa_logging_add_record(log_collector, test_log_record, NULL); ASSERT_EQUAL(error_code, KAA_ERR_NONE); - ASSERT_NOT_NULL(strategy.on_timeout_count); + ASSERT_TRUE(strategy.on_timeout_count); test_log_record->destroy(test_log_record); kaa_platform_message_writer_destroy(writer); @@ -519,16 +527,20 @@ void test_decline_timeout(void) memset(&strategy, 0, sizeof(mock_strategy_context_t)); strategy.timeout = TEST_TIMEOUT; strategy.decision = NOOP; - strategy.batch_size = 2 * test_log_record_size; strategy.max_parallel_uploads = UINT32_MAX; mock_storage_context_t *storage = create_mock_storage(); ASSERT_NOT_NULL(storage); - error_code = kaa_logging_init(log_collector, storage, &strategy); + kaa_log_bucket_constraints_t constraints = { + .max_bucket_size = 2 * test_log_record_size, + .max_bucket_log_count = UINT32_MAX, + }; + + error_code = kaa_logging_init(log_collector, storage, &strategy, &constraints); ASSERT_EQUAL(error_code, KAA_ERR_NONE); - error_code = kaa_logging_add_record(log_collector, test_log_record); + error_code = kaa_logging_add_record(log_collector, test_log_record, NULL); ASSERT_EQUAL(error_code, KAA_ERR_NONE); size_t request_buffer_size = 256; @@ -568,12 +580,12 @@ void test_decline_timeout(void) error_code = kaa_logging_handle_server_sync(log_collector, reader, 0, response_buffer_size); ASSERT_EQUAL(error_code, KAA_ERR_NONE); - ASSERT_NOT_NULL(storage->on_remove_by_id_count); + ASSERT_TRUE(storage->on_remove_by_id_count); - error_code = kaa_logging_add_record(log_collector, test_log_record); + error_code = kaa_logging_add_record(log_collector, test_log_record, NULL); ASSERT_EQUAL(error_code, KAA_ERR_NONE); - ASSERT_NULL(strategy.on_timeout_count); + ASSERT_FALSE(strategy.on_timeout_count); test_log_record->destroy(test_log_record); kaa_platform_message_writer_destroy(writer); @@ -606,21 +618,24 @@ void test_max_parallel_uploads_with_log_sync(void) mock_strategy_context_t strategy; memset(&strategy, 0, sizeof(mock_strategy_context_t)); strategy.timeout = UINT32_MAX; - strategy.batch_size = 2 * test_log_size; strategy.decision = UPLOAD; - mock_storage_context_t *storage = create_mock_storage(); ASSERT_NOT_NULL(storage); - error_code = kaa_logging_init(log_collector, storage, &strategy); + kaa_log_bucket_constraints_t constraints = { + .max_bucket_size = 2 * test_log_size, + .max_bucket_log_count = UINT32_MAX, + }; + + error_code = kaa_logging_init(log_collector, storage, &strategy, &constraints); ASSERT_EQUAL(error_code, KAA_ERR_NONE); /* * Ensure the log delivery is forbidden at all. */ strategy.max_parallel_uploads = 0; - error_code = kaa_logging_add_record(log_collector, test_log_record); + error_code = kaa_logging_add_record(log_collector, test_log_record, NULL); ASSERT_EQUAL(error_code, KAA_ERR_NONE); ASSERT_EQUAL(((mock_transport_channel_context_t *)transport_context.context)->on_sync_count, 0); @@ -629,7 +644,7 @@ void test_max_parallel_uploads_with_log_sync(void) * Ensure the first request is allowed. */ strategy.max_parallel_uploads = 1; - error_code = kaa_logging_add_record(log_collector, test_log_record); + error_code = kaa_logging_add_record(log_collector, test_log_record, NULL); ASSERT_EQUAL(error_code, KAA_ERR_NONE); ASSERT_EQUAL(((mock_transport_channel_context_t *)transport_context.context)->on_sync_count, 1); @@ -645,7 +660,7 @@ void test_max_parallel_uploads_with_log_sync(void) error_code = kaa_logging_request_serialize(log_collector, writer); ASSERT_EQUAL(error_code, KAA_ERR_NONE); - error_code = kaa_logging_add_record(log_collector, test_log_record); + error_code = kaa_logging_add_record(log_collector, test_log_record, NULL); ASSERT_EQUAL(error_code, KAA_ERR_NONE); /* @@ -688,38 +703,42 @@ void test_max_parallel_uploads_with_sync_all(void) mock_strategy_context_t strategy; memset(&strategy, 0, sizeof(mock_strategy_context_t)); strategy.timeout = UINT32_MAX; - strategy.batch_size = 2 * test_log_size; strategy.decision = UPLOAD; mock_storage_context_t *storage = create_mock_storage(); ASSERT_NOT_NULL(storage); - error_code = kaa_logging_init(log_collector, storage, &strategy); + kaa_log_bucket_constraints_t constraints = { + .max_bucket_size = 2 * test_log_size, + .max_bucket_log_count = UINT32_MAX, + }; + + error_code = kaa_logging_init(log_collector, storage, &strategy, &constraints); ASSERT_EQUAL(error_code, KAA_ERR_NONE); /* * Ensure the log delivery is forbidden at all. */ strategy.max_parallel_uploads = 0; - error_code = kaa_logging_add_record(log_collector, test_log_record); + error_code = kaa_logging_add_record(log_collector, test_log_record, NULL); ASSERT_EQUAL(error_code, KAA_ERR_NONE); size_t expected_size = 0; error_code = kaa_logging_request_get_size(log_collector, &expected_size); - ASSERT_NULL(expected_size); + ASSERT_FALSE(expected_size); /* * Ensure the first request is allowed. */ strategy.max_parallel_uploads = 1; - error_code = kaa_logging_add_record(log_collector, test_log_record); + error_code = kaa_logging_add_record(log_collector, test_log_record, NULL); ASSERT_EQUAL(error_code, KAA_ERR_NONE); /* * Do the first request to remember the delivery timeout of the log batch. */ error_code = kaa_logging_request_get_size(log_collector, &expected_size); - ASSERT_NOT_NULL(expected_size); + ASSERT_TRUE(expected_size); size_t request_buffer_size = 256; char request_buffer[request_buffer_size]; kaa_platform_message_writer_t *writer = NULL; @@ -729,14 +748,14 @@ void test_max_parallel_uploads_with_sync_all(void) error_code = kaa_logging_request_serialize(log_collector, writer); ASSERT_EQUAL(error_code, KAA_ERR_NONE); - error_code = kaa_logging_add_record(log_collector, test_log_record); + error_code = kaa_logging_add_record(log_collector, test_log_record, NULL); ASSERT_EQUAL(error_code, KAA_ERR_NONE); /* * Ensure the second request is forbidden. */ error_code = kaa_logging_request_get_size(log_collector, &expected_size); - ASSERT_NULL(expected_size); + ASSERT_FALSE(expected_size); /* * Clean up. @@ -750,8 +769,720 @@ void test_max_parallel_uploads_with_sync_all(void) KAA_TRACE_OUT(logger); } -#endif +/* ---------------------------------------------------------------------------*/ +/* Log delivery tests */ +/* ---------------------------------------------------------------------------*/ + +/* Server chunk, managed by a corresponding reader object. + * Perfectly packed. Packed attribute is intentionally avoided. */ +struct response_chunk +{ + uint8_t bucket_id[2]; /* 16 bits for bucket ID */ + uint8_t resp_code; /* 8 bits for response code. 0 == SUCCESS, 1 == FAILURE */ + uint8_t reserved; /* Should be 0 */ +}; + +struct response_packet +{ + uint8_t resp_cnt[4]; /* 32 bits for amount of responces in buffer */ + struct response_chunk resps[]; /* Responses itself */ +}; + +#define RESP_PACKETS 2 /* Amount of response packets */ +#define RESP_SUCCESS_IDX 0 /* Index of successfull response */ +#define RESP_FAILURE_IDX 1 /* Index of failed response */ +#define TEST_BUFFER_SIZE 1024 +#define TEST_EXT_OP 0 /* Simple stub */ +#define TEST_TIMEOUT 2 + +static mock_strategy_context_t test_strategy1; +static mock_strategy_context_t test_strategy2; +static mock_storage_context_t *test_storage1; +static mock_storage_context_t *test_storage2; +static kaa_log_collector_t *log_collector; +static size_t test_log_record_size = TEST_BUFFER_SIZE; +/* Will contain response_packet. Thus required to be aligned. */ +_Alignas(4) static char test_reader_buffer[TEST_BUFFER_SIZE]; +_Alignas(4) static char test_writer_buffer[TEST_BUFFER_SIZE]; +/* Portion of the test buffer filled with valid data */ +static size_t test_filled_size; +static kaa_platform_message_reader_t *test_reader; +static kaa_platform_message_writer_t *test_writer; +static kaa_user_log_record_t *test_log_record; + +/* Values to be checked inside mock event function */ +static void *expected_ctx; +static int check_bucket; +static uint16_t expected_bucked_id; + +/* Required to trace generic mock function calls */ +static int call_is_expected; +static int call_completed; + +/* Required to trace on fail mock function calls */ +static int failed_call_is_expected; +static int failed_call_completed; + +/* Required to trace on success mock function calls */ +static int success_call_is_expected; +static int success_call_completed; + +/* Required to trace on timeout mock function calls */ +static int timeout_call_is_expected; +static int timeout_call_completed; + +/* Mock event functions */ + +static void mock_log_event_generic_fn(void *ctx, const kaa_log_bucket_info_t *bucket) +{ + ASSERT_TRUE(call_is_expected); + ASSERT_NOT_NULL(bucket); /* Shouldn't be NULL no matter what */ + + if (check_bucket) { + ASSERT_EQUAL(expected_bucked_id, bucket->bucket_id); + } + + ASSERT_EQUAL(expected_ctx, ctx); + + call_completed++; +} + +static void mock_log_event_failed_fn(void *ctx, const kaa_log_bucket_info_t *bucket) +{ + ASSERT_TRUE(failed_call_is_expected); + /* Make sure that generic function will not fail */ + call_is_expected = 1; + mock_log_event_generic_fn(ctx, bucket); + + failed_call_completed++; +} + +static void mock_log_event_success_fn(void *ctx, const kaa_log_bucket_info_t *bucket) +{ + ASSERT_TRUE(success_call_is_expected); + /* Make sure that generic function will not fail */ + call_is_expected = 1; + mock_log_event_generic_fn(ctx, bucket); + + success_call_completed++; +} + +static void mock_log_event_timeout_fn(void *ctx, const kaa_log_bucket_info_t *bucket) +{ + ASSERT_TRUE(timeout_call_is_expected); + /* Make sure that generic function will not fail */ + call_is_expected = 1; + mock_log_event_generic_fn(ctx, bucket); + + timeout_call_completed++; +} + +/* ---------------------------------------------------------------------------*/ +/* Log setters test group */ +/* ---------------------------------------------------------------------------*/ + +KAA_GROUP_SETUP(log_setters) +{ + kaa_error_t rc; + + KAA_TRACE_IN(logger); + rc = kaa_log_collector_create(&log_collector, + status, + channel_manager, + logger); + + ASSERT_EQUAL(KAA_ERR_NONE, rc); + + /* Test objects for strategy test */ + + memset(&test_strategy1, 0, sizeof(test_strategy1)); + memset(&test_strategy2, 0, sizeof(test_strategy2)); + + kaa_log_bucket_constraints_t constraints = { + .max_bucket_size = 2 * test_log_record_size, + .max_bucket_log_count = UINT32_MAX, + }; + + /* Test objects for storage tests */ + + test_storage1 = create_mock_storage(); + test_storage2 = create_mock_storage(); + + rc = kaa_logging_init(log_collector, test_storage1, + &test_strategy1, &constraints); + ASSERT_EQUAL(KAA_ERR_NONE, rc); + + expected_ctx = NULL; + expected_bucked_id = 0; + call_is_expected = 0; + + KAA_TRACE_OUT(logger); +} + +KAA_GROUP_TEARDOWN(log_setters) +{ + KAA_TRACE_IN(logger); + + /* If tests will pass, one of storages will be destroyed. + * Each test in this will decide which one should be deleted. */ + kaa_log_collector_destroy(log_collector); + log_collector = NULL; + + KAA_TRACE_OUT(logger); +} + + +KAA_TEST_CASE_EX(log_setters, set_strategy_invalid_parameters) +{ + kaa_error_t rc; + + KAA_TRACE_IN(logger); + + rc = kaa_logging_set_strategy(log_collector, NULL); + ASSERT_EQUAL(KAA_ERR_BADPARAM, rc); + + rc = kaa_logging_set_strategy(NULL, &test_strategy2); + ASSERT_EQUAL(KAA_ERR_BADPARAM, rc); + + ext_log_storage_destroy(test_storage2); + ext_log_upload_strategy_destroy(&test_strategy2); + + KAA_TRACE_OUT(logger); +} + + +KAA_TEST_CASE_EX(log_setters, set_storage_invalid_parameters) +{ + kaa_error_t rc; + KAA_TRACE_IN(logger); + + rc = kaa_logging_set_storage(log_collector, NULL); + ASSERT_EQUAL(KAA_ERR_BADPARAM, rc); + + rc = kaa_logging_set_storage(NULL, test_storage2); + ASSERT_EQUAL(KAA_ERR_BADPARAM, rc); + + ext_log_storage_destroy(test_storage2); + ext_log_upload_strategy_destroy(&test_strategy2); + + KAA_TRACE_OUT(logger); +} + +KAA_TEST_CASE_EX(log_setters, set_strategy_valid_parameters) +{ + kaa_error_t rc; + + KAA_TRACE_IN(logger); + + /* First strategy will be internally deleted */ + rc = kaa_logging_set_strategy(log_collector, &test_strategy2); + ASSERT_EQUAL(KAA_ERR_NONE, rc); + + ext_log_storage_destroy(test_storage2); + + /* Second strategy will be deleted on test teardown */ + + KAA_TRACE_OUT(logger); +} + + +KAA_TEST_CASE_EX(log_setters, set_storage_valid_parameters) +{ + kaa_error_t rc; + + KAA_TRACE_IN(logger); + + /* First storage will be internally deleted */ + rc = kaa_logging_set_storage(log_collector, test_storage2); + ASSERT_EQUAL(KAA_ERR_NONE, rc); + + ext_log_upload_strategy_destroy(&test_strategy2); + + /* Second storage will be deleted on test teardown */ + + KAA_TRACE_OUT(logger); +} + + +/* ---------------------------------------------------------------------------*/ +/* Log delivery callback basic test group */ +/* ---------------------------------------------------------------------------*/ + + +KAA_GROUP_SETUP(log_callback_basic) +{ + kaa_error_t error_code; + + KAA_TRACE_IN(logger); + error_code = kaa_log_collector_create(&log_collector, + status, + channel_manager, + logger); + + ASSERT_EQUAL(error_code, KAA_ERR_NONE); + + memset(&test_strategy1, 0, sizeof(test_strategy1)); + + kaa_log_bucket_constraints_t constraints = { + .max_bucket_size = 2 * test_log_record_size, + .max_bucket_log_count = UINT32_MAX, + }; + + error_code = kaa_logging_init(log_collector, create_mock_storage(), + &test_strategy1, &constraints); + ASSERT_EQUAL(error_code, KAA_ERR_NONE); + + expected_ctx = NULL; + expected_bucked_id = 0; + call_is_expected = 0; + + KAA_TRACE_OUT(logger); +} + +KAA_GROUP_TEARDOWN(log_callback_basic) +{ + KAA_TRACE_IN(logger); + kaa_log_collector_destroy(log_collector); + log_collector = NULL; + + KAA_TRACE_OUT(logger); +} + +KAA_TEST_CASE_EX(log_callback_basic, invalid_parameters) +{ + KAA_TRACE_IN(logger); + kaa_log_delivery_listener_t listeners; + + /* NULL parameters case */ + + kaa_error_t rc = kaa_logging_set_listeners(log_collector, NULL); + ASSERT_EQUAL(KAA_ERR_BADPARAM, rc); + rc = kaa_logging_set_listeners(NULL, &listeners); + ASSERT_EQUAL(KAA_ERR_BADPARAM, rc); + + KAA_TRACE_OUT(logger); + return; +} + +/* This test is also testing the case when listeners isn't called + * if no logs added */ +KAA_TEST_CASE_EX(log_callback_basic, valid_parameters) +{ + KAA_TRACE_IN(logger); + + kaa_error_t rc; + + kaa_log_delivery_listener_t listeners = { + mock_log_event_generic_fn, + mock_log_event_generic_fn, + mock_log_event_generic_fn, + NULL, + }; + + /* Any of listeners can be NULL */ + + rc = kaa_logging_set_listeners(log_collector, &listeners); + ASSERT_EQUAL(KAA_ERR_NONE, rc); + + listeners.on_failed = NULL; + rc = kaa_logging_set_listeners(log_collector, &listeners); + ASSERT_EQUAL(KAA_ERR_NONE, rc); + + listeners.on_success = NULL; + rc = kaa_logging_set_listeners(log_collector, &listeners); + ASSERT_EQUAL(KAA_ERR_NONE, rc); + + listeners.on_timeout = NULL; + rc = kaa_logging_set_listeners(log_collector, &listeners); + ASSERT_EQUAL(KAA_ERR_NONE, rc); + + /* Special macro should work too */ + rc = kaa_logging_set_listeners(log_collector, &KAA_LOG_EMPTY_LISTENERS); + ASSERT_EQUAL(KAA_ERR_NONE, rc); + + /* Post conditions check */ + + /* No callbacks should be called */ + ASSERT_FALSE(call_completed); + KAA_TRACE_OUT(logger); +} + +/* ---------------------------------------------------------------------------*/ +/* Log delivery callback extended test group */ +/* ---------------------------------------------------------------------------*/ + +KAA_GROUP_SETUP(log_callback_with_storage) +{ + kaa_error_t error_code; + + KAA_TRACE_IN(logger); + error_code = kaa_log_collector_create(&log_collector, + status, + channel_manager, + logger); + + ASSERT_EQUAL(error_code, KAA_ERR_NONE); + + memset(&test_strategy1, 0, sizeof(mock_strategy_context_t)); + memset(test_reader_buffer, 0, sizeof(test_reader_buffer)); + memset(test_writer_buffer, 0, sizeof(test_writer_buffer)); + + expected_ctx = NULL; + expected_bucked_id = 0; + call_is_expected = 0; + call_completed = 0; + failed_call_completed = 0; + failed_call_is_expected = 0; + success_call_completed = 0; + success_call_is_expected = 0; + check_bucket = 0; + + test_storage1 = create_mock_storage(); + kaa_log_bucket_constraints_t constraints = { + .max_bucket_size = 2 * test_log_record_size, + .max_bucket_log_count = UINT32_MAX, + }; + + error_code = kaa_logging_init(log_collector, test_storage1, + &test_strategy1, &constraints); + ASSERT_EQUAL(error_code, KAA_ERR_NONE); + + + uint32_t response_count = 2; + struct response_packet *response = (struct response_packet *) test_reader_buffer; + *(uint32_t *) response->resp_cnt = KAA_HTONL(response_count); + + /* First response */ + + /* Later on we'll override that */ + *(uint16_t *) response->resps[RESP_SUCCESS_IDX].bucket_id = 0; + response->resps[RESP_SUCCESS_IDX].resp_code = 0; // SUCCESS + + /* Second response */ + + /* Later on we'll override that */ + *(uint16_t *) response->resps[RESP_FAILURE_IDX].bucket_id = 0; + response->resps[RESP_FAILURE_IDX].resp_code = 1; // FAILURE + + test_filled_size = sizeof(struct response_packet) + + sizeof(struct response_chunk) * 2; + + error_code = kaa_platform_message_reader_create(&test_reader, + test_reader_buffer, + test_filled_size); + + ASSERT_EQUAL(error_code, KAA_ERR_NONE); + ASSERT_NOT_NULL(test_reader); + + KAA_TRACE_OUT(logger); +} + +KAA_GROUP_TEARDOWN(log_callback_with_storage) +{ + KAA_TRACE_IN(logger); + + kaa_platform_message_reader_destroy(test_reader); + test_reader = NULL; + /* Destroys mock storage as well */ + kaa_log_collector_destroy(log_collector); + log_collector = NULL; + + KAA_TRACE_OUT(logger); +} + +KAA_TEST_CASE_EX(log_callback_with_storage, on_fail_called) +{ + KAA_TRACE_IN(logger); + + kaa_error_t rc; + int dummy_ctx; + + kaa_log_delivery_listener_t listeners = { + NULL, + mock_log_event_failed_fn, + NULL, + &dummy_ctx, + }; + + /* Notify mocks about test intentions */ + failed_call_is_expected = 1; + expected_ctx = &dummy_ctx; + check_bucket = 1; + expected_bucked_id = 42; + + rc = kaa_logging_set_listeners(log_collector, &listeners); + ASSERT_EQUAL(KAA_ERR_NONE, rc); + + /* Response packet is passed internally via test reader */ + struct response_packet *response = (struct response_packet *) test_reader_buffer; + *(uint16_t *) response->resps[RESP_FAILURE_IDX].bucket_id + = KAA_HTONS(expected_bucked_id); + + /* Test itself */ + rc = kaa_logging_handle_server_sync(log_collector, + test_reader, + TEST_EXT_OP, + test_filled_size + ); + + ASSERT_EQUAL(rc, KAA_ERR_NONE); + + /* Post-conditions check */ + + ASSERT_FALSE(success_call_completed); + ASSERT_TRUE(failed_call_completed); + ASSERT_FALSE(timeout_call_completed); + + KAA_TRACE_OUT(logger); +} + +KAA_TEST_CASE_EX(log_callback_with_storage, on_success_called) +{ + KAA_TRACE_IN(logger); + + kaa_error_t rc; + int dummy_ctx; + + kaa_log_delivery_listener_t listeners = { + mock_log_event_success_fn, + NULL, + NULL, + &dummy_ctx, + }; + + /* Notify mocks about test intentions */ + check_bucket = 1; + expected_bucked_id = 42; + success_call_is_expected = 1; + expected_ctx = &dummy_ctx; + + rc = kaa_logging_set_listeners(log_collector, &listeners); + ASSERT_EQUAL(KAA_ERR_NONE, rc); + + /* Response packet is passed internally via test reader */ + struct response_packet *response = (struct response_packet *) test_reader_buffer; + *(uint16_t *) response->resps[RESP_SUCCESS_IDX].bucket_id + = KAA_HTONS(expected_bucked_id); + + /* Test itself */ + rc = kaa_logging_handle_server_sync(log_collector, + test_reader, + TEST_EXT_OP, + test_filled_size + ); + + ASSERT_EQUAL(rc, KAA_ERR_NONE); + + /* Post-conditions check */ + + ASSERT_TRUE(success_call_completed); + ASSERT_FALSE(failed_call_completed); + ASSERT_FALSE(timeout_call_completed); + + KAA_TRACE_OUT(logger); +} + +KAA_TEST_CASE_EX(log_callback_with_storage, on_fail_and_success_called) +{ + KAA_TRACE_IN(logger); + + kaa_error_t rc; + int dummy_ctx; + + kaa_log_delivery_listener_t listeners = { + mock_log_event_success_fn, + mock_log_event_failed_fn, + NULL, + &dummy_ctx, + }; + + /* Notify mocks about test intentions */ + check_bucket = 1; + expected_bucked_id = 42; + failed_call_is_expected = 1; + success_call_is_expected = 1; + expected_ctx = &dummy_ctx; + + rc = kaa_logging_set_listeners(log_collector, &listeners); + ASSERT_EQUAL(KAA_ERR_NONE, rc); + + /* Response packet is passed internally via test reader */ + struct response_packet *response = (struct response_packet *) test_reader_buffer; + *(uint16_t *) response->resps[RESP_SUCCESS_IDX].bucket_id + = KAA_HTONS(expected_bucked_id); + *(uint16_t *) response->resps[RESP_FAILURE_IDX].bucket_id + = KAA_HTONS(expected_bucked_id); + + /* Test itself */ + rc = kaa_logging_handle_server_sync(log_collector, + test_reader, + TEST_EXT_OP, + test_filled_size + ); + + ASSERT_EQUAL(rc, KAA_ERR_NONE); + + /* Post-conditions check */ + + ASSERT_TRUE(success_call_completed); + ASSERT_TRUE(failed_call_completed); + ASSERT_FALSE(timeout_call_completed); + + KAA_TRACE_OUT(logger); +} + +/* ---------------------------------------------------------------------------*/ +/* Log delivery callback group with valid mock strategy. */ +/* The initialized mock strategy is essential for timeouts */ +/* ---------------------------------------------------------------------------*/ + +KAA_GROUP_SETUP(log_callback_with_storage_and_strategy) +{ + kaa_error_t error_code; + size_t test_log_record_size; + + KAA_TRACE_IN(logger); + error_code = kaa_log_collector_create(&log_collector, + status, + channel_manager, + logger); + + ASSERT_EQUAL(error_code, KAA_ERR_NONE); + + memset(&test_strategy1, 0, sizeof(mock_strategy_context_t)); + test_strategy1.timeout = TEST_TIMEOUT; + test_strategy1.decision = NOOP; + test_strategy1.max_parallel_uploads = UINT32_MAX; + + kaa_log_bucket_constraints_t constraints = { + .max_bucket_size = TEST_BUFFER_SIZE, + .max_bucket_log_count = UINT32_MAX, + }; + + expected_ctx = NULL; + expected_bucked_id = 0; + call_is_expected = 0; + call_completed = 0; + failed_call_completed = 0; + failed_call_is_expected = 0; + success_call_completed = 0; + success_call_is_expected = 0; + check_bucket = 0; + + error_code = kaa_logging_init(log_collector, create_mock_storage(), + &test_strategy1, &constraints); + + ASSERT_EQUAL(error_code, KAA_ERR_NONE); + + uint32_t response_count = 2; + + struct response_packet *response = (struct response_packet *) test_reader_buffer; + *(uint32_t *) response->resp_cnt = KAA_HTONL(response_count); + + /* First response */ + + /* Later on we'll override that */ + *(uint16_t *) response->resps[RESP_SUCCESS_IDX].bucket_id = 0; + response->resps[RESP_SUCCESS_IDX].resp_code = 0; // SUCCESS + + /* Second response */ + + /* Later on we'll override that */ + *(uint16_t *) response->resps[RESP_FAILURE_IDX].bucket_id = 0; + response->resps[RESP_FAILURE_IDX].resp_code = 1; // FAILURE + + test_filled_size = sizeof(struct response_packet) + + sizeof(struct response_chunk) * 2; + + test_log_record = kaa_test_log_record_create(); + test_log_record->data = kaa_string_copy_create(TEST_LOG_BUFFER); + test_log_record_size = test_log_record->get_size(test_log_record); + + error_code = kaa_platform_message_reader_create(&test_reader, + test_reader_buffer, + test_filled_size); + + ASSERT_EQUAL(error_code, KAA_ERR_NONE); + ASSERT_NOT_NULL(test_reader); + + error_code = kaa_platform_message_writer_create(&test_writer, + test_writer_buffer, + test_log_record_size); + ASSERT_EQUAL(error_code, KAA_ERR_NONE); + + KAA_TRACE_OUT(logger); +} + +KAA_GROUP_TEARDOWN(log_callback_with_storage_and_strategy) +{ + KAA_TRACE_IN(logger); + test_log_record->destroy(test_log_record); + + kaa_platform_message_writer_destroy(test_writer); + test_writer = NULL; + kaa_platform_message_reader_destroy(test_reader); + test_reader = NULL; + + /* Destroys mock storage as well */ + kaa_log_collector_destroy(log_collector); + log_collector = NULL; + + KAA_TRACE_OUT(logger); +} + +KAA_TEST_CASE_EX(log_callback_with_storage_and_strategy, on_timeout_called) +{ + KAA_TRACE_IN(logger); + + kaa_error_t rc; + int dummy_ctx; + + kaa_log_delivery_listener_t listeners = { + NULL, + NULL, + mock_log_event_timeout_fn, + &dummy_ctx, + }; + + kaa_log_record_info_t bucket; + + timeout_call_is_expected = 1; + expected_ctx = &dummy_ctx; + + rc = kaa_logging_set_listeners(log_collector, &listeners); + ASSERT_EQUAL(KAA_ERR_NONE, rc); + + rc = kaa_logging_add_record(log_collector, test_log_record, &bucket); + ASSERT_EQUAL(KAA_ERR_NONE, rc); + + /* Notify mocks about bucket */ + check_bucket = 1; + expected_bucked_id = bucket.bucket_id; + + /* Test itself */ + + rc = kaa_logging_request_serialize(log_collector, test_writer); + ASSERT_EQUAL(KAA_ERR_NONE, rc); + + sleep(TEST_TIMEOUT + 1); + + rc = kaa_logging_add_record(log_collector, test_log_record, NULL); + ASSERT_EQUAL(KAA_ERR_NONE, rc); + + /* Post-conditions check */ + + /* Timeout callback should be called once */ + ASSERT_EQUAL(1, timeout_call_completed); + + KAA_TRACE_OUT(logger); +} + +/* ---------------------------------------------------------------------------*/ +/* End of log delivery test groups */ +/* ---------------------------------------------------------------------------*/ + +#endif int test_init(void) { @@ -759,7 +1490,6 @@ int test_init(void) if (error || !logger) return error; - kaa_context.logger = logger; #ifndef KAA_DISABLE_FEATURE_LOGGING @@ -788,15 +1518,25 @@ int test_deinit(void) } - KAA_SUITE_MAIN(Log, test_init, test_deinit #ifndef KAA_DISABLE_FEATURE_LOGGING - , - KAA_TEST_CASE(create_request, test_create_request) - KAA_TEST_CASE(process_response, test_response) - KAA_TEST_CASE(process_timeout, test_timeout) - KAA_TEST_CASE(decline_timeout, test_decline_timeout) - KAA_TEST_CASE(max_parallel_uploads_with_log_sync, test_max_parallel_uploads_with_log_sync) - KAA_TEST_CASE(max_parallel_uploads_with_sync_all, test_max_parallel_uploads_with_sync_all) + , + KAA_TEST_CASE(create_request, test_create_request) + KAA_TEST_CASE(process_response, test_response) + KAA_TEST_CASE(process_timeout, test_timeout) + KAA_TEST_CASE(decline_timeout, test_decline_timeout) + KAA_TEST_CASE(max_parallel_uploads_with_log_sync, test_max_parallel_uploads_with_log_sync) + KAA_TEST_CASE(max_parallel_uploads_with_sync_all, test_max_parallel_uploads_with_sync_all) + KAA_RUN_TEST(log_setters, set_strategy_invalid_parameters); + KAA_RUN_TEST(log_setters, set_strategy_valid_parameters); + KAA_RUN_TEST(log_setters, set_storage_invalid_parameters); + KAA_RUN_TEST(log_setters, set_storage_valid_parameters); + KAA_RUN_TEST(log_callback_basic, valid_parameters); + KAA_RUN_TEST(log_callback_basic, invalid_parameters); + KAA_RUN_TEST(log_callback_basic, valid_parameters); + KAA_RUN_TEST(log_callback_with_storage, on_success_called); + KAA_RUN_TEST(log_callback_with_storage, on_fail_called); + KAA_RUN_TEST(log_callback_with_storage, on_fail_and_success_called); + KAA_RUN_TEST(log_callback_with_storage_and_strategy, on_timeout_called); #endif ) diff --git a/client/client-multi/client-c/test/test_platform_protocol.c b/client/client-multi/client-c/test/test_platform_protocol.c index e6f749df87..19326e11a9 100644 --- a/client/client-multi/client-c/test/test_platform_protocol.c +++ b/client/client-multi/client-c/test/test_platform_protocol.c @@ -73,7 +73,13 @@ void test_empty_log_collector_extension_count(void) , KAA_LOG_UPLOAD_VOLUME_STRATEGY); ASSERT_EQUAL(error_code, KAA_ERR_NONE); - error_code = kaa_logging_init(kaa_context->log_collector, log_storage_context, log_upload_strategy_context); + + kaa_log_bucket_constraints_t constraints = { + .max_bucket_size = 1024, + .max_bucket_log_count = UINT32_MAX, + }; + + error_code = kaa_logging_init(kaa_context->log_collector, log_storage_context, log_upload_strategy_context, &constraints); ASSERT_EQUAL(error_code, KAA_ERR_NONE); error_code = kaa_platform_protocol_serialize_client_sync(kaa_context->platform_protocol, info, &buffer, &buffer_size);