diff --git a/sys/checksum/doc.txt b/sys/checksum/doc.txt index 9c96b4e9a9..124b68dd18 100644 --- a/sys/checksum/doc.txt +++ b/sys/checksum/doc.txt @@ -20,8 +20,9 @@ * flavor of CRC16 (polynomial @$ x^{16} + x^{12} + x^{5} + 1 @$) for big-endian * numbers with starting seed `0x1d0f` (though others can be provided), while * @ref sys_checksum_ucrc16 is more generalized, since it takes the - * hexadecimal representation as a parameter and provides functions and - * standardized polynomials for both big- and little-endian numbers. + * hexadecimal representation of the polynomial as a parameter and provides + * functions and standardized polynomials for both big- and little-endian + * numbers. * * The caveat of @ref sys_checksum_ucrc16 is that it is significantly slower * (approximately factor 8) than @ref sys_checksum_crc16_ccitt since the latter diff --git a/sys/include/checksum/ucrc16.h b/sys/include/checksum/ucrc16.h index 393347b6a5..5e48e9a081 100644 --- a/sys/include/checksum/ucrc16.h +++ b/sys/include/checksum/ucrc16.h @@ -15,7 +15,7 @@ * thus very lightweight (memory-wise), but as a caveat slower (about factor 8) * than the version with pre-calculated lookup tables. * - * Additionally compared to @ref sys_checksum_crc_ccitt this is a generalized + * Additionally compared to @ref sys_checksum_crc16_ccitt this is a generalized * implementation. One can easily exchange generator polynomials and starting * seeds. * @@ -42,7 +42,7 @@ extern "C" { */ #define UCRC16_CCITT_POLY_BE (0x1021) /**< CRC16-CCITT polynomial (big-endian) */ #define UCRC16_CCITT_POLY_LE (0x8408) /**< CRC16-CCITT polynomial (little-endian) */ -/** *} */ +/** @} */ /** * @brief Calculate CRC16 (big-endian version) diff --git a/tests/unittests/Makefile b/tests/unittests/Makefile index 0e2705b224..268ab2dae1 100644 --- a/tests/unittests/Makefile +++ b/tests/unittests/Makefile @@ -1,7 +1,8 @@ APPLICATION = unittests include ../Makefile.tests_common -BOARD_INSUFFICIENT_MEMORY := airfy-beacon cc2650stk chronos msb-430 msb-430h pca10000 \ +BOARD_INSUFFICIENT_MEMORY := airfy-beacon cc2650stk chronos ek-lm4f120xl \ + msb-430 msb-430h pca10000 \ pca10005 spark-core stm32f0discovery stm32f3discovery \ telosb wsn430-v1_3b wsn430-v1_4 z1 nucleo-f103 \ nucleo-f334 yunjia-nrf51822 samr21-xpro \ @@ -9,7 +10,8 @@ BOARD_INSUFFICIENT_MEMORY := airfy-beacon cc2650stk chronos msb-430 msb-430h pca weio waspmote-pro nucleo-f072 arduino-uno \ arduino-duemilanove sodaq-autonomo arduino-zero \ nucleo-f030 nucleo-f070 nucleo-f091 pba-d-01-kw2x \ - saml21-xpro microbit calliope-mini limifrog-v1 + saml21-xpro microbit calliope-mini limifrog-v1 \ + slwstk6220a USEMODULE += embunit diff --git a/tests/unittests/tests-checksum/tests-checksum-ucrc16.c b/tests/unittests/tests-checksum/tests-checksum-ucrc16.c new file mode 100644 index 0000000000..b363df2f6f --- /dev/null +++ b/tests/unittests/tests-checksum/tests-checksum-ucrc16.c @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2016 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @{ + * + * @file + * @author Martine Lenders + */ + +#include + +#include "embUnit/embUnit.h" + +#include "checksum/ucrc16.h" + +#include "tests-checksum.h" + +#define CRC16_CCITT_SEED (0x1d0f) + +/* equivalent to crc16-ccitt version */ +static int calc_and_compare_crc_be_with_update(const uint8_t *buf, + size_t len, size_t split, uint16_t expected) +{ + uint16_t result = ucrc16_calc_be(buf, split, UCRC16_CCITT_POLY_BE, + CRC16_CCITT_SEED); + + result = ucrc16_calc_be(buf + split, len - split, UCRC16_CCITT_POLY_BE, + result); + + return result == expected; +} + +static int calc_and_compare_crc_be(const uint8_t *buf, size_t len, + uint16_t expected) +{ + uint16_t result = ucrc16_calc_be(buf, len, UCRC16_CCITT_POLY_BE, + CRC16_CCITT_SEED); + + return result == expected; +} + +static void test_checksum_ucrc16_be_sequence_empty(void) +{ + uint8_t buf[] = ""; + uint16_t expect = CRC16_CCITT_SEED; + + TEST_ASSERT(calc_and_compare_crc_be(buf, sizeof(buf) - 1, expect)); + TEST_ASSERT(calc_and_compare_crc_be_with_update(buf, sizeof(buf) - 1, + (sizeof(buf) - 1) / 2, expect)); +} + +static void test_checksum_ucrc16_be_sequence_1a(void) +{ + uint8_t buf[] = "A"; + uint16_t expect = 0x9479; + + TEST_ASSERT(calc_and_compare_crc_be(buf, sizeof(buf) - 1, expect)); + TEST_ASSERT(calc_and_compare_crc_be_with_update(buf, sizeof(buf) - 1, + (sizeof(buf) - 1) / 2, expect)); +} + +static void test_checksum_ucrc16_be_sequence_256a(void) +{ + uint8_t buf[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + uint16_t expect = 0xE938; + + TEST_ASSERT(calc_and_compare_crc_be(buf, sizeof(buf) - 1, expect)); + TEST_ASSERT(calc_and_compare_crc_be_with_update(buf, sizeof(buf) - 1, + (sizeof(buf) - 1) / 2, expect)); +} + +static void test_checksum_ucrc16_be_sequence_1to9(void) +{ + uint8_t buf[] = "123456789"; + uint16_t expect = 0xE5CC; + + TEST_ASSERT(calc_and_compare_crc_be(buf, sizeof(buf) - 1, expect)); + TEST_ASSERT(calc_and_compare_crc_be_with_update(buf, sizeof(buf) + - 1, (sizeof(buf) - 1) / 2, expect)); +} + +static void test_checksum_ucrc16_be_sequence_4bytes(void) +{ + uint8_t buf[] = { 0x12, 0x34, 0x56, 0x78 }; + uint16_t expect = 0xBA3C; + + TEST_ASSERT(calc_and_compare_crc_be(buf, sizeof(buf), expect)); + TEST_ASSERT(calc_and_compare_crc_be_with_update(buf, sizeof(buf), + sizeof(buf) / 2, expect)); +} + +static void test_checksum_ucrc16_le_ieee802164_frame(void) +{ + /* test data taken from first packet in + * https://wiki.wireshark.org/SampleCaptures?action=AttachFile&do=get&target=6LoWPAN.pcap.gz */ + uint8_t buf[] = { 0x41, 0xcc, 0xa4, 0xff, 0xff, 0x8a, 0x18, 0x00, + 0xff, 0xff, 0xda, 0x1c, 0x00, 0x88, 0x18, 0x00, + 0xff, 0xff, 0xda, 0x1c, 0x00, 0x41, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x19, 0x11, 0x40, 0xfe, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0xda, 0xff, 0xff, 0x00, 0x18, 0x88, 0xfe, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0xda, 0xff, 0xff, 0x00, 0x18, 0x8a, 0x04, 0x01, + 0xf0, 0xb1, 0x00, 0x19, 0xea, 0x8a, 0x48, 0x65, + 0x6c, 0x6c, 0x6f, 0x20, 0x30, 0x30, 0x33, 0x20, + 0x30, 0x78, 0x43, 0x35, 0x39, 0x41, 0x0a }; + uint16_t expect = 0x31f9; + uint16_t result = ucrc16_calc_le(buf, sizeof(buf), UCRC16_CCITT_POLY_LE, 0); + + TEST_ASSERT_EQUAL_INT(expect, result); +} + +Test *tests_checksum_ucrc16_tests(void) +{ + EMB_UNIT_TESTFIXTURES(fixtures) { + /* Reference values according to + * http://srecord.sourceforge.net/crc16-ccitt.html */ + new_TestFixture(test_checksum_ucrc16_be_sequence_empty), + new_TestFixture(test_checksum_ucrc16_be_sequence_1a), + new_TestFixture(test_checksum_ucrc16_be_sequence_256a), + new_TestFixture(test_checksum_ucrc16_be_sequence_1to9), + new_TestFixture(test_checksum_ucrc16_be_sequence_4bytes), + new_TestFixture(test_checksum_ucrc16_le_ieee802164_frame), + }; + + EMB_UNIT_TESTCALLER(checksum_ucrc16_tests, NULL, NULL, fixtures); + + return (Test *)&checksum_ucrc16_tests; +} diff --git a/tests/unittests/tests-checksum/tests-checksum.c b/tests/unittests/tests-checksum/tests-checksum.c index 8378bccdac..f4a40582ae 100644 --- a/tests/unittests/tests-checksum/tests-checksum.c +++ b/tests/unittests/tests-checksum/tests-checksum.c @@ -13,4 +13,5 @@ void tests_checksum(void) TESTS_RUN(tests_checksum_crc16_ccitt_tests()); TESTS_RUN(tests_checksum_fletcher16_tests()); TESTS_RUN(tests_checksum_fletcher32_tests()); + TESTS_RUN(tests_checksum_ucrc16_tests()); } diff --git a/tests/unittests/tests-checksum/tests-checksum.h b/tests/unittests/tests-checksum/tests-checksum.h index 781139e224..2c37421b60 100644 --- a/tests/unittests/tests-checksum/tests-checksum.h +++ b/tests/unittests/tests-checksum/tests-checksum.h @@ -50,6 +50,13 @@ Test *tests_checksum_fletcher16_tests(void); */ Test *tests_checksum_fletcher32_tests(void); +/** + * @brief Generates tests for checksum/ucrc16.h + * + * @return embUnit tests if successful, NULL if not. + */ +Test *tests_checksum_ucrc16_tests(void); + #ifdef __cplusplus } #endif