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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "src/string/strtok_r.h" 10 #include "utils/UnitTest/Test.h" 11 12 TEST(LlvmLibcStrTokReentrantTest, NoTokenFound) { 13 { // Empty source and delimiter string. 14 char empty[] = ""; 15 char *reserve = nullptr; 16 ASSERT_STREQ(__llvm_libc::strtok_r(empty, "", &reserve), nullptr); 17 // Another call to ensure that 'reserve' is not in a bad state. 18 ASSERT_STREQ(__llvm_libc::strtok_r(empty, "", &reserve), nullptr); 19 ASSERT_STREQ(__llvm_libc::strtok_r(nullptr, "", &reserve), nullptr); 20 } 21 { // Empty source and single character delimiter string. 22 char empty[] = ""; 23 char *reserve = nullptr; 24 ASSERT_STREQ(__llvm_libc::strtok_r(empty, "_", &reserve), nullptr); 25 // Another call to ensure that 'reserve' is not in a bad state. 26 ASSERT_STREQ(__llvm_libc::strtok_r(empty, "_", &reserve), nullptr); 27 ASSERT_STREQ(__llvm_libc::strtok_r(nullptr, "_", &reserve), nullptr); 28 } 29 { // Same character source and delimiter string. 30 char single[] = "_"; 31 char *reserve = nullptr; 32 ASSERT_STREQ(__llvm_libc::strtok_r(single, "_", &reserve), nullptr); 33 // Another call to ensure that 'reserve' is not in a bad state. 34 ASSERT_STREQ(__llvm_libc::strtok_r(single, "_", &reserve), nullptr); 35 ASSERT_STREQ(__llvm_libc::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(__llvm_libc::strtok_r(multiple, ":", &reserve), "1,2"); 41 // Another call to ensure that 'reserve' is not in a bad state. 42 ASSERT_STREQ(__llvm_libc::strtok_r(multiple, ":", &reserve), "1,2"); 43 ASSERT_STREQ(__llvm_libc::strtok_r(nullptr, ":", &reserve), nullptr); 44 } 45 } 46 47 TEST(LlvmLibcStrTokReentrantTest, DelimiterAsFirstCharacterShouldBeIgnored) { 48 char src[] = ".123"; 49 char *reserve = nullptr; 50 ASSERT_STREQ(__llvm_libc::strtok_r(src, ".", &reserve), "123"); 51 // Another call to ensure that 'reserve' is not in a bad state. 52 ASSERT_STREQ(__llvm_libc::strtok_r(src, ".", &reserve), "123"); 53 ASSERT_STREQ(__llvm_libc::strtok_r(nullptr, ".", &reserve), nullptr); 54 } 55 56 TEST(LlvmLibcStrTokReentrantTest, DelimiterIsMiddleCharacter) { 57 char src[] = "12,34"; 58 char *reserve = nullptr; 59 ASSERT_STREQ(__llvm_libc::strtok_r(src, ",", &reserve), "12"); 60 // Another call to ensure that 'reserve' is not in a bad state. 61 ASSERT_STREQ(__llvm_libc::strtok_r(src, ",", &reserve), "12"); 62 ASSERT_STREQ(__llvm_libc::strtok_r(nullptr, ",", &reserve), nullptr); 63 } 64 65 TEST(LlvmLibcStrTokReentrantTest, DelimiterAsLastCharacterShouldBeIgnored) { 66 char src[] = "1234:"; 67 char *reserve = nullptr; 68 ASSERT_STREQ(__llvm_libc::strtok_r(src, ":", &reserve), "1234"); 69 // Another call to ensure that 'reserve' is not in a bad state. 70 ASSERT_STREQ(__llvm_libc::strtok_r(src, ":", &reserve), "1234"); 71 ASSERT_STREQ(__llvm_libc::strtok_r(nullptr, ":", &reserve), nullptr); 72 } 73 74 TEST(LlvmLibcStrTokReentrantTest, ShouldNotGoPastNullTerminator) { 75 char src[] = {'1', '2', '\0', ',', '3'}; 76 char *reserve = nullptr; 77 ASSERT_STREQ(__llvm_libc::strtok_r(src, ",", &reserve), "12"); 78 // Another call to ensure that 'reserve' is not in a bad state. 79 ASSERT_STREQ(__llvm_libc::strtok_r(src, ",", &reserve), "12"); 80 ASSERT_STREQ(__llvm_libc::strtok_r(nullptr, ",", &reserve), nullptr); 81 } 82 83 TEST(LlvmLibcStrTokReentrantTest, 84 ShouldReturnNullptrWhenBothSrcAndSaveptrAreNull) { 85 char *src = nullptr; 86 char *reserve = nullptr; 87 // Ensure that instead of crashing if src and reserve are null, nullptr is 88 // returned 89 ASSERT_STREQ(__llvm_libc::strtok_r(src, ",", &reserve), nullptr); 90 // And that neither src nor reserve are changed when that happens 91 ASSERT_STREQ(src, nullptr); 92 ASSERT_STREQ(reserve, nullptr); 93 } 94 95 TEST(LlvmLibcStrTokReentrantTest, 96 SubsequentCallsShouldFindFollowingDelimiters) { 97 char src[] = "12,34.56"; 98 char *reserve = nullptr; 99 char *token = __llvm_libc::strtok_r(src, ",.", &reserve); 100 ASSERT_STREQ(token, "12"); 101 token = __llvm_libc::strtok_r(nullptr, ",.", &reserve); 102 ASSERT_STREQ(token, "34"); 103 token = __llvm_libc::strtok_r(nullptr, ",.", &reserve); 104 ASSERT_STREQ(token, "56"); 105 token = __llvm_libc::strtok_r(nullptr, "_:,_", &reserve); 106 ASSERT_STREQ(token, nullptr); 107 // Subsequent calls after hitting the end of the string should also return 108 // nullptr. 109 token = __llvm_libc::strtok_r(nullptr, "_:,_", &reserve); 110 ASSERT_STREQ(token, nullptr); 111 } 112 113 TEST(LlvmLibcStrTokReentrantTest, DelimitersShouldNotBeIncludedInToken) { 114 char src[] = "__ab__:_cd__:__ef__:__"; 115 char *reserve = nullptr; 116 char *token = __llvm_libc::strtok_r(src, "_:", &reserve); 117 ASSERT_STREQ(token, "ab"); 118 token = __llvm_libc::strtok_r(nullptr, ":_", &reserve); 119 ASSERT_STREQ(token, "cd"); 120 token = __llvm_libc::strtok_r(nullptr, "_:,", &reserve); 121 ASSERT_STREQ(token, "ef"); 122 token = __llvm_libc::strtok_r(nullptr, "_:,_", &reserve); 123 ASSERT_STREQ(token, nullptr); 124 } 125