Fix debug mode for vector/list and cleanup tests

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@290657 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eric Fiselier
2016-12-28 06:06:09 +00:00
parent 72a67ff116
commit fb342388df
28 changed files with 410 additions and 900 deletions

View File

@@ -1,32 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
// <list>
// Call back() on empty container.
#define _LIBCPP_DEBUG 1
#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
#include <list>
#include <cassert>
#include <iterator>
#include <exception>
#include <cstdlib>
int main()
{
typedef int T;
typedef std::list<T> C;
C c(1);
assert(c.back() == 0);
c.clear();
assert(c.back() == 0);
assert(false);
}

View File

@@ -1,30 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
// <list>
// Call back() on empty const container.
#define _LIBCPP_DEBUG 1
#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
#include <list>
#include <cassert>
#include <iterator>
#include <exception>
#include <cstdlib>
int main()
{
typedef int T;
typedef std::list<T> C;
const C c;
assert(c.back() == 0);
assert(false);
}

View File

@@ -1,30 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
// <list>
// Call front() on empty const container.
#define _LIBCPP_DEBUG 1
#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
#include <list>
#include <cassert>
#include <iterator>
#include <exception>
#include <cstdlib>
int main()
{
typedef int T;
typedef std::list<T> C;
const C c;
assert(c.front() == 0);
assert(false);
}

View File

@@ -1,32 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
// <list>
// Call front() on empty container.
#define _LIBCPP_DEBUG 1
#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
#include <list>
#include <cassert>
#include <iterator>
#include <exception>
#include <cstdlib>
int main()
{
typedef int T;
typedef std::list<T> C;
C c(1);
assert(c.front() == 0);
c.clear();
assert(c.front() == 0);
assert(false);
}

View File

@@ -1,33 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
// <list>
// Decrement iterator prior to begin.
#define _LIBCPP_DEBUG 1
#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
#include <list>
#include <cassert>
#include <iterator>
#include <exception>
#include <cstdlib>
int main()
{
typedef int T;
typedef std::list<T> C;
C c(1);
C::iterator i = c.end();
--i;
assert(i == c.begin());
--i;
assert(false);
}

View File

@@ -1,33 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
// <list>
// Increment iterator past end.
#define _LIBCPP_DEBUG 1
#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
#include <list>
#include <cassert>
#include <iterator>
#include <exception>
#include <cstdlib>
int main()
{
typedef int T;
typedef std::list<T> C;
C c(1);
C::iterator i = c.begin();
++i;
assert(i == c.end());
++i;
assert(false);
}

View File

@@ -1,32 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
// <list>
// Dereference non-dereferenceable iterator.
#define _LIBCPP_DEBUG 1
#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
#include <list>
#include <cassert>
#include <iterator>
#include <exception>
#include <cstdlib>
int main()
{
typedef int T;
typedef std::list<T> C;
C c(1);
C::iterator i = c.end();
T j = *i;
assert(false);
((void)j);
}

View File

@@ -1,59 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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
// UNSUPPORTED: libcpp-no-exceptions
// <list>
// Operations on "NULL" iterators
#define _LIBCPP_DEBUG 1
#define _LIBCPP_ASSERT(x, m) do { if (!x) throw 1; } while(0)
#include <list>
#include <cassert>
#include <iterator>
#include <exception>
#include <cstdlib>
struct S { int val; };
int main()
{
{
unsigned lib_asserts;
typedef S T;
typedef std::list<T> C;
C::iterator i{};
C::const_iterator ci{};
lib_asserts = 0;
try { ++i; } catch (int) { ++lib_asserts; }
try { i++; } catch (int) { ++lib_asserts; }
try { ++ci; } catch (int) { ++lib_asserts; }
try { ci++; } catch (int) { ++lib_asserts; }
assert(lib_asserts == 4);
lib_asserts = 0;
try { --i; } catch (int) { ++lib_asserts; }
try { i--; } catch (int) { ++lib_asserts; }
try { --ci; } catch (int) { ++lib_asserts; }
try { ci--; } catch (int) { ++lib_asserts; }
assert(lib_asserts == 4);
lib_asserts = 0;
try { *i; } catch (int) { ++lib_asserts; }
try { *ci; } catch (int) { ++lib_asserts; }
try { (void) i->val; } catch (int) { ++lib_asserts; }
try { (void) ci->val; } catch (int) { ++lib_asserts; }
assert(lib_asserts == 4);
}
}

View File

@@ -1,36 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
// <list>
// template <class T, class Alloc>
// void swap(list<T,Alloc>& x, list<T,Alloc>& y);
#define _LIBCPP_DEBUG 1
#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
#include <list>
#include <cstdlib>
#include <cassert>
int main()
{
int a1[] = {1, 3, 7, 9, 10};
int a2[] = {0, 2, 4, 5, 6, 8, 11};
std::list<int> c1(a1, a1+sizeof(a1)/sizeof(a1[0]));
std::list<int> c2(a2, a2+sizeof(a2)/sizeof(a2[0]));
std::list<int>::iterator i1 = c1.begin();
std::list<int>::iterator i2 = c2.begin();
swap(c1, c2);
c1.erase(i2);
c2.erase(i1);
std::list<int>::iterator j = i1;
c1.erase(i1); // called with iterator not refering to list.
assert(false);
}

View File

@@ -1,36 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
// <list>
// template <class T, class Alloc>
// void swap(list<T,Alloc>& x, list<T,Alloc>& y);
#define _LIBCPP_DEBUG 1
#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
#include <list>
#include <cassert>
#include "test_allocator.h"
#include "min_allocator.h"
int main()
{
// allocators do not compare equal
{
int a1[] = {1, 3, 7, 9, 10};
int a2[] = {0, 2, 4, 5, 6, 8, 11};
typedef test_allocator<int> A;
std::list<int, A> c1(a1, a1+sizeof(a1)/sizeof(a1[0]), A(1));
std::list<int, A> c2(a2, a2+sizeof(a2)/sizeof(a2[0]), A(2));
swap(c1, c2);
assert(false);
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}