[libcxx-commits] [libcxx] 8c6b248 - [libcxx][test][NFC] Various tests for std::vector
Ruslan Arutyunyan via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Dec 1 15:16:23 PST 2021
Author: Konstantin Boyarinov
Date: 2021-12-02T02:11:45+03:00
New Revision: 8c6b24899e51648286bb812d92a23a28798c53eb
URL: https://github.com/llvm/llvm-project/commit/8c6b24899e51648286bb812d92a23a28798c53eb
DIFF: https://github.com/llvm/llvm-project/commit/8c6b24899e51648286bb812d92a23a28798c53eb.diff
LOG: [libcxx][test][NFC] Various tests for std::vector
Add missing tests for std::vector funcionality to improve code coverage:
- Rewrote access tests to check modification of the container using
the reference returned by the non-const overload
- Added tests for reverse iterators: rbegin, rend, etc.
- Added exception test for vector::reserve
- Extended test cases for vector copy assignment
- Fixed insert_iter_value.pass.cpp to use insert overload with const
value_type& (not with value_type&& which is tested in
iter_rvalue.pass.cpp test)
Reviewed By: Quuxplusone, rarutyun, #libc
Differential Revision: https://reviews.llvm.org/D112438
Added:
libcxx/test/std/containers/sequences/vector/reverse_iterators.pass.cpp
libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_lvalue.pass.cpp
Modified:
libcxx/test/std/containers/sequences/vector/access.pass.cpp
libcxx/test/std/containers/sequences/vector/vector.capacity/reserve.pass.cpp
libcxx/test/std/containers/sequences/vector/vector.cons/assign_copy.pass.cpp
libcxx/test/std/containers/sequences/vector/vector.modifiers/emplace_extra.pass.cpp
libcxx/test/support/allocators.h
Removed:
libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_value.pass.cpp
################################################################################
diff --git a/libcxx/test/std/containers/sequences/vector/access.pass.cpp b/libcxx/test/std/containers/sequences/vector/access.pass.cpp
index 4ac19ff7189e6..35d93db0f95f0 100644
--- a/libcxx/test/std/containers/sequences/vector/access.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector/access.pass.cpp
@@ -29,7 +29,7 @@
template <class C>
C
-make(int size, int start = 0)
+make(int size, int start)
{
C c;
for (int i = 0; i < size; ++i)
@@ -37,84 +37,85 @@ make(int size, int start = 0)
return c;
}
-int main(int, char**)
-{
- {
- typedef std::vector<int> C;
- C c = make<C>(10);
- LIBCPP_ASSERT_NOEXCEPT(c[0]);
- LIBCPP_ASSERT_NOEXCEPT(c.front());
- LIBCPP_ASSERT_NOEXCEPT(c.back());
- // at() is NOT noexcept
- ASSERT_SAME_TYPE(C::reference, decltype(c[0]));
- ASSERT_SAME_TYPE(C::reference, decltype(c.at(0)));
- ASSERT_SAME_TYPE(C::reference, decltype(c.front()));
- ASSERT_SAME_TYPE(C::reference, decltype(c.back()));
- for (int i = 0; i < 10; ++i)
- assert(c[i] == i);
- for (int i = 0; i < 10; ++i)
- assert(c.at(i) == i);
- assert(c.front() == 0);
- assert(c.back() == 9);
+template <class Vector>
+void test_get_basic(Vector& c, int start_value) {
+ const int n = c.size();
+ for (int i = 0; i < n; ++i)
+ assert(c[i] == start_value + i);
+ for (int i = 0; i < n; ++i)
+ assert(c.at(i) == start_value + i);
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ try {
+ c.at(n);
+ assert(false);
+ } catch (const std::out_of_range&) {}
+#endif
+
+ assert(c.front() == start_value);
+ assert(c.back() == start_value + n - 1);
+}
+
+template <class Vector>
+void test_get() {
+ int start_value = 35;
+ Vector c = make<Vector>(10, start_value);
+ const Vector& cc = c;
+ test_get_basic(c, start_value);
+ test_get_basic(cc, start_value);
+}
+
+template <class Vector>
+void test_set() {
+ int start_value = 35;
+ const int n = 10;
+ Vector c = make<Vector>(n, start_value);
+
+ for (int i = 0; i < n; ++i) {
+ assert(c[i] == start_value + i);
+ c[i] = start_value + i + 1;
+ assert(c[i] == start_value + i + 1);
}
- {
- typedef std::vector<int> C;
- const int N = 5;
- const C c = make<C>(10, N);
- LIBCPP_ASSERT_NOEXCEPT(c[0]);
- LIBCPP_ASSERT_NOEXCEPT(c.front());
- LIBCPP_ASSERT_NOEXCEPT(c.back());
- // at() is NOT noexcept
- ASSERT_SAME_TYPE(C::const_reference, decltype(c[0]));
- ASSERT_SAME_TYPE(C::const_reference, decltype(c.at(0)));
- ASSERT_SAME_TYPE(C::const_reference, decltype(c.front()));
- ASSERT_SAME_TYPE(C::const_reference, decltype(c.back()));
- for (int i = 0; i < 10; ++i)
- assert(c[i] == N + i);
- for (int i = 0; i < 10; ++i)
- assert(c.at(i) == N + i);
- assert(c.front() == N);
- assert(c.back() == N + 9);
+ for (int i = 0; i < n; ++i) {
+ assert(c.at(i) == start_value + i + 1);
+ c.at(i) = start_value + i + 2;
+ assert(c.at(i) == start_value + i + 2);
}
+
+ assert(c.front() == start_value + 2);
+ c.front() = start_value + 3;
+ assert(c.front() == start_value + 3);
+
+ assert(c.back() == start_value + n + 1);
+ c.back() = start_value + n + 2;
+ assert(c.back() == start_value + n + 2);
+}
+
+template <class Vector>
+void test() {
+ test_get<Vector>();
+ test_set<Vector>();
+
+ Vector c;
+ const Vector& cc = c;
+ ASSERT_SAME_TYPE(typename Vector::reference, decltype(c[0]));
+ ASSERT_SAME_TYPE(typename Vector::const_reference, decltype(cc[0]));
+
+ ASSERT_SAME_TYPE(typename Vector::reference, decltype(c.at(0)));
+ ASSERT_SAME_TYPE(typename Vector::const_reference, decltype(cc.at(0)));
+
+ ASSERT_SAME_TYPE(typename Vector::reference, decltype(c.front()));
+ ASSERT_SAME_TYPE(typename Vector::const_reference, decltype(cc.front()));
+
+ ASSERT_SAME_TYPE(typename Vector::reference, decltype(c.back()));
+ ASSERT_SAME_TYPE(typename Vector::const_reference, decltype(cc.back()));
+}
+
+int main(int, char**)
+{
+ test<std::vector<int> >();
#if TEST_STD_VER >= 11
- {
- typedef std::vector<int, min_allocator<int>> C;
- const int N = 34;
- C c = make<C>(10, N);
- LIBCPP_ASSERT_NOEXCEPT(c[0]);
- LIBCPP_ASSERT_NOEXCEPT(c.front());
- LIBCPP_ASSERT_NOEXCEPT(c.back());
- // at() is NOT noexcept
- ASSERT_SAME_TYPE(C::reference, decltype(c[0]));
- ASSERT_SAME_TYPE(C::reference, decltype(c.at(0)));
- ASSERT_SAME_TYPE(C::reference, decltype(c.front()));
- ASSERT_SAME_TYPE(C::reference, decltype(c.back()));
- for (int i = 0; i < 10; ++i)
- assert(c[i] == N + i);
- for (int i = 0; i < 10; ++i)
- assert(c.at(i) == N + i);
- assert(c.front() == N);
- assert(c.back() == N + 9);
- }
- {
- typedef std::vector<int, min_allocator<int>> C;
- const int N = 23;
- const C c = make<C>(10, N);
- LIBCPP_ASSERT_NOEXCEPT(c[0]);
- LIBCPP_ASSERT_NOEXCEPT(c.front());
- LIBCPP_ASSERT_NOEXCEPT(c.back());
- // at() is NOT noexcept
- ASSERT_SAME_TYPE(C::const_reference, decltype(c[0]));
- ASSERT_SAME_TYPE(C::const_reference, decltype(c.at(0)));
- ASSERT_SAME_TYPE(C::const_reference, decltype(c.front()));
- ASSERT_SAME_TYPE(C::const_reference, decltype(c.back()));
- for (int i = 0; i < 10; ++i)
- assert(c[i] == N + i);
- for (int i = 0; i < 10; ++i)
- assert(c.at(i) == N + i);
- assert(c.front() == N);
- assert(c.back() == N + 9);
- }
+ test<std::vector<int, min_allocator<int> > >();
#endif
return 0;
diff --git a/libcxx/test/std/containers/sequences/vector/reverse_iterators.pass.cpp b/libcxx/test/std/containers/sequences/vector/reverse_iterators.pass.cpp
new file mode 100644
index 0000000000000..c2b5d4d481e54
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/vector/reverse_iterators.pass.cpp
@@ -0,0 +1,77 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// reverse_iterator rbegin();
+// reverse_iterator rend();
+// const_reverse_iterator rbegin() const;
+// const_reverse_iterator rend() const;
+// const_reverse_iterator crbegin() const;
+// const_reverse_iterator crend() const;
+
+#include <vector>
+#include <cassert>
+#include <iterator>
+
+#include "min_allocator.h"
+
+template <class Vector>
+void check_vector_reverse_iterators() {
+ {
+ Vector vec;
+ assert(vec.rbegin() == vec.rend());
+ assert(vec.crbegin() == vec.crend());
+ }
+ {
+ const int n = 10;
+ Vector vec;
+ const Vector& cvec = vec;
+ vec.reserve(n);
+ for (int i = 0; i < n; ++i)
+ vec.push_back(i);
+ {
+ int iterations = 0;
+
+ for (typename Vector::const_reverse_iterator it = vec.crbegin(); it != vec.crend(); ++it) {
+ assert(*it == (n - iterations - 1));
+ ++iterations;
+ }
+ assert(iterations == n);
+ }
+ {
+ assert(cvec.rbegin() == vec.crbegin());
+ assert(cvec.rend() == vec.crend());
+ }
+ {
+ int iterations = 0;
+
+ for (typename Vector::reverse_iterator it = vec.rbegin(); it != vec.rend(); ++it) {
+ assert(*it == (n - iterations - 1));
+ *it = 40;
+ assert(*it == 40);
+ ++iterations;
+ }
+ assert(iterations == n);
+ }
+
+ assert(std::distance(vec.rbegin(), vec.rend()) == n);
+ assert(std::distance(cvec.rbegin(), cvec.rend()) == n);
+ assert(std::distance(vec.crbegin(), vec.crend()) == n);
+ assert(std::distance(cvec.crbegin(), cvec.crend()) == n);
+ }
+}
+
+int main(int, char**) {
+ check_vector_reverse_iterators<std::vector<int> >();
+#if TEST_STD_VER >= 11
+ check_vector_reverse_iterators<std::vector<int, min_allocator<int> > >();
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/vector/vector.capacity/reserve.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.capacity/reserve.pass.cpp
index 378a67c96ce55..e525a752e091f 100644
--- a/libcxx/test/std/containers/sequences/vector/vector.capacity/reserve.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector/vector.capacity/reserve.pass.cpp
@@ -48,6 +48,39 @@ int main(int, char**)
assert(v.capacity() == 150);
assert(is_contiguous_container_asan_correct(v));
}
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ std::vector<int> v;
+ size_t sz = v.max_size() + 1;
+
+ try {
+ v.reserve(sz);
+ assert(false);
+ } catch (const std::length_error&) {
+ assert(v.size() == 0);
+ assert(v.capacity() == 0);
+ }
+ }
+ {
+ std::vector<int> v(10, 42);
+ int* previous_data = v.data();
+ size_t previous_capacity = v.capacity();
+ size_t sz = v.max_size() + 1;
+
+ try {
+ v.reserve(sz);
+ assert(false);
+ } catch (std::length_error&) {
+ assert(v.size() == 10);
+ assert(v.capacity() == previous_capacity);
+ assert(v.data() == previous_data);
+
+ for (int i = 0; i < 10; ++i) {
+ assert(v[i] == 42);
+ }
+ }
+ }
+#endif
#if TEST_STD_VER >= 11
{
std::vector<int, min_allocator<int>> v;
diff --git a/libcxx/test/std/containers/sequences/vector/vector.cons/assign_copy.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.cons/assign_copy.pass.cpp
index a318546119060..a14f90c0525da 100644
--- a/libcxx/test/std/containers/sequences/vector/vector.cons/assign_copy.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector/vector.cons/assign_copy.pass.cpp
@@ -15,6 +15,7 @@
#include "test_macros.h"
#include "test_allocator.h"
#include "min_allocator.h"
+#include "allocators.h"
int main(int, char**)
{
@@ -33,6 +34,44 @@ int main(int, char**)
assert(l2.get_allocator() == other_allocator<int>(5));
}
#if TEST_STD_VER >= 11
+ {
+ // Test with Allocator::propagate_on_container_copy_assignment == false_type
+ using Alloc = NonPOCCAAllocator<int>;
+ bool copy_assigned_into = false;
+ std::vector<int, Alloc> l(3, 2, Alloc(5, nullptr));
+ std::vector<int, Alloc> l2(l, Alloc(3, ©_assigned_into));
+ assert(!copy_assigned_into);
+ l2 = l;
+ assert(!copy_assigned_into);
+ assert(l2 == l);
+ assert(l2.get_allocator() == Alloc(3, nullptr));
+ }
+ {
+ // Test with Allocator::propagate_on_container_copy_assignment == true_type
+ // and equal allocators
+ using Alloc = POCCAAllocator<int>;
+ bool copy_assigned_into = false;
+ std::vector<int, Alloc> l(3, 2, Alloc(5, nullptr));
+ std::vector<int, Alloc> l2(l, Alloc(5, ©_assigned_into));
+ assert(!copy_assigned_into);
+ l2 = l;
+ assert(copy_assigned_into);
+ assert(l2 == l);
+ assert(l2.get_allocator() == Alloc(5, nullptr));
+ }
+ {
+ // Test with Allocator::propagate_on_container_copy_assignment == true_type
+ // and unequal allocators
+ using Alloc = POCCAAllocator<int>;
+ bool copy_assigned_into = false;
+ std::vector<int, Alloc> l(3, 2, Alloc(5, nullptr));
+ std::vector<int, Alloc> l2(l, Alloc(3, ©_assigned_into));
+ assert(!copy_assigned_into);
+ l2 = l;
+ assert(copy_assigned_into);
+ assert(l2 == l);
+ assert(l2.get_allocator() == Alloc(5, nullptr));
+ }
{
std::vector<int, min_allocator<int> > l(3, 2, min_allocator<int>());
std::vector<int, min_allocator<int> > l2(l, min_allocator<int>());
diff --git a/libcxx/test/std/containers/sequences/vector/vector.modifiers/emplace_extra.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.modifiers/emplace_extra.pass.cpp
index 7a73580d1e6fe..5bc35be643de6 100644
--- a/libcxx/test/std/containers/sequences/vector/vector.modifiers/emplace_extra.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector/vector.modifiers/emplace_extra.pass.cpp
@@ -57,6 +57,19 @@ int main(int, char**)
assert(v[0] == 3);
assert(is_contiguous_container_asan_correct(v));
}
+ {
+ std::vector<int> v;
+ v.reserve(8);
+ size_t old_capacity = v.capacity();
+ assert(old_capacity >= 8);
+ v.resize(4); // keep the existing capacity
+ assert(v.capacity() == old_capacity);
+
+ v.emplace(v.cend(), 42);
+ assert(v.size() == 5);
+ assert(v.capacity() == old_capacity);
+ assert(v[4] == 42);
+ }
return 0;
}
diff --git a/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_value.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_lvalue.pass.cpp
similarity index 80%
rename from libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_value.pass.cpp
rename to libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_lvalue.pass.cpp
index 2edadd0fe7774..63c1c64e272a8 100644
--- a/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_value.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_iter_lvalue.pass.cpp
@@ -23,7 +23,8 @@ int main(int, char**)
{
{
std::vector<int> v(100);
- std::vector<int>::iterator i = v.insert(v.cbegin() + 10, 1);
+ const int lvalue = 1;
+ std::vector<int>::iterator i = v.insert(v.cbegin() + 10, lvalue);
assert(v.size() == 101);
assert(is_contiguous_container_asan_correct(v));
assert(i == v.begin() + 10);
@@ -34,11 +35,29 @@ int main(int, char**)
for (++j; j < 101; ++j)
assert(v[j] == 0);
}
+ {
+ const size_t n = 100;
+ std::vector<int> v(n);
+ v.reserve(n + 1);
+ const int lvalue = 1;
+
+ // no reallocation expected
+ std::vector<int>::iterator it = v.insert(v.cbegin() + n, lvalue);
+
+ assert(v.size() == n + 1);
+ assert(is_contiguous_container_asan_correct(v));
+ assert(it == v.begin() + n);
+ for (size_t i = 0; i < n; ++i) {
+ assert(v[i] == 0);
+ }
+ assert(v[n] == lvalue);
+ }
{
std::vector<int> v(100);
while(v.size() < v.capacity()) v.push_back(0); // force reallocation
size_t sz = v.size();
- std::vector<int>::iterator i = v.insert(v.cbegin() + 10, 1);
+ const int lvalue = 1;
+ std::vector<int>::iterator i = v.insert(v.cbegin() + 10, lvalue);
assert(v.size() == sz + 1);
assert(is_contiguous_container_asan_correct(v));
assert(i == v.begin() + 10);
@@ -54,7 +73,8 @@ int main(int, char**)
while(v.size() < v.capacity()) v.push_back(0);
v.pop_back(); v.pop_back(); // force no reallocation
size_t sz = v.size();
- std::vector<int>::iterator i = v.insert(v.cbegin() + 10, 1);
+ const int lvalue = 1;
+ std::vector<int>::iterator i = v.insert(v.cbegin() + 10, lvalue);
assert(v.size() == sz + 1);
assert(is_contiguous_container_asan_correct(v));
assert(i == v.begin() + 10);
@@ -67,7 +87,8 @@ int main(int, char**)
}
{
std::vector<int, limited_allocator<int, 300> > v(100);
- std::vector<int, limited_allocator<int, 300> >::iterator i = v.insert(v.cbegin() + 10, 1);
+ const int lvalue = 1;
+ std::vector<int, limited_allocator<int, 300> >::iterator i = v.insert(v.cbegin() + 10, lvalue);
assert(v.size() == 101);
assert(is_contiguous_container_asan_correct(v));
assert(i == v.begin() + 10);
@@ -81,7 +102,8 @@ int main(int, char**)
#if TEST_STD_VER >= 11
{
std::vector<int, min_allocator<int>> v(100);
- std::vector<int, min_allocator<int>>::iterator i = v.insert(v.cbegin() + 10, 1);
+ const int lvalue = 1;
+ std::vector<int, min_allocator<int>>::iterator i = v.insert(v.cbegin() + 10, lvalue);
assert(v.size() == 101);
assert(is_contiguous_container_asan_correct(v));
assert(i == v.begin() + 10);
diff --git a/libcxx/test/support/allocators.h b/libcxx/test/support/allocators.h
index 759e9c3a415b9..f8e0c1b5e4cba 100644
--- a/libcxx/test/support/allocators.h
+++ b/libcxx/test/support/allocators.h
@@ -185,6 +185,55 @@ bool operator!=(const A3<T>& x, const A3<U>& y)
return !(x == y);
}
+template <class T, bool POCCAValue>
+class MaybePOCCAAllocator {
+ int id_ = 0;
+ bool* copy_assigned_into_ = nullptr;
+public:
+ typedef std::integral_constant<bool, POCCAValue> propagate_on_container_copy_assignment;
+ typedef T value_type;
+
+ MaybePOCCAAllocator() = default;
+ MaybePOCCAAllocator(int id, bool* copy_assigned_into)
+ : id_(id), copy_assigned_into_(copy_assigned_into) {}
+
+ MaybePOCCAAllocator(const MaybePOCCAAllocator&) = default;
+ MaybePOCCAAllocator& operator=(const MaybePOCCAAllocator& a)
+ {
+ id_ = a.id();
+ if (copy_assigned_into_)
+ *copy_assigned_into_ = true;
+ return *this;
+ }
+
+ T* allocate(std::size_t n)
+ {
+ return static_cast<T*>(::operator new(n * sizeof(T)));
+ }
+
+ void deallocate(T* ptr, std::size_t)
+ {
+ ::operator delete(ptr);
+ }
+
+ int id() const { return id_; }
+
+ friend bool operator==(const MaybePOCCAAllocator& lhs, const MaybePOCCAAllocator& rhs)
+ {
+ return lhs.id() == rhs.id();
+ }
+
+ friend bool operator!=(const MaybePOCCAAllocator& lhs, const MaybePOCCAAllocator& rhs)
+ {
+ return !(lhs == rhs);
+ }
+};
+
+template <class T>
+using POCCAAllocator = MaybePOCCAAllocator<T, /*POCCAValue = */true>;
+template <class T>
+using NonPOCCAAllocator = MaybePOCCAAllocator<T, /*POCCAValue = */false>;
+
#endif // TEST_STD_VER >= 11
#endif // ALLOCATORS_H
More information about the libcxx-commits
mailing list