diff options
Diffstat (limited to 'test/libcxx/debug/containers')
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(); + } +} |