BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
insertnewitemcommand.test.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // qt-mvvm: Model-view-view-model framework for large GUI applications
4 //
5 //! @file mvvm/tests/testmodel/insertnewitemcommand.test.cpp
6 //! @brief Implements class CLASS?
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2020
11 //! @authors Gennady Pospelov et al, Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
15 #include "google_test.h"
19 #include "mvvm/model/itempool.h"
20 #include "mvvm/model/itemutils.h"
21 #include "mvvm/model/sessionitem.h"
23 #include "mvvm/model/taginfo.h"
24 #include <stdexcept>
25 
26 using namespace ModelView;
27 
28 class InsertNewItemCommandTest : public ::testing::Test {
29 public:
31  std::unique_ptr<InsertNewItemCommand> create_command(SessionItem* parent, std::string tag,
32  int row)
33  {
34  auto factory_func = [parent]() {
35  return parent->model()->factory()->createItem(Constants::BaseType);
36  };
37  return std::make_unique<InsertNewItemCommand>(factory_func, parent, TagRow{tag, row});
38  }
39 };
40 
42 
43 //! Insert new item through InsertNewItemCommand command.
44 
45 TEST_F(InsertNewItemCommandTest, insertNewItemCommand)
46 {
47  SessionModel model;
48 
49  // command to insert item in a model
50  auto command = create_command(model.rootItem(), "", 0);
51 
52  // executing command
53  command->execute();
54  EXPECT_EQ(model.rootItem()->childrenCount(), 1);
55  EXPECT_EQ(std::get<SessionItem*>(command->result()), model.rootItem()->getItem("", 0));
56  EXPECT_EQ(command->isObsolete(), false);
57 
58  // undoing command
59  command->undo();
60  EXPECT_EQ(model.rootItem()->childrenCount(), 0);
61  EXPECT_EQ(std::get<SessionItem*>(command->result()), nullptr);
62  EXPECT_EQ(command->isObsolete(), false);
63 
64  // executing again
65  command->execute();
66  EXPECT_EQ(model.rootItem()->childrenCount(), 1);
67  EXPECT_EQ(std::get<SessionItem*>(command->result()), model.rootItem()->getItem("", 0));
68  EXPECT_EQ(command->isObsolete(), false);
69 }
70 
71 //! Insert new item through InsertNewItemCommand command.
72 
73 TEST_F(InsertNewItemCommandTest, insertNewItemWithTagCommand)
74 {
75  SessionModel model;
76 
77  // command to insert parent in the model
78  auto command1 = create_command(model.rootItem(), "", 0);
79  command1->execute(); // insertion
80  EXPECT_EQ(command1->isObsolete(), false);
81 
82  auto parent = std::get<SessionItem*>(command1->result());
83  parent->registerTag(TagInfo::universalTag("tag1"), /*set_as_default*/ true);
84  EXPECT_EQ(parent->childrenCount(), 0);
85 
86  // command to insert child
87  auto command2 = create_command(parent, "tag1", 0);
88  command2->execute(); // insertion
89  EXPECT_EQ(command2->isObsolete(), false);
90 
91  EXPECT_EQ(parent->childrenCount(), 1);
92  EXPECT_EQ(Utils::ChildAt(parent, 0), std::get<SessionItem*>(command2->result()));
93 
94  // undoing command
95  command2->undo();
96  EXPECT_EQ(parent->childrenCount(), 0);
97  EXPECT_EQ(nullptr, std::get<SessionItem*>(command2->result()));
98  EXPECT_EQ(command2->isObsolete(), false);
99 }
100 
101 //! Attempt to execute command twice.
102 
103 TEST_F(InsertNewItemCommandTest, attemptToExecuteTwice)
104 {
105  SessionModel model;
106  // command to set same value
107  auto command = create_command(model.rootItem(), "", 0);
108 
109  // executing command
110  command->execute();
111  EXPECT_THROW(command->execute(), std::runtime_error);
112 }
113 
114 //! Attempt to undo command twice.
115 
116 TEST_F(InsertNewItemCommandTest, attemptToUndoTwice)
117 {
118  SessionModel model;
119 
120  // command to set same value
121  auto command = create_command(model.rootItem(), "", 0);
122 
123  // executing command
124  command->execute();
125  command->undo();
126  EXPECT_THROW(command->undo(), std::runtime_error);
127 }
128 
129 //! Attempt to insert second property to the compount item.
130 
131 TEST_F(InsertNewItemCommandTest, attemptInsertSecondProperty)
132 {
133  SessionModel model;
134  auto parent = model.insertItem<CompoundItem>();
136 
137  // command to insert second property
138  auto factory_func = [parent]() {
139  return parent->model()->factory()->createItem(Constants::PropertyType);
140  };
141 
142  // adding property to another tag is valid
143  InsertNewItemCommand command1(factory_func, parent, TagRow{"radius", -1});
144  EXPECT_NO_THROW(command1.execute());
145  EXPECT_FALSE(command1.isObsolete());
146  EXPECT_EQ(std::get<SessionItem*>(command1.result()), parent->getItem("radius"));
147 
148  // adding second property to the same tag is not possible. Command should be in obsolete state
149  InsertNewItemCommand command2(factory_func, parent, TagRow{"radius", -1});
150  EXPECT_NO_THROW(command2.execute());
151  EXPECT_TRUE(command2.isObsolete());
152  EXPECT_EQ(std::get<SessionItem*>(command2.result()), nullptr);
153 
154  // undoing failed command shouldn't be possible
155  EXPECT_THROW(command2.undo(), std::runtime_error);
156 }
157 
158 //! Insert new item through InsertNewItemCommand command.
159 //! We validate that undoing, and then redoing, would restore very first unique identifier.
160 
161 TEST_F(InsertNewItemCommandTest, insertNewPropertyItemPreservedId)
162 {
163  SessionModel model;
164  // command to insert second property
165  auto factory_func = [&model]() { return model.factory()->createItem(Constants::PropertyType); };
166 
167  EXPECT_EQ(model.rootItem()->childrenCount(), 0);
168 
169  InsertNewItemCommand command1(factory_func, model.rootItem(), TagRow{"", 0});
170  command1.execute();
171 
172  EXPECT_EQ(model.rootItem()->childrenCount(), 1);
173  auto orig_identifier = model.rootItem()->children()[0]->identifier();
174 
175  command1.undo();
176  EXPECT_EQ(model.rootItem()->childrenCount(), 0);
177 
178  command1.execute();
179  EXPECT_EQ(model.rootItem()->childrenCount(), 1);
180  EXPECT_EQ(model.rootItem()->children()[0]->identifier(), orig_identifier);
181 }
182 
183 //! Insert new item through InsertNewItemCommand command.
184 //! We validate that undoing, and then redoing, would restore very first unique identifier.
185 //! Same as above, but we additionally controling item pool.
186 
187 TEST_F(InsertNewItemCommandTest, insertNewPropertyItemIdInPool)
188 {
189  auto pool = std::make_shared<ItemPool>();
190  SessionModel model("Model", pool);
191  // command to insert second property
192  auto factory_func = [&model]() { return model.factory()->createItem(Constants::PropertyType); };
193 
194  EXPECT_EQ(model.rootItem()->childrenCount(), 0);
195  EXPECT_EQ(pool->size(), 1); // rootItem
196 
197  InsertNewItemCommand command1(factory_func, model.rootItem(), TagRow{"", 0});
198  command1.execute();
199 
200  EXPECT_EQ(model.rootItem()->childrenCount(), 1);
201  auto orig_identifier = model.rootItem()->children()[0]->identifier();
202  EXPECT_EQ(pool->size(), 2);
203 
204  command1.undo();
205  EXPECT_EQ(model.rootItem()->childrenCount(), 0);
206 
207  command1.execute();
208  EXPECT_EQ(model.rootItem()->childrenCount(), 1);
209  auto restored_item = model.rootItem()->children()[0];
210  EXPECT_EQ(restored_item->identifier(), orig_identifier);
211  EXPECT_EQ(model.findItem(orig_identifier), restored_item);
212  EXPECT_EQ(pool->item_for_key(orig_identifier), restored_item);
213 }
std::unique_ptr< InsertNewItemCommand > create_command(SessionItem *parent, std::string tag, int row)
void undo()
Undo command as it was before execution.
Complex item holding mixed SessionItem types (single properties and other CompountItems).
Definition: compounditem.h:28
Command for unddo/redo to insert new item.
virtual std::unique_ptr< SessionItem > createItem(const model_type &modelType) const =0
The main object representing an editable/displayable/serializable entity.
Definition: sessionitem.h:38
SessionItem * getItem(const std::string &tag, int row=0) const
Returns item at given row of given tag.
void registerTag(const TagInfo &tagInfo, bool set_as_default=false)
Registers tag to hold items under given name.
SessionModel * model() const
Returns the model to which given item belongs to.
int childrenCount() const
Returns total number of children in all tags.
std::vector< SessionItem * > children() const
Returns vector of children formed from all chidlren from all tags.
Main class to hold hierarchy of SessionItem objects.
Definition: sessionmodel.h:37
SessionItem * findItem(const identifier_type &id)
Returns SessionItem for given identifier.
const ItemFactoryInterface * factory() const
Returns item factory which can generate all items supported by this model.
SessionItem * rootItem() const
Returns root item of the model.
T * insertItem(SessionItem *parent=nullptr, const TagRow &tagrow={})
Inserts item into given parent under given tagrow.
Definition: sessionmodel.h:104
static TagInfo universalTag(std::string name, std::vector< std::string > modelTypes={})
Constructs universal tag intended for unlimited amount of various items.
Definition: taginfo.cpp:34
static TagInfo propertyTag(std::string name, std::string model_type)
Constructs tag intended for single property.
Definition: taginfo.cpp:40
Aggregate to hold (tag, row) information for SessionModel.
Definition: tagrow.h:25
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
TEST_F(InsertNewItemCommandTest, insertNewItemCommand)
Insert new item through InsertNewItemCommand command.
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
const model_type PropertyType
Definition: mvvm_types.h:59
const model_type BaseType
Definition: mvvm_types.h:45
MVVM_MODEL_EXPORT SessionItem * ChildAt(const SessionItem *parent, int index)
Returns child at given index of parent.
Definition: itemutils.cpp:70
materialitems.h Collection of materials to populate MaterialModel.
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?