old_virtual.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // Copyright (C) 2008-2018 Lorenzo Caminiti
  2. // Distributed under the Boost Software License, Version 1.0 (see accompanying
  3. // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
  4. // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
  5. // Test old inits/ftors and of mixed types up inheritance tree.
  6. #include "../detail/oteststream.hpp"
  7. #include <boost/contract/public_function.hpp>
  8. #include <boost/contract/base_types.hpp>
  9. #include <boost/contract/assert.hpp>
  10. #include <boost/contract/old.hpp>
  11. #include <boost/contract/check.hpp>
  12. #include <boost/contract/override.hpp>
  13. #include <boost/lexical_cast.hpp>
  14. #include <boost/detail/lightweight_test.hpp>
  15. #include <sstream>
  16. #include <string>
  17. boost::contract::test::detail::oteststream out;
  18. struct num {
  19. static num make(int i) { // Test no ctor (not even explicit) but for copy.
  20. num n;
  21. n.value(i);
  22. return n;
  23. }
  24. num(num const& other) : value_(other.value_) {}
  25. void value(int i) { value_ = boost::lexical_cast<std::string>(i); }
  26. int value() const { return boost::lexical_cast<int>(value_); }
  27. num operator+(int left) {
  28. num n;
  29. n.value(value() + left);
  30. return n;
  31. }
  32. private:
  33. num() {} // Test no visible default ctor (only copy ctor).
  34. num& operator=(num const&); // Test no copy operator (only copy ctor).
  35. std::string value_; // Test this size-of != from other old type `int` below.
  36. };
  37. struct c {
  38. virtual void f(int& i, num& n, boost::contract::virtual_* v = 0) {
  39. boost::contract::old_ptr<int> old_a = BOOST_CONTRACT_OLDOF(v, i + 1);
  40. boost::contract::old_ptr<num> old_b = BOOST_CONTRACT_OLDOF(v, n + 2);
  41. boost::contract::old_ptr<int> old_x;
  42. boost::contract::old_ptr<num> old_y;
  43. boost::contract::check c = boost::contract::public_function(v, this)
  44. .old([&] {
  45. out << "c::f::old" << std::endl;
  46. old_x = BOOST_CONTRACT_OLDOF(v, i + 3);
  47. old_y = BOOST_CONTRACT_OLDOF(v, n + 4);
  48. })
  49. .postcondition([&] {
  50. out << "c::f::post" << std::endl;
  51. BOOST_CONTRACT_ASSERT(*old_a == n.value() + 1);
  52. BOOST_CONTRACT_ASSERT(old_b->value() == i + 2);
  53. BOOST_CONTRACT_ASSERT(*old_x == n.value() + 3);
  54. BOOST_CONTRACT_ASSERT(old_y->value() == i + 4);
  55. })
  56. ;
  57. out << "c::f::body" << std::endl;
  58. int tmp = i;
  59. i = n.value();
  60. n.value(tmp);
  61. }
  62. };
  63. struct b
  64. #define BASES public c
  65. : BASES
  66. {
  67. typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
  68. #undef BASES
  69. virtual void f(int& i, num& n, boost::contract::virtual_* v = 0)
  70. /* override */ {
  71. boost::contract::old_ptr<int> old_a = BOOST_CONTRACT_OLDOF(v, i + 1);
  72. boost::contract::old_ptr<num> old_b = BOOST_CONTRACT_OLDOF(v, n + 2);
  73. boost::contract::old_ptr<int> old_x;
  74. boost::contract::old_ptr<num> old_y;
  75. boost::contract::check c = boost::contract::public_function<
  76. override_f>(v, &c::f, this, i, n)
  77. .old([&] {
  78. out << "b::f::old" << std::endl;
  79. old_x = BOOST_CONTRACT_OLDOF(v, i + 3);
  80. old_y = BOOST_CONTRACT_OLDOF(v, n + 4);
  81. })
  82. .postcondition([&] {
  83. out << "b::f::post" << std::endl;
  84. BOOST_CONTRACT_ASSERT(*old_a == n.value() + 1);
  85. BOOST_CONTRACT_ASSERT(old_b->value() == i + 2);
  86. BOOST_CONTRACT_ASSERT(*old_x == n.value() + 3);
  87. BOOST_CONTRACT_ASSERT(old_y->value() == i + 4);
  88. })
  89. ;
  90. out << "b::f::body" << std::endl;
  91. int tmp = i;
  92. i = n.value();
  93. n.value(tmp);
  94. }
  95. BOOST_CONTRACT_OVERRIDE(f)
  96. };
  97. struct a
  98. #define BASES public b
  99. : BASES
  100. {
  101. typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
  102. #undef BASES
  103. virtual void f(int& i, num& n, boost::contract::virtual_* v = 0)
  104. /* override */ {
  105. boost::contract::old_ptr<int> old_a = BOOST_CONTRACT_OLDOF(v, i + 1);
  106. boost::contract::old_ptr<num> old_b = BOOST_CONTRACT_OLDOF(v, n + 2);
  107. boost::contract::old_ptr<int> old_x;
  108. boost::contract::old_ptr<num> old_y;
  109. boost::contract::check c = boost::contract::public_function<
  110. override_f>(v, &c::f, this, i, n)
  111. .old([&] {
  112. out << "a::f::old" << std::endl;
  113. old_x = BOOST_CONTRACT_OLDOF(v, i + 3);
  114. old_y = BOOST_CONTRACT_OLDOF(v, n + 4);
  115. })
  116. .postcondition([&] {
  117. out << "a::f::post" << std::endl;
  118. BOOST_CONTRACT_ASSERT(*old_a == n.value() + 1);
  119. BOOST_CONTRACT_ASSERT(old_b->value() == i + 2);
  120. BOOST_CONTRACT_ASSERT(*old_x == n.value() + 3);
  121. BOOST_CONTRACT_ASSERT(old_y->value() == i + 4);
  122. })
  123. ;
  124. out << "a::f::body" << std::endl;
  125. int tmp = i;
  126. i = n.value();
  127. n.value(tmp);
  128. }
  129. BOOST_CONTRACT_OVERRIDE(f)
  130. };
  131. int main() {
  132. std::ostringstream ok;
  133. int i = 0;
  134. num n = num::make(0);
  135. i = 123;
  136. n.value(-123);
  137. a aa; // Test virtual call with 2 bases.
  138. out.str("");
  139. aa.f(i, n);
  140. ok.str(""); ok
  141. #ifndef BOOST_CONTRACT_NO_OLDS
  142. << "c::f::old" << std::endl
  143. << "b::f::old" << std::endl
  144. << "a::f::old" << std::endl
  145. #endif
  146. << "a::f::body" << std::endl
  147. #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
  148. << "c::f::old" << std::endl
  149. << "c::f::post" << std::endl
  150. << "b::f::old" << std::endl
  151. << "b::f::post" << std::endl
  152. // No old call here because not a base object.
  153. << "a::f::post" << std::endl
  154. #endif
  155. ;
  156. BOOST_TEST(out.eq(ok.str()));
  157. i = 456;
  158. n.value(-456);
  159. b bb; // Test virtual call with 1 base.
  160. out.str("");
  161. bb.f(i, n);
  162. ok.str(""); ok
  163. #ifndef BOOST_CONTRACT_NO_OLDS
  164. << "c::f::old" << std::endl
  165. << "b::f::old" << std::endl
  166. #endif
  167. << "b::f::body" << std::endl
  168. #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
  169. << "c::f::old" << std::endl
  170. << "c::f::post" << std::endl
  171. // No old call here because not a base object.
  172. << "b::f::post" << std::endl
  173. #endif
  174. ;
  175. BOOST_TEST(out.eq(ok.str()));
  176. i = 789;
  177. n.value(-789);
  178. c cc; // Test virtual call with no bases.
  179. out.str("");
  180. cc.f(i, n);
  181. ok.str(""); ok
  182. #ifndef BOOST_CONTRACT_NO_OLDS
  183. << "c::f::old" << std::endl
  184. #endif
  185. << "c::f::body" << std::endl
  186. #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
  187. // No old call here because not a base object.
  188. << "c::f::post" << std::endl
  189. #endif
  190. ;
  191. BOOST_TEST(out.eq(ok.str()));
  192. return boost::report_errors();
  193. }