trompeloeil

FORK: Header only C++14 mocking framework
git clone https://git.neptards.moe/u3shit/trompeloeil.git
Log | Files | Refs | README

thread_terror.cpp (2257B)


      1 #include <trompeloeil.hpp>
      2 #include <iterator>
      3 #include <thread>
      4 #include <atomic>
      5 #include <iostream>
      6 #include <cassert>
      7 
      8 class C
      9 {
     10 public:
     11   MAKE_MOCK0(func, int(void));
     12   std::unique_ptr<trompeloeil::expectation> allow;
     13 };
     14 
     15 static std::mutex ptr_mutex;
     16 inline auto get_lock()
     17 {
     18   return std::unique_lock<std::mutex>{ ptr_mutex };
     19 }
     20 
     21 static std::shared_ptr<C> obj;
     22 
     23 inline std::shared_ptr<C> get_obj()
     24 {
     25   auto lock = get_lock();
     26   return obj;
     27 }
     28 
     29 static std::atomic<std::size_t> call_count[7];
     30 static std::atomic<std::size_t> ret_count[7];
     31 
     32 static void init_obj()
     33 {
     34   auto m = std::make_shared<C>();
     35   m->allow = NAMED_ALLOW_CALL(*m, func())
     36     .SIDE_EFFECT(++call_count[0])
     37     .RETURN(0);
     38   auto lock = get_lock();
     39   obj = m;
     40 }
     41 
     42 static void make(size_t count)
     43 {
     44   while (count--)
     45   {
     46     init_obj();
     47   }
     48 }
     49 
     50 static void call(size_t count)
     51 {
     52   while (count--)
     53   {
     54     if (auto m = get_obj())
     55     {
     56       ret_count[m->func()]++;
     57     }
     58   }
     59 }
     60 
     61 static void allow(size_t count, int id)
     62 {
     63   std::unique_ptr<trompeloeil::expectation> exp;
     64   while (count--)
     65   {
     66     if (auto m = get_obj())
     67     {
     68       exp = NAMED_ALLOW_CALL(*m, func())
     69         .SIDE_EFFECT(++call_count[id])
     70         .RETURN(id);
     71       assert(exp->is_satisfied());
     72       assert(!exp->is_saturated());
     73     }
     74   }
     75 }
     76 
     77 int main()
     78 {
     79   trompeloeil::set_reporter([](auto , auto , auto,  auto&)
     80     {
     81       abort();
     82     });
     83   init_obj();
     84 
     85   size_t count = 100000;
     86   std::vector<std::thread> allowers;
     87   std::vector<std::thread> callers;
     88   allowers.reserve(6);
     89   callers.reserve(6);
     90   auto maker = std::thread(make, count);
     91   for (int i = 1; i <= 6; ++i)
     92   {
     93     allowers.emplace_back(allow, count, i);
     94     callers.emplace_back(call, count);
     95   }
     96   for (auto& t : callers) t.join();
     97   for (auto& t : allowers) t.join();
     98   maker.join();
     99   std::cout << "calls   ";
    100   std::copy(std::begin(call_count), std::end(call_count),
    101             std::ostream_iterator<std::size_t>(std::cout, " "));
    102   std::cout << "\nreturns ";
    103   std::copy(std::begin(ret_count), std::end(ret_count),
    104             std::ostream_iterator<std::size_t>(std::cout, " "));
    105   std::cout << "\n";
    106   assert(std::equal(std::begin(call_count), std::end(call_count),
    107                     std::begin(ret_count), std::end(ret_count)));
    108   obj.reset();
    109 }