Newer
Older
mbed-os / TESTS / mbed_hal / crc / main.cpp
@Martin Kojtal Martin Kojtal on 21 Feb 2020 13 KB test: fix SPDX identifier
/* mbed Microcontroller Library
 * Copyright (c) 2018 ARM Limited
 * SPDX-License-Identifier: Apache-2.0
 *
 * 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.
 */
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#include "mbed.h"
#include "math.h"
#include "crc_api.h"

#if !DEVICE_CRC
#error [NOT_SUPPORTED] CRC not supported for this target
#else

using namespace utest::v1;

#define POLY_8BIT_MAXIM 0x31

#define UNSUPPORTED (-1)
#define POL_CNT (2)

const uint8_t input_data[] = "123456789";

typedef struct {
    const crc_mbed_config config_data;
    uint32_t expected_result;

} TEST_CASE;

/* We will allocate test case array on stack since memory limits on some boards
 * like NUCLEO_F070RB. */
static TEST_CASE *test_cases;
static uint32_t test_cases_size;

/* Test that hal_crc_is_supported() function returns true if given polynomial
 * is supported, false otherwise (at least one polynomial from the predefined list must be supported).  */
void crc_is_supported_test()
{
    /* Check if at least one crc polynomial/config is supported. */
    uint32_t num_of_supported_polynomials = 0;

    for (unsigned int i = 0; i < (test_cases_size / sizeof(TEST_CASE)); i++) {
        if (HAL_CRC_IS_SUPPORTED(test_cases[i].config_data.polynomial, test_cases[i].config_data.width)) {

            num_of_supported_polynomials++;
        }
    }

    TEST_ASSERT(num_of_supported_polynomials > 0);
}

/* Test that CRC module can be successfully configured, fed with data and the result can
 * be successfully obtained. */
void crc_calc_single_test()
{
    for (unsigned int i = 0; i < (test_cases_size / sizeof(TEST_CASE)); i++) {
        if (HAL_CRC_IS_SUPPORTED(test_cases[i].config_data.polynomial, test_cases[i].config_data.width)) {

            hal_crc_compute_partial_start(&test_cases[i].config_data);
            hal_crc_compute_partial((uint8_t *) input_data, strlen((const char *) input_data));
            const uint32_t crc = hal_crc_get_result();

            TEST_ASSERT_EQUAL(test_cases[i].expected_result, crc);
        }
    }
}

/* Test that hal_crc_compute_partial() function can be call multiple times in
 * succession in order to provide additional data to CRC module. */
void crc_calc_multi_test()
{
    for (unsigned int i = 0; i < (test_cases_size / sizeof(TEST_CASE)); i++) {
        if (HAL_CRC_IS_SUPPORTED(test_cases[i].config_data.polynomial, test_cases[i].config_data.width)) {

            const uint32_t first_part_bytes = 3;
            const uint32_t second_part_bytes = 1;
            const uint32_t third_part_bytes = strlen((const char *) input_data) - first_part_bytes
                                              - second_part_bytes;

            hal_crc_compute_partial_start(&test_cases[i].config_data);
            hal_crc_compute_partial((uint8_t *) input_data, first_part_bytes);
            hal_crc_compute_partial((uint8_t *)(input_data + first_part_bytes), second_part_bytes);
            hal_crc_compute_partial((uint8_t *)(input_data + first_part_bytes + second_part_bytes),
                                    third_part_bytes);
            const uint32_t crc = hal_crc_get_result();

            TEST_ASSERT_EQUAL(test_cases[i].expected_result, crc);
        }
    }
}

/* Test that calling hal_crc_compute_partial_start() without finalising the
 * CRC calculation overrides the current configuration. */
void crc_reconfigure_test()
{
    int pol_idx[POL_CNT] =
    { UNSUPPORTED, UNSUPPORTED };
    int pol_cnt = 0;
    const uint8_t dummy_input_data[] = "abcdefghijklmnopqrstuvwxyz";

    /* At least one configuration must be supported. If two are supported, then
     * re-initialize CRC module using different config. */
    for (unsigned int i = 0; i < (test_cases_size / sizeof(TEST_CASE)); i++) {

        /* Find two supported polynomials if possible. */
        if (HAL_CRC_IS_SUPPORTED(test_cases[i].config_data.polynomial, test_cases[i].config_data.width)) {
            if (pol_cnt == 0) {
                pol_idx[pol_cnt] = i;
                pol_cnt++;
            } else if (test_cases[pol_idx[0]].config_data.polynomial != test_cases[i].config_data.polynomial) {
                pol_idx[pol_cnt] = i;
                pol_cnt++;
            }

            if (pol_cnt == POL_CNT) {
                break;
            }
        }
    }

    pol_cnt = 0;

    /* Init CRC module and provide some data, but do not read the result. */
    hal_crc_compute_partial_start(&test_cases[pol_idx[pol_cnt]].config_data);
    hal_crc_compute_partial((uint8_t *) dummy_input_data, strlen((const char *) dummy_input_data));

    /* Change index only if more than one supported polynomial has been found. */
    if (pol_idx[POL_CNT - 1] != UNSUPPORTED) {
        pol_cnt++;
    }

    /* Now re-init CRC module and provide new data and check the result. */
    hal_crc_compute_partial_start(&test_cases[pol_idx[pol_cnt]].config_data);
    hal_crc_compute_partial((uint8_t *) input_data, strlen((const char *) input_data));
    const uint32_t crc = hal_crc_get_result();

    TEST_ASSERT_EQUAL(test_cases[pol_idx[pol_cnt]].expected_result, crc);
}

/* Test that hal_crc_compute_partial() does nothing if pointer to buffer is undefined or
 * data length is equal to 0. */
void crc_compute_partial_invalid_param_test()
{
    uint32_t crc = 0;

    /* At least one polynomial must be supported. */
    for (unsigned int i = 0; i < (test_cases_size / sizeof(TEST_CASE)); i++) {
        if (HAL_CRC_IS_SUPPORTED(test_cases[i].config_data.polynomial, test_cases[i].config_data.width)) {

            hal_crc_compute_partial_start(&test_cases[i].config_data);

            /* Call hal_crc_compute_partial() with invalid parameters. */
            hal_crc_compute_partial((uint8_t *) NULL, strlen((const char *) input_data));
            hal_crc_compute_partial((uint8_t *) input_data, 0);

            /* Now use valid parameters. */
            hal_crc_compute_partial((uint8_t *) input_data,
                                    strlen((const char *) input_data));

            crc = hal_crc_get_result();

            TEST_ASSERT_EQUAL(test_cases[i].expected_result, crc);

            break;
        }
    }
}

Case cases[] = {
    Case("test: supported polynomials.", crc_is_supported_test),
    Case("test: CRC calculation - single input.", crc_calc_single_test),
    Case("test: CRC calculation - multi input.", crc_calc_multi_test),
    Case("test: re-configure without getting the result.", crc_reconfigure_test),
    Case("test: hal_crc_compute_partial() - invalid parameters.", crc_compute_partial_invalid_param_test),
};

utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
{
    GREENTEA_SETUP(30, "default_auto");
    return greentea_test_setup_handler(number_of_cases);
}

Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);

int main()
{
    // *INDENT-OFF*
    TEST_CASE local_test_cases[] = {
        /* Predefined polynomials. */
        { {POLY_7BIT_SD     ,  7, 0x00000000, 0x00000000, false, false}, 0x75       },
        { {POLY_7BIT_SD     ,  7, 0x0000007F, 0x00000000, false, false}, 0x50       },
        { {POLY_7BIT_SD     ,  7, 0x0000002B, 0x00000000, false, false}, 0x3A       },
        { {POLY_7BIT_SD     ,  7, 0x00000000, 0x0000007F, false, false}, 0x0A       },
        { {POLY_7BIT_SD     ,  7, 0x00000000, 0x0000002B, false, false}, 0x5E       },
        { {POLY_7BIT_SD     ,  7, 0x00000000, 0x00000000, true , false}, 0x52       },
        { {POLY_7BIT_SD     ,  7, 0x00000000, 0x00000000, false, true }, 0x57       },
        { {POLY_7BIT_SD     ,  7, 0x0000002B, 0x00000000, true , false}, 0x1D       },
        { {POLY_7BIT_SD     ,  7, 0x0000002B, 0x00000000, false, true }, 0x2E       },
        { {POLY_7BIT_SD     ,  7, 0x0000002B, 0x00000000, true , true }, 0x5C       },
        { {POLY_7BIT_SD     ,  7, 0x00000000, 0x0000002B, false, true }, 0x7C       },

        { {POLY_8BIT_CCITT  ,  8, 0x00000000, 0x00000000, false, false}, 0xF4       },
        { {POLY_8BIT_CCITT  ,  8, 0x000000FF, 0x00000000, false, false}, 0xFB       },
        { {POLY_8BIT_CCITT  ,  8, 0x000000AB, 0x00000000, false, false}, 0x87       },
        { {POLY_8BIT_CCITT  ,  8, 0x00000000, 0x000000FF, false, false}, 0x0B       },
        { {POLY_8BIT_CCITT  ,  8, 0x00000000, 0x000000AB, false, false}, 0x5F       },
        { {POLY_8BIT_CCITT  ,  8, 0x00000000, 0x00000000, true , false}, 0x04       },
        { {POLY_8BIT_CCITT  ,  8, 0x00000000, 0x00000000, false, true }, 0x2F       },
        { {POLY_8BIT_CCITT  ,  8, 0x000000AB, 0x00000000, true,  false}, 0x77       },
        { {POLY_8BIT_CCITT  ,  8, 0x000000AB, 0x00000000, false, true }, 0xE1       },
        { {POLY_8BIT_CCITT  ,  8, 0x000000AB, 0x00000000, true,  true }, 0xEE       },
        { {POLY_8BIT_CCITT  ,  8, 0x00000000, 0x000000AB, false, true }, 0x84       },

        { {POLY_16BIT_CCITT , 16, 0x00000000, 0x00000000, false, false}, 0x31C3     },
        { {POLY_16BIT_CCITT , 16, 0x0000FFFF, 0x00000000, false, false}, 0x29B1     },
        { {POLY_16BIT_CCITT , 16, 0x0000ABAB, 0x00000000, false, false}, 0x7D70     },
        { {POLY_16BIT_CCITT , 16, 0x00000000, 0x0000FFFF, false, false}, 0xCE3C     },
        { {POLY_16BIT_CCITT , 16, 0x00000000, 0x0000ABAB, false, false}, 0x9A68     },
        { {POLY_16BIT_CCITT , 16, 0x00000000, 0x00000000, true , false}, 0x9184     },
        { {POLY_16BIT_CCITT , 16, 0x00000000, 0x00000000, false, true }, 0xC38C     },
        { {POLY_16BIT_CCITT , 16, 0x0000ABAB, 0x00000000, true,  false}, 0xDD37     },
        { {POLY_16BIT_CCITT , 16, 0x0000ABAB, 0x00000000, false, true }, 0x0EBE     },
        { {POLY_16BIT_CCITT , 16, 0x0000ABAB, 0x00000000, true,  true }, 0xECBB     },
        { {POLY_16BIT_CCITT , 16, 0x00000000, 0x0000ABAB, false, true }, 0x6827     },

        { {POLY_16BIT_IBM   , 16, 0x00000000, 0x00000000, false, false}, 0xFEE8     },
        { {POLY_16BIT_IBM   , 16, 0x0000FFFF, 0x00000000, false, false}, 0xAEE7     },
        { {POLY_16BIT_IBM   , 16, 0x0000ABAB, 0x00000000, false, false}, 0x0887     },
        { {POLY_16BIT_IBM   , 16, 0x00000000, 0x0000FFFF, false, false}, 0x0117     },
        { {POLY_16BIT_IBM   , 16, 0x00000000, 0x0000ABAB, false, false}, 0x5543     },
        { {POLY_16BIT_IBM   , 16, 0x00000000, 0x00000000, true , false}, 0xBCDD     },
        { {POLY_16BIT_IBM   , 16, 0x00000000, 0x00000000, false, true }, 0x177F     },
        { {POLY_16BIT_IBM   , 16, 0x0000ABAB, 0x00000000, true,  false}, 0x4AB2     },
        { {POLY_16BIT_IBM   , 16, 0x0000ABAB, 0x00000000, false, true }, 0xE110     },
        { {POLY_16BIT_IBM   , 16, 0x0000ABAB, 0x00000000, true,  true }, 0x4D52     },
        { {POLY_16BIT_IBM   , 16, 0x00000000, 0x0000ABAB, false, true }, 0xBCD4     },

        { {POLY_32BIT_ANSI  , 32, 0x00000000, 0x00000000, false, false}, 0x89A1897F },
        { {POLY_32BIT_ANSI  , 32, 0xFFFFFFFF, 0x00000000, false, false}, 0x0376E6E7 },
        { {POLY_32BIT_ANSI  , 32, 0xABABABAB, 0x00000000, false, false}, 0x871A2FAA },
        { {POLY_32BIT_ANSI  , 32, 0x00000000, 0xFFFFFFFF, false, false}, 0x765E7680 },
        { {POLY_32BIT_ANSI  , 32, 0x00000000, 0xABABABAB, false, false}, 0x220A22D4 },
        { {POLY_32BIT_ANSI  , 32, 0x00000000, 0x00000000, true , false}, 0x11B4BFB4 },
        { {POLY_32BIT_ANSI  , 32, 0x00000000, 0x00000000, false, true }, 0xFE918591 },
        { {POLY_32BIT_ANSI  , 32, 0xABABABAB, 0x00000000, true,  false}, 0x1F0F1961 },
        { {POLY_32BIT_ANSI  , 32, 0xABABABAB, 0x00000000, false, true }, 0x55F458E1 },
        { {POLY_32BIT_ANSI  , 32, 0xABABABAB, 0x00000000, true,  true }, 0x8698F0F8 },
        { {POLY_32BIT_ANSI  , 32, 0x00000000, 0xABABABAB, false, true }, 0x553A2E3A },

        /* Not-predefined polynomials. */
        { {POLY_8BIT_MAXIM  ,  8, 0x00000000, 0x00000000, false, false}, 0xA2       },
        { {POLY_8BIT_MAXIM  ,  8, 0x000000FF, 0x00000000, false, false}, 0xF7       },
        { {POLY_8BIT_MAXIM  ,  8, 0x000000AB, 0x00000000, false, false}, 0x71       },
        { {POLY_8BIT_MAXIM  ,  8, 0x00000000, 0x000000FF, false, false}, 0x5D       },
        { {POLY_8BIT_MAXIM  ,  8, 0x00000000, 0x000000AB, false, false}, 0x09       },
        { {POLY_8BIT_MAXIM  ,  8, 0x00000000, 0x00000000, true , false}, 0x85       },
        { {POLY_8BIT_MAXIM  ,  8, 0x00000000, 0x00000000, false, true }, 0x45       },
        { {POLY_8BIT_MAXIM  ,  8, 0x000000AB, 0x00000000, true,  false}, 0x56       },
        { {POLY_8BIT_MAXIM  ,  8, 0x000000AB, 0x00000000, false, true }, 0x8E       },
        { {POLY_8BIT_MAXIM  ,  8, 0x000000AB, 0x00000000, true,  true }, 0x6A       },
        { {POLY_8BIT_MAXIM  ,  8, 0x00000000, 0x000000AB, false, true }, 0xEE       },
    };
    // *INDENT-ON*

    test_cases = local_test_cases;
    test_cases_size = sizeof(local_test_cases);

    Harness::run(specification);
}

#endif // !DEVICE_CRC