1//===-- Unittests for wcstok ----------------------------------------------===//
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 "hdr/types/size_t.h"
10#include "hdr/types/wchar_t.h"
11#include "src/wchar/wcstok.h"
12#include "test/UnitTest/Test.h"
13
14TEST(LlvmLibcWCSTokReentrantTest, NoTokenFound) {
15 { // Empty source and delimiter string.
16 wchar_t empty[] = L"";
17 wchar_t *reserve = nullptr;
18 ASSERT_EQ(LIBC_NAMESPACE::wcstok(empty, L"", &reserve), nullptr);
19 // Another call to ensure that 'reserve' is not in a bad state.
20 ASSERT_EQ(LIBC_NAMESPACE::wcstok(empty, L"", &reserve), nullptr);
21 ASSERT_EQ(LIBC_NAMESPACE::wcstok(nullptr, L"", &reserve), nullptr);
22 }
23 { // Empty source and single character delimiter string.
24 wchar_t empty[] = L"";
25 wchar_t *reserve = nullptr;
26 ASSERT_EQ(LIBC_NAMESPACE::wcstok(empty, L"_", &reserve), nullptr);
27 // Another call to ensure that 'reserve' is not in a bad state.
28 ASSERT_EQ(LIBC_NAMESPACE::wcstok(empty, L"_", &reserve), nullptr);
29 ASSERT_EQ(LIBC_NAMESPACE::wcstok(nullptr, L"_", &reserve), nullptr);
30 }
31 { // Same character source and delimiter string.
32 wchar_t single[] = L"_";
33 wchar_t *reserve = nullptr;
34 ASSERT_EQ(LIBC_NAMESPACE::wcstok(single, L"_", &reserve), nullptr);
35 // Another call to ensure that 'reserve' is not in a bad state.
36 ASSERT_EQ(LIBC_NAMESPACE::wcstok(single, L"_", &reserve), nullptr);
37 ASSERT_EQ(LIBC_NAMESPACE::wcstok(nullptr, L"_", &reserve), nullptr);
38 }
39 { // Multiple character source and single character delimiter string.
40 wchar_t multiple[] = L"1,2";
41 wchar_t *reserve = nullptr;
42 wchar_t *tok = LIBC_NAMESPACE::wcstok(multiple, L":", &reserve);
43 ASSERT_TRUE(tok[0] == L'1');
44 ASSERT_TRUE(tok[1] == L',');
45 ASSERT_TRUE(tok[2] == L'2');
46 ASSERT_TRUE(tok[3] == L'\0');
47 // Another call to ensure that 'reserve' is not in a bad state.
48 tok = LIBC_NAMESPACE::wcstok(multiple, L":", &reserve);
49 ASSERT_TRUE(tok[0] == L'1');
50 ASSERT_TRUE(tok[1] == L',');
51 ASSERT_TRUE(tok[2] == L'2');
52 ASSERT_TRUE(tok[3] == L'\0');
53 ASSERT_EQ(LIBC_NAMESPACE::wcstok(nullptr, L":", &reserve), nullptr);
54 }
55}
56
57TEST(LlvmLibcWCSTokReentrantTest, DelimiterAsFirstCharacterShouldBeIgnored) {
58 wchar_t src[] = L".123";
59 wchar_t *reserve = nullptr;
60 wchar_t *tok = LIBC_NAMESPACE::wcstok(src, L".", &reserve);
61 ASSERT_TRUE(tok[0] == L'1');
62 ASSERT_TRUE(tok[1] == L'2');
63 ASSERT_TRUE(tok[2] == L'3');
64 ASSERT_TRUE(tok[3] == L'\0');
65 // Another call to ensure that 'reserve' is not in a bad state.
66 tok = LIBC_NAMESPACE::wcstok(src, L".", &reserve);
67 ASSERT_TRUE(tok[0] == L'1');
68 ASSERT_TRUE(tok[1] == L'2');
69 ASSERT_TRUE(tok[2] == L'3');
70 ASSERT_TRUE(tok[3] == L'\0');
71 ASSERT_EQ(LIBC_NAMESPACE::wcstok(nullptr, L".", &reserve), nullptr);
72}
73
74TEST(LlvmLibcWCSTokReentrantTest, DelimiterIsMiddleCharacter) {
75 wchar_t src[] = L"12,34";
76 wchar_t *reserve = nullptr;
77 wchar_t *tok = LIBC_NAMESPACE::wcstok(src, L",", &reserve);
78 ASSERT_TRUE(tok[0] == L'1');
79 ASSERT_TRUE(tok[1] == L'2');
80 ASSERT_TRUE(tok[2] == L'\0');
81 // Another call to ensure that 'reserve' is not in a bad state.
82 tok = LIBC_NAMESPACE::wcstok(src, L",", &reserve);
83 ASSERT_TRUE(tok[0] == L'1');
84 ASSERT_TRUE(tok[1] == L'2');
85 ASSERT_TRUE(tok[2] == L'\0');
86 ASSERT_EQ(LIBC_NAMESPACE::wcstok(nullptr, L",", &reserve), nullptr);
87}
88
89TEST(LlvmLibcWCSTokReentrantTest, DelimiterAsLastCharacterShouldBeIgnored) {
90 wchar_t src[] = L"1234:";
91 wchar_t *reserve = nullptr;
92 wchar_t *tok = LIBC_NAMESPACE::wcstok(src, L":", &reserve);
93 ASSERT_TRUE(tok[0] == L'1');
94 ASSERT_TRUE(tok[1] == L'2');
95 ASSERT_TRUE(tok[2] == L'3');
96 ASSERT_TRUE(tok[3] == L'4');
97 ASSERT_TRUE(tok[4] == L'\0');
98 // Another call to ensure that 'reserve' is not in a bad state.
99 tok = LIBC_NAMESPACE::wcstok(src, L":", &reserve);
100 ASSERT_TRUE(tok[0] == L'1');
101 ASSERT_TRUE(tok[1] == L'2');
102 ASSERT_TRUE(tok[2] == L'3');
103 ASSERT_TRUE(tok[3] == L'4');
104 ASSERT_TRUE(tok[4] == L'\0');
105 ASSERT_EQ(LIBC_NAMESPACE::wcstok(nullptr, L":", &reserve), nullptr);
106}
107
108TEST(LlvmLibcWCSTokReentrantTest, ShouldNotGoPastNullTerminator) {
109 wchar_t src[] = {L'1', L'2', L'\0', L',', L'3'};
110 wchar_t *reserve = nullptr;
111 wchar_t *tok = LIBC_NAMESPACE::wcstok(src, L",", &reserve);
112 ASSERT_TRUE(tok[0] == L'1');
113 ASSERT_TRUE(tok[1] == L'2');
114 ASSERT_TRUE(tok[2] == L'\0');
115 // Another call to ensure that 'reserve' is not in a bad state.
116 tok = LIBC_NAMESPACE::wcstok(src, L",", &reserve);
117 ASSERT_TRUE(tok[0] == L'1');
118 ASSERT_TRUE(tok[1] == L'2');
119 ASSERT_TRUE(tok[2] == L'\0');
120 ASSERT_EQ(LIBC_NAMESPACE::wcstok(nullptr, L",", &reserve), nullptr);
121}
122
123TEST(LlvmLibcWCSTokReentrantTest,
124 ShouldReturnNullptrWhenBothSrcAndSaveptrAreNull) {
125 wchar_t *src = nullptr;
126 wchar_t *reserve = nullptr;
127 // Ensure that instead of crashing if src and reserve are null, nullptr is
128 // returned
129 ASSERT_EQ(LIBC_NAMESPACE::wcstok(src, L",", &reserve), nullptr);
130 // And that neither src nor reserve are changed when that happens
131 ASSERT_EQ(src, nullptr);
132 ASSERT_EQ(reserve, nullptr);
133}
134
135TEST(LlvmLibcWCSTokReentrantTest,
136 SubsequentCallsShouldFindFollowingDelimiters) {
137 wchar_t src[] = L"12,34.56";
138 wchar_t *reserve = nullptr;
139 wchar_t *token = LIBC_NAMESPACE::wcstok(src, L",.", &reserve);
140 ASSERT_TRUE(token[0] == L'1');
141 ASSERT_TRUE(token[1] == L'2');
142 ASSERT_TRUE(token[2] == L'\0');
143
144 token = LIBC_NAMESPACE::wcstok(nullptr, L",.", &reserve);
145 ASSERT_TRUE(token[0] == L'3');
146 ASSERT_TRUE(token[1] == L'4');
147 ASSERT_TRUE(token[2] == L'\0');
148
149 token = LIBC_NAMESPACE::wcstok(nullptr, L",.", &reserve);
150 ASSERT_TRUE(token[0] == L'5');
151 ASSERT_TRUE(token[1] == L'6');
152 ASSERT_TRUE(token[2] == L'\0');
153 token = LIBC_NAMESPACE::wcstok(nullptr, L"_:,_", &reserve);
154 ASSERT_EQ(token, nullptr);
155 // Subsequent calls after hitting the end of the string should also return
156 // nullptr.
157 token = LIBC_NAMESPACE::wcstok(nullptr, L"_:,_", &reserve);
158 ASSERT_EQ(token, nullptr);
159}
160
161TEST(LlvmLibcWCSTokReentrantTest, DelimitersShouldNotBeIncludedInToken) {
162 wchar_t src[] = L"__ab__:_cd__:__ef__:__";
163 wchar_t *reserve = nullptr;
164 wchar_t *token = LIBC_NAMESPACE::wcstok(src, L"_:", &reserve);
165 ASSERT_TRUE(token[0] == L'a');
166 ASSERT_TRUE(token[1] == L'b');
167 ASSERT_TRUE(token[2] == L'\0');
168
169 token = LIBC_NAMESPACE::wcstok(nullptr, L":_", &reserve);
170 ASSERT_TRUE(token[0] == L'c');
171 ASSERT_TRUE(token[1] == L'd');
172 ASSERT_TRUE(token[2] == L'\0');
173
174 token = LIBC_NAMESPACE::wcstok(nullptr, L"_:,", &reserve);
175 ASSERT_TRUE(token[0] == L'e');
176 ASSERT_TRUE(token[1] == L'f');
177 ASSERT_TRUE(token[2] == L'\0');
178
179 token = LIBC_NAMESPACE::wcstok(nullptr, L"_:,_", &reserve);
180 ASSERT_EQ(token, nullptr);
181}
182

source code of libc/test/src/wchar/wcstok_test.cpp