From 96eff6135b141e63d2b8d0ac722a77cef1cea6f8 Mon Sep 17 00:00:00 2001 From: Damian Modzelewski Date: Fri, 28 Apr 2023 09:55:27 +0200 Subject: [PATCH] libc: string.h: add cmp functions tests JIRA: CI-231 --- libc/main.c | 5 + libc/string_cmp.c | 450 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 455 insertions(+) create mode 100644 libc/string_cmp.c diff --git a/libc/main.c b/libc/main.c index 363309514..dd78c1d74 100644 --- a/libc/main.c +++ b/libc/main.c @@ -52,6 +52,7 @@ void runner(void) RUN_TEST_GROUP(stdio_scanf_squareBrackets); RUN_TEST_GROUP(stdio_scanf_rest); RUN_TEST_GROUP(string_chr); + RUN_TEST_GROUP(mem_cmp); RUN_TEST_GROUP(string_memset); RUN_TEST_GROUP(string_memmove); RUN_TEST_GROUP(string_memmove_big); @@ -62,6 +63,10 @@ void runner(void) RUN_TEST_GROUP(string_strcpy_stpcpy); RUN_TEST_GROUP(string_strlcpy); RUN_TEST_GROUP(string_strlcat); + RUN_TEST_GROUP(string_memcmp); + RUN_TEST_GROUP(string_strncmp); + RUN_TEST_GROUP(string_strcmp); + RUN_TEST_GROUP(string_strcoll); } diff --git a/libc/string_cmp.c b/libc/string_cmp.c new file mode 100644 index 000000000..b181a4f55 --- /dev/null +++ b/libc/string_cmp.c @@ -0,0 +1,450 @@ +/* + * Phoenix-RTOS + * + * POSIX.1-2017 standard library functions tests + * HEADER: + * - string.h + * TESTED: + * - memcmp() + * - strcmp() + * - strncmp() + * - strcoll() + * + * Copyright 2023 Phoenix Systems + * Author: Damian Modzelewski + * + * This file is part of Phoenix-RTOS. + * + * %LICENSE% + */ + + +#include +#include +#include +#include +#include +#include + + +#define BUFF_SIZE 128 + +static char asciiSet[BUFF_SIZE] = { 0 }, + nonZeroAsciiSet[BUFF_SIZE] = { 0 }, + outOfAsciiSet[UCHAR_MAX] = { 0 }, + empty[BUFF_SIZE] = { 0 }, + ucharSet[UCHAR_MAX] = { 0 }, + ucharEmpty[UCHAR_MAX] = { 0 }, + hugeString[INT16_MAX] = { 0 }, + hugeZeroString[INT16_MAX] = { 0 }, + separated[24] = { 0, 0, 0, 0, 0, 0, 'T', 'E', 'S', 'T', 0, 0, 0 }; + + +TEST_GROUP(string_memcmp); +TEST_GROUP(string_strncmp); +TEST_GROUP(string_strcmp); +TEST_GROUP(string_strcoll); + +/* +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +*/ + + +TEST_SETUP(string_memcmp) +{ +} + +// TEST_SETUP(mem_cmp) +// { +// } + +TEST_TEAR_DOWN(string_memcmp) +{ +} + +// TEST_TEAR_DOWN(mem_cmp) +// { +// } + +TEST(string_memcmp, basic) +{ + int s1, s2, szOffset; + char dataSet[4000] = { 0 }, + supportSet[4000] = { 0 }; + int sz = sizeof(dataSet); + + TEST_ASSERT_EQUAL_INT(0, memcmp(asciiSet, asciiSet, BUFF_SIZE)); + TEST_ASSERT_LESS_THAN_INT(0, memcmp(asciiSet, nonZeroAsciiSet, BUFF_SIZE)); + TEST_ASSERT_GREATER_THAN_INT(0, memcmp(nonZeroAsciiSet, asciiSet, BUFF_SIZE)); + TEST_ASSERT_LESS_THAN_INT(0, memcmp(ucharEmpty, ucharSet, UCHAR_MAX - 1)); + + for (s1 = 0; s1 < sz; s1++) { + dataSet[s1] = (unsigned char)s1; + supportSet[s1] = (unsigned char)s1; + } + + + for (s1 = 0; s1 < 8; s1++) { + for (s2 = 0; s2 < 8; s2++) { + for (szOffset = 0; szOffset < 8; szOffset++) { + if (s2 < s1) { + TEST_ASSERT_GREATER_THAN_INT(0, memcmp(&dataSet[s1], &dataSet[s2], sz - (s1 + szOffset))); + TEST_ASSERT_GREATER_THAN_INT(0, memcmp(&dataSet[s1], &supportSet[s2], sz - (s1 + szOffset))); + } + else if (s2 == s1) { + TEST_ASSERT_EQUAL_INT(0, memcmp(&dataSet[s1], &dataSet[s2], sz - (s1 + s2) - szOffset)); + TEST_ASSERT_EQUAL_INT(0, memcmp(&dataSet[s1], &supportSet[s2], sz - (s1 + s2) - szOffset)); + } + else { + TEST_ASSERT_LESS_THAN_INT(0, memcmp(&dataSet[s1], &dataSet[s2], sz - (s2 + szOffset))); + TEST_ASSERT_LESS_THAN_INT(0, memcmp(&dataSet[s1], &supportSet[s2], sz - (s2 + szOffset))); + } + } + } + } +} + +// TEST(mem_cmp, memcmp_unsigned) +// { +// char holderOutOfAscii[UCHAR_MAX] = { 0 }; + +TEST(string_memcmp, unsignedChar) +{ + char holderOutOfAscii[UCHAR_MAX] = { 0 }; + + /* + * Loop for creating a buffer similar to ucharSet but with negative values + * to check the ability of memcmp to convert elements to unsigned char + */ + for (int i = 0; i < sizeof(holderOutOfAscii); i++) { + holderOutOfAscii[i] = outOfAsciiSet[sizeof(outOfAsciiSet) - 1 - i]; + } + + TEST_ASSERT_EQUAL_INT(0, memcmp(ucharSet, holderOutOfAscii, sizeof(holderOutOfAscii))); +} + + +TEST(string_memcmp, emptyInput) +{ + TEST_ASSERT_LESS_THAN_INT(0, memcmp(empty, asciiSet, BUFF_SIZE)); + TEST_ASSERT_LESS_THAN_INT(0, memcmp(empty, nonZeroAsciiSet, BUFF_SIZE)); + TEST_ASSERT_GREATER_THAN_INT(0, memcmp(asciiSet, empty, BUFF_SIZE)); + TEST_ASSERT_EQUAL_INT(0, memcmp(empty, empty, BUFF_SIZE)); + + /* Memory cmp is not sensitive for NUL characters */ + TEST_ASSERT_NOT_EQUAL_INT(0, memcmp(empty, separated, sizeof(separated))); +} + +TEST(string_memcmp, big) +{ + TEST_ASSERT_EQUAL_INT(0, memcmp(hugeString, hugeString, sizeof(hugeString))); + TEST_ASSERT_LESS_THAN_INT(0, memcmp(hugeZeroString, hugeString, sizeof(hugeString))); + TEST_ASSERT_GREATER_THAN_INT(0, memcmp(hugeString, hugeZeroString, sizeof(hugeString))); + TEST_ASSERT_EQUAL_INT(0, memcmp(hugeZeroString, hugeZeroString, sizeof(hugeString))); +} + + +TEST(string_memcmp, sizes) +{ + int i; + + // /* Memory cmp is not sensitive for NUL characters */ + // TEST_ASSERT_NOT_EQUAL_INT(0, memcmp(empty, separated, sizeof(separated))); + // } + + /* Loop which changes the size of compared space to place where asciSet ends */ + for (i = 1; i < sizeof(asciiSet); i++) { + TEST_ASSERT_LESS_THAN_INT(0, memcmp(asciiSet, nonZeroAsciiSet, i)); + } +} + +// TEST(mem_cmp, memcmp_sizes) +// { +// int i; + +// TEST_ASSERT_LESS_THAN_INT(0, memcmp(&asciiSet[BUFF_SIZE / 2], &nonZeroAsciiSet[BUFF_SIZE / 2], BUFF_SIZE / 2)); +// TEST_ASSERT_GREATER_THAN_INT(0, memcmp(&asciiSet[sizeof(asciiSet) - 1], &nonZeroAsciiSet[sizeof(nonZeroAsciiSet) - 1], 1)); +// TEST_ASSERT_LESS_THAN_INT(0, memcmp(&nonZeroAsciiSet[BUFF_SIZE - 1], &asciiSet[BUFF_SIZE - 1], 1)); +// TEST_ASSERT_EQUAL_INT(0, memcmp(&nonZeroAsciiSet[sizeof(nonZeroAsciiSet) - 1], &nonZeroAsciiSet[sizeof(nonZeroAsciiSet) - 1], BUFF_SIZE - 1)); +// TEST_ASSERT_EQUAL_INT(0, memcmp(asciiSet, nonZeroAsciiSet, 0)); + +// /* Loop which changes the size of compared space to place where asciSet ends */ +// for (i = 1; i < sizeof(asciiSet); i++) { +// TEST_ASSERT_LESS_THAN_INT(0, memcmp(asciiSet, nonZeroAsciiSet, i)); +// } +// } + + +/* +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +*/ + + +TEST_SETUP(string_strncmp) +{ +} + + +TEST_TEAR_DOWN(string_strncmp) +{ +} + + +TEST(string_strncmp, basic) +{ + TEST_ASSERT_EQUAL_INT(0, strncmp(asciiSet, asciiSet, BUFF_SIZE)); + TEST_ASSERT_LESS_THAN_INT(0, strncmp(asciiSet, nonZeroAsciiSet, BUFF_SIZE)); + TEST_ASSERT_GREATER_THAN_INT(0, strncmp(nonZeroAsciiSet, asciiSet, BUFF_SIZE)); + + /* + * We avoid the first place of ucharSet and set size smaller of that place + * because it is a null terminator which means strncmp will stop its compare + */ + TEST_ASSERT_LESS_THAN_INT(0, strncmp(&ucharEmpty[1], &ucharSet[1], UCHAR_MAX - 1)); +} + + +TEST(string_strncmp, unsignedChar) +{ + char holderOutOfAscii[UCHAR_MAX] = { 0 }; + + /* + * Loop for creating a buffer similar to ucharSet but with negative values + * to check the ability of strncmp to convert elements to unsigned char + */ + for (int i = 0; i < sizeof(holderOutOfAscii); i++) { + holderOutOfAscii[i] = outOfAsciiSet[sizeof(outOfAsciiSet) - 1 - i]; + } + + TEST_ASSERT_EQUAL_INT(0, strncmp(ucharSet, holderOutOfAscii, sizeof(holderOutOfAscii))); +} + + +TEST(string_strncmp, emptyInput) +{ + TEST_ASSERT_EQUAL_INT(0, strncmp(empty, asciiSet, BUFF_SIZE)); + TEST_ASSERT_LESS_THAN_INT(0, strncmp(empty, nonZeroAsciiSet, BUFF_SIZE)); + TEST_ASSERT_EQUAL_INT(0, strncmp(asciiSet, empty, BUFF_SIZE)); + TEST_ASSERT_EQUAL_INT(0, strncmp(empty, empty, BUFF_SIZE)); + + /* Otherwise than in memcmp, strncmp is NUL character sensitive and treats 0 as the end of array */ + TEST_ASSERT_EQUAL_INT(0, strncmp(empty, separated, BUFF_SIZE)); +} + +TEST(string_strncmp, big) +{ + TEST_ASSERT_EQUAL_INT(0, strncmp(hugeString, hugeString, sizeof(hugeString))); + TEST_ASSERT_LESS_THAN_INT(0, strncmp(hugeZeroString, hugeString, sizeof(hugeString))); + TEST_ASSERT_EQUAL_INT(0, strncmp(hugeZeroString, hugeZeroString, sizeof(hugeString))); +} + + +TEST(string_strncmp, sizes) +{ + int i; + + TEST_ASSERT_LESS_THAN_INT(0, strncmp(&asciiSet[BUFF_SIZE / 2], &nonZeroAsciiSet[BUFF_SIZE / 2], BUFF_SIZE / 2)); + TEST_ASSERT_GREATER_THAN_INT(0, strncmp(&asciiSet[sizeof(asciiSet) - 1], &nonZeroAsciiSet[sizeof(nonZeroAsciiSet) - 1], 1)); + TEST_ASSERT_LESS_THAN_INT(0, strncmp(&nonZeroAsciiSet[BUFF_SIZE - 1], &asciiSet[BUFF_SIZE - 1], 1)); + TEST_ASSERT_EQUAL_INT(0, strncmp(&nonZeroAsciiSet[sizeof(nonZeroAsciiSet) - 1], &nonZeroAsciiSet[sizeof(nonZeroAsciiSet) - 1], BUFF_SIZE - 1)); + TEST_ASSERT_EQUAL_INT(0, strncmp(asciiSet, nonZeroAsciiSet, 0)); + + /* Loop which changes the size of compared space to place where asciSet ends */ + for (i = 1; i < sizeof(asciiSet); i++) { + TEST_ASSERT_LESS_THAN_INT(0, strncmp(asciiSet, nonZeroAsciiSet, i)); + } + + /* Testing size bigger than string having in mind the compare will end with null terminator */ + TEST_ASSERT_EQUAL_INT(0, strncmp(asciiSet, asciiSet, SIZE_MAX)); +} + + +/* +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +*/ + + +TEST_SETUP(string_strcmp) +{ +} + + +TEST_TEAR_DOWN(string_strcmp) +{ +} + + +TEST(string_strcmp, basic) +{ + TEST_ASSERT_EQUAL_INT(0, strcmp(asciiSet, asciiSet)); + TEST_ASSERT_LESS_THAN_INT(0, strcmp(asciiSet, nonZeroAsciiSet)); + TEST_ASSERT_GREATER_THAN_INT(0, strcmp(nonZeroAsciiSet, asciiSet)); + + /* We avoid the first place of ucharSet because it is a null terminator which means strcmp will stop its compare */ + TEST_ASSERT_LESS_THAN_INT(0, strcmp(&ucharEmpty[1], &ucharSet[1])); +} + + +TEST(string_strcmp, unsignedChar) +{ + char holderOutOfAscii[UCHAR_MAX] = { 0 }; + + /* + * Loop for creating a buffer similar to ucharSet but with negative values + * to check the ability of strcmp to convert elements to unsigned char + */ + for (int i = 0; i < sizeof(holderOutOfAscii); i++) { + holderOutOfAscii[i] = outOfAsciiSet[sizeof(outOfAsciiSet) - 1 - i]; + } + + /* + * From lack of defined space size on which CMP is done we are forced to + * set up the last elements of arrays as NULL terms to indicate + * stop point + */ + ucharSet[sizeof(ucharSet) - 1] = 0; + holderOutOfAscii[sizeof(holderOutOfAscii) - 1] = 0; + + TEST_ASSERT_EQUAL_INT(0, strcmp(ucharSet, holderOutOfAscii)); +} + + +TEST(string_strcmp, emptyInput) +{ + TEST_ASSERT_EQUAL_INT(0, strcmp(empty, asciiSet)); + TEST_ASSERT_LESS_THAN_INT(0, strcmp(empty, nonZeroAsciiSet)); + TEST_ASSERT_EQUAL_INT(0, strcmp(asciiSet, empty)); + TEST_ASSERT_EQUAL_INT(0, strcmp(empty, empty)); +} + + +TEST(string_strcmp, big) +{ + TEST_ASSERT_EQUAL_INT(0, strcmp(hugeString, hugeString)); + TEST_ASSERT_LESS_THAN_INT(0, strcmp(hugeZeroString, hugeString)); + TEST_ASSERT_EQUAL_INT(0, strcmp(hugeZeroString, hugeZeroString)); +} + + +TEST(string_strcmp, sizes) +{ + TEST_ASSERT_LESS_THAN_INT(0, strcmp(&asciiSet[BUFF_SIZE / 2], &nonZeroAsciiSet[BUFF_SIZE / 2])); + TEST_ASSERT_GREATER_THAN_INT(0, strcmp(&asciiSet[sizeof(asciiSet) - 1], &nonZeroAsciiSet[sizeof(nonZeroAsciiSet) - 1])); +} + + +/* +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +*/ + + +TEST_SETUP(string_strcoll) +{ + errno = 0; +} + + +TEST_TEAR_DOWN(string_strcoll) +{ +} + + +TEST(string_strcoll, basic) +{ + TEST_ASSERT_EQUAL_INT(0, strcoll(asciiSet, asciiSet)); + TEST_ASSERT_LESS_THAN_INT(0, strcoll(asciiSet, nonZeroAsciiSet)); + TEST_ASSERT_GREATER_THAN_INT(0, strcoll(nonZeroAsciiSet, asciiSet)); + + /* We avoid the first place of ucharSet because it is a null terminator which means strcoll will stop its compare */ + TEST_ASSERT_LESS_THAN_INT(0, strcoll(&ucharEmpty[1], &ucharSet[1])); + + TEST_ASSERT_EQUAL_INT(0, errno); +} + + +TEST(string_strcoll, emptyInput) +{ + TEST_ASSERT_EQUAL_INT(0, strcoll(empty, asciiSet)); + TEST_ASSERT_LESS_THAN_INT(0, strcoll(empty, nonZeroAsciiSet)); + TEST_ASSERT_EQUAL_INT(0, strcoll(asciiSet, empty)); + TEST_ASSERT_EQUAL_INT(0, strcoll(empty, empty)); + TEST_ASSERT_EQUAL_INT(0, errno); +} + + +TEST(string_strcoll, big) +{ + TEST_ASSERT_EQUAL_INT(0, strcoll(hugeString, hugeString)); + TEST_ASSERT_LESS_THAN_INT(0, strcoll(hugeZeroString, hugeString)); + TEST_ASSERT_EQUAL_INT(0, strcoll(hugeZeroString, hugeZeroString)); +} + + +TEST(string_strcoll, sizes) +{ + TEST_ASSERT_LESS_THAN_INT(0, strcoll(&asciiSet[BUFF_SIZE / 2], &nonZeroAsciiSet[BUFF_SIZE / 2])); + TEST_ASSERT_GREATER_THAN_INT(0, strcoll(&asciiSet[sizeof(asciiSet) - 1], &nonZeroAsciiSet[sizeof(nonZeroAsciiSet) - 1])); + TEST_ASSERT_EQUAL_INT(0, errno); +} + + +/* +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +*/ + + +TEST_GROUP_RUNNER(string_memcmp) +{ + /* Creating all needed data sets to run test cases */ + int i; + + for (i = 1; i < BUFF_SIZE; i++) { + nonZeroAsciiSet[i - 1] = i; + asciiSet[i] = i; + } + + for (i = 1; i < UCHAR_MAX + 1; i++) { + ucharSet[i - 1] = i; + outOfAsciiSet[i - 1] = i * -1; + } + + for (i = 0; i < INT16_MAX - 1; i++) { + hugeString[i] = i % 256; + /* Avoid null term to get one long string */ + if (i % 256 == 0 || i == 0) { + hugeString[i] = (i % 256) + 1; + } + } + + RUN_TEST_CASE(string_memcmp, basic); + RUN_TEST_CASE(string_memcmp, unsignedChar); + RUN_TEST_CASE(string_memcmp, emptyInput); + RUN_TEST_CASE(string_memcmp, big); + RUN_TEST_CASE(string_memcmp, sizes); +} + +TEST_GROUP_RUNNER(string_strncmp) +{ + RUN_TEST_CASE(string_strncmp, basic); + RUN_TEST_CASE(string_strncmp, unsignedChar); + RUN_TEST_CASE(string_strncmp, emptyInput); + RUN_TEST_CASE(string_strncmp, big); + RUN_TEST_CASE(string_strncmp, sizes); +} + +TEST_GROUP_RUNNER(string_strcmp) +{ + RUN_TEST_CASE(string_strcmp, basic); + RUN_TEST_CASE(string_strcmp, unsignedChar); + RUN_TEST_CASE(string_strcmp, emptyInput); + RUN_TEST_CASE(string_strcmp, big); + RUN_TEST_CASE(string_strcmp, sizes); +} + +TEST_GROUP_RUNNER(string_strcoll) +{ + RUN_TEST_CASE(string_strcoll, basic); + RUN_TEST_CASE(string_strcoll, emptyInput); + RUN_TEST_CASE(string_strcoll, big); + RUN_TEST_CASE(string_strcoll, sizes); +}