any_test.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. // what: unit tests for variant type boost::any
  2. // who: contributed by Kevlin Henney
  3. // when: July 2001, 2013, 2014
  4. // where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95
  5. #include <cstdlib>
  6. #include <string>
  7. #include <vector>
  8. #include <utility>
  9. #include <boost/any.hpp>
  10. #include "test.hpp"
  11. namespace any_tests
  12. {
  13. typedef test<const char *, void (*)()> test_case;
  14. typedef const test_case * test_case_iterator;
  15. extern const test_case_iterator begin, end;
  16. }
  17. int main()
  18. {
  19. using namespace any_tests;
  20. tester<test_case_iterator> test_suite(begin, end);
  21. return test_suite() ? EXIT_SUCCESS : EXIT_FAILURE;
  22. }
  23. namespace any_tests // test suite
  24. {
  25. void test_default_ctor();
  26. void test_converting_ctor();
  27. void test_copy_ctor();
  28. void test_copy_assign();
  29. void test_converting_assign();
  30. void test_bad_cast();
  31. void test_swap();
  32. void test_null_copying();
  33. void test_cast_to_reference();
  34. void test_with_array();
  35. void test_with_func();
  36. void test_clear();
  37. void test_vectors();
  38. void test_addressof();
  39. const test_case test_cases[] =
  40. {
  41. { "default construction", test_default_ctor },
  42. { "single argument construction", test_converting_ctor },
  43. { "copy construction", test_copy_ctor },
  44. { "copy assignment operator", test_copy_assign },
  45. { "converting assignment operator", test_converting_assign },
  46. { "failed custom keyword cast", test_bad_cast },
  47. { "swap member function", test_swap },
  48. { "copying operations on a null", test_null_copying },
  49. { "cast to reference types", test_cast_to_reference },
  50. { "storing an array inside", test_with_array },
  51. { "implicit cast of returned value",test_with_func },
  52. { "clear() methods", test_clear },
  53. { "testing with vectors", test_vectors },
  54. { "class with operator&()", test_addressof }
  55. };
  56. const test_case_iterator begin = test_cases;
  57. const test_case_iterator end =
  58. test_cases + (sizeof test_cases / sizeof *test_cases);
  59. struct copy_counter
  60. {
  61. public:
  62. copy_counter() {}
  63. copy_counter(const copy_counter&) { ++count; }
  64. copy_counter& operator=(const copy_counter&) { ++count; return *this; }
  65. static int get_count() { return count; }
  66. private:
  67. static int count;
  68. };
  69. int copy_counter::count = 0;
  70. }
  71. namespace any_tests // test definitions
  72. {
  73. using namespace boost;
  74. void test_default_ctor()
  75. {
  76. const any value;
  77. check_true(value.empty(), "empty");
  78. check_null(any_cast<int>(&value), "any_cast<int>");
  79. check_equal(value.type(), boost::typeindex::type_id<void>(), "type");
  80. }
  81. void test_converting_ctor()
  82. {
  83. std::string text = "test message";
  84. any value = text;
  85. check_false(value.empty(), "empty");
  86. check_equal(value.type(), boost::typeindex::type_id<std::string>(), "type");
  87. check_null(any_cast<int>(&value), "any_cast<int>");
  88. check_non_null(any_cast<std::string>(&value), "any_cast<std::string>");
  89. check_equal(
  90. any_cast<std::string>(value), text,
  91. "comparing cast copy against original text");
  92. check_unequal(
  93. any_cast<std::string>(&value), &text,
  94. "comparing address in copy against original text");
  95. }
  96. void test_copy_ctor()
  97. {
  98. std::string text = "test message";
  99. any original = text, copy = original;
  100. check_false(copy.empty(), "empty");
  101. check_equal(boost::typeindex::type_index(original.type()), copy.type(), "type");
  102. check_equal(
  103. any_cast<std::string>(original), any_cast<std::string>(copy),
  104. "comparing cast copy against original");
  105. check_equal(
  106. text, any_cast<std::string>(copy),
  107. "comparing cast copy against original text");
  108. check_unequal(
  109. any_cast<std::string>(&original),
  110. any_cast<std::string>(&copy),
  111. "comparing address in copy against original");
  112. }
  113. void test_copy_assign()
  114. {
  115. std::string text = "test message";
  116. any original = text, copy;
  117. any * assign_result = &(copy = original);
  118. check_false(copy.empty(), "empty");
  119. check_equal(boost::typeindex::type_index(original.type()), copy.type(), "type");
  120. check_equal(
  121. any_cast<std::string>(original), any_cast<std::string>(copy),
  122. "comparing cast copy against cast original");
  123. check_equal(
  124. text, any_cast<std::string>(copy),
  125. "comparing cast copy against original text");
  126. check_unequal(
  127. any_cast<std::string>(&original),
  128. any_cast<std::string>(&copy),
  129. "comparing address in copy against original");
  130. check_equal(assign_result, &copy, "address of assignment result");
  131. }
  132. void test_converting_assign()
  133. {
  134. std::string text = "test message";
  135. any value;
  136. any * assign_result = &(value = text);
  137. check_false(value.empty(), "type");
  138. check_equal(value.type(), boost::typeindex::type_id<std::string>(), "type");
  139. check_null(any_cast<int>(&value), "any_cast<int>");
  140. check_non_null(any_cast<std::string>(&value), "any_cast<std::string>");
  141. check_equal(
  142. any_cast<std::string>(value), text,
  143. "comparing cast copy against original text");
  144. check_unequal(
  145. any_cast<std::string>(&value),
  146. &text,
  147. "comparing address in copy against original text");
  148. check_equal(assign_result, &value, "address of assignment result");
  149. }
  150. void test_bad_cast()
  151. {
  152. std::string text = "test message";
  153. any value = text;
  154. TEST_CHECK_THROW(
  155. any_cast<const char *>(value),
  156. bad_any_cast,
  157. "any_cast to incorrect type");
  158. }
  159. void test_swap()
  160. {
  161. std::string text = "test message";
  162. any original = text, swapped;
  163. std::string * original_ptr = any_cast<std::string>(&original);
  164. any * swap_result = &original.swap(swapped);
  165. check_true(original.empty(), "empty on original");
  166. check_false(swapped.empty(), "empty on swapped");
  167. check_equal(swapped.type(), boost::typeindex::type_id<std::string>(), "type");
  168. check_equal(
  169. text, any_cast<std::string>(swapped),
  170. "comparing swapped copy against original text");
  171. check_non_null(original_ptr, "address in pre-swapped original");
  172. check_equal(
  173. original_ptr,
  174. any_cast<std::string>(&swapped),
  175. "comparing address in swapped against original");
  176. check_equal(swap_result, &original, "address of swap result");
  177. any copy1 = copy_counter();
  178. any copy2 = copy_counter();
  179. int count = copy_counter::get_count();
  180. swap(copy1, copy2);
  181. check_equal(count, copy_counter::get_count(), "checking that free swap doesn't make any copies.");
  182. }
  183. void test_null_copying()
  184. {
  185. const any null;
  186. any copied = null, assigned;
  187. assigned = null;
  188. check_true(null.empty(), "empty on null");
  189. check_true(copied.empty(), "empty on copied");
  190. check_true(assigned.empty(), "empty on copied");
  191. }
  192. void test_cast_to_reference()
  193. {
  194. any a(137);
  195. const any b(a);
  196. int & ra = any_cast<int &>(a);
  197. int const & ra_c = any_cast<int const &>(a);
  198. int volatile & ra_v = any_cast<int volatile &>(a);
  199. int const volatile & ra_cv = any_cast<int const volatile&>(a);
  200. check_true(
  201. &ra == &ra_c && &ra == &ra_v && &ra == &ra_cv,
  202. "cv references to same obj");
  203. int const & rb_c = any_cast<int const &>(b);
  204. int const volatile & rb_cv = any_cast<int const volatile &>(b);
  205. check_true(&rb_c == &rb_cv, "cv references to copied const obj");
  206. check_true(&ra != &rb_c, "copies hold different objects");
  207. ++ra;
  208. int incremented = any_cast<int>(a);
  209. check_true(incremented == 138, "increment by reference changes value");
  210. TEST_CHECK_THROW(
  211. any_cast<char &>(a),
  212. bad_any_cast,
  213. "any_cast to incorrect reference type");
  214. TEST_CHECK_THROW(
  215. any_cast<const char &>(b),
  216. bad_any_cast,
  217. "any_cast to incorrect const reference type");
  218. }
  219. void test_with_array()
  220. {
  221. any value1("Char array");
  222. any value2;
  223. value2 = "Char array";
  224. check_false(value1.empty(), "type");
  225. check_false(value2.empty(), "type");
  226. check_equal(value1.type(), boost::typeindex::type_id<const char*>(), "type");
  227. check_equal(value2.type(), boost::typeindex::type_id<const char*>(), "type");
  228. check_non_null(any_cast<const char*>(&value1), "any_cast<const char*>");
  229. check_non_null(any_cast<const char*>(&value2), "any_cast<const char*>");
  230. }
  231. const std::string& returning_string1()
  232. {
  233. static const std::string ret("foo");
  234. return ret;
  235. }
  236. std::string returning_string2()
  237. {
  238. static const std::string ret("foo");
  239. return ret;
  240. }
  241. void test_with_func()
  242. {
  243. std::string s;
  244. s = any_cast<std::string>(returning_string1());
  245. s = any_cast<const std::string&>(returning_string1());
  246. s = any_cast<std::string>(returning_string2());
  247. s = any_cast<const std::string&>(returning_string2());
  248. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  249. #if !defined(__INTEL_COMPILER) && !defined(__ICL) && (!defined(_MSC_VER) || _MSC_VER != 1600)
  250. // Intel compiler thinks that it must choose the `any_cast(const any&)` function
  251. // instead of the `any_cast(const any&&)`.
  252. // Bug was not reported because of missing premier support account + annoying
  253. // registrations requirements.
  254. // MSVC-10 had a bug:
  255. //
  256. // any.hpp(291) : error C2440: 'return' : cannot convert.
  257. // Conversion loses qualifiers
  258. // any_test.cpp(304) : see reference to function template instantiation
  259. //
  260. // This issue was fixed in MSVC-11.
  261. s = any_cast<std::string&&>(returning_string1());
  262. #endif
  263. s = any_cast<std::string&&>(returning_string2());
  264. #endif
  265. }
  266. void test_clear()
  267. {
  268. std::string text = "test message";
  269. any value = text;
  270. check_false(value.empty(), "empty");
  271. value.clear();
  272. check_true(value.empty(), "non-empty after clear");
  273. value.clear();
  274. check_true(value.empty(), "non-empty after second clear");
  275. value = text;
  276. check_false(value.empty(), "empty");
  277. value.clear();
  278. check_true(value.empty(), "non-empty after clear");
  279. }
  280. // Following tests cover the case from #9462
  281. // https://svn.boost.org/trac/boost/ticket/9462
  282. boost::any makeVec()
  283. {
  284. return std::vector<int>(100 /*size*/, 7 /*value*/);
  285. }
  286. void test_vectors()
  287. {
  288. const std::vector<int>& vec = boost::any_cast<std::vector<int> >(makeVec());
  289. check_equal(vec.size(), 100u, "size of vector extracted from boost::any");
  290. check_equal(vec.back(), 7, "back value of vector extracted from boost::any");
  291. check_equal(vec.front(), 7, "front value of vector extracted from boost::any");
  292. std::vector<int> vec1 = boost::any_cast<std::vector<int> >(makeVec());
  293. check_equal(vec1.size(), 100u, "size of second vector extracted from boost::any");
  294. check_equal(vec1.back(), 7, "back value of second vector extracted from boost::any");
  295. check_equal(vec1.front(), 7, "front value of second vector extracted from boost::any");
  296. }
  297. template<typename T>
  298. class class_with_address_op {
  299. public:
  300. class_with_address_op(const T* p)
  301. : ptr(p)
  302. {}
  303. const T** operator &() {
  304. return &ptr;
  305. }
  306. const T* get() const {
  307. return ptr;
  308. }
  309. private:
  310. const T* ptr;
  311. };
  312. void test_addressof()
  313. {
  314. int val = 10;
  315. const int* ptr = &val;
  316. class_with_address_op<int> obj(ptr);
  317. boost::any test_val(obj);
  318. class_with_address_op<int> returned_obj = boost::any_cast<class_with_address_op<int> >(test_val);
  319. check_equal(&val, returned_obj.get(), "any_cast incorrectly works with type that has operator&(): addresses differ");
  320. check_true(!!boost::any_cast<class_with_address_op<int> >(&test_val), "any_cast incorrectly works with type that has operator&()");
  321. 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&()");
  322. }
  323. }
  324. // Copyright Kevlin Henney, 2000, 2001. All rights reserved.
  325. // Copyright Antony Polukhin, 2013-2019.
  326. //
  327. // Distributed under the Boost Software License, Version 1.0. (See
  328. // accompanying file LICENSE_1_0.txt or copy at
  329. // http://www.boost.org/LICENSE_1_0.txt)
  330. //