Paste Search Dynamic
Recent pastes
MockClock
  1. #include <iostream>
  2. #include <memory>
  3.  
  4. namespace base {
  5.  
  6. class clock {
  7.  public:
  8.   virtual int Now() = 0;
  9.   virtual ~clock() {}
  10. };
  11.  
  12. class DefaultClock : public clock {
  13.  public:
  14.   DefaultClock() {
  15.     std::cout << "Constructed DefaultClock" << std::endl;
  16.   }
  17.  
  18.   virtual ~DefaultClock() {
  19.     std::cout << "Destroyed DefaultClock" << std::endl;
  20.   }
  21.  
  22.   int Now() override {
  23.     static int now = 42;
  24.     return now++;
  25.   };
  26. };
  27.  
  28. class MockClock : public clock {
  29.  public:
  30.   MockClock(int fixed) : fixed_(fixed), now_(fixed) {
  31.     std::cout << "Constructed MockClock" << fixed_ << std::endl;
  32.   }
  33.  
  34.   virtual ~MockClock() {
  35.     std::cout << "Destroyed MockClock" << fixed_ << std::endl;
  36.   }
  37.  
  38.   int Now() override { return now_; }
  39.  
  40.   void SetNow(int now) { now_ = now; }
  41.  private:
  42.   int fixed_;
  43.   int now_;
  44. };
  45.  
  46. template <typename T, typename O = std::nullptr_t>
  47. class NoDestructor {
  48.  public:
  49.   // Not constexpr; just write static constexpr T x = ...; if the value should
  50.   // be a constexpr.
  51.   template <typename... Args>
  52.   explicit NoDestructor(Args&&... args) {
  53.     new (storage_) T(std::forward<Args>(args)...);
  54.   }
  55.  
  56.   // Allows copy and move construction of the contained type, to allow
  57.   // construction from an initializer list, e.g. for std::vector.
  58.   explicit NoDestructor(const T& x) { new (storage_) T(x); }
  59.   explicit NoDestructor(T&& x) { new (storage_) T(std::move(x)); }
  60.  
  61.   NoDestructor(const NoDestructor&) = delete;
  62.   NoDestructor& operator=(const NoDestructor&) = delete;
  63.  
  64.   ~NoDestructor() = default;
  65.  
  66.   const T& operator*() const { return *get(); }
  67.   T& operator*() { return *get(); }
  68.  
  69.   const T* operator->() const { return get(); }
  70.   T* operator->() { return get(); }
  71.  
  72.   const T* get() const { return reinterpret_cast<const T*>(storage_); }
  73.   T* get() { return reinterpret_cast<T*>(storage_); }
  74.  
  75.  private:
  76.   alignas(T) char storage_[sizeof(T)];
  77. };
  78.  
  79. }
  80.  
  81. #define STATIC_MOCKABLE(type, name, default)                                
  82.   public:                                                                  
  83.     template <class T, class... Args>                                      
  84.     static T* Create##name##ForTesting(Args&&... args) {                    
  85.       Get##name##Ptr() = std::make_unique<T>(std::forward<Args>(args)...);  
  86.       return static_cast<T*>(Get##name##Ptr().get());                      
  87.     }                                                                      
  88.   private:                                                                  
  89.    static std::unique_ptr<type>& Get##name##Ptr() {                        
  90.      static base::NoDestructor<std::unique_ptr<type>> instance([] {        
  91.        return default;                                                      
  92.      }());                                                                  
  93.      return *instance;                                                      
  94.    }                                                                        
  95.    static type& Get##name() {                                              
  96.      return *Get##name##Ptr().get();                                        
  97.    }
  98.  
  99. // Example class allowing to inject custom Clock.
  100. class Example {
  101.  public:
  102.   static void PrintNow() {
  103.     std::cout << GetClock().Now() << std::endl;
  104.   }
  105.    
  106.   STATIC_MOCKABLE(base::clock, clock, std::make_unique<base::DefaultClock>());
  107. };
  108.  
  109. // Test code.
  110. void test() {
  111.     auto* clock_mock = Example::CreateClockForTesting<base::MockClock>(11);
  112.     Example::PrintNow();
  113.     clock_mock->SetNow(22);
  114. }
  115.  
  116.  
  117. int main() {
  118.   std::cout << "Start: nothing should be constructed before" << std::endl;
  119.   std::cout << "===========================================" << std::endl;
  120.   Example::PrintNow();
  121.   Example::PrintNow();
  122.   test();
  123.   Example::PrintNow();
  124.   Example::CreateClockForTesting<base::MockClock>(33);
  125.   Example::PrintNow();
  126.   std::cout << "======================================" << std::endl;
  127.   std::cout << "End: nothing should be destroyed after" << std::endl;
  128. }
Parsed in 0.018 seconds