void test_empty_log_collector_extension_count(void)
{
    kaa_service_t service = KAA_SERVICE_LOGGING;
    info = (kaa_serialize_info_t *) KAA_MALLOC(sizeof(kaa_serialize_info_t));
    info->services = &service;
    info->services_count = 1;
    info->allocator = &allocator;
    info->allocator_context = mock;

    void *log_storage_context         = NULL;
    void *log_upload_strategy_context = NULL;

    kaa_error_t error_code = ext_unlimited_log_storage_create(&log_storage_context, kaa_context->logger);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    error_code = ext_log_upload_strategy_create(kaa_context
                                              , &log_upload_strategy_context
                                              , 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);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    error_code = kaa_platform_protocol_serialize_client_sync(kaa_context->platform_protocol, info, &buffer, &buffer_size);
    KAA_FREE(info);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    char count_of_extensions = *(buffer + 7);
    KAA_LOG_DEBUG(kaa_context->logger, KAA_ERR_NONE, "count of extensions is %d, expected 1", count_of_extensions);
    ASSERT_EQUAL(count_of_extensions, 1);
}
示例#2
0
/*
 * Initializes Kaa log collector.
 */
kaa_error_t kaa_log_collector_init()
{
    kaa_error_t error_code = ext_unlimited_log_storage_create(&log_storage_context, kaa_context_->logger);
    if (error_code) {
        KAA_LOG_ERROR(kaa_context_->logger, error_code, "Failed to create log storage");
        return error_code;
    }

    error_code = ext_log_upload_strategy_by_volume_create(&log_upload_strategy_context
                                                        , kaa_context_->channel_manager
                                                        , kaa_context_->bootstrap_manager);

    if (error_code) {
        KAA_LOG_ERROR(kaa_context_->logger, error_code, "Failed to create log upload strategy");
        return error_code;
    }

    error_code = ext_log_upload_strategy_by_volume_set_threshold_count(log_upload_strategy_context
                                                                     , KAA_DEMO_UPLOAD_COUNT_THRESHOLD);

    error_code = kaa_logging_init(kaa_context_->log_collector
                                , log_storage_context
                                , log_upload_strategy_context);

    return error_code;
}
示例#3
0
int main(/*int argc, char *argv[]*/)
{
    printf("Cassandra data analytics demo started\n");

    if (wiringPiSetup() == -1) {
        printf("Failed to initialize Pi wiring\n");
        exit(1);
    }

    kaa_client_t *kaa_client = NULL;

    void *log_storage_context         = NULL;
    void *log_upload_strategy_context = NULL;

    /**
     * Initialize Kaa client.
     */
    kaa_error_t error_code = kaa_client_create(&kaa_client, NULL);
    KAA_DEMO_RETURN_IF_ERROR(error_code, "Failed create Kaa client");

    /**
     * Configure Kaa data collection module.
     */
    error_code = ext_unlimited_log_storage_create(&log_storage_context, kaa_client_get_context(kaa_client)->logger);
    KAA_DEMO_RETURN_IF_ERROR(error_code, "Failed to create unlimited log storage");

    error_code = ext_log_upload_strategy_create(kaa_client_get_context(kaa_client), &log_upload_strategy_context, KAA_LOG_UPLOAD_VOLUME_STRATEGY);
    KAA_DEMO_RETURN_IF_ERROR(error_code, "Failed to create log upload strategy");

    error_code = ext_log_upload_strategy_set_threshold_count(log_upload_strategy_context, KAA_DEMO_UPLOAD_COUNT_THRESHOLD);
    KAA_DEMO_RETURN_IF_ERROR(error_code, "Failed to set threshold log record count");

    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_get_context(kaa_client)->log_collector
                                , log_storage_context
                                , log_upload_strategy_context
                                , &bucket_sizes);
    KAA_DEMO_RETURN_IF_ERROR(error_code, "Failed to init Kaa log collector");

    /**
     * Start Kaa client main loop.
     */
    error_code = kaa_client_start(kaa_client, &kaa_demo_add_log_record, (void *)kaa_client, KAA_DEMO_LOG_GENERATION_FREQUENCY);
    KAA_DEMO_RETURN_IF_ERROR(error_code, "Failed to start Kaa main loop");

    /**
     * Destroy Kaa client.
     */
    kaa_client_destroy(kaa_client);

    printf("Cassandra data analytics demo stopped\n");

    return error_code;
}
示例#4
0
/*
* Initializes Kaa log collector.
*/
kaa_error_t kaa_log_collector_init(kaa_client_t *kaa_client)
{
    KAA_RETURN_IF_NIL(kaa_client, KAA_ERR_BADPARAM)
    kaa_error_t error_code = ext_unlimited_log_storage_create(&kaa_client->log_storage_context
                                                            , kaa_client->kaa_context->logger);

    if (error_code) {
       KAA_LOG_ERROR(kaa_client->kaa_context->logger, error_code, "Failed to create log storage");
       return error_code;
    }

    error_code = ext_log_upload_strategy_create(kaa_client->kaa_context
                                              ,&kaa_client->log_upload_strategy_context
                                              , KAA_LOG_UPLOAD_VOLUME_STRATEGY);
    if (error_code) {
        KAA_LOG_ERROR(kaa_client->kaa_context->logger, error_code, "Failed to create log upload strategy");
        return error_code;
    }

    // Due to unknown problems with networking via ESP8266, some server responses are lost.
    // It leads to log delivery timeouts.
    error_code = ext_log_upload_strategy_set_upload_timeout(kaa_client->log_upload_strategy_context
                                                                    , KAA_DEMO_TWO_DAYS_UPLOAD_TIMEOUT);
    if (error_code) {
        KAA_LOG_ERROR(kaa_client->kaa_context->logger,
                                                error_code,
                                                "Failed to create log upload strategy by volume set upload timeout to %d",
                                                KAA_DEMO_TWO_DAYS_UPLOAD_TIMEOUT);
        return error_code;
    }

    error_code = ext_log_upload_strategy_et_threshold_count(kaa_client->log_upload_strategy_context
                                                , KAA_DEMO_UPLOAD_COUNT_THRESHOLD);
    if (error_code) {
        KAA_LOG_ERROR(kaa_client->kaa_context->logger,
                                                error_code,
                                                "Failed to create log upload strategy by volume set threshold count to %d",
                                                KAA_DEMO_UPLOAD_COUNT_THRESHOLD);
        return error_code;
    }

    error_code = kaa_logging_init(kaa_client->kaa_context->log_collector
                                                , kaa_client->log_storage_context
                                                , kaa_client->log_upload_strategy_context);
    if (error_code) {
        KAA_LOG_ERROR(kaa_client->kaa_context->logger, error_code,"Failed to logging init");
        return error_code;
    }

    KAA_LOG_INFO(kaa_client->kaa_context->logger, KAA_ERR_NONE, "Log collector init complete");
    return error_code;
}
示例#5
0
/*
 * Initializes Kaa log collector.
 */
kaa_error_t kaa_log_collector_init(kaa_client_t *kaa_client)
{
    KAA_RETURN_IF_NIL(kaa_client, KAA_ERR_BADPARAM);

        kaa_error_t error_code = ext_unlimited_log_storage_create(
                &kaa_client->log_storage_context,
                kaa_client->kaa_context->logger);
        if (error_code) {
            KAA_LOG_ERROR(kaa_client->kaa_context->logger,
                    error_code,
                    "Failed to create log storage");
            return error_code;
        }

        error_code = ext_log_upload_strategy_create(kaa_client->kaa_context
                                                  ,&kaa_client->log_upload_strategy_context
                                                  , KAA_LOG_UPLOAD_VOLUME_STRATEGY);

        if (error_code) {
            KAA_LOG_ERROR(kaa_client->kaa_context->logger,
                    error_code,
                    "Failed to create log upload strategy");
            return error_code;
        }

        error_code = ext_log_upload_strategy_set_threshold_count(kaa_client->log_upload_strategy_context
                                                                         , KAA_DEMO_UPLOAD_COUNT_THRESHOLD);
        if (error_code) {
            KAA_LOG_ERROR(kaa_client->kaa_context->logger,
                    error_code,
                    "Failed to create log upload strategy by volume set threshold count to %d",
                    KAA_DEMO_UPLOAD_COUNT_THRESHOLD);
            return error_code;
        }

        error_code = kaa_logging_init(kaa_client->kaa_context->log_collector
                                    , kaa_client->log_storage_context
                                    , kaa_client->log_upload_strategy_context);

        if (error_code) {
            KAA_LOG_ERROR(kaa_client->kaa_context->logger,
                    error_code,
                    "Failed to logging init");
            return error_code;
        }
        KAA_LOG_INFO(kaa_client->kaa_context->logger,
                KAA_ERR_NONE,
                "Log collector init complete");
        return error_code;

}
示例#6
0
int main(/*int argc, char *argv[]*/)
{
    printf("Data collection demo started\n");
    kaa_log_bucket_constraints_t bucket_sizes = {
        .max_bucket_size       = KAA_DEMO_BUCKET_SIZE,
        .max_bucket_log_count  = KAA_DEMO_LOGS_IN_BUCKET,
    };

    /**
     * Initialize Kaa client.
     */
    kaa_error_t error_code = kaa_client_create(&kaa_client, NULL);
    KAA_DEMO_RETURN_IF_ERROR(error_code, "Failed create Kaa client");

    error_code = ext_limited_log_storage_create(&log_storage_context, kaa_client_get_context(kaa_client)->logger, KAA_DEMO_LOG_STORAGE_SIZE, KAA_DEMO_LOGS_TO_KEEP);
    KAA_DEMO_RETURN_IF_ERROR(error_code, "Failed to create limited log storage");

    error_code = ext_log_upload_strategy_create(kaa_client_get_context(kaa_client), &log_upload_strategy_context, KAA_LOG_UPLOAD_VOLUME_STRATEGY);
    KAA_DEMO_RETURN_IF_ERROR(error_code, "Failed to create log upload strategy");

    error_code = ext_log_upload_strategy_set_threshold_count(log_upload_strategy_context, KAA_DEMO_UPLOAD_COUNT_THRESHOLD);
    KAA_DEMO_RETURN_IF_ERROR(error_code, "Failed to set threshold log record count");

    error_code = kaa_logging_init(kaa_client_get_context(kaa_client)->log_collector
                                , log_storage_context
                                , log_upload_strategy_context
                                , &bucket_sizes);

    KAA_DEMO_RETURN_IF_ERROR(error_code, "Failed to init Kaa log collector");

    error_code = kaa_logging_set_listeners(kaa_client_get_context(kaa_client)->log_collector,
                                           &log_listener);
    KAA_DEMO_RETURN_IF_ERROR(error_code, "Failed to add log listeners");

    /**
     * Start Kaa client main loop.
     */
    error_code = kaa_client_start(kaa_client, &kaa_demo_add_log_record, (void *)kaa_client, KAA_DEMO_LOG_GENERATION_FREQUENCY);
    KAA_DEMO_RETURN_IF_ERROR(error_code, "Failed to start Kaa main loop");

    /**
     * Destroy Kaa client.
     */
    kaa_client_destroy(kaa_client);

    printf("Data collection demo stopped\n");

    return error_code;
}
示例#7
0
文件: kaa_demo.c 项目: xwiz/kaa
int main(/*int argc, char *argv[]*/)
{
    printf("Data collection demo started\n");

    /**
     * Initialize Kaa client.
     */
    kaa_error_t error_code = kaa_client_create(&kaa_client, NULL);
    KAA_DEMO_RETURN_IF_ERROR(error_code, "Failed create Kaa client");

    error_code = ext_unlimited_log_storage_create(&log_storage_context, kaa_client_get_context(kaa_client)->logger);
    KAA_DEMO_RETURN_IF_ERROR(error_code, "Failed to create unlimited log storage");

    error_code = ext_log_upload_strategy_by_volume_create(&log_upload_strategy_context
                                                        , kaa_client_get_context(kaa_client)->channel_manager
                                                        , kaa_client_get_context(kaa_client)->bootstrap_manager);
    KAA_DEMO_RETURN_IF_ERROR(error_code, "Failed to create log upload strategy");

    error_code = ext_log_upload_strategy_by_volume_set_threshold_count(log_upload_strategy_context
                                                                     , KAA_DEMO_UPLOAD_COUNT_THRESHOLD);
    KAA_DEMO_RETURN_IF_ERROR(error_code, "Failed to set threshold log record count");

    error_code = kaa_logging_init(kaa_client_get_context(kaa_client)->log_collector
                                , log_storage_context
                                , log_upload_strategy_context);
    KAA_DEMO_RETURN_IF_ERROR(error_code, "Failed to init Kaa log collector");

    /**
     * Start Kaa client main loop.
     */
    error_code = kaa_client_start(kaa_client, &kaa_demo_add_log_record, (void *)kaa_client, KAA_DEMO_LOG_GENERATION_FREQUENCY);
    KAA_DEMO_RETURN_IF_ERROR(error_code, "Failed to start Kaa main loop");

    /**
     * Destroy Kaa client.
     */
    kaa_client_destroy(kaa_client);

    printf("Data collection demo stopped\n");

    return error_code;
}
示例#8
0
void test_create_request(void **state)
{
    (void)state;

    kaa_user_log_record_t *test_log_record = kaa_test_log_record_create();
    test_log_record->data = kaa_string_copy_create(TEST_LOG_BUFFER);
    size_t test_log_record_size = test_log_record->get_size(test_log_record);

    kaa_log_collector_t *log_collector = NULL;
    kaa_error_t error_code = kaa_log_collector_create(&log_collector, status,
            channel_manager, logger);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    mock_strategy_context_t strategy;
    memset(&strategy, 0, sizeof(mock_strategy_context_t));
    strategy.decision = NOOP;
    strategy.max_parallel_uploads = UINT32_MAX;

    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, 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_EQUAL(error_code, KAA_ERR_NONE);

    uint8_t buffer[expected_size];
    kaa_platform_message_writer_t *writer = NULL;
    error_code = kaa_platform_message_writer_create(&writer, buffer, expected_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);
    ASSERT_NOT_NULL(writer);

    error_code = kaa_logging_request_serialize(log_collector, writer);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);
    kaa_platform_message_writer_destroy(writer);

    uint8_t *buf_cursor = buffer;
    ASSERT_EQUAL(KAA_EXTENSION_LOGGING, KAA_HTONS(*(uint16_t *)buf_cursor));
    buf_cursor += sizeof(uint16_t);

    uint8_t options[] = { 0x00, 0x01 };
    ASSERT_EQUAL(memcmp(buf_cursor, options, 2), 0);
    buf_cursor += 2;

    ASSERT_EQUAL(*(uint32_t *) buf_cursor, KAA_HTONL(20));
    buf_cursor += sizeof(uint32_t);

    uint8_t request_id_records_count[]  = { 0x00, 0x01, 0x00, 0x01 };
    ASSERT_EQUAL(memcmp(buf_cursor, request_id_records_count, 4), 0);
    buf_cursor += 4;

    uint8_t record_buf[test_log_record_size];
    avro_writer_t avro_writer = avro_writer_memory((char *)record_buf, test_log_record_size);
    test_log_record->serialize(avro_writer, test_log_record);
    avro_writer_free(avro_writer);

    ASSERT_EQUAL(*(uint32_t *) buf_cursor, KAA_HTONL(test_log_record_size));
    buf_cursor += sizeof(uint32_t);

    ASSERT_EQUAL(memcmp(buf_cursor, record_buf, test_log_record_size), 0);

    kaa_log_collector_destroy(log_collector);
    test_log_record->destroy(test_log_record);
}



void test_response(void **state)
{
    (void)state;

    srand(time(NULL));

    kaa_log_collector_t *log_collector = NULL;
    kaa_error_t error_code = kaa_log_collector_create(&log_collector, status, channel_manager, logger);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    mock_strategy_context_t strategy;
    memset(&strategy, 0, sizeof(mock_strategy_context_t));

    mock_storage_context_t *storage = create_mock_storage();

    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;
    size_t response_buffer_size = sizeof(uint32_t) + sizeof(uint32_t) * response_count;
    uint8_t response_buffer[response_buffer_size];

    uint8_t *response = response_buffer;
    *((uint32_t *)response) = KAA_HTONL(response_count);
    response += sizeof(uint32_t);

    /* First response */
    *((uint16_t *)response) = KAA_HTONS(rand());
    response += sizeof(uint16_t);
    *((uint8_t *)response) = 0x0; // SUCCESS
    response += sizeof(uint8_t);
    *((uint8_t *)response) = 0;
    response += sizeof(uint8_t);

    /* Second response */
    *((uint16_t *)response) = KAA_HTONS(rand());
    response += sizeof(uint16_t);
    *((uint8_t *)response) = 0x1; // FAILURE
    response += sizeof(uint8_t);
    *((uint8_t *)response) = rand() % 4;
    response += sizeof(uint8_t);

    kaa_platform_message_reader_t *reader = NULL;
    error_code = kaa_platform_message_reader_create(&reader, response_buffer, response_buffer_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);
    ASSERT_NOT_NULL(reader);

    error_code = kaa_logging_handle_server_sync(log_collector, reader, 0, response_buffer_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    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);
}



void test_timeout(void **state)
{
    (void)state;

    kaa_log_collector_t *log_collector = NULL;
    kaa_error_t error_code = kaa_log_collector_create(&log_collector,
            status, channel_manager, logger);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    kaa_user_log_record_t *test_log_record = kaa_test_log_record_create();
    test_log_record->data = kaa_string_copy_create(TEST_LOG_BUFFER);
    size_t test_log_record_size = test_log_record->get_size(test_log_record);

    mock_strategy_context_t strategy;
    memset(&strategy, 0, sizeof(mock_strategy_context_t));
    strategy.timeout = TEST_TIMEOUT;
    strategy.decision = NOOP;
    strategy.max_parallel_uploads = UINT32_MAX;

    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, NULL);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    size_t request_buffer_size = 256;
    uint8_t request_buffer[request_buffer_size];
    kaa_platform_message_writer_t *writer = NULL;
    error_code = kaa_platform_message_writer_create(&writer, request_buffer, request_buffer_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    error_code = kaa_logging_request_serialize(log_collector, writer);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    sleep(TEST_TIMEOUT + 1);

    error_code = kaa_logging_add_record(log_collector, test_log_record, NULL);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    ASSERT_TRUE(strategy.on_timeout_count);

    test_log_record->destroy(test_log_record);
    kaa_platform_message_writer_destroy(writer);
    kaa_log_collector_destroy(log_collector);
}

void test_decline_timeout(void **state)
{
    (void)state;

    kaa_log_collector_t *log_collector = NULL;
    kaa_error_t error_code = kaa_log_collector_create(&log_collector, status, channel_manager, logger);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    kaa_user_log_record_t *test_log_record = kaa_test_log_record_create();
    test_log_record->data = kaa_string_copy_create(TEST_LOG_BUFFER);
    size_t test_log_record_size = test_log_record->get_size(test_log_record);

    mock_strategy_context_t strategy;
    memset(&strategy, 0, sizeof(mock_strategy_context_t));
    strategy.timeout = TEST_TIMEOUT;
    strategy.decision = NOOP;
    strategy.max_parallel_uploads = UINT32_MAX;

    mock_storage_context_t *storage = create_mock_storage();
    ASSERT_NOT_NULL(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, storage, &strategy, &constraints);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    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;
    uint8_t request_buffer[request_buffer_size];
    kaa_platform_message_writer_t *writer = NULL;
    error_code = kaa_platform_message_writer_create(&writer, request_buffer, request_buffer_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    error_code = kaa_logging_request_serialize(log_collector, writer);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    sleep(TEST_TIMEOUT + 1);

    uint16_t bucket_id = *((uint16_t *)(request_buffer + KAA_EXTENSION_HEADER_SIZE));
    bucket_id = KAA_NTOHS(bucket_id);

    uint32_t response_count = 1;
    size_t response_buffer_size = sizeof(uint32_t) + sizeof(uint32_t) * response_count;
    uint8_t response_buffer[response_buffer_size];

    uint8_t *response = response_buffer;
    *((uint32_t *)response) = KAA_HTONL(response_count);
    response += sizeof(uint32_t);

    /* First response */
    *((uint16_t *)response) = KAA_HTONS(bucket_id);
    response += sizeof(uint16_t);
    *((uint8_t *)response) = 0x0; // SUCCESS
    response += sizeof(uint8_t);
    *((uint8_t *)response) = 0;
    response += sizeof(uint8_t);

    kaa_platform_message_reader_t *reader = NULL;
    error_code = kaa_platform_message_reader_create(&reader, response_buffer, response_buffer_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);
    ASSERT_NOT_NULL(reader);

    error_code = kaa_logging_handle_server_sync(log_collector, reader, 0, response_buffer_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);
    ASSERT_TRUE(storage->on_remove_by_id_count);

    error_code = kaa_logging_add_record(log_collector, test_log_record, NULL);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    ASSERT_FALSE(strategy.on_timeout_count);

    test_log_record->destroy(test_log_record);
    kaa_platform_message_writer_destroy(writer);
    kaa_platform_message_reader_destroy(reader);
    kaa_log_collector_destroy(log_collector);
}

void test_max_parallel_uploads_with_log_sync(void **state)
{
    (void)state;

    uint32_t channel_id = 0;
    kaa_transport_channel_interface_t transport_context;
    test_kaa_channel_create(&transport_context);

    kaa_channel_manager_add_transport_channel(channel_manager, &transport_context, &channel_id);

    kaa_log_collector_t *log_collector = NULL;
    kaa_error_t error_code = kaa_log_collector_create(&log_collector, status, channel_manager, logger);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    kaa_user_log_record_t *test_log_record = kaa_test_log_record_create();
    test_log_record->data = kaa_string_copy_create(TEST_LOG_BUFFER);
    size_t test_log_size = test_log_record->get_size(test_log_record);

    mock_strategy_context_t strategy;
    memset(&strategy, 0, sizeof(mock_strategy_context_t));
    strategy.timeout = INT16_MAX;
    strategy.decision = UPLOAD;

    mock_storage_context_t *storage = create_mock_storage();
    ASSERT_NOT_NULL(storage);

    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, NULL);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    ASSERT_EQUAL(((mock_transport_channel_context_t *)transport_context.context)->on_sync_count, 0);

    /*
     * Ensure the first request is allowed.
     */
    strategy.max_parallel_uploads = 1;
    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);

    /*
     * Do the first request to remember the delivery timeout of the log batch.
     */
    size_t request_buffer_size = 256;
    uint8_t request_buffer[request_buffer_size];
    kaa_platform_message_writer_t *writer = NULL;
    error_code = kaa_platform_message_writer_create(&writer, request_buffer, request_buffer_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    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, NULL);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    /*
     * Ensure the second request is forbidden.
     */
    ASSERT_EQUAL(((mock_transport_channel_context_t *)transport_context.context)->on_sync_count, 1);

    /*
     * Clean up.
     */
    error_code = kaa_channel_manager_remove_transport_channel(channel_manager, channel_id);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    test_log_record->destroy(test_log_record);
    kaa_log_collector_destroy(log_collector);
}

void test_max_parallel_uploads_with_sync_all(void **state)
{
    (void)state;

    uint32_t channel_id = 0;
    kaa_transport_channel_interface_t transport_context;
    test_kaa_channel_create(&transport_context);

    kaa_channel_manager_add_transport_channel(channel_manager, &transport_context, &channel_id);

    kaa_log_collector_t *log_collector = NULL;
    kaa_error_t error_code = kaa_log_collector_create(&log_collector,
            status, channel_manager, logger);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    kaa_user_log_record_t *test_log_record = kaa_test_log_record_create();
    test_log_record->data = kaa_string_copy_create(TEST_LOG_BUFFER);
    size_t test_log_size = test_log_record->get_size(test_log_record);

    mock_strategy_context_t strategy;
    memset(&strategy, 0, sizeof(mock_strategy_context_t));
    strategy.timeout = INT16_MAX;
    strategy.decision = UPLOAD;

    mock_storage_context_t *storage = create_mock_storage();
    ASSERT_NOT_NULL(storage);

    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, 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_int_equal(KAA_ERR_NONE, error_code);
    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, 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_int_equal(KAA_ERR_NONE, error_code);
    ASSERT_TRUE(expected_size);
    size_t request_buffer_size = 256;
    uint8_t request_buffer[request_buffer_size];
    kaa_platform_message_writer_t *writer = NULL;
    error_code = kaa_platform_message_writer_create(&writer, request_buffer, request_buffer_size);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    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, 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_int_equal(KAA_ERR_NONE, error_code);
    ASSERT_FALSE(expected_size);

    /*
     * Clean up.
     */
    error_code = kaa_channel_manager_remove_transport_channel(channel_manager, channel_id);
    ASSERT_EQUAL(error_code, KAA_ERR_NONE);

    test_log_record->destroy(test_log_record);
    kaa_log_collector_destroy(log_collector);
}

/* ---------------------------------------------------------------------------*/
/* 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 */
    // cppcheck-suppress unusedStructMember
    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 */


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. */
static uint32_t                        test_reader_buffer[TEST_BUFFER_SIZE / 4];
static uint32_t                        test_writer_buffer[TEST_BUFFER_SIZE / 4];
/* 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++;
}