[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, &copy_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, &copy_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, &copy_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