xref: /llvm-project/libc/test/src/string/strtok_r_test.cpp (revision b6bc9d72f65a5086f310f321e969d96e9a559e75)
1bc45bab7Sparallels //===-- Unittests for strtok_r -------------------------------------------===//
2bc45bab7Sparallels //
3bc45bab7Sparallels // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bc45bab7Sparallels // See https://llvm.org/LICENSE.txt for license information.
5bc45bab7Sparallels // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bc45bab7Sparallels //
7bc45bab7Sparallels //===----------------------------------------------------------------------===//
8bc45bab7Sparallels 
9bc45bab7Sparallels #include "src/string/strtok_r.h"
10af1315c2SSiva Chandra Reddy #include "test/UnitTest/Test.h"
11bc45bab7Sparallels 
TEST(LlvmLibcStrTokReentrantTest,NoTokenFound)121df0dbfcSMichael Jones TEST(LlvmLibcStrTokReentrantTest, NoTokenFound) {
13bc45bab7Sparallels   { // Empty source and delimiter string.
14bc45bab7Sparallels     char empty[] = "";
15bc45bab7Sparallels     char *reserve = nullptr;
16*b6bc9d72SGuillaume Chatelet     ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(empty, "", &reserve), nullptr);
17bc45bab7Sparallels     // Another call to ensure that 'reserve' is not in a bad state.
18*b6bc9d72SGuillaume Chatelet     ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(empty, "", &reserve), nullptr);
19*b6bc9d72SGuillaume Chatelet     ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(nullptr, "", &reserve), nullptr);
20bc45bab7Sparallels   }
21bc45bab7Sparallels   { // Empty source and single character delimiter string.
22bc45bab7Sparallels     char empty[] = "";
23bc45bab7Sparallels     char *reserve = nullptr;
24*b6bc9d72SGuillaume Chatelet     ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(empty, "_", &reserve), nullptr);
25bc45bab7Sparallels     // Another call to ensure that 'reserve' is not in a bad state.
26*b6bc9d72SGuillaume Chatelet     ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(empty, "_", &reserve), nullptr);
27*b6bc9d72SGuillaume Chatelet     ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(nullptr, "_", &reserve), nullptr);
28bc45bab7Sparallels   }
29bc45bab7Sparallels   { // Same character source and delimiter string.
30bc45bab7Sparallels     char single[] = "_";
31bc45bab7Sparallels     char *reserve = nullptr;
32*b6bc9d72SGuillaume Chatelet     ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(single, "_", &reserve), nullptr);
33bc45bab7Sparallels     // Another call to ensure that 'reserve' is not in a bad state.
34*b6bc9d72SGuillaume Chatelet     ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(single, "_", &reserve), nullptr);
35*b6bc9d72SGuillaume Chatelet     ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(nullptr, "_", &reserve), nullptr);
36bc45bab7Sparallels   }
37bc45bab7Sparallels   { // Multiple character source and single character delimiter string.
38bc45bab7Sparallels     char multiple[] = "1,2";
39bc45bab7Sparallels     char *reserve = nullptr;
40*b6bc9d72SGuillaume Chatelet     ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(multiple, ":", &reserve), "1,2");
41bc45bab7Sparallels     // Another call to ensure that 'reserve' is not in a bad state.
42*b6bc9d72SGuillaume Chatelet     ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(multiple, ":", &reserve), "1,2");
43*b6bc9d72SGuillaume Chatelet     ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(nullptr, ":", &reserve), nullptr);
44bc45bab7Sparallels   }
45bc45bab7Sparallels }
46bc45bab7Sparallels 
TEST(LlvmLibcStrTokReentrantTest,DelimiterAsFirstCharacterShouldBeIgnored)471df0dbfcSMichael Jones TEST(LlvmLibcStrTokReentrantTest, DelimiterAsFirstCharacterShouldBeIgnored) {
48bc45bab7Sparallels   char src[] = ".123";
49bc45bab7Sparallels   char *reserve = nullptr;
50*b6bc9d72SGuillaume Chatelet   ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(src, ".", &reserve), "123");
51bc45bab7Sparallels   // Another call to ensure that 'reserve' is not in a bad state.
52*b6bc9d72SGuillaume Chatelet   ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(src, ".", &reserve), "123");
53*b6bc9d72SGuillaume Chatelet   ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(nullptr, ".", &reserve), nullptr);
54bc45bab7Sparallels }
55bc45bab7Sparallels 
TEST(LlvmLibcStrTokReentrantTest,DelimiterIsMiddleCharacter)561df0dbfcSMichael Jones TEST(LlvmLibcStrTokReentrantTest, DelimiterIsMiddleCharacter) {
57bc45bab7Sparallels   char src[] = "12,34";
58bc45bab7Sparallels   char *reserve = nullptr;
59*b6bc9d72SGuillaume Chatelet   ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(src, ",", &reserve), "12");
60bc45bab7Sparallels   // Another call to ensure that 'reserve' is not in a bad state.
61*b6bc9d72SGuillaume Chatelet   ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(src, ",", &reserve), "12");
62*b6bc9d72SGuillaume Chatelet   ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(nullptr, ",", &reserve), nullptr);
63bc45bab7Sparallels }
64bc45bab7Sparallels 
TEST(LlvmLibcStrTokReentrantTest,DelimiterAsLastCharacterShouldBeIgnored)651df0dbfcSMichael Jones TEST(LlvmLibcStrTokReentrantTest, DelimiterAsLastCharacterShouldBeIgnored) {
66bc45bab7Sparallels   char src[] = "1234:";
67bc45bab7Sparallels   char *reserve = nullptr;
68*b6bc9d72SGuillaume Chatelet   ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(src, ":", &reserve), "1234");
69bc45bab7Sparallels   // Another call to ensure that 'reserve' is not in a bad state.
70*b6bc9d72SGuillaume Chatelet   ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(src, ":", &reserve), "1234");
71*b6bc9d72SGuillaume Chatelet   ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(nullptr, ":", &reserve), nullptr);
72bc45bab7Sparallels }
73bc45bab7Sparallels 
TEST(LlvmLibcStrTokReentrantTest,ShouldNotGoPastNullTerminator)741df0dbfcSMichael Jones TEST(LlvmLibcStrTokReentrantTest, ShouldNotGoPastNullTerminator) {
75bc45bab7Sparallels   char src[] = {'1', '2', '\0', ',', '3'};
76bc45bab7Sparallels   char *reserve = nullptr;
77*b6bc9d72SGuillaume Chatelet   ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(src, ",", &reserve), "12");
78bc45bab7Sparallels   // Another call to ensure that 'reserve' is not in a bad state.
79*b6bc9d72SGuillaume Chatelet   ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(src, ",", &reserve), "12");
80*b6bc9d72SGuillaume Chatelet   ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(nullptr, ",", &reserve), nullptr);
81bc45bab7Sparallels }
82bc45bab7Sparallels 
TEST(LlvmLibcStrTokReentrantTest,ShouldReturnNullptrWhenBothSrcAndSaveptrAreNull)831df0dbfcSMichael Jones TEST(LlvmLibcStrTokReentrantTest,
840784e62cSAlfonso Gregory      ShouldReturnNullptrWhenBothSrcAndSaveptrAreNull) {
850784e62cSAlfonso Gregory   char *src = nullptr;
860784e62cSAlfonso Gregory   char *reserve = nullptr;
870784e62cSAlfonso Gregory   // Ensure that instead of crashing if src and reserve are null, nullptr is
880784e62cSAlfonso Gregory   // returned
89*b6bc9d72SGuillaume Chatelet   ASSERT_STREQ(LIBC_NAMESPACE::strtok_r(src, ",", &reserve), nullptr);
900784e62cSAlfonso Gregory   // And that neither src nor reserve are changed when that happens
910784e62cSAlfonso Gregory   ASSERT_STREQ(src, nullptr);
920784e62cSAlfonso Gregory   ASSERT_STREQ(reserve, nullptr);
930784e62cSAlfonso Gregory }
940784e62cSAlfonso Gregory 
TEST(LlvmLibcStrTokReentrantTest,SubsequentCallsShouldFindFollowingDelimiters)950784e62cSAlfonso Gregory TEST(LlvmLibcStrTokReentrantTest,
961df0dbfcSMichael Jones      SubsequentCallsShouldFindFollowingDelimiters) {
97bc45bab7Sparallels   char src[] = "12,34.56";
98bc45bab7Sparallels   char *reserve = nullptr;
99*b6bc9d72SGuillaume Chatelet   char *token = LIBC_NAMESPACE::strtok_r(src, ",.", &reserve);
100bc45bab7Sparallels   ASSERT_STREQ(token, "12");
101*b6bc9d72SGuillaume Chatelet   token = LIBC_NAMESPACE::strtok_r(nullptr, ",.", &reserve);
102bc45bab7Sparallels   ASSERT_STREQ(token, "34");
103*b6bc9d72SGuillaume Chatelet   token = LIBC_NAMESPACE::strtok_r(nullptr, ",.", &reserve);
104bc45bab7Sparallels   ASSERT_STREQ(token, "56");
105*b6bc9d72SGuillaume Chatelet   token = LIBC_NAMESPACE::strtok_r(nullptr, "_:,_", &reserve);
106bc45bab7Sparallels   ASSERT_STREQ(token, nullptr);
107bc45bab7Sparallels   // Subsequent calls after hitting the end of the string should also return
108bc45bab7Sparallels   // nullptr.
109*b6bc9d72SGuillaume Chatelet   token = LIBC_NAMESPACE::strtok_r(nullptr, "_:,_", &reserve);
110bc45bab7Sparallels   ASSERT_STREQ(token, nullptr);
111bc45bab7Sparallels }
112bc45bab7Sparallels 
TEST(LlvmLibcStrTokReentrantTest,DelimitersShouldNotBeIncludedInToken)1131df0dbfcSMichael Jones TEST(LlvmLibcStrTokReentrantTest, DelimitersShouldNotBeIncludedInToken) {
114bc45bab7Sparallels   char src[] = "__ab__:_cd__:__ef__:__";
115bc45bab7Sparallels   char *reserve = nullptr;
116*b6bc9d72SGuillaume Chatelet   char *token = LIBC_NAMESPACE::strtok_r(src, "_:", &reserve);
117bc45bab7Sparallels   ASSERT_STREQ(token, "ab");
118*b6bc9d72SGuillaume Chatelet   token = LIBC_NAMESPACE::strtok_r(nullptr, ":_", &reserve);
119bc45bab7Sparallels   ASSERT_STREQ(token, "cd");
120*b6bc9d72SGuillaume Chatelet   token = LIBC_NAMESPACE::strtok_r(nullptr, "_:,", &reserve);
121bc45bab7Sparallels   ASSERT_STREQ(token, "ef");
122*b6bc9d72SGuillaume Chatelet   token = LIBC_NAMESPACE::strtok_r(nullptr, "_:,_", &reserve);
123bc45bab7Sparallels   ASSERT_STREQ(token, nullptr);
124bc45bab7Sparallels }
125