Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

3813 Zeilen
106KB

  1. /*
  2. * Trompeloeil C++ mocking framework
  3. *
  4. * Copyright Björn Fahller 2014-2017
  5. *
  6. * Use, modification and distribution is subject to the
  7. * Boost Software License, Version 1.0. (See accompanying
  8. * file LICENSE_1_0.txt or copy at
  9. * http://www.boost.org/LICENSE_1_0.txt)
  10. *
  11. * Project home: https://github.com/rollbear/trompeloeil
  12. */
  13. #ifndef TROMPELOEIL_HPP_
  14. #define TROMPELOEIL_HPP_
  15. // trompe l'oeil noun (Concise Encyclopedia)
  16. // Style of representation in which a painted object is intended
  17. // to deceive the viewer into believing it is the object itself...
  18. // project home: https://github.com/rollbear/trompeloeil
  19. // Deficiencies and missing features
  20. // * Mocking function templates is not supported
  21. // * If a macro kills a kitten, this threatens extinction of all felines!
  22. #if defined(_MSC_VER)
  23. # define TROMPELOEIL_NORETURN
  24. # if (!defined(__cplusplus) || _MSC_VER < 1900)
  25. # error requires C++ in Visual Studio 2015 RC or later
  26. # endif
  27. #else
  28. # define TROMPELOEIL_NORETURN [[noreturn]]
  29. # if (!defined(__cplusplus) || __cplusplus <= 201103)
  30. # error requires C++14 or higher
  31. # endif
  32. #endif
  33. #include <tuple>
  34. #include <iomanip>
  35. #include <sstream>
  36. #include <exception>
  37. #include <functional>
  38. #include <memory>
  39. #include <cstring>
  40. #include <regex>
  41. #include <mutex>
  42. #include <atomic>
  43. #include <type_traits>
  44. #ifdef TROMPELOEIL_SANITY_CHECKS
  45. #include <cassert>
  46. #define TROMPELOEIL_ASSERT(x) assert(x)
  47. #else
  48. #define TROMPELOEIL_ASSERT(x) do {} while (false)
  49. #endif
  50. #define TROMPELOEIL_IDENTITY(...) __VA_ARGS__ // work around stupid MS VS2015 RC bug
  51. #define TROMPELOEIL_ARG16(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15, ...) _15
  52. #define TROMPELOEIL_COUNT(...) \
  53. TROMPELOEIL_IDENTITY(TROMPELOEIL_ARG16(__VA_ARGS__, \
  54. 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0))
  55. #define TROMPELOEIL_CONCAT_(x, y) x ## y
  56. #define TROMPELOEIL_CONCAT(x, y) TROMPELOEIL_CONCAT_(x, y)
  57. #define TROMPELOEIL_INIT_WITH_STR15(base, x, ...) \
  58. base{#x, x}, TROMPELOEIL_INIT_WITH_STR14(base, __VA_ARGS__)
  59. #define TROMPELOEIL_INIT_WITH_STR14(base, x, ...) \
  60. base{#x, x}, TROMPELOEIL_INIT_WITH_STR13(base, __VA_ARGS__)
  61. #define TROMPELOEIL_INIT_WITH_STR13(base, x, ...) \
  62. base{#x, x}, TROMPELOEIL_INIT_WITH_STR12(base, __VA_ARGS__)
  63. #define TROMPELOEIL_INIT_WITH_STR12(base, x, ...) \
  64. base{#x, x}, TROMPELOEIL_INIT_WITH_STR11(base, __VA_ARGS__)
  65. #define TROMPELOEIL_INIT_WITH_STR11(base, x, ...) \
  66. base{#x, x}, TROMPELOEIL_INIT_WITH_STR10(base, __VA_ARGS__)
  67. #define TROMPELOEIL_INIT_WITH_STR10(base, x, ...) \
  68. base{#x, x}, TROMPELOEIL_INIT_WITH_STR9(base, __VA_ARGS__)
  69. #define TROMPELOEIL_INIT_WITH_STR9(base, x, ...) \
  70. base{#x, x}, TROMPELOEIL_INIT_WITH_STR8(base, __VA_ARGS__)
  71. #define TROMPELOEIL_INIT_WITH_STR8(base, x, ...) \
  72. base{#x, x}, TROMPELOEIL_INIT_WITH_STR7(base, __VA_ARGS__)
  73. #define TROMPELOEIL_INIT_WITH_STR7(base, x, ...) \
  74. base{#x, x}, TROMPELOEIL_INIT_WITH_STR6(base, __VA_ARGS__)
  75. #define TROMPELOEIL_INIT_WITH_STR6(base, x, ...) \
  76. base{#x, x}, TROMPELOEIL_INIT_WITH_STR5(base, __VA_ARGS__)
  77. #define TROMPELOEIL_INIT_WITH_STR5(base, x, ...) \
  78. base{#x, x}, TROMPELOEIL_INIT_WITH_STR4(base, __VA_ARGS__)
  79. #define TROMPELOEIL_INIT_WITH_STR4(base, x, ...) \
  80. base{#x, x}, TROMPELOEIL_INIT_WITH_STR3(base, __VA_ARGS__)
  81. #define TROMPELOEIL_INIT_WITH_STR3(base, x, ...) \
  82. base{#x, x}, TROMPELOEIL_INIT_WITH_STR2(base, __VA_ARGS__)
  83. #define TROMPELOEIL_INIT_WITH_STR2(base, x, ...) \
  84. base{#x, x}, TROMPELOEIL_INIT_WITH_STR1(base, __VA_ARGS__)
  85. #define TROMPELOEIL_INIT_WITH_STR1(base, x) \
  86. base{#x, x}
  87. #define TROMPELOEIL_INIT_WITH_STR0(base)
  88. #define TROMPELOEIL_INIT_WITH_STR(base, ...) \
  89. TROMPELOEIL_CONCAT(TROMPELOEIL_INIT_WITH_STR, \
  90. TROMPELOEIL_COUNT(__VA_ARGS__))(base, __VA_ARGS__)
  91. #define TROMPELOEIL_PARAM_LIST15(func_type) \
  92. TROMPELOEIL_PARAM_LIST14(func_type), \
  93. ::trompeloeil::param_list_t<func_type, 14> p15
  94. #define TROMPELOEIL_PARAM_LIST14(func_type) \
  95. TROMPELOEIL_PARAM_LIST13(func_type), \
  96. ::trompeloeil::param_list_t<func_type, 13> p14
  97. #define TROMPELOEIL_PARAM_LIST13(func_type) \
  98. TROMPELOEIL_PARAM_LIST12(func_type), \
  99. ::trompeloeil::param_list_t<func_type, 12> p13
  100. #define TROMPELOEIL_PARAM_LIST12(func_type) \
  101. TROMPELOEIL_PARAM_LIST11(func_type), \
  102. ::trompeloeil::param_list_t<func_type, 11> p12
  103. #define TROMPELOEIL_PARAM_LIST11(func_type) \
  104. TROMPELOEIL_PARAM_LIST10(func_type), \
  105. ::trompeloeil::param_list_t<func_type, 10> p11
  106. #define TROMPELOEIL_PARAM_LIST10(func_type) \
  107. TROMPELOEIL_PARAM_LIST9(func_type), \
  108. ::trompeloeil::param_list_t<func_type, 9> p10
  109. #define TROMPELOEIL_PARAM_LIST9(func_type) \
  110. TROMPELOEIL_PARAM_LIST8(func_type), \
  111. ::trompeloeil::param_list_t<func_type, 8> p9
  112. #define TROMPELOEIL_PARAM_LIST8(func_type) \
  113. TROMPELOEIL_PARAM_LIST7(func_type), \
  114. ::trompeloeil::param_list_t<func_type, 7> p8
  115. #define TROMPELOEIL_PARAM_LIST7(func_type) \
  116. TROMPELOEIL_PARAM_LIST6(func_type), \
  117. ::trompeloeil::param_list_t<func_type, 6> p7
  118. #define TROMPELOEIL_PARAM_LIST6(func_type) \
  119. TROMPELOEIL_PARAM_LIST5(func_type), \
  120. ::trompeloeil::param_list_t<func_type, 5> p6
  121. #define TROMPELOEIL_PARAM_LIST5(func_type) \
  122. TROMPELOEIL_PARAM_LIST4(func_type), \
  123. ::trompeloeil::param_list_t<func_type, 4> p5
  124. #define TROMPELOEIL_PARAM_LIST4(func_type) \
  125. TROMPELOEIL_PARAM_LIST3(func_type), \
  126. ::trompeloeil::param_list_t<func_type, 3> p4
  127. #define TROMPELOEIL_PARAM_LIST3(func_type) \
  128. TROMPELOEIL_PARAM_LIST2(func_type), \
  129. ::trompeloeil::param_list_t<func_type, 2> p3
  130. #define TROMPELOEIL_PARAM_LIST2(func_type) \
  131. TROMPELOEIL_PARAM_LIST1(func_type), \
  132. ::trompeloeil::param_list_t<func_type, 1> p2
  133. #define TROMPELOEIL_PARAM_LIST1(func_type) \
  134. ::trompeloeil::param_list_t<func_type, 0> p1
  135. #define TROMPELOEIL_PARAM_LIST0(func_type)
  136. #define TROMPELOEIL_PARAM_LIST(num, func_type) \
  137. TROMPELOEIL_CONCAT(TROMPELOEIL_PARAM_LIST, num)(func_type)
  138. #define TROMPELOEIL_PARAMS15 TROMPELOEIL_PARAMS14, p15
  139. #define TROMPELOEIL_PARAMS14 TROMPELOEIL_PARAMS13, p14
  140. #define TROMPELOEIL_PARAMS13 TROMPELOEIL_PARAMS12, p13
  141. #define TROMPELOEIL_PARAMS12 TROMPELOEIL_PARAMS11, p12
  142. #define TROMPELOEIL_PARAMS11 TROMPELOEIL_PARAMS10, p11
  143. #define TROMPELOEIL_PARAMS10 TROMPELOEIL_PARAMS9, p10
  144. #define TROMPELOEIL_PARAMS9 TROMPELOEIL_PARAMS8, p9
  145. #define TROMPELOEIL_PARAMS8 TROMPELOEIL_PARAMS7, p8
  146. #define TROMPELOEIL_PARAMS7 TROMPELOEIL_PARAMS6, p7
  147. #define TROMPELOEIL_PARAMS6 TROMPELOEIL_PARAMS5, p6
  148. #define TROMPELOEIL_PARAMS5 TROMPELOEIL_PARAMS4, p5
  149. #define TROMPELOEIL_PARAMS4 TROMPELOEIL_PARAMS3, p4
  150. #define TROMPELOEIL_PARAMS3 TROMPELOEIL_PARAMS2, p3
  151. #define TROMPELOEIL_PARAMS2 TROMPELOEIL_PARAMS1, p2
  152. #define TROMPELOEIL_PARAMS1 , p1
  153. #define TROMPELOEIL_PARAMS0
  154. #define TROMPELOEIL_PARAMS(num) TROMPELOEIL_CONCAT(TROMPELOEIL_PARAMS, num)
  155. namespace trompeloeil
  156. {
  157. class specialized;
  158. namespace {
  159. inline
  160. const std::shared_ptr<std::recursive_mutex>&
  161. get_mutex_obj()
  162. {
  163. static auto obj = std::make_shared<std::recursive_mutex>();
  164. return obj;
  165. }
  166. auto mutex_holder = get_mutex_obj();
  167. }
  168. template <typename T = void>
  169. std::unique_lock<std::recursive_mutex> get_lock()
  170. {
  171. return std::unique_lock<std::recursive_mutex>{ *get_mutex_obj() };
  172. }
  173. template <size_t N, typename T>
  174. using conditional_tuple_element
  175. = std::conditional_t<(N < std::tuple_size<T>::value),
  176. typename std::tuple_element<N, T>::type,
  177. int>;
  178. template <typename T>
  179. struct param_list;
  180. template <typename R, typename ... P>
  181. struct param_list<R(P...)>
  182. {
  183. static size_t constexpr const size = sizeof...(P);
  184. template <size_t N>
  185. using type = conditional_tuple_element<N, std::tuple<P...>>;
  186. };
  187. template <typename Sig, size_t N>
  188. using param_list_t = typename param_list<Sig>::template type<N>;
  189. class expectation_violation : public std::logic_error
  190. {
  191. public:
  192. using std::logic_error::logic_error;
  193. };
  194. struct location
  195. {
  196. location()
  197. noexcept
  198. : file("")
  199. , line(0U)
  200. {}
  201. location(
  202. char const* file_,
  203. unsigned long line_
  204. )
  205. noexcept
  206. : file{file_}
  207. , line{line_}
  208. {}
  209. char const *file;
  210. unsigned long line;
  211. };
  212. inline
  213. std::ostream&
  214. operator<<(
  215. std::ostream& os,
  216. const location& loc)
  217. {
  218. if (loc.line != 0U) os << loc.file << ':' << loc.line;
  219. return os;
  220. }
  221. enum class severity { fatal, nonfatal };
  222. using reporter_func = std::function<void(severity,
  223. char const *file,
  224. unsigned long line,
  225. std::string const &msg)>;
  226. inline
  227. void default_reporter(
  228. severity,
  229. char const *file,
  230. unsigned long line,
  231. std::string const &msg)
  232. {
  233. if (!std::current_exception())
  234. {
  235. std::stringstream os;
  236. os << location{ file, line } << "\n" << msg;
  237. throw expectation_violation(os.str());
  238. }
  239. }
  240. inline
  241. reporter_func&
  242. reporter_obj()
  243. {
  244. static reporter_func obj = default_reporter;
  245. return obj;
  246. }
  247. inline
  248. reporter_func set_reporter(
  249. reporter_func f)
  250. {
  251. return std::exchange(reporter_obj(), std::move(f));
  252. }
  253. class tracer;
  254. inline
  255. tracer*&
  256. tracer_obj()
  257. noexcept
  258. {
  259. static tracer* ptr = nullptr;
  260. return ptr;
  261. }
  262. inline
  263. tracer*
  264. set_tracer(
  265. tracer* obj)
  266. noexcept
  267. {
  268. // std::exchange would be sane here, but it costs compilation time
  269. auto& ptr = tracer_obj();
  270. auto rv = ptr;
  271. ptr = obj;
  272. return rv;
  273. }
  274. class tracer
  275. {
  276. public:
  277. virtual
  278. void
  279. trace(
  280. char const *file,
  281. unsigned long line,
  282. std::string const &call) = 0;
  283. protected:
  284. tracer()
  285. noexcept
  286. : previous{set_tracer(this)} {}
  287. tracer(tracer const&) = delete;
  288. tracer& operator=(tracer const&) = delete;
  289. virtual
  290. ~tracer()
  291. {
  292. set_tracer(previous);
  293. }
  294. private:
  295. tracer* previous = nullptr;
  296. };
  297. class stream_tracer : public tracer
  298. {
  299. public:
  300. stream_tracer(
  301. std::ostream& stream_)
  302. : stream(stream_) {}
  303. void
  304. trace(
  305. char const *file,
  306. unsigned long line,
  307. std::string const &call)
  308. override
  309. {
  310. stream << location{file, line} << '\n' << call << '\n';
  311. }
  312. private:
  313. std::ostream& stream;
  314. };
  315. class trace_agent;
  316. template <typename T>
  317. struct reporter;
  318. template <typename T>
  319. void
  320. send_report(
  321. severity s,
  322. location loc,
  323. std::string const &msg)
  324. {
  325. reporter<T>::send(s, loc.file, loc.line, msg.c_str());
  326. }
  327. template <typename T>
  328. struct reporter
  329. {
  330. static
  331. void
  332. send(
  333. severity s,
  334. char const *file,
  335. unsigned long line,
  336. char const *msg);
  337. };
  338. template <typename T>
  339. void reporter<T>::
  340. send(
  341. severity s,
  342. char const *file,
  343. unsigned long line,
  344. char const *msg)
  345. {
  346. reporter_obj()(s, file, line, msg);
  347. }
  348. template <typename ... T>
  349. inline
  350. constexpr
  351. bool
  352. ignore(
  353. T const& ...)
  354. noexcept
  355. {
  356. return true;
  357. }
  358. struct illegal_argument
  359. {
  360. template <bool b = false>
  361. constexpr
  362. illegal_argument const& operator&() const
  363. {
  364. static_assert(b, "illegal argument");
  365. return *this;
  366. }
  367. template <bool b = false>
  368. constexpr
  369. illegal_argument const& operator*() const
  370. {
  371. static_assert(b, "illegal argument");
  372. return *this;
  373. }
  374. template <typename T, bool b = false>
  375. constexpr
  376. illegal_argument const& operator=(T const&) const
  377. {
  378. static_assert(b, "illegal argument");
  379. return *this;
  380. }
  381. template <typename T, bool b = false>
  382. constexpr
  383. operator T() const
  384. {
  385. static_assert(b, "illegal argument");
  386. return {};
  387. }
  388. };
  389. template <typename ...>
  390. struct void_t_
  391. {
  392. using type = void;
  393. };
  394. template <typename ... T>
  395. using void_t = typename void_t_<T...>::type;
  396. template <template <typename ...> class, typename, typename ...>
  397. struct is_detected_{
  398. using type = std::false_type;
  399. };
  400. template <template <typename ...> class D, typename ... Ts>
  401. struct is_detected_<D, void_t<D<Ts...>>, Ts...>
  402. {
  403. using type = std::true_type;
  404. };
  405. template <template <typename ...> class D, typename ... Ts>
  406. using is_detected = typename is_detected_<D, void, Ts...>::type;
  407. struct matcher { };
  408. template <typename T>
  409. using matcher_access = decltype(static_cast<matcher*>(std::declval<typename std::add_pointer<T>::type>()));
  410. template <typename T>
  411. using is_matcher = typename is_detected<matcher_access, T>::type;
  412. template <typename T>
  413. struct typed_matcher : matcher
  414. {
  415. operator T() const;
  416. };
  417. template <>
  418. struct typed_matcher<std::nullptr_t> : matcher
  419. {
  420. template <typename T, typename = decltype(std::declval<T>() == nullptr)>
  421. operator T&&() const;
  422. template <typename T,
  423. typename = decltype(std::declval<T>() == nullptr),
  424. typename = std::enable_if_t<std::is_copy_constructible<T>::value>>
  425. operator T&()const;
  426. template <typename T, typename C>
  427. operator T C::*() const;
  428. };
  429. template <typename Pred, typename ... T>
  430. class duck_typed_matcher : public matcher
  431. {
  432. public:
  433. template <typename V,
  434. typename = decltype(std::declval<Pred>()(std::declval<V&&>(), std::declval<T>()...))>
  435. operator V&&() const;
  436. template <typename V,
  437. typename = decltype(std::declval<Pred>()(std::declval<V&>(), std::declval<T>()...))>
  438. operator V&() const;
  439. };
  440. template <typename T>
  441. using ostream_insertion = decltype(std::declval<std::ostream&>() << std::declval<T>());
  442. template <typename T>
  443. using is_output_streamable = std::integral_constant<bool, is_detected<ostream_insertion, T>::value && !std::is_array<T>::value>;
  444. struct stream_sentry
  445. {
  446. stream_sentry(
  447. std::ostream& os_)
  448. : os(os_)
  449. , width(os.width(0))
  450. , flags(os.flags(std::ios_base::dec | std::ios_base::left))
  451. , fill(os.fill(' '))
  452. { }
  453. ~stream_sentry()
  454. {
  455. os.flags(flags);
  456. os.fill(fill);
  457. os.width(width);
  458. }
  459. private:
  460. std::ostream& os;
  461. std::streamsize width;
  462. std::ios_base::fmtflags flags;
  463. char fill;
  464. };
  465. template <typename T, typename U>
  466. using equality_comparison = decltype(std::declval<T>() == std::declval<U>());
  467. template <typename T, typename U>
  468. using is_equal_comparable = is_detected<equality_comparison, T, U>;
  469. template <typename T>
  470. using is_null_comparable = is_equal_comparable<T, std::nullptr_t>;
  471. template <typename T>
  472. inline
  473. constexpr
  474. bool
  475. is_null(
  476. T const &t,
  477. std::true_type)
  478. noexcept(noexcept(std::declval<const T&>() == nullptr))
  479. {
  480. return t == nullptr;
  481. }
  482. template <typename T>
  483. inline
  484. constexpr
  485. bool
  486. is_null(
  487. T const &,
  488. std::false_type)
  489. noexcept
  490. {
  491. return false;
  492. }
  493. template <typename T>
  494. inline
  495. constexpr
  496. bool
  497. is_null(
  498. T const &t)
  499. {
  500. // g++-4.9 uses C++11 rules for constexpr function, so can't
  501. // break this up into smaller bits
  502. using tag = std::integral_constant<bool, is_null_comparable<T>::value
  503. && !is_matcher<T>::value
  504. && !std::is_array<T>::value>;
  505. return ::trompeloeil::is_null(t, tag{});
  506. }
  507. template <typename T>
  508. void
  509. print(
  510. std::ostream& os,
  511. T const &t);
  512. template <typename T>
  513. using iterable = decltype(std::begin(std::declval<T&>()) == std::end(std::declval<T&>()));
  514. template <typename T>
  515. using is_collection = is_detected<iterable, T>;
  516. template <typename T,
  517. bool = is_output_streamable<T>::value,
  518. bool = is_collection<std::remove_reference_t<T>>::value>
  519. struct streamer
  520. {
  521. static
  522. void
  523. print(
  524. std::ostream& os,
  525. T const &t)
  526. {
  527. stream_sentry s(os);
  528. os << t;
  529. }
  530. };
  531. template <typename ... T>
  532. struct streamer<std::tuple<T...>, false, false>
  533. {
  534. static
  535. void
  536. print(
  537. std::ostream& os,
  538. std::tuple<T...> const& t)
  539. {
  540. print_tuple(os, t, std::index_sequence_for<T...>{});
  541. }
  542. template <size_t ... I>
  543. static
  544. void
  545. print_tuple(
  546. std::ostream& os,
  547. std::tuple<T...> const& t,
  548. std::index_sequence<I...>)
  549. {
  550. os << "{ ";
  551. const char* sep = "";
  552. std::initializer_list<const char*> v{((os << sep),
  553. ::trompeloeil::print(os, std::get<I>(t)),
  554. (sep = ", "))...};
  555. ignore(v);
  556. os << " }";
  557. }
  558. };
  559. template <typename T, typename U>
  560. struct streamer<std::pair<T, U>, false, false>
  561. {
  562. static
  563. void
  564. print(
  565. std::ostream& os,
  566. std::pair<T, U> const& t)
  567. {
  568. os << "{ ";
  569. ::trompeloeil::print(os, t.first);
  570. os << ", ";
  571. ::trompeloeil::print(os, t.second);
  572. os << " }";
  573. }
  574. };
  575. template <typename T>
  576. struct streamer<T, false, true>
  577. {
  578. static
  579. void
  580. print(
  581. std::ostream& os,
  582. T const& t)
  583. {
  584. os << "{ ";
  585. const char* sep = "";
  586. for (auto& elem : t)
  587. {
  588. os << sep;
  589. ::trompeloeil::print(os, elem);
  590. sep = ", ";
  591. }
  592. os << " }";
  593. }
  594. };
  595. template <typename T>
  596. struct streamer<T, false, false>
  597. {
  598. static
  599. void
  600. print(
  601. std::ostream& os,
  602. T const &t)
  603. {
  604. stream_sentry s(os);
  605. static const char *linebreak = "\n";
  606. os << sizeof(T) << "-byte object={";
  607. os << (linebreak + (sizeof(T) <= 8)); // stupid construction silences VS2015 warining
  608. os << std::setfill('0') << std::hex;
  609. auto p = reinterpret_cast<uint8_t const*>(&t);
  610. for (size_t i = 0; i < sizeof(T); ++i)
  611. {
  612. os << " 0x" << std::setw(2) << unsigned(p[i]);
  613. if ((i & 0xf) == 0xf) os << '\n';
  614. }
  615. os << " }";
  616. }
  617. };
  618. template <typename T>
  619. void
  620. print(
  621. std::ostream& os,
  622. T const &t)
  623. {
  624. if (is_null(t))
  625. {
  626. os << "nullptr";
  627. }
  628. else
  629. {
  630. streamer<T>::print(os, t);
  631. }
  632. }
  633. inline
  634. constexpr
  635. auto
  636. param_compare_operator(
  637. ...)
  638. {
  639. return " == ";
  640. }
  641. inline
  642. constexpr
  643. auto
  644. param_compare_operator(
  645. matcher const*)
  646. {
  647. return "";
  648. }
  649. template <typename T>
  650. void
  651. print_expectation(
  652. std::ostream& os,
  653. T const& t)
  654. {
  655. os << param_compare_operator(&t);
  656. print(os, t);
  657. os << '\n';
  658. }
  659. template <typename T>
  660. class list_elem
  661. {
  662. public:
  663. list_elem(
  664. const list_elem&)
  665. = delete;
  666. list_elem(
  667. list_elem &&r)
  668. noexcept
  669. {
  670. *this = std::move(r);
  671. }
  672. list_elem&
  673. operator=(
  674. list_elem &&r)
  675. noexcept
  676. {
  677. if (this != &r)
  678. {
  679. next = r.next;
  680. prev = &r;
  681. r.invariant_check();
  682. next->prev = this;
  683. r.next = this;
  684. TROMPELOEIL_ASSERT(next->prev == this);
  685. TROMPELOEIL_ASSERT(prev->next == this);
  686. r.unlink();
  687. TROMPELOEIL_ASSERT(!r.is_linked());
  688. invariant_check();
  689. }
  690. return *this;
  691. }
  692. list_elem&
  693. operator=(
  694. const list_elem&)
  695. = delete;
  696. virtual
  697. ~list_elem()
  698. {
  699. unlink();
  700. }
  701. void
  702. unlink()
  703. noexcept
  704. {
  705. invariant_check();
  706. auto n = next;
  707. auto p = prev;
  708. n->prev = p;
  709. p->next = n;
  710. next = this;
  711. prev = this;
  712. invariant_check();
  713. }
  714. void
  715. invariant_check()
  716. const
  717. noexcept
  718. {
  719. #ifdef TROMPELOEIL_SANITY_CHECKS
  720. TROMPELOEIL_ASSERT(next->prev == this);
  721. TROMPELOEIL_ASSERT(prev->next == this);
  722. TROMPELOEIL_ASSERT((next == this) == (prev == this));
  723. TROMPELOEIL_ASSERT((prev->next == next) == (next == this));
  724. TROMPELOEIL_ASSERT((next->prev == prev) == (prev == this));
  725. auto pp = prev;
  726. auto nn = next;
  727. do {
  728. TROMPELOEIL_ASSERT((nn == this) == (pp == this));
  729. TROMPELOEIL_ASSERT(nn->next->prev == nn);
  730. TROMPELOEIL_ASSERT(nn->prev->next == nn);
  731. TROMPELOEIL_ASSERT(pp->next->prev == pp);
  732. TROMPELOEIL_ASSERT(pp->prev->next == pp);
  733. TROMPELOEIL_ASSERT((nn->next == nn) == (nn == this));
  734. TROMPELOEIL_ASSERT((pp->prev == pp) == (pp == this));
  735. nn = nn->next;
  736. pp = pp->prev;
  737. } while (nn != this);
  738. #endif
  739. }
  740. bool
  741. is_linked()
  742. const
  743. noexcept
  744. {
  745. invariant_check();
  746. return next != this;
  747. }
  748. protected:
  749. list_elem() noexcept = default;
  750. public:
  751. list_elem* next = this;
  752. list_elem* prev = this;
  753. };
  754. class ignore_disposer
  755. {
  756. protected:
  757. template <typename T>
  758. TROMPELOEIL_NORETURN
  759. void
  760. dispose(
  761. T*)
  762. const
  763. noexcept
  764. {
  765. std::abort(); // must never be called
  766. }
  767. };
  768. class delete_disposer
  769. {
  770. protected:
  771. template <typename T>
  772. void
  773. dispose(
  774. T* t)
  775. const
  776. {
  777. delete t;
  778. }
  779. };
  780. template <typename T, typename Disposer = ignore_disposer>
  781. class list : private list_elem<T>, private Disposer
  782. {
  783. public:
  784. list() noexcept;
  785. list(list&&) noexcept;
  786. list(const list&) = delete;
  787. list& operator=(list&&) noexcept;
  788. list& operator=(const list&) = delete;
  789. ~list();
  790. class iterator;
  791. iterator begin() const noexcept;
  792. iterator end() const noexcept;
  793. iterator push_front(T* t) noexcept;
  794. iterator push_back(T* t) noexcept;
  795. bool empty() const noexcept { return begin() == end(); }
  796. private:
  797. using list_elem<T>::invariant_check;
  798. using list_elem<T>::next;
  799. using list_elem<T>::prev;
  800. };
  801. template <typename T, typename Disposer>
  802. class list<T, Disposer>::iterator
  803. : public std::iterator<std::bidirectional_iterator_tag, T>
  804. {
  805. friend class list<T, Disposer>;
  806. public:
  807. iterator()
  808. noexcept
  809. : p{nullptr}
  810. {}
  811. friend
  812. bool
  813. operator==(
  814. iterator const &lh,
  815. iterator const &rh)
  816. noexcept
  817. {
  818. return lh.p == rh.p;
  819. }
  820. friend
  821. bool
  822. operator!=(
  823. iterator const &lh,
  824. iterator const &rh)
  825. noexcept
  826. {
  827. return !(lh == rh);
  828. }
  829. iterator&
  830. operator++()
  831. noexcept
  832. {
  833. p = p->next;
  834. return *this;
  835. }
  836. iterator
  837. operator++(int)
  838. noexcept
  839. {
  840. auto rv = *this;
  841. operator++();
  842. return rv;
  843. }
  844. T&
  845. operator*()
  846. noexcept
  847. {
  848. return static_cast<T&>(*p);
  849. }
  850. T*
  851. operator->()
  852. noexcept
  853. {
  854. return static_cast<T*>(p);
  855. }
  856. private:
  857. iterator(
  858. list_elem<T> const *t)
  859. noexcept
  860. : p{const_cast<list_elem<T>*>(t)}
  861. {}
  862. list_elem<T>* p;
  863. };
  864. template <typename T, typename Disposer>
  865. list<T, Disposer>::list() noexcept = default;
  866. template <typename T, typename Disposer>
  867. list<T, Disposer>::list(list&&) noexcept = default;
  868. template <typename T, typename Disposer>
  869. list<T, Disposer>& list<T, Disposer>::operator=(list&&) noexcept = default;
  870. template <typename T, typename Disposer>
  871. list<T, Disposer>::~list()
  872. {
  873. auto i = this->begin();
  874. while (i != this->end())
  875. {
  876. auto p = i++;
  877. Disposer::dispose(&*p);
  878. }
  879. }
  880. template <typename T, typename Disposer>
  881. auto
  882. list<T, Disposer>::begin()
  883. const
  884. noexcept
  885. -> iterator
  886. {
  887. return {next};
  888. }
  889. template <typename T, typename Disposer>
  890. auto
  891. list<T, Disposer>::end()
  892. const
  893. noexcept
  894. -> iterator
  895. {
  896. return {this};
  897. }
  898. template <typename T, typename Disposer>
  899. auto
  900. list<T, Disposer>::push_front(
  901. T* t)
  902. noexcept
  903. -> iterator
  904. {
  905. invariant_check();
  906. t->next = next;
  907. t->prev = this;
  908. next->prev = t;
  909. next = t;
  910. invariant_check();
  911. return {t};
  912. }
  913. template <typename T, typename Disposer>
  914. auto
  915. list<T, Disposer>::push_back(
  916. T* t)
  917. noexcept
  918. -> iterator
  919. {
  920. invariant_check();
  921. t->prev = prev;
  922. t->next = this;
  923. prev->next = t;
  924. prev = t;
  925. invariant_check();
  926. return {t};
  927. }
  928. class sequence_matcher;
  929. class sequence_type
  930. {
  931. public:
  932. sequence_type() noexcept = default;
  933. sequence_type(sequence_type&&) noexcept = delete;
  934. sequence_type(const sequence_type&) = delete;
  935. sequence_type& operator=(sequence_type&&) noexcept = delete;
  936. sequence_type& operator=(const sequence_type&) = delete;
  937. ~sequence_type();
  938. bool
  939. is_completed()
  940. const
  941. noexcept;
  942. bool
  943. is_first(
  944. sequence_matcher const *m)
  945. const
  946. noexcept;
  947. void
  948. add_last(
  949. sequence_matcher *m)
  950. noexcept;
  951. void
  952. validate_match(
  953. severity s,
  954. sequence_matcher const *matcher,
  955. char const *seq_name,
  956. char const *match_name,
  957. location loc)
  958. const;
  959. private:
  960. list<sequence_matcher> matchers;
  961. };
  962. class sequence
  963. {
  964. public:
  965. sequence() : obj(new sequence_type) {}
  966. sequence_type& operator*() { return *obj; }
  967. bool is_completed() const { return obj->is_completed(); }
  968. private:
  969. std::unique_ptr<sequence_type> obj;
  970. };
  971. class sequence_matcher : public list_elem<sequence_matcher>
  972. {
  973. public:
  974. using init_type = std::pair<char const*, sequence&>;
  975. sequence_matcher(
  976. char const *exp,
  977. location loc,
  978. init_type i)
  979. noexcept
  980. : seq_name(i.first)
  981. , exp_name(exp)
  982. , exp_loc(loc)
  983. , seq(*i.second)
  984. {
  985. seq.add_last(this);
  986. }
  987. void
  988. validate_match(
  989. severity s,
  990. char const *match_name,
  991. location loc)
  992. const
  993. {
  994. seq.validate_match(s, this, seq_name, match_name, loc);
  995. }
  996. bool
  997. is_first()
  998. const
  999. noexcept
  1000. {
  1001. return seq.is_first(this);
  1002. }
  1003. void
  1004. retire()
  1005. noexcept
  1006. {
  1007. this->unlink();
  1008. }
  1009. void
  1010. print_expectation(std::ostream& os)
  1011. const
  1012. {
  1013. os << exp_name << " at " << exp_loc;
  1014. }
  1015. char const*
  1016. sequence_name()
  1017. noexcept
  1018. {
  1019. return seq_name;
  1020. }
  1021. private:
  1022. char const *seq_name;
  1023. char const *exp_name;
  1024. location exp_loc;
  1025. sequence_type& seq;
  1026. };
  1027. inline
  1028. bool
  1029. sequence_type::is_completed()
  1030. const
  1031. noexcept
  1032. {
  1033. return matchers.empty();
  1034. }
  1035. inline
  1036. bool
  1037. sequence_type::is_first(
  1038. sequence_matcher const *m)
  1039. const
  1040. noexcept
  1041. {
  1042. return !matchers.empty() && &*matchers.begin() == m;
  1043. }
  1044. inline
  1045. void
  1046. sequence_type::validate_match(
  1047. severity s,
  1048. sequence_matcher const *matcher,
  1049. char const* seq_name,
  1050. char const* match_name,
  1051. location loc)
  1052. const
  1053. {
  1054. if (is_first(matcher)) return;
  1055. for (auto& m : matchers)
  1056. {
  1057. std::ostringstream os;
  1058. os << "Sequence mismatch for sequence \"" << seq_name
  1059. << "\" with matching call of " << match_name
  1060. << " at " << loc
  1061. << ". Sequence \"" << seq_name << "\" has ";
  1062. m.print_expectation(os);
  1063. os << " first in line\n";
  1064. send_report<specialized>(s, loc, os.str());
  1065. }
  1066. }
  1067. inline
  1068. sequence_type::~sequence_type()
  1069. {
  1070. bool touched = false;
  1071. std::ostringstream os;
  1072. while (!matchers.empty())
  1073. {
  1074. auto m = matchers.begin();
  1075. if (!touched)
  1076. {
  1077. os << "Sequence expectations not met at destruction of sequence object \""
  1078. << m->sequence_name() << "\":";
  1079. touched = true;
  1080. }
  1081. os << "\n missing ";
  1082. m->print_expectation(os);
  1083. m->unlink();
  1084. }
  1085. if (touched)
  1086. {
  1087. os << "\n";
  1088. send_report<specialized>(severity::nonfatal, location{}, os.str());
  1089. }
  1090. }
  1091. inline
  1092. void
  1093. sequence_type::add_last(
  1094. sequence_matcher *m)
  1095. noexcept
  1096. {
  1097. matchers.push_back(m);
  1098. }
  1099. struct wildcard : public matcher
  1100. {
  1101. // This abomination of constructor seems necessary for g++ 4.9 and 5.1
  1102. template <typename ... T>
  1103. constexpr
  1104. wildcard(
  1105. T&& ...)
  1106. noexcept
  1107. {}
  1108. template<typename T,
  1109. typename = std::enable_if_t<!std::is_lvalue_reference<T>::value>>
  1110. operator T&&()
  1111. const;
  1112. template<typename T,
  1113. typename = std::enable_if_t<std::is_copy_constructible<T>::value
  1114. || !std::is_move_constructible<T>::value>>
  1115. operator T&()
  1116. const;
  1117. template <typename T>
  1118. constexpr
  1119. bool
  1120. matches(
  1121. T const&)
  1122. const
  1123. noexcept
  1124. {
  1125. return true;
  1126. }
  1127. friend
  1128. std::ostream&
  1129. operator<<(
  1130. std::ostream& os,
  1131. wildcard const&)
  1132. noexcept
  1133. {
  1134. return os << " matching _";
  1135. }
  1136. };
  1137. static constexpr wildcard const _{};
  1138. template <typename T>
  1139. void can_match_parameter(T&);
  1140. template <typename T>
  1141. void can_match_parameter(T&&);
  1142. template <typename M>
  1143. class ptr_deref : public matcher
  1144. {
  1145. public:
  1146. template <typename U,
  1147. typename = decltype(can_match_parameter<std::remove_reference_t<decltype(*std::declval<U>())>>(std::declval<M>()))>
  1148. operator U() const;
  1149. template <typename U>
  1150. explicit
  1151. ptr_deref(
  1152. U&& m_)
  1153. : m( std::forward<U>(m_) )
  1154. {}
  1155. template <typename U>
  1156. bool
  1157. matches(
  1158. const U& u)
  1159. const
  1160. noexcept(noexcept(std::declval<M>().matches(*u)))
  1161. {
  1162. return (u != nullptr) && m.matches(*u);
  1163. }
  1164. friend
  1165. std::ostream&
  1166. operator<<(
  1167. std::ostream& os,
  1168. ptr_deref<M> const& p)
  1169. {
  1170. return os << p.m;
  1171. }
  1172. private:
  1173. M m;
  1174. };
  1175. template <typename M>
  1176. class neg_matcher : public matcher
  1177. {
  1178. public:
  1179. template <typename U,
  1180. typename = decltype(can_match_parameter<std::remove_reference_t<decltype(std::declval<U>())>>(std::declval<M>()))>
  1181. operator U() const;
  1182. template <typename U>
  1183. explicit
  1184. neg_matcher(
  1185. U&& m_)
  1186. : m( std::forward<U>(m_) )
  1187. {}
  1188. template <typename U>
  1189. bool
  1190. matches(
  1191. const U& u)
  1192. const
  1193. noexcept(noexcept(!std::declval<M>().matches(u)))
  1194. {
  1195. return !m.matches(u);
  1196. }
  1197. friend
  1198. std::ostream&
  1199. operator<<(
  1200. std::ostream& os,
  1201. neg_matcher<M> const& p)
  1202. {
  1203. return os << p.m;
  1204. }
  1205. private:
  1206. M m;
  1207. };
  1208. template <typename MatchType, typename Predicate, typename ... ActualType>
  1209. struct matcher_kind
  1210. {
  1211. using type = typed_matcher<MatchType>;
  1212. };
  1213. template <typename Predicate, typename ... ActualType>
  1214. struct matcher_kind<wildcard, Predicate, ActualType...>
  1215. {
  1216. using type = duck_typed_matcher<Predicate, ActualType...>;
  1217. };
  1218. template <typename MatchType, typename Predicate, typename ... ActualType>
  1219. using matcher_kind_t =
  1220. typename matcher_kind<MatchType, Predicate, ActualType...>::type;
  1221. template <typename Predicate, typename Printer, typename MatcherType, typename ... T>
  1222. class predicate_matcher
  1223. : private Predicate
  1224. , private Printer
  1225. , public MatcherType
  1226. {
  1227. public:
  1228. template <typename ... U>
  1229. constexpr
  1230. predicate_matcher(
  1231. Predicate&& pred,
  1232. Printer&& printer,
  1233. U&& ... v)
  1234. noexcept(noexcept(std::tuple<T...>(std::declval<U>()...)) && noexcept(Predicate(std::declval<Predicate&&>())) && noexcept(Printer(std::declval<Printer&&>())))
  1235. : Predicate(std::move(pred))
  1236. , Printer(std::move(printer))
  1237. , value(std::forward<U>(v)...)
  1238. {}
  1239. template <typename V>
  1240. constexpr
  1241. bool
  1242. matches(
  1243. V&& v)
  1244. const
  1245. noexcept(noexcept(std::declval<Predicate const&>()(std::declval<V&&>(), std::declval<const T&>()...)))
  1246. {
  1247. return matches_(std::forward<V>(v), std::make_index_sequence<sizeof...(T)>{});
  1248. }
  1249. friend
  1250. std::ostream&
  1251. operator<<(
  1252. std::ostream& os,
  1253. predicate_matcher const& v)
  1254. {
  1255. return v.print_(os, std::make_index_sequence<sizeof...(T)>{});
  1256. }
  1257. private:
  1258. // The below function call operator must be declared to
  1259. // work around gcc bug 78446
  1260. //
  1261. // For some reason microsoft compiler from VS2015 update 3
  1262. // requires the function call operator to be private to avoid
  1263. // ambiguities.
  1264. template <typename ... U>
  1265. void operator()(U&&...) const = delete;
  1266. template <typename V, size_t ... I>
  1267. bool matches_(V&& v, std::index_sequence<I...>) const
  1268. {
  1269. return Predicate::operator()(std::forward<V>(v), std::get<I>(value)...);
  1270. }
  1271. template <size_t ... I>
  1272. std::ostream& print_(std::ostream& os_, std::index_sequence<I...>) const
  1273. {
  1274. Printer::operator()(os_, std::get<I>(value)...);
  1275. return os_;
  1276. }
  1277. std::tuple<T...> value;
  1278. };
  1279. namespace lambdas {
  1280. // The below must be classes/structs to work with VS 2015 update 3
  1281. // since it doesn't respect the trailing return type declaration on
  1282. // the lambdas of template deduction context
  1283. #define TROMPELOEIL_MK_PRED_BINOP(name, op) \
  1284. struct name { \
  1285. template <typename X, typename Y> \
  1286. auto operator()(X const& x, Y const& y) const -> decltype(x op y) \
  1287. { \
  1288. ::trompeloeil::ignore(x,y); \
  1289. return x op y; \
  1290. } \
  1291. }
  1292. TROMPELOEIL_MK_PRED_BINOP(equal, ==);
  1293. TROMPELOEIL_MK_PRED_BINOP(not_equal, !=);
  1294. TROMPELOEIL_MK_PRED_BINOP(less, <);
  1295. TROMPELOEIL_MK_PRED_BINOP(less_equal, <=);
  1296. TROMPELOEIL_MK_PRED_BINOP(greater, >);
  1297. TROMPELOEIL_MK_PRED_BINOP(greater_equal, >=);
  1298. #undef TROMPELOEIL_MK_PRED_BINOP
  1299. }
  1300. template <typename MatchType, typename Predicate, typename Printer, typename ... T>
  1301. inline
  1302. predicate_matcher <Predicate, Printer, matcher_kind_t<MatchType, Predicate, std::decay_t<T>...>, std::decay_t<T>...>
  1303. make_matcher(Predicate pred, Printer print, T&& ... t)
  1304. {
  1305. return {std::move(pred), std::move(print), std::forward<T>(t)...};
  1306. }
  1307. template <typename T>
  1308. inline
  1309. auto
  1310. any_matcher(char const* type_name)
  1311. {
  1312. return make_matcher<T>([](auto&&) { return true; },
  1313. [type_name](std::ostream& os)
  1314. { os << " matching ANY(" << type_name << ")";});
  1315. }
  1316. template <typename T = wildcard, typename V>
  1317. inline
  1318. auto
  1319. eq(
  1320. V&& v)
  1321. {
  1322. return make_matcher<T>(lambdas::equal(),
  1323. [](std::ostream& os, auto const& value) {
  1324. os << " == ";
  1325. ::trompeloeil::print(os, value);
  1326. },
  1327. std::forward<V>(v));
  1328. }
  1329. template <typename T = wildcard, typename V>
  1330. inline
  1331. auto
  1332. ne(
  1333. V&& v)
  1334. {
  1335. return make_matcher<T>(lambdas::not_equal(),
  1336. [](std::ostream& os, auto const& value) {
  1337. os << " != ";
  1338. ::trompeloeil::print(os, value);
  1339. },
  1340. std::forward<V>(v));
  1341. }
  1342. template <typename T = wildcard, typename V>
  1343. inline
  1344. auto
  1345. ge(
  1346. V&& v)
  1347. {
  1348. return make_matcher<T>(lambdas::greater_equal(),
  1349. [](std::ostream& os, auto const& value) {
  1350. os << " >= ";
  1351. ::trompeloeil::print(os, value);
  1352. },
  1353. std::forward<V>(v));
  1354. }
  1355. template <typename T = wildcard, typename V>
  1356. inline
  1357. auto
  1358. gt(
  1359. V&& v)
  1360. {
  1361. return make_matcher<T>(lambdas::greater(),
  1362. [](std::ostream& os, auto const& value) {
  1363. os << " > ";
  1364. ::trompeloeil::print(os, value);
  1365. },
  1366. std::forward<V>(v));
  1367. }
  1368. template <typename T = wildcard, typename V>
  1369. inline
  1370. auto
  1371. lt(
  1372. V&& v)
  1373. {
  1374. return make_matcher<T>(lambdas::less(),
  1375. [](std::ostream& os, auto const& value) {
  1376. os << " < ";
  1377. ::trompeloeil::print(os, value);
  1378. },
  1379. std::forward<V>(v));
  1380. }
  1381. template <typename T = wildcard, typename V>
  1382. inline
  1383. auto
  1384. le(
  1385. V&& v)
  1386. {
  1387. return make_matcher<T>(lambdas::less_equal(),
  1388. [](std::ostream& os, auto const& value) {
  1389. os << " <= ";
  1390. ::trompeloeil::print(os, value);
  1391. },
  1392. std::forward<V>(v));
  1393. }
  1394. namespace lambdas {
  1395. inline
  1396. auto
  1397. regex_check(
  1398. std::regex&& re,
  1399. std::regex_constants::match_flag_type match_type)
  1400. {
  1401. class string_helper // a vastly simplified string_view type of class
  1402. {
  1403. public:
  1404. string_helper(
  1405. std::string const& s)
  1406. noexcept
  1407. : str(s.c_str())
  1408. {}
  1409. constexpr
  1410. string_helper(
  1411. char const* s)
  1412. noexcept
  1413. : str(s)
  1414. {}
  1415. char const*
  1416. c_str()
  1417. const
  1418. noexcept
  1419. {
  1420. return str;
  1421. }
  1422. private:
  1423. char const* str;
  1424. };
  1425. return [re = std::move(re), match_type](string_helper str, auto const&)
  1426. -> decltype(std::regex_search(str.c_str(), re, match_type))
  1427. {
  1428. return !::trompeloeil::is_null(str.c_str())
  1429. && std::regex_search(str.c_str(), re, match_type);
  1430. };
  1431. }
  1432. inline auto regex_printer()
  1433. {
  1434. return [](std::ostream& os, auto const& str)
  1435. {
  1436. os << " matching regular expression /" << str << "/";
  1437. };
  1438. }
  1439. }
  1440. template <typename Kind = wildcard>
  1441. auto
  1442. re(
  1443. std::string s,
  1444. std::regex_constants::syntax_option_type opt = std::regex_constants::ECMAScript,
  1445. std::regex_constants::match_flag_type match_type = std::regex_constants::match_default)
  1446. {
  1447. return make_matcher<Kind>(lambdas::regex_check(std::regex(s, opt),
  1448. match_type),
  1449. lambdas::regex_printer(),
  1450. std::move(s));
  1451. }
  1452. template <typename Kind = wildcard>
  1453. auto
  1454. re(
  1455. std::string s,
  1456. std::regex_constants::match_flag_type match_type)
  1457. {
  1458. return make_matcher<Kind>(lambdas::regex_check(std::regex(s), match_type),
  1459. lambdas::regex_printer(),
  1460. std::move(s));
  1461. }
  1462. inline
  1463. std::string
  1464. param_name_prefix(
  1465. ...)
  1466. {
  1467. return "";
  1468. }
  1469. template <typename M>
  1470. std::string
  1471. param_name_prefix(
  1472. const ptr_deref<M>*)
  1473. {
  1474. return "*" + ::trompeloeil::param_name_prefix(static_cast<M*>(nullptr));
  1475. }
  1476. template <typename M>
  1477. std::string
  1478. param_name_prefix(
  1479. const neg_matcher<M>*)
  1480. {
  1481. return "not " + ::trompeloeil::param_name_prefix(static_cast<M*>(nullptr));
  1482. }
  1483. template <typename T>
  1484. struct null_on_move
  1485. {
  1486. public:
  1487. null_on_move()
  1488. noexcept
  1489. : p{nullptr}
  1490. {}
  1491. null_on_move(
  1492. T* p_)
  1493. noexcept
  1494. : p{p_}
  1495. {}
  1496. null_on_move(
  1497. null_on_move&&)
  1498. noexcept
  1499. : p{nullptr}
  1500. {}
  1501. null_on_move(
  1502. null_on_move const&)
  1503. noexcept
  1504. : p{nullptr}
  1505. {}
  1506. null_on_move&
  1507. operator=(
  1508. const null_on_move&)
  1509. noexcept
  1510. {
  1511. p = nullptr;
  1512. return *this;
  1513. }
  1514. null_on_move&
  1515. operator=(
  1516. null_on_move&&)
  1517. noexcept
  1518. {
  1519. p = nullptr;
  1520. return *this;
  1521. }
  1522. null_on_move&
  1523. operator=(
  1524. T* t)
  1525. noexcept
  1526. {
  1527. p = t;
  1528. return *this;
  1529. }
  1530. T*&
  1531. leak()
  1532. noexcept
  1533. {
  1534. return p;
  1535. }
  1536. T&
  1537. operator*()
  1538. const
  1539. noexcept
  1540. {
  1541. return *p;
  1542. }
  1543. T*
  1544. operator->()
  1545. const
  1546. noexcept
  1547. {
  1548. return p;
  1549. }
  1550. explicit
  1551. operator bool()
  1552. const
  1553. noexcept
  1554. {
  1555. return p != nullptr;
  1556. }
  1557. private:
  1558. T* p;
  1559. };
  1560. struct sequence_handler_base
  1561. {
  1562. virtual
  1563. ~sequence_handler_base()
  1564. noexcept = default;
  1565. virtual
  1566. void
  1567. validate(severity s, char const *, location) = 0;
  1568. virtual
  1569. bool
  1570. is_first()
  1571. const
  1572. noexcept = 0;
  1573. virtual
  1574. void
  1575. retire()
  1576. noexcept = 0;
  1577. };
  1578. template <size_t N>
  1579. struct sequence_handler : public sequence_handler_base
  1580. {
  1581. public:
  1582. template <typename ... S>
  1583. sequence_handler(
  1584. char const *name,
  1585. location loc,
  1586. S&& ... s)
  1587. noexcept
  1588. : matchers{{name, loc, std::forward<S>(s)}...}
  1589. {
  1590. }
  1591. void
  1592. validate(
  1593. severity s,
  1594. char const *match_name,
  1595. location loc)
  1596. override
  1597. {
  1598. for (auto& e : matchers)
  1599. {
  1600. e.validate_match(s, match_name, loc);
  1601. }
  1602. }
  1603. bool
  1604. is_first()
  1605. const
  1606. noexcept
  1607. override
  1608. {
  1609. // std::all_of() is almost always preferable. The only reason
  1610. // for using a hand rolled loop is because it cuts compilation
  1611. // times quite noticeably (almost 10% with g++5.1)
  1612. for (auto& m : matchers)
  1613. {
  1614. if (!m.is_first()) return false;
  1615. }
  1616. return true;
  1617. }
  1618. void
  1619. retire()
  1620. noexcept
  1621. override
  1622. {
  1623. for (auto& e : matchers)
  1624. {
  1625. e.retire();
  1626. }
  1627. }
  1628. private:
  1629. sequence_matcher matchers[N];
  1630. };
  1631. struct lifetime_monitor;
  1632. template <typename T>
  1633. class deathwatched : public T
  1634. {
  1635. static_assert(std::has_virtual_destructor<T>::value,
  1636. "virtual destructor is a necessity for deathwatched to work");
  1637. public:
  1638. template <typename ... U,
  1639. typename = std::enable_if_t<std::is_constructible<T,U...>::value>>
  1640. deathwatched(
  1641. U&& ...u)
  1642. noexcept(noexcept(T(std::declval<U>()...)))
  1643. : T(std::forward<U>(u)...)
  1644. {}
  1645. ~deathwatched();
  1646. trompeloeil::lifetime_monitor*&
  1647. trompeloeil_expect_death(
  1648. trompeloeil::lifetime_monitor* monitor)
  1649. const
  1650. noexcept
  1651. {
  1652. auto lock = get_lock();
  1653. trompeloeil_lifetime_monitor = monitor;
  1654. return trompeloeil_lifetime_monitor.leak();
  1655. }
  1656. private:
  1657. mutable null_on_move<trompeloeil::lifetime_monitor> trompeloeil_lifetime_monitor;
  1658. };
  1659. struct expectation {
  1660. virtual ~expectation() = default;
  1661. virtual bool is_satisfied() const noexcept = 0;
  1662. virtual bool is_saturated() const noexcept = 0;
  1663. };
  1664. struct lifetime_monitor : public expectation
  1665. {
  1666. template <typename T>
  1667. lifetime_monitor(
  1668. ::trompeloeil::deathwatched<T> const &obj,
  1669. char const* obj_name_,
  1670. char const* invocation_name_,
  1671. char const* call_name_,
  1672. location loc_)
  1673. noexcept
  1674. : object_monitor(obj.trompeloeil_expect_death(this))
  1675. , loc(loc_)
  1676. , object_name(obj_name_)
  1677. , invocation_name(invocation_name_)
  1678. , call_name(call_name_)
  1679. {
  1680. }
  1681. bool is_satisfied() const noexcept override
  1682. {
  1683. return died;
  1684. }
  1685. bool is_saturated() const noexcept override
  1686. {
  1687. return died;
  1688. }
  1689. lifetime_monitor(lifetime_monitor const&) = delete;
  1690. ~lifetime_monitor()
  1691. {
  1692. auto lock = get_lock();
  1693. if (!died)
  1694. {
  1695. std::ostringstream os;
  1696. os << "Object " << object_name << " is still alive";
  1697. send_report<specialized>(severity::nonfatal, loc, os.str());
  1698. object_monitor = nullptr; // prevent its death poking this cadaver
  1699. }
  1700. }
  1701. void
  1702. notify()
  1703. noexcept
  1704. {
  1705. died = true;
  1706. if (sequences) sequences->validate(severity::nonfatal, call_name, loc);
  1707. }
  1708. template <typename ... T>
  1709. void
  1710. set_sequence(
  1711. T&& ... t)
  1712. {
  1713. auto seq = new sequence_handler<sizeof...(T)>(invocation_name,
  1714. loc,
  1715. std::forward<T>(t)...);
  1716. sequences.reset(seq);
  1717. }
  1718. private:
  1719. std::atomic<bool> died{false};
  1720. lifetime_monitor *&object_monitor;
  1721. location loc;
  1722. char const *object_name;
  1723. char const *invocation_name;
  1724. char const *call_name;
  1725. std::unique_ptr<sequence_handler_base> sequences;
  1726. };
  1727. template <typename T>
  1728. deathwatched<T>::~deathwatched()
  1729. {
  1730. auto lock = get_lock();
  1731. if (trompeloeil_lifetime_monitor)
  1732. {
  1733. trompeloeil_lifetime_monitor->notify();
  1734. return;
  1735. }
  1736. std::ostringstream os;
  1737. os << "Unexpected destruction of "
  1738. << typeid(T).name() << "@" << this << '\n';
  1739. send_report<specialized>(severity::nonfatal,
  1740. location{},
  1741. os.str());
  1742. }
  1743. template<typename T>
  1744. struct return_of;
  1745. template<typename R, typename ... A>
  1746. struct return_of<R(A...)>
  1747. {
  1748. using type = R;
  1749. };
  1750. template<typename T>
  1751. using return_of_t = typename return_of<T>::type;
  1752. template<typename T>
  1753. struct call_params_type;
  1754. template<typename R, typename ... T>
  1755. struct call_params_type<R(T...)>
  1756. {
  1757. using type = std::tuple<typename std::add_lvalue_reference<T>::type...>;
  1758. };
  1759. template<typename T>
  1760. using call_params_type_t = typename call_params_type<T>::type;
  1761. template <typename R>
  1762. struct default_return_t
  1763. {
  1764. TROMPELOEIL_NORETURN static R value()
  1765. {
  1766. std::abort(); // must never be called
  1767. }
  1768. };
  1769. template <typename R>
  1770. inline
  1771. R
  1772. default_return()
  1773. {
  1774. return default_return_t<R>::value();
  1775. }
  1776. template <>
  1777. inline
  1778. void
  1779. default_return<void>()
  1780. {
  1781. }
  1782. template<typename Sig>
  1783. struct call_matcher_base;
  1784. template <typename Sig>
  1785. struct call_matcher_list : public list<call_matcher_base<Sig>>
  1786. {
  1787. void decommission()
  1788. {
  1789. auto lock = get_lock();
  1790. auto iter = this->begin();
  1791. auto const e = this->end();
  1792. while (iter != e)
  1793. {
  1794. auto i = iter++;
  1795. auto &m = *i;
  1796. m.mock_destroyed();
  1797. m.unlink();
  1798. }
  1799. }
  1800. };
  1801. template<typename Sig>
  1802. struct call_matcher_base : public list_elem<call_matcher_base<Sig> >
  1803. {
  1804. call_matcher_base(
  1805. location loc_,
  1806. char const* name_)
  1807. : loc{loc_}
  1808. , name{name_}
  1809. {
  1810. }
  1811. call_matcher_base(call_matcher_base&&) = delete;
  1812. virtual
  1813. ~call_matcher_base() = default;
  1814. virtual
  1815. void
  1816. mock_destroyed() = 0;
  1817. virtual
  1818. bool
  1819. matches(
  1820. call_params_type_t<Sig> const&)
  1821. const = 0;
  1822. virtual
  1823. bool
  1824. first_in_sequence()
  1825. const
  1826. noexcept = 0;
  1827. virtual
  1828. void
  1829. run_actions(
  1830. call_params_type_t<Sig> &,
  1831. call_matcher_list<Sig> &saturated_list
  1832. ) = 0;
  1833. virtual
  1834. std::ostream&
  1835. report_signature(
  1836. std::ostream&)
  1837. const = 0;
  1838. TROMPELOEIL_NORETURN
  1839. virtual
  1840. std::ostream&
  1841. report_mismatch(
  1842. std::ostream&,
  1843. call_params_type_t<Sig> const &) = 0;
  1844. virtual
  1845. return_of_t<Sig>
  1846. return_value(
  1847. trace_agent&,
  1848. call_params_type_t<Sig>& p) = 0;
  1849. virtual
  1850. void
  1851. report_missed(
  1852. char const *reason) = 0;
  1853. location loc;
  1854. char const *name;
  1855. };
  1856. template <typename T, typename U>
  1857. bool
  1858. param_matches_impl(
  1859. T const& t,
  1860. U const& u,
  1861. matcher const*)
  1862. noexcept(noexcept(t.matches(u)))
  1863. {
  1864. return t.matches(u);
  1865. }
  1866. template <typename T,
  1867. typename U,
  1868. typename = std::enable_if_t<is_equal_comparable<T, U>::value>>
  1869. inline
  1870. U&
  1871. identity(
  1872. U& t)
  1873. noexcept
  1874. {
  1875. return t;
  1876. }
  1877. template <typename T,
  1878. typename U,
  1879. typename = std::enable_if_t<!is_equal_comparable<T, U>::value>>
  1880. inline
  1881. T
  1882. identity(
  1883. const U& u)
  1884. noexcept(noexcept(T(u)))
  1885. {
  1886. return u;
  1887. }
  1888. template <typename T, typename U>
  1889. bool
  1890. param_matches_impl(
  1891. T const& t,
  1892. U const& u,
  1893. ...)
  1894. noexcept(noexcept(::trompeloeil::identity<U>(t) == u))
  1895. {
  1896. return ::trompeloeil::identity<U>(t) == u;
  1897. }
  1898. template <typename T, typename U>
  1899. bool
  1900. param_matches(
  1901. T const& t,
  1902. U const& u)
  1903. noexcept(noexcept(param_matches_impl(t, u, &t)))
  1904. {
  1905. return ::trompeloeil::param_matches_impl(t, u, &t);
  1906. }
  1907. template <size_t ... I, typename T, typename U>
  1908. bool
  1909. match_parameters(
  1910. std::index_sequence<I...>,
  1911. T const& t,
  1912. U const& u)
  1913. noexcept(noexcept(std::initializer_list<bool>{trompeloeil::param_matches(std::get<I>(t),std::get<I>(u))...}))
  1914. {
  1915. bool all_true = true;
  1916. ::trompeloeil::ignore(t, u); // Kills unmotivated VS2015 warning in the empty case
  1917. ::trompeloeil::ignore(std::initializer_list<bool>{all_true = all_true && ::trompeloeil::param_matches(std::get<I>(t), std::get<I>(u))...});
  1918. return all_true;
  1919. }
  1920. template <typename ... T, typename ... U>
  1921. bool
  1922. match_parameters(
  1923. std::tuple<T...> const& t,
  1924. std::tuple<U...> const& u)
  1925. noexcept(noexcept(match_parameters(std::make_index_sequence<sizeof...(T)>{}, t, u)))
  1926. {
  1927. return ::trompeloeil::match_parameters(std::make_index_sequence<sizeof...(T)>{}, t, u);
  1928. }
  1929. template <typename V, typename P>
  1930. void print_mismatch(
  1931. std::ostream& os,
  1932. size_t num,
  1933. V const& v,
  1934. P const& p)
  1935. {
  1936. if (!::trompeloeil::param_matches(v, p))
  1937. {
  1938. auto prefix = ::trompeloeil::param_name_prefix(&v) + "_";
  1939. os << " Expected " << std::setw((num < 9) + 1) << prefix << num+1;
  1940. ::trompeloeil::print_expectation(os, v);
  1941. }
  1942. }
  1943. template <typename ... V, typename ... P, size_t ... I>
  1944. void print_mismatch(
  1945. std::ostream& os,
  1946. std::index_sequence<I...>,
  1947. std::tuple<V...> const& v,
  1948. std::tuple<P...> const& p)
  1949. {
  1950. ::trompeloeil::ignore(os, v, p); // Kills unmotivated VS2015 warning in the empty case
  1951. ::trompeloeil::ignore(std::initializer_list<int>{(print_mismatch(os, I, std::get<I>(v), std::get<I>(p)),0)...});
  1952. }
  1953. template <typename ... V, typename ... P>
  1954. void print_mismatch(
  1955. std::ostream& os,
  1956. std::tuple<V...> const& v,
  1957. std::tuple<P...> const& p)
  1958. {
  1959. print_mismatch(os, std::make_index_sequence<sizeof...(V)>{}, v, p);
  1960. }
  1961. template <typename T>
  1962. void missed_value(
  1963. std::ostream& os,
  1964. int i,
  1965. T const& t)
  1966. {
  1967. auto prefix = ::trompeloeil::param_name_prefix(&t) + "_";
  1968. os << " param " << std::setw((i < 9) + 1) << prefix << i + 1
  1969. << ::trompeloeil::param_compare_operator(&t);
  1970. ::trompeloeil::print(os, t);
  1971. os << '\n';
  1972. }
  1973. template <size_t ... I, typename ... T>
  1974. void stream_params(
  1975. std::ostream &os,
  1976. std::index_sequence<I...>,
  1977. std::tuple<T...> const &t)
  1978. {
  1979. ::trompeloeil::ignore(os, t); // Kills unmotivated VS2015 warning in the empty case
  1980. ::trompeloeil::ignore(std::initializer_list<int>{(missed_value(os, I, std::get<I>(t)),0)...});
  1981. }
  1982. template <typename ... T>
  1983. void
  1984. stream_params(
  1985. std::ostream &os,
  1986. std::tuple<T...> const &t)
  1987. {
  1988. stream_params(os, std::make_index_sequence<sizeof...(T)>{}, t);
  1989. }
  1990. template <typename ... T>
  1991. std::string
  1992. params_string(
  1993. std::tuple<T...> const& t)
  1994. {
  1995. std::ostringstream os;
  1996. stream_params(os, t);
  1997. return os.str();
  1998. }
  1999. class trace_agent
  2000. {
  2001. public:
  2002. trace_agent(
  2003. location loc_,
  2004. char const* name_,
  2005. tracer* t_)
  2006. : loc{loc_}
  2007. , t{t_}
  2008. {
  2009. if (t)
  2010. {
  2011. os << name_ << " with.\n";
  2012. }
  2013. }
  2014. trace_agent(trace_agent const&) = delete;
  2015. trace_agent(trace_agent &&) = delete;
  2016. ~trace_agent()
  2017. {
  2018. if (t)
  2019. {
  2020. t->trace(loc.file, loc.line, os.str());
  2021. }
  2022. }
  2023. trace_agent&
  2024. operator=(trace_agent const&) = delete;
  2025. trace_agent&
  2026. operator=(trace_agent &&) = delete;
  2027. template <typename ... T>
  2028. void
  2029. trace_params(
  2030. std::tuple<T...> const& params)
  2031. {
  2032. if (t)
  2033. {
  2034. stream_params(os, params);
  2035. }
  2036. }
  2037. template <typename T>
  2038. auto
  2039. trace_return(
  2040. T&& rv)
  2041. -> T
  2042. {
  2043. if (t)
  2044. {
  2045. os << " -> ";
  2046. print(os, rv);
  2047. os << '\n';
  2048. }
  2049. return std::forward<T>(rv);
  2050. }
  2051. void
  2052. trace_exception()
  2053. {
  2054. if (t)
  2055. {
  2056. try {
  2057. throw;
  2058. }
  2059. catch (std::exception& e)
  2060. {
  2061. os << "threw exception: what() = " << e.what() << '\n';
  2062. }
  2063. catch (...)
  2064. {
  2065. os << "threw unknown exception\n";
  2066. }
  2067. }
  2068. }
  2069. private:
  2070. location loc;
  2071. tracer* t;
  2072. std::ostringstream os;
  2073. };
  2074. template <typename Sig>
  2075. call_matcher_base <Sig> *
  2076. find(
  2077. call_matcher_list <Sig> &list,
  2078. call_params_type_t <Sig> const &p)
  2079. noexcept
  2080. {
  2081. call_matcher_base<Sig>* first_match = nullptr;
  2082. for (auto& i : list)
  2083. {
  2084. if (i.matches(p))
  2085. {
  2086. if (i.first_in_sequence())
  2087. {
  2088. return &i;
  2089. }
  2090. if (!first_match)
  2091. {
  2092. first_match = &i;
  2093. }
  2094. }
  2095. }
  2096. return first_match;
  2097. }
  2098. template <typename Sig>
  2099. TROMPELOEIL_NORETURN
  2100. void
  2101. report_mismatch(
  2102. call_matcher_list <Sig> &matcher_list,
  2103. call_matcher_list <Sig> &saturated_list,
  2104. std::string const &name,
  2105. call_params_type_t <Sig> const &p)
  2106. {
  2107. std::ostringstream os;
  2108. os << "No match for call of " << name << " with.\n";
  2109. stream_params(os, p);
  2110. bool saturated_match = false;
  2111. for (auto& m : saturated_list)
  2112. {
  2113. if (m.matches(p))
  2114. {
  2115. if (!saturated_match)
  2116. {
  2117. os << "\nMatches saturated call requirement\n";
  2118. saturated_match = true;
  2119. }
  2120. os << " ";
  2121. m.report_signature(os) << '\n';
  2122. }
  2123. }
  2124. if (!saturated_match)
  2125. {
  2126. for (auto& m : matcher_list)
  2127. {
  2128. os << "\nTried ";
  2129. m.report_mismatch(os, p);
  2130. }
  2131. }
  2132. send_report<specialized>(severity::fatal, location{}, os.str());
  2133. std::abort(); // must never get here.
  2134. }
  2135. template <typename Sig>
  2136. class return_handler
  2137. {
  2138. public:
  2139. virtual
  2140. ~return_handler() = default;
  2141. virtual
  2142. return_of_t<Sig>
  2143. call(
  2144. trace_agent&,
  2145. call_params_type_t<Sig>& params) = 0;
  2146. };
  2147. template <typename Ret, typename F, typename P, typename = std::enable_if_t<std::is_void<Ret>::value>>
  2148. void
  2149. trace_return(
  2150. trace_agent&,
  2151. F& func,
  2152. P& params)
  2153. {
  2154. func(params);
  2155. }
  2156. template <typename Ret, typename F, typename P, typename = std::enable_if_t<!std::is_void<Ret>::value>>
  2157. Ret
  2158. trace_return(
  2159. trace_agent& agent,
  2160. F& func,
  2161. P& params)
  2162. {
  2163. return agent.trace_return(func(params));
  2164. }
  2165. template <typename Sig, typename T>
  2166. class return_handler_t : public return_handler<Sig>
  2167. {
  2168. public:
  2169. template <typename U>
  2170. return_handler_t(
  2171. U&& u)
  2172. : func(std::forward<U>(u))
  2173. {}
  2174. return_of_t<Sig>
  2175. call(
  2176. trace_agent& agent,
  2177. call_params_type_t<Sig>& params)
  2178. override
  2179. {
  2180. return trace_return<return_of_t<Sig>>(agent, func, params);
  2181. }
  2182. private:
  2183. T func;
  2184. };
  2185. template<typename Sig>
  2186. class condition_base : public list_elem<condition_base<Sig> >
  2187. {
  2188. public:
  2189. condition_base(
  2190. char const *n)
  2191. noexcept
  2192. : id(n)
  2193. {}
  2194. virtual
  2195. ~condition_base() = default;
  2196. virtual
  2197. bool
  2198. check(
  2199. call_params_type_t<Sig> const&)
  2200. const = 0;
  2201. virtual
  2202. char const*
  2203. name()
  2204. const
  2205. noexcept
  2206. {
  2207. return id;
  2208. }
  2209. private:
  2210. char const *id;
  2211. };
  2212. template <typename Sig>
  2213. using condition_list = list<condition_base<Sig>, delete_disposer >;
  2214. template<typename Sig, typename Cond>
  2215. struct condition : public condition_base<Sig>
  2216. {
  2217. condition(
  2218. char const *str_,
  2219. Cond c_)
  2220. : condition_base<Sig>(str_)
  2221. , c(c_) {}
  2222. bool
  2223. check(
  2224. call_params_type_t<Sig> const & t)
  2225. const
  2226. override
  2227. {
  2228. return c(t);
  2229. }
  2230. private:
  2231. Cond c;
  2232. };
  2233. template<typename Sig>
  2234. struct side_effect_base : public list_elem<side_effect_base<Sig> >
  2235. {
  2236. virtual
  2237. ~side_effect_base() = default;
  2238. virtual
  2239. void
  2240. action(
  2241. call_params_type_t<Sig> &)
  2242. const = 0;
  2243. };
  2244. template<typename Sig>
  2245. using side_effect_list = list<side_effect_base<Sig>, delete_disposer>;
  2246. template<typename Sig, typename Action>
  2247. struct side_effect : public side_effect_base<Sig>
  2248. {
  2249. template <typename A>
  2250. side_effect(
  2251. A&& a_)
  2252. : a(std::forward<A>(a_))
  2253. {}
  2254. void
  2255. action(
  2256. call_params_type_t<Sig> &t)
  2257. const
  2258. override
  2259. {
  2260. a(t);
  2261. }
  2262. private:
  2263. Action a;
  2264. };
  2265. template <unsigned long long L, unsigned long long H = L>
  2266. struct multiplicity { };
  2267. template<typename R, typename Parent>
  2268. struct return_injector : Parent
  2269. {
  2270. using return_type = R;
  2271. };
  2272. template <typename Parent>
  2273. struct throw_injector : Parent
  2274. {
  2275. static bool const throws = true;
  2276. };
  2277. template <typename Parent>
  2278. struct sideeffect_injector : Parent
  2279. {
  2280. static bool const side_effects = true;
  2281. };
  2282. template <typename Parent, unsigned long long H>
  2283. struct call_limit_injector : Parent
  2284. {
  2285. static bool const call_limit_set = true;
  2286. static unsigned long long const upper_call_limit = H;
  2287. };
  2288. template <typename Parent>
  2289. struct call_limit_injector<Parent, 0ULL> : Parent
  2290. {
  2291. static bool const call_limit_set = true;
  2292. static unsigned long long const upper_call_limit = 0ULL;
  2293. };
  2294. template <typename Parent>
  2295. struct sequence_injector : Parent
  2296. {
  2297. static bool const sequence_set = true;
  2298. };
  2299. template <typename Matcher, typename modifier_tag, typename Parent>
  2300. struct call_modifier : public Parent
  2301. {
  2302. using typename Parent::signature;
  2303. using typename Parent::return_type;
  2304. using Parent::call_limit_set;
  2305. using Parent::upper_call_limit;
  2306. using Parent::sequence_set;
  2307. using Parent::throws;
  2308. using Parent::side_effects;
  2309. call_modifier(
  2310. Matcher* m)
  2311. noexcept
  2312. : matcher{m}
  2313. {}
  2314. template <typename D>
  2315. call_modifier&&
  2316. with(
  2317. char const* str,
  2318. D&& d)
  2319. &&
  2320. {
  2321. matcher->add_condition(str, std::forward<D>(d));
  2322. return std::move(*this);
  2323. }
  2324. template <typename A>
  2325. call_modifier<Matcher, modifier_tag, sideeffect_injector<Parent>>
  2326. sideeffect(
  2327. A&& a)
  2328. {
  2329. constexpr bool forbidden = upper_call_limit == 0U;
  2330. static_assert(!forbidden,
  2331. "SIDE_EFFECT for forbidden call does not make sense");
  2332. matcher->add_side_effect(std::forward<A>(a));
  2333. return {std::move(matcher)};
  2334. }
  2335. template <typename H>
  2336. call_modifier<Matcher, modifier_tag, return_injector<return_of_t<signature>, Parent >>
  2337. handle_return(
  2338. H&& h)
  2339. {
  2340. using params_type = call_params_type_t<signature>&;
  2341. using sigret = return_of_t<signature>;
  2342. using ret = decltype(std::declval<H>()(std::declval<params_type>()));
  2343. // don't know why MS VS 2015 RC doesn't like std::result_of
  2344. constexpr bool is_illegal_type = std::is_same<std::decay_t<ret>, illegal_argument>::value;
  2345. constexpr bool is_first_return = std::is_same<return_type, void>::value;
  2346. constexpr bool void_signature = std::is_same<sigret, void>::value;
  2347. constexpr bool is_pointer_sigret = std::is_pointer<sigret>::value;
  2348. constexpr bool is_pointer_ret = std::is_pointer<std::decay_t<ret>>::value;
  2349. constexpr bool ptr_const_mismatch = is_pointer_ret && is_pointer_sigret && !std::is_const<std::remove_pointer_t<sigret>>{} && std::is_const<std::remove_pointer_t<std::decay_t<ret>>>{};
  2350. constexpr bool is_ref_sigret = std::is_reference<sigret>::value;
  2351. constexpr bool is_ref_ret = std::is_reference<ret>::value;
  2352. constexpr bool ref_const_mismatch=
  2353. is_ref_ret &&
  2354. is_ref_sigret &&
  2355. !std::is_const<std::remove_reference_t<sigret>>::value &&
  2356. std::is_const<std::remove_reference_t<ret>>::value;
  2357. constexpr bool matching_ret_type = std::is_constructible<sigret, ret>::value;
  2358. constexpr bool ref_value_mismatch = !is_ref_ret && is_ref_sigret;
  2359. static_assert(matching_ret_type || !void_signature,
  2360. "RETURN does not make sense for void-function");
  2361. static_assert(!is_illegal_type,
  2362. "RETURN illegal argument");
  2363. static_assert(!ptr_const_mismatch,
  2364. "RETURN const* from function returning pointer to non-const");
  2365. static_assert(!ref_value_mismatch || matching_ret_type,
  2366. "RETURN non-reference from function returning reference");
  2367. static_assert(ref_value_mismatch || !ref_const_mismatch,
  2368. "RETURN const& from function returning non-const reference");
  2369. static_assert(ptr_const_mismatch || ref_const_mismatch || is_illegal_type || matching_ret_type || void_signature,
  2370. "RETURN value is not convertible to the return type of the function");
  2371. static_assert(is_first_return,
  2372. "Multiple RETURN does not make sense");
  2373. static_assert(!throws || upper_call_limit == 0,
  2374. "THROW and RETURN does not make sense");
  2375. static_assert(upper_call_limit > 0ULL,
  2376. "RETURN for forbidden call does not make sense");
  2377. constexpr bool valid = !is_illegal_type && matching_ret_type && is_first_return && !throws && upper_call_limit > 0ULL;
  2378. using tag = std::integral_constant<bool, valid>;
  2379. matcher->set_return(tag{}, std::forward<H>(h));
  2380. return {matcher};
  2381. }
  2382. template <typename H>
  2383. call_modifier<Matcher, modifier_tag, throw_injector<Parent> >
  2384. handle_throw(
  2385. H&& h)
  2386. {
  2387. static_assert(!throws,
  2388. "Multiple THROW does not make sense");
  2389. constexpr bool has_return = !std::is_same<return_type, void>::value;
  2390. static_assert(!has_return,
  2391. "THROW and RETURN does not make sense");
  2392. constexpr bool forbidden = upper_call_limit == 0U;
  2393. static_assert(!forbidden,
  2394. "THROW for forbidden call does not make sense");
  2395. constexpr bool valid = !throws && !has_return;// && !forbidden;
  2396. using tag = std::integral_constant<bool, valid>;
  2397. auto handler = [=](auto& p) -> decltype(auto)
  2398. {
  2399. h(p);
  2400. return trompeloeil::default_return<return_of_t<signature>>();
  2401. };
  2402. matcher->set_return(tag{}, std::move(handler));
  2403. return {matcher};
  2404. }
  2405. template <unsigned long long L,
  2406. unsigned long long H,
  2407. bool times_set = call_limit_set>
  2408. call_modifier<Matcher, modifier_tag, call_limit_injector<Parent, H>>
  2409. times(
  2410. multiplicity<L, H>)
  2411. {
  2412. static_assert(!times_set,
  2413. "Only one TIMES call limit is allowed, but it can express an interval");
  2414. static_assert(H >= L,
  2415. "In TIMES the first value must not exceed the second");
  2416. static_assert(H > 0 || !throws,
  2417. "THROW and TIMES(0) does not make sense");
  2418. static_assert(H > 0 || std::is_same<return_type, void>::value,
  2419. "RETURN and TIMES(0) does not make sense");
  2420. static_assert(H > 0 || !side_effects,
  2421. "SIDE_EFFECT and TIMES(0) does not make sense");
  2422. static_assert(H > 0 || !sequence_set,
  2423. "IN_SEQUENCE and TIMES(0) does not make sense");
  2424. matcher->min_calls = L;
  2425. matcher->max_calls = H;
  2426. return {matcher};
  2427. }
  2428. template <typename ... T,
  2429. bool b = sequence_set>
  2430. call_modifier<Matcher, modifier_tag, sequence_injector<Parent>>
  2431. in_sequence(
  2432. T&& ... t)
  2433. {
  2434. static_assert(!b,
  2435. "Multiple IN_SEQUENCE does not make sense."
  2436. " You can list several sequence objects at once");
  2437. static_assert(upper_call_limit > 0ULL,
  2438. "IN_SEQUENCE for forbidden call does not make sense");
  2439. matcher->set_sequence(std::forward<T>(t)...);
  2440. return {matcher};
  2441. }
  2442. Matcher* matcher;
  2443. };
  2444. inline
  2445. void
  2446. report_unfulfilled(
  2447. const char* reason,
  2448. char const *name,
  2449. std::string const &values,
  2450. unsigned long long min_calls,
  2451. unsigned long long call_count,
  2452. location loc)
  2453. {
  2454. std::ostringstream os;
  2455. os << reason
  2456. << ":\nExpected " << name << " to be called ";
  2457. if (min_calls == 1)
  2458. os << "once";
  2459. else
  2460. os << min_calls << " times";
  2461. os << ", actually ";
  2462. switch (call_count)
  2463. {
  2464. case 0:
  2465. os << "never called\n"; break;
  2466. case 1:
  2467. os << "called once\n"; break;
  2468. default:
  2469. os << "called " << call_count << " times\n";
  2470. }
  2471. os << values;
  2472. send_report<specialized>(severity::nonfatal, loc, os.str());
  2473. }
  2474. inline
  2475. void
  2476. report_forbidden_call(
  2477. char const *name,
  2478. location loc,
  2479. std::string const& values)
  2480. {
  2481. std::ostringstream os;
  2482. os << "Match of forbidden call of " << name
  2483. << " at " << loc << '\n' << values;
  2484. send_report<specialized>(severity::fatal, loc, os.str());
  2485. }
  2486. template <typename Sig>
  2487. struct matcher_info
  2488. {
  2489. using signature = Sig;
  2490. using return_type = void;
  2491. static unsigned long long const upper_call_limit = 1;
  2492. static bool const throws = false;
  2493. static bool const call_limit_set = false;
  2494. static bool const sequence_set = false;
  2495. static bool const side_effects = false;
  2496. };
  2497. template<typename Sig, typename Value>
  2498. struct call_matcher : public call_matcher_base<Sig>, expectation
  2499. {
  2500. using call_matcher_base<Sig>::name;
  2501. using call_matcher_base<Sig>::loc;
  2502. template<typename ... U>
  2503. call_matcher(
  2504. char const *file,
  2505. unsigned long line,
  2506. char const *call_string,
  2507. U &&... u)
  2508. : call_matcher_base<Sig>(location{file, line}, call_string)
  2509. , val(std::forward<U>(u)...)
  2510. {}
  2511. call_matcher(call_matcher &&r) = delete;
  2512. ~call_matcher()
  2513. {
  2514. auto lock = get_lock();
  2515. if (is_unfulfilled())
  2516. {
  2517. report_missed("Unfulfilled expectation");
  2518. }
  2519. this->unlink();
  2520. }
  2521. bool
  2522. is_satisfied()
  2523. const
  2524. noexcept
  2525. override
  2526. {
  2527. auto lock = get_lock();
  2528. return call_count >= min_calls;
  2529. }
  2530. bool
  2531. is_saturated()
  2532. const
  2533. noexcept
  2534. override
  2535. {
  2536. auto lock = get_lock();
  2537. return call_count >= max_calls;
  2538. }
  2539. bool
  2540. is_unfulfilled()
  2541. const
  2542. noexcept
  2543. {
  2544. return !reported && this->is_linked() && call_count < min_calls;
  2545. }
  2546. void
  2547. mock_destroyed()
  2548. override
  2549. {
  2550. if (is_unfulfilled())
  2551. {
  2552. report_missed("Pending expectation on destroyed mock object");
  2553. }
  2554. }
  2555. call_matcher*
  2556. hook_last(
  2557. call_matcher_list<Sig> &list)
  2558. noexcept
  2559. {
  2560. list.push_front(this);
  2561. return this;
  2562. }
  2563. bool
  2564. matches(
  2565. call_params_type_t<Sig> const& params)
  2566. const
  2567. override
  2568. {
  2569. return match_parameters(val, params) && match_conditions(params);
  2570. }
  2571. bool
  2572. match_conditions(
  2573. call_params_type_t<Sig> const & params)
  2574. const
  2575. {
  2576. // std::all_of() is almost always preferable. The only reason
  2577. // for using a hand rolled loop is because it cuts compilation
  2578. // times quite noticeably (almost 10% with g++5.1)
  2579. for (auto& c : conditions)
  2580. {
  2581. if (!c.check(params)) return false;
  2582. }
  2583. return true;
  2584. }
  2585. bool
  2586. first_in_sequence()
  2587. const
  2588. noexcept
  2589. override
  2590. {
  2591. auto saturated = call_count >= min_calls;
  2592. return saturated || !sequences || sequences->is_first();
  2593. }
  2594. return_of_t<Sig>
  2595. return_value(
  2596. trace_agent& agent,
  2597. call_params_type_t<Sig>& params)
  2598. override
  2599. {
  2600. if (!return_handler_obj) return default_return<return_of_t<Sig>>();
  2601. return return_handler_obj->call(agent, params);
  2602. }
  2603. void
  2604. run_actions(
  2605. call_params_type_t<Sig>& params,
  2606. call_matcher_list<Sig> &saturated_list)
  2607. override
  2608. {
  2609. if (max_calls == 0)
  2610. {
  2611. reported = true;
  2612. report_forbidden_call(name, loc, params_string(params));
  2613. }
  2614. auto lock = get_lock();
  2615. {
  2616. if (call_count < min_calls && sequences)
  2617. {
  2618. sequences->validate(severity::fatal, name, loc);
  2619. }
  2620. if (++call_count == min_calls && sequences)
  2621. {
  2622. sequences->retire();
  2623. }
  2624. if (call_count == max_calls)
  2625. {
  2626. this->unlink();
  2627. saturated_list.push_back(this);
  2628. }
  2629. }
  2630. for (auto& a : actions) a.action(params);
  2631. }
  2632. std::ostream&
  2633. report_signature(
  2634. std::ostream& os)
  2635. const override
  2636. {
  2637. return os << name << " at " << loc;
  2638. }
  2639. std::ostream&
  2640. report_mismatch(
  2641. std::ostream& os,
  2642. call_params_type_t<Sig> const & params)
  2643. override
  2644. {
  2645. reported = true;
  2646. report_signature(os);
  2647. if (match_parameters(val, params))
  2648. {
  2649. for (auto& cond : conditions)
  2650. {
  2651. if (!cond.check(params))
  2652. {
  2653. os << "\n Failed WITH(" << cond.name() << ')';
  2654. }
  2655. }
  2656. }
  2657. else
  2658. {
  2659. os << '\n';
  2660. ::trompeloeil::print_mismatch(os, val, params);
  2661. }
  2662. return os;
  2663. }
  2664. void
  2665. report_missed(
  2666. char const *reason)
  2667. override
  2668. {
  2669. reported = true;
  2670. report_unfulfilled(
  2671. reason,
  2672. name,
  2673. params_string(val),
  2674. min_calls,
  2675. call_count,
  2676. loc);
  2677. }
  2678. template <typename C>
  2679. void
  2680. add_condition(
  2681. char const *str,
  2682. C&& c)
  2683. {
  2684. auto cond = new condition<Sig, C>(str, std::forward<C>(c));
  2685. conditions.push_back(cond);
  2686. }
  2687. template <typename S>
  2688. void
  2689. add_side_effect(
  2690. S&& s)
  2691. {
  2692. auto effect = new side_effect<Sig, S>(std::forward<S>(s));
  2693. actions.push_back(effect);
  2694. }
  2695. template <typename ... T>
  2696. void
  2697. set_sequence(
  2698. T&& ... t)
  2699. {
  2700. auto seq = new sequence_handler<sizeof...(T)>(name,
  2701. loc,
  2702. std::forward<T>(t)...);
  2703. sequences.reset(seq);
  2704. }
  2705. template <typename T>
  2706. inline
  2707. void
  2708. set_return(
  2709. std::true_type,
  2710. T&& h)
  2711. {
  2712. using basic_t = typename std::remove_reference<T>::type;
  2713. using handler = return_handler_t<Sig, basic_t>;
  2714. return_handler_obj.reset(new handler(std::forward<T>(h)));
  2715. }
  2716. template <typename T>
  2717. inline // Never called. Used to limit errmsg
  2718. static // with RETURN of wrong type and after:
  2719. void // FORBIDDEN_CALL
  2720. set_return(std::false_type, T&&t)// RETURN
  2721. noexcept; // THROW
  2722. condition_list<Sig> conditions;
  2723. side_effect_list<Sig> actions;
  2724. std::unique_ptr<return_handler<Sig>> return_handler_obj;
  2725. std::unique_ptr<sequence_handler_base> sequences;
  2726. unsigned long long call_count = 0;
  2727. std::atomic<unsigned long long> min_calls{1};
  2728. std::atomic<unsigned long long> max_calls{1};
  2729. Value val;
  2730. bool reported = false;
  2731. };
  2732. template<int N, typename T>
  2733. constexpr
  2734. inline
  2735. decltype(auto)
  2736. arg(
  2737. T* t,
  2738. std::true_type)
  2739. {
  2740. return std::get<N-1>(*t);
  2741. }
  2742. template <int N>
  2743. inline
  2744. constexpr
  2745. illegal_argument const
  2746. arg(
  2747. void const*,
  2748. std::false_type)
  2749. noexcept
  2750. {
  2751. return {};
  2752. }
  2753. template <int N, typename T>
  2754. decltype(auto)
  2755. mkarg(
  2756. T& t)
  2757. noexcept
  2758. {
  2759. return arg<N>(&t, std::integral_constant<bool, (N <= std::tuple_size<T>::value)>{});
  2760. }
  2761. template <typename Mock>
  2762. struct call_validator_t
  2763. {
  2764. template <typename M, typename Tag, typename Info>
  2765. auto
  2766. make_expectation(
  2767. std::true_type,
  2768. call_modifier<M, Tag, Info>&& m)
  2769. const
  2770. noexcept
  2771. {
  2772. auto lock = get_lock();
  2773. m.matcher->hook_last(obj.trompeloeil_matcher_list(static_cast<Tag*>(nullptr)));
  2774. return std::unique_ptr<expectation>(m.matcher);
  2775. }
  2776. template <typename T>
  2777. static // Never called. Used to
  2778. std::unique_ptr<expectation> // limit errmsg when RETURN
  2779. make_expectation(std::false_type, T&&) noexcept; // is missing in non-void
  2780. // function
  2781. template <typename M, typename Tag, typename Info>
  2782. inline
  2783. auto
  2784. operator+(
  2785. call_modifier<M, Tag, Info>&& t)
  2786. const
  2787. {
  2788. using call = call_modifier<M, Tag, Info>;
  2789. using sigret = return_of_t<typename call::signature>;
  2790. using ret = typename call::return_type;
  2791. constexpr bool retmatch = std::is_same<ret, sigret>::value;
  2792. constexpr bool forbidden = call::upper_call_limit == 0ULL;
  2793. constexpr bool valid_return_type = call::throws || retmatch || forbidden;
  2794. static_assert(valid_return_type, "RETURN missing for non-void function");
  2795. auto tag = std::integral_constant<bool, valid_return_type>{};
  2796. return make_expectation(tag, std::move(t));
  2797. }
  2798. Mock& obj;
  2799. };
  2800. template <typename T,
  2801. typename = std::enable_if_t<std::is_lvalue_reference<T&&>::value>>
  2802. inline
  2803. T&&
  2804. decay_return_type(
  2805. T&& t)
  2806. {
  2807. return std::forward<T>(t);
  2808. }
  2809. template <typename T,
  2810. typename = std::enable_if_t<std::is_rvalue_reference<T&&>::value>>
  2811. inline
  2812. T
  2813. decay_return_type(
  2814. T&& t)
  2815. {
  2816. return std::forward<T>(t);
  2817. }
  2818. template <typename T, size_t N>
  2819. inline
  2820. T*
  2821. decay_return_type(
  2822. T (&t)[N])
  2823. {
  2824. return t;
  2825. }
  2826. template <bool sequence_set>
  2827. struct lifetime_monitor_modifier
  2828. {
  2829. operator std::unique_ptr<lifetime_monitor>() { return std::move(monitor);}
  2830. template <typename ... T, bool b = sequence_set>
  2831. lifetime_monitor_modifier<true>
  2832. in_sequence(T&& ... t)
  2833. {
  2834. static_assert(!b,
  2835. "Multiple IN_SEQUENCE does not make sense."
  2836. " You can list several sequence objects at once");
  2837. monitor->set_sequence(std::forward<T>(t)...);
  2838. return { std::move(monitor) };
  2839. }
  2840. std::unique_ptr<lifetime_monitor> monitor;
  2841. };
  2842. struct lifetime_monitor_releaser
  2843. {
  2844. template <bool b>
  2845. std::unique_ptr<trompeloeil::lifetime_monitor>
  2846. operator+(
  2847. lifetime_monitor_modifier<b>&& m)
  2848. const
  2849. {
  2850. return m;
  2851. }
  2852. };
  2853. template <typename Sig>
  2854. struct expectations
  2855. {
  2856. ~expectations() {
  2857. active.decommission();
  2858. saturated.decommission();
  2859. }
  2860. call_matcher_list<Sig> active;
  2861. call_matcher_list<Sig> saturated;
  2862. };
  2863. template <typename Sig, typename ... P>
  2864. return_of_t<Sig> mock_func(std::false_type, P&& ...);
  2865. template <typename Sig, typename ... P>
  2866. return_of_t<Sig>
  2867. mock_func(std::true_type,
  2868. expectations<Sig>& e,
  2869. char const *func_name,
  2870. char const *sig_name,
  2871. P&& ... p)
  2872. {
  2873. auto lock = get_lock();
  2874. call_params_type_t<void(P...)> param_value(std::forward<P>(p)...);
  2875. auto i = find(e.active, param_value);
  2876. if (!i)
  2877. {
  2878. report_mismatch(e.active,
  2879. e.saturated,
  2880. func_name + std::string(" with signature ") + sig_name,
  2881. param_value);
  2882. }
  2883. trace_agent ta{i->loc, i->name, tracer_obj()};
  2884. try
  2885. {
  2886. ta.trace_params(param_value);
  2887. i->run_actions(param_value, e.saturated);
  2888. return i->return_value(ta, param_value);
  2889. }
  2890. catch (...)
  2891. {
  2892. ta.trace_exception();
  2893. throw;
  2894. }
  2895. }
  2896. template <typename ... U>
  2897. struct param_helper {
  2898. using type = decltype(std::make_tuple(std::declval<U>()...));
  2899. };
  2900. template <typename ... U>
  2901. using param_t = typename param_helper<U...>::type;
  2902. template <typename sig, typename tag, typename... U>
  2903. using modifier_t = call_modifier<call_matcher<sig, param_t<U...>>,
  2904. tag,
  2905. matcher_info<sig>>;
  2906. template <typename M,
  2907. typename = std::enable_if_t<::trompeloeil::is_matcher<M>::value>>
  2908. inline
  2909. ::trompeloeil::ptr_deref<std::decay_t<M>>
  2910. operator*(
  2911. M&& m)
  2912. {
  2913. return ::trompeloeil::ptr_deref<std::decay_t<M>>{std::forward<M>(m)};
  2914. }
  2915. template <typename M,
  2916. typename = std::enable_if_t<::trompeloeil::is_matcher<M>::value>>
  2917. inline
  2918. ::trompeloeil::neg_matcher<std::decay_t<M>>
  2919. operator!(
  2920. M&& m)
  2921. {
  2922. return ::trompeloeil::neg_matcher<std::decay_t<M>>{std::forward<M>(m)};
  2923. }
  2924. /*
  2925. * Convert the signature S of a mock function to the signature of
  2926. * a member function of class T that takes the same parameters P
  2927. * but returns R.
  2928. *
  2929. * The member function has the same constness as the mock function.
  2930. */
  2931. template <typename T, typename R, typename S>
  2932. struct signature_to_member_function;
  2933. template <typename T, typename R, typename R_of_S, typename... P>
  2934. struct signature_to_member_function<T, R, R_of_S(P...)>
  2935. {
  2936. using type = std::conditional_t<
  2937. std::is_const<T>::value,
  2938. R (T::*)(P...) const,
  2939. R (T::*)(P...)>;
  2940. };
  2941. }
  2942. #define TROMPELOEIL_LINE_ID(name) \
  2943. TROMPELOEIL_CONCAT(trompeloeil_l_ ## name ## _, __LINE__)
  2944. #define TROMPELOEIL_COUNT_ID(name) \
  2945. TROMPELOEIL_CONCAT(trompeloeil_c_ ## name ## _, __COUNTER__)
  2946. #ifdef _MSC_VER
  2947. #define TROMPELOEIL_MAKE_MOCK0(name, sig, ...) \
  2948. TROMPELOEIL_MAKE_MOCK_(name,,0, sig, __VA_ARGS__,,)
  2949. #define TROMPELOEIL_MAKE_MOCK1(name, sig, ...) \
  2950. TROMPELOEIL_MAKE_MOCK_(name,,1, sig, __VA_ARGS__,,)
  2951. #define TROMPELOEIL_MAKE_MOCK2(name, sig, ...) \
  2952. TROMPELOEIL_MAKE_MOCK_(name,,2, sig, __VA_ARGS__,,)
  2953. #define TROMPELOEIL_MAKE_MOCK3(name, sig, ...) \
  2954. TROMPELOEIL_MAKE_MOCK_(name,,3, sig, __VA_ARGS__,,)
  2955. #define TROMPELOEIL_MAKE_MOCK4(name, sig, ...) \
  2956. TROMPELOEIL_MAKE_MOCK_(name,,4, sig, __VA_ARGS__,,)
  2957. #define TROMPELOEIL_MAKE_MOCK5(name, sig, ...) \
  2958. TROMPELOEIL_MAKE_MOCK_(name,,5, sig, __VA_ARGS__,,)
  2959. #define TROMPELOEIL_MAKE_MOCK6(name, sig, ...) \
  2960. TROMPELOEIL_MAKE_MOCK_(name,,6, sig, __VA_ARGS__,,)
  2961. #define TROMPELOEIL_MAKE_MOCK7(name, sig, ...) \
  2962. TROMPELOEIL_MAKE_MOCK_(name,,7, sig, __VA_ARGS__,,)
  2963. #define TROMPELOEIL_MAKE_MOCK8(name, sig, ...) \
  2964. TROMPELOEIL_MAKE_MOCK_(name,,8, sig, __VA_ARGS__,,)
  2965. #define TROMPELOEIL_MAKE_MOCK9(name, sig, ...) \
  2966. TROMPELOEIL_MAKE_MOCK_(name,,9, sig, __VA_ARGS__,,)
  2967. #define TROMPELOEIL_MAKE_MOCK10(name, sig, ...) \
  2968. TROMPELOEIL_MAKE_MOCK_(name,,10, sig, __VA_ARGS__,,)
  2969. #define TROMPELOEIL_MAKE_MOCK11(name, sig, ...) \
  2970. TROMPELOEIL_MAKE_MOCK_(name,,11, sig, __VA_ARGS__,,)
  2971. #define TROMPELOEIL_MAKE_MOCK12(name, sig, ...) \
  2972. TROMPELOEIL_MAKE_MOCK_(name,,12, sig, __VA_ARGS__,,)
  2973. #define TROMPELOEIL_MAKE_MOCK13(name, sig, ...) \
  2974. TROMPELOEIL_MAKE_MOCK_(name,,13, sig, __VA_ARGS__,,)
  2975. #define TROMPELOEIL_MAKE_MOCK14(name, sig, ...) \
  2976. TROMPELOEIL_MAKE_MOCK_(name,,14, sig, __VA_ARGS__,,)
  2977. #define TROMPELOEIL_MAKE_MOCK15(name, sig, ...) \
  2978. TROMPELOEIL_MAKE_MOCK_(name,,15, sig, __VA_ARGS__,,)
  2979. #define TROMPELOEIL_MAKE_CONST_MOCK0(name, sig, ...) \
  2980. TROMPELOEIL_MAKE_MOCK_(name,const,0, sig, __VA_ARGS__,,)
  2981. #define TROMPELOEIL_MAKE_CONST_MOCK1(name, sig, ...) \
  2982. TROMPELOEIL_MAKE_MOCK_(name,const,1, sig, __VA_ARGS__,,)
  2983. #define TROMPELOEIL_MAKE_CONST_MOCK2(name, sig, ...) \
  2984. TROMPELOEIL_MAKE_MOCK_(name,const,2, sig, __VA_ARGS__,,)
  2985. #define TROMPELOEIL_MAKE_CONST_MOCK3(name, sig, ...) \
  2986. TROMPELOEIL_MAKE_MOCK_(name,const,3, sig, __VA_ARGS__,,)
  2987. #define TROMPELOEIL_MAKE_CONST_MOCK4(name, sig, ...) \
  2988. TROMPELOEIL_MAKE_MOCK_(name,const,4, sig, __VA_ARGS__,,)
  2989. #define TROMPELOEIL_MAKE_CONST_MOCK5(name, sig, ...) \
  2990. TROMPELOEIL_MAKE_MOCK_(name,const,5, sig, __VA_ARGS__,,)
  2991. #define TROMPELOEIL_MAKE_CONST_MOCK6(name, sig, ...) \
  2992. TROMPELOEIL_MAKE_MOCK_(name,const,6, sig, __VA_ARGS__,,)
  2993. #define TROMPELOEIL_MAKE_CONST_MOCK7(name, sig, ...) \
  2994. TROMPELOEIL_MAKE_MOCK_(name,const,7, sig, __VA_ARGS__,,)
  2995. #define TROMPELOEIL_MAKE_CONST_MOCK8(name, sig, ...) \
  2996. TROMPELOEIL_MAKE_MOCK_(name,const,8, sig, __VA_ARGS__,,)
  2997. #define TROMPELOEIL_MAKE_CONST_MOCK9(name, sig, ...) \
  2998. TROMPELOEIL_MAKE_MOCK_(name,const,9, sig, __VA_ARGS__,,)
  2999. #define TROMPELOEIL_MAKE_CONST_MOCK10(name, sig, ...) \
  3000. TROMPELOEIL_MAKE_MOCK_(name,const,10, sig, __VA_ARGS__,,)
  3001. #define TROMPELOEIL_MAKE_CONST_MOCK11(name, sig, ...) \
  3002. TROMPELOEIL_MAKE_MOCK_(name,const,11, sig, __VA_ARGS__,,)
  3003. #define TROMPELOEIL_MAKE_CONST_MOCK12(name, sig, ...) \
  3004. TROMPELOEIL_MAKE_MOCK_(name,const,12, sig, __VA_ARGS__,,)
  3005. #define TROMPELOEIL_MAKE_CONST_MOCK13(name, sig, ...) \
  3006. TROMPELOEIL_MAKE_MOCK_(name,const,13, sig, __VA_ARGS__,,)
  3007. #define TROMPELOEIL_MAKE_CONST_MOCK14(name, sig, ...) \
  3008. TROMPELOEIL_MAKE_MOCK_(name,const,14, sig, __VA_ARGS__,,)
  3009. #define TROMPELOEIL_MAKE_CONST_MOCK15(name, sig, ...) \
  3010. TROMPELOEIL_MAKE_MOCK_(name,const,15, sig, __VA_ARGS__,,)
  3011. #else
  3012. // sane standards compliant preprocessor
  3013. #define TROMPELOEIL_MAKE_MOCK0(name, ...) \
  3014. TROMPELOEIL_MAKE_MOCK_(name,,0, __VA_ARGS__,,)
  3015. #define TROMPELOEIL_MAKE_MOCK1(name, ...) \
  3016. TROMPELOEIL_MAKE_MOCK_(name,,1, __VA_ARGS__,,)
  3017. #define TROMPELOEIL_MAKE_MOCK2(name, ...) \
  3018. TROMPELOEIL_MAKE_MOCK_(name,,2, __VA_ARGS__,,)
  3019. #define TROMPELOEIL_MAKE_MOCK3(name, ...) \
  3020. TROMPELOEIL_MAKE_MOCK_(name,,3, __VA_ARGS__,,)
  3021. #define TROMPELOEIL_MAKE_MOCK4(name, ...) \
  3022. TROMPELOEIL_MAKE_MOCK_(name,,4, __VA_ARGS__,,)
  3023. #define TROMPELOEIL_MAKE_MOCK5(name, ...) \
  3024. TROMPELOEIL_MAKE_MOCK_(name,,5, __VA_ARGS__,,)
  3025. #define TROMPELOEIL_MAKE_MOCK6(name, ...) \
  3026. TROMPELOEIL_MAKE_MOCK_(name,,6, __VA_ARGS__,,)
  3027. #define TROMPELOEIL_MAKE_MOCK7(name, ...) \
  3028. TROMPELOEIL_MAKE_MOCK_(name,,7, __VA_ARGS__,,)
  3029. #define TROMPELOEIL_MAKE_MOCK8(name, ...) \
  3030. TROMPELOEIL_MAKE_MOCK_(name,,8, __VA_ARGS__,,)
  3031. #define TROMPELOEIL_MAKE_MOCK9(name, ...) \
  3032. TROMPELOEIL_MAKE_MOCK_(name,,9, __VA_ARGS__,,)
  3033. #define TROMPELOEIL_MAKE_MOCK10(name, ...) \
  3034. TROMPELOEIL_MAKE_MOCK_(name,,10, __VA_ARGS__,,)
  3035. #define TROMPELOEIL_MAKE_MOCK11(name, ...) \
  3036. TROMPELOEIL_MAKE_MOCK_(name,,11, __VA_ARGS__,,)
  3037. #define TROMPELOEIL_MAKE_MOCK12(name, ...) \
  3038. TROMPELOEIL_MAKE_MOCK_(name,,12, __VA_ARGS__,,)
  3039. #define TROMPELOEIL_MAKE_MOCK13(name, ...) \
  3040. TROMPELOEIL_MAKE_MOCK_(name,,13, __VA_ARGS__,,)
  3041. #define TROMPELOEIL_MAKE_MOCK14(name, ...) \
  3042. TROMPELOEIL_MAKE_MOCK_(name,,14,__VA_ARGS__,,)
  3043. #define TROMPELOEIL_MAKE_MOCK15(name, ...) \
  3044. TROMPELOEIL_MAKE_MOCK_(name,,15, __VA_ARGS__,,)
  3045. #define TROMPELOEIL_MAKE_CONST_MOCK0(name, ...) \
  3046. TROMPELOEIL_MAKE_MOCK_(name,const,0, __VA_ARGS__,,)
  3047. #define TROMPELOEIL_MAKE_CONST_MOCK1(name, ...) \
  3048. TROMPELOEIL_MAKE_MOCK_(name,const,1, __VA_ARGS__,,)
  3049. #define TROMPELOEIL_MAKE_CONST_MOCK2(name, ...) \
  3050. TROMPELOEIL_MAKE_MOCK_(name,const,2, __VA_ARGS__,,)
  3051. #define TROMPELOEIL_MAKE_CONST_MOCK3(name, ...) \
  3052. TROMPELOEIL_MAKE_MOCK_(name,const,3, __VA_ARGS__,,)
  3053. #define TROMPELOEIL_MAKE_CONST_MOCK4(name, ...) \
  3054. TROMPELOEIL_MAKE_MOCK_(name,const,4, __VA_ARGS__,,)
  3055. #define TROMPELOEIL_MAKE_CONST_MOCK5(name, ...) \
  3056. TROMPELOEIL_MAKE_MOCK_(name,const,5, __VA_ARGS__,,)
  3057. #define TROMPELOEIL_MAKE_CONST_MOCK6(name, ...) \
  3058. TROMPELOEIL_MAKE_MOCK_(name,const,6, __VA_ARGS__,,)
  3059. #define TROMPELOEIL_MAKE_CONST_MOCK7(name, ...) \
  3060. TROMPELOEIL_MAKE_MOCK_(name,const,7, __VA_ARGS__,,)
  3061. #define TROMPELOEIL_MAKE_CONST_MOCK8(name, ...) \
  3062. TROMPELOEIL_MAKE_MOCK_(name,const,8, __VA_ARGS__,,)
  3063. #define TROMPELOEIL_MAKE_CONST_MOCK9(name, ...) \
  3064. TROMPELOEIL_MAKE_MOCK_(name,const,9, __VA_ARGS__,,)
  3065. #define TROMPELOEIL_MAKE_CONST_MOCK10(name, ...) \
  3066. TROMPELOEIL_MAKE_MOCK_(name,const,10, __VA_ARGS__,,)
  3067. #define TROMPELOEIL_MAKE_CONST_MOCK11(name, ...) \
  3068. TROMPELOEIL_MAKE_MOCK_(name,const,11, __VA_ARGS__,,)
  3069. #define TROMPELOEIL_MAKE_CONST_MOCK12(name, ...) \
  3070. TROMPELOEIL_MAKE_MOCK_(name,const,12, __VA_ARGS__,,)
  3071. #define TROMPELOEIL_MAKE_CONST_MOCK13(name, ...) \
  3072. TROMPELOEIL_MAKE_MOCK_(name,const,13, __VA_ARGS__,,)
  3073. #define TROMPELOEIL_MAKE_CONST_MOCK14(name, ...) \
  3074. TROMPELOEIL_MAKE_MOCK_(name,const,14, __VA_ARGS__,,)
  3075. #define TROMPELOEIL_MAKE_CONST_MOCK15(name, ...) \
  3076. TROMPELOEIL_MAKE_MOCK_(name,const,15, __VA_ARGS__,,)
  3077. #endif
  3078. #define TROMPELOEIL_MAKE_MOCK_(name, constness, num, sig, spec, ...) \
  3079. using TROMPELOEIL_LINE_ID(cardinality_match) = \
  3080. std::integral_constant<bool, num == ::trompeloeil::param_list<sig>::size>; \
  3081. static_assert(TROMPELOEIL_LINE_ID(cardinality_match)::value, \
  3082. "Function signature does not have " #num " parameters"); \
  3083. using TROMPELOEIL_LINE_ID(matcher_list_t) = ::trompeloeil::call_matcher_list<sig>;\
  3084. using TROMPELOEIL_LINE_ID(expectation_list_t) = ::trompeloeil::expectations<sig>; \
  3085. struct TROMPELOEIL_LINE_ID(tag_type_trompeloeil) \
  3086. { \
  3087. const char* trompeloeil_expectation_file; \
  3088. unsigned long trompeloeil_expectation_line; \
  3089. const char *trompeloeil_expectation_string; \
  3090. \
  3091. template <typename ... trompeloeil_param_type> \
  3092. auto name( \
  3093. trompeloeil_param_type&& ... trompeloeil_param) \
  3094. -> ::trompeloeil::modifier_t<sig, \
  3095. TROMPELOEIL_LINE_ID(tag_type_trompeloeil), \
  3096. trompeloeil_param_type...> \
  3097. { \
  3098. using matcher = ::trompeloeil::call_matcher< \
  3099. sig, \
  3100. ::trompeloeil::param_t<trompeloeil_param_type...>>; \
  3101. return { \
  3102. new matcher { \
  3103. trompeloeil_expectation_file, \
  3104. trompeloeil_expectation_line, \
  3105. trompeloeil_expectation_string, \
  3106. std::forward<trompeloeil_param_type>(trompeloeil_param)... \
  3107. } \
  3108. }; \
  3109. } \
  3110. }; \
  3111. \
  3112. TROMPELOEIL_LINE_ID(matcher_list_t)& \
  3113. trompeloeil_matcher_list( \
  3114. TROMPELOEIL_LINE_ID(tag_type_trompeloeil)*) \
  3115. constness \
  3116. noexcept \
  3117. { \
  3118. return TROMPELOEIL_LINE_ID(expectations).active; \
  3119. } \
  3120. \
  3121. ::trompeloeil::return_of_t<sig> \
  3122. name( \
  3123. TROMPELOEIL_PARAM_LIST(num, sig)) \
  3124. constness \
  3125. spec \
  3126. { \
  3127. /* Use the auxiliary functions to avoid unneeded-member-function warning */\
  3128. using T_ ## name = typename std::remove_reference<decltype(*this)>::type; \
  3129. \
  3130. using pmf_s_t = typename ::trompeloeil::signature_to_member_function< \
  3131. T_ ## name, decltype(*this), sig>::type; \
  3132. \
  3133. using pmf_e_t = typename ::trompeloeil::signature_to_member_function< \
  3134. T_ ## name, TROMPELOEIL_LINE_ID(tag_type_trompeloeil), sig>::type; \
  3135. \
  3136. auto s_ptr = static_cast<pmf_s_t>(&T_ ## name::trompeloeil_self_ ## name); \
  3137. auto e_ptr = static_cast<pmf_e_t>(&T_ ## name::trompeloeil_tag_ ## name); \
  3138. \
  3139. ::trompeloeil::ignore(s_ptr, e_ptr); \
  3140. \
  3141. return ::trompeloeil::mock_func<sig>(TROMPELOEIL_LINE_ID(cardinality_match){}, \
  3142. TROMPELOEIL_LINE_ID(expectations), \
  3143. #name, \
  3144. #sig \
  3145. TROMPELOEIL_PARAMS(num)); \
  3146. } \
  3147. \
  3148. auto \
  3149. trompeloeil_self_ ## name(TROMPELOEIL_PARAM_LIST(num, sig)) constness \
  3150. -> decltype(*this) \
  3151. { \
  3152. ::trompeloeil::ignore(#name TROMPELOEIL_PARAMS(num)); \
  3153. return *this; \
  3154. } \
  3155. \
  3156. TROMPELOEIL_LINE_ID(tag_type_trompeloeil) \
  3157. trompeloeil_tag_ ## name(TROMPELOEIL_PARAM_LIST(num, sig)) constness \
  3158. { \
  3159. ::trompeloeil::ignore(#name TROMPELOEIL_PARAMS(num)); \
  3160. return {nullptr, 0ul, nullptr}; \
  3161. } \
  3162. \
  3163. mutable TROMPELOEIL_LINE_ID(expectation_list_t) TROMPELOEIL_LINE_ID(expectations)
  3164. #define TROMPELOEIL_REQUIRE_CALL(obj, func) \
  3165. TROMPELOEIL_REQUIRE_CALL_(obj, func, #obj, #func)
  3166. #define TROMPELOEIL_REQUIRE_CALL_(obj, func, obj_s, func_s) \
  3167. auto TROMPELOEIL_COUNT_ID(call_obj) = TROMPELOEIL_REQUIRE_CALL_OBJ(obj, func,\
  3168. obj_s, func_s)
  3169. #define TROMPELOEIL_NAMED_REQUIRE_CALL(obj, func) \
  3170. TROMPELOEIL_NAMED_REQUIRE_CALL_(obj, func, #obj, #func)
  3171. #define TROMPELOEIL_NAMED_REQUIRE_CALL_(obj, func, obj_s, func_s) \
  3172. TROMPELOEIL_REQUIRE_CALL_OBJ(obj, func, obj_s, func_s)
  3173. #define TROMPELOEIL_REQUIRE_CALL_OBJ(obj, func, obj_s, func_s) \
  3174. ::trompeloeil::call_validator_t<decltype((obj).TROMPELOEIL_CONCAT(trompeloeil_self_, func))>{(obj)} + \
  3175. std::conditional_t<false, \
  3176. decltype((obj).func), \
  3177. decltype((obj).TROMPELOEIL_CONCAT(trompeloeil_tag_,func))>\
  3178. {__FILE__, static_cast<unsigned long>(__LINE__), obj_s "." func_s}.func
  3179. #define TROMPELOEIL_ALLOW_CALL(obj, func) \
  3180. TROMPELOEIL_ALLOW_CALL_(obj, func, #obj, #func)
  3181. #define TROMPELOEIL_ALLOW_CALL_(obj, func, obj_s, func_s) \
  3182. TROMPELOEIL_REQUIRE_CALL_(obj, func, obj_s, func_s) \
  3183. .TROMPELOEIL_TIMES(0, ~0ULL)
  3184. #define TROMPELOEIL_NAMED_ALLOW_CALL(obj, func) \
  3185. TROMPELOEIL_NAMED_ALLOW_CALL_(obj, func, #obj, #func)
  3186. #define TROMPELOEIL_NAMED_ALLOW_CALL_(obj, func, obj_s, func_s) \
  3187. TROMPELOEIL_NAMED_REQUIRE_CALL_(obj, func, obj_s, func_s) \
  3188. .TROMPELOEIL_TIMES(0, ~0ULL)
  3189. #define TROMPELOEIL_FORBID_CALL(obj, func) \
  3190. TROMPELOEIL_FORBID_CALL_(obj, func, #obj, #func)
  3191. #define TROMPELOEIL_FORBID_CALL_(obj, func, obj_s, func_s) \
  3192. TROMPELOEIL_REQUIRE_CALL_(obj, func, obj_s, func_s) \
  3193. .TROMPELOEIL_TIMES(0)
  3194. #define TROMPELOEIL_NAMED_FORBID_CALL(obj, func) \
  3195. TROMPELOEIL_NAMED_FORBID_CALL_(obj, func, #obj, #func)
  3196. #define TROMPELOEIL_NAMED_FORBID_CALL_(obj, func, obj_s, func_s) \
  3197. TROMPELOEIL_NAMED_REQUIRE_CALL_(obj, func, obj_s, func_s) \
  3198. .TROMPELOEIL_TIMES(0)
  3199. #define TROMPELOEIL_WITH(...) TROMPELOEIL_WITH_(=,#__VA_ARGS__, __VA_ARGS__)
  3200. #define TROMPELOEIL_LR_WITH(...) TROMPELOEIL_WITH_(&,#__VA_ARGS__, __VA_ARGS__)
  3201. #define TROMPELOEIL_WITH_(capture, arg_s, ...) \
  3202. with(arg_s, [capture](auto const& trompeloeil_x) { \
  3203. auto& _1 = ::trompeloeil::mkarg<1>(trompeloeil_x); \
  3204. auto& _2 = ::trompeloeil::mkarg<2>(trompeloeil_x); \
  3205. auto& _3 = ::trompeloeil::mkarg<3>(trompeloeil_x); \
  3206. auto& _4 = ::trompeloeil::mkarg<4>(trompeloeil_x); \
  3207. auto& _5 = ::trompeloeil::mkarg<5>(trompeloeil_x); \
  3208. auto& _6 = ::trompeloeil::mkarg<6>(trompeloeil_x); \
  3209. auto& _7 = ::trompeloeil::mkarg<7>(trompeloeil_x); \
  3210. auto& _8 = ::trompeloeil::mkarg<8>(trompeloeil_x); \
  3211. auto& _9 = ::trompeloeil::mkarg<9>(trompeloeil_x); \
  3212. auto&_10 = ::trompeloeil::mkarg<10>(trompeloeil_x); \
  3213. auto&_11 = ::trompeloeil::mkarg<11>(trompeloeil_x); \
  3214. auto&_12 = ::trompeloeil::mkarg<12>(trompeloeil_x); \
  3215. auto&_13 = ::trompeloeil::mkarg<13>(trompeloeil_x); \
  3216. auto&_14 = ::trompeloeil::mkarg<14>(trompeloeil_x); \
  3217. auto&_15 = ::trompeloeil::mkarg<15>(trompeloeil_x); \
  3218. ::trompeloeil::ignore(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15); \
  3219. return __VA_ARGS__; \
  3220. })
  3221. #define TROMPELOEIL_SIDE_EFFECT(...) TROMPELOEIL_SIDE_EFFECT_(=, __VA_ARGS__)
  3222. #define TROMPELOEIL_LR_SIDE_EFFECT(...) TROMPELOEIL_SIDE_EFFECT_(&, __VA_ARGS__)
  3223. #define TROMPELOEIL_SIDE_EFFECT_(capture, ...) \
  3224. sideeffect([capture](auto& trompeloeil_x) { \
  3225. auto& _1 = ::trompeloeil::mkarg<1>(trompeloeil_x); \
  3226. auto& _2 = ::trompeloeil::mkarg<2>(trompeloeil_x); \
  3227. auto& _3 = ::trompeloeil::mkarg<3>(trompeloeil_x); \
  3228. auto& _4 = ::trompeloeil::mkarg<4>(trompeloeil_x); \
  3229. auto& _5 = ::trompeloeil::mkarg<5>(trompeloeil_x); \
  3230. auto& _6 = ::trompeloeil::mkarg<6>(trompeloeil_x); \
  3231. auto& _7 = ::trompeloeil::mkarg<7>(trompeloeil_x); \
  3232. auto& _8 = ::trompeloeil::mkarg<8>(trompeloeil_x); \
  3233. auto& _9 = ::trompeloeil::mkarg<9>(trompeloeil_x); \
  3234. auto&_10 = ::trompeloeil::mkarg<10>(trompeloeil_x); \
  3235. auto&_11 = ::trompeloeil::mkarg<11>(trompeloeil_x); \
  3236. auto&_12 = ::trompeloeil::mkarg<12>(trompeloeil_x); \
  3237. auto&_13 = ::trompeloeil::mkarg<13>(trompeloeil_x); \
  3238. auto&_14 = ::trompeloeil::mkarg<14>(trompeloeil_x); \
  3239. auto&_15 = ::trompeloeil::mkarg<15>(trompeloeil_x); \
  3240. ::trompeloeil::ignore(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15); \
  3241. __VA_ARGS__; \
  3242. })
  3243. #define TROMPELOEIL_RETURN(...) TROMPELOEIL_RETURN_(=, __VA_ARGS__)
  3244. #define TROMPELOEIL_LR_RETURN(...) TROMPELOEIL_RETURN_(&, __VA_ARGS__)
  3245. #define TROMPELOEIL_RETURN_(capture, ...) \
  3246. handle_return([capture](auto& trompeloeil_x) -> decltype(auto) { \
  3247. auto& _1 = ::trompeloeil::mkarg<1>(trompeloeil_x); \
  3248. auto& _2 = ::trompeloeil::mkarg<2>(trompeloeil_x); \
  3249. auto& _3 = ::trompeloeil::mkarg<3>(trompeloeil_x); \
  3250. auto& _4 = ::trompeloeil::mkarg<4>(trompeloeil_x); \
  3251. auto& _5 = ::trompeloeil::mkarg<5>(trompeloeil_x); \
  3252. auto& _6 = ::trompeloeil::mkarg<6>(trompeloeil_x); \
  3253. auto& _7 = ::trompeloeil::mkarg<7>(trompeloeil_x); \
  3254. auto& _8 = ::trompeloeil::mkarg<8>(trompeloeil_x); \
  3255. auto& _9 = ::trompeloeil::mkarg<9>(trompeloeil_x); \
  3256. auto&_10 = ::trompeloeil::mkarg<10>(trompeloeil_x); \
  3257. auto&_11 = ::trompeloeil::mkarg<11>(trompeloeil_x); \
  3258. auto&_12 = ::trompeloeil::mkarg<12>(trompeloeil_x); \
  3259. auto&_13 = ::trompeloeil::mkarg<13>(trompeloeil_x); \
  3260. auto&_14 = ::trompeloeil::mkarg<14>(trompeloeil_x); \
  3261. auto&_15 = ::trompeloeil::mkarg<15>(trompeloeil_x); \
  3262. ::trompeloeil::ignore(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15); \
  3263. return ::trompeloeil::decay_return_type(__VA_ARGS__); \
  3264. })
  3265. #define TROMPELOEIL_THROW(...) TROMPELOEIL_THROW_(=, __VA_ARGS__)
  3266. #define TROMPELOEIL_LR_THROW(...) TROMPELOEIL_THROW_(&, __VA_ARGS__)
  3267. #define TROMPELOEIL_THROW_(capture, ...) \
  3268. handle_throw([capture](auto& trompeloeil_x) { \
  3269. auto& _1 = ::trompeloeil::mkarg<1>(trompeloeil_x); \
  3270. auto& _2 = ::trompeloeil::mkarg<2>(trompeloeil_x); \
  3271. auto& _3 = ::trompeloeil::mkarg<3>(trompeloeil_x); \
  3272. auto& _4 = ::trompeloeil::mkarg<4>(trompeloeil_x); \
  3273. auto& _5 = ::trompeloeil::mkarg<5>(trompeloeil_x); \
  3274. auto& _6 = ::trompeloeil::mkarg<6>(trompeloeil_x); \
  3275. auto& _7 = ::trompeloeil::mkarg<7>(trompeloeil_x); \
  3276. auto& _8 = ::trompeloeil::mkarg<8>(trompeloeil_x); \
  3277. auto& _9 = ::trompeloeil::mkarg<9>(trompeloeil_x); \
  3278. auto&_10 = ::trompeloeil::mkarg<10>(trompeloeil_x); \
  3279. auto&_11 = ::trompeloeil::mkarg<11>(trompeloeil_x); \
  3280. auto&_12 = ::trompeloeil::mkarg<12>(trompeloeil_x); \
  3281. auto&_13 = ::trompeloeil::mkarg<13>(trompeloeil_x); \
  3282. auto&_14 = ::trompeloeil::mkarg<14>(trompeloeil_x); \
  3283. auto&_15 = ::trompeloeil::mkarg<15>(trompeloeil_x); \
  3284. ::trompeloeil::ignore(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15); \
  3285. throw __VA_ARGS__; \
  3286. })
  3287. #define TROMPELOEIL_TIMES(...) times(::trompeloeil::multiplicity<__VA_ARGS__>{})
  3288. #define TROMPELOEIL_IN_SEQUENCE(...) \
  3289. in_sequence(TROMPELOEIL_INIT_WITH_STR(::trompeloeil::sequence_matcher::init_type, __VA_ARGS__))
  3290. #define TROMPELOEIL_ANY(type) ::trompeloeil::any_matcher<type>(#type)
  3291. #define TROMPELOEIL_AT_LEAST(num) num, ~0ULL
  3292. #define TROMPELOEIL_AT_MOST(num) 0, num
  3293. #define TROMPELOEIL_REQUIRE_DESTRUCTION(obj) \
  3294. TROMPELOEIL_REQUIRE_DESTRUCTION_(obj, #obj)
  3295. #define TROMPELOEIL_REQUIRE_DESTRUCTION_(obj, obj_s) \
  3296. std::unique_ptr<trompeloeil::expectation> \
  3297. TROMPELOEIL_CONCAT(trompeloeil_death_monitor_, __LINE__) \
  3298. = TROMPELOEIL_NAMED_REQUIRE_DESTRUCTION_(,obj, obj_s)
  3299. #define TROMPELOEIL_NAMED_REQUIRE_DESTRUCTION(obj) \
  3300. TROMPELOEIL_NAMED_REQUIRE_DESTRUCTION_("NAMED_", obj, #obj)
  3301. #define TROMPELOEIL_NAMED_REQUIRE_DESTRUCTION_(prefix, obj, obj_s) \
  3302. trompeloeil::lifetime_monitor_releaser{} + \
  3303. trompeloeil::lifetime_monitor_modifier<false>{ \
  3304. std::make_unique<trompeloeil::lifetime_monitor>( \
  3305. obj, \
  3306. obj_s, \
  3307. prefix "REQUIRE_DESTRUCTION(" obj_s ")", \
  3308. "destructor for " obj_s, \
  3309. ::trompeloeil::location{__FILE__, \
  3310. static_cast<unsigned long>(__LINE__)}) \
  3311. }
  3312. #ifndef TROMPELOEIL_LONG_MACROS
  3313. #define MAKE_MOCK0 TROMPELOEIL_MAKE_MOCK0
  3314. #define MAKE_MOCK1 TROMPELOEIL_MAKE_MOCK1
  3315. #define MAKE_MOCK2 TROMPELOEIL_MAKE_MOCK2
  3316. #define MAKE_MOCK3 TROMPELOEIL_MAKE_MOCK3
  3317. #define MAKE_MOCK4 TROMPELOEIL_MAKE_MOCK4
  3318. #define MAKE_MOCK5 TROMPELOEIL_MAKE_MOCK5
  3319. #define MAKE_MOCK6 TROMPELOEIL_MAKE_MOCK6
  3320. #define MAKE_MOCK7 TROMPELOEIL_MAKE_MOCK7
  3321. #define MAKE_MOCK8 TROMPELOEIL_MAKE_MOCK8
  3322. #define MAKE_MOCK9 TROMPELOEIL_MAKE_MOCK9
  3323. #define MAKE_MOCK10 TROMPELOEIL_MAKE_MOCK10
  3324. #define MAKE_MOCK11 TROMPELOEIL_MAKE_MOCK11
  3325. #define MAKE_MOCK12 TROMPELOEIL_MAKE_MOCK12
  3326. #define MAKE_MOCK13 TROMPELOEIL_MAKE_MOCK13
  3327. #define MAKE_MOCK14 TROMPELOEIL_MAKE_MOCK14
  3328. #define MAKE_MOCK15 TROMPELOEIL_MAKE_MOCK15
  3329. #define MAKE_CONST_MOCK0 TROMPELOEIL_MAKE_CONST_MOCK0
  3330. #define MAKE_CONST_MOCK1 TROMPELOEIL_MAKE_CONST_MOCK1
  3331. #define MAKE_CONST_MOCK2 TROMPELOEIL_MAKE_CONST_MOCK2
  3332. #define MAKE_CONST_MOCK3 TROMPELOEIL_MAKE_CONST_MOCK3
  3333. #define MAKE_CONST_MOCK4 TROMPELOEIL_MAKE_CONST_MOCK4
  3334. #define MAKE_CONST_MOCK5 TROMPELOEIL_MAKE_CONST_MOCK5
  3335. #define MAKE_CONST_MOCK6 TROMPELOEIL_MAKE_CONST_MOCK6
  3336. #define MAKE_CONST_MOCK7 TROMPELOEIL_MAKE_CONST_MOCK7
  3337. #define MAKE_CONST_MOCK8 TROMPELOEIL_MAKE_CONST_MOCK8
  3338. #define MAKE_CONST_MOCK9 TROMPELOEIL_MAKE_CONST_MOCK9
  3339. #define MAKE_CONST_MOCK10 TROMPELOEIL_MAKE_CONST_MOCK10
  3340. #define MAKE_CONST_MOCK11 TROMPELOEIL_MAKE_CONST_MOCK11
  3341. #define MAKE_CONST_MOCK12 TROMPELOEIL_MAKE_CONST_MOCK12
  3342. #define MAKE_CONST_MOCK13 TROMPELOEIL_MAKE_CONST_MOCK13
  3343. #define MAKE_CONST_MOCK14 TROMPELOEIL_MAKE_CONST_MOCK14
  3344. #define MAKE_CONST_MOCK15 TROMPELOEIL_MAKE_CONST_MOCK15
  3345. #define REQUIRE_CALL TROMPELOEIL_REQUIRE_CALL
  3346. #define NAMED_REQUIRE_CALL TROMPELOEIL_NAMED_REQUIRE_CALL
  3347. #define ALLOW_CALL TROMPELOEIL_ALLOW_CALL
  3348. #define NAMED_ALLOW_CALL TROMPELOEIL_NAMED_ALLOW_CALL
  3349. #define FORBID_CALL TROMPELOEIL_FORBID_CALL
  3350. #define NAMED_FORBID_CALL TROMPELOEIL_NAMED_FORBID_CALL
  3351. #define WITH TROMPELOEIL_WITH
  3352. #define LR_WITH TROMPELOEIL_LR_WITH
  3353. #define SIDE_EFFECT TROMPELOEIL_SIDE_EFFECT
  3354. #define LR_SIDE_EFFECT TROMPELOEIL_LR_SIDE_EFFECT
  3355. #define RETURN TROMPELOEIL_RETURN
  3356. #define LR_RETURN TROMPELOEIL_LR_RETURN
  3357. #define THROW TROMPELOEIL_THROW
  3358. #define LR_THROW TROMPELOEIL_LR_THROW
  3359. #define TIMES TROMPELOEIL_TIMES
  3360. #define IN_SEQUENCE TROMPELOEIL_IN_SEQUENCE
  3361. #define ANY TROMPELOEIL_ANY
  3362. #define AT_LEAST TROMPELOEIL_AT_LEAST
  3363. #define AT_MOST TROMPELOEIL_AT_MOST
  3364. #define REQUIRE_DESTRUCTION TROMPELOEIL_REQUIRE_DESTRUCTION
  3365. #define NAMED_REQUIRE_DESTRUCTION TROMPELOEIL_NAMED_REQUIRE_DESTRUCTION
  3366. #endif // TROMPELOEIL_LONG_MACROS
  3367. #endif // include guard