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 // Tests the inherited function using a custom allocator.
19 //
20 // int_type basic_streambuf<charT, traits>::sputc(char_type c);
21 //
22 // This test also validates the observable behaviour after move assignment and
23 // construction. This test uses a small so the underlying string is in short
24 // mode.
25
26 #include <array>
27 #include <syncstream>
28 #include <cassert>
29 #include <sstream>
30
31 #include "test_macros.h"
32 #include "test_allocator.h"
33
34 template <class CharT>
test()35 void test() {
36 std::array< CharT, 17> input{
37 CharT('a'),
38 CharT('1'),
39 CharT('+'),
40 CharT('A'),
41 CharT('g'),
42 CharT('0'),
43 CharT('@'),
44 CharT('Z'),
45 CharT('q'),
46 CharT('8'),
47 CharT('#'),
48 CharT('D'),
49 CharT('t'),
50 CharT('9'),
51 CharT('$'),
52 CharT('A'),
53 CharT(' ')};
54 using SyncBuf = std::basic_syncbuf<CharT, std::char_traits<CharT>, test_allocator<CharT>>;
55
56 { // Normal
57 std::basic_string<CharT> expected;
58 std::basic_stringbuf<CharT> buf;
59 test_allocator_statistics stats;
60 test_allocator<CharT> allocator{&stats};
61
62 {
63 SyncBuf sync_buf{&buf, allocator};
64 for (int i = 0; i < 1024; ++i) {
65 CharT c = input[i % input.size()];
66 expected.push_back(c);
67 typename SyncBuf::int_type ret = sync_buf.sputc(c);
68 assert(ret == typename SyncBuf::int_type(c));
69 }
70 // The synchronization happens upon destruction of sync_buf.
71 assert(buf.str().empty());
72 assert(stats.allocated_size >= 1024);
73 }
74 assert(buf.str() == expected);
75 assert(stats.allocated_size == 0);
76 }
77 { // Move construction
78 std::basic_stringbuf<CharT> buf;
79 test_allocator_statistics stats;
80 test_allocator<CharT> allocator{&stats};
81
82 {
83 SyncBuf sync_buf{&buf, allocator};
84 CharT c = CharT('4');
85 typename SyncBuf::int_type ret = sync_buf.sputc(c);
86 assert(ret == typename SyncBuf::int_type(c));
87
88 {
89 c = CharT('2');
90
91 SyncBuf new_sync_buf{std::move(sync_buf)};
92 ret = new_sync_buf.sputc(c);
93 assert(ret == typename SyncBuf::int_type(c));
94
95 // The synchronization happens upon destruction of new_sync_buf.
96 assert(buf.str().empty());
97 assert(stats.allocated_size >= 2);
98 }
99 assert(buf.str().size() == 2);
100 assert(buf.str()[0] == CharT('4'));
101 assert(buf.str()[1] == CharT('2'));
102 assert(stats.allocated_size == 0);
103 }
104 assert(buf.str().size() == 2);
105 assert(buf.str()[0] == CharT('4'));
106 assert(buf.str()[1] == CharT('2'));
107 assert(stats.allocated_size == 0);
108 }
109 { // Move assignment non-propagating allocator
110 std::basic_stringbuf<CharT> buf;
111 test_allocator_statistics stats;
112 test_allocator<CharT> allocator{&stats};
113 static_assert(!std::allocator_traits<test_allocator<CharT>>::propagate_on_container_move_assignment::value);
114
115 {
116 SyncBuf sync_buf{&buf, allocator};
117 CharT c = CharT('4');
118 typename SyncBuf::int_type ret = sync_buf.sputc(c);
119 assert(ret == typename SyncBuf::int_type(c));
120
121 {
122 c = CharT('2');
123
124 SyncBuf new_sync_buf;
125 test_allocator<CharT> a = new_sync_buf.get_allocator();
126 new_sync_buf = std::move(sync_buf);
127 assert(new_sync_buf.get_allocator() == a);
128
129 ret = new_sync_buf.sputc(c);
130 assert(ret == typename SyncBuf::int_type(c));
131
132 // The synchronization happens upon destruction of new_sync_buf.
133 assert(buf.str().empty());
134 }
135 assert(buf.str().size() == 2);
136 assert(buf.str()[0] == CharT('4'));
137 assert(buf.str()[1] == CharT('2'));
138 }
139 assert(buf.str().size() == 2);
140 assert(buf.str()[0] == CharT('4'));
141 assert(buf.str()[1] == CharT('2'));
142 }
143 }
144
main(int,char **)145 int main(int, char**) {
146 test<char>();
147 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
148 test<wchar_t>();
149 #endif
150 return 0;
151 }
152