From 929c250a540612475a3b0f33edda58a46b3e932f Mon Sep 17 00:00:00 2001 From: Peng Liu Date: Sun, 8 Dec 2024 22:54:51 -0500 Subject: [PATCH 1/3] Improve tests for assign in std::vector --- .../vector.cons/assign_iter_iter.pass.cpp | 107 ++++++++++++++++-- 1 file changed, 100 insertions(+), 7 deletions(-) diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/assign_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/assign_iter_iter.pass.cpp index b6aeba4e4eef3..acbb1a6231204 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/assign_iter_iter.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/assign_iter_iter.pass.cpp @@ -19,17 +19,16 @@ #include "asan_testing.h" #include "test_iterators.h" #if TEST_STD_VER >= 11 -#include "emplace_constructible.h" -#include "container_test_types.h" +# include "emplace_constructible.h" +# include "container_test_types.h" #endif - TEST_CONSTEXPR_CXX20 bool test() { #if TEST_STD_VER >= 11 int arr1[] = {42}; int arr2[] = {1, 101, 42}; - { - using T = EmplaceConstructibleMoveableAndAssignable; + { // Test with new_size > capacity() == 0 for forward_iterator, resulting in reallocation during assign + using T = EmplaceConstructibleMoveableAndAssignable; using It = forward_iterator; { std::vector v; @@ -44,8 +43,8 @@ TEST_CONSTEXPR_CXX20 bool test() { assert(v[2].value == 42); } } - { - using T = EmplaceConstructibleMoveableAndAssignable; + { // Test with new_size > capacity() == 0 for input_iterator, resulting in reallocation during assign + using T = EmplaceConstructibleMoveableAndAssignable; using It = cpp17_input_iterator; { std::vector v; @@ -64,6 +63,100 @@ TEST_CONSTEXPR_CXX20 bool test() { assert(v[2].value == 42); } } + + { // Test with new_size < size() for forward_iterator, resulting in destruction at end during assign + using T = EmplaceConstructibleMoveableAndAssignable; + using It = forward_iterator; + { + std::vector v; + v.reserve(5); + for (std::size_t i = 0; i < v.capacity(); ++i) + v.emplace_back(99); + v.assign(It(arr1), It(std::end(arr1))); + assert(v.size() == 1); + assert(v[0].value == 42); + } + { + std::vector v; + v.reserve(5); + for (std::size_t i = 0; i < v.capacity(); ++i) + v.emplace_back(99); + v.assign(It(arr2), It(std::end(arr2))); + assert(v.size() == 3); + assert(v[0].value == 1); + assert(v[1].value == 101); + assert(v[2].value == 42); + } + } + { // Test with new_size < size() for input_iterator, resulting in destruction at end during assign + using T = EmplaceConstructibleMoveableAndAssignable; + using It = cpp17_input_iterator; + { + std::vector v; + v.reserve(5); + for (std::size_t i = 0; i < v.capacity(); ++i) + v.emplace_back(99); + v.assign(It(arr1), It(std::end(arr1))); + assert(v.size() == 1); + assert(v[0].value == 42); + } + { + std::vector v; + v.reserve(5); + for (std::size_t i = 0; i < v.capacity(); ++i) + v.emplace_back(99); + v.assign(It(arr2), It(std::end(arr2))); + assert(v.size() == 3); + assert(v[0].value == 1); + assert(v[1].value == 101); + assert(v[2].value == 42); + } + } + + { // Test with size() < new_size < capacity() for forward_iterator, resulting in construction at end during assign + using T = EmplaceConstructibleMoveableAndAssignable; + using It = forward_iterator; + { + std::vector v; + v.reserve(5); + v.assign(It(arr1), It(std::end(arr1))); + assert(v.size() == 1); + assert(v[0].value == 42); + } + { + std::vector v; + v.reserve(5); + for (std::size_t i = 0; i < 2; ++i) + v.emplace_back(99); + v.assign(It(arr2), It(std::end(arr2))); + assert(v.size() == 3); + assert(v[0].value == 1); + assert(v[1].value == 101); + assert(v[2].value == 42); + } + } + { // Test with size() < new_size < capacity() for inputs_iterator, resulting in construction at end during assign + using T = EmplaceConstructibleMoveableAndAssignable; + using It = cpp17_input_iterator; + { + std::vector v; + v.reserve(5); + v.assign(It(arr1), It(std::end(arr1))); + assert(v.size() == 1); + assert(v[0].value == 42); + } + { + std::vector v; + v.reserve(5); + for (std::size_t i = 0; i < 2; ++i) + v.emplace_back(99); + v.assign(It(arr2), It(std::end(arr2))); + assert(v.size() == 3); + assert(v[0].value == 1); + assert(v[1].value == 101); + assert(v[2].value == 42); + } + } #endif // Test with a number of elements in the source range that is greater than capacity From 0bde3b1a93cc2e936b4eb8ed760af67bc55f1970 Mon Sep 17 00:00:00 2001 From: Peng Liu Date: Mon, 9 Dec 2024 13:01:20 -0500 Subject: [PATCH 2/3] Add test coverage for vector::assign --- .../vector.bool/assign_iter_iter.pass.cpp | 93 +++++++++++++++++++ .../vector.bool/assign_size_value.pass.cpp | 57 ++++++++++++ .../vector.cons/assign_iter_iter.pass.cpp | 2 +- 3 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 libcxx/test/std/containers/sequences/vector.bool/assign_iter_iter.pass.cpp create mode 100644 libcxx/test/std/containers/sequences/vector.bool/assign_size_value.pass.cpp diff --git a/libcxx/test/std/containers/sequences/vector.bool/assign_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/assign_iter_iter.pass.cpp new file mode 100644 index 0000000000000..492007fa7890d --- /dev/null +++ b/libcxx/test/std/containers/sequences/vector.bool/assign_iter_iter.pass.cpp @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// void assign(_InputIterator __first, _InputIterator __last); +// void assign(_ForwardIterator __first, _ForwardIterator __last); + +#include +#include +#include "test_macros.h" +#include "test_iterators.h" + +TEST_CONSTEXPR_CXX20 bool tests() { + { // Test with various cases where assign may or may not trigger reallocations for forward_iterator + { // Reallocation happens + std::vector in(128, true); + std::vector v(5, false); + assert(v.capacity() < in.size()); + using It = forward_iterator::iterator>; + v.assign(It(in.begin()), It(in.end())); + assert(v == in); + } + { // No reallocation: fit wintin current size + bool in[] = {false, true, false, true, true}; + TEST_CONSTEXPR std::size_t N = sizeof(in) / sizeof(in[0]); + std::vector v(2 * N, false); + using It = forward_iterator; + v.assign(It(in), It(in + N)); + assert(v.size() == N); + for (std::size_t i = 0; i < N; ++i) + assert(v[i] == in[i]); + } + { // No reallocation: fit wintin spare space + bool in[] = {false, true, false, true, true}; + TEST_CONSTEXPR std::size_t N = sizeof(in) / sizeof(in[0]); + std::vector v(N / 2, false); + v.reserve(N * 2); + using It = forward_iterator; + v.assign(It(in), It(in + N)); + assert(v.size() == N); + for (std::size_t i = 0; i < N; ++i) + assert(v[i] == in[i]); + } + } + + { // Test with various cases where assign may or may not trigger reallocations for input_iterator + { // Reallocation happens + std::vector in(128, true); + std::vector v(5, false); + assert(v.capacity() < in.size()); + using It = cpp17_input_iterator::iterator>; + v.assign(It(in.begin()), It(in.end())); + assert(v == in); + } + { // No reallocation: fit wintin current size + bool in[] = {false, true, false, true, true}; + TEST_CONSTEXPR std::size_t N = sizeof(in) / sizeof(in[0]); + std::vector v(2 * N, false); + using It = cpp17_input_iterator; + v.assign(It(in), It(in + N)); + assert(v.size() == N); + for (std::size_t i = 0; i < N; ++i) + assert(v[i] == in[i]); + } + { // No reallocation: fit wintin spare space + bool in[] = {false, true, false, true, true}; + TEST_CONSTEXPR std::size_t N = sizeof(in) / sizeof(in[0]); + std::vector v(N / 2, false); + v.reserve(N * 2); + using It = cpp17_input_iterator; + v.assign(It(in), It(in + N)); + assert(v.size() == N); + for (std::size_t i = 0; i < N; ++i) + assert(v[i] == in[i]); + } + } + + return true; +} + +int main(int, char**) { + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; +} diff --git a/libcxx/test/std/containers/sequences/vector.bool/assign_size_value.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/assign_size_value.pass.cpp new file mode 100644 index 0000000000000..28198e748e2bf --- /dev/null +++ b/libcxx/test/std/containers/sequences/vector.bool/assign_size_value.pass.cpp @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// void assign(size_type __n, const value_type& __x); + +#include +#include +#include "test_macros.h" +#include "test_iterators.h" + +TEST_CONSTEXPR_CXX20 bool tests() { + { // Test with various cases where assign may or may not trigger reallocations + { // Reallocation happens + TEST_CONSTEXPR std::size_t N = 128; + std::vector v(5, false); + assert(v.capacity() < N); + v.assign(N, true); + assert(v.size() == N); + for (std::size_t i = 0; i < N; ++i) + assert(v[i] == true); + } + { // No reallocation: fit wintin current size + TEST_CONSTEXPR std::size_t N = 5; + std::vector v(2 * N, false); + v.assign(N, true); + assert(v.size() == N); + for (std::size_t i = 0; i < N; ++i) + assert(v[i] == true); + } + { // No reallocation: fit wintin spare space + TEST_CONSTEXPR std::size_t N = 5; + std::vector v(N / 2, false); + v.reserve(N * 2); + v.assign(N, true); + assert(v.size() == N); + for (std::size_t i = 0; i < N; ++i) + assert(v[i] == true); + } + } + + return true; +} + +int main(int, char**) { + tests(); +#if TEST_STD_VER > 17 + static_assert(tests()); +#endif + return 0; +} diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/assign_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/assign_iter_iter.pass.cpp index acbb1a6231204..91060679cd7f9 100644 --- a/libcxx/test/std/containers/sequences/vector/vector.cons/assign_iter_iter.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.cons/assign_iter_iter.pass.cpp @@ -135,7 +135,7 @@ TEST_CONSTEXPR_CXX20 bool test() { assert(v[2].value == 42); } } - { // Test with size() < new_size < capacity() for inputs_iterator, resulting in construction at end during assign + { // Test with size() < new_size < capacity() for input_iterator, resulting in construction at end during assign using T = EmplaceConstructibleMoveableAndAssignable; using It = cpp17_input_iterator; { From 4ada49a27f183818fb5878819b148c0248cf087e Mon Sep 17 00:00:00 2001 From: Peng Liu Date: Fri, 13 Dec 2024 11:15:47 -0500 Subject: [PATCH 3/3] Apply reviewer suggestions --- .../vector.bool/assign_iter_iter.pass.cpp | 28 +++++++++---------- .../vector.bool/assign_size_value.pass.cpp | 12 ++++---- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/libcxx/test/std/containers/sequences/vector.bool/assign_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/assign_iter_iter.pass.cpp index 492007fa7890d..91788b3707592 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/assign_iter_iter.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/assign_iter_iter.pass.cpp @@ -8,8 +8,8 @@ // -// void assign(_InputIterator __first, _InputIterator __last); -// void assign(_ForwardIterator __first, _ForwardIterator __last); +// template +// constexpr void assign(InputIt first, InputIt last); #include #include @@ -26,9 +26,9 @@ TEST_CONSTEXPR_CXX20 bool tests() { v.assign(It(in.begin()), It(in.end())); assert(v == in); } - { // No reallocation: fit wintin current size - bool in[] = {false, true, false, true, true}; - TEST_CONSTEXPR std::size_t N = sizeof(in) / sizeof(in[0]); + { // No reallocation: fit within current size + bool in[] = {false, true, false, true, true}; + std::size_t N = sizeof(in) / sizeof(in[0]); std::vector v(2 * N, false); using It = forward_iterator; v.assign(It(in), It(in + N)); @@ -36,9 +36,9 @@ TEST_CONSTEXPR_CXX20 bool tests() { for (std::size_t i = 0; i < N; ++i) assert(v[i] == in[i]); } - { // No reallocation: fit wintin spare space - bool in[] = {false, true, false, true, true}; - TEST_CONSTEXPR std::size_t N = sizeof(in) / sizeof(in[0]); + { // No reallocation: fit within spare space + bool in[] = {false, true, false, true, true}; + std::size_t N = sizeof(in) / sizeof(in[0]); std::vector v(N / 2, false); v.reserve(N * 2); using It = forward_iterator; @@ -58,9 +58,9 @@ TEST_CONSTEXPR_CXX20 bool tests() { v.assign(It(in.begin()), It(in.end())); assert(v == in); } - { // No reallocation: fit wintin current size - bool in[] = {false, true, false, true, true}; - TEST_CONSTEXPR std::size_t N = sizeof(in) / sizeof(in[0]); + { // No reallocation: fit within current size + bool in[] = {false, true, false, true, true}; + std::size_t N = sizeof(in) / sizeof(in[0]); std::vector v(2 * N, false); using It = cpp17_input_iterator; v.assign(It(in), It(in + N)); @@ -68,9 +68,9 @@ TEST_CONSTEXPR_CXX20 bool tests() { for (std::size_t i = 0; i < N; ++i) assert(v[i] == in[i]); } - { // No reallocation: fit wintin spare space - bool in[] = {false, true, false, true, true}; - TEST_CONSTEXPR std::size_t N = sizeof(in) / sizeof(in[0]); + { // No reallocation: fit within spare space + bool in[] = {false, true, false, true, true}; + std::size_t N = sizeof(in) / sizeof(in[0]); std::vector v(N / 2, false); v.reserve(N * 2); using It = cpp17_input_iterator; diff --git a/libcxx/test/std/containers/sequences/vector.bool/assign_size_value.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/assign_size_value.pass.cpp index 28198e748e2bf..d2513bb84c806 100644 --- a/libcxx/test/std/containers/sequences/vector.bool/assign_size_value.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector.bool/assign_size_value.pass.cpp @@ -8,7 +8,7 @@ // -// void assign(size_type __n, const value_type& __x); +// void assign(size_type n, const value_type& x); #include #include @@ -18,7 +18,7 @@ TEST_CONSTEXPR_CXX20 bool tests() { { // Test with various cases where assign may or may not trigger reallocations { // Reallocation happens - TEST_CONSTEXPR std::size_t N = 128; + std::size_t N = 128; std::vector v(5, false); assert(v.capacity() < N); v.assign(N, true); @@ -26,16 +26,16 @@ TEST_CONSTEXPR_CXX20 bool tests() { for (std::size_t i = 0; i < N; ++i) assert(v[i] == true); } - { // No reallocation: fit wintin current size - TEST_CONSTEXPR std::size_t N = 5; + { // No reallocation: fit within current size + std::size_t N = 5; std::vector v(2 * N, false); v.assign(N, true); assert(v.size() == N); for (std::size_t i = 0; i < N; ++i) assert(v[i] == true); } - { // No reallocation: fit wintin spare space - TEST_CONSTEXPR std::size_t N = 5; + { // No reallocation: fit within spare space + std::size_t N = 5; std::vector v(N / 2, false); v.reserve(N * 2); v.assign(N, true);