blob: cd9580a5092d25a8f1299f5dbf40f107b6cdc5d2 [file] [log] [blame]
William A. Kennington III3c7107f2023-06-13 15:13:50 -07001#include <stdplus/str/buf.hpp>
2#include <stdplus/str/cexpr.hpp>
3
4#include <gtest/gtest.h>
5
6namespace stdplus
7{
8
9static constexpr auto makeIncStr(std::size_t len)
10{
11 stdplus::StrBuf ret;
12 auto ptr = ret.append(len);
13 for (std::size_t i = 0; i < len; i++)
14 {
15 ptr[i] = 'A' + (i % 26);
16 }
17 return ret;
18}
19
20constexpr auto data = cexprSv<[]() { return makeIncStr(sizeof(StrBuf) + 10); }>;
William A. Kennington III3c7107f2023-06-13 15:13:50 -070021
22TEST(StrBuf, BasicInline)
23{
24 StrBuf buf;
25 EXPECT_EQ(buf.size(), 0);
26 auto old_ptr = buf.begin();
27
28 // Ensure that we inline small amounts of data only
William A. Kennington III11572d22023-07-18 14:08:17 -070029 std::copy(data.begin(), data.begin() + 4, std::back_inserter(buf));
William A. Kennington III3c7107f2023-06-13 15:13:50 -070030 EXPECT_EQ(buf.begin(), old_ptr);
31 EXPECT_EQ(buf.size(), 4);
32 EXPECT_EQ(std::string_view(data).substr(0, 4), buf);
33
34 // Ensure that the max data size inline doesn't dynamically allocate
35 constexpr std::size_t max_size = sizeof(StrBuf) - sizeof(std::size_t);
36 buf.append(max_size - 4);
37 EXPECT_EQ(buf.begin(), old_ptr);
38 EXPECT_EQ(buf.size(), max_size);
39}
40
41TEST(StrBuf, DynamicAppend)
42{
43 constexpr std::size_t seg = 15;
44
45 StrBuf buf;
46 auto old_ptr = buf.begin();
47 std::copy(data.begin(), data.begin() + seg, buf.append(seg));
48
49 // Ensure that inline -> dynamic is working
50 std::copy(data.begin() + seg, data.end(), buf.append(data.size() - seg));
51 EXPECT_NE(buf.begin(), old_ptr);
52 EXPECT_EQ(data, buf);
53 EXPECT_EQ(data.size(), buf.size());
54
55 // Ensure dynamic allocation is large enough to allow additional
56 // small appends with no reallocation
57 old_ptr = buf.begin();
58 std::copy(data.begin(), data.begin() + seg, buf.append(seg));
59 EXPECT_EQ(buf.begin(), old_ptr);
60 EXPECT_EQ(data.size() + seg, buf.size());
61 EXPECT_EQ(data.substr(0, seg), std::string_view{buf}.substr(data.size()));
62
63 // Ensure new dynamic allocations copy
64 std::copy(data.begin() + seg, data.end(), buf.append(data.size() - seg));
65 EXPECT_NE(buf.begin(), old_ptr);
66 EXPECT_EQ(data.size() << 1, buf.size());
67 EXPECT_EQ(data, std::string_view{buf}.substr(0, data.size()));
68 EXPECT_EQ(data, std::string_view{buf}.substr(data.size()));
69}
70
71TEST(StrBuf, CopiesInline)
72{
73 StrBuf buf1;
74 buf1.append(1)[0] = 'a';
75 StrBuf buf2 = buf1;
76 EXPECT_EQ(buf1, buf2);
77 buf1.append(1)[0] = 'b';
78 StrBuf buf3 = buf1;
79 EXPECT_EQ("ab", buf3);
80 EXPECT_EQ("ab", buf1);
81 EXPECT_EQ("a", buf2);
82 buf3 = buf2;
83 EXPECT_EQ("a", buf3);
84 EXPECT_EQ("ab", buf1);
85 EXPECT_EQ("a", buf2);
86}
87
88TEST(StrBuf, MoveInline)
89{
90 StrBuf buf1;
91 buf1.append(1)[0] = 'a';
92 StrBuf buf2 = std::move(buf1);
93 EXPECT_EQ("a", std::string_view{buf2});
94 buf2.append(1)[0] = 'b';
95 // NOLINTNEXTLINE(clang-analyzer-cplusplus.Move)
96 EXPECT_EQ(0, buf1.size());
97 StrBuf buf3 = buf1;
98 EXPECT_EQ(0, buf3.size());
99 buf3 = std::move(buf2);
100 // NOLINTNEXTLINE(clang-analyzer-cplusplus.Move)
101 EXPECT_EQ(0, buf2.size());
102 EXPECT_EQ("ab", std::string_view{buf3});
103}
104
105TEST(StrBuf, CopyInlToDyn)
106{
107 StrBuf buf1;
108 buf1.append(1)[0] = 'a';
109 StrBuf buf2;
110 buf2.append(sizeof(StrBuf) + 10);
111 buf2 = buf1;
112 EXPECT_EQ("a", buf2);
113}
114
115TEST(StrBuf, MoveInlToDyn)
116{
117 StrBuf buf1;
118 buf1.append(1)[0] = 'a';
119 StrBuf buf2;
120 buf2.append(sizeof(StrBuf) + 10);
121 // NOLINTNEXTLINE(clang-analyzer-cplusplus.Move)
122 buf2 = std::move(buf1);
123 EXPECT_EQ("", buf1);
124 EXPECT_EQ("a", buf2);
125}
126
127TEST(StrBuf, MoveDynToInl)
128{
129 StrBuf buf1;
130 std::copy(data.begin(), data.end(), buf1.append(data.size()));
131 StrBuf buf2;
132 buf2.append(1)[0] = 'a';
133 // NOLINTNEXTLINE(clang-analyzer-cplusplus.Move)
134 buf2 = std::move(buf1);
135 EXPECT_EQ("", buf1);
136 EXPECT_EQ(data, buf2);
137}
138
139TEST(StrBuf, MoveDynToDyn)
140{
141 StrBuf buf1;
142 std::copy(data.begin(), data.end(), buf1.append(data.size()));
143 StrBuf buf2;
144 buf2.append(data.size());
145 // NOLINTNEXTLINE(clang-analyzer-cplusplus.Move)
146 buf2 = std::move(buf1);
147 EXPECT_EQ("", buf1);
148 EXPECT_EQ(data, buf2);
149}
150
151TEST(StrBuf, CopyDynToInl)
152{
153 StrBuf buf1;
154 buf1.append(data.size());
William A. Kennington III11572d22023-07-18 14:08:17 -0700155 buf1.clear();
William A. Kennington III3c7107f2023-06-13 15:13:50 -0700156 buf1.append(1)[0] = 'a';
157 StrBuf buf2 = buf1;
158 StrBuf buf3;
159 buf3.append(1)[0] = 'b';
160 buf3 = buf1;
161 EXPECT_EQ("a", buf1);
162 EXPECT_EQ("a", buf2);
163 EXPECT_EQ("a", buf3);
164}
165
166TEST(StrBuf, CopyDynToDyn)
167{
168 StrBuf buf1;
169 std::copy(data.begin(), data.end(), buf1.append(data.size()));
170 std::copy(data.begin(), data.end(), buf1.append(data.size()));
171 StrBuf buf2 = buf1;
172 StrBuf buf3;
173 std::copy(data.begin(), data.end(), buf3.append(data.size()));
174 buf3 = buf1;
175 EXPECT_EQ(buf2, buf1);
176 EXPECT_EQ(buf3, buf1);
177 buf3.append(1)[0] = 'a';
178 buf1 = buf3;
179 EXPECT_EQ(buf3, buf1);
180}
181
182} // namespace stdplus