ACF $AcfVersion:0$
CMultiModelObserverBaseTest.h
Go to the documentation of this file.
1// SPDX-License-Identifier: LGPL-2.1-or-later OR GPL-2.0-or-later OR GPL-3.0-or-later OR LicenseRef-ACF-Commercial
2#pragma once
3
4
5// Qt includes
6#include <QtCore/QObject>
7#include <QtTest/QtTest>
8
9// ACF includes
11#include <imod/TModelWrap.h>
12#include <iser/CSerializableBase.h>
13
14
23class CMultiModelObserverBaseTest: public QObject
24{
25 Q_OBJECT
26
27private slots:
28 void initTestCase();
29 void cleanupTestCase();
30
31 // Basic functionality tests
32 void testAttachMultipleModels();
33 void testDetachModel();
34 void testEnsureModelsDetached();
35 void testGetModelCount();
36 void testGetObservedModel();
37 void testIsModelAttached();
38
39 // Update notification tests
40 void testOnUpdateFromMultipleModels();
41 void testChangeSetFiltering();
42 void testSetObservedIds();
43
44 // Edge cases
45 void testAttachSameModelMultipleTimes();
46 void testDetachNonAttachedModel();
47 void testUpdateAfterPartialDetach();
48
49private:
50 // Helper class: Simple data model for testing
51 class TestDataModel: public iser::CSerializableBase
52 {
53 public:
54 enum ChangeFlags
55 {
56 CF_VALUE_CHANGED = 0x1,
57 CF_STATE_CHANGED = 0x2
58 };
59
60 TestDataModel() : m_value(0), m_state(0) {}
61
62 void SetValue(int value)
63 {
64 if (m_value != value)
65 {
67 changeSet.Set(CF_VALUE_CHANGED);
68 BeginChanges(changeSet);
69 m_value = value;
70 EndChanges(changeSet);
71 }
72 }
73
74 int GetValue() const { return m_value; }
75
76 void SetState(int state)
77 {
78 if (m_state != state)
79 {
81 changeSet.Set(CF_STATE_CHANGED);
82 BeginChanges(changeSet);
83 m_state = state;
84 EndChanges(changeSet);
85 }
86 }
87
88 int GetState() const { return m_state; }
89
90 // IChangeable interface
91 virtual int GetSupportedOperations() const override
92 {
94 }
95
98 {
99 TestDataModel* clone = new TestDataModel();
100 clone->m_value = m_value;
101 clone->m_state = m_state;
103 }
104
105 virtual bool CopyFrom(const istd::IChangeable& object,
107 {
108 const TestDataModel* other = dynamic_cast<const TestDataModel*>(&object);
109 if (other)
110 {
111 m_value = other->m_value;
112 m_state = other->m_state;
113 return true;
114 }
115 return false;
116 }
117
119 {
120 m_value = 0;
121 m_state = 0;
122 return true;
123 }
124
125 virtual bool Serialize(iser::IArchive& archive) override
126 {
127 archive.SerializeValue("value", m_value);
128 archive.SerializeValue("state", m_state);
129 return true;
130 }
131
132 private:
133 int m_value;
134 int m_state;
135 };
136
137 // Helper class: Multi-model observer that tracks updates
138 class TestObserver: public imod::CMultiModelObserverBase
139 {
140 public:
141 TestObserver() : m_updateCount(0) {}
142
143 int GetUpdateCount() const { return m_updateCount; }
144 imod::IModel* GetLastUpdatedModel() const { return m_lastUpdatedModel; }
145 const istd::IChangeable::ChangeSet& GetLastChangeSet() const { return m_lastChangeSet; }
146
147 void Reset()
148 {
149 m_updateCount = 0;
150 m_lastUpdatedModel = nullptr;
151 m_lastChangeSet.Clear();
152 }
153
154 // Track all model updates
160
161 const QVector<UpdateRecord>& GetUpdateHistory() const { return m_updateHistory; }
162
163 void ClearHistory()
164 {
165 m_updateHistory.clear();
166 }
167
168 // Reimplemented from CMultiModelObserverBase
169 virtual void OnUpdate(imod::IModel* modelPtr, const istd::IChangeable::ChangeSet& changeSet) override
170 {
171 m_updateCount++;
172 m_lastUpdatedModel = modelPtr;
173 m_lastChangeSet = changeSet;
174
175 UpdateRecord record;
176 record.model = modelPtr;
177 record.changeSet = changeSet;
178 m_updateHistory.append(record);
179 }
180
181 private:
182 int m_updateCount;
183 imod::IModel* m_lastUpdatedModel;
184 istd::IChangeable::ChangeSet m_lastChangeSet;
185 QVector<UpdateRecord> m_updateHistory;
186 };
187
188 typedef imod::TModelWrap<TestDataModel> TestModel;
189
190 TestModel* m_model1;
191 TestModel* m_model2;
192 TestModel* m_model3;
193 TestObserver* m_observer;
194};
Test class for CMultiModelObserverBase functionality.
Basic implementation of a multiple model observer.
Common interface for model objects, that supports Model/Observer design pattern.
Definition IModel.h:25
This model wrapper provides a simple connection between a concrete istd::IChangeable implementation a...
Definition TModelWrap.h:24
Represents an input/output persistence archive for object serialization.
Definition IArchive.h:164
Set of change flags (its IDs).
Definition IChangeable.h:36
Common interface for data model objects, which can be changed.
Definition IChangeable.h:28
CompatibilityMode
Control how relationship betweeen objects are interpreted.
@ CM_WITHOUT_REFS
External references are simple ignored.
@ SO_COPY
Copying from other object.
@ SO_RESET
Resetting of object state.
@ SO_CLONE
Creating of copy of this object.
Unique ownership smart pointer for interface types.