summaryrefslogtreecommitdiff
path: root/test/libcxx/debug/containers
diff options
context:
space:
mode:
Diffstat (limited to 'test/libcxx/debug/containers')
-rw-r--r--test/libcxx/debug/containers/db_associative_container_tests.pass.cpp64
-rw-r--r--test/libcxx/debug/containers/db_sequence_container_iterators.pass.cpp265
-rw-r--r--test/libcxx/debug/containers/db_string.pass.cpp96
-rw-r--r--test/libcxx/debug/containers/db_unord_container_tests.pass.cpp66
4 files changed, 491 insertions, 0 deletions
diff --git a/test/libcxx/debug/containers/db_associative_container_tests.pass.cpp b/test/libcxx/debug/containers/db_associative_container_tests.pass.cpp
new file mode 100644
index 000000000000..c2c2d9221cf1
--- /dev/null
+++ b/test/libcxx/debug/containers/db_associative_container_tests.pass.cpp
@@ -0,0 +1,64 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// UNSUPPORTED: libcpp-no-exceptions, libcpp-no-if-constexpr
+
+// test container debugging
+
+#define _LIBCPP_DEBUG 1
+#define _LIBCPP_DEBUG_USE_EXCEPTIONS
+#include <map>
+#include <set>
+#include <utility>
+#include <cassert>
+#include "debug_mode_helper.h"
+
+using namespace IteratorDebugChecks;
+
+template <class Container, ContainerType CT>
+struct AssociativeContainerChecks : BasicContainerChecks<Container, CT> {
+ using Base = BasicContainerChecks<Container, CT>;
+ using value_type = typename Container::value_type;
+ using iterator = typename Container::iterator;
+ using const_iterator = typename Container::const_iterator;
+ using traits = std::iterator_traits<iterator>;
+ using category = typename traits::iterator_category;
+
+ using Base::makeContainer;
+public:
+ static void run() {
+ Base::run();
+ try {
+ // FIXME Add tests
+ } catch (...) {
+ assert(false && "uncaught debug exception");
+ }
+ }
+
+private:
+ // FIXME Add tests here
+};
+
+int main()
+{
+ using SetAlloc = test_allocator<int>;
+ using MapAlloc = test_allocator<std::pair<const int, int>>;
+ // FIXME: Add debug mode to these containers
+ if ((false)) {
+ AssociativeContainerChecks<
+ std::set<int, std::less<int>, SetAlloc>, CT_Set>::run();
+ AssociativeContainerChecks<
+ std::multiset<int, std::less<int>, SetAlloc>, CT_MultiSet>::run();
+ AssociativeContainerChecks<
+ std::map<int, int, std::less<int>, MapAlloc>, CT_Map>::run();
+ AssociativeContainerChecks<
+ std::multimap<int, int, std::less<int>, MapAlloc>, CT_MultiMap>::run();
+ }
+}
diff --git a/test/libcxx/debug/containers/db_sequence_container_iterators.pass.cpp b/test/libcxx/debug/containers/db_sequence_container_iterators.pass.cpp
new file mode 100644
index 000000000000..46f960c15b1e
--- /dev/null
+++ b/test/libcxx/debug/containers/db_sequence_container_iterators.pass.cpp
@@ -0,0 +1,265 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// UNSUPPORTED: libcpp-no-exceptions, libcpp-no-if-constexpr
+
+// test container debugging
+
+#define _LIBCPP_DEBUG 1
+#define _LIBCPP_DEBUG_USE_EXCEPTIONS
+#include <forward_list>
+#include <list>
+#include <vector>
+#include <deque>
+#include "debug_mode_helper.h"
+
+using namespace IteratorDebugChecks;
+
+template <class Container, ContainerType CT>
+struct SequenceContainerChecks : BasicContainerChecks<Container, CT> {
+ using Base = BasicContainerChecks<Container, CT>;
+ using value_type = typename Container::value_type;
+ using allocator_type = typename Container::allocator_type;
+ using iterator = typename Container::iterator;
+ using const_iterator = typename Container::const_iterator;
+
+ using Base::makeContainer;
+ using Base::makeValueType;
+public:
+ static void run() {
+ Base::run();
+ try {
+ FrontOnEmptyContainer();
+ if constexpr (CT != CT_ForwardList) {
+ AssignInvalidates();
+ BackOnEmptyContainer();
+ InsertIterValue();
+ InsertIterSizeValue();
+ InsertIterIterIter();
+ EmplaceIterValue();
+ EraseIterIter();
+ }
+ if constexpr (CT == CT_Vector || CT == CT_Deque || CT == CT_List) {
+ PopBack();
+ }
+ if constexpr (CT == CT_List || CT == CT_Deque) {
+ PopFront(); // FIXME: Run with forward list as well
+ }
+ } catch (...) {
+ assert(false && "uncaught debug exception");
+ }
+ }
+
+private:
+ static void AssignInvalidates() {
+ CHECKPOINT("assign(Size, Value)");
+ Container C(allocator_type{});
+ iterator it1, it2, it3;
+ auto reset = [&]() {
+ C = makeContainer(3);
+ it1 = C.begin();
+ it2 = ++C.begin();
+ it3 = C.end();
+ };
+ auto check = [&]() {
+ CHECK_DEBUG_THROWS( C.erase(it1) );
+ CHECK_DEBUG_THROWS( C.erase(it2) );
+ CHECK_DEBUG_THROWS( C.erase(it3, C.end()) );
+ };
+ reset();
+ C.assign(2, makeValueType(4));
+ check();
+ reset();
+ CHECKPOINT("assign(Iter, Iter)");
+ std::vector<value_type> V = {
+ makeValueType(1),
+ makeValueType(2),
+ makeValueType(3)
+ };
+ C.assign(V.begin(), V.end());
+ check();
+ reset();
+ CHECKPOINT("assign(initializer_list)");
+ C.assign({makeValueType(1), makeValueType(2), makeValueType(3)});
+ check();
+ }
+
+ static void BackOnEmptyContainer() {
+ CHECKPOINT("testing back on empty");
+ Container C = makeContainer(1);
+ Container const& CC = C;
+ (void)C.back();
+ (void)CC.back();
+ C.clear();
+ CHECK_DEBUG_THROWS( C.back() );
+ CHECK_DEBUG_THROWS( CC.back() );
+ }
+
+ static void FrontOnEmptyContainer() {
+ CHECKPOINT("testing front on empty");
+ Container C = makeContainer(1);
+ Container const& CC = C;
+ (void)C.front();
+ (void)CC.front();
+ C.clear();
+ CHECK_DEBUG_THROWS( C.front() );
+ CHECK_DEBUG_THROWS( CC.front() );
+ }
+
+ static void EraseIterIter() {
+ CHECKPOINT("testing erase iter iter invalidation");
+ Container C1 = makeContainer(3);
+ iterator it1 = C1.begin();
+ iterator it1_next = ++C1.begin();
+ iterator it1_after_next = ++C1.begin();
+ ++it1_after_next;
+ iterator it1_back = --C1.end();
+ assert(it1_next != it1_back);
+ if (CT == CT_Vector) {
+ CHECK_DEBUG_THROWS( C1.erase(it1_next, it1) ); // bad range
+ }
+ C1.erase(it1, it1_after_next);
+ CHECK_DEBUG_THROWS( C1.erase(it1) );
+ CHECK_DEBUG_THROWS( C1.erase(it1_next) );
+ if (CT == CT_List) {
+ C1.erase(it1_back);
+ } else {
+ CHECK_DEBUG_THROWS( C1.erase(it1_back) );
+ }
+ }
+
+ static void PopBack() {
+ CHECKPOINT("testing pop_back() invalidation");
+ Container C1 = makeContainer(2);
+ iterator it1 = C1.end();
+ --it1;
+ C1.pop_back();
+ CHECK_DEBUG_THROWS( C1.erase(it1) );
+ C1.erase(C1.begin());
+ assert(C1.size() == 0);
+ CHECK_DEBUG_THROWS( C1.pop_back() );
+ }
+
+ static void PopFront() {
+ CHECKPOINT("testing pop_front() invalidation");
+ Container C1 = makeContainer(2);
+ iterator it1 = C1.begin();
+ C1.pop_front();
+ CHECK_DEBUG_THROWS( C1.erase(it1) );
+ C1.erase(C1.begin());
+ assert(C1.size() == 0);
+ CHECK_DEBUG_THROWS( C1.pop_front() );
+ }
+
+ static void InsertIterValue() {
+ CHECKPOINT("testing insert(iter, value)");
+ Container C1 = makeContainer(2);
+ iterator it1 = C1.begin();
+ iterator it1_next = it1;
+ ++it1_next;
+ Container C2 = C1;
+ const value_type value = makeValueType(3);
+ value_type rvalue = makeValueType(3);
+ CHECK_DEBUG_THROWS( C2.insert(it1, value) ); // wrong container
+ CHECK_DEBUG_THROWS( C2.insert(it1, std::move(rvalue)) ); // wrong container
+ C1.insert(it1_next, value);
+ if (CT == CT_List) {
+ C1.insert(it1_next, value);
+ C1.insert(it1, value);
+ C1.insert(it1_next, std::move(rvalue));
+ C1.insert(it1, std::move(rvalue));
+ } else {
+ CHECK_DEBUG_THROWS( C1.insert(it1_next, value) ); // invalidated iterator
+ CHECK_DEBUG_THROWS( C1.insert(it1, value) ); // invalidated iterator
+ CHECK_DEBUG_THROWS( C1.insert(it1_next, std::move(rvalue)) ); // invalidated iterator
+ CHECK_DEBUG_THROWS( C1.insert(it1, std::move(rvalue)) ); // invalidated iterator
+ }
+ }
+
+ static void EmplaceIterValue() {
+ CHECKPOINT("testing emplace(iter, value)");
+ Container C1 = makeContainer(2);
+ iterator it1 = C1.begin();
+ iterator it1_next = it1;
+ ++it1_next;
+ Container C2 = C1;
+ const value_type value = makeValueType(3);
+ CHECK_DEBUG_THROWS( C2.emplace(it1, value) ); // wrong container
+ CHECK_DEBUG_THROWS( C2.emplace(it1, makeValueType(4)) ); // wrong container
+ C1.emplace(it1_next, value);
+ if (CT == CT_List) {
+ C1.emplace(it1_next, value);
+ C1.emplace(it1, value);
+ } else {
+ CHECK_DEBUG_THROWS( C1.emplace(it1_next, value) ); // invalidated iterator
+ CHECK_DEBUG_THROWS( C1.emplace(it1, value) ); // invalidated iterator
+ }
+ }
+
+ static void InsertIterSizeValue() {
+ CHECKPOINT("testing insert(iter, size, value)");
+ Container C1 = makeContainer(2);
+ iterator it1 = C1.begin();
+ iterator it1_next = it1;
+ ++it1_next;
+ Container C2 = C1;
+ const value_type value = makeValueType(3);
+ CHECK_DEBUG_THROWS( C2.insert(it1, 1, value) ); // wrong container
+ C1.insert(it1_next, 2, value);
+ if (CT == CT_List) {
+ C1.insert(it1_next, 3, value);
+ C1.insert(it1, 1, value);
+ } else {
+ CHECK_DEBUG_THROWS( C1.insert(it1_next, 1, value) ); // invalidated iterator
+ CHECK_DEBUG_THROWS( C1.insert(it1, 1, value) ); // invalidated iterator
+ }
+ }
+
+ static void InsertIterIterIter() {
+ CHECKPOINT("testing insert(iter, iter, iter)");
+ Container C1 = makeContainer(2);
+ iterator it1 = C1.begin();
+ iterator it1_next = it1;
+ ++it1_next;
+ Container C2 = C1;
+ std::vector<value_type> V = {
+ makeValueType(1),
+ makeValueType(2),
+ makeValueType(3)
+ };
+ CHECK_DEBUG_THROWS( C2.insert(it1, V.begin(), V.end()) ); // wrong container
+ C1.insert(it1_next, V.begin(), V.end());
+ if (CT == CT_List) {
+ C1.insert(it1_next, V.begin(), V.end());
+ C1.insert(it1, V.begin(), V.end());
+ } else {
+ CHECK_DEBUG_THROWS( C1.insert(it1_next, V.begin(), V.end()) ); // invalidated iterator
+ CHECK_DEBUG_THROWS( C1.insert(it1, V.begin(), V.end()) ); // invalidated iterator
+ }
+ }
+};
+
+int main()
+{
+ using Alloc = test_allocator<int>;
+ {
+ SequenceContainerChecks<std::list<int, Alloc>, CT_List>::run();
+ SequenceContainerChecks<std::vector<int, Alloc>, CT_Vector>::run();
+ }
+ // FIXME these containers don't support iterator debugging
+ if ((false)) {
+ SequenceContainerChecks<
+ std::vector<bool, test_allocator<bool>>, CT_VectorBool>::run();
+ SequenceContainerChecks<
+ std::forward_list<int, Alloc>, CT_ForwardList>::run();
+ SequenceContainerChecks<
+ std::deque<int, Alloc>, CT_Deque>::run();
+ }
+}
diff --git a/test/libcxx/debug/containers/db_string.pass.cpp b/test/libcxx/debug/containers/db_string.pass.cpp
new file mode 100644
index 000000000000..ee1634140ff6
--- /dev/null
+++ b/test/libcxx/debug/containers/db_string.pass.cpp
@@ -0,0 +1,96 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// UNSUPPORTED: libcpp-no-exceptions, libcpp-no-if-constexpr
+
+// test container debugging
+
+#define _LIBCPP_DEBUG 1
+#define _LIBCPP_DEBUG_USE_EXCEPTIONS
+#include <string>
+#include <vector>
+
+#include "test_macros.h"
+#include "debug_mode_helper.h"
+
+using namespace IteratorDebugChecks;
+
+typedef std::basic_string<char, std::char_traits<char>, test_allocator<char>> StringType;
+
+template <class Container = StringType, ContainerType CT = CT_String>
+struct StringContainerChecks : BasicContainerChecks<Container, CT> {
+ using Base = BasicContainerChecks<Container, CT_String>;
+ using value_type = typename Container::value_type;
+ using allocator_type = typename Container::allocator_type;
+ using iterator = typename Container::iterator;
+ using const_iterator = typename Container::const_iterator;
+
+ using Base::makeContainer;
+ using Base::makeValueType;
+
+public:
+ static void run() {
+ Base::run_iterator_tests();
+ // FIXME: get these passing
+ // Base::run_allocator_aware_tests();
+ try {
+ for (int N : {3, 128}) {
+ FrontOnEmptyContainer(N);
+ BackOnEmptyContainer(N);
+ PopBack(N);
+ }
+ } catch (...) {
+ assert(false && "uncaught debug exception");
+ }
+ }
+
+private:
+ static void BackOnEmptyContainer(int N) {
+ CHECKPOINT("testing back on empty");
+ Container C = makeContainer(N);
+ Container const& CC = C;
+ iterator it = --C.end();
+ (void)C.back();
+ (void)CC.back();
+ C.pop_back();
+ CHECK_DEBUG_THROWS( C.erase(it) );
+ C.clear();
+ CHECK_DEBUG_THROWS( C.back() );
+ CHECK_DEBUG_THROWS( CC.back() );
+ }
+
+ static void FrontOnEmptyContainer(int N) {
+ CHECKPOINT("testing front on empty");
+ Container C = makeContainer(N);
+ Container const& CC = C;
+ (void)C.front();
+ (void)CC.front();
+ C.clear();
+ CHECK_DEBUG_THROWS( C.front() );
+ CHECK_DEBUG_THROWS( CC.front() );
+ }
+
+ static void PopBack(int N) {
+ CHECKPOINT("testing pop_back() invalidation");
+ Container C1 = makeContainer(N);
+ iterator it1 = C1.end();
+ --it1;
+ C1.pop_back();
+ CHECK_DEBUG_THROWS( C1.erase(it1) );
+ C1.erase(C1.begin(), C1.end());
+ assert(C1.size() == 0);
+ CHECK_DEBUG_THROWS( C1.pop_back() );
+ }
+};
+
+int main()
+{
+ StringContainerChecks<>::run();
+}
diff --git a/test/libcxx/debug/containers/db_unord_container_tests.pass.cpp b/test/libcxx/debug/containers/db_unord_container_tests.pass.cpp
new file mode 100644
index 000000000000..708fc7f8b950
--- /dev/null
+++ b/test/libcxx/debug/containers/db_unord_container_tests.pass.cpp
@@ -0,0 +1,66 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// UNSUPPORTED: libcpp-no-exceptions, libcpp-no-if-constexpr
+
+// test container debugging
+
+#define _LIBCPP_DEBUG 1
+#define _LIBCPP_DEBUG_USE_EXCEPTIONS
+#include <unordered_map>
+#include <unordered_set>
+#include <utility>
+#include <cassert>
+#include "debug_mode_helper.h"
+
+using namespace IteratorDebugChecks;
+
+template <class Container, ContainerType CT>
+struct UnorderedContainerChecks : BasicContainerChecks<Container, CT> {
+ using Base = BasicContainerChecks<Container, CT>;
+ using value_type = typename Container::value_type;
+ using iterator = typename Container::iterator;
+ using const_iterator = typename Container::const_iterator;
+ using traits = std::iterator_traits<iterator>;
+ using category = typename traits::iterator_category;
+
+ using Base::makeContainer;
+public:
+ static void run() {
+ Base::run();
+ try {
+ // FIXME
+ } catch (...) {
+ assert(false && "uncaught debug exception");
+ }
+ }
+private:
+
+};
+
+int main()
+{
+ using SetAlloc = test_allocator<int>;
+ using MapAlloc = test_allocator<std::pair<const int, int>>;
+ {
+ UnorderedContainerChecks<
+ std::unordered_map<int, int, std::hash<int>, std::equal_to<int>, MapAlloc>,
+ CT_UnorderedMap>::run();
+ UnorderedContainerChecks<
+ std::unordered_set<int, std::hash<int>, std::equal_to<int>, SetAlloc>,
+ CT_UnorderedSet>::run();
+ UnorderedContainerChecks<
+ std::unordered_multimap<int, int, std::hash<int>, std::equal_to<int>, MapAlloc>,
+ CT_UnorderedMultiMap>::run();
+ UnorderedContainerChecks<
+ std::unordered_multiset<int, std::hash<int>, std::equal_to<int>, SetAlloc>,
+ CT_UnorderedMultiSet>::run();
+ }
+}