void TestFcoSpecUtil()
{
    cDebug d("TestFcoSpecUtil()");

    // first check the equality operator...
    cFCOSpecStopPointSet* pSet1  = new cFCOSpecStopPointSet;
    cFCOSpecStopPointSet* pSet2  = new cFCOSpecStopPointSet;
    cFCOSpecImpl*         pSpec1 = new cFCOSpecImpl(_T("Spec1"), NULL, pSet1);
    cFCOSpecImpl*         pSpec2 = new cFCOSpecImpl(_T("Spec2"), NULL, pSet2);

    pSpec1->SetStartPoint(cFCOName(_T("Dog")));
    pSpec2->SetStartPoint(cFCOName(_T("Dog")));
    pSet1->Add(cFCOName(_T("Dog/Bark")));
    pSet2->Add(cFCOName(_T("Dog/Bark")));
    pSet1->Add(cFCOName(_T("Dog/Pant")));
    pSet2->Add(cFCOName(_T("Dog/Pant")));
    TEST(iFCOSpecUtil::FCOSpecEqual(*pSpec1, *pSpec2));

    // make them a little different...
    cFCOSpecStopPointIter iter(*pSet1);
    iter.SeekBegin();
    cFCOName removedName = iter.StopPoint();
    iter.Remove();
    pSet1->Add(cFCOName(_T("Dog/Scratch")));
    TEST(!iFCOSpecUtil::FCOSpecEqual(*pSpec1, *pSpec2));

    pSet1->Add(removedName);
    TEST(!iFCOSpecUtil::FCOSpecEqual(*pSpec1, *pSpec2));

    pSpec1->SetStartPoint(cFCOName(_T("Dog")));
    pSet2->Add(cFCOName(_T("Dog/Howl")));
    TEST(!iFCOSpecUtil::FCOSpecEqual(*pSpec1, *pSpec2));
    TEST(iFCOSpecUtil::FCOSpecLessThan(*pSpec1, *pSpec2));
    pSet1->Add(cFCOName(_T("Dog/Howm")));
    TEST(iFCOSpecUtil::FCOSpecLessThan(*pSpec2, *pSpec1));

    pSpec1->Release();
    pSpec2->Release();

    d.TraceDebug("Leaving..\n");
}
void TestFSDataSourceIter()
{
    cFSDataSourceIter   iter;
    cDebug              d("TestFSDataSourceIter");
    try
    {
        // go to my temp directory and iterate over everything!
        iter.SeekToFCO( cFCOName(_T("/tmp")) );
        //
        // print out everything below the iterator
        //
        PrintIter( iter, d );
    }
    catch( eError& e )
    {
            d.TraceError( "*** Caught exception %d %s\n", e.GetID(), e.GetMsg().c_str() );
        TEST( false );
    }
}
void TestFSPropCalc()
{
#pragma message( __FILE__ "(1) : TODO - implement this test file")
#if 0
	cDebug d("TestFSPropCalc");
	cFSDataSource ds;

	iFSServices* pFSServices = iFSServices::GetInstance();
	bool bCaseSensitive = pFSServices->IsCaseSensitive();

	// oh boy! I finally get to test property calculation!
	d.TraceDebug("Creating FCO c:\\temp\\foo.bin\n");

	cFileArchive arch;
	int ret;
	ret = arch.OpenReadWrite(TEMP_DIR _T("/foo.bin"), true);
	TEST(ret);
	arch.WriteBlob("\x1\x2\x3\x4\x5\x6\x7\x8\x9\x0", 10);
	arch.Close();
	
	// get the fco but none of its children...
	iFCO* pFCO = ds.CreateFCO(cFCOName(TEMP_DIR _T("/foo.bin")), 0);
	ASSERT(pFCO);

	// create the calculator and set some properties to calculate...
	cFSPropCalc propCalc;
	cFCOPropVector v(pFCO->GetPropSet()->GetValidVector().GetSize());
	v.AddItem(cFSPropSet::PROP_DEV);
	v.AddItem(cFSPropSet::PROP_CTIME);
	v.AddItem(cFSPropSet::PROP_SIZE);
	v.AddItem(cFSPropSet::PROP_BLOCKS);
	v.AddItem(cFSPropSet::PROP_CRC32);
	v.AddItem(cFSPropSet::PROP_MD5);
	propCalc.SetPropVector(v);

	// finally, do the calculation
	pFCO->AcceptVisitor(&propCalc);

	// see what properties were evaluated...
	PrintProps(pFCO);

	d.TraceDebug("CRC32 should be \"2ARm2G\"\n");
	d.TraceDebug("MD5 should be \"1.Oyjj1dbom.DF2KktvtQe\"\n");

	// if we do it with "Leave", then nothing should change...
	d.TraceDebug("Changing collision action to Leave; the following run should _not_ call Stat()\n");
	propCalc.SetCollisionAction(iFCOPropCalc::PROP_LEAVE);
	pFCO->AcceptVisitor(&propCalc);

	
	// test only calculating unevaluated props...
	d.TraceDebug("invalidating PROP_MD5 in fco, and changing the file. \n\tAll should remain the same except md5.\n");
	ret = arch.OpenReadWrite(TEMP_DIR _T("/foo.bin"), true);
	TEST(ret);
	arch.WriteString(_T("Bark Bark Bark\n"));
	arch.Close();

	// do the calculation
	pFCO->GetPropSet()->InvalidateProp(cFSPropSet::PROP_MD5);
	pFCO->AcceptVisitor(&propCalc);
	PrintProps(pFCO);


	// TODO -- is there any way to test the error queue in the prop calc?

	// release the fco
	pFCO->Release();
#endif
	return;
}
Пример #4
0
///////////////////////////////////////////////////////////////////////////////
// TestFCOSetImpl -- FCOSetImpl component test harness
///////////////////////////////////////////////////////////////////////////////
void TestFCOSetImpl()
{
    cDebug d("TestFCOSetImpl()");
    d.TraceDebug("Entering...\n");


    iFCO* pFCO1 = new cFSObject(cFCOName(_T("fco1")));
    iFCO* pFCO2 = new cFSObject(cFCOName(_T("fco2")));
    iFCO* pFCO3 = new cFSObject(cFCOName(_T("fco3")));

    cFCOSetImpl set;
    set.Insert(pFCO1);
    set.Insert(pFCO2);
    set.Insert(pFCO3);

    // the set should have AddRef()ed, so I can release these now.
    pFCO1->Release();
    pFCO2->Release();
    pFCO3->Release();

    // let's iterate over the fcos
    cIterProxy<iFCOIter> pit(set.GetIter());
    pit->SeekBegin();
    PrintIter(pit, d);

    // lookup a specific fco
    cIterProxy<iFCOIter> pit2(set.Lookup(cFCOName(_T("fco2"))));
    if(! (iFCOIter*)pit2)
    {
        d.TraceError("Lookup failed for fco2!\n");
        TEST(false);
    }
    
    d.TraceDebug("Iterating from fco2 to end...\n");
    PrintIter(pit2, d);

    // Insert something
    d.TraceDebug("Inserting dog...\n");
    pFCO1 = new cFSObject(cFCOName(_T("dog")));
    set.Insert(pFCO1);
    pFCO1->Release();
    pit->SeekBegin();
    PrintIter(pit, d);

    // ...and then remove it
    d.TraceDebug("Removing fco3\n");
    cIterProxy<iFCOIter> pit3(set.Lookup(cFCOName(_T("fco3"))));
    if(! (iFCOIter*)pit3)
    {
        d.TraceError("Lookup failed for fco3!\n");
        TEST(false);
    }
    pit3->Remove();
    pit3->SeekBegin();
    PrintIter(pit3, d);

    // test operator=
    cFCOSetImpl set2;
    set2 = set;
    pit = set2.GetIter();
    d.TraceDebug("Made a new set and set it equal to the first with operator=; printing out...\n");
    PrintIter(pit, d);

    // test IsEmpty
    set.Clear();
    TEST(set.IsEmpty());

    // test refrence counting...
    d.TraceDebug("Set 1 was cleared out; printing set 2 to ensure ref counting worked\n");
    pit->SeekBegin();
    PrintIter(pit, d);

    // test serialization
    cFCOSetImpl set3;
    cMemoryArchive a;
    cSerializerImpl writeSer(a, cSerializerImpl::S_WRITE);
    writeSer.Init();
    set2.Write(&writeSer);
    writeSer.Finit();
    a.Seek(0, cBidirArchive::BEGINNING);
    cSerializerImpl readSer(a, cSerializerImpl::S_READ);
    readSer.Init();
    set3.Read(&readSer);
    readSer.Finit();
    d.TraceDebug("Serialized the set out and read it back in; this should be the same as above...\n");
    pit = set3.GetIter();
    PrintIter(pit, d);


    d.TraceDebug("Leaving...\n");
    return;

}
void TestFCOSpecHelper()
{
	cDebug d("TestFCOSpecHelper");
	d.TraceDebug("Entering...\n");

	// test the start and stop point fringe cases...
	d.TraceDebug("Testing start and stop point stuff...\n");
	cFCOSpecStopPointSet* pSet3 = new cFCOSpecStopPointSet;
	pSet3->SetStartPoint(cFCOName(_T("/etc")));		d.TraceDebug("*** Added start point /etc\n");
	pSet3->Add(cFCOName(_T("/etc/dog/bark")));		d.TraceDebug("*** Added stop  point /etc/dog/bark\n");
	pSet3->Add(cFCOName(_T("/etc/dog/pant")));		d.TraceDebug("*** Added stop  point /etc/dog/pant\n\n");
	pSet3->Add(cFCOName(_T("/etc/cat/meow")));		d.TraceDebug("*** Added stop  point /etc/cat/meow\n");
	pSet3->TraceContents();	
	pSet3->Add(cFCOName(_T("/etc/dog")));			d.TraceDebug("*** Added stop  point /etc/dog\n");
	pSet3->Add(cFCOName(_T("/etc/cat/purr")));		d.TraceDebug("*** Added stop  point /etc/cat/purr\n");
	pSet3->Add(cFCOName(_T("/etc/cat/purr/loud")));	d.TraceDebug("*** Added stop  point /etc/cat/purr/loud\n");
	pSet3->TraceContents();	
	pSet3->Add(cFCOName(_T("/etc/dog")));			d.TraceDebug("*** Added stop  point /etc/dog\n");
	try
	{
		pSet3->Add(cFCOName(_T("/var/spool")));		d.TraceDebug("*** Added stop  point /var/spool\n");
	}
	catch(eError& e)
	{
		d.TraceDebug(_T("Caught exception : %s\n"), e.GetMsg().c_str());
	}
	try
	{
		pSet3->SetStartPoint(cFCOName(_T("/var")));	d.TraceDebug("*** Added start point /var\n");
	}
	catch(eError& e)
	{
		d.TraceDebug(_T("Caught exception : %s\n"), e.GetMsg().c_str());
	}
	try
	{
		pSet3->SetStartPoint(cFCOName(_T("/")));				d.TraceDebug("*** Added start point /\n");
	}
	catch(eError& e)
	{
		d.TraceDebug(_T("Caught exception : %s\n"), e.GetMsg().c_str());
	}
	pSet3->TraceContents();	

	// test SpecContainsFCO()
	cFCOSpecStopPointSet* pSet4 = new cFCOSpecStopPointSet;
	pSet4->SetStartPoint(cFCOName(_T("/etc")));
	pSet4->Add(cFCOName(_T("/etc/dog")));
	pSet4->Add(cFCOName(_T("/etc/cat/meow")));
	TEST(  pSet4->ContainsFCO( cFCOName(_T("/etc/frog"))));
	TEST(  pSet4->ContainsFCO( cFCOName(_T("/etc/cat/paw"))));
	TEST(! pSet4->ContainsFCO( cFCOName(_T("/etc/dog"))));
	TEST(! pSet4->ContainsFCO( cFCOName(_T("/var/spool/mail"))));
	TEST(! pSet4->ContainsFCO( cFCOName(_T("/etc/dog/bark"))));

	// test the All Children Stop Points case
	cFCOSpecNoChildren noChildren;
	noChildren.SetStartPoint(cFCOName(_T("/etc")));
	TEST(  noChildren.ContainsFCO( cFCOName(_T("/etc"))));
	TEST(! noChildren.ContainsFCO( cFCOName(_T("/etc/frog"))));

	// TODO -- test Compare()

	// test serialization
		// test serialization
	cMemoryArchive a;
	cSerializerImpl s(a, cSerializerImpl::S_WRITE);
	s.Init();
	s.WriteObjectDynCreate(pSet3);
	s.WriteObjectDynCreate(&noChildren);
	s.Finit();
	a.Seek(0, cBidirArchive::BEGINNING);

	iFCOSpecHelper* pHelp1, *pHelp2;
	cSerializerImpl s2(a, cSerializerImpl::S_READ);
	s2.Init();
	pHelp1 = (iFCOSpecHelper*)s2.ReadObjectDynCreate();
	pHelp2 = (iFCOSpecHelper*)s2.ReadObjectDynCreate();
	s2.Finit();

	TEST(pHelp1->Compare(pSet3)			== iFCOSpecHelper::CMP_EQ);
	TEST(pHelp2->Compare(&noChildren)	== iFCOSpecHelper::CMP_EQ);
	TEST(pHelp1->Compare(&noChildren)	!= iFCOSpecHelper::CMP_EQ);
	TEST(pHelp2->Compare(pSet3)			!= iFCOSpecHelper::CMP_EQ);


	delete pSet3;
	delete pSet4;
	delete pHelp1;
	delete pHelp2;
}
void TestTextReportViewer()
{
    cFCOReport  report;
    cFCOReportGenreIter genreIter(report);
    cFCOReportSpecIter specIter(genreIter);

    cDebug d("TestFCOReport");
    
    cFCOName fcoNameSpec1;
    cFCOName fcoNameSpec2;
    TSTRING  fcoNameTempFile;
    try
    {
        iFSServices* pFSServices = iFSServices::GetInstance();
        ASSERT( pFSServices );

        TSTRING fcoNameTempDir;
        pFSServices->GetTempDirName( fcoNameTempDir );
        
        fcoNameSpec1 = fcoNameTempDir += _T("SPEC1/");
        fcoNameSpec2 = fcoNameTempDir += _T("SPEC2/");
        
        pFSServices->Mkdir( fcoNameTempDir );
        pFSServices->Mkdir( fcoNameSpec1.AsString() );
        pFSServices->Mkdir( fcoNameSpec2.AsString() );
        
        fcoNameTempFile = fcoNameTempDir += _T("twtempXXXXXX");
        pFSServices->MakeTempFilename( fcoNameTempFile );
    }
    catch(eFSServices& /* e */)
    {
        // TODO: properly handle error
        ASSERT( false );
    }

    // need two prop calcs because.....
    // if cFSPropCalc::VisitFSObject succeeds, cFSPropCalc stores the FCO in
    // an internal set (why, I don't know), and the cFCOSet ASSERTs that the same 
    // FCO isn't inserted more than once.  But since we visit changed FCOs twice 
    // in this test routine, we need two calcs.  Make sense?  Oh, well.
    cFSPropCalc* pPropCalc = new cFSPropCalc;
    cFSPropCalc* pPropCalc2 = new cFSPropCalc;
 
    
    cFCOSpecStopPointSet *pStopPts = new cFCOSpecStopPointSet;
    cFCOSpecImpl*    pSpec          = new cFCOSpecImpl( fcoNameSpec1.AsString(), NULL, pStopPts);
    cFCOSpecAttr* pAttr         = new cFCOSpecAttr;
    
    
    cFCOPropVector v;    
    for( int i = 0; i < 32; i++ )
        v.AddItem( i );
    
    pPropCalc->SetPropVector(v);
    pPropCalc2->SetPropVector(v);


    TSTRING fcoNameMakeMe;
    fcoNameMakeMe = fcoNameSpec1.AsString() + _T("/added_fileXXXXXX");
    MakeFile( fcoNameMakeMe );
    cFSObject*  addedFCO        = new cFSObject( cFCOName(fcoNameMakeMe));
    pPropCalc->VisitFSObject( *addedFCO );

    
    // MakeTempFile can't handle strings with escaped quotes, so we'll have to do this ourselves
    fcoNameMakeMe = fcoNameSpec1.AsString() + _T("/\"quoted\\_and_backslashed_file1\"");    
    //TOFSTREAM file1( fcoNameMakeMe.c_str() );
    //ASSERT( file1 );
    //file1.close();

    cFSObject*  addedFCO2       = new cFSObject( cFCOName(fcoNameMakeMe) );
    //pPropCalc->VisitFSObject( *addedFCO2 );
    
    
    // MakeTempFile can't handle strings with escaped quotes, so we'll have to do this ourselves
    fcoNameMakeMe = fcoNameSpec1.AsString() + _T("/quoted_file\"2\"XXXXXX");
    //TOFSTREAM file2( fcoNameMakeMe.c_str() );
    //ASSERT( file2 );
    //file2.close();

    cFSObject*  addedFCO3       = new cFSObject( cFCOName(fcoNameMakeMe) );
    //pPropCalc->VisitFSObject( *addedFCO3 );

    
    fcoNameMakeMe = fcoNameSpec1.AsString() + _T("/removed_fileXXXXXX");
    MakeFile( fcoNameMakeMe );
    cFSObject*  removedFCO      = new cFSObject( cFCOName(fcoNameMakeMe) );
    pPropCalc->VisitFSObject( *removedFCO );

    
    fcoNameMakeMe = fcoNameSpec1.AsString() + _T("/removed_fileXXXXXX");
    MakeFile( fcoNameMakeMe );
    cFSObject*  removedFCO2     = new cFSObject( cFCOName(fcoNameMakeMe) );
    pPropCalc->VisitFSObject( *removedFCO2 );

    pSpec->SetStartPoint( fcoNameSpec1 );
    pAttr->SetName( fcoNameSpec1.AsString() );
    pAttr->SetSeverity(53);
    pStopPts->Add( cFCOName( fcoNameSpec1.AsString() + _T("/End1")) );
    report.AddSpec(0x00020001, pSpec, pAttr, &specIter); // TODO:bam - use cFS::Genre
    pAttr->Release();    

    
    specIter.GetAddedSet()->Insert(addedFCO);
    specIter.GetAddedSet()->Insert(addedFCO2);
    specIter.GetAddedSet()->Insert(addedFCO3);
    specIter.GetRemovedSet()->Insert(removedFCO);
    specIter.GetRemovedSet()->Insert(removedFCO2);

    // make changed FCO1
    cFCOPropVector changedPropVector1;

    
    fcoNameMakeMe = fcoNameSpec1.AsString() + _T("/changed_fileXXXXXX");
    MakeFile( fcoNameMakeMe );
    cFSObject*  oldChangedFCO   = new cFSObject( cFCOName(fcoNameMakeMe) );
    pPropCalc->VisitFSObject( *oldChangedFCO );
    (static_cast<cFSPropSet*> (oldChangedFCO->GetPropSet()))->SetSize(123);
    //(static_cast<cFSPropSet*> (oldChangedFCO->GetPropSet()))->SetUID(_T("old"));

    cFSObject*  newChangedFCO   = new cFSObject( cFCOName(fcoNameMakeMe) );
    pPropCalc2->VisitFSObject( *newChangedFCO );
    (static_cast<cFSPropSet*> (newChangedFCO->GetPropSet()))->SetSize(666);
    //(static_cast<cFSPropSet*> (newChangedFCO->GetPropSet()))->SetUID(_T("new"));

    changedPropVector1.AddItem(cFSPropSet::PROP_SIZE);
    changedPropVector1.AddItem(cFSPropSet::PROP_UID);
    report.AddChangedFCO(specIter, oldChangedFCO, newChangedFCO, changedPropVector1);

    // make changed FCO2
    cFCOPropVector changedPropVector2;

    fcoNameMakeMe = fcoNameSpec1.AsString() + _T("/changed_fileXXXXXX");
    MakeFile( fcoNameMakeMe );
    cFSObject*  oldChangedFCO2  = new cFSObject( cFCOName(fcoNameMakeMe) );
    pPropCalc->VisitFSObject( *oldChangedFCO2 );
    
    //(static_cast<cFSPropSet*> (oldChangedFCO2->GetPropSet()))->SetGSID( _T("S-1-1-0") );

    cFSObject*  newChangedFCO2  = new cFSObject( cFCOName(fcoNameMakeMe) );
    pPropCalc2->VisitFSObject( *newChangedFCO2 );
    //(static_cast<cFSPropSet*> (newChangedFCO2->GetPropSet()))->SetGSID( _T("S-1-1-1") );

    //changedPropVector2.AddItem(cFSPropSet::PROP_GSID);
    report.AddChangedFCO(specIter, oldChangedFCO2, newChangedFCO2, changedPropVector2);

    // add some errors
//    report.GetErrorQueue()->AddError(eError(_T("this is a general error")));
 //   report.GetErrorQueue()->AddError(eError(_T("this too is a general error")));
        

    cFCOSpecStopPointSet *pStopPts2     = new cFCOSpecStopPointSet;
    cFCOSpecImpl*       pSpec2              = new cFCOSpecImpl( fcoNameSpec2.AsString(), NULL, pStopPts2);
    cFCOSpecAttr*   pAttr2              = new cFCOSpecAttr;

    fcoNameMakeMe = fcoNameSpec2.AsString() + _T("/added_fileXXXXXX");
    MakeFile( fcoNameMakeMe );
    cFSObject*  addedFCO5       = new cFSObject( cFCOName(fcoNameMakeMe) );
    pPropCalc->VisitFSObject( *addedFCO5 );
    
    fcoNameMakeMe = fcoNameSpec2.AsString() + _T("/removed_fileXXXXXX");
    MakeFile( fcoNameMakeMe );
    cFSObject*  removedFCO5     = new cFSObject( cFCOName(fcoNameMakeMe) );
    pPropCalc->VisitFSObject( *removedFCO5 );

    pSpec2->SetStartPoint( fcoNameSpec2 );    
    pAttr2->SetName( fcoNameSpec2.AsString() );
    pAttr2->SetSeverity(64);
    pStopPts2->Add( cFCOName( fcoNameSpec2.AsString() + _T("/End2") ) );
    report.AddSpec(0x00020001, pSpec2, pAttr2, &specIter); // TODO:bam -- use cFS::Genre
    pAttr2->Release();
    
    specIter.GetAddedSet()->Insert(addedFCO5);
    specIter.GetRemovedSet()->Insert(removedFCO5);

        

    // make changed FCO3
    cFCOPropVector changedPropVector3;
    
    fcoNameMakeMe = fcoNameSpec2.AsString() + _T("/changed_fileXXXXXX");
    MakeFile( fcoNameMakeMe );
    cFSObject*  oldChangedFCO3  = new cFSObject( cFCOName(fcoNameMakeMe) );
    pPropCalc->VisitFSObject( *oldChangedFCO3 );
    (static_cast<cFSPropSet*> (oldChangedFCO3->GetPropSet()))->SetBlockSize(313222);
    
    cFSObject*  newChangedFCO3  = new cFSObject( cFCOName(fcoNameMakeMe) );
    pPropCalc2->VisitFSObject( *newChangedFCO3 );
    (static_cast<cFSPropSet*> (newChangedFCO3->GetPropSet()))->SetBlockSize(22213145);

    changedPropVector3.AddItem(cFSPropSet::PROP_BLOCK_SIZE);
    report.AddChangedFCO(specIter, oldChangedFCO3, newChangedFCO3, changedPropVector3);

    // make changed FCO4
    cFCOPropVector changedPropVector4;
    
    fcoNameMakeMe = fcoNameSpec2.AsString() + _T("/changed_fileXXXXXX");
    MakeFile( fcoNameMakeMe );
    cFSObject*  oldChangedFCO4  = new cFSObject( cFCOName(fcoNameMakeMe) );
    pPropCalc->VisitFSObject( *oldChangedFCO4 );
    (static_cast<cFSPropSet*> (oldChangedFCO4->GetPropSet()))->SetSize(9104498);
    (static_cast<cFSPropSet*> (oldChangedFCO4->GetPropSet()))->SetMode( S_IREAD | S_IWRITE );    
    
    cFSObject*  newChangedFCO4  = new cFSObject( cFCOName(fcoNameMakeMe) );
    pPropCalc2->VisitFSObject( *newChangedFCO4 );
    (static_cast<cFSPropSet*> (newChangedFCO4->GetPropSet()))->SetSize(66);
    (static_cast<cFSPropSet*> (newChangedFCO4->GetPropSet()))->SetMode( S_IREAD | S_IWRITE | S_IEXEC );

    changedPropVector4.AddItem(cFSPropSet::PROP_SIZE);
    changedPropVector4.AddItem(cFSPropSet::PROP_MODE);
    report.AddChangedFCO(specIter, oldChangedFCO4, newChangedFCO4, changedPropVector4);

    specIter.SeekBegin();
    specIter.Next();
    //specIter.GetErrorQueue()->AddError(2, "this is an \"/etc2\" spec error",NULL);


    d.TraceDebug(_T("\n======================================================\nStart PrintTextReport...\n======================================================\n\n\n"));
        
    TSTRING tstrEmpty( _T("") );
    cFCOReportHeader rhi;
    cFCOReportUtil::FinalizeReport( report );
    cTextReportViewer trv;
    trv.DisplayReportAndHaveUserUpdateIt( rhi, report, _T("") );

            // test writing of USID
            cFileArchive outFile;
            outFile.OpenReadWrite(_T("tmp.twr"));
            cSerializerImpl outSer(outFile, cSerializerImpl::S_WRITE);

            //TraceReport(report, d);
            outSer.Init();
            outSer.WriteObject(&report);
            outSer.Finit();

            outFile.Close();

            cFileArchive inFile;
            inFile.OpenRead(_T("tmp.twr"));
            cSerializerImpl inSer(inFile, cSerializerImpl::S_READ);

            cFCOReport inReport;

            inSer.Init();
            inSer.ReadObject(&inReport);
            inSer.Finit();

            d.TraceDebug("Read in serialized report:\n");
            //TraceReport(inReport, d);
            trv.PrintTextReport( rhi, inReport, TSTRING( TEMP_DIR _T( "/test2.txt" ) ) );    

            //TODO: this does not work any more
            //trv.LaunchEditorOnFile( TSTRING( TEMP_DIR _T("/test2.txt") ), _T("") );


    // look at results
    trv.PrintTextReport( rhi, report, fcoNameTempFile );    
    //TODO: this does not work any more
    //cTextReportViewer::LaunchEditorOnFile( fcoNameTempFile, _T("") );

    
    iFSServices* pFSServices = iFSServices::GetInstance();
    ASSERT( pFSServices );
    pFSServices->FileDelete( addedFCO->GetName().AsString() );
    pFSServices->FileDelete( addedFCO2->GetName().AsString() );
    pFSServices->FileDelete( addedFCO3->GetName().AsString() );
    pFSServices->FileDelete( addedFCO5->GetName().AsString() );
    pFSServices->FileDelete( removedFCO->GetName().AsString() );
    pFSServices->FileDelete( removedFCO2->GetName().AsString() );
    pFSServices->FileDelete( removedFCO5->GetName().AsString() );
    pFSServices->FileDelete( newChangedFCO->GetName().AsString() );
    pFSServices->FileDelete( newChangedFCO2->GetName().AsString() );
    pFSServices->FileDelete( newChangedFCO3->GetName().AsString() );
    pFSServices->FileDelete( newChangedFCO4->GetName().AsString() );
    pFSServices->FileDelete( fcoNameTempFile );

    // don't remove TEMP_DIR since other people may be using it
    pFSServices->Rmdir( fcoNameSpec1.AsString() );
    pFSServices->Rmdir( fcoNameSpec2.AsString() );

    pSpec->Release();
    pSpec2->Release();
    addedFCO->Release();
    addedFCO2->Release();
    addedFCO3->Release();
    addedFCO5->Release();
    removedFCO->Release();
    removedFCO2->Release();
    removedFCO5->Release();
    delete pPropCalc;
    delete pPropCalc2;
    oldChangedFCO->Release();
    newChangedFCO->Release();
    oldChangedFCO2->Release();
    newChangedFCO2->Release();
    oldChangedFCO3->Release();
    newChangedFCO3->Release();
    oldChangedFCO4->Release();
    newChangedFCO4->Release();

    return;
}