From a9b11dde21b285bb1b7f5c3467e37bbe8de40b24 Mon Sep 17 00:00:00 2001
From: Gennady Pospelov <g.pospelov@fz-juelich.de>
Date: Wed, 20 Apr 2016 12:23:04 +0200
Subject: [PATCH] Refactored tests for model mapper.

---
 GUI/coregui/Models/ModelMapper.cpp          |  14 +-
 GUI/coregui/Models/ModelMapper.h            |  19 +-
 Tests/UnitTests/TestGUI/TestMapperForItem.h | 295 ++++++++++----------
 3 files changed, 158 insertions(+), 170 deletions(-)

diff --git a/GUI/coregui/Models/ModelMapper.cpp b/GUI/coregui/Models/ModelMapper.cpp
index 44b5dfa9d0b..0fec1c3b1da 100644
--- a/GUI/coregui/Models/ModelMapper.cpp
+++ b/GUI/coregui/Models/ModelMapper.cpp
@@ -75,13 +75,13 @@ void ModelMapper::setOnAnyChildChange(std::function<void (SessionItem *)> f, voi
 //! Cancells all subscribtion of given caller
 void ModelMapper::unsubscribe(void *caller)
 {
-    qDebug() << "XXX" << m_onPropertyChange.size();
-//    m_onPropertyChange.erase(std::remove_if(m_onPropertyChange.begin(), m_onPropertyChange.end(),
-//                           [](call_str_t const & x) -> bool { Q_UNUSED(x); return true; }),
-//            m_onPropertyChange.end());
-
-    clean_container(m_onPropertyChange);
-    qDebug() << "XXX 1.2" << m_onPropertyChange.size();
+    clean_container(m_onValueChange, caller);
+    clean_container(m_onPropertyChange, caller);
+    clean_container(m_onChildPropertyChange, caller);
+    clean_container(m_onParentChange, caller);
+    clean_container(m_onChildrenChange, caller);
+    clean_container(m_onSiblingsChange, caller);
+    clean_container(m_onAnyChildChange, caller);
 }
 
 void ModelMapper::setModel(SessionModel *model)
diff --git a/GUI/coregui/Models/ModelMapper.h b/GUI/coregui/Models/ModelMapper.h
index 8f0fbf6807b..57e48a522ff 100644
--- a/GUI/coregui/Models/ModelMapper.h
+++ b/GUI/coregui/Models/ModelMapper.h
@@ -76,14 +76,8 @@ public slots:
     void onRowRemoved(const QModelIndex & parent, int first, int last);
 
 private:
-    template<class U>
-    void clean_container(U& v) {
-        v.erase(std::remove_if(v.begin(), v.end(),
-                               [](call_str_t const & x) -> bool { Q_UNUSED(x); return true; }),
-                v.end());
-
-    }
-
+    //! removes all callbacks related to given caller
+    template<class U> void clean_container(U& v, void *caller);
 
     void setModel(SessionModel *model);
     int nestlingDepth(SessionItem* item, int level = 0);
@@ -117,4 +111,13 @@ private:
     QModelIndex m_aboutToDelete;
 };
 
+
+template<class U>
+inline void ModelMapper::clean_container(U& v, void *caller) {
+    v.erase(std::remove_if(v.begin(), v.end(),
+        [caller](typename U::value_type const &x) -> bool { return (x.second == caller ? true : false); }),
+            v.end());
+}
+
+
 #endif
diff --git a/Tests/UnitTests/TestGUI/TestMapperForItem.h b/Tests/UnitTests/TestGUI/TestMapperForItem.h
index 9b89ac1a615..1a5ae46a3c5 100644
--- a/Tests/UnitTests/TestGUI/TestMapperForItem.h
+++ b/Tests/UnitTests/TestGUI/TestMapperForItem.h
@@ -10,20 +10,15 @@
 #include <QtTest>
 
 
-//! Test if ModelMapper reports correctly (number of callbacks,
-//! names of properties and reporting items)
-class TestMapperForItem : public QObject {
-    Q_OBJECT
-
+//! Test Widget which logs calling activity of ModelMapper
+class Widget {
 public:
-    TestMapperForItem(QObject *parent = 0)
-        : QObject(parent)
-        , m_onPropertyChangeCount(0)
+    Widget()
+        : m_onPropertyChangeCount(0)
         , m_onChildPropertyChangeCount(0)
         , m_onParentChangeCount(0)
         , m_onChildrenChangeCount(0)
         , m_onSiblingsChangeCount(0)
-        , m_mapped_item(0)
     { }
 
     void clear()
@@ -33,91 +28,48 @@ public:
         m_onParentChangeCount = 0;
         m_onChildrenChangeCount = 0;
         m_onSiblingsChangeCount = 0;
-        m_mapped_item = 0;
         m_reported_items.clear();
         m_reported_names.clear();
     }
 
-    void setItem(SessionItem *item)
+    void subscribe(ModelMapper *mapper, bool with_subscription = false)
     {
         clear();
-        m_mapped_item = item;
-        m_mapper.reset(new ModelMapper);
-        m_mapper->setItem(item);
 
-        m_mapper->setOnPropertyChange(
-                    [this] (QString name)
-        {
-            onPropertyChange(name);
-        });
-
-        m_mapper->setOnChildPropertyChange(
-                    [this](SessionItem* item, QString name)
-        {
-            onChildPropertyChange(item, name);
-        });
+        void *caller = (with_subscription ? this : 0);
 
-        m_mapper->setOnParentChange(
-                    [this](SessionItem *parent) {
-            onParentChange(parent);
-        });
-
-
-        m_mapper->setOnChildrenChange(
-                    [this](SessionItem*)
-        {
-            onChildrenChange();
-        });
-
-        m_mapper->setOnSiblingsChange(
-                    [this]()
-        {
-            onSiblingsChange();
-        });
-
-    }
-
-    void setItemSubscribe(SessionItem *item)
-    {
-        clear();
-        m_mapped_item = item;
-        m_mapper.reset(new ModelMapper);
-        m_mapper->setItem(item);
-
-        m_mapper->setOnPropertyChange(
+        mapper->setOnPropertyChange(
                     [this] (QString name)
         {
             onPropertyChange(name);
-        }, this);
+        }, caller);
 
-        m_mapper->setOnChildPropertyChange(
+        mapper->setOnChildPropertyChange(
                     [this](SessionItem* item, QString name)
         {
             onChildPropertyChange(item, name);
-        }, this);
+        }, caller);
 
-        m_mapper->setOnParentChange(
+        mapper->setOnParentChange(
                     [this](SessionItem *parent) {
             onParentChange(parent);
-        }, this);
+        }, caller);
 
 
-        m_mapper->setOnChildrenChange(
+        mapper->setOnChildrenChange(
                     [this](SessionItem*)
         {
             onChildrenChange();
-        }, this);
+        }, caller);
 
-        m_mapper->setOnSiblingsChange(
+        mapper->setOnSiblingsChange(
                     [this]()
         {
             onSiblingsChange();
-        }, this);
+        }, caller);
 
     }
 
-
-private:
     void onPropertyChange(const QString &name)
     {
         m_reported_names.append(name);
@@ -147,157 +99,189 @@ private:
         m_onSiblingsChangeCount++;
     }
 
+    void unsubscribe(ModelMapper *mapper) {
+        mapper->unsubscribe(this);
+    }
+
     int m_onPropertyChangeCount;
     int m_onChildPropertyChangeCount;
     int m_onParentChangeCount;
     int m_onChildrenChangeCount;
     int m_onSiblingsChangeCount;
-    SessionItem *m_mapped_item;
     QList<SessionItem *> m_reported_items;
     QStringList m_reported_names;
+};
+
+
+//! Test if ModelMapper reports correctly (number of callbacks,
+//! names of properties and reporting items)
+class TestMapperForItem : public QObject {
+    Q_OBJECT
+
+public:
+    TestMapperForItem(QObject *parent = 0)
+        : QObject(parent)
+        , m_mapped_item(0)
+    { }
+
+    void setItem(SessionItem *item, Widget *widget, bool with_subscription = false)
+    {
+        m_mapped_item = item;
+        m_mapper.reset(new ModelMapper);
+        m_mapper->setItem(item);
+        widget->subscribe(m_mapper.get(), with_subscription);
+    }
+
+private:
+    SessionItem *m_mapped_item;
     std::unique_ptr<ModelMapper> m_mapper;
 
 private slots:
-
+    void test_initialCondition();
     void test_onPropertyChange();
     void test_onParentChange();
     void test_onChildrenChange();
     void test_onSiblingsChange();
-
     void test_Subscription();
 };
 
+inline void TestMapperForItem::test_initialCondition()
+{
+    Widget w;
+    QCOMPARE(w.m_onPropertyChangeCount, 0);
+    QCOMPARE(w.m_onChildPropertyChangeCount, 0);
+    QCOMPARE(w.m_onParentChangeCount, 0);
+    QCOMPARE(w.m_onChildrenChangeCount, 0);
+    QCOMPARE(w.m_onSiblingsChangeCount, 0);
+    QVERIFY(w.m_reported_items.isEmpty());
+    QVERIFY(w.m_reported_names.isEmpty());
+    QVERIFY(m_mapped_item == nullptr);
+    QVERIFY(!m_mapper);
+}
+
 inline void TestMapperForItem::test_onPropertyChange()
 {
+    Widget w;
     SampleModel model;
     SessionItem *multilayer = model.insertNewItem(Constants::MultiLayerType);
     SessionItem *layer = model.insertNewItem(Constants::LayerType, model.indexOfItem(multilayer));
 
-    // check initial state of our test class
-    QCOMPARE(m_onPropertyChangeCount, 0);
-    QCOMPARE(m_onChildPropertyChangeCount, 0);
-    QCOMPARE(m_onParentChangeCount, 0);
-    QCOMPARE(m_onChildrenChangeCount, 0);
-    QCOMPARE(m_onSiblingsChangeCount, 0);
-    QVERIFY(m_mapped_item == nullptr);
-    QVERIFY(m_reported_items.isEmpty());
-    QVERIFY(m_reported_names.isEmpty());
-
     // Mapper is looking on child; set property of child
-    setItem(layer);
-    layer->setItemValue(LayerItem::P_THICKNESS, 1.0);
-    QCOMPARE(m_onPropertyChangeCount, 1);
-    QCOMPARE(m_onChildPropertyChangeCount, 0);
-    QCOMPARE(m_onParentChangeCount, 0);
-    QCOMPARE(m_onChildrenChangeCount, 0);
-    QCOMPARE(m_onSiblingsChangeCount, 0);
+    setItem(layer, &w);
     QVERIFY(m_mapped_item == layer);
-    QVERIFY(m_reported_items.isEmpty());
-    QVERIFY((m_reported_names.size() == 1) && (m_reported_names[0] == LayerItem::P_THICKNESS));
+
+    layer->setItemValue(LayerItem::P_THICKNESS, 1.0);
+    QCOMPARE(w.m_onPropertyChangeCount, 1);
+    QCOMPARE(w.m_onChildPropertyChangeCount, 0);
+    QCOMPARE(w.m_onParentChangeCount, 0);
+    QCOMPARE(w.m_onChildrenChangeCount, 0);
+    QCOMPARE(w.m_onSiblingsChangeCount, 0);
+    QVERIFY(w.m_reported_items.isEmpty());
+    QVERIFY((w.m_reported_names.size() == 1) && (w.m_reported_names[0] == LayerItem::P_THICKNESS));
 
     // Mapper is looking on child; set property of parent;
-    setItem(layer);
-    multilayer->setItemValue(MultiLayerItem::P_CROSS_CORR_LENGTH, 1.0);
-    QCOMPARE(m_onPropertyChangeCount, 0);
-    QCOMPARE(m_onChildPropertyChangeCount, 0);
-    QCOMPARE(m_onParentChangeCount, 0);
-    QCOMPARE(m_onChildrenChangeCount, 0);
-    QCOMPARE(m_onSiblingsChangeCount, 0);
+    setItem(layer, &w);
     QVERIFY(m_mapped_item == layer);
-    QVERIFY(m_reported_items.isEmpty());
-    QVERIFY(m_reported_names.isEmpty());
+    multilayer->setItemValue(MultiLayerItem::P_CROSS_CORR_LENGTH, 1.0);
+    QCOMPARE(w.m_onPropertyChangeCount, 0);
+    QCOMPARE(w.m_onChildPropertyChangeCount, 0);
+    QCOMPARE(w.m_onParentChangeCount, 0);
+    QCOMPARE(w.m_onChildrenChangeCount, 0);
+    QCOMPARE(w.m_onSiblingsChangeCount, 0);
+    QVERIFY(w.m_reported_items.isEmpty());
+    QVERIFY(w.m_reported_names.isEmpty());
 
     // Mapper is looking on parent; set property of child;
-    setItem(multilayer);
-    layer->setItemValue(LayerItem::P_THICKNESS, 2.0);
-    QCOMPARE(m_onPropertyChangeCount, 0);
-    QCOMPARE(m_onChildPropertyChangeCount, 1);
-    QCOMPARE(m_onParentChangeCount, 0);
-    QCOMPARE(m_onChildrenChangeCount, 0);
-    QCOMPARE(m_onSiblingsChangeCount, 0);
+    setItem(multilayer, &w);
     QVERIFY(m_mapped_item == multilayer);
-    QVERIFY( (m_reported_items.size() == 1) && (m_reported_items[0] == layer));
-    QVERIFY((m_reported_names.size() == 1) && (m_reported_names[0] == LayerItem::P_THICKNESS));
+    layer->setItemValue(LayerItem::P_THICKNESS, 2.0);
+    QCOMPARE(w.m_onPropertyChangeCount, 0);
+    QCOMPARE(w.m_onChildPropertyChangeCount, 1);
+    QCOMPARE(w.m_onParentChangeCount, 0);
+    QCOMPARE(w.m_onChildrenChangeCount, 0);
+    QCOMPARE(w.m_onSiblingsChangeCount, 0);
+    QVERIFY( (w.m_reported_items.size() == 1) && (w.m_reported_items[0] == layer));
+    QVERIFY((w.m_reported_names.size() == 1) && (w.m_reported_names[0] == LayerItem::P_THICKNESS));
 
     // Mapper is looking on parent; set property of parent;
-    setItem(multilayer);
-    multilayer->setItemValue(MultiLayerItem::P_CROSS_CORR_LENGTH, 2.0);
-    QCOMPARE(m_onPropertyChangeCount, 1);
-    QCOMPARE(m_onChildPropertyChangeCount, 0);
-    QCOMPARE(m_onParentChangeCount, 0);
-    QCOMPARE(m_onChildrenChangeCount, 0);
-    QCOMPARE(m_onSiblingsChangeCount, 0);
+    setItem(multilayer, &w);
     QVERIFY(m_mapped_item == multilayer);
-    QVERIFY(m_reported_items.isEmpty());
-    QVERIFY((m_reported_names.size() == 1) && (m_reported_names[0] == MultiLayerItem::P_CROSS_CORR_LENGTH));
+    multilayer->setItemValue(MultiLayerItem::P_CROSS_CORR_LENGTH, 2.0);
+    QCOMPARE(w.m_onPropertyChangeCount, 1);
+    QCOMPARE(w.m_onChildPropertyChangeCount, 0);
+    QCOMPARE(w.m_onParentChangeCount, 0);
+    QCOMPARE(w.m_onChildrenChangeCount, 0);
+    QCOMPARE(w.m_onSiblingsChangeCount, 0);
+    QVERIFY(w.m_reported_items.isEmpty());
+    QVERIFY((w.m_reported_names.size() == 1) && (w.m_reported_names[0] == MultiLayerItem::P_CROSS_CORR_LENGTH));
 }
 
 inline void TestMapperForItem::test_onParentChange()
 {
-    clear();
+    Widget w;
     SampleModel model;
     SessionItem *multilayer = model.insertNewItem(Constants::MultiLayerType);
     SessionItem *layer = model.insertNewItem(Constants::LayerType, model.indexOfItem(multilayer));
 //    SessionItem *layer = model.insertNewItem(Constants::LayerType);
 
     // Mapper is looking on child; changing child's parent
-    setItem(layer);
+    setItem(layer, &w);
+    QVERIFY(m_mapped_item == layer);
     multilayer->takeRow(layer->parentRow());
 //    model.moveParameterizedItem(layer, multilayer);
     // FIXME check onParentChange while moving an item
 
-    QCOMPARE(m_onPropertyChangeCount, 0);
-    QCOMPARE(m_onChildPropertyChangeCount, 0);
-    QCOMPARE(m_onParentChangeCount, 1);
-    QCOMPARE(m_onChildrenChangeCount, 0);
-    QVERIFY(m_mapped_item == layer);
-    //QVERIFY((m_reported_items.size() == 1) && (m_reported_items[0] == nullptr));
-    QVERIFY(m_reported_names.isEmpty());
+    QCOMPARE(w.m_onPropertyChangeCount, 0);
+    QCOMPARE(w.m_onChildPropertyChangeCount, 0);
+    QCOMPARE(w.m_onParentChangeCount, 1);
+    QCOMPARE(w.m_onChildrenChangeCount, 0);
+    //QVERIFY((w.m_reported_items.size() == 1) && (w.m_reported_items[0] == nullptr));
+    QVERIFY(w.m_reported_names.isEmpty());
 }
 
 inline void TestMapperForItem::test_onChildrenChange()
 {
-    clear();
+    Widget w;
     SampleModel model;
     SessionItem *multilayer = model.insertNewItem(Constants::MultiLayerType);
 
     // Mapper is looking on parent; adding new child to parent
-    setItem(multilayer);
+    setItem(multilayer, &w);
+    QVERIFY(m_mapped_item == multilayer);
     model.insertNewItem(Constants::LayerType, model.indexOfItem(multilayer));
 
-    QCOMPARE(m_onPropertyChangeCount, 0);
-    QCOMPARE(m_onChildPropertyChangeCount, 2);
-    QCOMPARE(m_onParentChangeCount, 0);
-    QCOMPARE(m_onChildrenChangeCount, 1);
-    QCOMPARE(m_onSiblingsChangeCount, 0);
-    QVERIFY(m_mapped_item == multilayer);
-    QCOMPARE(m_reported_items.size(), 2);
-    QCOMPARE(m_reported_names.size(), 2);
+    QCOMPARE(w.m_onPropertyChangeCount, 0);
+    QCOMPARE(w.m_onChildPropertyChangeCount, 2);
+    QCOMPARE(w.m_onParentChangeCount, 0);
+    QCOMPARE(w.m_onChildrenChangeCount, 1);
+    QCOMPARE(w.m_onSiblingsChangeCount, 0);
+    QCOMPARE(w.m_reported_items.size(), 2);
+    QCOMPARE(w.m_reported_names.size(), 2);
 }
 
 inline void TestMapperForItem::test_onSiblingsChange()
 {
-    clear();
+    Widget w;
     SampleModel model;
     SessionItem *multilayer = model.insertNewItem(Constants::MultiLayerType);
     SessionItem *layer = model.insertNewItem(Constants::LayerType, model.indexOfItem(multilayer));
 
     // Mapper is looking on child; adding another child to parent
-    setItem(layer);
+    setItem(layer, &w);
+    QVERIFY(m_mapped_item == layer);
     SessionItem *layer2 = model.insertNewItem(Constants::LayerType, model.indexOfItem(multilayer));
     Q_UNUSED(layer2);
 
-    QCOMPARE(m_onPropertyChangeCount, 0);
-    QCOMPARE(m_onChildPropertyChangeCount, 0);
-    QCOMPARE(m_onParentChangeCount, 0);
-    QCOMPARE(m_onChildrenChangeCount, 0);
-    QCOMPARE(m_onSiblingsChangeCount, 1);
-    QVERIFY(m_mapped_item == layer);
-    QVERIFY(m_reported_items.isEmpty());
-    QVERIFY(m_reported_names.isEmpty());
+    QCOMPARE(w.m_onPropertyChangeCount, 0);
+    QCOMPARE(w.m_onChildPropertyChangeCount, 0);
+    QCOMPARE(w.m_onParentChangeCount, 0);
+    QCOMPARE(w.m_onChildrenChangeCount, 0);
+    QCOMPARE(w.m_onSiblingsChangeCount, 1);
+    QVERIFY(w.m_reported_items.isEmpty());
+    QVERIFY(w.m_reported_names.isEmpty());
 
     multilayer->takeItem(1, MultiLayerItem::T_LAYERS);
-    QCOMPARE(m_onSiblingsChangeCount, 2);
+    QCOMPARE(w.m_onSiblingsChangeCount, 2);
 
     // FIXME
 //    multilayer->takeRow(layer2->parentRow());
@@ -306,28 +290,29 @@ inline void TestMapperForItem::test_onSiblingsChange()
 
 inline void TestMapperForItem::test_Subscription()
 {
+    Widget w;
     SampleModel model;
     SessionItem *multilayer = model.insertNewItem(Constants::MultiLayerType);
     SessionItem *layer = model.insertNewItem(Constants::LayerType, model.indexOfItem(multilayer));
 
     // Mapper is looking on child; set property of child
-    setItemSubscribe(layer);
-    layer->setItemValue(LayerItem::P_THICKNESS, 1.0);
-    QCOMPARE(m_onPropertyChangeCount, 1);
-    QCOMPARE(m_onChildPropertyChangeCount, 0);
-    QCOMPARE(m_onParentChangeCount, 0);
-    QCOMPARE(m_onChildrenChangeCount, 0);
-    QCOMPARE(m_onSiblingsChangeCount, 0);
+    setItem(layer, &w, true);
     QVERIFY(m_mapped_item == layer);
-    QVERIFY(m_reported_items.isEmpty());
-    QVERIFY((m_reported_names.size() == 1) && (m_reported_names[0] == LayerItem::P_THICKNESS));
+    layer->setItemValue(LayerItem::P_THICKNESS, 1.0);
+    QCOMPARE(w.m_onPropertyChangeCount, 1);
+    QCOMPARE(w.m_onChildPropertyChangeCount, 0);
+    QCOMPARE(w.m_onParentChangeCount, 0);
+    QCOMPARE(w.m_onChildrenChangeCount, 0);
+    QCOMPARE(w.m_onSiblingsChangeCount, 0);
+    QVERIFY(w.m_reported_items.isEmpty());
+    QVERIFY((w.m_reported_names.size() == 1) && (w.m_reported_names[0] == LayerItem::P_THICKNESS));
 
     layer->setItemValue(LayerItem::P_THICKNESS, 2.0);
-    QCOMPARE(m_onPropertyChangeCount, 2);
+    QCOMPARE(w.m_onPropertyChangeCount, 2);
 
-    m_mapper->unsubscribe(this);
+    w.unsubscribe(m_mapper.get());
     layer->setItemValue(LayerItem::P_THICKNESS, 3.0);
-    QCOMPARE(m_onPropertyChangeCount, 2);
+    QCOMPARE(w.m_onPropertyChangeCount, 2);
 }
 
 
-- 
GitLab