diff options
Diffstat (limited to 'src/boost/libs/any/test/any_test.cpp')
-rw-r--r-- | src/boost/libs/any/test/any_test.cpp | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/src/boost/libs/any/test/any_test.cpp b/src/boost/libs/any/test/any_test.cpp new file mode 100644 index 00000000..6fbcbd91 --- /dev/null +++ b/src/boost/libs/any/test/any_test.cpp @@ -0,0 +1,405 @@ +// what: unit tests for variant type boost::any +// who: contributed by Kevlin Henney +// when: July 2001, 2013, 2014 +// where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95 + +#include <cstdlib> +#include <string> +#include <vector> +#include <utility> + +#include <boost/any.hpp> +#include "test.hpp" + +namespace any_tests +{ + typedef test<const char *, void (*)()> test_case; + typedef const test_case * test_case_iterator; + + extern const test_case_iterator begin, end; +} + +int main() +{ + using namespace any_tests; + tester<test_case_iterator> test_suite(begin, end); + return test_suite() ? EXIT_SUCCESS : EXIT_FAILURE; +} + +namespace any_tests // test suite +{ + void test_default_ctor(); + void test_converting_ctor(); + void test_copy_ctor(); + void test_copy_assign(); + void test_converting_assign(); + void test_bad_cast(); + void test_swap(); + void test_null_copying(); + void test_cast_to_reference(); + void test_with_array(); + void test_with_func(); + void test_clear(); + void test_vectors(); + void test_addressof(); + + const test_case test_cases[] = + { + { "default construction", test_default_ctor }, + { "single argument construction", test_converting_ctor }, + { "copy construction", test_copy_ctor }, + { "copy assignment operator", test_copy_assign }, + { "converting assignment operator", test_converting_assign }, + { "failed custom keyword cast", test_bad_cast }, + { "swap member function", test_swap }, + { "copying operations on a null", test_null_copying }, + { "cast to reference types", test_cast_to_reference }, + { "storing an array inside", test_with_array }, + { "implicit cast of returned value",test_with_func }, + { "clear() methods", test_clear }, + { "testing with vectors", test_vectors }, + { "class with operator&()", test_addressof } + }; + + const test_case_iterator begin = test_cases; + const test_case_iterator end = + test_cases + (sizeof test_cases / sizeof *test_cases); + + + + struct copy_counter + { + + public: + + copy_counter() {} + copy_counter(const copy_counter&) { ++count; } + copy_counter& operator=(const copy_counter&) { ++count; return *this; } + static int get_count() { return count; } + + private: + + static int count; + + }; + + int copy_counter::count = 0; +} + +namespace any_tests // test definitions +{ + using namespace boost; + + void test_default_ctor() + { + const any value; + + check_true(value.empty(), "empty"); + check_null(any_cast<int>(&value), "any_cast<int>"); + check_equal(value.type(), boost::typeindex::type_id<void>(), "type"); + } + + void test_converting_ctor() + { + std::string text = "test message"; + any value = text; + + check_false(value.empty(), "empty"); + check_equal(value.type(), boost::typeindex::type_id<std::string>(), "type"); + check_null(any_cast<int>(&value), "any_cast<int>"); + check_non_null(any_cast<std::string>(&value), "any_cast<std::string>"); + check_equal( + any_cast<std::string>(value), text, + "comparing cast copy against original text"); + check_unequal( + any_cast<std::string>(&value), &text, + "comparing address in copy against original text"); + } + + void test_copy_ctor() + { + std::string text = "test message"; + any original = text, copy = original; + + check_false(copy.empty(), "empty"); + check_equal(boost::typeindex::type_index(original.type()), copy.type(), "type"); + check_equal( + any_cast<std::string>(original), any_cast<std::string>(copy), + "comparing cast copy against original"); + check_equal( + text, any_cast<std::string>(copy), + "comparing cast copy against original text"); + check_unequal( + any_cast<std::string>(&original), + any_cast<std::string>(©), + "comparing address in copy against original"); + } + + void test_copy_assign() + { + std::string text = "test message"; + any original = text, copy; + any * assign_result = &(copy = original); + + check_false(copy.empty(), "empty"); + check_equal(boost::typeindex::type_index(original.type()), copy.type(), "type"); + check_equal( + any_cast<std::string>(original), any_cast<std::string>(copy), + "comparing cast copy against cast original"); + check_equal( + text, any_cast<std::string>(copy), + "comparing cast copy against original text"); + check_unequal( + any_cast<std::string>(&original), + any_cast<std::string>(©), + "comparing address in copy against original"); + check_equal(assign_result, ©, "address of assignment result"); + } + + void test_converting_assign() + { + std::string text = "test message"; + any value; + any * assign_result = &(value = text); + + check_false(value.empty(), "type"); + check_equal(value.type(), boost::typeindex::type_id<std::string>(), "type"); + check_null(any_cast<int>(&value), "any_cast<int>"); + check_non_null(any_cast<std::string>(&value), "any_cast<std::string>"); + check_equal( + any_cast<std::string>(value), text, + "comparing cast copy against original text"); + check_unequal( + any_cast<std::string>(&value), + &text, + "comparing address in copy against original text"); + check_equal(assign_result, &value, "address of assignment result"); + } + + void test_bad_cast() + { + std::string text = "test message"; + any value = text; + + TEST_CHECK_THROW( + any_cast<const char *>(value), + bad_any_cast, + "any_cast to incorrect type"); + } + + void test_swap() + { + std::string text = "test message"; + any original = text, swapped; + std::string * original_ptr = any_cast<std::string>(&original); + any * swap_result = &original.swap(swapped); + + check_true(original.empty(), "empty on original"); + check_false(swapped.empty(), "empty on swapped"); + check_equal(swapped.type(), boost::typeindex::type_id<std::string>(), "type"); + check_equal( + text, any_cast<std::string>(swapped), + "comparing swapped copy against original text"); + check_non_null(original_ptr, "address in pre-swapped original"); + check_equal( + original_ptr, + any_cast<std::string>(&swapped), + "comparing address in swapped against original"); + check_equal(swap_result, &original, "address of swap result"); + + any copy1 = copy_counter(); + any copy2 = copy_counter(); + int count = copy_counter::get_count(); + swap(copy1, copy2); + check_equal(count, copy_counter::get_count(), "checking that free swap doesn't make any copies."); + } + + void test_null_copying() + { + const any null; + any copied = null, assigned; + assigned = null; + + check_true(null.empty(), "empty on null"); + check_true(copied.empty(), "empty on copied"); + check_true(assigned.empty(), "empty on copied"); + } + + void test_cast_to_reference() + { + any a(137); + const any b(a); + + int & ra = any_cast<int &>(a); + int const & ra_c = any_cast<int const &>(a); + int volatile & ra_v = any_cast<int volatile &>(a); + int const volatile & ra_cv = any_cast<int const volatile&>(a); + + check_true( + &ra == &ra_c && &ra == &ra_v && &ra == &ra_cv, + "cv references to same obj"); + + int const & rb_c = any_cast<int const &>(b); + int const volatile & rb_cv = any_cast<int const volatile &>(b); + + check_true(&rb_c == &rb_cv, "cv references to copied const obj"); + check_true(&ra != &rb_c, "copies hold different objects"); + + ++ra; + int incremented = any_cast<int>(a); + check_true(incremented == 138, "increment by reference changes value"); + + TEST_CHECK_THROW( + any_cast<char &>(a), + bad_any_cast, + "any_cast to incorrect reference type"); + + TEST_CHECK_THROW( + any_cast<const char &>(b), + bad_any_cast, + "any_cast to incorrect const reference type"); + } + + void test_with_array() + { + any value1("Char array"); + any value2; + value2 = "Char array"; + + check_false(value1.empty(), "type"); + check_false(value2.empty(), "type"); + + check_equal(value1.type(), boost::typeindex::type_id<const char*>(), "type"); + check_equal(value2.type(), boost::typeindex::type_id<const char*>(), "type"); + + check_non_null(any_cast<const char*>(&value1), "any_cast<const char*>"); + check_non_null(any_cast<const char*>(&value2), "any_cast<const char*>"); + } + + const std::string& returning_string1() + { + static const std::string ret("foo"); + return ret; + } + + std::string returning_string2() + { + static const std::string ret("foo"); + return ret; + } + + void test_with_func() + { + std::string s; + s = any_cast<std::string>(returning_string1()); + s = any_cast<const std::string&>(returning_string1()); + + s = any_cast<std::string>(returning_string2()); + s = any_cast<const std::string&>(returning_string2()); + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +#if !defined(__INTEL_COMPILER) && !defined(__ICL) && (!defined(_MSC_VER) || _MSC_VER != 1600) + // Intel compiler thinks that it must choose the `any_cast(const any&)` function + // instead of the `any_cast(const any&&)`. + // Bug was not reported because of missing premier support account + annoying + // registrations requirements. + + // MSVC-10 had a bug: + // + // any.hpp(291) : error C2440: 'return' : cannot convert. + // Conversion loses qualifiers + // any_test.cpp(304) : see reference to function template instantiation + // + // This issue was fixed in MSVC-11. + + s = any_cast<std::string&&>(returning_string1()); +#endif + + s = any_cast<std::string&&>(returning_string2()); +#endif + } + + + void test_clear() + { + std::string text = "test message"; + any value = text; + + check_false(value.empty(), "empty"); + + value.clear(); + check_true(value.empty(), "non-empty after clear"); + + value.clear(); + check_true(value.empty(), "non-empty after second clear"); + + value = text; + check_false(value.empty(), "empty"); + + value.clear(); + check_true(value.empty(), "non-empty after clear"); + } + + // Following tests cover the case from #9462 + // https://svn.boost.org/trac/boost/ticket/9462 + boost::any makeVec() + { + return std::vector<int>(100 /*size*/, 7 /*value*/); + } + + void test_vectors() + { + const std::vector<int>& vec = boost::any_cast<std::vector<int> >(makeVec()); + check_equal(vec.size(), 100u, "size of vector extracted from boost::any"); + check_equal(vec.back(), 7, "back value of vector extracted from boost::any"); + check_equal(vec.front(), 7, "front value of vector extracted from boost::any"); + + std::vector<int> vec1 = boost::any_cast<std::vector<int> >(makeVec()); + check_equal(vec1.size(), 100u, "size of second vector extracted from boost::any"); + check_equal(vec1.back(), 7, "back value of second vector extracted from boost::any"); + check_equal(vec1.front(), 7, "front value of second vector extracted from boost::any"); + + } + + template<typename T> + class class_with_address_op { + public: + class_with_address_op(const T* p) + : ptr(p) + {} + + const T** operator &() { + return &ptr; + } + + const T* get() const { + return ptr; + } + + private: + const T* ptr; + }; + + void test_addressof() + { + int val = 10; + const int* ptr = &val; + class_with_address_op<int> obj(ptr); + boost::any test_val(obj); + + class_with_address_op<int> returned_obj = boost::any_cast<class_with_address_op<int> >(test_val); + check_equal(&val, returned_obj.get(), "any_cast incorrectly works with type that has operator&(): addresses differ"); + + check_true(!!boost::any_cast<class_with_address_op<int> >(&test_val), "any_cast incorrectly works with type that has operator&()"); + check_equal(boost::unsafe_any_cast<class_with_address_op<int> >(&test_val)->get(), ptr, "unsafe_any_cast incorrectly works with type that has operator&()"); + } + +} + +// Copyright Kevlin Henney, 2000, 2001. All rights reserved. +// Copyright Antony Polukhin, 2013-2019. +// +// Distributed under 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) +// |