#include #include #include #include #include "IDatum.hxx" #include "IData.hxx" #include "IDataVector.hxx" #include "IDataSymLink.hxx" #include "IRealDatum.hxx" namespace tut { /// Test COMET::IDatum and COMET::IDataVector. This tests the object access /// methods of both IDatum and IDataVector (the test is badly named.). struct baseTDatum { // A simple COMET::IDataVector and a standard vector used to cross check. COMET::IDataVector *fVector; std::vector fCheckVector; baseTDatum() { // Run before each test. fVector = new COMET::IDataVector("parent"); for (int i=0; i<5; ++i) { std::ostringstream n1; n1 << "child." << i; COMET::IDataVector *v1 = new COMET::IDataVector(n1.str().c_str()); fVector->push_back(v1); fCheckVector.push_back(v1); for (int j=0; j<5; ++j) { std::ostringstream n2; n2 << "child." << i << "." << j; COMET::IDatum *d1 = new COMET::IDatum(n2.str().c_str()); v1->push_back(d1); } } } ~baseTDatum() { // Run after each test. delete fVector; } }; // Declare the test typedef test_group::object testTDatum; test_group groupTDatum("IDatum"); // Test the basic constructor and destructor. template<> template <> void testTDatum::test<1> () { COMET::IDatum *data = new COMET::IDatum("data"); COMET::IDataVector *vect = new COMET::IDataVector("vect"); COMET::IDataSymLink *link = new COMET::IDataSymLink("lnk"); ensure("IDatum constructor",data); ensure("IDataVector constructor", vect); ensure("IDataSymLink constructor", link); delete data; delete vect; delete link; } namespace { bool VectorsEqual(const std::vector& vect, const COMET::IDataVector& data) { if (vect.size() != data.size()) return false; std::vector::const_iterator v = vect.begin(); COMET::IDataVector::const_iterator d = data.begin(); for (; v != vect.end(); ++v, ++d) { if (*v != *d) return false; } return true; } } // Test the index element access. template <> template <> void testTDatum::test<2> () { ensure_equals("vector length", fCheckVector.size(), fVector->size()); ensure("Order matches insertion order", VectorsEqual(fCheckVector,*fVector)); ensure_equals("IDataVector::At()", fCheckVector.at(2), fVector->At(2)); ensure_equals("IDataVector::operator[]", fCheckVector[2], fVector->operator[](2)); } // Test insertion template <> template <> void testTDatum::test<3> () { std::vector::iterator v = ++fCheckVector.begin(); COMET::IDataVector::iterator d = ++fVector->begin(); // Check insertion. COMET::IDataVector *newObject = new COMET::IDataVector("newObject.1"); fCheckVector.insert(v,newObject); // The new object is now owned by fVector. fVector->insert(d,newObject); ensure("Insertion into vector", VectorsEqual(fCheckVector,*fVector)); v = ++fCheckVector.begin(); d = ++fVector->begin(); ensure_equals("Inserted correctly into std::vector", newObject, *v); ensure_equals("Inserted correctly into IDataVector", newObject, *d); } // Test erasure. template <> template <> void testTDatum::test<4> () { std::vector::iterator v = ++fCheckVector.begin(); COMET::IDatum *erasure = *v; // Check erasure. fCheckVector.erase(v); fVector->erase(erasure); ensure("Erase from vector", VectorsEqual(fCheckVector,*fVector)); } // Class to test that COMET::IDataVector deletes children as well as parent. class testIDatumDelete: public COMET::IDatum { public: static int count; testIDatumDelete() {++count;} testIDatumDelete(const char* name, const char* title = "testDelete") : COMET::IDatum(name,title) {++count;} virtual ~testIDatumDelete() {--count;} }; int testIDatumDelete::count = 0; // Test that COMET::IDataVector children are deleted when parent // COMET::IDataVector is deleted. template <> template <> void testTDatum::test<5> () { int count = 0; COMET::IDataVector *vect = new COMET::IDataVector("parent"); for (int i=0; i<4; ++i) { std::ostringstream name; name << "child." << i; COMET::IDatum *c1 = new testIDatumDelete(name.str().c_str()); ++count; vect->push_back(c1); } ensure("Some COMET::IDataVector children created", (0 template <> void testTDatum::test<6> () { COMET::IHandle d1 = fVector->Get("child.2"); ensure("Name found", d1); ensure_equals("Name matchs", d1->GetName(), std::string("child.2")); } // Test the Get member template with a recursive search template <> template <> void testTDatum::test<7> () { COMET::IHandle d1 = fVector->Get("child.2/child.2.3"); ensure("Name found", d1); ensure_equals("Name matchs", d1->GetName(), std::string("child.2.3")); } // Test the Get member template rooted in the named parent. template <> template <> void testTDatum::test<8> () { COMET::IHandle d1 = fVector->Get("child.2/child.2.3"); COMET::IHandle d2 = d1->Get("//parent/child.3/child.3.2"); ensure("Name found", d2); ensure_equals("Name matchs", d2->GetName(), std::string("child.3.2")); } // Test the Get member template from the top level parent (without name). template <> template <> void testTDatum::test<9> () { COMET::IHandle d1 = fVector->Get("child.2/child.2.3"); COMET::IHandle d2 = d1->Get("~/child.3/child.3.2"); ensure("Name found", d2); ensure_equals("Name matchs", d2->GetName(), std::string("child.3.2")); } // Test the Get member template with a nearest parent. template <> template <> void testTDatum::test<10> () { COMET::IHandle d1 = fVector->Get("child.2/child.2.3"); COMET::IHandle d2 = d1->Get("/child.2/child.2.2"); ensure("Name found", d2); ensure_equals("Name matchs", d2->GetName(), std::string("child.2.2")); } // Test the Get member template with a relative search. template <> template <> void testTDatum::test<11> () { COMET::IHandle d1 = fVector->Get("child.2/child.2.3"); COMET::IHandle d2 = d1->Get("../child.2.2"); ensure("Name found", d2); ensure_equals("Name matchs", d2->GetName(), std::string("child.2.2")); } // Test getting the root parent. template <> template <> void testTDatum::test<12> () { COMET::IHandle d1 = fVector->Get("child.2/child.2.3"); COMET::IHandle d2 = d1->Get("~/"); ensure("Name found", d2); ensure_equals("Name matchs", d2->GetName(), std::string("parent")); } // Test getting the root parent. template <> template <> void testTDatum::test<13> () { COMET::IHandle d1 = fVector->Get("child.2/child.2.3"); COMET::IHandle d2 = d1->Get("//"); ensure("Name found", d2); ensure_equals("Name matchs", d2->GetName(), std::string("parent")); } // Test converting to an incorrect class. template <> template <> void testTDatum::test<14> () { try { COMET::IHandle d1 = fVector->Get("child.2/child.2.3"); fail("Bad data conversion should fail"); } catch (COMET::EBadConversion) {} } /// Test the Has member template. template <> template <> void testTDatum::test<15> () { ensure("Has finds an contained element", fVector->Has("child.2")); ensure("Has reports a missing element", !fVector->Has("notThere")); } /// Test the Use member template. template <> template <> void testTDatum::test<16> () { COMET::IDataVector& child = fVector->Use("child.2"); ensure_equals("The child.2 element was found", child.GetName(), std::string("child.2")); try { fVector->Use("notThere").GetName(); fail("Non-existent element should cause exception"); } catch (COMET::ENoSuchElement) {} try { fVector->Use("child.2").GetName(); fail("Wrong class element should cause exception"); } catch (COMET::EBadConversion) {} } // Test indexed access to the wrong data type. template <> template <> void testTDatum::test<17> () { COMET::IDataVector* d1 = fVector->At(2); ensure("Indexed IDataVector was found", d1); try { COMET::IDataVector* d2 = d1->At(0); if (d2 != NULL) fail("Bad data conversion did not fail"); fail("Bad data conversion did not throw exception"); } catch (COMET::EBadConversion) {} } // Test indexed access past end of vector. template <> template <> void testTDatum::test<18> () { try { COMET::IDatum* d1 = fVector->At(fVector->size()); if (d1 != NULL) fail("Access past end of vector did not fail."); fail("Access past end of vector did not throw exception."); } catch (COMET::ENoSuchElement) {} } // Test that temporary objects can be added to the IDataVector. template <> template <> void testTDatum::test<19> () { COMET::IDataVector *newObject = new COMET::IDataVector("newObject.1"); fVector->AddTemporary(newObject); ensure("Object was added to IDataVector.", fVector->end() != std::find(fVector->begin(), fVector->end(), newObject)); ensure("Object is saved as non persistent", fVector->IsTemporary(newObject)); } // Test that temporary objects found in the IDataVector. template <> template <> void testTDatum::test<20> () { COMET::IDataVector *newObject = new COMET::IDataVector("newObject.1"); fVector->AddTemporary(newObject); COMET::IHandle obj = fVector->Get("newObject.1"); ensure("Temporary object was found in IDataVector.",obj); } // Test that temporary objects mask persistent objects in the IDataVector. template <> template <> void testTDatum::test<21> () { COMET::IHandle persist = fVector->Get("child.1"); ensure("Object was found in IDataVector.",persist); ensure("Object is persistent",!fVector->IsTemporary(persist)); COMET::IDataVector *newObject = new COMET::IDataVector("child.1"); fVector->AddTemporary(newObject); COMET::IHandle temp = fVector->Get("child.1"); ensure("Temporary masks persistent object.", fVector->IsTemporary(temp)); ensure("Temporary and persistent objects are different", !(persist == temp)); // Erase the non-persistent object from the vector and make sure that // the persistent one is visible. fVector->erase(temp); COMET::IHandle exposed = fVector->Get("child.1"); ensure("See original object after masking temporary is removed", exposed == persist); } // Test that size works with temporary objects template <> template <> void testTDatum::test<22> () { COMET::IHandle vector(new COMET::IDataVector); // Insert stuff into the data vector vector->AddDatum(new COMET::IDatum("A")); vector->AddDatum(new COMET::IDatum("B")); vector->AddDatum(new COMET::IDatum("C")); ensure_equals("Vector size matches number of inserts", vector->size(),(unsigned) 3); vector->AddTemporary(new COMET::IDatum("D")); vector->AddTemporary(new COMET::IDatum("E")); vector->AddTemporary(new COMET::IDatum("F")); ensure_equals("Vector size with temporaries matches number of inserts", vector->size(),(unsigned)6); } // Test that iterator works template <> template <> void testTDatum::test<23> () { COMET::IHandle vector(new COMET::IDataVector); // Insert stuff into the data vector vector->AddDatum(new COMET::IDatum("A")); vector->AddDatum(new COMET::IDatum("B")); vector->AddDatum(new COMET::IDatum("C")); int count = 0; for (COMET::IDataVector::iterator v = vector->begin(); v != vector->end(); ++v) { ++count; } ensure_equals("Forward iterator went through all elements",count,3); COMET::IDataVector::iterator v = vector->begin(); ensure_equals("Element is A", std::string((*v)->GetName()),std::string("A")); ++v; ensure_equals("Element is B", std::string((*v)->GetName()),std::string("B")); ++v; ensure_equals("Element is C", std::string((*v)->GetName()),std::string("C")); ++v; ensure("Element is end",v == vector->end()); } // Test that reverse_iterator works template <> template <> void testTDatum::test<24> () { COMET::IHandle vector(new COMET::IDataVector); // Insert stuff into the data vector vector->AddDatum(new COMET::IDatum("A")); vector->AddDatum(new COMET::IDatum("B")); vector->AddDatum(new COMET::IDatum("C")); int count = 0; for (COMET::IDataVector::reverse_iterator v = vector->rbegin(); v != vector->rend(); ++v) { ++count; } ensure_equals("Reverse iterator went through all elements",count,3); COMET::IDataVector::reverse_iterator v = vector->rbegin(); ensure_equals("Element is C", std::string((*v)->GetName()),std::string("C")); ++v; ensure_equals("Element is B", std::string((*v)->GetName()),std::string("B")); ++v; ensure_equals("Element is A", std::string((*v)->GetName()),std::string("A")); ++v; ensure("Element is end", v==vector->rend()); } // Test that iterator works with temporary objects template <> template <> void testTDatum::test<25> () { COMET::IHandle vector(new COMET::IDataVector); // Insert stuff into the data vector vector->AddDatum(new COMET::IDatum("A")); vector->AddDatum(new COMET::IDatum("B")); vector->AddDatum(new COMET::IDatum("C")); vector->AddTemporary(new COMET::IDatum("D")); vector->AddTemporary(new COMET::IDatum("E")); vector->AddTemporary(new COMET::IDatum("F")); int count = 0; for (COMET::IDataVector::iterator v = vector->begin(); v != vector->end(); ++v) { ++count; } ensure_equals("Forward iterator went through all elements",count,6); COMET::IDataVector::iterator v = vector->begin(); ensure_equals("Element is A", std::string((*v)->GetName()),std::string("A")); ++v; ensure_equals("Element is B", std::string((*v)->GetName()),std::string("B")); ++v; ensure_equals("Element is C", std::string((*v)->GetName()),std::string("C")); ++v; ensure_equals("Element is D", std::string((*v)->GetName()),std::string("D")); ++v; ensure_equals("Element is E", std::string((*v)->GetName()),std::string("E")); ++v; ensure_equals("Element is F", std::string((*v)->GetName()),std::string("F")); ++v; ensure("Element is end",v == vector->end()); } // Test that reverse_iterator works with temporary objects template <> template <> void testTDatum::test<26> () { COMET::IHandle vector(new COMET::IDataVector); // Insert stuff into the data vector vector->AddDatum(new COMET::IDatum("A")); vector->AddDatum(new COMET::IDatum("B")); vector->AddDatum(new COMET::IDatum("C")); vector->AddTemporary(new COMET::IDatum("D")); vector->AddTemporary(new COMET::IDatum("E")); vector->AddTemporary(new COMET::IDatum("F")); int count = 0; for (COMET::IDataVector::reverse_iterator v = vector->rbegin(); v != vector->rend(); ++v) { ++count; } ensure_equals("Reverse iterator went through all elements",count,6); COMET::IDataVector::reverse_iterator v = vector->rbegin(); ensure_equals("Element is F", std::string((*v)->GetName()),std::string("F")); ++v; ensure_equals("Element is E", std::string((*v)->GetName()),std::string("E")); ++v; ensure_equals("Element is D", std::string((*v)->GetName()),std::string("D")); ++v; ensure_equals("Element is C", std::string((*v)->GetName()),std::string("C")); ++v; ensure_equals("Element is B", std::string((*v)->GetName()),std::string("B")); ++v; ensure_equals("Element is A", std::string((*v)->GetName()),std::string("A")); ++v; ensure("Element is end",v == vector->rend()); } };