276 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++1710// UNSUPPORTED: no-localization11// UNSUPPORTED: libcpp-has-no-experimental-syncstream12 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 28template <class CharT>29static 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 string33 34 {35 std::basic_syncbuf<CharT> sync_buf1(&sstr1);36 sync_buf1.sputc(CharT('A')); // a short string37 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#endif45 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#endif57 }58 59 assert(sstr1.str().size() == 1);60 assert(sstr1.str()[0] == CharT('A'));61 assert(sstr2.str() == expected);62}63 64template <class CharT>65static 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 string69 70 {71 std::basic_syncbuf<CharT> sync_buf1(&sstr1);72 sync_buf1.sputc(CharT('A')); // a short string73 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 92template <class CharT>93static 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 string97 98 {99 std::basic_syncbuf<CharT> sync_buf1(&sstr1);100 sync_buf1.sputc(CharT('A')); // a short string101 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 119template <class CharT>120static void test_emit_on_sync() {121 { // false false122 123 std::basic_stringbuf<CharT> sstr1;124 std::basic_stringbuf<CharT> sstr2;125 std::basic_string<CharT> expected(42, CharT('*')); // a long string126 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 string131 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 true156 157 std::basic_stringbuf<CharT> sstr1;158 std::basic_stringbuf<CharT> sstr2;159 std::basic_string<CharT> expected(42, CharT('*')); // a long string160 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 string165 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 false191 192 std::basic_stringbuf<CharT> sstr1;193 std::basic_stringbuf<CharT> sstr2;194 std::basic_string<CharT> expected(42, CharT('*')); // a long string195 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 string200 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 true225 226 std::basic_stringbuf<CharT> sstr1;227 std::basic_stringbuf<CharT> sstr2;228 std::basic_string<CharT> expected(42, CharT('*')); // a long string229 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 string234 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 260template <class CharT>261static 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 268int main(int, char**) {269 test<char>();270#ifndef TEST_HAS_NO_WIDE_CHARACTERS271 test<wchar_t>();272#endif273 274 return 0;275}276