diff UnitTestsSources/TestMessageBroker2.cpp @ 300:b4abaeb783b1 am-callable-and-promise

messaging refactoring almost complete: works fine in native
author am@osimis.io
date Tue, 18 Sep 2018 15:23:21 +0200
parents 3897f9f28cfa
children 4a79193ffb58
line wrap: on
line diff
--- a/UnitTestsSources/TestMessageBroker2.cpp	Fri Sep 14 16:44:01 2018 +0200
+++ b/UnitTestsSources/TestMessageBroker2.cpp	Tue Sep 18 15:23:21 2018 +0200
@@ -22,296 +22,291 @@
 #include "gtest/gtest.h"
 
 #include "Framework/Messages/MessageBroker.h"
+#include "Framework/Messages/Promise.h"
+#include "Framework/Messages/IObservable.h"
+#include "Framework/Messages/IObserver.h"
+#include "Framework/Messages/MessageForwarder.h"
 
-#include <boost/noncopyable.hpp>
-#include <boost/function.hpp>
-#include <boost/bind.hpp>
-
-#include <string>
-#include <map>
-#include <set>
 
 int testCounter = 0;
 namespace {
 
-  class IObserver;
-  class IObservable;
-  class Promise;
+//  class IObserver;
+//  class IObservable;
+//  class Promise;
 
-  enum MessageType
-  {
-    MessageType_Test1,
-    MessageType_Test2,
+//  enum MessageType
+//  {
+//    MessageType_Test1,
+//    MessageType_Test2,
 
-    MessageType_CustomMessage,
-    MessageType_LastGenericStoneMessage
-  };
+//    MessageType_CustomMessage,
+//    MessageType_LastGenericStoneMessage
+//  };
 
-  struct IMessage  : public boost::noncopyable
-  {
-    MessageType messageType_;
-  public:
-    IMessage(const MessageType& messageType)
-      : messageType_(messageType)
-    {}
-    virtual ~IMessage() {}
+//  struct IMessage  : public boost::noncopyable
+//  {
+//    MessageType messageType_;
+//  public:
+//    IMessage(const MessageType& messageType)
+//      : messageType_(messageType)
+//    {}
+//    virtual ~IMessage() {}
 
-    virtual int GetType() const {return messageType_;}
-  };
+//    virtual int GetType() const {return messageType_;}
+//  };
 
 
-  struct ICustomMessage  : public IMessage
-  {
-    int customMessageType_;
-  public:
-    ICustomMessage(int customMessageType)
-      : IMessage(MessageType_CustomMessage),
-        customMessageType_(customMessageType)
-    {}
-    virtual ~ICustomMessage() {}
+//  struct ICustomMessage  : public IMessage
+//  {
+//    int customMessageType_;
+//  public:
+//    ICustomMessage(int customMessageType)
+//      : IMessage(MessageType_CustomMessage),
+//        customMessageType_(customMessageType)
+//    {}
+//    virtual ~ICustomMessage() {}
 
-    virtual int GetType() const {return customMessageType_;}
-  };
+//    virtual int GetType() const {return customMessageType_;}
+//  };
 
 
-  // This is referencing an object and member function that can be notified
-  // by an IObservable.  The object must derive from IO
-  // The member functions must be of type "void Function(const IMessage& message)" or reference a derived class of IMessage
-  class ICallable : public boost::noncopyable
-  {
-  public:
-    virtual ~ICallable()
-    {
-    }
+//  // This is referencing an object and member function that can be notified
+//  // by an IObservable.  The object must derive from IO
+//  // The member functions must be of type "void Function(const IMessage& message)" or reference a derived class of IMessage
+//  class ICallable : public boost::noncopyable
+//  {
+//  public:
+//    virtual ~ICallable()
+//    {
+//    }
 
-    virtual void Apply(const IMessage& message) = 0;
+//    virtual void Apply(const IMessage& message) = 0;
 
-    virtual MessageType GetMessageType() const = 0;
-    virtual IObserver* GetObserver() const = 0;
-  };
+//    virtual MessageType GetMessageType() const = 0;
+//    virtual IObserver* GetObserver() const = 0;
+//  };
 
-  template <typename TObserver,
-            typename TMessage>
-  class Callable : public ICallable
-  {
-  private:
-    typedef void (TObserver::* MemberFunction) (const TMessage&);
+//  template <typename TObserver,
+//            typename TMessage>
+//  class Callable : public ICallable
+//  {
+//  private:
+//    typedef void (TObserver::* MemberFunction) (const TMessage&);
 
-    TObserver&      observer_;
-    MemberFunction  function_;
+//    TObserver&      observer_;
+//    MemberFunction  function_;
 
-  public:
-    Callable(TObserver& observer,
-             MemberFunction function) :
-      observer_(observer),
-      function_(function)
-    {
-    }
+//  public:
+//    Callable(TObserver& observer,
+//             MemberFunction function) :
+//      observer_(observer),
+//      function_(function)
+//    {
+//    }
 
-    void ApplyInternal(const TMessage& message)
-    {
-      (observer_.*function_) (message);
-    }
+//    void ApplyInternal(const TMessage& message)
+//    {
+//      (observer_.*function_) (message);
+//    }
 
-    virtual void Apply(const IMessage& message)
-    {
-      ApplyInternal(dynamic_cast<const TMessage&>(message));
-    }
+//    virtual void Apply(const IMessage& message)
+//    {
+//      ApplyInternal(dynamic_cast<const TMessage&>(message));
+//    }
 
-    virtual MessageType GetMessageType() const
-    {
-      return static_cast<MessageType>(TMessage::Type);
-    }
+//    virtual MessageType GetMessageType() const
+//    {
+//      return static_cast<MessageType>(TMessage::Type);
+//    }
 
-    virtual IObserver* GetObserver() const
-    {
-      return &observer_;
-    }
-  };
+//    virtual IObserver* GetObserver() const
+//    {
+//      return &observer_;
+//    }
+//  };
 
 
 
 
-  /*
-   * This is a central message broker.  It keeps track of all observers and knows
-   * when an observer is deleted.
-   * This way, it can prevent an observable to send a message to a delete observer.
-   */
-  class MessageBroker : public boost::noncopyable
-  {
+//  /*
+//   * This is a central message broker.  It keeps track of all observers and knows
+//   * when an observer is deleted.
+//   * This way, it can prevent an observable to send a message to a delete observer.
+//   */
+//  class MessageBroker : public boost::noncopyable
+//  {
 
-    std::set<IObserver*> activeObservers_;  // the list of observers that are currently alive (that have not been deleted)
+//    std::set<IObserver*> activeObservers_;  // the list of observers that are currently alive (that have not been deleted)
 
-  public:
+//  public:
 
-    void Register(IObserver& observer)
-    {
-      activeObservers_.insert(&observer);
-    }
+//    void Register(IObserver& observer)
+//    {
+//      activeObservers_.insert(&observer);
+//    }
 
-    void Unregister(IObserver& observer)
-    {
-      activeObservers_.erase(&observer);
-    }
+//    void Unregister(IObserver& observer)
+//    {
+//      activeObservers_.erase(&observer);
+//    }
 
-    bool IsActive(IObserver* observer)
-    {
-      return activeObservers_.find(observer) != activeObservers_.end();
-    }
-  };
+//    bool IsActive(IObserver* observer)
+//    {
+//      return activeObservers_.find(observer) != activeObservers_.end();
+//    }
+//  };
 
 
-  class Promise : public boost::noncopyable
-  {
-  protected:
-    MessageBroker&                    broker_;
+//  class Promise : public boost::noncopyable
+//  {
+//  protected:
+//    MessageBroker&                    broker_;
 
-    ICallable* successCallable_;
-    ICallable* failureCallable_;
+//    ICallable* successCallable_;
+//    ICallable* failureCallable_;
 
-  public:
-    Promise(MessageBroker& broker)
-      : broker_(broker),
-        successCallable_(NULL),
-        failureCallable_(NULL)
-    {
-    }
+//  public:
+//    Promise(MessageBroker& broker)
+//      : broker_(broker),
+//        successCallable_(NULL),
+//        failureCallable_(NULL)
+//    {
+//    }
 
-    void Success(const IMessage& message)
-    {
-      // check the target is still alive in the broker
-      if (broker_.IsActive(successCallable_->GetObserver()))
-      {
-        successCallable_->Apply(message);
-      }
-    }
+//    void Success(const IMessage& message)
+//    {
+//      // check the target is still alive in the broker
+//      if (broker_.IsActive(successCallable_->GetObserver()))
+//      {
+//        successCallable_->Apply(message);
+//      }
+//    }
 
-    void Failure(const IMessage& message)
-    {
-      // check the target is still alive in the broker
-      if (broker_.IsActive(failureCallable_->GetObserver()))
-      {
-        failureCallable_->Apply(message);
-      }
-    }
+//    void Failure(const IMessage& message)
+//    {
+//      // check the target is still alive in the broker
+//      if (broker_.IsActive(failureCallable_->GetObserver()))
+//      {
+//        failureCallable_->Apply(message);
+//      }
+//    }
 
-    Promise& Then(ICallable* successCallable)
-    {
-      if (successCallable_ != NULL)
-      {
-        // TODO: throw throw new "Promise may only have a single success target"
-      }
-      successCallable_ = successCallable;
-      return *this;
-    }
+//    Promise& Then(ICallable* successCallable)
+//    {
+//      if (successCallable_ != NULL)
+//      {
+//        // TODO: throw throw new "Promise may only have a single success target"
+//      }
+//      successCallable_ = successCallable;
+//      return *this;
+//    }
 
-    Promise& Else(ICallable* failureCallable)
-    {
-      if (failureCallable_ != NULL)
-      {
-        // TODO: throw throw new "Promise may only have a single failure target"
-      }
-      failureCallable_ = failureCallable;
-      return *this;
-    }
+//    Promise& Else(ICallable* failureCallable)
+//    {
+//      if (failureCallable_ != NULL)
+//      {
+//        // TODO: throw throw new "Promise may only have a single failure target"
+//      }
+//      failureCallable_ = failureCallable;
+//      return *this;
+//    }
 
-  };
+//  };
 
-  class IObserver : public boost::noncopyable
-  {
-  protected:
-    MessageBroker&                    broker_;
+//  class IObserver : public boost::noncopyable
+//  {
+//  protected:
+//    MessageBroker&                    broker_;
 
-  public:
-    IObserver(MessageBroker& broker)
-      : broker_(broker)
-    {
-      broker_.Register(*this);
-    }
+//  public:
+//    IObserver(MessageBroker& broker)
+//      : broker_(broker)
+//    {
+//      broker_.Register(*this);
+//    }
 
-    virtual ~IObserver()
-    {
-      broker_.Unregister(*this);
-    }
+//    virtual ~IObserver()
+//    {
+//      broker_.Unregister(*this);
+//    }
 
-  };
+//  };
 
 
-  class IObservable : public boost::noncopyable
-  {
-  protected:
-    MessageBroker&                     broker_;
+//  class IObservable : public boost::noncopyable
+//  {
+//  protected:
+//    MessageBroker&                     broker_;
 
-    typedef std::map<int, std::set<ICallable*> >   Callables;
-    Callables  callables_;
-  public:
+//    typedef std::map<int, std::set<ICallable*> >   Callables;
+//    Callables  callables_;
+//  public:
 
-    IObservable(MessageBroker& broker)
-      : broker_(broker)
-    {
-    }
+//    IObservable(MessageBroker& broker)
+//      : broker_(broker)
+//    {
+//    }
 
-    virtual ~IObservable()
-    {
-      for (Callables::const_iterator it = callables_.begin();
-           it != callables_.end(); ++it)
-      {
-        for (std::set<ICallable*>::const_iterator
-               it2 = it->second.begin(); it2 != it->second.end(); ++it2)
-        {
-          delete *it2;
-        }
-      }
-    }
+//    virtual ~IObservable()
+//    {
+//      for (Callables::const_iterator it = callables_.begin();
+//           it != callables_.end(); ++it)
+//      {
+//        for (std::set<ICallable*>::const_iterator
+//               it2 = it->second.begin(); it2 != it->second.end(); ++it2)
+//        {
+//          delete *it2;
+//        }
+//      }
+//    }
 
-    void Register(ICallable* callable)
-    {
-      MessageType messageType = callable->GetMessageType();
+//    void Register(ICallable* callable)
+//    {
+//      MessageType messageType = callable->GetMessageType();
 
-      callables_[messageType].insert(callable);
-    }
+//      callables_[messageType].insert(callable);
+//    }
 
-    void EmitMessage(const IMessage& message)
-    {
-      Callables::const_iterator found = callables_.find(message.GetType());
+//    void EmitMessage(const IMessage& message)
+//    {
+//      Callables::const_iterator found = callables_.find(message.GetType());
 
-      if (found != callables_.end())
-      {
-        for (std::set<ICallable*>::const_iterator
-               it = found->second.begin(); it != found->second.end(); ++it)
-        {
-          if (broker_.IsActive((*it)->GetObserver()))
-          {
-            (*it)->Apply(message);
-          }
-        }
-      }
-    }
+//      if (found != callables_.end())
+//      {
+//        for (std::set<ICallable*>::const_iterator
+//               it = found->second.begin(); it != found->second.end(); ++it)
+//        {
+//          if (broker_.IsActive((*it)->GetObserver()))
+//          {
+//            (*it)->Apply(message);
+//          }
+//        }
+//      }
+//    }
 
-  };
+//  };
 
 
-  enum CustomMessageType
-  {
-    CustomMessageType_First = MessageType_LastGenericStoneMessage + 1,
+//  enum CustomMessageType
+//  {
+//    CustomMessageType_First = MessageType_LastGenericStoneMessage + 1,
 
-    CustomMessageType_Completed,
-    CustomMessageType_Increment
-  };
+//    CustomMessageType_Completed,
+//    CustomMessageType_Increment
+//  };
+
+  using namespace OrthancStone;
 
   class MyObservable : public IObservable
   {
   public:
-    struct MyCustomMessage: public ICustomMessage
+    struct MyCustomMessage: public BaseMessage<MessageType_Test1>
     {
       int payload_;
-      enum
-      {
-        Type = CustomMessageType_Completed
-      };
 
       MyCustomMessage(int payload)
-        : ICustomMessage(Type),
+        : BaseMessage(),
           payload_(payload)
       {}
     };
@@ -337,20 +332,30 @@
   };
 
 
+  class MyIntermediate : public IObserver, public IObservable
+  {
+    IObservable& observedObject_;
+  public:
+    MyIntermediate(MessageBroker& broker, IObservable& observedObject)
+      : IObserver(broker),
+        IObservable(broker),
+        observedObject_(observedObject)
+    {
+      observedObject_.RegisterObserverCallback(new MessageForwarder<MyObservable::MyCustomMessage>(broker, *this));
+    }
+  };
+
+
   class MyPromiseSource : public IObservable
   {
     Promise* currentPromise_;
   public:
-    struct MyPromiseMessage: public ICustomMessage
+    struct MyPromiseMessage: public BaseMessage<MessageType_Test1>
     {
       int increment;
-      enum
-      {
-        Type = CustomMessageType_Increment
-      };
 
       MyPromiseMessage(int increment)
-        : ICustomMessage(Type),
+        : BaseMessage(),
           increment(increment)
       {}
     };
@@ -407,7 +412,7 @@
   MyObserver    observer(broker);
 
   // create a permanent connection between an observable and an observer
-  observable.Register(new Callable<MyObserver, MyObservable::MyCustomMessage>(observer, &MyObserver::HandleCompletedMessage));
+  observable.RegisterObserverCallback(new Callable<MyObserver, MyObservable::MyCustomMessage>(observer, &MyObserver::HandleCompletedMessage));
 
   testCounter = 0;
   observable.EmitMessage(MyObservable::MyCustomMessage(12));
@@ -426,7 +431,7 @@
   MyObserver*   observer = new MyObserver(broker);
 
   // create a permanent connection between an observable and an observer
-  observable.Register(new Callable<MyObserver, MyObservable::MyCustomMessage>(*observer, &MyObserver::HandleCompletedMessage));
+  observable.RegisterObserverCallback(new Callable<MyObserver, MyObservable::MyCustomMessage>(*observer, &MyObserver::HandleCompletedMessage));
 
   testCounter = 0;
   observable.EmitMessage(MyObservable::MyCustomMessage(12));
@@ -441,6 +446,27 @@
   ASSERT_EQ(0, testCounter);
 }
 
+TEST(MessageBroker2, TestMessageForwarderSimpleUseCase)
+{
+  MessageBroker broker;
+  MyObservable  observable(broker);
+  MyIntermediate intermediate(broker, observable);
+  MyObserver    observer(broker);
+
+  // let the observer observers the intermediate that is actually forwarding the messages from the observable
+  intermediate.RegisterObserverCallback(new Callable<MyObserver, MyObservable::MyCustomMessage>(observer, &MyObserver::HandleCompletedMessage));
+
+  testCounter = 0;
+  observable.EmitMessage(MyObservable::MyCustomMessage(12));
+  ASSERT_EQ(12, testCounter);
+
+  // the connection is permanent; if we emit the same message again, the observer will be notified again
+  testCounter = 0;
+  observable.EmitMessage(MyObservable::MyCustomMessage(20));
+  ASSERT_EQ(20, testCounter);
+}
+
+
 
 TEST(MessageBroker2, TestPromiseSuccessFailure)
 {
@@ -496,196 +522,3 @@
   ASSERT_EQ(0, testCounter);
 }
 
-
-
-//#include <stdio.h>
-//#include <boost/noncopyable.hpp>
-
-//#include <string>
-//#include <memory>
-//#include <map>
-//#include <set>
-
-//enum MessageType
-//{
-//  MessageType_SeriesDownloaded = 1
-//};
-
-
-//class IMessage : public boost::noncopyable
-//{
-//private:
-//  MessageType  type_;
-
-//public:
-//  IMessage(MessageType  type) :
-//    type_(type)
-//  {
-//  }
-
-//  virtual ~IMessage()
-//  {
-//  }
-
-//  MessageType GetMessageType() const
-//  {
-//    return type_;
-//  }
-//};
-
-
-//class IObserver : public boost::noncopyable
-//{
-//public:
-//  virtual ~IObserver()
-//  {
-//  }
-//};
-
-
-//class SeriesDownloadedMessage : public IMessage
-//{
-//private:
-//  std::string value_;
-
-//public:
-//  enum
-//  {
-//    Type = MessageType_SeriesDownloaded
-//  };
-
-//  SeriesDownloadedMessage(const std::string& value) :
-//    IMessage(static_cast<MessageType>(Type)),
-//    value_(value)
-//  {
-//  }
-
-//  const std::string& GetValue() const
-//  {
-//    return value_;
-//  }
-//};
-
-
-//class MyObserver : public IObserver
-//{
-//public:
-//  void OnSeriesDownloaded(const SeriesDownloadedMessage& message)
-//  {
-//    printf("received: [%s]\n", message.GetValue().c_str());
-//  }
-//};
-
-
-
-//class ICallable : public boost::noncopyable  // ne peut referencer que les classes de base
-//{
-//public:
-//  virtual ~ICallable()
-//  {
-//  }
-
-//  virtual void Apply(const IMessage& message) = 0;
-
-//  virtual MessageType GetMessageType() const = 0;
-//};
-
-
-
-//template <typename Observer,
-//          typename Message>
-//class Callable : public ICallable
-//{
-//private:
-//  typedef void (Observer::* MemberFunction) (const Message&);
-
-//  Observer&       observer_;
-//  MemberFunction  function_;
-
-//public:
-//  Callable(Observer& observer,
-//           MemberFunction function) :
-//    observer_(observer),
-//    function_(function)
-//  {
-//  }
-
-//  void ApplyInternal(const Message& message)
-//  {
-//    (observer_.*function_) (message);
-//  }
-
-//  virtual void Apply(const IMessage& message)
-//  {
-//    ApplyInternal(dynamic_cast<const Message&>(message));
-//  }
-
-//  virtual MessageType GetMessageType() const
-//  {
-//    return static_cast<MessageType>(Message::Type);
-//  }
-//};
-
-
-
-//class IObservable : public boost::noncopyable
-//{
-//private:
-//  typedef std::map<MessageType, std::set<ICallable*> >   Callables;
-
-//  Callables  callables_;
-
-//public:
-//  virtual ~IObservable()
-//  {
-//    for (Callables::const_iterator it = callables_.begin();
-//         it != callables_.end(); ++it)
-//    {
-//      for (std::set<ICallable*>::const_iterator
-//             it2 = it->second.begin(); it2 != it->second.end(); ++it2)
-//      {
-//        delete *it2;
-//      }
-//    }
-//  }
-
-//  void Register(ICallable* callable)
-//  {
-//    MessageType type = callable->GetMessageType();
-
-//    callables_[type].insert(callable);
-//  }
-
-//  void Emit(const IMessage& message) const
-//  {
-//    Callables::const_iterator found = callables_.find(message.GetMessageType());
-
-//    if (found != callables_.end())
-//    {
-//      for (std::set<ICallable*>::const_iterator
-//             it = found->second.begin(); it != found->second.end(); ++it)
-//      {
-//        (*it)->Apply(message);
-//      }
-//    }
-//  }
-//};
-
-
-
-
-//int main()
-//{
-//  MyObserver observer;
-
-//  SeriesDownloadedMessage message("coucou");
-
-//  IObservable observable;
-//  observable.Register(new Callable<MyObserver, SeriesDownloadedMessage>(observer, &MyObserver::OnSeriesDownloaded));
-//  observable.Register(new Callable<MyObserver, SeriesDownloadedMessage>(observer, &MyObserver::OnSeriesDownloaded));
-
-//  SeriesDownloadedMessage message2("hello");
-//  observable.Emit(message2);
-
-//  printf("%d\n", SeriesDownloadedMessage::Type);
-//}