ACF $AcfVersion:0$
CModelBaseTest.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
10#include <imod/CModelBase.h>
12#include <iser/CSerializableBase.h>
13
14
24class CModelBaseTest: public QObject
25{
26 Q_OBJECT
27
28private slots:
29 void initTestCase();
30 void cleanupTestCase();
31
32 // Observer attachment/detachment tests
33 void testAttachObserver();
34 void testDetachObserver();
35 void testDetachAllObservers();
36 void testIsAttached();
37 void testGetObserverCount();
38 void testGetObservers();
39
40 // Notification tests
41 void testNotifyBeforeChange();
42 void testNotifyAfterChange();
43 void testChangeSetAccumulation();
44 void testMultipleObserversNotification();
45
46 // Edge cases
47 void testAttachSameObserverTwice();
48 void testDetachUnattachedObserver();
49 void testNotifyWithNoObservers();
50
51private:
52 // Helper class: Concrete model implementation for testing
53 class TestModel: public imod::CModelBase, public iser::CSerializableBase
54 {
55 public:
56 enum ChangeFlags
57 {
58 CF_VALUE_CHANGED = 0x1,
59 CF_NAME_CHANGED = 0x2,
60 CF_STATUS_CHANGED = 0x4
61 };
62
63 TestModel() : m_value(0) {}
64
65 void SetValue(int value)
66 {
67 if (m_value != value)
68 {
70 changeSet.Set(CF_VALUE_CHANGED);
71 NotifyBeforeChange(changeSet, false);
72 m_value = value;
73 NotifyAfterChange(changeSet);
74 }
75 }
76
77 int GetValue() const { return m_value; }
78
79 void SetName(const QString& name)
80 {
81 if (m_name != name)
82 {
84 changeSet.Set(CF_NAME_CHANGED);
85 NotifyBeforeChange(changeSet, false);
86 m_name = name;
87 NotifyAfterChange(changeSet);
88 }
89 }
90
91 QString GetName() const { return m_name; }
92
93 void BeginGroupChanges()
94 {
96 changeSet.Set(CF_VALUE_CHANGED);
97 changeSet.Set(CF_NAME_CHANGED);
98 NotifyBeforeChange(changeSet, true);
99 }
100
101 void EndGroupChanges()
102 {
104 NotifyAfterChange(changeSet);
105 }
106
107 // Implement required virtual methods
108 virtual void OnBeginGlobalChanges() override {}
109 virtual void OnEndGlobalChanges(const istd::IChangeable::ChangeSet& changeSet) override {}
110
111 // IChangeable interface
112 virtual int GetSupportedOperations() const override
113 {
115 }
116
119 {
120 TestModel* clone = new TestModel();
121 clone->m_value = m_value;
122 clone->m_name = m_name;
124 }
125
126 virtual bool CopyFrom(const istd::IChangeable& object,
128 {
129 const TestModel* other = dynamic_cast<const TestModel*>(&object);
130 if (other)
131 {
132 m_value = other->m_value;
133 m_name = other->m_name;
134 return true;
135 }
136 return false;
137 }
138
140 {
141 m_value = 0;
142 m_name.clear();
143 return true;
144 }
145
146 virtual bool Serialize(iser::IArchive& archive) override
147 {
148 archive.SerializeValue("value", m_value);
149 archive.SerializeValue("name", m_name);
150 return true;
151 }
152
153 private:
154 int m_value;
155 QString m_name;
156 };
157
158 // Helper class: Test observer that records notifications
159 class TestObserver: public imod::CSingleModelObserverBase
160 {
161 public:
162 TestObserver() : m_beforeUpdateCount(0), m_afterUpdateCount(0) {}
163
164 int GetBeforeUpdateCount() const { return m_beforeUpdateCount; }
165 int GetAfterUpdateCount() const { return m_afterUpdateCount; }
166 const istd::IChangeable::ChangeSet& GetLastChangeSet() const { return m_lastChangeSet; }
167
168 void Reset()
169 {
170 m_beforeUpdateCount = 0;
171 m_afterUpdateCount = 0;
172 m_lastChangeSet.Clear();
173 }
174
175 // Reimplemented from IObserver
176 virtual void BeforeUpdate(imod::IModel* modelPtr) override
177 {
178 CSingleModelObserverBase::BeforeUpdate(modelPtr);
179 m_beforeUpdateCount++;
180 }
181
182 virtual void OnUpdate(const istd::IChangeable::ChangeSet& changeSet) override
183 {
184 m_afterUpdateCount++;
185 m_lastChangeSet = changeSet;
186 }
187
188 private:
189 int m_beforeUpdateCount;
190 int m_afterUpdateCount;
191 istd::IChangeable::ChangeSet m_lastChangeSet;
192 };
193
194 TestModel* m_model;
195 TestObserver* m_observer;
196};
Test class for CModelBase functionality.
Basic implementation of a model.
Definition CModelBase.h:25
istd::IChangeable::ChangeSet GetCumulatedChanges() const
Definition CModelBase.h:129
void NotifyBeforeChange(const istd::IChangeable::ChangeSet &changeSet, bool isGroup)
Called before each change.
void NotifyAfterChange(const istd::IChangeable::ChangeSet &changeSet)
Called after each change.
Basic implementation for a single model observer.
Common interface for model objects, that supports Model/Observer design pattern.
Definition IModel.h:25
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.