135 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// Tests the inherited function using a custom allocator.19//20// streamsize basic_streambuf<charT, traits>::sputc(const char_type* s, streamsize n);21//22// This test also validates the observable behaviour after move assignment and23// construction. This test uses a large buffer so the underlying string is in24// long 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 34template <class CharT>35void 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 std::basic_string<CharT> expected;55 for (int i = 0; i < 1024; ++i)56 expected.push_back(input[i % input.size()]);57 58 using SyncBuf = std::basic_syncbuf<CharT, std::char_traits<CharT>, test_allocator<CharT>>;59 { // Normal60 std::basic_stringbuf<CharT> buf;61 test_allocator_statistics stats;62 test_allocator<CharT> allocator{&stats};63 64 {65 SyncBuf sync_buf{&buf, allocator};66 std::streamsize ret = sync_buf.sputn(expected.data(), expected.size());67 assert(ret == 1024);68 69 // The synchronization happens upon destruction of sync_buf.70 assert(buf.str().empty());71 assert(stats.allocated_size >= 1024);72 }73 assert(buf.str() == expected);74 assert(stats.allocated_size == 0);75 }76 { // Move construction77 std::basic_stringbuf<CharT> buf;78 test_allocator_statistics stats;79 test_allocator<CharT> allocator{&stats};80 81 {82 SyncBuf sync_buf{&buf, allocator};83 std::streamsize ret = sync_buf.sputn(expected.data(), expected.size());84 assert(ret == 1024);85 {86 SyncBuf new_sync_buf{std::move(sync_buf)};87 ret = new_sync_buf.sputn(expected.data(), expected.size());88 assert(ret == 1024);89 90 // The synchronization happens upon destruction of new_sync_buf.91 assert(buf.str().empty());92 assert(stats.allocated_size >= 2048);93 }94 assert(buf.str() == expected + expected);95 assert(stats.allocated_size == 0);96 }97 assert(buf.str() == expected + expected);98 assert(stats.allocated_size == 0);99 }100 { // Move assignment non-propagating allocator101 std::basic_stringbuf<CharT> buf;102 test_allocator_statistics stats;103 test_allocator<CharT> allocator{&stats};104 static_assert(!std::allocator_traits<test_allocator<CharT>>::propagate_on_container_move_assignment::value);105 106 {107 SyncBuf sync_buf{&buf, allocator};108 std::streamsize ret = sync_buf.sputn(expected.data(), expected.size());109 assert(ret == 1024);110 {111 SyncBuf new_sync_buf;112 test_allocator<CharT> a = new_sync_buf.get_allocator();113 new_sync_buf = std::move(sync_buf);114 assert(new_sync_buf.get_allocator() == a);115 116 ret = new_sync_buf.sputn(expected.data(), expected.size());117 assert(ret == 1024);118 119 // The synchronization happens upon destruction of new_sync_buf.120 assert(buf.str().empty());121 }122 assert(buf.str() == expected + expected);123 }124 assert(buf.str() == expected + expected);125 }126}127 128int main(int, char**) {129 test<char>();130#ifndef TEST_HAS_NO_WIDE_CHARACTERS131 test<wchar_t>();132#endif133 return 0;134}135