Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
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.