123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405 |
- // 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)
- //
|