1// Copyright 2017 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <fbl/string_buffer.h>
6
7#include <unittest/unittest.h>
8
9#define EXPECT_DATA_AND_LENGTH(expected, actual)      \
10    do {                                              \
11        EXPECT_STR_EQ(expected, actual.data());      \
12        EXPECT_EQ(strlen(expected), actual.length()); \
13    } while (false)
14
15namespace {
16
17// Note: |runnable| can't be a reference since that'd make the behavior of
18// |va_start()| undefined.
19template <typename Runnable>
20void VAListHelper(Runnable runnable, ...) {
21    va_list ap;
22    va_start(ap, runnable);
23    runnable(ap);
24    va_end(ap);
25}
26
27bool capacity_test() {
28    BEGIN_TEST;
29
30    {
31        fbl::StringBuffer<0u> buf;
32        EXPECT_EQ(0u, buf.capacity());
33    }
34
35    {
36        fbl::StringBuffer<100u> buf;
37        EXPECT_EQ(100u, buf.capacity());
38    }
39
40    END_TEST;
41}
42
43bool empty_string_test() {
44    BEGIN_TEST;
45
46    {
47        fbl::StringBuffer<0u> empty;
48
49        EXPECT_STR_EQ("", empty.data());
50        EXPECT_STR_EQ("", empty.c_str());
51
52        EXPECT_EQ(0u, empty.length());
53        EXPECT_EQ(0u, empty.size());
54        EXPECT_TRUE(empty.empty());
55        EXPECT_EQ(0u, empty.capacity());
56
57        EXPECT_STR_EQ("", empty.begin());
58        EXPECT_EQ(0u, empty.end() - empty.begin());
59        EXPECT_STR_EQ("", empty.cbegin());
60        EXPECT_EQ(0u, empty.cend() - empty.cbegin());
61
62        EXPECT_EQ(0, empty[0u]);
63    }
64
65    {
66        fbl::StringBuffer<16u> empty;
67
68        EXPECT_STR_EQ("", empty.data());
69        EXPECT_STR_EQ("", empty.c_str());
70
71        EXPECT_EQ(0u, empty.length());
72        EXPECT_EQ(0u, empty.size());
73        EXPECT_TRUE(empty.empty());
74        EXPECT_EQ(16u, empty.capacity());
75
76        EXPECT_STR_EQ("", empty.begin());
77        EXPECT_EQ(0u, empty.end() - empty.begin());
78        EXPECT_STR_EQ("", empty.cbegin());
79        EXPECT_EQ(0u, empty.cend() - empty.cbegin());
80
81        EXPECT_EQ(0, empty[0u]);
82    }
83
84    END_TEST;
85}
86
87bool append_test() {
88    BEGIN_TEST;
89
90    {
91        fbl::StringBuffer<16u> str;
92        str.Append('a')
93            .Append('b')
94            .Append("cd")
95            .Append("efghi", 3u)
96            .Append(fbl::StringPiece("hijkl", 3u))
97            .Append(fbl::String("klmnopqrstuvwxyz"))
98            .Append('z') // these will be truncated away
99            .Append("zz")
100            .Append("zzzzzz", 3u)
101            .Append(fbl::StringPiece("zzzzz", 3u))
102            .Append(fbl::String("zzzzz"));
103
104        EXPECT_STR_EQ("abcdefghijklmnop", str.data());
105        EXPECT_STR_EQ("abcdefghijklmnop", str.c_str());
106
107        EXPECT_EQ(16u, str.length());
108        EXPECT_EQ(16u, str.size());
109        EXPECT_FALSE(str.empty());
110        EXPECT_EQ(16u, str.capacity());
111
112        EXPECT_STR_EQ("abcdefghijklmnop", str.begin());
113        EXPECT_EQ(16u, str.end() - str.begin());
114        EXPECT_STR_EQ("abcdefghijklmnop", str.cbegin());
115        EXPECT_EQ(16u, str.cend() - str.cbegin());
116
117        EXPECT_EQ('b', str[1u]);
118    }
119
120    {
121        fbl::StringBuffer<3u> str;
122        str.Append('a');
123        EXPECT_DATA_AND_LENGTH("a", str);
124        str.Append('b');
125        EXPECT_DATA_AND_LENGTH("ab", str);
126        str.Append('c');
127        EXPECT_DATA_AND_LENGTH("abc", str);
128        str.Append('d');
129        EXPECT_DATA_AND_LENGTH("abc", str);
130    }
131
132    {
133        fbl::StringBuffer<3u> str;
134        str.Append("ab");
135        EXPECT_DATA_AND_LENGTH("ab", str);
136        str.Append("");
137        EXPECT_DATA_AND_LENGTH("ab", str);
138        str.Append("cdefg");
139        EXPECT_DATA_AND_LENGTH("abc", str);
140    }
141
142    {
143        fbl::StringBuffer<3u> str;
144        str.Append("abcdef", 2u);
145        EXPECT_DATA_AND_LENGTH("ab", str);
146        str.Append("zzzz", 0u);
147        EXPECT_DATA_AND_LENGTH("ab", str);
148        str.Append("cdefghijk", 5u);
149        EXPECT_DATA_AND_LENGTH("abc", str);
150    }
151
152    {
153        fbl::StringBuffer<3u> str;
154        str.Append(fbl::StringPiece("abcdef", 2u));
155        EXPECT_DATA_AND_LENGTH("ab", str);
156        str.Append(fbl::StringPiece("zzzz", 0u));
157        EXPECT_DATA_AND_LENGTH("ab", str);
158        str.Append(fbl::StringPiece("cdefghijk", 5u));
159        EXPECT_DATA_AND_LENGTH("abc", str);
160    }
161
162    {
163        fbl::StringBuffer<3u> str;
164        str.Append(fbl::String("ab"));
165        EXPECT_DATA_AND_LENGTH("ab", str);
166        str.Append(fbl::String());
167        EXPECT_DATA_AND_LENGTH("ab", str);
168        str.Append(fbl::String("cdefg"));
169        EXPECT_DATA_AND_LENGTH("abc", str);
170    }
171
172    END_TEST;
173}
174
175bool append_printf_test() {
176    BEGIN_TEST;
177
178    {
179        fbl::StringBuffer<12u> str;
180        str.AppendPrintf("abc");
181        EXPECT_DATA_AND_LENGTH("abc", str);
182        str.AppendPrintf("%d,%s", 20, "de").Append('f');
183        EXPECT_DATA_AND_LENGTH("abc20,def", str);
184        str.AppendPrintf("%d", 123456789);
185        EXPECT_DATA_AND_LENGTH("abc20,def123", str);
186    }
187
188    {
189        fbl::StringBuffer<12u> str;
190        VAListHelper([&str](va_list ap) { str.AppendVPrintf("abc", ap); });
191        EXPECT_DATA_AND_LENGTH("abc", str);
192        VAListHelper([&str](va_list ap) { str.AppendVPrintf("%d,%s", ap).Append('f'); },
193                     20, "de");
194        EXPECT_DATA_AND_LENGTH("abc20,def", str);
195        VAListHelper([&str](va_list ap) { str.AppendVPrintf("%d", ap); }, 123456789);
196        EXPECT_DATA_AND_LENGTH("abc20,def123", str);
197    }
198
199    END_TEST;
200}
201
202bool modify_test() {
203    BEGIN_TEST;
204
205    {
206        fbl::StringBuffer<16u> str;
207        str.Append("abcdef");
208
209        EXPECT_EQ('c', str[2u]);
210        str[2u] = 'x';
211        EXPECT_EQ('x', str[2u]);
212        EXPECT_DATA_AND_LENGTH("abxdef", str);
213
214        memcpy(str.data(), "yyyy", 4u);
215        EXPECT_DATA_AND_LENGTH("yyyyef", str);
216    }
217
218    END_TEST;
219}
220
221bool resize_test() {
222    BEGIN_TEST;
223
224    {
225        fbl::StringBuffer<16u> str;
226
227        str.Resize(4u, 'x');
228        EXPECT_STR_EQ("xxxx", str.data());
229        EXPECT_EQ(4u, str.length());
230
231        str.Resize(8u, 'y');
232        EXPECT_STR_EQ("xxxxyyyy", str.data());
233        EXPECT_EQ(8u, str.length());
234
235        str.Resize(16u);
236        EXPECT_STR_EQ("xxxxyyyy", str.data());
237        EXPECT_EQ(0, memcmp("xxxxyyyy\0\0\0\0\0\0\0\0\0", str.data(), str.length() + 1));
238        EXPECT_EQ(16u, str.length());
239
240        str.Resize(0u);
241        EXPECT_STR_EQ("", str.data());
242        EXPECT_EQ(0u, str.length());
243    }
244
245    END_TEST;
246}
247
248bool clear_test() {
249    BEGIN_TEST;
250
251    {
252        fbl::StringBuffer<16u> str;
253        str.Append("abcdef");
254
255        str.Clear();
256        EXPECT_STR_EQ("", str.data());
257        EXPECT_EQ(0u, str.length());
258    }
259
260    END_TEST;
261}
262
263bool to_string_test() {
264    BEGIN_TEST;
265
266    {
267        fbl::StringBuffer<16u> buf;
268        buf.Append("abcdef");
269
270        fbl::String str = buf.ToString();
271        EXPECT_TRUE(str == "abcdef");
272    }
273
274    END_TEST;
275}
276
277bool to_string_piece_test() {
278    BEGIN_TEST;
279
280    {
281        fbl::StringBuffer<16u> buf;
282        buf.Append("abcdef");
283
284        fbl::StringPiece piece = buf.ToStringPiece();
285        EXPECT_EQ(buf.data(), piece.data());
286        EXPECT_EQ(buf.length(), piece.length());
287    }
288
289    END_TEST;
290}
291
292} // namespace
293
294BEGIN_TEST_CASE(string_buffer_tests)
295RUN_TEST(capacity_test)
296RUN_TEST(empty_string_test)
297RUN_TEST(append_test)
298RUN_TEST(append_printf_test)
299RUN_TEST(modify_test)
300RUN_TEST(resize_test)
301RUN_TEST(clear_test)
302RUN_TEST(to_string_test)
303RUN_TEST(to_string_piece_test)
304END_TEST_CASE(string_buffer_tests)
305