BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
jsonmodelconverter.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/jsonmodelconverter.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 "folderbasedtest.h"
16 #include "google_test.h"
17 #include "mvvm/model/itempool.h"
19 #include "mvvm/model/sessionitem.h"
22 #include "mvvm/model/taginfo.h"
26 #include "test_utils.h"
27 #include <QJsonArray>
28 #include <QJsonDocument>
29 #include <QJsonObject>
30 #include <stdexcept>
31 
32 using namespace ModelView;
33 
34 //! Checks JsonModel class and its ability to convert SessionModel to json and back.
35 
37 public:
38  JsonModelConverterTest() : FolderBasedTest("test_JsonModelConverter") {}
40 };
41 
43 
44 //! Creation of json object: empty model.
45 
47 {
49  SessionModel model("TestModel");
50 
51  QJsonObject object = converter.to_json(model);
52 
53  EXPECT_EQ(object[JsonItemFormatAssistant::sessionModelKey], "TestModel");
54  EXPECT_EQ(object[JsonItemFormatAssistant::itemsKey].toArray().size(), 0);
55 
56  JsonItemFormatAssistant assistant;
57  EXPECT_TRUE(assistant.isSessionModel(object));
58 }
59 
60 //! Empty model to json and back.
61 
62 TEST_F(JsonModelConverterTest, emptyModelToJsonAndBack)
63 {
65  SessionModel model("TestModel");
66 
67  QJsonObject object = converter.to_json(model);
68 
69  // attempt to reconstruct model of different type.
70  SessionModel target1("NewModel");
71  EXPECT_THROW(converter.from_json(object, target1), std::runtime_error);
72 
73  // attempt to reconstruct non-empty model
74  SessionModel target2("TestModel");
75  target2.insertItem<SessionItem>();
76  EXPECT_NO_THROW(converter.from_json(object, target2));
77 
78  // succesfull reconstruction
79  SessionModel target3("TestModel");
80  EXPECT_NO_THROW(converter.from_json(object, target3));
81  EXPECT_EQ(target3.rootItem()->childrenCount(), 0u);
82 }
83 
84 //! Creation of json object: single item in a model.
85 
86 TEST_F(JsonModelConverterTest, singleItemToJsonAndBack)
87 {
89  SessionModel model("TestModel");
90 
91  auto item = model.insertItem<SessionItem>();
92 
93  QJsonObject object = converter.to_json(model);
94 
95  // filling new model
96  SessionModel target("TestModel");
97  converter.from_json(object, target);
98  EXPECT_EQ(target.rootItem()->childrenCount(), 1u);
99  auto reco_item = target.rootItem()->getItem("", 0);
100  EXPECT_EQ(reco_item->parent(), target.rootItem());
101  EXPECT_EQ(reco_item->modelType(), item->modelType());
102 }
103 
104 //! Filling model from json: parent and child in a model to json and back.
105 
106 TEST_F(JsonModelConverterTest, parentAndChildToJsonAndBack)
107 {
109  SessionModel model("TestModel");
110 
111  // filling original model with content
112  auto parent = model.insertItem<SessionItem>();
113  parent->setDisplayName("parent_name");
114  parent->registerTag(TagInfo::universalTag("defaultTag"), /*set_as_default*/ true);
115 
116  parent->setData(QVariant::fromValue(42));
117  auto child = model.insertItem<PropertyItem>(parent);
118  child->setDisplayName("child_name");
119 
120  // writing model to json
121  QJsonObject object = converter.to_json(model);
122 
123  // reading model from json
124  SessionModel target("TestModel");
125  converter.from_json(object, target);
126 
127  // accessing reconstructed parent and child
128  auto reco_parent = target.rootItem()->getItem("", 0);
129  auto reco_child = reco_parent->getItem("", 0);
130 
131  // checking parent reconstruction
132  EXPECT_EQ(reco_parent->model(), &target);
133  EXPECT_EQ(reco_parent->modelType(), Constants::BaseType);
134  EXPECT_EQ(reco_parent->parent(), target.rootItem());
135  EXPECT_EQ(reco_parent->displayName(),
136  "SessionItem"); // Name changed because of ProjectConverter
137  EXPECT_EQ(reco_parent->childrenCount(), 1);
138  EXPECT_EQ(reco_parent->identifier(), parent->identifier());
139  EXPECT_EQ(reco_parent->itemTags()->defaultTag(), "defaultTag");
140  EXPECT_EQ(reco_parent->data<int>(), 42);
141 
142  // checking child reconstruction
143  EXPECT_EQ(reco_child->model(), &target);
144  EXPECT_EQ(reco_child->modelType(), Constants::PropertyType);
145  EXPECT_EQ(reco_child->parent(), reco_parent);
146  EXPECT_EQ(reco_child->displayName(), "Property"); // // Name changed because of ProjectConverter
147  EXPECT_EQ(reco_child->childrenCount(), 0);
148  EXPECT_EQ(reco_child->identifier(), child->identifier());
149  EXPECT_EQ(reco_child->itemTags()->defaultTag(), "");
150 }
151 
152 //! Item in a model to json and back: how persistent are identifiers.
153 
155 {
157  auto pool1 = std::make_shared<ItemPool>();
158 
159  // creating model and converting it to json
160  SessionModel source("SourceModel", pool1);
161  auto parent1 = source.insertItem<SessionItem>();
162  QJsonObject json_source = converter.to_json(source);
163 
164  // creating source and filling it from json
165  auto pool2 = std::make_shared<ItemPool>();
166  SessionModel target("SourceModel", pool2);
167  converter.from_json(json_source, target);
168  auto reco_parent = target.rootItem()->getItem("", 0);
169 
170  // comparing identifiers of two items from different models
171  auto id1 = parent1->identifier();
172  auto id2 = reco_parent->identifier();
173  EXPECT_EQ(id1, id2);
174 
175  // saving target in its own json
176  QJsonObject json_target = converter.to_json(target);
177 
178  // comparing text representations of two json
179  EXPECT_EQ(TestUtils::JsonToString(json_source), TestUtils::JsonToString(json_target));
180 
181  // checking item registrations
182  EXPECT_EQ(pool1->item_for_key(id1), parent1);
183  EXPECT_EQ(pool2->item_for_key(id2), reco_parent);
184 }
185 
186 //! Filling model from json: parent and child in a model to json and back.
187 
188 TEST_F(JsonModelConverterTest, parentAndChildToFileAndBack)
189 {
191  SessionModel model("TestModel");
192 
193  // filling original model with content
194  auto parent = model.insertItem<SessionItem>();
195  parent->setDisplayName("parent_name");
196  parent->registerTag(TagInfo::universalTag("defaultTag"), /*set_as_default*/ true);
197 
198  parent->setData(QVariant::fromValue(42));
199  auto child = model.insertItem<PropertyItem>(parent);
200  child->setDisplayName("child_name");
201 
202  // writing model to json
203  auto object = converter.to_json(model);
204 
205  // saving object to file
206  auto fileName = TestUtils::TestFileName(testDir(), "model.json");
207  TestUtils::SaveJson(object, fileName);
208 
209  // converting document back to item
210  auto document = TestUtils::LoadJson(fileName);
211  SessionModel target("TestModel");
212  converter.from_json(document.object(), target);
213 
214  // accessing reconstructed parent and child
215  auto reco_parent = target.rootItem()->getItem("", 0);
216  auto reco_child = reco_parent->getItem("", 0);
217 
218  // checking parent reconstruction
219  EXPECT_EQ(reco_parent->model(), &target);
220  EXPECT_EQ(reco_parent->modelType(), Constants::BaseType);
221  EXPECT_EQ(reco_parent->parent(), target.rootItem());
222  EXPECT_EQ(reco_parent->displayName(), "SessionItem");
223  EXPECT_EQ(reco_parent->childrenCount(), 1);
224  EXPECT_EQ(reco_parent->identifier(), parent->identifier());
225  EXPECT_EQ(reco_parent->itemTags()->defaultTag(), "defaultTag");
226  EXPECT_EQ(reco_parent->data<int>(), 42);
227 
228  // checking child reconstruction
229  EXPECT_EQ(reco_child->model(), &target);
230  EXPECT_EQ(reco_child->modelType(), Constants::PropertyType);
231  EXPECT_EQ(reco_child->parent(), reco_parent);
232  EXPECT_EQ(reco_child->displayName(), "Property");
233  EXPECT_EQ(reco_child->childrenCount(), 0);
234  EXPECT_EQ(reco_child->identifier(), child->identifier());
235  EXPECT_EQ(reco_child->itemTags()->defaultTag(), "");
236 }
237 
238 //! Creation of json object (single item in a model), then writing same json object back
239 //! to model without emptying it. Real bug case: check if unsubscribtion mechanism works.
240 
241 TEST_F(JsonModelConverterTest, singleItemToJsonAndBackToSameModel)
242 {
243  auto pool = std::make_shared<ItemPool>();
244 
246  SessionModel model("TestModel", pool);
247  auto item = model.insertItem<SessionItem>();
248 
249  auto root_item = model.rootItem();
250  auto root_id = root_item->identifier();
251  auto item_id = item->identifier();
252 
253  QJsonObject object = converter.to_json(model);
254 
255  // filling new model
256  converter.from_json(object, model);
257 
258  EXPECT_EQ(pool->size(), 2);
259  EXPECT_FALSE(pool->item_for_key(root_id) == model.rootItem()); // old root identifier has gone
260  EXPECT_TRUE(model.rootItem() != root_item); // old root item gone
261 
262  auto new_item = model.rootItem()->children().at(0);
263  EXPECT_EQ(pool->item_for_key(item_id), new_item);
264 }
Convenience class which creates a directory on disk for test content.
Checks JsonModel class and its ability to convert SessionModel to json and back.
Utility class to determine, whether given JSON object can represent various parts of SessionModel.
bool isSessionModel(const QJsonObject &object) const
Returns true if given json object represents SessionModel.
Converter of SessionModel to/from json object with posibility to select one of convertion modes.
void from_json(const QJsonObject &json, SessionModel &model) const override
Reads json object and build the model.
QJsonObject to_json(const SessionModel &model) const override
Writes content of model into json.
Item to carry concrete editable entity (e.g.
Definition: propertyitem.h:27
PropertyItem * setDisplayName(const std::string &name) override
Sets display name (fluent interface).
The main object representing an editable/displayable/serializable entity.
Definition: sessionitem.h:38
std::string identifier() const
Returns unique identifier.
Definition: sessionitem.cpp:87
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.
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.
virtual SessionItem * setDisplayName(const std::string &name)
Sets display name (fluent interface).
Main class to hold hierarchy of SessionItem objects.
Definition: sessionmodel.h:37
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
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
TEST_F(JsonModelConverterTest, emptyModel)
Creation of json object: empty model.
const model_type PropertyType
Definition: mvvm_types.h:59
const model_type BaseType
Definition: mvvm_types.h:45
materialitems.h Collection of materials to populate MaterialModel.
@ project
selective copying for saving/loading the project (tags and data created by item, updated from JSON)
std::string TestFileName(const std::string &test_sub_dir, const std::string &file_name)
Returns full path to the file in test directory.
Definition: test_utils.cpp:52
void SaveJson(const QJsonObject &object, const std::string &fileName)
Definition: test_utils.cpp:58
QJsonDocument LoadJson(const std::string &fileName)
Definition: test_utils.cpp:81
QString JsonToString(const QJsonObject &object)
Definition: test_utils.cpp:70
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?
Defines class CLASS?