Anna Karas has uploaded this change for review.

View Change

tests: Complete lib/string-test test case

Implement unit tests for remaining string library functions. Fix memory leak
in test_strdup().

Signed-off-by: Anna Karas <aka@semihalf.com>
Change-Id: I8ac6a6b2413d9077dc9ea81f638a2b0acd5c8862
---
M tests/lib/string-test.c
1 file changed, 212 insertions(+), 19 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/11/42311/1
diff --git a/tests/lib/string-test.c b/tests/lib/string-test.c
index 08f4177..39e9be9 100644
--- a/tests/lib/string-test.c
+++ b/tests/lib/string-test.c
@@ -1,50 +1,243 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
#include <tests/test.h>

+#define DST_SIZE 20
+
/*
* Important note: In every particular test, don't use any string-related
* functions other than function under test. We are linking against
* src/lib/string.c not the standard library. This is important for proper test
- * isolation. One can use __builtin_xxx for many of the most simple str*()
- * functions, when non-coreboot one is required.
+ * isolation.
*/

-struct strings_t {
- char *str;
- size_t size;
-} strings[] = {
- {"coreboot", 8},
- {"is\0very", 2}, /* strlen should be 2 because of the embedded \0 */
- {"nice\n", 5}
+struct string_pairs_t {
+ char *dst;
+ char *src;
+} string_pairs[] = {
+ {"Hello ", "world!"},
+ {"He\0llo ", "world"},
+ {"", "world!"},
+ {"", ""},
};

-static void test_strlen_strings(void **state)
-{
- int i;
+const char *strings[] = {
+ "coreboot",
+ "is\0very",
+ "nice\n"
+};

- for (i = 0; i < ARRAY_SIZE(strings); i++)
- assert_int_equal(strings[i].size, strlen(strings[i].str));
-}
+struct str_with_l_val_t {
+ char *str;
+ long value;
+} str_with_l_val[] = {
+ {"42", 42},
+ {"four42", 0},
+ {"42five5", 42},
+ {"4\02", 4},
+ {"+42", 42},
+ {"-42", -42},
+ {"\t\n\r\f\v-42", -42},
+};
+
+struct str_with_u_val_t {
+ char *str;
+ uint32_t value;
+} str_with_u_val[] = {
+ {"42aa", 42},
+ {"a", 0},
+ {"0", 0},
+ {"4a2", 4},
+};

static void test_strdup(void **state)
{
char str[] = "Hello coreboot\n";
- char *duplicate;
-
- duplicate = strdup(str);
+ char *duplicate = strdup(str);

/* There is a more suitable Cmocka's function 'assert_string_equal()', but it
is using strcmp() internally. */
assert_int_equal(0, memcmp(str, duplicate, __builtin_strlen(str)));
+
+ free(duplicate);
+}
+
+static void test_strconcat(void **state)
+{
+ int i;
+ size_t str_len, str2_len, res_len;
+ char *result;
+
+ for (i = 0; i < ARRAY_SIZE(string_pairs); i++) {
+ str_len = __builtin_strlen(string_pairs[i].dst);
+ str2_len = __builtin_strlen(string_pairs[i].src);
+
+ result = strconcat(string_pairs[i].dst, string_pairs[i].src);
+ res_len = __builtin_strlen(result);
+
+ assert_int_equal(res_len, str_len + str2_len);
+ assert_int_equal(0, memcmp(string_pairs[i].dst, result, str_len));
+ assert_int_equal(0, memcmp(string_pairs[i].src, result + str_len, str2_len));
+
+ free(result);
+ }
+}
+
+static void test_strnlen(void **state)
+{
+ int i, n = 5;
+ size_t str_len, limited_len;
+
+ for (i = 0; i < ARRAY_SIZE(strings); i++) {
+ str_len = __builtin_strlen(strings[i]);
+ limited_len = str_len > n ? n : str_len;
+ assert_int_equal(limited_len, strnlen(strings[i], n));
+ }
+}
+
+static void test_strlen(void **state)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(strings); i++)
+ assert_int_equal(__builtin_strlen(strings[i]), strlen(strings[i]));
+}
+
+static void test_strchr(void **state)
+{
+ char str[] = "Abracadabra!\n";
+
+ assert_ptr_equal(str, strchr(str, 'A'));
+ assert_ptr_equal(str + 3, strchr(str, 'a'));
+ assert_ptr_not_equal(str + 10, strchr(str, 'a'));
+
+ assert_null(strchr(str, 'z'));
+}
+
+
+static void test_strrchr(void **state)
+{
+ char str[] = "Abracadabra!\n";
+
+ assert_ptr_equal(str + 9, strrchr(str, 'r'));
+ assert_ptr_not_equal(str + 2, strrchr(str, 'r'));
+
+ assert_null(strrchr(str, 'z'));
+}
+
+
+static void test_strncpy(void **state)
+{
+ int i, n = 7;
+ char dst[DST_SIZE];
+ char src[] = "Hello coreboot\n";
+ size_t src_len = __builtin_strlen(src);
+
+ strncpy(dst, src, n);
+
+ assert_int_equal(0, memcmp(dst, src, n));
+
+ for (i = src_len; i < n; i++)
+ assert_true(dst[i] == '\0');
+}
+
+static void test_strcpy(void **state)
+{
+ char dst[DST_SIZE];
+ char src[] = "Hello coreboot\n";
+
+ /* Make sure that strcpy() sets '\0' by initializing a whole
+ dst array to fixed, non-'\0' value */
+ memset(dst, 'x', DST_SIZE);
+
+ strcpy(dst, src);
+
+ assert_int_equal(0, memcmp(dst, src, __builtin_strlen(src)));
+ assert_true(dst[__builtin_strlen(dst)] == '\0');
+}
+
+static void test_strcmp(void **state)
+{
+ char str[] = "Banana";
+ char str2[] = "Bananas";
+
+ assert_true(strcmp(str, str2) < 0);
+ assert_int_equal(0, strcmp(str, str));
+ assert_true(strcmp(str2, str) > 0);
+}
+
+static void test_strncmp(void **state)
+{
+ char str[] = "Banana";
+ char str2[] = "Bananas";
+
+ size_t str2_len = __builtin_strlen(str2);
+
+ assert_true(strncmp(str, str2, str2_len) < 0);
+ assert_int_equal(0, strncmp(str, str2, str2_len - 1));
+}
+
+static void test_skip_atoi(void **state)
+{
+ int i;
+ char *ptr;
+
+ for (i = 0; i < ARRAY_SIZE(str_with_u_val); i++) {
+ ptr = str_with_u_val[i].str;
+ assert_int_equal(str_with_u_val[i].value, skip_atoi(&ptr));
+ }
+}
+
+static void test_strspn(void **state)
+{
+ char str[] = "123404567";
+ char str2[] = "01234";
+ char str3[] = "1234";
+
+ assert_int_equal(4, strspn(str, str3));
+ assert_int_equal(0, strspn(str2, str3));
+}
+
+static void test_strcspn(void **state)
+{
+ char str[] = "12340000";
+ char str2[] = "00001234";
+ char str3[] = "1234";
+
+ assert_int_equal(0, strcspn(str, str3));
+ assert_int_equal(4, strcspn(str2, str3));
+}
+
+/* Please bear in mind that `atol()` uses `strspn()` internally, so the result
+ of `test_atol` is dependent on the result of `test_strspn`. */
+static void test_atol(void **state)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(str_with_l_val); i++)
+ assert_int_equal(str_with_l_val[i].value, atol(str_with_l_val[i].str));
}

int main(void)
{
const struct CMUnitTest tests[] = {
- cmocka_unit_test(test_strlen_strings),
cmocka_unit_test(test_strdup),
+ cmocka_unit_test(test_strconcat),
+ cmocka_unit_test(test_strnlen),
+ cmocka_unit_test(test_strlen),
+ cmocka_unit_test(test_strchr),
+ cmocka_unit_test(test_strrchr),
+ cmocka_unit_test(test_strncpy),
+ cmocka_unit_test(test_strcpy),
+ cmocka_unit_test(test_strcmp),
+ cmocka_unit_test(test_strncmp),
+ cmocka_unit_test(test_skip_atoi),
+ cmocka_unit_test(test_strspn),
+ cmocka_unit_test(test_strcspn),
+ cmocka_unit_test(test_atol),
};

return cmocka_run_group_tests(tests, NULL, NULL);

To view, visit change 42311. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I8ac6a6b2413d9077dc9ea81f638a2b0acd5c8862
Gerrit-Change-Number: 42311
Gerrit-PatchSet: 1
Gerrit-Owner: Anna Karas <aka@semihalf.com>
Gerrit-MessageType: newchange