LCOV - code coverage report
Current view: top level - unit_test/test_spdm_requester - encap_digests.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 133 133
Test Date: 2026-02-22 08:11:49 Functions: 100.0 % 7 7

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 2021-2026 DMTF. All rights reserved.
       4              :  *  License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
       5              :  **/
       6              : #include "spdm_unit_test.h"
       7              : #include "internal/libspdm_requester_lib.h"
       8              : 
       9              : #if (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) && \
      10              :     (LIBSPDM_ENABLE_CAPABILITY_CERT_CAP)
      11              : 
      12              : spdm_get_digest_request_t m_spdm_get_digests_request1 = {
      13              :     {
      14              :         SPDM_MESSAGE_VERSION_11,
      15              :         SPDM_GET_DIGESTS,
      16              :     },
      17              : };
      18              : size_t m_spdm_get_digests_request1_size = sizeof(m_spdm_get_digests_request1);
      19              : 
      20              : 
      21              : spdm_get_digest_request_t m_spdm_get_digests_request2 = {
      22              :     {
      23              :         SPDM_MESSAGE_VERSION_13,
      24              :         SPDM_GET_DIGESTS,
      25              :     },
      26              : };
      27              : size_t m_spdm_get_digests_request2_size = sizeof(m_spdm_get_digests_request2);
      28              : 
      29              : static uint8_t m_local_certificate_chain[LIBSPDM_MAX_CERT_CHAIN_SIZE];
      30              : 
      31              : /**
      32              :  * Test 1: receives a valid GET_DIGESTS request message from Requester
      33              :  * Expected Behavior: produces a valid DIGESTS response message
      34              :  **/
      35            1 : static void req_encap_digests_case1(void **state)
      36              : {
      37              :     libspdm_return_t status;
      38              :     libspdm_test_context_t *spdm_test_context;
      39              :     libspdm_context_t *spdm_context;
      40              :     size_t response_size;
      41              :     uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
      42              :     spdm_digest_response_t *spdm_response;
      43              : 
      44            1 :     spdm_test_context = *state;
      45            1 :     spdm_context = spdm_test_context->spdm_context;
      46            1 :     spdm_test_context->case_id = 0x1;
      47            1 :     spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_11
      48              :                                             << SPDM_VERSION_NUMBER_SHIFT_BIT;
      49            1 :     spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_NEGOTIATED;
      50            1 :     spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CERT_CAP;
      51            1 :     spdm_context->connection_info.algorithm.base_hash_algo = m_libspdm_use_hash_algo;
      52            1 :     spdm_context->local_context.local_cert_chain_provision[0] = m_local_certificate_chain;
      53            1 :     spdm_context->local_context.local_cert_chain_provision_size[0] =
      54              :         sizeof(m_local_certificate_chain);
      55            1 :     libspdm_set_mem(m_local_certificate_chain, sizeof(m_local_certificate_chain), (uint8_t)(0xFF));
      56              : 
      57              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
      58              :     spdm_context->transcript.message_m.buffer_size =
      59              :         spdm_context->transcript.message_m.max_buffer_size;
      60              : #endif
      61              : 
      62            1 :     response_size = sizeof(response);
      63            1 :     status = libspdm_get_encap_response_digest(spdm_context,
      64              :                                                m_spdm_get_digests_request1_size,
      65              :                                                &m_spdm_get_digests_request1,
      66              :                                                &response_size, response);
      67            1 :     assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
      68            1 :     assert_int_equal(
      69              :         response_size,
      70              :         sizeof(spdm_digest_response_t) +
      71              :         libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo));
      72            1 :     spdm_response = (void *)response;
      73            1 :     assert_int_equal(spdm_response->header.request_response_code, SPDM_DIGESTS);
      74              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
      75              :     assert_int_equal(spdm_context->transcript.message_m.buffer_size, 0);
      76              : #endif
      77            1 : }
      78              : 
      79              : /**
      80              :  * Test 2:
      81              :  * Expected Behavior:
      82              :  **/
      83            1 : static void req_encap_digests_case2(void **state)
      84              : {
      85            1 : }
      86              : 
      87              : /**
      88              :  * Test 3: receives a valid GET_DIGESTS request message from Requester, but the request message cannot be appended to the internal cache since the internal cache is full
      89              :  * Expected Behavior: produces an ERROR response message with error code = Unspecified
      90              :  **/
      91            1 : static void req_encap_digests_case3(void **state)
      92              : {
      93              :     libspdm_return_t status;
      94              :     libspdm_test_context_t *spdm_test_context;
      95              :     libspdm_context_t *spdm_context;
      96              :     size_t response_size;
      97              :     uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
      98              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
      99              :     spdm_digest_response_t *spdm_response;
     100              : #endif
     101            1 :     spdm_test_context = *state;
     102            1 :     spdm_context = spdm_test_context->spdm_context;
     103            1 :     spdm_test_context->case_id = 0x3;
     104            1 :     spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_11
     105              :                                             << SPDM_VERSION_NUMBER_SHIFT_BIT;
     106            1 :     spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_NEGOTIATED;
     107            1 :     spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CERT_CAP;
     108            1 :     spdm_context->connection_info.algorithm.base_hash_algo = m_libspdm_use_hash_algo;
     109            1 :     spdm_context->local_context.local_cert_chain_provision[0] = m_local_certificate_chain;
     110            1 :     spdm_context->local_context.local_cert_chain_provision_size[0] =
     111              :         sizeof(m_local_certificate_chain);
     112            1 :     libspdm_set_mem(m_local_certificate_chain, sizeof(m_local_certificate_chain), (uint8_t)(0xFF));
     113              : 
     114            1 :     response_size = sizeof(response);
     115              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     116              :     spdm_context->transcript.message_b.buffer_size =
     117              :         spdm_context->transcript.message_b.max_buffer_size;
     118              : #endif
     119            1 :     status = libspdm_get_encap_response_digest(spdm_context,
     120              :                                                m_spdm_get_digests_request1_size,
     121              :                                                &m_spdm_get_digests_request1,
     122              :                                                &response_size, response);
     123            1 :     assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
     124              : 
     125              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     126              :     assert_int_equal(
     127              :         response_size,
     128              :         sizeof(spdm_digest_response_t) +
     129              :         libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo));
     130              :     spdm_response = (void *)response;
     131              :     assert_int_equal(spdm_response->header.request_response_code, SPDM_DIGESTS);
     132              :     assert_int_equal(spdm_response->header.param1, 0);
     133              :     assert_int_equal(spdm_response->header.param2, SPDM_ERROR_CODE_INVALID_REQUEST);
     134              : #endif
     135            1 : }
     136              : 
     137              : /**
     138              :  * Test 4: receives a valid GET_DIGESTS request message from Requester, but the response message cannot be appended to the internal cache since the internal cache is full
     139              :  * Expected Behavior: produces an ERROR response message with error code = Unspecified
     140              :  **/
     141            1 : static void req_encap_digests_case4(void **state)
     142              : {
     143              :     libspdm_test_context_t *spdm_test_context;
     144              :     libspdm_context_t *spdm_context;
     145              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     146              :     size_t response_size;
     147              :     uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
     148              :     libspdm_return_t status;
     149              :     spdm_digest_response_t *spdm_response;
     150              : #endif
     151              : 
     152            1 :     spdm_test_context = *state;
     153            1 :     spdm_context = spdm_test_context->spdm_context;
     154            1 :     spdm_test_context->case_id = 0x4;
     155            1 :     spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_11
     156              :                                             << SPDM_VERSION_NUMBER_SHIFT_BIT;
     157            1 :     spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_NEGOTIATED;
     158            1 :     spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CERT_CAP;
     159            1 :     spdm_context->connection_info.algorithm.base_hash_algo = m_libspdm_use_hash_algo;
     160            1 :     spdm_context->local_context.local_cert_chain_provision[0] = m_local_certificate_chain;
     161            1 :     spdm_context->local_context.local_cert_chain_provision_size[0] =
     162              :         sizeof(m_local_certificate_chain);
     163            1 :     libspdm_set_mem(m_local_certificate_chain, sizeof(m_local_certificate_chain), (uint8_t)(0xFF));
     164              : 
     165              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     166              :     spdm_context->transcript.message_b.buffer_size =
     167              :         spdm_context->transcript.message_b.max_buffer_size -
     168              :         sizeof(spdm_get_digest_request_t);
     169              :     response_size = sizeof(response);
     170              :     status = libspdm_get_encap_response_digest(spdm_context,
     171              :                                                m_spdm_get_digests_request1_size,
     172              :                                                &m_spdm_get_digests_request1,
     173              :                                                &response_size, response);
     174              :     assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
     175              :     assert_int_equal(
     176              :         response_size,
     177              :         sizeof(spdm_digest_response_t) +
     178              :         libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo));
     179              :     spdm_response = (void *)response;
     180              :     assert_int_equal(spdm_response->header.request_response_code, SPDM_DIGESTS);
     181              :     assert_int_equal(spdm_response->header.param1, 0);
     182              :     assert_int_equal(spdm_response->header.param2, SPDM_ERROR_CODE_INVALID_REQUEST);
     183              : #endif
     184            1 : }
     185              : 
     186              : /**
     187              :  * Test 5: receives a valid GET_DIGESTS request message from Requester ,
     188              :  * Set multi_key_conn_req to check if it responds correctly
     189              :  * Expected Behavior: produces a valid DIGESTS response message
     190              :  **/
     191            1 : static void req_encap_digests_case5(void **state)
     192              : {
     193              :     libspdm_return_t status;
     194              :     libspdm_test_context_t *spdm_test_context;
     195              :     libspdm_context_t *spdm_context;
     196              :     size_t response_size;
     197              :     uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
     198              :     spdm_digest_response_t *spdm_response;
     199              :     libspdm_session_info_t *session_info;
     200              :     uint32_t session_id;
     201              : 
     202            1 :     spdm_test_context = *state;
     203            1 :     spdm_context = spdm_test_context->spdm_context;
     204            1 :     spdm_test_context->case_id = 0x5;
     205            1 :     spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13
     206              :                                             << SPDM_VERSION_NUMBER_SHIFT_BIT;
     207            1 :     spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_NEGOTIATED;
     208            1 :     spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CERT_CAP;
     209            1 :     spdm_context->connection_info.algorithm.base_hash_algo = m_libspdm_use_hash_algo;
     210            1 :     spdm_context->local_context.local_cert_chain_provision[0] = m_local_certificate_chain;
     211            1 :     spdm_context->local_context.local_cert_chain_provision_size[0] =
     212              :         sizeof(m_local_certificate_chain);
     213            1 :     libspdm_set_mem(m_local_certificate_chain, sizeof(m_local_certificate_chain), (uint8_t)(0xFF));
     214              : 
     215            1 :     session_id = 0xFFFFFFFF;
     216            1 :     spdm_context->latest_session_id = session_id;
     217            1 :     spdm_context->last_spdm_request_session_id_valid = true;
     218            1 :     spdm_context->last_spdm_request_session_id = session_id;
     219            1 :     session_info = &spdm_context->session_info[0];
     220            1 :     libspdm_session_info_init(spdm_context, session_info, session_id,
     221              :                               SECURED_SPDM_VERSION_11 << SPDM_VERSION_NUMBER_SHIFT_BIT, true);
     222            1 :     libspdm_secured_message_set_session_state(
     223              :         session_info->secured_message_context,
     224              :         LIBSPDM_SESSION_STATE_ESTABLISHED);
     225              : 
     226              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     227              :     spdm_context->transcript.message_m.buffer_size =
     228              :         spdm_context->transcript.message_m.max_buffer_size;
     229              : #endif
     230              :     /* Sub Case 1: Set multi_key_conn_req to true*/
     231            1 :     spdm_context->connection_info.multi_key_conn_req = true;
     232            1 :     libspdm_reset_message_encap_d(session_info);
     233              : 
     234            1 :     response_size = sizeof(response);
     235            1 :     status = libspdm_get_encap_response_digest(spdm_context,
     236              :                                                m_spdm_get_digests_request2_size,
     237              :                                                &m_spdm_get_digests_request2,
     238              :                                                &response_size, response);
     239            1 :     assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
     240            1 :     assert_int_equal(
     241              :         response_size,
     242              :         sizeof(spdm_digest_response_t) +  sizeof(spdm_key_pair_id_t) +
     243              :         sizeof(spdm_certificate_info_t) +
     244              :         sizeof(spdm_key_usage_bit_mask_t) +
     245              :         libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo));
     246            1 :     spdm_response = (void *)response;
     247            1 :     assert_int_equal(spdm_response->header.request_response_code, SPDM_DIGESTS);
     248            1 :     assert_int_equal(session_info->session_transcript.message_encap_d.buffer_size,
     249              :                      sizeof(spdm_digest_response_t) +  sizeof(spdm_key_pair_id_t) +
     250              :                      sizeof(spdm_certificate_info_t) +
     251              :                      sizeof(spdm_key_usage_bit_mask_t) +
     252              :                      libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo));
     253              : 
     254              :     /* Sub Case 2: Set multi_key_conn_req to false*/
     255            1 :     spdm_context->connection_info.multi_key_conn_req = false;
     256            1 :     libspdm_reset_message_encap_d(session_info);
     257              : 
     258            1 :     response_size = sizeof(response);
     259            1 :     status = libspdm_get_encap_response_digest(spdm_context,
     260              :                                                m_spdm_get_digests_request2_size,
     261              :                                                &m_spdm_get_digests_request2,
     262              :                                                &response_size, response);
     263            1 :     assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
     264            1 :     assert_int_equal(
     265              :         response_size,
     266              :         sizeof(spdm_digest_response_t) +
     267              :         libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo));
     268            1 :     spdm_response = (void *)response;
     269            1 :     assert_int_equal(spdm_response->header.request_response_code, SPDM_DIGESTS);
     270            1 :     assert_int_equal(session_info->session_transcript.message_encap_d.buffer_size, 0);
     271            1 : }
     272              : 
     273              : /**
     274              :  * Test 6: receives a valid GET_DIGESTS request message from Requester ,
     275              :  * Check KeyPairID CertificateInfo and KeyUsageMask
     276              :  * Expected Behavior: produces a valid DIGESTS response message
     277              :  **/
     278            1 : static void req_encap_digests_case6(void **state)
     279              : {
     280              :     libspdm_return_t status;
     281              :     libspdm_test_context_t *spdm_test_context;
     282              :     libspdm_context_t *spdm_context;
     283              :     size_t response_size;
     284              :     uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
     285              :     spdm_digest_response_t *spdm_response;
     286              :     libspdm_session_info_t *session_info;
     287              :     uint32_t session_id;
     288              :     uint8_t *digest;
     289              :     spdm_key_pair_id_t *key_pair_id;
     290              :     spdm_certificate_info_t *cert_info;
     291              :     spdm_key_usage_bit_mask_t *key_usage_bit_mask;
     292              :     uint32_t hash_size;
     293              :     uint8_t slot_count;
     294              :     size_t additional_size;
     295              : 
     296            1 :     spdm_test_context = *state;
     297            1 :     spdm_context = spdm_test_context->spdm_context;
     298            1 :     spdm_test_context->case_id = 0x6;
     299            1 :     spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13
     300              :                                             << SPDM_VERSION_NUMBER_SHIFT_BIT;
     301            1 :     spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_NEGOTIATED;
     302            1 :     spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CERT_CAP;
     303            1 :     spdm_context->connection_info.algorithm.base_hash_algo = m_libspdm_use_hash_algo;
     304              : 
     305            1 :     slot_count = SPDM_MAX_SLOT_COUNT;
     306            1 :     additional_size = sizeof(spdm_key_pair_id_t) + sizeof(spdm_certificate_info_t) +
     307              :                       sizeof(spdm_key_usage_bit_mask_t);
     308            1 :     hash_size = libspdm_get_hash_size(m_libspdm_use_hash_algo);
     309              : 
     310            9 :     for (uint8_t index = 0; index < SPDM_MAX_SLOT_COUNT; index++) {
     311            8 :         spdm_context->local_context.local_cert_chain_provision[index] =
     312            8 :             &m_local_certificate_chain[hash_size * index];
     313              :         spdm_context->local_context
     314            8 :         .local_cert_chain_provision_size[index] = hash_size;
     315              :     }
     316              : 
     317            1 :     libspdm_set_mem(m_local_certificate_chain, sizeof(m_local_certificate_chain), (uint8_t)(0xFF));
     318              : 
     319            1 :     session_id = 0xFFFFFFFF;
     320            1 :     spdm_context->latest_session_id = session_id;
     321            1 :     spdm_context->last_spdm_request_session_id_valid = true;
     322            1 :     spdm_context->last_spdm_request_session_id = session_id;
     323            1 :     session_info = &spdm_context->session_info[0];
     324            1 :     libspdm_session_info_init(spdm_context, session_info, session_id,
     325              :                               SECURED_SPDM_VERSION_11 << SPDM_VERSION_NUMBER_SHIFT_BIT, true);
     326            1 :     libspdm_secured_message_set_session_state(
     327              :         session_info->secured_message_context,
     328              :         LIBSPDM_SESSION_STATE_ESTABLISHED);
     329              : 
     330              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     331              :     spdm_context->transcript.message_m.buffer_size =
     332              :         spdm_context->transcript.message_m.max_buffer_size;
     333              : #endif
     334            1 :     spdm_context->connection_info.multi_key_conn_req = true;
     335            1 :     libspdm_reset_message_encap_d(session_info);
     336              : 
     337            1 :     response_size = sizeof(response);
     338            1 :     status = libspdm_get_encap_response_digest(spdm_context,
     339              :                                                m_spdm_get_digests_request2_size,
     340              :                                                &m_spdm_get_digests_request2,
     341              :                                                &response_size, response);
     342              : 
     343            1 :     assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
     344            1 :     assert_int_equal(response_size,
     345              :                      sizeof(spdm_digest_response_t) + (hash_size + additional_size) * slot_count);
     346              : 
     347            1 :     spdm_response = (void *)response;
     348            1 :     assert_int_equal(spdm_response->header.request_response_code, SPDM_DIGESTS);
     349            1 :     assert_int_equal(session_info->session_transcript.message_encap_d.buffer_size,
     350              :                      sizeof(spdm_digest_response_t) + (hash_size + additional_size) * slot_count);
     351              : 
     352            1 :     digest = (void *)(spdm_response + 1);
     353            1 :     libspdm_zero_mem (digest, hash_size * slot_count);
     354            1 :     key_pair_id = (spdm_key_pair_id_t *)((uint8_t *)digest + (hash_size * slot_count));
     355            1 :     cert_info = (spdm_certificate_info_t *)((uint8_t *)key_pair_id +
     356            1 :                                             sizeof(spdm_key_pair_id_t) * slot_count);
     357            1 :     key_usage_bit_mask = (spdm_key_usage_bit_mask_t *)((uint8_t *)cert_info +
     358            1 :                                                        sizeof(spdm_certificate_info_t) *
     359              :                                                        slot_count);
     360            9 :     for (uint8_t index = 0; index < SPDM_MAX_SLOT_COUNT; index++) {
     361            8 :         assert_memory_equal((void *)&key_pair_id[index],
     362              :                             (void *)&spdm_context->local_context.local_key_pair_id[index],
     363              :                             sizeof(spdm_key_pair_id_t));
     364            8 :         assert_memory_equal((void *)&cert_info[index],
     365              :                             (void *)&spdm_context->local_context.local_cert_info[index],
     366              :                             sizeof(spdm_certificate_info_t));
     367            8 :         assert_memory_equal((void *)&key_usage_bit_mask[index],
     368              :                             (void *)&spdm_context->local_context.local_key_usage_bit_mask[index],
     369              :                             sizeof(spdm_key_usage_bit_mask_t));
     370              :     }
     371            1 : }
     372              : 
     373            1 : int libspdm_req_encap_digests_test(void)
     374              : {
     375            1 :     const struct CMUnitTest test_cases[] = {
     376              :         /* Success Case*/
     377              :         cmocka_unit_test(req_encap_digests_case1),
     378              :         /* Can be populated with new test.*/
     379              :         cmocka_unit_test(req_encap_digests_case2),
     380              :         /* Internal cache full (request message)*/
     381              :         cmocka_unit_test(req_encap_digests_case3),
     382              :         /* Internal cache full (response message)*/
     383              :         cmocka_unit_test(req_encap_digests_case4),
     384              :         /* Set multi_key_conn_req to check if it responds correctly */
     385              :         cmocka_unit_test(req_encap_digests_case5),
     386              :         /* Check KeyPairID CertificateInfo and KeyUsageMask*/
     387              :         cmocka_unit_test(req_encap_digests_case6),
     388              :     };
     389              : 
     390            1 :     libspdm_test_context_t test_context = {
     391              :         LIBSPDM_TEST_CONTEXT_VERSION,
     392              :         false,
     393              :     };
     394              : 
     395            1 :     libspdm_setup_test_context(&test_context);
     396              : 
     397            1 :     return cmocka_run_group_tests(test_cases,
     398              :                                   libspdm_unit_test_group_setup,
     399              :                                   libspdm_unit_test_group_teardown);
     400              : }
     401              : 
     402              : #endif /* (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (..) */
        

Generated by: LCOV version 2.0-1