Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
mitkDataStorageTest.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include <algorithm>
18 #include <fstream>
19 
20 #include "mitkColorProperty.h"
21 #include "mitkDataNode.h"
22 #include "mitkGroupTagProperty.h"
23 #include "mitkImage.h"
25 #include "mitkStringProperty.h"
26 #include "mitkSurface.h"
27 
28 #include "mitkDataStorage.h"
29 #include "mitkIOUtil.h"
30 #include "mitkMessage.h"
31 #include "mitkNodePredicateAnd.h"
32 #include "mitkNodePredicateData.h"
35 #include "mitkNodePredicateNot.h"
36 #include "mitkNodePredicateOr.h"
40 //#include "mitkPicFileReader.h"
41 #include "mitkTestingMacros.h"
42 
43 void TestDataStorage(mitk::DataStorage *ds, std::string filename);
44 
45 namespace mitk
46 {
47  class TestStandaloneDataStorage : public StandaloneDataStorage
48  {
49  public:
50  mitkClassMacro(TestStandaloneDataStorage, mitk::DataStorage);
51  itkFactorylessNewMacro(Self)
52  itkCloneMacro(Self) std::map<const mitk::DataNode *, unsigned long> GetModifiedObserverTags() const
53  {
55  }
56  std::map<const mitk::DataNode *, unsigned long> GetDeletedObserverTags() const { return m_NodeDeleteObserverTags; }
57  protected:
58  TestStandaloneDataStorage() {}
59  };
60 }
61 
62 class DSEventReceiver // Helper class for event testing
63 {
64 public:
65  const mitk::DataNode *m_NodeAdded;
66  const mitk::DataNode *m_NodeRemoved;
67 
68  DSEventReceiver() : m_NodeAdded(NULL), m_NodeRemoved(NULL) {}
69  void OnAdd(const mitk::DataNode *node) { m_NodeAdded = node; }
70  void OnRemove(const mitk::DataNode *node) { m_NodeRemoved = node; }
71 };
72 
80 struct ItkDeleteEventListener
81 {
82  ItkDeleteEventListener(mitk::DataStorage *ds) : m_Node(0), m_DataStorage(ds), m_DeleteObserverTag(0) {}
83  void SetNode(mitk::DataNode *_Node)
84  {
85  if (m_Node)
86  return;
87 
88  m_Node = _Node;
91 
92  onObjectDelete->SetCallbackFunction(this, &ItkDeleteEventListener::OnObjectDelete);
93  m_DeleteObserverTag = m_Node->AddObserver(itk::DeleteEvent(), onObjectDelete);
94  }
95 
96  void OnObjectDelete(const itk::Object * /*caller*/, const itk::EventObject &)
97  {
99  m_DataStorage->Add(node); // SHOULD NOT CAUSE A DEADLOCK!
100  m_DataStorage->Remove(node); // tidy up: remove the empty node again
101 
102  m_Node = 0;
103  }
104 
105 protected:
108  unsigned int m_DeleteObserverTag;
109 };
110 
111 //## Documentation
112 //## main testing method
113 //## NOTE: the current Singleton implementation of DataTreeStorage will lead to crashes if a testcase fails
114 //## and therefore mitk::DataStorage::ShutdownSingleton() is not called.
115 int mitkDataStorageTest(int argc, char *argv[])
116 {
117  MITK_TEST_BEGIN("DataStorageTest");
118 
119  // muellerm: test observer tag remove
122  testDS->Add(n1);
123  MITK_TEST_CONDITION_REQUIRED(testDS->GetModifiedObserverTags().size() == 1,
124  "Testing if modified"
125  " observer was added.");
126  MITK_TEST_CONDITION_REQUIRED(testDS->GetDeletedObserverTags().size() == 1,
127  "Testing if delete"
128  " observer was added.");
129  testDS->Remove(n1);
130  MITK_TEST_CONDITION_REQUIRED(testDS->GetModifiedObserverTags().size() == 0,
131  "Testing if modified"
132  " observer was removed.");
133  MITK_TEST_CONDITION_REQUIRED(testDS->GetDeletedObserverTags().size() == 0,
134  "Testing if delete"
135  " observer was removed.");
136 
137  /* Create StandaloneDataStorage */
138  MITK_TEST_OUTPUT(<< "Create StandaloneDataStorage : ");
140  try
141  {
143  MITK_TEST_CONDITION_REQUIRED(sds.IsNotNull(), "Testing Instatiation");
144  }
145  catch (...)
146  {
147  MITK_TEST_FAILED_MSG(<< "Exception during creation of StandaloneDataStorage");
148  }
149 
150  MITK_TEST_OUTPUT(<< "Testing StandaloneDataStorage: ");
151  MITK_TEST_CONDITION_REQUIRED(argc > 1, "Testing correct test invocation");
152  TestDataStorage(sds, argv[1]);
153  // TODO: Add specific StandaloneDataStorage Tests here
154  sds = NULL;
155 
156  MITK_TEST_END();
157 }
158 
159 //##Documentation
160 //## @brief Test for the DataStorage class and its associated classes (e.g. the predicate classes)
161 //## This method will be called once for each subclass of DataStorage
163 {
164  /* DataStorage valid? */
165  MITK_TEST_CONDITION_REQUIRED(ds != NULL, "DataStorage valid?");
166 
167  // Take the ItkImageFile Reader for the .nrrd data format.
168  // (was previously pic which is now deprecated format)
170 
171  // create some DataNodes to fill the ds
172  mitk::DataNode::Pointer n1 = mitk::DataNode::New(); // node with image and name property
173  // mitk::Image::Pointer image = mitk::Image::New();
174  // unsigned int imageDimensions[] = { 10, 10, 10, 10 };
175  // mitk::PixelType pt(typeid(int));
176  // image->Initialize( pt, 4, imageDimensions );
177  n1->SetData(image);
178  n1->SetProperty("name", mitk::StringProperty::New("Node 1 - Image Node"));
180 
181  mitk::DataNode::Pointer n2 = mitk::DataNode::New(); // node with surface and name and color properties
183  n2->SetData(surface);
184  n2->SetProperty("name", mitk::StringProperty::New("Node 2 - Surface Node"));
185  mitk::Color color;
186  color.Set(1.0f, 1.0f, 0.0f);
187  n2->SetColor(color);
188  n2->SetProperty("Resection Proposal 1", mitk::GroupTagProperty::New());
190  parents2->InsertElement(0, n1); // n1 (image node) is source of n2 (surface node)
191 
192  mitk::DataNode::Pointer n3 = mitk::DataNode::New(); // node without data but with name property
193  n3->SetProperty("name", mitk::StringProperty::New("Node 3 - Empty Node"));
194  n3->SetProperty("Resection Proposal 1", mitk::GroupTagProperty::New());
195  n3->SetProperty("Resection Proposal 2", mitk::GroupTagProperty::New());
197  parents3->InsertElement(0, n2); // n2 is source of n3
198 
199  mitk::DataNode::Pointer n4 = mitk::DataNode::New(); // node without data but with color property
200  n4->SetColor(color);
201  n4->SetProperty("Resection Proposal 2", mitk::GroupTagProperty::New());
203  parents4->InsertElement(0, n2);
204  parents4->InsertElement(1, n3); // n2 and n3 are sources of n4
205 
206  mitk::DataNode::Pointer n5 = mitk::DataNode::New(); // extra node
207  n5->SetProperty("name", mitk::StringProperty::New("Node 5"));
208 
209  try /* adding objects */
210  {
211  /* Add an object */
212  ds->Add(n1, parents1);
213  MITK_TEST_CONDITION_REQUIRED((ds->GetAll()->Size() == 1) && (ds->GetAll()->GetElement(0) == n1),
214  "Testing Adding a new object");
215 
216  /* Check exception on adding the same object again */
217  MITK_TEST_OUTPUT(<< "Check exception on adding the same object again: ");
218  MITK_TEST_FOR_EXCEPTION(..., ds->Add(n1, parents1));
219  MITK_TEST_CONDITION(ds->GetAll()->Size() == 1, "Test if object count is correct after exception");
220 
221  /* Add an object that has a source object */
222  ds->Add(n2, parents2);
223  MITK_TEST_CONDITION_REQUIRED(ds->GetAll()->Size() == 2, "Testing Adding an object that has a source object");
224 
225  /* Add some more objects needed for further tests */
226  ds->Add(n3, parents3); // n3 object that has name property and one parent
227  ds->Add(n4, parents4); // n4 object that has color property
228  ds->Add(n5); // n5 has no parents
229  MITK_TEST_CONDITION_REQUIRED(ds->GetAll()->Size() == 5, "Adding some more objects needed for further tests");
230  }
231  catch (...)
232  {
233  MITK_TEST_FAILED_MSG(<< "Exeption during object creation");
234  }
235 
236  try /* object retrieval methods */
237  {
238  /* Requesting all Objects */
239  {
241  std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
242 
243  MITK_TEST_CONDITION((stlAll.size() == 5) // check if all tree nodes are in resultset
244  &&
245  (std::find(stlAll.begin(), stlAll.end(), n1) != stlAll.end()) &&
246  (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()) &&
247  (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end()) &&
248  (std::find(stlAll.begin(), stlAll.end(), n4) != stlAll.end()) &&
249  (std::find(stlAll.begin(), stlAll.end(), n5) != stlAll.end()),
250  "Testing GetAll()");
251  }
252  /* Requesting a named object */
253  {
255  mitk::NodePredicateProperty::New("name", mitk::StringProperty::New("Node 2 - Surface Node")));
257  MITK_TEST_CONDITION((all->Size() == 1) && (all->GetElement(0) == n2), "Requesting a named object");
258  }
259 
260  /* Requesting objects of specific data type */
261  {
264  MITK_TEST_CONDITION((all->Size() == 1) && (all->GetElement(0) == n1), "Requesting objects of specific data type")
265  }
266  /* Requesting objects of specific dimension */
267  {
270  MITK_TEST_CONDITION((all->Size() == 1) && (all->GetElement(0) == n1), "Requesting objects of specific dimension")
271  }
272  /* Requesting objects with specific data object */
273  {
276  MITK_TEST_CONDITION((all->Size() == 1) && (all->GetElement(0) == n1),
277  "Requesting objects with specific data object")
278  }
279  /* Requesting objects with NULL data */
280  {
283  MITK_TEST_CONDITION((all->Size() == 3) && (std::find(all->begin(), all->end(), n3) != all->end()) &&
284  (std::find(all->begin(), all->end(), n4) != all->end()) &&
285  (std::find(all->begin(), all->end(), n5) != all->end()),
286  "Requesting objects with NULL data");
287  }
288  /* Requesting objects that meet a conjunction criteria */
289  {
294  predicate->AddPredicate(p1);
295  predicate->AddPredicate(p2); // objects must be of datatype "Surface" and have red color (= n2)
296  const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(predicate);
297  MITK_TEST_CONDITION((all->Size() == 1) && (all->GetElement(0) == n2),
298  "Requesting objects that meet a conjunction criteria");
299  }
300  /* Requesting objects that meet a disjunction criteria */
301  {
306  predicate->AddPredicate(p1);
307  predicate->AddPredicate(p2); // objects must be of datatype "Surface" or have red color (= n1, n2, n4)
308  const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(predicate);
309  MITK_TEST_CONDITION((all->Size() == 3) && (std::find(all->begin(), all->end(), n1) != all->end()) &&
310  (std::find(all->begin(), all->end(), n2) != all->end()) &&
311  (std::find(all->begin(), all->end(), n4) != all->end()),
312  "Requesting objects that meet a disjunction criteria");
313  }
314  /* Requesting objects that do not meet a criteria */
315  {
319 
320  const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSubset(predicate);
321  std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
322  MITK_TEST_CONDITION((all->Size() == 3) // check if correct objects are in resultset
323  &&
324  (std::find(stlAll.begin(), stlAll.end(), n1) != stlAll.end()) &&
325  (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end()) &&
326  (std::find(stlAll.begin(), stlAll.end(), n5) != stlAll.end()),
327  "Requesting objects that do not meet a criteria");
328  }
329 
330  /* Requesting *direct* source objects */
331  {
333  ds->GetSources(n3, NULL, true); // Get direct parents of n3 (=n2)
334  std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
335  MITK_TEST_CONDITION((all->Size() == 1) && (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()),
336  "Requesting *direct* source objects");
337  }
338 
339  /* Requesting *all* source objects */
340  {
342  ds->GetSources(n3, NULL, false); // Get all parents of n3 (= n1 + n2)
343  std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
344  MITK_TEST_CONDITION((all->Size() == 2) && (std::find(stlAll.begin(), stlAll.end(), n1) != stlAll.end()) &&
345  (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()),
346  "Requesting *all* source objects"); // check if n1 and n2 are the resultset
347  }
348 
349  /* Requesting *all* sources of object with multiple parents */
350  {
352  ds->GetSources(n4, NULL, false); // Get all parents of n4 (= n1 + n2 + n3)
353  std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
355  (all->Size() == 3) && (std::find(stlAll.begin(), stlAll.end(), n1) != stlAll.end()) &&
356  (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()) &&
357  (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end()) // check if n1 and n2 and n3 are the resultset
358  ,
359  "Requesting *all* sources of object with multiple parents");
360  }
361 
362  /* Requesting *direct* derived objects */
363  {
365  ds->GetDerivations(n1, NULL, true); // Get direct childs of n1 (=n2)
366  std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
367  MITK_TEST_CONDITION((all->Size() == 1) && (std::find(stlAll.begin(), stlAll.end(), n2) !=
368  stlAll.end()) // check if n1 is the resultset
369  ,
370  "Requesting *direct* derived objects");
371  }
372 
374 
375  {
377  ds->GetDerivations(n2, NULL, true); // Get direct childs of n2 (=n3 + n4)
378  std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
380  (all->Size() == 2) &&
381  (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end()) // check if n3 is the resultset
382  &&
383  (std::find(stlAll.begin(), stlAll.end(), n4) != stlAll.end()) // check if n4 is the resultset
384  ,
385  "Requesting *direct* derived objects with multiple parents/derivations");
386  }
387 
388  //* Requesting *all* derived objects */
389  {
391  ds->GetDerivations(n1, NULL, false); // Get all childs of n1 (=n2, n3, n4)
392  std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
393  MITK_TEST_CONDITION((all->Size() == 3) && (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()) &&
394  (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end()) &&
395  (std::find(stlAll.begin(), stlAll.end(), n4) != stlAll.end()),
396  "Requesting *all* derived objects");
397  }
398 
399  /* Checking for circular source relationships */
400  {
401  parents1->InsertElement(0, n4); // make n1 derived from n4 (which is derived from n2, which is derived from n1)
403  n4,
404  NULL,
405  false); // Get all parents of n4 (= n1 + n2 + n3, not n4 itself and not multiple versions of the nodes!)
406  std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
408  (all->Size() == 3) && (std::find(stlAll.begin(), stlAll.end(), n1) != stlAll.end()) &&
409  (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()) &&
410  (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end()) // check if n1 and n2 and n3 are the resultset
411  ,
412  "Checking for circular source relationships");
413  }
414 
417  // can not be accessed from the outside. (Therefore it should not be possible to create these circular relations
418  // */
419 
420  //* Checking GroupTagProperty */
421  {
425  std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
426  MITK_TEST_CONDITION((all->Size() == 2) // check if n2 and n3 are in resultset
427  &&
428  (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()) &&
429  (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end()),
430  "Checking GroupTagProperty");
431  }
432 
433  /* Checking GroupTagProperty 2 */
434  {
438  std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
439  MITK_TEST_CONDITION((all->Size() == 2) // check if n3 and n4 are in resultset
440  &&
441  (std::find(stlAll.begin(), stlAll.end(), n3) != stlAll.end()) &&
442  (std::find(stlAll.begin(), stlAll.end(), n4) != stlAll.end()),
443  "Checking GroupTagProperty 2");
444  }
445 
446  /* Checking direct sources with condition */
447  {
449  const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSources(n4, pred, true);
450  std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
451  MITK_TEST_CONDITION((all->Size() == 1) // check if n2 is in resultset
452  &&
453  (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()),
454  "checking direct sources with condition");
455  }
456 
457  /* Checking all sources with condition */
458  {
460  const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSources(n4, pred, false);
461  std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
462  MITK_TEST_CONDITION((all->Size() == 1) // check if n1 is in resultset
463  &&
464  (std::find(stlAll.begin(), stlAll.end(), n1) != stlAll.end()),
465  "Checking all sources with condition");
466  }
467 
468  /* Checking all sources with condition with empty resultset */
469  {
471  const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetSources(n4, pred, false);
472  MITK_TEST_CONDITION(all->Size() == 0,
473  "Checking all sources with condition with empty resultset"); // check if resultset is empty
474  }
475 
476  /* Checking direct derivations with condition */
477  {
479  const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetDerivations(n1, pred, true);
480  std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
481  MITK_TEST_CONDITION((all->Size() == 1) // check if n2 is in resultset
482  &&
483  (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()),
484  "Checking direct derivations with condition");
485  }
486 
487  /* Checking all derivations with condition */
488  {
490 
491  const mitk::DataStorage::SetOfObjects::ConstPointer all = ds->GetDerivations(n1, pred, false);
492  std::vector<mitk::DataNode::Pointer> stlAll = all->CastToSTLConstContainer();
493  MITK_TEST_CONDITION((all->Size() == 2) // check if n2 and n4 are in resultset
494  &&
495  (std::find(stlAll.begin(), stlAll.end(), n2) != stlAll.end()) &&
496  (std::find(stlAll.begin(), stlAll.end(), n4) != stlAll.end()),
497  "Checking direct derivations with condition");
498  }
499 
500  /* Checking named node method */
501  MITK_TEST_CONDITION(ds->GetNamedNode("Node 2 - Surface Node") == n2, "Checking named node method");
502  MITK_TEST_CONDITION(ds->GetNamedNode(std::string("Node 2 - Surface Node")) == n2,
503  "Checking named node(std::string) method");
504 
505  /* Checking named node method with wrong name */
506  MITK_TEST_CONDITION(ds->GetNamedNode("This name does not exist") == NULL,
507  "Checking named node method with wrong name");
508 
509  /* Checking named object method */
510  MITK_TEST_CONDITION(ds->GetNamedObject<mitk::Image>("Node 1 - Image Node") == image,
511  "Checking named object method");
512  MITK_TEST_CONDITION(ds->GetNamedObject<mitk::Image>(std::string("Node 1 - Image Node")) == image,
513  "Checking named object(std::string) method");
514 
515  /* Checking named object method with wrong DataType */
516  MITK_TEST_CONDITION(ds->GetNamedObject<mitk::Surface>("Node 1 - Image Node") == NULL,
517  "Checking named object method with wrong DataType");
518 
519  /* Checking named object method with wrong name */
520  MITK_TEST_CONDITION(ds->GetNamedObject<mitk::Image>("This name does not exist") == NULL,
521  "Checking named object method with wrong name");
522 
523  /* Checking GetNamedDerivedNode with valid name and direct derivation only */
524  MITK_TEST_CONDITION(ds->GetNamedDerivedNode("Node 2 - Surface Node", n1, true) == n2,
525  "Checking GetNamedDerivedNode with valid name & direct derivation only");
526 
527  /* Checking GetNamedDerivedNode with invalid Name and direct derivation only */
528  MITK_TEST_CONDITION(ds->GetNamedDerivedNode("wrong name", n1, true) == NULL,
529  "Checking GetNamedDerivedNode with invalid name & direct derivation only");
530 
531  /* Checking GetNamedDerivedNode with invalid Name and direct derivation only */
532  MITK_TEST_CONDITION(ds->GetNamedDerivedNode("Node 3 - Empty Node", n1, false) == n3,
533  "Checking GetNamedDerivedNode with invalid name & direct derivation only");
534 
535  /* Checking GetNamedDerivedNode with valid Name but direct derivation only */
536  MITK_TEST_CONDITION(ds->GetNamedDerivedNode("Node 3 - Empty Node", n1, true) == NULL,
537  "Checking GetNamedDerivedNode with valid Name but direct derivation only");
538 
539  /* Checking GetNode with valid predicate */
540  {
542  MITK_TEST_CONDITION(ds->GetNode(p) == n1, "Checking GetNode with valid predicate");
543  }
544  /* Checking GetNode with invalid predicate */
545  {
547  MITK_TEST_CONDITION(ds->GetNode(p) == NULL, "Checking GetNode with invalid predicate");
548  }
549  } // object retrieval methods
550  catch (...)
551  {
552  MITK_TEST_FAILED_MSG(<< "Exeption during object retrieval (GetXXX() Methods)");
553  }
554 
555  try /* object removal methods */
556  {
557  /* Checking removal of a node without relations */
558  {
560  extra->SetProperty("name", mitk::StringProperty::New("extra"));
562  int refCountbeforeDS = watcher->GetReferenceCount();
563  ds->Add(extra);
564  MITK_TEST_CONDITION(ds->GetNamedNode("extra") == extra, "Adding extra node");
565  ds->Remove(extra);
566  MITK_TEST_CONDITION((ds->GetNamedNode("extra") == NULL) && (refCountbeforeDS == watcher->GetReferenceCount()),
567  "Checking removal of a node without relations");
568  extra = NULL;
569  }
570 
571  /* Checking removal of a node with a parent */
572  {
574  extra->SetProperty("name", mitk::StringProperty::New("extra"));
575 
577  int refCountbeforeDS = watcher->GetReferenceCount();
578  ds->Add(extra, n1); // n1 is parent of extra
579 
580  MITK_TEST_CONDITION((ds->GetNamedNode("extra") == extra) &&
581  (ds->GetDerivations(n1)->Size() == 2) // n2 and extra should be derived from n1
582  ,
583  "Adding extra node");
584  ds->Remove(extra);
585  MITK_TEST_CONDITION((ds->GetNamedNode("extra") == NULL) && (refCountbeforeDS == watcher->GetReferenceCount()) &&
586  (ds->GetDerivations(n1)->Size() == 1),
587  "Checking removal of a node with a parent");
588  extra = NULL;
589  }
590 
591  /* Checking removal of a node with two parents */
592  {
594  extra->SetProperty("name", mitk::StringProperty::New("extra"));
595 
597  int refCountbeforeDS = watcher->GetReferenceCount();
599  p->push_back(n1);
600  p->push_back(n2);
601  ds->Add(extra, p); // n1 and n2 are parents of extra
602 
603  MITK_TEST_CONDITION((ds->GetNamedNode("extra") == extra) &&
604  (ds->GetDerivations(n1)->Size() == 2) // n2 and extra should be derived from n1
605  &&
606  (ds->GetDerivations(n2)->Size() == 3),
607  "add extra node");
608 
609  ds->Remove(extra);
611  (ds->GetNamedNode("extra") == NULL) && (refCountbeforeDS == watcher->GetReferenceCount()) &&
612  (ds->GetDerivations(n1)->Size() == 1) // after remove, only n2 should be derived from n1
613  &&
614  (ds->GetDerivations(n2)->Size() == 2) // after remove, only n3 and n4 should be derived from n2
615  ,
616  "Checking removal of a node with two parents");
617  extra = NULL;
618  }
619 
620  /* Checking removal of a node with two derived nodes */
621  {
623  extra->SetProperty("name", mitk::StringProperty::New("extra"));
625  int refCountbeforeDS = watcher->GetReferenceCount();
626  ds->Add(extra);
628  d1->SetProperty("name", mitk::StringProperty::New("d1"));
629  ds->Add(d1, extra);
631  d2->SetProperty("name", mitk::StringProperty::New("d2"));
632  ds->Add(d2, extra);
633 
634  MITK_TEST_CONDITION((ds->GetNamedNode("extra") == extra) && (ds->GetNamedNode("d1") == d1) &&
635  (ds->GetNamedNode("d2") == d2) &&
636  (ds->GetSources(d1)->Size() == 1) // extra should be source of d1
637  &&
638  (ds->GetSources(d2)->Size() == 1) // extra should be source of d2
639  &&
640  (ds->GetDerivations(extra)->Size() == 2) // d1 and d2 should be derived from extra
641  ,
642  "add extra node");
643 
644  ds->Remove(extra);
645  MITK_TEST_CONDITION((ds->GetNamedNode("extra") == NULL) && (ds->GetNamedNode("d1") == d1) &&
646  (ds->GetNamedNode("d2") == d2) && (refCountbeforeDS == watcher->GetReferenceCount()) &&
647  (ds->GetSources(d1)->Size() == 0) // after remove, d1 should not have a source anymore
648  &&
649  (ds->GetSources(d2)->Size() == 0) // after remove, d2 should not have a source anymore
650  ,
651  "Checking removal of a node with two derived nodes");
652  extra = NULL;
653  }
654 
655  /* Checking removal of a node with two parents and two derived nodes */
656  {
658  extra->SetProperty("name", mitk::StringProperty::New("extra"));
661  int refCountbeforeDS = watcher->GetReferenceCount();
662 
664  p->push_back(n1);
665  p->push_back(n2);
666  ds->Add(extra, p); // n1 and n2 are parents of extra
667 
669  d1->SetProperty("name", mitk::StringProperty::New("d1x"));
670  ds->Add(d1, extra);
672  d2->SetProperty("name", mitk::StringProperty::New("d2x"));
673  ds->Add(d2, extra);
674 
675  MITK_TEST_CONDITION((ds->GetNamedNode("extra") == extra) && (ds->GetNamedNode("d1x") == d1) &&
676  (ds->GetNamedNode("d2x") == d2) &&
677  (ds->GetSources(d1)->Size() == 1) // extra should be source of d1
678  &&
679  (ds->GetSources(d2)->Size() == 1) // extra should be source of d2
680  &&
681  (ds->GetDerivations(n1)->Size() == 2) // n2 and extra should be derived from n1
682  &&
683  (ds->GetDerivations(n2)->Size() == 3) // n3, n4 and extra should be derived from n2
684  &&
685  (ds->GetDerivations(extra)->Size() == 2) // d1 and d2 should be derived from extra
686  ,
687  "add extra node");
688 
689  ds->Remove(extra);
691  (ds->GetNamedNode("extra") == NULL) && (ds->GetNamedNode("d1x") == d1) && (ds->GetNamedNode("d2x") == d2) &&
692  (refCountbeforeDS == watcher->GetReferenceCount()) &&
693  (ds->GetDerivations(n1)->Size() == 1) // after remove, only n2 should be derived from n1
694  &&
695  (ds->GetDerivations(n2)->Size() == 2) // after remove, only n3 and n4 should be derived from n2
696  &&
697  (ds->GetSources(d1)->Size() == 0) // after remove, d1 should not have a source anymore
698  &&
699  (ds->GetSources(d2)->Size() == 0) // after remove, d2 should not have a source anymore
700  ,
701  "Checking removal of a node with two parents and two derived nodes");
702  extra = NULL;
703  }
704  }
705  catch (...)
706  {
707  MITK_TEST_FAILED_MSG(<< "Exeption during object removal methods");
708  }
709 
710  /* Checking for node is it's own parent exception */
711  {
714  extra->SetProperty("name", mitk::StringProperty::New("extra"));
716  p->push_back(n1);
717  p->push_back(extra); // extra is parent of extra!!!
718  ds->Add(extra, p);
720  }
721 
722  /* Checking reference count of node after add and remove */
723  {
726  extra->SetProperty("name", mitk::StringProperty::New("extra"));
728  p->push_back(n1);
729  p->push_back(n3);
730  ds->Add(extra, p);
731  extra = NULL;
732  ds->Remove(ds->GetNamedNode("extra"));
733  MITK_TEST_CONDITION(watcher->GetReferenceCount() == 0, "Checking reference count of node after add and remove");
734  }
735 
736  /* Checking removal of a node with two derived nodes [ dataStorage->GetDerivations( rootNode )] see bug #3426 */
737  {
739  extra->SetProperty("name", mitk::StringProperty::New("extra"));
740 
741  ds->Add(extra);
743  d1y->SetProperty("name", mitk::StringProperty::New("d1y"));
745  int refCountbeforeDS = watcherD1y->GetReferenceCount();
746  ds->Add(d1y, extra);
748  d2y->SetProperty("name", mitk::StringProperty::New("d2y"));
749  ds->Add(d2y, extra);
750 
751  MITK_TEST_CONDITION((ds->GetNamedNode("extra") == extra) && (ds->GetNamedNode("d1y") == d1y) &&
752  (ds->GetNamedNode("d2y") == d2y) &&
753  (ds->GetSources(d1y)->Size() == 1) // extra should be source of d1y
754  &&
755  (ds->GetSources(d2y)->Size() == 1) // extra should be source of d2y
756  &&
757  (ds->GetDerivations(extra)->Size() == 2) // d1y and d2y should be derived from extra
758  ,
759  "add extra node");
760 
761  ds->Remove(ds->GetDerivations(extra));
762  MITK_TEST_CONDITION((ds->GetNamedNode("extra") == extra) &&
763  (ds->GetNamedNode("d1y") == NULL) // d1y should be NULL now
764  &&
765  (ds->GetNamedNode("d2y") == NULL) // d2y should be NULL now
766  &&
767  (refCountbeforeDS == watcherD1y->GetReferenceCount()),
768  "Checking removal of subset of two derived nodes from one parent node");
769 
770  ds->Remove(extra);
771  MITK_TEST_CONDITION((ds->GetNamedNode("extra") == NULL), "Checking removal of a parent node");
772  extra = NULL;
773  }
774 
775  /* Checking GetGrouptags() */
776  {
777  const std::set<std::string> groupTags = ds->GetGroupTags();
778  MITK_TEST_CONDITION((groupTags.size() == 2) &&
779  (std::find(groupTags.begin(), groupTags.end(), "Resection Proposal 1") != groupTags.end()) &&
780  (std::find(groupTags.begin(), groupTags.end(), "Resection Proposal 2") != groupTags.end()),
781  "Checking GetGrouptags()");
782  }
783 
784  /* Checking Event handling */
785  DSEventReceiver listener;
786  try
787  {
788  ds->AddNodeEvent +=
789  mitk::MessageDelegate1<DSEventReceiver, const mitk::DataNode *>(&listener, &DSEventReceiver::OnAdd);
790  ds->RemoveNodeEvent +=
791  mitk::MessageDelegate1<DSEventReceiver, const mitk::DataNode *>(&listener, &DSEventReceiver::OnRemove);
792 
795  ds->Add(extra);
796 
797  MITK_TEST_CONDITION(listener.m_NodeAdded == extra.GetPointer(), "Checking AddEvent");
798 
799  ds->Remove(extra);
800  MITK_TEST_CONDITION(listener.m_NodeRemoved == extra.GetPointer(), "Checking RemoveEvent");
801 
802  /* RemoveListener */
803  ds->AddNodeEvent -=
804  mitk::MessageDelegate1<DSEventReceiver, const mitk::DataNode *>(&listener, &DSEventReceiver::OnAdd);
805  ds->RemoveNodeEvent -=
806  mitk::MessageDelegate1<DSEventReceiver, const mitk::DataNode *>(&listener, &DSEventReceiver::OnRemove);
807  listener.m_NodeAdded = NULL;
808  listener.m_NodeRemoved = NULL;
809  ds->Add(extra);
810  ds->Remove(extra);
811  MITK_TEST_CONDITION((listener.m_NodeRemoved == NULL) && (listener.m_NodeAdded == NULL), "Checking RemoveListener");
812 
813  std::cout << "Pointer handling after event handling: " << std::flush;
814  extra = NULL; // delete reference to the node. its memory should be freed now
815  MITK_TEST_CONDITION(watcher->GetReferenceCount() == 0, "Pointer handling after event handling");
816  }
817  catch (...)
818  {
819  /* cleanup */
820  ds->AddNodeEvent -=
821  mitk::MessageDelegate1<DSEventReceiver, const mitk::DataNode *>(&listener, &DSEventReceiver::OnAdd);
822  ds->RemoveNodeEvent -=
823  mitk::MessageDelegate1<DSEventReceiver, const mitk::DataNode *>(&listener, &DSEventReceiver::OnRemove);
824  MITK_TEST_FAILED_MSG(<< "Exception during object removal methods");
825  }
826 
827  // Checking ComputeBoundingGeometry3D method*/
830  MITK_TEST_CONDITION(geometry->CountTimeSteps() == 4, "Test for number or time steps with ComputeBoundingGeometry()");
831  mitk::TimeBounds timebounds = geometry->GetTimeBounds();
832  MITK_TEST_CONDITION((timebounds[0] == 0) && (timebounds[1] == 4),
833  "Test for timebounds with ComputeBoundingGeometry()");
834  for (unsigned int i = 0; i < geometry->CountTimeSteps(); i++)
835  {
836  mitk::BaseGeometry::Pointer subGeometry = geometry->GetGeometryForTimeStep(i);
837  mitk::TimeBounds bounds = geometry->GetTimeBounds(i);
838  MITK_TEST_CONDITION((bounds[0] == i) && (bounds[1] == i + 1),
839  "Test for timebounds of geometry at different time steps with ComputeBoundingGeometry()");
840  }
841  geometry = ds->ComputeBoundingGeometry3D(all);
842  MITK_TEST_CONDITION(geometry->CountTimeSteps() == 4,
843  "Test for number or time steps with ComputeBoundingGeometry(allNodes)");
844  timebounds = geometry->GetTimeBounds();
845  MITK_TEST_CONDITION((timebounds[0] == 0) && (timebounds[1] == 4),
846  "Test for timebounds with ComputeBoundingGeometry(allNodes)");
847  for (unsigned int i = 0; i < geometry->CountTimeSteps(); i++)
848  {
849  mitk::BaseGeometry::Pointer subGeometry = geometry->GetGeometryForTimeStep(i);
850  mitk::TimeBounds bounds = geometry->GetTimeBounds(i);
851  MITK_TEST_CONDITION((bounds[0] == i) && (bounds[1] == i + 1),
852  "Test for timebounds of geometry at different time steps with ComputeBoundingGeometry()");
853  }
854 
855  // test for thread safety of DataStorage
856  try
857  {
859  ItkDeleteEventListener listener(standaloneDataStorage);
860  {
862  mitk::DataNode *pEmptyNode = emptyNode;
863  listener.SetNode(emptyNode);
864  standaloneDataStorage->Add(emptyNode);
865  emptyNode = 0; // emptyNode is still alive because standaloneDataStorage
866  // owns it
867  standaloneDataStorage->Remove(pEmptyNode); // this should not freeze the whole thing
868  }
869  }
870  catch (...)
871  {
872  MITK_TEST_FAILED_MSG(<< "Exception during testing DataStorage thread safe");
873  }
874 
875  /* Clear DataStorage */
876  ds->Remove(ds->GetAll());
877  MITK_TEST_CONDITION(ds->GetAll()->Size() == 0, "Checking Clear DataStorage");
878 }
mitk::DataNode * GetNode(const NodePredicateBase *condition=nullptr) const
Convenience method to get the first node that matches the predicate condition.
virtual void Add(mitk::DataNode *node, const mitk::DataStorage::SetOfObjects *parents=nullptr)=0
Adds a DataNode containing a data object to its internal storage.
Class for storing surfaces (vtkPolyData).
Definition: mitkSurface.h:32
Data management class that handles 'was created by' relations.
itk::SmartPointer< Self > Pointer
static Pointer New()
#define MITK_TEST_FOR_EXCEPTION_END(EXCEPTIONCLASS)
int mitkDataStorageTest(int argc, char *argv[])
itk::FixedArray< ScalarType, 2 > TimeBounds
Standard typedef for time-bounds.
std::map< const mitk::DataNode *, unsigned long > m_NodeModifiedObserverTags
Saves Modified-Observer Tags for each node in order to remove the event listeners again...
virtual SetOfObjects::ConstPointer GetDerivations(const mitk::DataNode *node, const NodePredicateBase *condition=nullptr, bool onlyDirectDerivations=true) const =0
returns a set of derived objects for a given node.
static Pointer New()
#define MITK_TEST_CONDITION_REQUIRED(COND, MSG)
static Pointer New()
STL namespace.
DataCollection - Class to facilitate loading/accessing structured data.
section GeneralTestsDeprecatedOldTestingStyle Deprecated macros All tests with MITK_TEST_BEGIN()
static Pointer New(unsigned int _arg)
#define MITK_TEST_FOR_EXCEPTION(EXCEPTIONCLASS, STATEMENT)
Simplified version of MITK_TEST_FOR_EXCEPTION_BEGIN / END for a single statement. ...
itk::SmartPointer< const Self > ConstPointer
virtual SetOfObjects::ConstPointer GetSources(const mitk::DataNode *node, const NodePredicateBase *condition=nullptr, bool onlyDirectSources=true) const =0
returns a set of source objects for a given node that meet the given condition(s).
#define MITK_TEST_OUTPUT(x)
Output some text.
mitk::DataNode::Pointer m_Node
const DataNode::GroupTagList GetGroupTags() const
Returns a list of used grouptags.
static Pointer New()
virtual SetOfObjects::ConstPointer GetAll() const =0
returns a set of all data objects that are stored in the data storage
DataType * GetNamedObject(const char *name) const
Convenience method to get the first data object of a given data type with a given name...
mitk::DataStorage::Pointer m_DataStorage
Keeps track of the reference count of an object even if it is destroyed.
SetOfObjects::ConstPointer GetSubset(const NodePredicateBase *condition) const
returns a set of data objects that meet the given condition(s)
static Pointer New(mitk::BaseData *_arg)
static Pointer New()
#define MITK_TEST_CONDITION(COND, MSG)
static const std::string filename
#define mitkClassMacro(className, SuperClassName)
Definition: mitkCommon.h:44
std::map< const mitk::DataNode *, unsigned long > m_NodeDeleteObserverTags
Saves Delete-Observer Tags for each node in order to remove the event listeners again.
void TestDataStorage(mitk::DataStorage *ds, std::string filename)
Test for the DataStorage class and its associated classes (e.g. the predicate classes) This method wi...
static Pointer New(const mitk::NodePredicateBase *_arg)
#define MITK_TEST_FAILED_MSG(MSG)
Fail and finish test with message MSG.
Image class for storing images.
Definition: mitkImage.h:76
#define MITK_TEST_FOR_EXCEPTION_BEGIN(EXCEPTIONCLASS)
Begin block which should be checked for exceptions.
DataStorageEvent AddNodeEvent
AddEvent is emitted whenever a new node has been added to the DataStorage.
mitk::DataNode * GetNamedDerivedNode(const char *name, const mitk::DataNode *sourceNode, bool onlyDirectDerivations=true) const
Convenience method to get the first node with a given name that is derived from sourceNode.
static Pointer New(const char *_arg)
itk::RGBPixel< float > Color
Color Standard RGB color typedef (float)
mitk::TimeGeometry::Pointer ComputeBoundingGeometry3D(const SetOfObjects *input, const char *boolPropertyKey=nullptr, const mitk::BaseRenderer *renderer=nullptr, const char *boolPropertyKey2=nullptr) const
Compute the axis-parallel bounding geometry of the input objects.
static Pointer New(const char *_arg)
DataStorageEvent RemoveNodeEvent
RemoveEvent is emitted directly before a node is removed from the DataStorage.
and MITK_TEST_END()
virtual void Remove(const mitk::DataNode *node)=0
Removes node from the DataStorage.
mitk::DataNode * GetNamedNode(const char *name) const
Convenience method to get the first node with a given name.
static Pointer New()
static mitk::Image::Pointer LoadImage(const std::string &path)
LoadImage Convenience method to load an arbitrary mitkImage.
Definition: mitkIOUtil.cpp:597
static Pointer New()
Class for nodes of the DataTree.
Definition: mitkDataNode.h:66
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.