1 | //===----------------------------------------------------------------------===// |
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 | // UNSUPPORTED: c++03, c++11, c++14, c++17 |
10 | // UNSUPPORTED: no-localization |
11 | // UNSUPPORTED: libcpp-has-no-experimental-syncstream |
12 | |
13 | // <syncstream> |
14 | |
15 | // template <class charT, class traits, class Allocator> |
16 | // class basic_syncbuf; |
17 | |
18 | // void swap(basic_syncbuf& other) noexcept; |
19 | |
20 | #include <syncstream> |
21 | #include <sstream> |
22 | #include <cassert> |
23 | |
24 | #include "test_macros.h" |
25 | |
26 | #include <iostream> |
27 | |
28 | template <class CharT> |
29 | static void test_basic() { |
30 | std::basic_stringbuf<CharT> sstr1; |
31 | std::basic_stringbuf<CharT> sstr2; |
32 | std::basic_string<CharT> expected(42, CharT('*')); // a long string |
33 | |
34 | { |
35 | std::basic_syncbuf<CharT> sync_buf1(&sstr1); |
36 | sync_buf1.sputc(CharT('A')); // a short string |
37 | |
38 | std::basic_syncbuf<CharT> sync_buf2(&sstr2); |
39 | sync_buf2.sputn(expected.data(), expected.size()); |
40 | |
41 | #if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS) |
42 | assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&sstr1) == 1); |
43 | assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&sstr2) == 1); |
44 | #endif |
45 | |
46 | sync_buf1.swap(sync_buf2); |
47 | assert(sync_buf1.get_wrapped() == &sstr2); |
48 | assert(sync_buf2.get_wrapped() == &sstr1); |
49 | |
50 | assert(sstr1.str().empty()); |
51 | assert(sstr2.str().empty()); |
52 | |
53 | #if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_THREADS) |
54 | assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&sstr1) == 1); |
55 | assert(std::__wrapped_streambuf_mutex::__instance().__get_count(&sstr2) == 1); |
56 | #endif |
57 | } |
58 | |
59 | assert(sstr1.str().size() == 1); |
60 | assert(sstr1.str()[0] == CharT('A')); |
61 | assert(sstr2.str() == expected); |
62 | } |
63 | |
64 | template <class CharT> |
65 | static void test_short_write_after_swap() { |
66 | std::basic_stringbuf<CharT> sstr1; |
67 | std::basic_stringbuf<CharT> sstr2; |
68 | std::basic_string<CharT> expected(42, CharT('*')); // a long string |
69 | |
70 | { |
71 | std::basic_syncbuf<CharT> sync_buf1(&sstr1); |
72 | sync_buf1.sputc(CharT('A')); // a short string |
73 | |
74 | std::basic_syncbuf<CharT> sync_buf2(&sstr2); |
75 | sync_buf2.sputn(expected.data(), expected.size()); |
76 | |
77 | sync_buf1.swap(sync_buf2); |
78 | sync_buf1.sputc(CharT('B')); |
79 | expected.push_back(CharT('B')); |
80 | sync_buf2.sputc(CharT('Z')); |
81 | |
82 | assert(sstr1.str().empty()); |
83 | assert(sstr2.str().empty()); |
84 | } |
85 | |
86 | assert(sstr1.str().size() == 2); |
87 | assert(sstr1.str()[0] == CharT('A')); |
88 | assert(sstr1.str()[1] == CharT('Z')); |
89 | assert(sstr2.str() == expected); |
90 | } |
91 | |
92 | template <class CharT> |
93 | static void test_long_write_after_swap() { |
94 | std::basic_stringbuf<CharT> sstr1; |
95 | std::basic_stringbuf<CharT> sstr2; |
96 | std::basic_string<CharT> expected(42, CharT('*')); // a long string |
97 | |
98 | { |
99 | std::basic_syncbuf<CharT> sync_buf1(&sstr1); |
100 | sync_buf1.sputc(CharT('A')); // a short string |
101 | |
102 | std::basic_syncbuf<CharT> sync_buf2(&sstr2); |
103 | sync_buf2.sputn(expected.data(), expected.size()); |
104 | |
105 | sync_buf1.swap(sync_buf2); |
106 | sync_buf1.sputn(expected.data(), expected.size()); |
107 | sync_buf2.sputn(expected.data(), expected.size()); |
108 | |
109 | assert(sstr1.str().empty()); |
110 | assert(sstr2.str().empty()); |
111 | } |
112 | |
113 | assert(sstr1.str().size() == 1 + expected.size()); |
114 | assert(sstr1.str()[0] == CharT('A')); |
115 | assert(sstr1.str().substr(1) == expected); |
116 | assert(sstr2.str() == expected + expected); |
117 | } |
118 | |
119 | template <class CharT> |
120 | static void test_emit_on_sync() { |
121 | { // false false |
122 | |
123 | std::basic_stringbuf<CharT> sstr1; |
124 | std::basic_stringbuf<CharT> sstr2; |
125 | std::basic_string<CharT> expected(42, CharT('*')); // a long string |
126 | |
127 | { |
128 | std::basic_syncbuf<CharT> sync_buf1(&sstr1); |
129 | sync_buf1.set_emit_on_sync(false); |
130 | sync_buf1.sputc(CharT('A')); // a short string |
131 | |
132 | std::basic_syncbuf<CharT> sync_buf2(&sstr2); |
133 | sync_buf2.set_emit_on_sync(false); |
134 | sync_buf2.sputn(expected.data(), expected.size()); |
135 | |
136 | sync_buf1.swap(sync_buf2); |
137 | |
138 | assert(sstr1.str().empty()); |
139 | assert(sstr2.str().empty()); |
140 | |
141 | sync_buf1.pubsync(); |
142 | assert(sstr1.str().empty()); |
143 | assert(sstr2.str().empty()); |
144 | |
145 | sync_buf2.pubsync(); |
146 | assert(sstr1.str().empty()); |
147 | assert(sstr2.str().empty()); |
148 | } |
149 | |
150 | assert(sstr1.str().size() == 1); |
151 | assert(sstr1.str()[0] == CharT('A')); |
152 | assert(sstr2.str() == expected); |
153 | } |
154 | |
155 | { // false true |
156 | |
157 | std::basic_stringbuf<CharT> sstr1; |
158 | std::basic_stringbuf<CharT> sstr2; |
159 | std::basic_string<CharT> expected(42, CharT('*')); // a long string |
160 | |
161 | { |
162 | std::basic_syncbuf<CharT> sync_buf1(&sstr1); |
163 | sync_buf1.set_emit_on_sync(true); |
164 | sync_buf1.sputc(CharT('A')); // a short string |
165 | |
166 | std::basic_syncbuf<CharT> sync_buf2(&sstr2); |
167 | sync_buf2.set_emit_on_sync(false); |
168 | sync_buf2.sputn(expected.data(), expected.size()); |
169 | |
170 | sync_buf1.swap(sync_buf2); |
171 | |
172 | assert(sstr1.str().empty()); |
173 | assert(sstr2.str().empty()); |
174 | |
175 | sync_buf1.pubsync(); |
176 | assert(sstr1.str().empty()); |
177 | assert(sstr2.str().empty()); |
178 | |
179 | sync_buf2.pubsync(); |
180 | assert(sstr1.str().size() == 1); |
181 | assert(sstr1.str()[0] == CharT('A')); |
182 | assert(sstr2.str().empty()); |
183 | } |
184 | |
185 | assert(sstr1.str().size() == 1); |
186 | assert(sstr1.str()[0] == CharT('A')); |
187 | assert(sstr2.str() == expected); |
188 | } |
189 | |
190 | { // true false |
191 | |
192 | std::basic_stringbuf<CharT> sstr1; |
193 | std::basic_stringbuf<CharT> sstr2; |
194 | std::basic_string<CharT> expected(42, CharT('*')); // a long string |
195 | |
196 | { |
197 | std::basic_syncbuf<CharT> sync_buf1(&sstr1); |
198 | sync_buf1.set_emit_on_sync(false); |
199 | sync_buf1.sputc(CharT('A')); // a short string |
200 | |
201 | std::basic_syncbuf<CharT> sync_buf2(&sstr2); |
202 | sync_buf2.set_emit_on_sync(true); |
203 | sync_buf2.sputn(expected.data(), expected.size()); |
204 | |
205 | sync_buf1.swap(sync_buf2); |
206 | |
207 | assert(sstr1.str().empty()); |
208 | assert(sstr2.str().empty()); |
209 | |
210 | sync_buf1.pubsync(); |
211 | assert(sstr1.str().empty()); |
212 | assert(sstr2.str() == expected); |
213 | |
214 | sync_buf2.pubsync(); |
215 | assert(sstr1.str().empty()); |
216 | assert(sstr2.str() == expected); |
217 | } |
218 | |
219 | assert(sstr1.str().size() == 1); |
220 | assert(sstr1.str()[0] == CharT('A')); |
221 | assert(sstr2.str() == expected); |
222 | } |
223 | |
224 | { // true true |
225 | |
226 | std::basic_stringbuf<CharT> sstr1; |
227 | std::basic_stringbuf<CharT> sstr2; |
228 | std::basic_string<CharT> expected(42, CharT('*')); // a long string |
229 | |
230 | { |
231 | std::basic_syncbuf<CharT> sync_buf1(&sstr1); |
232 | sync_buf1.set_emit_on_sync(true); |
233 | sync_buf1.sputc(CharT('A')); // a short string |
234 | |
235 | std::basic_syncbuf<CharT> sync_buf2(&sstr2); |
236 | sync_buf2.set_emit_on_sync(true); |
237 | sync_buf2.sputn(expected.data(), expected.size()); |
238 | |
239 | sync_buf1.swap(sync_buf2); |
240 | |
241 | assert(sstr1.str().empty()); |
242 | assert(sstr2.str().empty()); |
243 | |
244 | sync_buf1.pubsync(); |
245 | assert(sstr1.str().empty()); |
246 | assert(sstr2.str() == expected); |
247 | |
248 | sync_buf2.pubsync(); |
249 | assert(sstr1.str().size() == 1); |
250 | assert(sstr1.str()[0] == CharT('A')); |
251 | assert(sstr2.str() == expected); |
252 | } |
253 | |
254 | assert(sstr1.str().size() == 1); |
255 | assert(sstr1.str()[0] == CharT('A')); |
256 | assert(sstr2.str() == expected); |
257 | } |
258 | } |
259 | |
260 | template <class CharT> |
261 | static void test() { |
262 | test_basic<CharT>(); |
263 | test_emit_on_sync<CharT>(); |
264 | test_short_write_after_swap<CharT>(); |
265 | test_long_write_after_swap<CharT>(); |
266 | } |
267 | |
268 | int main(int, char**) { |
269 | test<char>(); |
270 | #ifndef TEST_HAS_NO_WIDE_CHARACTERS |
271 | test<wchar_t>(); |
272 | #endif |
273 | |
274 | return 0; |
275 | } |
276 | |