diff --git a/test/container/Jamfile.v2 b/test/container/Jamfile.v2 new file mode 100644 index 00000000..a0dcd090 --- /dev/null +++ b/test/container/Jamfile.v2 @@ -0,0 +1,17 @@ + +# Copyright Daniel James 2005. Use, modification, and distribution are +# subject to the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +import testing ; + +project unordered-test/container + : requirements + intel-linux:"-strict_ansi -cxxlib-icc" + ; + +test-suite container-tests + : + [ run set_compile.cpp ] + [ run map_compile.cpp ] + ; diff --git a/test/container/compile_tests.hpp b/test/container/compile_tests.hpp new file mode 100644 index 00000000..1016f870 --- /dev/null +++ b/test/container/compile_tests.hpp @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include +#include +#include +#include "../helpers/check_return_type.hpp" + +typedef long double comparison_type; + +template void sink(T const&) {} + +template +void container_test(X& r, T& value) +{ + typedef typename X::iterator iterator; + typedef typename X::const_iterator const_iterator; + typedef typename X::difference_type difference_type; + typedef typename X::size_type size_type; + + typedef typename boost::iterator_value::type iterator_value_type; + typedef typename boost::iterator_value::type const_iterator_value_type; + typedef typename boost::iterator_difference::type iterator_difference_type; + typedef typename boost::iterator_difference::type const_iterator_difference_type; + + typedef typename X::value_type value_type; + typedef typename X::reference reference; + typedef typename X::const_reference const_reference; + + // value_type + + BOOST_MPL_ASSERT((boost::is_same)); + boost::function_requires >(); + + // reference_type / const_reference_type + + // TODO: 'lvalue of T' + BOOST_MPL_ASSERT((boost::is_same)); + // TODO: 'const lvalue of T' + BOOST_MPL_ASSERT((boost::is_same)); + + // iterator + + boost::function_requires >(); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_convertible)); + + // const_iterator + + // TODO: Test that it's a constant iterator? + boost::function_requires >(); + BOOST_MPL_ASSERT((boost::is_same)); + + // difference_type + + BOOST_MPL_ASSERT((boost::mpl::bool_< + std::numeric_limits::is_signed>)); + BOOST_MPL_ASSERT((boost::mpl::bool_< + std::numeric_limits::is_integer>)); + BOOST_MPL_ASSERT((boost::is_same)); + BOOST_MPL_ASSERT((boost::is_same)); + + // size_type + + BOOST_MPL_ASSERT_NOT((boost::mpl::bool_< + std::numeric_limits::is_signed>)); + BOOST_MPL_ASSERT((boost::mpl::bool_< + std::numeric_limits::is_integer>)); + + // size_type can represent any non-negative value type of difference_type + // I'm not sure about either of these tests... + size_type max_diff((std::numeric_limits::max)()); + difference_type converted_diff(max_diff); + BOOST_TEST((std::numeric_limits::max)() + == converted_diff); + + BOOST_TEST( + static_cast( + (std::numeric_limits::max)()) > + static_cast( + (std::numeric_limits::max)())); + + // I don't test the runtime post-conditions here. + X u; + BOOST_TEST(u.size() == 0); + BOOST_TEST(X().size() == 0); + + X a,b; + + sink(X(a)); + X u2(a); + X u3 = a; + + X* ptr = new X(); + X& a1 = *ptr; + (&a1)->~X(); + + X const a_const; + test::check_return_type::equals(a.begin()); + test::check_return_type::equals(a_const.begin()); + test::check_return_type::equals(a.end()); + test::check_return_type::equals(a_const.end()); + + // No tests for ==, != since they're not required for unordered containers. + + a.swap(b); + test::check_return_type::equals_ref(r = a); + test::check_return_type::equals(a.size()); + test::check_return_type::equals(a.max_size()); + test::check_return_type::convertible(a.empty()); +} diff --git a/test/container/map_compile.cpp b/test/container/map_compile.cpp new file mode 100644 index 00000000..281b9c62 --- /dev/null +++ b/test/container/map_compile.cpp @@ -0,0 +1,45 @@ + +// Copyright Daniel James 2006. Use, modification, and distribution are +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// This test creates the containers with members that meet their minimum +// requirements. Makes sure everything compiles and is defined correctly. + +#include + +#include +#include +#include "../objects/minimal.hpp" +#include "./compile_tests.hpp" + +int main() +{ + typedef std::pair value_type; + value_type value( + test::minimal::assignable::create(), + test::minimal::copy_constructible::create()); + + std::cout<<"Test unordered_map.\n"; + boost::unordered_map< + test::minimal::assignable, + test::minimal::copy_constructible, + test::minimal::hash, + test::minimal::equal_to, + test::minimal::allocator > map; + + container_test(map, value); + + std::cout<<"Test unordered_multimap.\n"; + boost::unordered_multimap< + test::minimal::assignable, + test::minimal::copy_constructible, + test::minimal::hash, + test::minimal::equal_to, + test::minimal::allocator > multimap; + + container_test(multimap, value); + + return boost::report_errors(); +} diff --git a/test/container/set_compile.cpp b/test/container/set_compile.cpp new file mode 100644 index 00000000..469f6630 --- /dev/null +++ b/test/container/set_compile.cpp @@ -0,0 +1,39 @@ + +// Copyright Daniel James 2006. Use, modification, and distribution are +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// This test creates the containers with members that meet their minimum +// requirements. Makes sure everything compiles and is defined correctly. + +#include + +#include +#include +#include "../objects/minimal.hpp" +#include "./compile_tests.hpp" + +int main() +{ + test::minimal::assignable assignable = test::minimal::assignable::create(); + + std::cout<<"Test unordered_set.\n"; + boost::unordered_set< + test::minimal::assignable, + test::minimal::hash, + test::minimal::equal_to, + test::minimal::allocator > set; + + container_test(set, assignable); + + std::cout<<"Test unordered_multiset.\n"; + boost::unordered_multiset< + test::minimal::assignable, + test::minimal::hash, + test::minimal::equal_to, + test::minimal::allocator > multiset; + + container_test(multiset, assignable); + + return boost::report_errors(); +} diff --git a/test/helpers/check_return_type.hpp b/test/helpers/check_return_type.hpp new file mode 100644 index 00000000..87ce7e28 --- /dev/null +++ b/test/helpers/check_return_type.hpp @@ -0,0 +1,38 @@ + +// Copyright Daniel James 2005-2006. Use, modification, and distribution are +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_UNORDERED_TEST_HELPERS_CHECK_RETURN_TYPE_HEADER) +#define BOOST_UNORDERED_TEST_HELPERS_CHECK_RETURN_TYPE_HEADER + +#include +#include +#include + +namespace test +{ + template + struct check_return_type + { + template + static void equals(T2) + { + BOOST_MPL_ASSERT((boost::is_same)); + } + + template + static void equals_ref(T2&) + { + BOOST_MPL_ASSERT((boost::is_same)); + } + + template + static void convertible(T2) + { + BOOST_MPL_ASSERT((boost::is_convertible)); + } + }; +} + +#endif diff --git a/test/objects/minimal.hpp b/test/objects/minimal.hpp new file mode 100644 index 00000000..5ed9c84d --- /dev/null +++ b/test/objects/minimal.hpp @@ -0,0 +1,245 @@ + +// Copyright Daniel James 2006. Use, modification, and distribution are +// subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_UNORDERED_OBJECTS_MINIMAL_HEADER) +#define BOOST_UNORDERED_OBJECTS_MINIMAL_HEADER + +#include + +namespace test +{ +namespace minimal +{ + class copy_constructible; + class assignable; + template class hash; + template class equal_to; + template class pointer; + template class const_pointer; + template class allocator; + + class copy_constructible + { + public: + static copy_constructible create() { return copy_constructible(); } + copy_constructible(copy_constructible const&) {} + ~copy_constructible() {} + private: + copy_constructible& operator=(copy_constructible const&); + copy_constructible() {} + }; + + class assignable + { + public: + static assignable create() { return assignable(); } + assignable(assignable const&) {} + assignable& operator=(assignable const&) { return *this; } + ~assignable() {} + private: + assignable() {} + }; + + template + class hash + { + public: + static hash create() { return hash(); } + // TODO: hash has to be default constructible for the default + // parameters. Maybe use an alternative version for testing + // other member functions. + // + // Or maybe it's required to be default constructible? + // The Container requirements include a default constructor. + hash() {} + hash(hash const&) {} + // TODO: Required to be assignable? + hash& operator=(hash const&) { return *this; } + ~hash() {} + + std::size_t operator()(T const& x) const { return 0; } + }; + + template + class equal_to + { + public: + static equal_to create() { return equal_to(); } + // TODO: equal_to has to be default constructible for the default + // parameters. Maybe use an alternative version for testing + // other member functions. + // + // Or maybe it's required to be default constructible? + // The Container requirements include a default constructor. + equal_to() {} + equal_to(equal_to const&) {} + // TODO: Required to be assignable? + equal_to& operator=(equal_to const&) { return *this; } + ~equal_to() {} + + bool operator()(T const& x, T const& y) const { return true; } + }; + + namespace detail + { + template + class pointer_base + { + protected: + pointer_base() : ptr_(0) {} + explicit pointer_base(T* ptr) : ptr_(ptr) {} + ~pointer_base() {} + Ptr& get() { return *static_cast(this); } + T* ptr_; + public: + typedef void (pointer_base::*bool_type)() const; + void this_type_does_not_support_comparisons() const {} + + T& operator*() const { return *ptr_; } + T* operator->() const { return ptr_; } + Ptr& operator++() { ++ptr_; return get(); } + Ptr operator++(int) { Ptr tmp(get()); ++ptr_; return tmp; } + Ptr operator+(int s) const { return Ptr(ptr_ + s); } + T& operator[](int s) const { return ptr_[s]; } + + operator bool_type() const { + return ptr_ ? + &pointer_base::this_type_does_not_support_comparisons + : 0; + } + + bool operator!() const { return !ptr_; } + bool operator==(Ptr const& x) const { return ptr_ == x.ptr_; } + bool operator!=(Ptr const& x) const { return ptr_ != x.ptr_; } + bool operator<(Ptr const& x) const { return ptr_ < x.ptr_; } + bool operator>(Ptr const& x) const { return ptr_ > x.ptr_; } + bool operator<=(Ptr const& x) const { return ptr_ <= x.ptr_; } + bool operator>=(Ptr const& x) const { return ptr_ >= x.ptr_; } + }; + } + + template class pointer; + template class const_pointer; + + template + class pointer : public detail::pointer_base, T> + { + friend class allocator; + friend class detail::pointer_base, T>; + friend class const_pointer; + typedef detail::pointer_base, T> base; + + pointer(T* ptr) : base(ptr) {} + + public: + pointer() : base() {} + + bool operator==(pointer const& x) const { return base::operator==(x); } + bool operator!=(pointer const& x) const { return base::operator!=(x); } + bool operator<(pointer const& x) const { return base::operator<(x);} + bool operator>(pointer const& x) const { return base::operator>(x);} + bool operator<=(pointer const& x) const { return base::operator<=(x);} + bool operator>=(pointer const& x) const { return base::operator<=(x);} + + bool operator==(const_pointer const& x) const { return x == *this; } + bool operator!=(const_pointer const& x) const { return x != *this; } + bool operator<(const_pointer const& x) const { return x > *this; } + bool operator>(const_pointer const& x) const { return x < *this; } + bool operator<=(const_pointer const& x) const { return x >= *this; } + bool operator>=(const_pointer const& x) const { return x <= *this; } + }; + + template + class const_pointer : public detail::pointer_base, T const> + { + friend class allocator; + friend class detail::pointer_base, T const>; + typedef detail::pointer_base, T const> base; + + const_pointer(T* ptr) : base(ptr) {} + + public: + const_pointer() : base() {} + const_pointer(pointer const& x) : base(x.ptr_) {} + + bool operator==(const_pointer const& x) const { return base::operator==(x); } + bool operator!=(const_pointer const& x) const { return base::operator!=(x); } + bool operator<(const_pointer const& x) const { return base::operator<(x);} + bool operator>(const_pointer const& x) const { return base::operator>(x);} + bool operator<=(const_pointer const& x) const { return base::operator<=(x);} + bool operator>=(const_pointer const& x) const { return base::operator<=(x);} + + bool operator==(pointer const& x) const { return operator==(const_pointer(x)); } + bool operator!=(pointer const& x) const { return operator!=(const_pointer(x)); } + bool operator<(pointer const& x) const { return operator<(const_pointer(x));} + bool operator>(pointer const& x) const { return operator>(const_pointer(x));} + bool operator<=(pointer const& x) const { return operator<=(const_pointer(x));} + bool operator>=(pointer const& x) const { return operator<=(const_pointer(x));} + }; + + template + class allocator + { + public: + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef pointer pointer; + typedef const_pointer const_pointer; + typedef T& reference; + typedef T const& const_reference; + typedef T value_type; + + template struct rebind { typedef allocator other; }; + + allocator() {} + allocator(allocator const&) {} + template allocator(allocator const&) {} + ~allocator() {} + + pointer address(reference r) { return pointer(&r); } + const_pointer address(const_reference r) { return const_pointer(&r); } + + pointer allocate(size_type n) { + return pointer(static_cast(::operator new(n * sizeof(T)))); + } + + pointer allocate(size_type n, const_pointer u) + { + return pointer(static_cast(::operator new(n * sizeof(T)))); + } + + void deallocate(pointer p, size_type n) + { + ::operator delete((void*) p.ptr_); + } + + void construct(pointer p, T const& t) { new((void*)p.ptr_) T(t); } + void destroy(pointer p) { ((T*)p.ptr_)->~T(); } + + size_type max_size() const { return 1000; } + private: + allocator& operator=(allocator const&); + }; + + template + inline bool operator==(allocator const& x, allocator const& y) + { + return true; + } + + template + inline bool operator!=(allocator const& x, allocator const& y) + { + return false; + } + + template + void swap(allocator& x, allocator& y) + { + } +} +} + +#endif