using namespace std;
#include <cppunit/Test.h>
#include <cppunit/TestCaller.h>
#include <cppunit/TestSuite.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/ui/text/TestRunner.h>
#include <Archivable.h>
#include <Message.h>
#include <MessagePrivate.h>
const char* kSelfField = "cr:self";
const char* kAField = "cr:A";
const char* kACopyField = "cr:Acopy";
const char* kChildField = "cr:child";
const char* kParentField = "cr:parent";
const char* kNullField = "cr:null";
class CrossReferencer: public BArchivable {
public:
CrossReferencer();
CrossReferencer(BMessage* archive);
~CrossReferencer();
void SetAPointer(CrossReferencer* aPointer);
CrossReferencer* APointer();
CrossReferencer* Child();
CrossReferencer* Parent();
void SetChild(CrossReferencer* child);
void Validate();
virtual status_t Archive(BMessage* into, bool deep = true) const;
static BArchivable* Instantiate(BMessage* from);
private:
CrossReferencer* fSelfPointer;
CrossReferencer* fAPointer;
CrossReferencer* fAPointerCopy;
CrossReferencer* fChildPointer;
CrossReferencer* fParentPointer;
CrossReferencer* fNullPointer;
};
CrossReferencer::CrossReferencer()
:
fSelfPointer(this),
fAPointer(NULL),
fAPointerCopy(NULL),
fChildPointer(NULL),
fParentPointer(NULL),
fNullPointer(NULL)
{
}
CrossReferencer::~CrossReferencer()
{
}
status_t
CrossReferencer::Archive(BMessage* into, bool deep) const
{
BArchivable::Archive(BArchiver::PrepareArchive(into));
BArchiver archiver(into);
archiver.AddArchivable(kSelfField, fSelfPointer);
archiver.AddArchivable(kAField, fAPointer);
archiver.AddArchivable(kACopyField, fAPointerCopy);
archiver.AddArchivable(kChildField, fChildPointer);
archiver.AddArchivable(kParentField, fParentPointer);
archiver.AddArchivable(kNullField, fNullPointer);
return B_OK;
}
CrossReferencer::CrossReferencer(BMessage* archive)
:
BArchivable(BUnarchiver::PrepareArchive(archive))
{
BUnarchiver unarchiver(archive);
BArchivable* retriever;
unarchiver.FindArchivable(kSelfField, &retriever);
fSelfPointer = static_cast<CrossReferencer*>(retriever);
unarchiver.FindArchivable(kAField, &retriever);
fAPointer = static_cast<CrossReferencer*>(retriever);
unarchiver.FindArchivable(kACopyField, &retriever);
fAPointerCopy = static_cast<CrossReferencer*>(retriever);
unarchiver.FindArchivable(kChildField, &retriever);
fChildPointer = static_cast<CrossReferencer*>(retriever);
unarchiver.FindArchivable(kParentField, &retriever);
fParentPointer = static_cast<CrossReferencer*>(retriever);
unarchiver.FindArchivable(kNullField, &retriever);
fNullPointer = static_cast<CrossReferencer*>(retriever);
}
BArchivable*
CrossReferencer::Instantiate(BMessage* from)
{
if (validate_instantiation(from, "CrossReferencer"))
return new CrossReferencer(from);
return NULL;
}
void
CrossReferencer::Validate()
{
CPPUNIT_ASSERT(fSelfPointer == this);
CPPUNIT_ASSERT(fAPointer);
CPPUNIT_ASSERT(fAPointer == fAPointerCopy);
CPPUNIT_ASSERT(fChildPointer->fParentPointer == this);
CPPUNIT_ASSERT(fParentPointer->fChildPointer == this);
CPPUNIT_ASSERT(fNullPointer == NULL);
}
void
CrossReferencer::SetAPointer(CrossReferencer* aPointer)
{
fAPointer = aPointer;
fAPointerCopy = fAPointer;
}
CrossReferencer*
CrossReferencer::APointer()
{
return fAPointer;
}
void
CrossReferencer::SetChild(CrossReferencer* child)
{
fChildPointer = child;
if (child)
child->fParentPointer = this;
}
CrossReferencer*
CrossReferencer::Child()
{
return fChildPointer;
}
CrossReferencer*
CrossReferencer::Parent()
{
return fParentPointer;
}
class CrossReferencerTest: public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(CrossReferencerTest);
CPPUNIT_TEST(TestArchiveTopInstantiateTop);
CPPUNIT_TEST(TestArchiveTwoInstantiateChildTwo);
CPPUNIT_TEST(TestArchiveOneInsantiateChildOne);
CPPUNIT_TEST(TestManagerSetsItselfToNULL);
CPPUNIT_TEST(TestArchiveIsManagedMethod);
CPPUNIT_TEST_SUITE_END();
private:
CrossReferencer* top;
CrossReferencer* childOne;
CrossReferencer* childTwo;
CrossReferencer* topCopy;
CrossReferencer* childOneCopy;
CrossReferencer* childTwoCopy;
public:
void
setUp() {
top = new CrossReferencer();
childOne = new CrossReferencer();
childTwo = new CrossReferencer();
top->SetChild(childOne);
top->SetAPointer(childTwo);
childOne->SetChild(childTwo);
childOne->SetAPointer(childOne);
childTwo->SetAPointer(top);
childTwo->SetChild(top);
topCopy = NULL;
childOneCopy = NULL;
childTwoCopy = NULL;
}
void
tearDown() {
delete top;
delete childOne;
delete childTwo;
delete topCopy;
delete childOneCopy;
delete childTwoCopy;
}
void
ValidateCopies() {
topCopy->Validate();
childOneCopy->Validate();
childTwoCopy->Validate();
CPPUNIT_ASSERT(childOneCopy->APointer() == childOneCopy);
CPPUNIT_ASSERT(childTwoCopy->APointer() == topCopy);
CPPUNIT_ASSERT(topCopy->APointer() == childTwoCopy);
}
void
FillCopyFields() {
if (topCopy) {
childOneCopy = topCopy->Child();
childTwoCopy = childOneCopy->Child();
} else if (childOneCopy) {
childTwoCopy = childOneCopy->Child();
topCopy = childTwoCopy->Child();
} else if (childTwoCopy) {
topCopy = childTwoCopy->Child();
childOneCopy = topCopy->Child();
}
}
void
CompleteTest()
{
FillCopyFields();
ValidateCopies();
}
void
ArchiveInstantiateAndTest(CrossReferencer* archiveFrom,
CrossReferencer** instantiateTo) {
BMessage archive;
CPPUNIT_ASSERT(archiveFrom->Archive(&archive) == B_OK);
CPPUNIT_ASSERT(*instantiateTo =
dynamic_cast<CrossReferencer*>(instantiate_object(&archive)));
CompleteTest();
}
void
TestArchiveTopInstantiateTop() {
ArchiveInstantiateAndTest(top, &topCopy);
}
void
TestArchiveTwoInstantiateChildTwo() {
ArchiveInstantiateAndTest(childTwo, &childTwoCopy);
}
void
TestArchiveOneInsantiateChildOne() {
ArchiveInstantiateAndTest(childOne, &childOneCopy);
}
void
TestManagerSetsItselfToNULL() {
BMessage archive;
top->Archive(&archive);
BMessage::Private messagePrivate(archive);
CPPUNIT_ASSERT(!messagePrivate.ArchiveManager());
topCopy = (CrossReferencer*)instantiate_object(&archive);
CPPUNIT_ASSERT(!messagePrivate.UnarchiveManager());
CompleteTest();
}
void
TestArchiveIsManagedMethod() {
BMessage archive;
CPPUNIT_ASSERT(!BUnarchiver::ArchiveIsManaged(&archive));
top->Archive(&archive);
CPPUNIT_ASSERT(BUnarchiver::ArchiveIsManaged(&archive));
}
};
int main() {
CppUnit::TextUi::TestRunner runner;
runner.addTest(CrossReferencerTest::suite());
runner.run();
return 0;
}