From d6a92611ebb55bcca6231d2bdc5749eaecf349d6 Mon Sep 17 00:00:00 2001 From: Piotr Fusik Date: Fri, 13 Oct 2023 15:33:54 -0700 Subject: [PATCH] [libc++] Improve the tests for std::basic_stringbuf's constructors and assignment operators Differential Revision: https://reviews.llvm.org/D154499 Co-authored-by: Louis Dionne --- .../stringbuf/stringbuf.assign/move.pass.cpp | 108 +++++++++++------- .../stringbuf.cons/move.alloc.pass.cpp | 74 +++++++++++- .../stringbuf/stringbuf.cons/move.pass.cpp | 106 +++++++++++------ libcxx/utils/data/ignore_format.txt | 2 - 4 files changed, 208 insertions(+), 82 deletions(-) diff --git a/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/move.pass.cpp b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/move.pass.cpp index 3ae562e17e80..e1c71829aa30 100644 --- a/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/move.pass.cpp +++ b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/move.pass.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++03 + // // template , class Allocator = allocator > @@ -15,49 +17,75 @@ #include #include +#include +#include "make_string.h" #include "test_macros.h" -int main(int, char**) -{ - { - std::stringbuf buf1("testing"); - std::stringbuf buf; - buf = std::move(buf1); - assert(buf.str() == "testing"); - } - { - std::stringbuf buf1("testing", std::ios_base::in); - std::stringbuf buf; - buf = std::move(buf1); - assert(buf.str() == "testing"); - } - { - std::stringbuf buf1("testing", std::ios_base::out); - std::stringbuf buf; - buf = std::move(buf1); - assert(buf.str() == "testing"); - } -#ifndef TEST_HAS_NO_WIDE_CHARACTERS - { - std::wstringbuf buf1(L"testing"); - std::wstringbuf buf; - buf = std::move(buf1); - assert(buf.str() == L"testing"); - } - { - std::wstringbuf buf1(L"testing", std::ios_base::in); - std::wstringbuf buf; - buf = std::move(buf1); - assert(buf.str() == L"testing"); - } - { - std::wstringbuf buf1(L"testing", std::ios_base::out); - std::wstringbuf buf; - buf = std::move(buf1); - assert(buf.str() == L"testing"); - } -#endif // TEST_HAS_NO_WIDE_CHARACTERS +#define STR(S) MAKE_STRING(CharT, S) +template +struct test_stringbuf : std::basic_stringbuf { + using std::basic_stringbuf::basic_stringbuf; + + // Checks the following requirement after being moved from: + // The six pointers of std::basic_streambuf in *this are guaranteed to be different + // from the corresponding pointers in the moved-from rhs unless null. + void check_different_pointers(test_stringbuf const& other) const { + assert(this->eback() == nullptr || this->eback() != other.eback()); + assert(this->gptr() == nullptr || this->gptr() != other.gptr()); + assert(this->egptr() == nullptr || this->egptr() != other.egptr()); + assert(this->pbase() == nullptr || this->pbase() != other.pbase()); + assert(this->pptr() == nullptr || this->pptr() != other.pptr()); + assert(this->epptr() == nullptr || this->epptr() != other.epptr()); + } +}; + +template +void test() { + std::basic_string strings[] = {STR(""), STR("short"), STR("loooooooooooooooooooong")}; + for (std::basic_string const& s : strings) { + { + test_stringbuf buf1(s); + test_stringbuf buf; + buf = std::move(buf1); + assert(buf.str() == s); + buf.check_different_pointers(buf1); + } + { + test_stringbuf buf1(s, std::ios_base::in); + test_stringbuf buf; + buf = std::move(buf1); + assert(buf.str() == s); + buf.check_different_pointers(buf1); + } + { + test_stringbuf buf1(s, std::ios_base::out); + test_stringbuf buf; + buf = std::move(buf1); + assert(buf.str() == s); + buf.check_different_pointers(buf1); + } + { + test_stringbuf buf1; + test_stringbuf buf; + buf = std::move(buf1); + buf.check_different_pointers(buf1); + } + // Use the assignment operator on an actual std::stringbuf, not test_stringbuf + { + std::basic_stringbuf buf1(s); + std::basic_stringbuf buf; + buf = std::move(buf1); + assert(buf.str() == s); + } + } +} + +int main(int, char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif return 0; } diff --git a/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/move.alloc.pass.cpp b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/move.alloc.pass.cpp index ac90d423373f..c652fa10127d 100644 --- a/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/move.alloc.pass.cpp +++ b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/move.alloc.pass.cpp @@ -17,6 +17,7 @@ #include #include +#include #include "make_string.h" #include "test_allocator.h" @@ -26,12 +27,73 @@ #define SV(S) MAKE_STRING_VIEW(CharT, S) template -static void test() { - std::basic_stringbuf, test_allocator> buf1(STR("testing")); - const test_allocator a(2); - const std::basic_stringbuf, test_allocator> buf(std::move(buf1), a); - assert(buf.get_allocator() == a); - assert(buf.view() == SV("testing")); +struct test_stringbuf : std::basic_stringbuf, test_allocator> { + using std::basic_stringbuf, test_allocator>::basic_stringbuf; + + // Checks the following requirement after being moved from: + // The six pointers of std::basic_streambuf in *this are guaranteed to be different + // from the corresponding pointers in the moved-from rhs unless null. + void check_different_pointers(test_stringbuf const& other) const { + assert(this->eback() == nullptr || this->eback() != other.eback()); + assert(this->gptr() == nullptr || this->gptr() != other.gptr()); + assert(this->egptr() == nullptr || this->egptr() != other.egptr()); + assert(this->pbase() == nullptr || this->pbase() != other.pbase()); + assert(this->pptr() == nullptr || this->pptr() != other.pptr()); + assert(this->epptr() == nullptr || this->epptr() != other.epptr()); + } +}; + +template +void test() { + std::basic_string strings[] = {STR(""), STR("short"), STR("loooooooooooooooooooong")}; + for (std::basic_string const& s : strings) { + using StringBuf = std::basic_stringbuf, test_allocator>; + { + test_stringbuf buf1(s); + const test_allocator a(2); + test_stringbuf buf(std::move(static_cast(buf1)), a); + assert(buf.get_allocator() == a); + assert(buf.view() == s); + assert(buf1.view().empty()); + buf.check_different_pointers(buf1); + } + { + test_stringbuf buf1(s, std::ios_base::in); + const test_allocator a(2); + test_stringbuf buf(std::move(static_cast(buf1)), a); + assert(buf.get_allocator() == a); + assert(buf.view() == s); + assert(buf1.view().empty()); + buf.check_different_pointers(buf1); + } + { + test_stringbuf buf1(s, std::ios_base::out); + const test_allocator a(2); + test_stringbuf buf(std::move(static_cast(buf1)), a); + assert(buf.get_allocator() == a); + assert(buf.view() == s); + assert(buf1.view().empty()); + buf.check_different_pointers(buf1); + } + { + test_stringbuf buf1; + const test_allocator a(2); + test_stringbuf buf(std::move(static_cast(buf1)), a); + assert(buf.get_allocator() == a); + assert(buf.view().empty()); + assert(buf1.view().empty()); + buf.check_different_pointers(buf1); + } + // Use the constructor from an actual std::stringbuf, not test_stringbuf + { + StringBuf buf1(s); + const test_allocator a(2); + StringBuf buf(std::move(buf1), a); + assert(buf.get_allocator() == a); + assert(buf.view() == s); + assert(buf1.view().empty()); + } + } } int main(int, char**) { diff --git a/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/move.pass.cpp b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/move.pass.cpp index c4846c01d413..65767a95ad8f 100644 --- a/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/move.pass.cpp +++ b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/move.pass.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +// UNSUPPORTED: c++03 + // // template , class Allocator = allocator > @@ -15,43 +17,79 @@ #include #include +#include +#include "make_string.h" #include "test_macros.h" -int main(int, char**) -{ - { - std::stringbuf buf1("testing"); - std::stringbuf buf(std::move(buf1)); - assert(buf.str() == "testing"); - } - { - std::stringbuf buf1("testing", std::ios_base::in); - std::stringbuf buf(std::move(buf1)); - assert(buf.str() == "testing"); - } - { - std::stringbuf buf1("testing", std::ios_base::out); - std::stringbuf buf(std::move(buf1)); - assert(buf.str() == "testing"); - } -#ifndef TEST_HAS_NO_WIDE_CHARACTERS - { - std::wstringbuf buf1(L"testing"); - std::wstringbuf buf(std::move(buf1)); - assert(buf.str() == L"testing"); - } - { - std::wstringbuf buf1(L"testing", std::ios_base::in); - std::wstringbuf buf(std::move(buf1)); - assert(buf.str() == L"testing"); - } - { - std::wstringbuf buf1(L"testing", std::ios_base::out); - std::wstringbuf buf(std::move(buf1)); - assert(buf.str() == L"testing"); - } -#endif +#define STR(S) MAKE_STRING(CharT, S) +template +struct test_stringbuf : std::basic_stringbuf { + using std::basic_stringbuf::basic_stringbuf; + + test_stringbuf(std::basic_stringbuf&& other) : std::basic_stringbuf(std::move(other)) {} + + // Checks the following requirement after being moved from: + // The six pointers of std::basic_streambuf in *this are guaranteed to be different + // from the corresponding pointers in the moved-from rhs unless null. + void check_different_pointers(test_stringbuf const& other) const { + assert(this->eback() == nullptr || this->eback() != other.eback()); + assert(this->gptr() == nullptr || this->gptr() != other.gptr()); + assert(this->egptr() == nullptr || this->egptr() != other.egptr()); + assert(this->pbase() == nullptr || this->pbase() != other.pbase()); + assert(this->pptr() == nullptr || this->pptr() != other.pptr()); + assert(this->epptr() == nullptr || this->epptr() != other.epptr()); + } +}; + +template +void test() { + std::basic_string strings[] = {STR(""), STR("short"), STR("loooooooooooooooooooong")}; + for (std::basic_string const& s : strings) { + using StringBuf = std::basic_stringbuf; + { + test_stringbuf buf1(s); + test_stringbuf buf(std::move(static_cast(buf1))); + assert(buf.str() == s); + assert(buf1.str().empty()); + buf.check_different_pointers(buf1); + } + { + test_stringbuf buf1(s, std::ios_base::in); + test_stringbuf buf(std::move(static_cast(buf1))); + assert(buf.str() == s); + assert(buf1.str().empty()); + buf.check_different_pointers(buf1); + } + { + test_stringbuf buf1(s, std::ios_base::out); + test_stringbuf buf(std::move(static_cast(buf1))); + assert(buf.str() == s); + assert(buf1.str().empty()); + buf.check_different_pointers(buf1); + } + { + test_stringbuf buf1; + test_stringbuf buf(std::move(static_cast(buf1))); + assert(buf.str().empty()); + assert(buf1.str().empty()); + buf.check_different_pointers(buf1); + } + // Use the constructor from an actual std::stringbuf, not test_stringbuf + { + StringBuf buf1(s); + StringBuf buf(std::move(buf1)); + assert(buf.str() == s); + assert(buf1.str().empty()); + } + } +} + +int main(int, char**) { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif return 0; } diff --git a/libcxx/utils/data/ignore_format.txt b/libcxx/utils/data/ignore_format.txt index 8a415c1610d4..82b1bc920d1d 100644 --- a/libcxx/utils/data/ignore_format.txt +++ b/libcxx/utils/data/ignore_format.txt @@ -3477,10 +3477,8 @@ libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.cons/str libcxx/test/std/input.output/string.streams/ostringstream/ostringstream.members/str.pass.cpp libcxx/test/std/input.output/string.streams/ostringstream/types.pass.cpp libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/member_swap.pass.cpp -libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/move.pass.cpp libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/nonmember_swap.pass.cpp libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/default.pass.cpp -libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/move.pass.cpp libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.cons/string.pass.cpp libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.members/str.pass.cpp libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.virtuals/overflow.pass.cpp