142 lines · cpp
1//===-- Unittests for strtok_r -------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "src/string/strtok_r.h"10#include "test/UnitTest/Test.h"11 12TEST(LlvmLibcStrTokReentrantTest, NoTokenFound) {13 { // Empty source and delimiter string.14 char empty[] = "";15 char *reserve = nullptr;16 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(empty, "", &reserve), nullptr);17 // Another call to ensure that 'reserve' is not in a bad state.18 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(empty, "", &reserve), nullptr);19 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(nullptr, "", &reserve), nullptr);20 }21 { // Empty source and single character delimiter string.22 char empty[] = "";23 char *reserve = nullptr;24 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(empty, "_", &reserve), nullptr);25 // Another call to ensure that 'reserve' is not in a bad state.26 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(empty, "_", &reserve), nullptr);27 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(nullptr, "_", &reserve), nullptr);28 }29 { // Same character source and delimiter string.30 char single[] = "_";31 char *reserve = nullptr;32 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(single, "_", &reserve), nullptr);33 // Another call to ensure that 'reserve' is not in a bad state.34 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(single, "_", &reserve), nullptr);35 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(nullptr, "_", &reserve), nullptr);36 }37 { // Multiple character source and single character delimiter string.38 char multiple[] = "1,2";39 char *reserve = nullptr;40 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(multiple, ":", &reserve), "1,2");41 // Another call to ensure that 'reserve' is not in a bad state.42 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(multiple, ":", &reserve), "1,2");43 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(nullptr, ":", &reserve), nullptr);44 }45}46 47TEST(LlvmLibcStrTokReentrantTest, DelimiterAsFirstCharacterShouldBeIgnored) {48 char src[] = ".123";49 char *reserve = nullptr;50 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(src, ".", &reserve), "123");51 // Another call to ensure that 'reserve' is not in a bad state.52 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(src, ".", &reserve), "123");53 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(nullptr, ".", &reserve), nullptr);54}55 56TEST(LlvmLibcStrTokReentrantTest, DelimiterIsMiddleCharacter) {57 char src[] = "12,34";58 char *reserve = nullptr;59 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(src, ",", &reserve), "12");60 // Another call to ensure that 'reserve' is not in a bad state.61 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(src, ",", &reserve), "12");62 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(nullptr, ",", &reserve), nullptr);63}64 65TEST(LlvmLibcStrTokReentrantTest, DelimiterAsLastCharacterShouldBeIgnored) {66 char src[] = "1234:";67 char *reserve = nullptr;68 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(src, ":", &reserve), "1234");69 // Another call to ensure that 'reserve' is not in a bad state.70 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(src, ":", &reserve), "1234");71 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(nullptr, ":", &reserve), nullptr);72}73 74TEST(LlvmLibcStrTokReentrantTest, ShouldNotGoPastNullTerminator) {75 char src[] = {'1', '2', '\0', ',', '3'};76 char *reserve = nullptr;77 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(src, ",", &reserve), "12");78 // Another call to ensure that 'reserve' is not in a bad state.79 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(src, ",", &reserve), "12");80 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(nullptr, ",", &reserve), nullptr);81}82 83TEST(LlvmLibcStrTokReentrantTest,84 ShouldReturnNullptrWhenBothSrcAndSaveptrAreNull) {85 char *src = nullptr;86 char *reserve = nullptr;87 // Ensure that instead of crashing if src and reserve are null, nullptr is88 // returned89 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(src, ",", &reserve), nullptr);90 // And that neither src nor reserve are changed when that happens91 ASSERT_STREQ(src, nullptr);92 ASSERT_STREQ(reserve, nullptr);93}94 95TEST(LlvmLibcStrTokReentrantTest,96 SubsequentCallsShouldFindFollowingDelimiters) {97 char src[] = "12,34.56";98 char *reserve = nullptr;99 char *token = LIBC_NAMESPACE::strtok_r(src, ",.", &reserve);100 ASSERT_STREQ(token, "12");101 token = LIBC_NAMESPACE::strtok_r(nullptr, ",.", &reserve);102 ASSERT_STREQ(token, "34");103 token = LIBC_NAMESPACE::strtok_r(nullptr, ",.", &reserve);104 ASSERT_STREQ(token, "56");105 token = LIBC_NAMESPACE::strtok_r(nullptr, "_:,_", &reserve);106 ASSERT_STREQ(token, nullptr);107 // Subsequent calls after hitting the end of the string should also return108 // nullptr.109 token = LIBC_NAMESPACE::strtok_r(nullptr, "_:,_", &reserve);110 ASSERT_STREQ(token, nullptr);111}112 113TEST(LlvmLibcStrTokReentrantTest, DelimitersShouldNotBeIncludedInToken) {114 char src[] = "__ab__:_cd__:__ef__:__";115 char *reserve = nullptr;116 char *token = LIBC_NAMESPACE::strtok_r(src, "_:", &reserve);117 ASSERT_STREQ(token, "ab");118 token = LIBC_NAMESPACE::strtok_r(nullptr, ":_", &reserve);119 ASSERT_STREQ(token, "cd");120 token = LIBC_NAMESPACE::strtok_r(nullptr, "_:,", &reserve);121 ASSERT_STREQ(token, "ef");122 token = LIBC_NAMESPACE::strtok_r(nullptr, "_:,_", &reserve);123 ASSERT_STREQ(token, nullptr);124}125 126TEST(LlvmLibcStrTokReentrantTest, SubsequentSearchesReturnNull) {127 char src[] = "a";128 char *reserve = nullptr;129 char *token = LIBC_NAMESPACE::strtok_r(src, ":", &reserve);130 ASSERT_STREQ(token, "a");131 ASSERT_EQ(LIBC_NAMESPACE::strtok_r(nullptr, ":", &reserve), nullptr);132 ASSERT_EQ(LIBC_NAMESPACE::strtok_r(nullptr, ":", &reserve), nullptr);133}134 135TEST(LlvmLibcStrTokReentrantTest, TopBitSet) {136 char top_bit_set_str[] = "hello\x80world";137 char *p;138 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(top_bit_set_str, "\x80", &p), "hello");139 ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(nullptr, "\x80", &p), "world");140 ASSERT_EQ(LIBC_NAMESPACE::strtok_r(nullptr, "\x80", &p), nullptr);141}142